bloom filter uses vector instead of hashmap, added few comments

This commit is contained in:
debris 2015-11-28 20:32:46 +01:00
parent 1a30d91853
commit d1223b3b15
1 changed files with 22 additions and 10 deletions

View File

@ -35,24 +35,26 @@ pub struct ChainFilter<'a, D>
{ {
data_source: &'a D, data_source: &'a D,
index_size: usize, index_size: usize,
levels: u8, level_sizes: Vec<usize>,
level_sizes: HashMap<u8, usize>,
} }
impl<'a, D> ChainFilter<'a, D> where D: FilterDataSource impl<'a, D> ChainFilter<'a, D> where D: FilterDataSource
{ {
/// creates new filter instance /// creates new filter instance
pub fn new(data_source: &'a D, index_size: usize, levels: u8) -> Self { pub fn new(data_source: &'a D, index_size: usize, levels: u8) -> Self {
if levels == 0 {
panic!("ChainFilter requires and least 1 level");
}
let mut filter = ChainFilter { let mut filter = ChainFilter {
data_source: data_source, data_source: data_source,
index_size: index_size, index_size: index_size,
levels: levels, level_sizes: vec![]
level_sizes: HashMap::new(),
}; };
// cache level sizes, so we do not have to calculate them all the time // cache level sizes, so we do not have to calculate them all the time
for i in 0..levels { for i in 0..levels {
filter.level_sizes.insert(i, pow(index_size, i as usize)); filter.level_sizes.push(pow(index_size, i as usize));
} }
filter filter
@ -60,7 +62,7 @@ impl<'a, D> ChainFilter<'a, D> where D: FilterDataSource
/// unsafely get level size /// unsafely get level size
fn level_size(&self, level: u8) -> usize { fn level_size(&self, level: u8) -> usize {
*self.level_sizes.get(&level).unwrap() self.level_sizes[level as usize]
} }
/// converts block number and level to `BloomIndex` /// converts block number and level to `BloomIndex`
@ -95,9 +97,14 @@ impl<'a, D> ChainFilter<'a, D> where D: FilterDataSource
indexes indexes
} }
/// return number of levels
fn levels(&self) -> u8 {
self.level_sizes.len() as u8
}
/// returns max filter level /// returns max filter level
fn max_level(&self) -> u8 { fn max_level(&self) -> u8 {
self.levels - 1 self.level_sizes.len() as u8 - 1
} }
/// internal function which actually does bloom search /// internal function which actually does bloom search
@ -146,7 +153,7 @@ impl<'a, D> Filter for ChainFilter<'a, D> where D: FilterDataSource
fn add_bloom(&self, bloom: &H2048, block_number: usize) -> HashMap<BloomIndex, H2048> { fn add_bloom(&self, bloom: &H2048, block_number: usize) -> HashMap<BloomIndex, H2048> {
let mut result: HashMap<BloomIndex, H2048> = HashMap::new(); let mut result: HashMap<BloomIndex, H2048> = HashMap::new();
for level in 0..self.levels { for level in 0..self.levels() {
let bloom_index = self.bloom_index(block_number, level); let bloom_index = self.bloom_index(block_number, level);
let new_bloom = match self.data_source.bloom_at_index(&bloom_index) { let new_bloom = match self.data_source.bloom_at_index(&bloom_index) {
Some(old_bloom) => old_bloom | bloom, Some(old_bloom) => old_bloom | bloom,
@ -165,7 +172,7 @@ impl<'a, D> Filter for ChainFilter<'a, D> where D: FilterDataSource
fn add_blooms(&self, blooms: &[H2048], block_number: usize) -> HashMap<BloomIndex, H2048> { fn add_blooms(&self, blooms: &[H2048], block_number: usize) -> HashMap<BloomIndex, H2048> {
let mut result: HashMap<BloomIndex, H2048> = HashMap::new(); let mut result: HashMap<BloomIndex, H2048> = HashMap::new();
for level in 0..self.levels { for level in 0..self.levels() {
for i in 0..blooms.len() { for i in 0..blooms.len() {
let bloom_index = self.bloom_index(block_number + i, level); let bloom_index = self.bloom_index(block_number + i, level);
let is_new_bloom = match result.get_mut(&bloom_index) { let is_new_bloom = match result.get_mut(&bloom_index) {
@ -199,13 +206,18 @@ impl<'a, D> Filter for ChainFilter<'a, D> where D: FilterDataSource
let mut reset_index = self.bloom_index(block_number, 0); let mut reset_index = self.bloom_index(block_number, 0);
result.insert(reset_index.clone(), bloom.clone()); result.insert(reset_index.clone(), bloom.clone());
for level in 1..self.levels { for level in 1..self.levels() {
let index = self.bloom_index(block_number, level); let index = self.bloom_index(block_number, level);
// get all bloom indexes that were used to construct this bloom
let lower_indexes = self.lower_level_bloom_indexes(&index); let lower_indexes = self.lower_level_bloom_indexes(&index);
let new_bloom = lower_indexes.into_iter() let new_bloom = lower_indexes.into_iter()
// skip reseted one
.filter(|li| li != &reset_index) .filter(|li| li != &reset_index)
// get blooms for these indexes
.map(|li| self.data_source.bloom_at_index(&li)) .map(|li| self.data_source.bloom_at_index(&li))
// filter existing ones
.filter_map(|b| b) .filter_map(|b| b)
// BitOr all of them
.fold(H2048::new(), |acc, bloom| &acc | bloom); .fold(H2048::new(), |acc, bloom| &acc | bloom);
reset_index = index.clone(); reset_index = index.clone();