github.com/TrueBlocks/trueblocks-core/src/apps/chifra@v0.0.0-20241022031540-b362680128f7/internal/chunks/handle_blooms.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  	"fmt"
     9  	"strings"
    10  
    11  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/base"
    12  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/index"
    13  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/output"
    14  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/tslib"
    15  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/types"
    16  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/walk"
    17  )
    18  
    19  func (opts *ChunksOptions) HandleBlooms(rCtx *output.RenderCtx, blockNums []base.Blknum) error {
    20  	chain := opts.Globals.Chain
    21  
    22  	fetchData := func(modelChan chan types.Modeler, errorChan chan error) {
    23  		showBloom := func(walker *walk.CacheWalker, path string, first bool) (bool, error) {
    24  			if path != index.ToBloomPath(path) {
    25  				return false, fmt.Errorf("should not happen in showBloom")
    26  			}
    27  
    28  			var bl index.Bloom
    29  			_ = bl.Read(path)
    30  			nInserted := 0
    31  			for _, bl := range bl.Blooms {
    32  				nInserted += int(bl.NInserted)
    33  			}
    34  
    35  			if opts.Globals.Verbose {
    36  				displayBloom(&bl, 1)
    37  			}
    38  
    39  			stats, err := GetChunkStats(chain, path)
    40  			if err != nil {
    41  				return false, err
    42  			}
    43  
    44  			rng, err := base.RangeFromFilenameE(path)
    45  			if err != nil {
    46  				return false, err
    47  			}
    48  			s := types.ChunkBloom{
    49  				Magic:     fmt.Sprintf("0x%x", bl.Header.Magic),
    50  				Hash:      bl.Header.Hash,
    51  				Size:      stats.BloomSz,
    52  				Range:     rng.String(),
    53  				NBlooms:   stats.NBlooms,
    54  				ByteWidth: index.BLOOM_WIDTH_IN_BYTES,
    55  				NInserted: uint64(nInserted),
    56  			}
    57  			rd := tslib.RangeToBounds(chain, &rng)
    58  			s.RangeDates = &rd
    59  
    60  			modelChan <- &s
    61  			return true, nil
    62  		}
    63  
    64  		walker := walk.NewCacheWalker(
    65  			chain,
    66  			opts.Globals.TestMode,
    67  			10, /* maxTests */
    68  			showBloom,
    69  		)
    70  		if err := walker.WalkBloomFilters(blockNums); err != nil {
    71  			errorChan <- err
    72  			rCtx.Cancel()
    73  		}
    74  	}
    75  
    76  	return output.StreamMany(rCtx, fetchData, opts.Globals.OutputOpts())
    77  }
    78  
    79  func displayBloom(bl *index.Bloom, verbose int) {
    80  	var bytesPerLine = (2048 / 16) /* 128 */
    81  	if verbose > 0 && verbose <= 4 {
    82  		bytesPerLine = 32
    83  	}
    84  
    85  	nInserted := uint32(0)
    86  	for i := uint32(0); i < bl.Count; i++ {
    87  		nInserted += bl.Blooms[i].NInserted
    88  	}
    89  	fmt.Println("range:", bl.Range)
    90  	fmt.Println("nBlooms:", bl.Count)
    91  	fmt.Println("byteWidth:", index.BLOOM_WIDTH_IN_BYTES)
    92  	fmt.Println("nInserted:", nInserted)
    93  	if verbose > 0 {
    94  		for i := uint32(0); i < bl.Count; i++ {
    95  			for j := 0; j < len(bl.Blooms[i].Bytes); j++ {
    96  				if (j % bytesPerLine) == 0 {
    97  					if j != 0 {
    98  						fmt.Println()
    99  					}
   100  				}
   101  				ch := bl.Blooms[i].Bytes[j]
   102  				str := fmt.Sprintf("%08b", ch)
   103  				fmt.Printf("%s ", strings.Replace(str, "0", ".", -1))
   104  			}
   105  		}
   106  		fmt.Println()
   107  	}
   108  }