Skip to content

Commit

Permalink
cr: use custom error for bitfield_queue
Browse files Browse the repository at this point in the history
  • Loading branch information
dignifiedquire committed Apr 19, 2022
1 parent e9be933 commit 465b56e
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 33 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions actors/miner/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ byteorder = "1.4.3"
itertools = "0.10.3"
fvm_ipld_blockstore = { version = "0.1" }
fvm_ipld_encoding = "0.1.0"
thiserror = "1.0"

[dev-dependencies]
fil_actors_runtime = { version = "8.0.0-alpha.1", path = "../runtime", features = ["test_utils", "sector-default"] }
Expand Down
68 changes: 39 additions & 29 deletions actors/miner/src/bitfield_queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
// SPDX-License-Identifier: Apache-2.0, MIT

use std::convert::TryInto;
use std::num::TryFromIntError;

use cid::Cid;
use fil_actors_runtime::{ActorContext, ActorError, Array};
use fil_actors_runtime::{ActorError, Array};
use fvm_ipld_amt::Error as AmtError;
use fvm_ipld_bitfield::BitField;
use fvm_ipld_blockstore::Blockstore;
Expand All @@ -18,8 +19,28 @@ pub struct BitFieldQueue<'db, BS> {
quant: QuantSpec,
}

#[derive(thiserror::Error, Debug)]
pub enum Error<E> {
#[error("amt {0}")]
Amt(#[from] AmtError<E>),
#[error("conversion failure {0}")]
Int(#[from] TryFromIntError),
#[error("bitfield {0}")]
Bitfield(#[from] fvm_ipld_bitfield::OutOfRangeError),
}

impl<E: std::error::Error> From<Error<E>> for ActorError {
fn from(e: Error<E>) -> Self {
match e {
Error::Amt(e) => e.into(),
Error::Int(e) => e.into(),
Error::Bitfield(e) => e.into(),
}
}
}

impl<'db, BS: Blockstore> BitFieldQueue<'db, BS> {
pub fn new(store: &'db BS, root: &Cid, quant: QuantSpec) -> Result<Self, AmtError<BS::Error>> {
pub fn new(store: &'db BS, root: &Cid, quant: QuantSpec) -> Result<Self, Error<BS::Error>> {
Ok(Self { amt: Array::load(root, store)?, quant })
}

Expand All @@ -28,24 +49,17 @@ impl<'db, BS: Blockstore> BitFieldQueue<'db, BS> {
&mut self,
raw_epoch: ChainEpoch,
values: &BitField,
) -> Result<(), ActorError> {
) -> Result<(), Error<BS::Error>> {
if values.is_empty() {
// nothing to do.
return Ok(());
}

let epoch: u64 = self.quant.quantize_up(raw_epoch).try_into()?;

let bitfield = self
.amt
.get(epoch)
.with_context(|| format!("failed to lookup queue epoch {}", epoch))?
.cloned()
.unwrap_or_default();
let bitfield = self.amt.get(epoch)?.cloned().unwrap_or_default();

self.amt
.set(epoch, &bitfield | values)
.with_context(|| format!("failed to set queue epoch {}", epoch))?;
self.amt.set(epoch, &bitfield | values)?;

Ok(())
}
Expand All @@ -54,40 +68,36 @@ impl<'db, BS: Blockstore> BitFieldQueue<'db, BS> {
&mut self,
epoch: ChainEpoch,
values: impl IntoIterator<Item = u64>,
) -> Result<(), ActorError> {
) -> Result<(), Error<BS::Error>> {
self.add_to_queue(epoch, &BitField::try_from_bits(values)?)
}

/// Cut cuts the elements from the bits in the given bitfield out of the queue,
/// shifting other bits down and removing any newly empty entries.
///
/// See the docs on `BitField::cut` to better understand what it does.
pub fn cut(&mut self, to_cut: &BitField) -> Result<(), ActorError> {
pub fn cut(&mut self, to_cut: &BitField) -> Result<(), Error<BS::Error>> {
let mut epochs_to_remove = Vec::<u64>::new();

self.amt
.for_each_mut(|epoch, bitfield| {
let bf = bitfield.cut(to_cut);
self.amt.for_each_mut(|epoch, bitfield| {
let bf = bitfield.cut(to_cut);

if bf.is_empty() {
epochs_to_remove.push(epoch);
} else {
**bitfield = bf;
}
})
.context("failed to cut from bitfield queue")?;
if bf.is_empty() {
epochs_to_remove.push(epoch);
} else {
**bitfield = bf;
}
})?;

self.amt
.batch_delete(epochs_to_remove, true)
.context("failed to remove empty epochs from bitfield queue")?;
self.amt.batch_delete(epochs_to_remove, true)?;

Ok(())
}

pub fn add_many_to_queue_values(
&mut self,
values: impl IntoIterator<Item = (ChainEpoch, u64)>,
) -> Result<(), ActorError> {
) -> Result<(), Error<BS::Error>> {
// Pre-quantize to reduce the number of updates.
let mut quantized_values: Vec<_> = values
.into_iter()
Expand All @@ -112,7 +122,7 @@ impl<'db, BS: Blockstore> BitFieldQueue<'db, BS> {

/// Removes and returns all values with keys less than or equal to until.
/// Modified return value indicates whether this structure has been changed by the call.
pub fn pop_until(&mut self, until: ChainEpoch) -> Result<(BitField, bool), ActorError> {
pub fn pop_until(&mut self, until: ChainEpoch) -> Result<(BitField, bool), Error<BS::Error>> {
let mut popped_values = BitField::new();
let mut popped_keys = Vec::<u64>::new();

Expand Down
8 changes: 4 additions & 4 deletions actors/miner/src/deadline_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,11 +279,11 @@ impl Deadline {
return Ok(());
}

let mut queue = BitFieldQueue::new(store, &self.expirations_epochs, quant)
.context("failed to load expiration queue")?;
let mut queue = BitFieldQueue::new(store, &self.expirations_epochs, quant)?;

queue
.add_to_queue_values(expiration_epoch, partitions.iter().copied())
.context("failed to mutate expiration queue")?;
.add_to_queue_values(expiration_epoch, partitions.iter().copied())?;

self.expirations_epochs = queue.amt.flush().context("failed to save expiration queue")?;

Ok(())
Expand Down

0 comments on commit 465b56e

Please sign in to comment.