Merge pull request #266 from ethcore/block_assembler

MemoryPoolIterator
This commit is contained in:
Svyatoslav Nikolsky 2016-12-08 14:11:23 +03:00 committed by GitHub
commit a16cc16b88
1 changed files with 44 additions and 42 deletions

View File

@ -381,47 +381,6 @@ impl Storage {
} }
} }
pub fn read_n_with_strategy(&self, mut n: usize, strategy: OrderingStrategy) -> Vec<H256> {
if n == 0 {
return Vec::new();
}
if n == 1 {
return self.read_with_strategy(strategy)
.map_or(Vec::new(), |h| vec![h]);
}
let mut references = self.references.clone();
let mut result: Vec<H256> = Vec::new();
let mut removed: HashSet<H256> = HashSet::new();
loop {
if n == 0 {
break;
}
n -= 1;
let top_hash = match strategy {
OrderingStrategy::ByTimestamp => references.ordered.by_storage_index.iter().map(|entry| entry.hash.clone()).nth(0),
OrderingStrategy::ByTransactionScore => references.ordered.by_transaction_score.iter().map(|entry| entry.hash.clone()).nth(0),
OrderingStrategy::ByPackageScore => references.ordered.by_package_score.iter().map(|entry| entry.hash.clone()).nth(0),
};
match top_hash {
None => break,
Some(top_hash) => {
self.by_hash.get(&top_hash).map(|entry| {
// simulate removal
removed.insert(top_hash.clone());
references.remove(Some(&removed), &self.by_hash, entry);
// return this entry
result.push(top_hash);
});
},
}
}
result
}
pub fn remove_by_hash(&mut self, h: &H256) -> Option<Entry> { pub fn remove_by_hash(&mut self, h: &H256) -> Option<Entry> {
self.by_hash.remove(h) self.by_hash.remove(h)
.map(|entry| { .map(|entry| {
@ -634,6 +593,11 @@ impl MemoryPool {
} }
} }
/// Iterator over memory pool transactions according to specified strategy
pub fn iter(&self, strategy: OrderingStrategy) -> MemoryPoolIterator {
MemoryPoolIterator::new(self, strategy)
}
/// Removes single transaction by its hash. /// Removes single transaction by its hash.
/// All descedants remain in the pool. /// All descedants remain in the pool.
pub fn remove_by_hash(&mut self, h: &H256) -> Option<Transaction> { pub fn remove_by_hash(&mut self, h: &H256) -> Option<Transaction> {
@ -660,7 +624,7 @@ impl MemoryPool {
/// Ancestors are always returned before descendant transactions. /// Ancestors are always returned before descendant transactions.
/// Use this function with care, only if really needed (heavy memory usage) /// Use this function with care, only if really needed (heavy memory usage)
pub fn read_n_with_strategy(&mut self, n: usize, strategy: OrderingStrategy) -> Vec<H256> { pub fn read_n_with_strategy(&mut self, n: usize, strategy: OrderingStrategy) -> Vec<H256> {
self.storage.read_n_with_strategy(n, strategy) self.iter(strategy).take(n).collect()
} }
/// Removes the 'top' transaction from the `MemoryPool` using selected strategy. /// Removes the 'top' transaction from the `MemoryPool` using selected strategy.
@ -789,6 +753,44 @@ impl HeapSizeOf for MemoryPool {
} }
} }
pub struct MemoryPoolIterator<'a> {
memory_pool: &'a MemoryPool,
references: ReferenceStorage,
removed: HashSet<H256>,
strategy: OrderingStrategy,
}
impl<'a> MemoryPoolIterator<'a> {
fn new(memory_pool: &'a MemoryPool, strategy: OrderingStrategy) -> Self {
MemoryPoolIterator {
memory_pool: memory_pool,
references: memory_pool.storage.references.clone(),
removed: HashSet::new(),
strategy: strategy,
}
}
}
impl<'a> Iterator for MemoryPoolIterator<'a> {
type Item = H256;
fn next(&mut self) -> Option<Self::Item> {
let top_hash = match self.strategy {
OrderingStrategy::ByTimestamp => self.references.ordered.by_storage_index.iter().map(|entry| entry.hash.clone()).nth(0),
OrderingStrategy::ByTransactionScore => self.references.ordered.by_transaction_score.iter().map(|entry| entry.hash.clone()).nth(0),
OrderingStrategy::ByPackageScore => self.references.ordered.by_package_score.iter().map(|entry| entry.hash.clone()).nth(0),
};
if let Some(ref top_hash) = top_hash {
let entry = self.memory_pool.storage.by_hash.get(top_hash).expect("missing hash is a sign of MemoryPool internal inconsistancy");
self.removed.insert(top_hash.clone());
self.references.remove(Some(&self.removed), &self.memory_pool.storage.by_hash, entry);
}
top_hash
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use db::PreviousTransactionOutputProvider; use db::PreviousTransactionOutputProvider;