github.com/sberex/go-sberex@v1.8.2-0.20181113200658-ed96ac38f7d7/core/bloombits/generator.go (about)

     1  // This file is part of the go-sberex library. The go-sberex library is 
     2  // free software: you can redistribute it and/or modify it under the terms 
     3  // of the GNU Lesser General Public License as published by the Free 
     4  // Software Foundation, either version 3 of the License, or (at your option)
     5  // any later version.
     6  //
     7  // The go-sberex library is distributed in the hope that it will be useful, 
     8  // but WITHOUT ANY WARRANTY; without even the implied warranty of
     9  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 
    10  // General Public License <http://www.gnu.org/licenses/> for more details.
    11  
    12  package bloombits
    13  
    14  import (
    15  	"errors"
    16  
    17  	"github.com/Sberex/go-sberex/core/types"
    18  )
    19  
    20  // errSectionOutOfBounds is returned if the user tried to add more bloom filters
    21  // to the batch than available space, or if tries to retrieve above the capacity,
    22  var errSectionOutOfBounds = errors.New("section out of bounds")
    23  
    24  // Generator takes a number of bloom filters and generates the rotated bloom bits
    25  // to be used for batched filtering.
    26  type Generator struct {
    27  	blooms   [types.BloomBitLength][]byte // Rotated blooms for per-bit matching
    28  	sections uint                         // Number of sections to batch together
    29  	nextBit  uint                         // Next bit to set when adding a bloom
    30  }
    31  
    32  // NewGenerator creates a rotated bloom generator that can iteratively fill a
    33  // batched bloom filter's bits.
    34  func NewGenerator(sections uint) (*Generator, error) {
    35  	if sections%8 != 0 {
    36  		return nil, errors.New("section count not multiple of 8")
    37  	}
    38  	b := &Generator{sections: sections}
    39  	for i := 0; i < types.BloomBitLength; i++ {
    40  		b.blooms[i] = make([]byte, sections/8)
    41  	}
    42  	return b, nil
    43  }
    44  
    45  // AddBloom takes a single bloom filter and sets the corresponding bit column
    46  // in memory accordingly.
    47  func (b *Generator) AddBloom(index uint, bloom types.Bloom) error {
    48  	// Make sure we're not adding more bloom filters than our capacity
    49  	if b.nextBit >= b.sections {
    50  		return errSectionOutOfBounds
    51  	}
    52  	if b.nextBit != index {
    53  		return errors.New("bloom filter with unexpected index")
    54  	}
    55  	// Rotate the bloom and insert into our collection
    56  	byteIndex := b.nextBit / 8
    57  	bitMask := byte(1) << byte(7-b.nextBit%8)
    58  
    59  	for i := 0; i < types.BloomBitLength; i++ {
    60  		bloomByteIndex := types.BloomByteLength - 1 - i/8
    61  		bloomBitMask := byte(1) << byte(i%8)
    62  
    63  		if (bloom[bloomByteIndex] & bloomBitMask) != 0 {
    64  			b.blooms[i][byteIndex] |= bitMask
    65  		}
    66  	}
    67  	b.nextBit++
    68  
    69  	return nil
    70  }
    71  
    72  // Bitset returns the bit vector belonging to the given bit index after all
    73  // blooms have been added.
    74  func (b *Generator) Bitset(idx uint) ([]byte, error) {
    75  	if b.nextBit != b.sections {
    76  		return nil, errors.New("bloom not fully generated yet")
    77  	}
    78  	if idx >= b.sections {
    79  		return nil, errSectionOutOfBounds
    80  	}
    81  	return b.blooms[idx], nil
    82  }