github.com/TrueBlocks/trueblocks-core/src/apps/chifra@v0.0.0-20241022031540-b362680128f7/internal/chunks/handle_address.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  	"errors"
    10  	"fmt"
    11  	"io"
    12  	"strings"
    13  
    14  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/base"
    15  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/config"
    16  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/file"
    17  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/index"
    18  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/output"
    19  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/tslib"
    20  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/types"
    21  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/walk"
    22  )
    23  
    24  func (opts *ChunksOptions) HandleAddresses(rCtx *output.RenderCtx, blockNums []base.Blknum) error {
    25  	chain := opts.Globals.Chain
    26  	been_here := 0
    27  	fetchData := func(modelChan chan types.Modeler, errorChan chan error) {
    28  		var showAddresses func(walker *walk.CacheWalker, path string, first bool) (bool, error)
    29  		if opts.Globals.Verbose {
    30  			showAddresses = func(walker *walk.CacheWalker, path string, first bool) (bool, error) {
    31  				return opts.handleResolvedRecords1(modelChan, walker, path)
    32  			}
    33  		} else {
    34  			showAddresses = func(walker *walk.CacheWalker, path string, first bool) (bool, error) {
    35  				if path != index.ToBloomPath(path) {
    36  					return false, fmt.Errorf("should not happen in showAddresses")
    37  				}
    38  
    39  				path = index.ToIndexPath(path)
    40  				if !file.FileExists(path) {
    41  					// This is okay, if the user used chifra init without the --all option. Warn them and continue
    42  					msg := ""
    43  					path = strings.Replace(path, config.PathToIndex(chain)+"/", "$indexPath/", 1)
    44  					if been_here < 3 {
    45  						msg = fmt.Sprintf("index file %s does not exist. Run 'chifra init --all' to create it.", path)
    46  					} else if been_here == 3 {
    47  						msg = fmt.Sprintf("index file %s does not exist. Warnings turned off...", path)
    48  					}
    49  					if msg != "" {
    50  						errorChan <- errors.New(msg)
    51  					}
    52  					been_here++
    53  					return true, nil
    54  				}
    55  
    56  				indexChunk, err := index.OpenIndex(path, true /* check */)
    57  				if err != nil {
    58  					return false, err
    59  				}
    60  				defer indexChunk.Close()
    61  
    62  				_, err = indexChunk.File.Seek(int64(index.HeaderWidth), io.SeekStart)
    63  				if err != nil {
    64  					return false, err
    65  				}
    66  
    67  				cnt := 0
    68  				for i := 0; i < int(indexChunk.Header.AddressCount); i++ {
    69  					if opts.Globals.TestMode && i > walker.MaxTests() {
    70  						continue
    71  					}
    72  
    73  					obj := types.AddrRecord{}
    74  					if err := binary.Read(indexChunk.File, binary.LittleEndian, &obj); err != nil {
    75  						return false, err
    76  					}
    77  
    78  					rng := indexChunk.Range
    79  					s := types.ChunkAddress{
    80  						Address: obj.Address,
    81  						Range:   rng.String(),
    82  						Offset:  uint64(obj.Offset),
    83  						Count:   uint64(obj.Count),
    84  					}
    85  					rd := tslib.RangeToBounds(chain, &rng)
    86  					s.RangeDates = &rd
    87  
    88  					modelChan <- &s
    89  					cnt++
    90  				}
    91  				return true, nil
    92  			}
    93  		}
    94  
    95  		walker := walk.NewCacheWalker(
    96  			chain,
    97  			opts.Globals.TestMode,
    98  			10, /* maxTests */
    99  			showAddresses,
   100  		)
   101  		if err := walker.WalkBloomFilters(blockNums); err != nil {
   102  			errorChan <- err
   103  			rCtx.Cancel()
   104  		}
   105  	}
   106  
   107  	return output.StreamMany(rCtx, fetchData, opts.Globals.OutputOpts())
   108  }