@@ -13,18 +13,17 @@ import (
1313func (s * Secretary ) NewBTree (
1414 collectionName string ,
1515 order uint8 ,
16- batchNumLevel uint8 ,
16+ numLevel uint8 ,
1717 batchBaseSize uint32 ,
18- batchIncrement uint8 ,
19- batchLength uint8 ,
18+ increment uint8 ,
2019 compactionBatchSize uint32 ,
2120) (* BTree , error ) {
2221 if order < MIN_ORDER || order > MAX_ORDER {
2322 return nil , ErrorInvalidOrder
2423 }
2524
26- if batchIncrement < 110 || batchIncrement > 200 {
27- return nil , ErrorInvalidBatchIncrement
25+ if increment < 110 || increment > 200 {
26+ return nil , ErrorInvalidIncrement
2827 }
2928
3029 nodeSize := uint32 (order )* (KEY_SIZE + KEY_OFFSET_SIZE ) + 3 * POINTER_SIZE + 1
@@ -43,11 +42,10 @@ func (s *Secretary) NewBTree(
4342
4443 root : & Node {},
4544
46- Order : order ,
47- BatchNumLevel : batchNumLevel ,
48- BatchBaseSize : batchBaseSize ,
49- BatchIncrement : batchIncrement ,
50- BatchLength : batchLength ,
45+ Order : order ,
46+ NumLevel : numLevel ,
47+ BatchBaseSize : batchBaseSize ,
48+ Increment : increment ,
5149
5250 nodeSize : uint32 (nodeSize ),
5351
@@ -62,7 +60,7 @@ func (s *Secretary) NewBTree(
6260 }
6361 tree .nodePager = nodePager
6462
65- recordPagers := make ([]* RecordPager , batchNumLevel )
63+ recordPagers := make ([]* RecordPager , numLevel )
6664 for i := range recordPagers {
6765 pager , err := tree .NewRecordPager ("record" , uint8 (i ))
6866 if err != nil {
@@ -99,36 +97,79 @@ func (tree *BTree) SaveHeader() error {
9997 headerBytes = append ([]byte (SECRETARY ), headerBytes ... )
10098
10199 if len (headerBytes ) < SECRETARY_HEADER_LENGTH {
102- // header = append(header, make([]byte, rootHeaderSize-len(header))...)
103100 headerBytes = append (headerBytes , utils .MakeByteArray (SECRETARY_HEADER_LENGTH - len (headerBytes ), '-' )... )
104101 }
105102
106103 return tree .nodePager .WriteAt (headerBytes , 0 )
107104}
108105
109- func (tree * BTree ) readRoot () error {
110- rootBytes , err := tree .nodePager .ReadAt (SECRETARY_HEADER_LENGTH , int32 (tree .nodeSize ))
106+ func (tree * BTree ) ReadNodeAtIndex (index uint64 ) (* Node , error ) {
107+ offset := SECRETARY_HEADER_LENGTH + index * uint64 (tree .nodeSize )
108+
109+ rootBytes , err := tree .nodePager .ReadAt (int64 (offset ), int32 (tree .nodeSize ))
111110 if err != nil {
112- return err
111+ return nil , err
113112 }
114113
115- var root Node
116- err = binstruct .Deserialize (rootBytes , & root )
114+ var node Node
115+ err = binstruct .Deserialize (rootBytes , & node )
116+ if err != nil {
117+ return nil , err
118+ }
119+
120+ return & node , nil
121+ }
122+
123+ func (tree * BTree ) readRoot () error {
124+ node , err := tree .ReadNodeAtIndex (0 )
117125 if err != nil {
118126 return err
119127 }
128+ tree .root = node
129+ return nil
130+ }
120131
121- tree .root = & root
132+ func (tree * BTree ) SaveNode (node * Node ) error {
133+ if node .Index == 0 {
134+ stat , err := tree .nodePager .file .Stat ()
135+ if err != nil {
136+ return err
137+ }
138+ lastFileIndex := uint64 (stat .Size ()) - uint64 (SECRETARY_HEADER_LENGTH )/ uint64 (tree .nodeSize )
139+ if lastFileIndex != tree .NumNodeSeq {
140+ return fmt .Errorf ("NumNodes dont match %d != %d" , lastFileIndex , tree .NumNodeSeq )
141+ }
142+ tree .SaveNodeAtIndex (node , lastFileIndex )
143+ } else {
144+ tree .SaveNodeAtIndex (node , uint64 (node .Index ))
145+ }
122146 return nil
123147}
124148
125- func (tree * BTree ) saveRoot () error {
126- rootHeader , err := binstruct .Serialize (tree .root )
149+ func (tree * BTree ) SaveNodeAtIndex (node * Node , index uint64 ) error {
150+ node .Index = index
151+ if node .parent != nil {
152+ node .ParentIndex = node .parent .Index
153+ }
154+ if node .next != nil {
155+ node .NextIndex = node .next .Index
156+ }
157+ if node .prev != nil {
158+ node .PrevIndex = node .prev .Index
159+ }
160+
161+ rootHeader , err := binstruct .Serialize (node )
127162 if err != nil {
128163 return err
129164 }
130165
131- return tree .nodePager .WriteAt (rootHeader , SECRETARY_HEADER_LENGTH )
166+ offset := SECRETARY_HEADER_LENGTH + index * uint64 (tree .nodeSize )
167+
168+ return tree .nodePager .WriteAt (rootHeader , int64 (offset ))
169+ }
170+
171+ func (tree * BTree ) saveRoot () error {
172+ return tree .SaveNodeAtIndex (tree .root , 0 )
132173}
133174
134175func (s * Secretary ) NewBTreeReadHeader (collectionName string ) (* BTree , error ) {
@@ -138,7 +179,6 @@ func (s *Secretary) NewBTreeReadHeader(collectionName string) (*BTree, error) {
138179 0 ,
139180 125 ,
140181 0 ,
141- 0 ,
142182 )
143183 if err != nil {
144184 return nil , err
@@ -174,6 +214,20 @@ func (tree *BTree) Height() int {
174214 return height
175215}
176216
217+ func (tree * BTree ) Level (node * Node ) int {
218+ if node == nil || tree .root == nil {
219+ return - 1 // Return -1 for invalid nodes
220+ }
221+
222+ level := 0
223+ for node != nil && node != tree .root {
224+ level ++
225+ node = node .parent
226+ }
227+
228+ return level
229+ }
230+
177231func (tree * BTree ) GetFirstNodePerHeight () []* Node {
178232 var firstNodePerHeight []* Node
179233
@@ -188,3 +242,45 @@ func (tree *BTree) GetFirstNodePerHeight() []*Node {
188242
189243 return firstNodePerHeight
190244}
245+
246+ func (tree * BTree ) BFSCompactBatchTraversal () []* Node {
247+ var compactBatch []* Node
248+
249+ firstNodePerHeight := tree .GetFirstNodePerHeight ()
250+
251+ if tree .root == nil {
252+ return compactBatch
253+ }
254+ if tree .nextCompactionNode == nil {
255+ tree .nextCompactionNode = tree .root
256+ }
257+
258+ for i := 0 ; i < int (tree .CompactionBatchSize ); i ++ {
259+
260+ // Ensure nextCompactionNode is not nil
261+ if tree .nextCompactionNode == nil {
262+ // utils.Log("tree.nextCompactionNode == nil")
263+ break
264+ }
265+
266+ compactBatch = append (compactBatch , tree .nextCompactionNode )
267+
268+ if tree .nextCompactionNode .next != nil {
269+ tree .nextCompactionNode = tree .nextCompactionNode .next
270+ } else {
271+ // Ensure nextCompactionNode is not nil before calling Level()
272+ level := tree .Level (tree .nextCompactionNode )
273+
274+ // utils.Log("level", level, "lenfirst", len(firstNodePerHeight), level > 0 && (level+1) < len(firstNodePerHeight))
275+
276+ if level >= 0 && (level + 1 ) < len (firstNodePerHeight ) {
277+ firstNode := firstNodePerHeight [level + 1 ]
278+ tree .nextCompactionNode = firstNode
279+ } else {
280+ break
281+ }
282+ }
283+ }
284+
285+ return compactBatch
286+ }
0 commit comments