@@ -325,22 +325,65 @@ func readSubTriesConcurrently(dir string, fileName string, subtrieChecksums []ui
325325 return nodesGroups , nil
326326}
327327
328+ func readCheckpointSubTrie (dir string , fileName string , index int , checksum uint32 , logger * zerolog.Logger ) (
329+ []* node.Node ,
330+ error ,
331+ ) {
332+ var nodes []* node.Node
333+ err := processCheckpointSubTrie (dir , fileName , index , checksum , logger ,
334+ func (reader * Crc32Reader , nodesCount uint64 ) error {
335+ scratch := make ([]byte , 1024 * 4 ) // must not be less than 1024
336+
337+ nodes = make ([]* node.Node , nodesCount + 1 ) //+1 for 0 index meaning nil
338+ logging := logProgress (fmt .Sprintf ("reading %v-th sub trie roots" , index ), int (nodesCount ), logger )
339+ for i := uint64 (1 ); i <= nodesCount ; i ++ {
340+ node , err := flattener .ReadNode (reader , scratch , func (nodeIndex uint64 ) (* node.Node , error ) {
341+ if nodeIndex >= i {
342+ return nil , fmt .Errorf ("sequence of serialized nodes does not satisfy Descendents-First-Relationship" )
343+ }
344+ return nodes [nodeIndex ], nil
345+ })
346+ if err != nil {
347+ return fmt .Errorf ("cannot read node %d: %w" , i , err )
348+ }
349+ nodes [i ] = node
350+ logging (i )
351+ }
352+ return nil
353+ })
354+
355+ if err != nil {
356+ return nil , err
357+ }
358+
359+ // since nodes[0] is always `nil`, returning a slice without nodes[0] could simplify the
360+ // implementation of getNodeByIndex
361+ // return nodes[1:], nil
362+ return nodes [1 :], nil
363+ }
364+
328365// subtrie file contains:
329366// 1. checkpoint version
330367// 2. nodes
331368// 3. node count
332369// 4. checksum
333- func readCheckpointSubTrie (dir string , fileName string , index int , checksum uint32 , logger * zerolog.Logger ) (
334- subtrieRootNodes []* node.Node ,
370+ func processCheckpointSubTrie (
371+ dir string ,
372+ fileName string ,
373+ index int ,
374+ checksum uint32 ,
375+ logger * zerolog.Logger ,
376+ processNode func (* Crc32Reader , uint64 ) error ,
377+ ) (
335378 errToReturn error ,
336379) {
337380 filepath , _ , err := filePathSubTries (dir , fileName , index )
338381 if err != nil {
339- return nil , err
382+ return err
340383 }
341384 f , err := os .Open (filepath )
342385 if err != nil {
343- return nil , fmt .Errorf ("could not open file %v: %w" , filepath , err )
386+ return fmt .Errorf ("could not open file %v: %w" , filepath , err )
344387 }
345388 defer func (file * os.File ) {
346389 evictErr := evictFileFromLinuxPageCache (file , false , logger )
@@ -354,81 +397,68 @@ func readCheckpointSubTrie(dir string, fileName string, index int, checksum uint
354397 // valite the magic bytes and version
355398 err = validateFileHeader (MagicBytesCheckpointSubtrie , VersionV6 , f )
356399 if err != nil {
357- return nil , err
400+ return err
358401 }
359402
360403 nodesCount , expectedSum , err := readSubTriesFooter (f )
361404 if err != nil {
362- return nil , fmt .Errorf ("cannot read sub trie node count: %w" , err )
405+ return fmt .Errorf ("cannot read sub trie node count: %w" , err )
363406 }
364407
365408 if checksum != expectedSum {
366- return nil , fmt .Errorf ("mismatch checksum in subtrie file. checksum from checkpoint header %v does not " +
409+ return fmt .Errorf ("mismatch checksum in subtrie file. checksum from checkpoint header %v does not " +
367410 "match with the checksum in subtrie file %v" , checksum , expectedSum )
368411 }
369412
370- // restart from the beginning of the file, make sure CRC32Reader has seen all the bytes
413+ // restart from the beginning of the file, make sure Crc32Reader has seen all the bytes
371414 // in order to compute the correct checksum
372415 _ , err = f .Seek (0 , io .SeekStart )
373416 if err != nil {
374- return nil , fmt .Errorf ("cannot seek to start of file: %w" , err )
417+ return fmt .Errorf ("cannot seek to start of file: %w" , err )
375418 }
376419
377420 reader := NewCRC32Reader (bufio .NewReaderSize (f , defaultBufioReadSize ))
378421
379422 // read version again for calculating checksum
380423 _ , _ , err = readFileHeader (reader )
381424 if err != nil {
382- return nil , fmt .Errorf ("could not read version again for subtrie: %w" , err )
425+ return fmt .Errorf ("could not read version again for subtrie: %w" , err )
383426 }
384427
385428 // read file part index and verify
386- scratch := make ([]byte , 1024 * 4 ) // must not be less than 1024
387- logging := logProgress (fmt .Sprintf ("reading %v-th sub trie roots" , index ), int (nodesCount ), logger )
388429
389- nodes := make ([]* node.Node , nodesCount + 1 ) //+1 for 0 index meaning nil
390- for i := uint64 (1 ); i <= nodesCount ; i ++ {
391- node , err := flattener .ReadNode (reader , scratch , func (nodeIndex uint64 ) (* node.Node , error ) {
392- if nodeIndex >= i {
393- return nil , fmt .Errorf ("sequence of serialized nodes does not satisfy Descendents-First-Relationship" )
394- }
395- return nodes [nodeIndex ], nil
396- })
397- if err != nil {
398- return nil , fmt .Errorf ("cannot read node %d: %w" , i , err )
399- }
400- nodes [i ] = node
401- logging (i )
430+ err = processNode (reader , nodesCount )
431+ if err != nil {
432+ return err
402433 }
403434
435+ scratch := make ([]byte , 1024 )
404436 // read footer and discard, since we only care about checksum
405437 _ , err = io .ReadFull (reader , scratch [:encNodeCountSize ])
406438 if err != nil {
407- return nil , fmt .Errorf ("cannot read footer: %w" , err )
439+ return fmt .Errorf ("cannot read footer: %w" , err )
408440 }
409441
410442 // calculate the actual checksum
411443 actualSum := reader .Crc32 ()
412444
413445 if actualSum != expectedSum {
414- return nil , fmt .Errorf ("invalid checksum in subtrie checkpoint, expected %v, actual %v" ,
446+ return fmt .Errorf ("invalid checksum in subtrie checkpoint, expected %v, actual %v" ,
415447 expectedSum , actualSum )
416448 }
417449
418450 // read the checksum and discard, since we only care about whether ensureReachedEOF
419451 _ , err = io .ReadFull (reader , scratch [:crc32SumSize ])
420452 if err != nil {
421- return nil , fmt .Errorf ("could not read subtrie file's checksum: %w" , err )
453+ return fmt .Errorf ("could not read subtrie file's checksum: %w" , err )
422454 }
423455
424456 err = ensureReachedEOF (reader )
425457 if err != nil {
426- return nil , fmt .Errorf ("fail to read %v-th sutrie file: %w" , index , err )
458+ return fmt .Errorf ("fail to read %v-th sutrie file: %w" , index , err )
427459 }
428460
429- // since nodes[0] is always `nil`, returning a slice without nodes[0] could simplify the
430- // implementation of getNodeByIndex
431- return nodes [1 :], nil
461+ return nil
432462}
433463
434464func readSubTriesFooter (f * os.File ) (uint64 , uint32 , error ) {
0 commit comments