Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace lazycell with once_cell #976

Merged
merged 6 commits into from
Feb 1, 2021
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion blockchain/state_manager/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ filecoin-proofs-api = { version = "5.4.1", features = [
futures = "0.3.5"
runtime = { package = "forest_runtime", version = "0.1" }
lazy_static = "1.4"
lazycell = "1.2.1"
once_cell = "1.5"
forest_crypto = { version = "0.4" }
networks = { path = "../../types/networks" }
statediff = { path = "../../utils/statediff", optional = true }
10 changes: 5 additions & 5 deletions blockchain/state_manager/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ use futures::FutureExt;
use interpreter::{resolve_to_key_addr, ApplyRet, BlockMessages, Rand, VM};
use interpreter::{CircSupplyCalc, LookbackStateGetter};
use ipld_amt::Amt;
use lazycell::AtomicLazyCell;
use log::{debug, info, trace, warn};
use message::{message_receipt, unsigned_message};
use message::{ChainMessage, Message, MessageReceipt, UnsignedMessage};
use networks::get_network_version_default;
use num_bigint::{bigint_ser, BigInt};
use num_traits::identities::Zero;
use once_cell::sync::OnceCell;
use serde::{Deserialize, Serialize};
use state_tree::StateTree;
use std::collections::HashMap;
Expand Down Expand Up @@ -473,14 +473,14 @@ where
{
// This isn't ideal to have, since the execution is syncronous, but this needs to be the
// case because the state transition has to be in blocking thread to avoid starving executor
let outm: AtomicLazyCell<UnsignedMessage> = Default::default();
let outr: AtomicLazyCell<ApplyRet> = Default::default();
let outm: OnceCell<UnsignedMessage> = Default::default();
let outr: OnceCell<ApplyRet> = Default::default();
let m_clone = outm.clone();
let r_clone = outr.clone();
let callback = move |cid: &Cid, unsigned: &ChainMessage, apply_ret: &ApplyRet| {
if *cid == mcid {
let _ = m_clone.fill(unsigned.message().clone());
let _ = r_clone.fill(apply_ret.clone());
let _ = m_clone.set(unsigned.message().clone());
let _ = r_clone.set(apply_ret.clone());
return Err("halt".to_string());
}

Expand Down
53 changes: 27 additions & 26 deletions blockchain/state_manager/src/vm_circ_supply.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ use cid::Cid;
use clock::ChainEpoch;
use fil_types::{FILECOIN_PRECISION, FIL_RESERVED};
use interpreter::CircSupplyCalc;
use lazycell::AtomicLazyCell;
use networks::{
UPGRADE_ACTORS_V2_HEIGHT, UPGRADE_CALICO_HEIGHT, UPGRADE_IGNITION_HEIGHT,
UPGRADE_LIFTOFF_HEIGHT,
};
use num_bigint::BigInt;
use once_cell::sync::OnceCell;
use state_tree::StateTree;
use std::error::Error as StdError;
use vm::{ActorState, TokenAmount};
Expand Down Expand Up @@ -51,8 +51,8 @@ pub struct GenesisInfo {
vesting: GenesisInfoVesting,

/// info about the Accounts in the genesis state
pub genesis_pledge: AtomicLazyCell<TokenAmount>,
pub genesis_market_funds: AtomicLazyCell<TokenAmount>,
pub genesis_pledge: OnceCell<TokenAmount>,
pub genesis_market_funds: OnceCell<TokenAmount>,
}

impl GenesisInfo {
Expand All @@ -67,18 +67,18 @@ impl GenesisInfo {

let _ = self
.genesis_market_funds
.fill(get_fil_market_locked(&state_tree)?);
let _ = self.genesis_pledge.fill(get_fil_power_locked(&state_tree)?);
.set(get_fil_market_locked(&state_tree)?);
let _ = self.genesis_pledge.set(get_fil_power_locked(&state_tree)?);

Ok(())
}
}

#[derive(Default)]
pub struct GenesisInfoVesting {
pub genesis: AtomicLazyCell<Vec<msig0::State>>,
pub ignition: AtomicLazyCell<Vec<msig0::State>>,
pub calico: AtomicLazyCell<Vec<msig0::State>>,
pub genesis: OnceCell<Vec<msig0::State>>,
pub ignition: OnceCell<Vec<msig0::State>>,
pub calico: OnceCell<Vec<msig0::State>>,
}

impl CircSupplyCalc for GenesisInfo {
Expand All @@ -92,19 +92,20 @@ impl CircSupplyCalc for GenesisInfo {
// but it's not ideal to have the side effect from the VM to modify the genesis info
// of the state manager. This isn't terrible because it's just caching to avoid
// recalculating using the store, and it avoids computing until circ_supply is called.
if !self.vesting.genesis.filled() {
self.init(state_tree.store())?;
let _ = self.vesting.genesis.fill(setup_genesis_vesting_schedule());
}
if !self.vesting.ignition.filled() {
let _ = self
.vesting
.ignition
.fill(setup_ignition_vesting_schedule());
}
if !self.vesting.calico.filled() {
let _ = self.vesting.calico.fill(setup_calico_vesting_schedule());
}
self.vesting
.genesis
.get_or_try_init(|| -> Result<_, Box<dyn StdError>> {
self.init(state_tree.store())?;
Ok(setup_genesis_vesting_schedule())
})?;

self.vesting
.ignition
.get_or_init(|| setup_ignition_vesting_schedule());

self.vesting
.calico
.get_or_init(|| setup_calico_vesting_schedule());

get_circulating_supply(&self, height, state_tree)
}
Expand All @@ -128,17 +129,17 @@ pub fn get_fil_vested(
let pre_ignition = genesis_info
.vesting
.genesis
.borrow()
.get()
.expect("Pre ignition should be initialized");
let post_ignition = genesis_info
.vesting
.ignition
.borrow()
.get()
.expect("Post ignition should be initialized");
let calico_vesting = genesis_info
.vesting
.calico
.borrow()
.get()
.expect("calico vesting should be initialized");

if height <= UPGRADE_IGNITION_HEIGHT {
Expand All @@ -160,11 +161,11 @@ pub fn get_fil_vested(
if height <= UPGRADE_ACTORS_V2_HEIGHT {
return_value += genesis_info
.genesis_pledge
.borrow()
.get()
.expect("Genesis info should be initialized")
+ genesis_info
.genesis_market_funds
.borrow()
.get()
.expect("Genesis info should be initialized");
}

Expand Down
2 changes: 1 addition & 1 deletion ipld/amt/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ encoding = { package = "forest_encoding", version = "0.2.1" }
serde = { version = "1.0", features = ["derive"] }
ipld_blockstore = "0.1"
thiserror = "1.0"
lazycell = "1.2.1"
once_cell = "1.5"
ahash = { version = "0.6", optional = true }

[features]
Expand Down
57 changes: 22 additions & 35 deletions ipld/amt/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use encoding::{
ser::{self, Serialize},
};
use ipld_blockstore::BlockStore;
use lazycell::LazyCell;
use once_cell::unsync::OnceCell;
use std::error::Error as StdError;

use super::ValueMut;
Expand All @@ -19,7 +19,7 @@ pub(super) enum Link<V> {
/// Unchanged link to data with an atomic cache.
Cid {
cid: Cid,
cache: LazyCell<Box<Node<V>>>,
cache: OnceCell<Box<Node<V>>>,
},
/// Modifications have been made to the link, requires flush to clear
Dirty(Box<Node<V>>),
Expand Down Expand Up @@ -75,14 +75,8 @@ impl<V> Default for Node<V> {
}

/// Turns the WIDTH length array into a vector for serialization
fn values_to_vec<T>(bmap: BitMap, values: &[Option<T>; WIDTH]) -> Vec<&T> {
let mut v: Vec<&T> = Vec::new();
for (i, _) in values.iter().enumerate().take(WIDTH) {
if bmap.get_bit(i as u64) {
v.push(values[i].as_ref().unwrap())
}
}
v
fn values_to_vec<T>(values: &[Option<T>]) -> Vec<&T> {
values.iter().filter_map(|val| val.as_ref()).collect()
}

/// Puts values from vector into shard array
Expand Down Expand Up @@ -125,7 +119,9 @@ where
S: ser::Serializer,
{
match &self {
Node::Leaf { bmap, vals } => (bmap, [0u8; 0], values_to_vec(*bmap, &vals)).serialize(s),
Node::Leaf { bmap, vals } => {
(bmap, [0u8; 0], values_to_vec(vals.as_ref())).serialize(s)
}
Node::Link { bmap, links } => {
let cids = cids_from_links(links).map_err(|e| ser::Error::custom(e.to_string()))?;
(bmap, cids, [0u8; 0]).serialize(s)
Expand Down Expand Up @@ -173,7 +169,7 @@ where
if let Some(Link::Cid { cache, .. }) = link {
// Yes, this is necessary to interop, and yes this is safe to borrow
// mutably because there are no values changed here, just extra db writes.
if let Some(cached) = cache.borrow_mut() {
if let Some(cached) = cache.get_mut() {
cached.flush(bs)?;
bs.put(cached, Blake2b256)?;
}
Expand All @@ -186,11 +182,9 @@ where
// Puts node in blockstore and and retrieves it's CID
let cid = bs.put(n, Blake2b256)?;

let cache = LazyCell::new();

// Can keep the flushed node in link cache
let node = std::mem::take(n);
let _ = cache.fill(node);
let cache = OnceCell::from(node);

// Turn dirty node into a Cid link
*link = Some(Link::Cid { cid, cache });
Expand Down Expand Up @@ -230,18 +224,13 @@ where
Node::Leaf { vals, .. } => Ok(vals[i as usize].as_ref()),
Node::Link { links, .. } => match &links[sub_i as usize] {
Some(Link::Cid { cid, cache }) => {
if let Some(cached_node) = cache.borrow() {
cached_node.get(bs, height - 1, i % nodes_for_height(height))
} else {
let node: Box<Node<V>> = bs
.get(cid)?
.ok_or_else(|| Error::CidNotFound(cid.to_string()))?;

// Ignore error intentionally, the cache value will always be the same
let _ = cache.fill(node);
let cache_node = cache.borrow().expect("cache filled on line above");
cache_node.get(bs, height - 1, i % nodes_for_height(height))
}
let cached_node =
cache.get_or_try_init(|| -> Result<Box<Node<V>>, Error> {
bs.get(cid)?
.ok_or_else(|| Error::CidNotFound(cid.to_string()))
})?;

cached_node.get(bs, height - 1, i % nodes_for_height(height))
}
Some(Link::Dirty(n)) => n.get(bs, height - 1, i % nodes_for_height(height)),
None => Ok(None),
Expand Down Expand Up @@ -387,7 +376,7 @@ where
// Replace cache, no node deleted.
// Error can be ignored because value will always be the same
// even if possible to hit race condition.
let _ = cache.fill(sub_node);
let _ = cache.set(sub_node);

// Index to be deleted was not found
return Ok(false);
Expand Down Expand Up @@ -446,7 +435,8 @@ where
let keep_going = match l.as_ref().expect("bit set at index") {
Link::Dirty(sub) => sub.for_each_while(store, height - 1, offs, f)?,
Link::Cid { cid, cache } => {
if let Some(cached_node) = cache.borrow() {
// TODO simplify with try_init when go-interop feature not needed
if let Some(cached_node) = cache.get() {
cached_node.for_each_while(store, height - 1, offs, f)?
} else {
let node: Box<Node<V>> = store
Expand All @@ -456,10 +446,7 @@ where
#[cfg(not(feature = "go-interop"))]
{
// Ignore error intentionally, the cache value will always be the same
let _ = cache.fill(node);
let cache_node =
cache.borrow().expect("cache filled on line above");

let cache_node = cache.get_or_init(|| node);
cache_node.for_each_while(store, height - 1, offs, f)?
}

Expand Down Expand Up @@ -542,14 +529,14 @@ where
#[cfg(feature = "go-interop")]
{
if cached {
let _ = cache.fill(node);
let _ = cache.set(node);
}
}

// Replace cache, or else iteration over without modification
// will consume cache
#[cfg(not(feature = "go-interop"))]
let _ = cache.fill(node);
let _ = cache.set(node);
}

(keep_going, did_mutate_node)
Expand Down
2 changes: 1 addition & 1 deletion ipld/hamt/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ forest_ipld = "0.1.1"
serde_bytes = { package = "cs_serde_bytes", version = "0.12" }
thiserror = "1.0"
sha2 = "0.9.1"
lazycell = "1.2.1"
once_cell = "1.5"
forest_hash_utils = "0.1"

[features]
Expand Down
Loading