github.com/TrueBlocks/trueblocks-core/src/apps/chifra@v0.0.0-20241022031540-b362680128f7/internal/chunks/handle_appearances.go (about) 1 // Copyright 2021 The TrueBlocks Authors. All rights reserved. 2 // Use of this source code is governed by a license that can 3 // be found in the LICENSE file. 4 5 package chunksPkg 6 7 import ( 8 "encoding/binary" 9 "fmt" 10 "io" 11 12 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/base" 13 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/file" 14 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/index" 15 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/output" 16 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/types" 17 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/walk" 18 ) 19 20 func (opts *ChunksOptions) HandleAppearances(rCtx *output.RenderCtx, blockNums []base.Blknum) error { 21 chain := opts.Globals.Chain 22 23 fetchData := func(modelChan chan types.Modeler, errorChan chan error) { 24 showAppearances := func(walker *walk.CacheWalker, path string, first bool) (bool, error) { 25 if path != index.ToBloomPath(path) { 26 return false, fmt.Errorf("should not happen in showAppearances") 27 } 28 29 path = index.ToIndexPath(path) 30 if !file.FileExists(path) { 31 // Bloom files exist, but index files don't. It's okay. 32 return true, nil 33 } 34 35 indexChunk, err := index.OpenIndex(path, true /* check */) 36 if err != nil { 37 return false, err 38 } 39 defer indexChunk.Close() 40 41 _, err = indexChunk.File.Seek(indexChunk.AppTableStart, io.SeekStart) 42 if err != nil { 43 return false, err 44 } 45 46 for i := 0; i < int(indexChunk.Header.AppearanceCount); i++ { 47 if opts.Globals.TestMode && i > walker.MaxTests() { 48 continue 49 } 50 rec := types.AppRecord{} 51 if err := binary.Read(indexChunk.File, binary.LittleEndian, &rec); err != nil { 52 return false, err 53 } 54 55 s := types.Appearance{ 56 BlockNumber: rec.BlockNumber, 57 TransactionIndex: rec.TransactionIndex, 58 } 59 60 modelChan <- &s 61 } 62 63 return true, nil 64 } 65 66 walker := walk.NewCacheWalker( 67 chain, 68 opts.Globals.TestMode, 69 10, /* maxTests */ 70 showAppearances, 71 ) 72 73 if err := walker.WalkBloomFilters(blockNums); err != nil { 74 errorChan <- err 75 rCtx.Cancel() 76 } 77 } 78 79 extraOpts := map[string]any{ 80 "appearances": true, 81 } 82 return output.StreamMany(rCtx, fetchData, opts.Globals.OutputOptsWithExtra(extraOpts)) 83 }