db: migrate from lmdb-zero to heed

This commit is contained in:
ardocrat
2026-04-16 12:12:34 +03:00
parent 90dab5fcc6
commit 1036ca6ac1
16 changed files with 594 additions and 532 deletions
+35 -25
View File
@@ -275,22 +275,30 @@ impl Peers {
}
}
/// Iterator over all peers we know about (stored in our db).
pub fn peer_data_iter(&self) -> Result<impl Iterator<Item = PeerData>, Error> {
self.store.peers_iter().map_err(From::from)
}
/// Convenience for reading all peer data from the db.
pub fn all_peer_data(&self) -> Vec<PeerData> {
self.peer_data_iter()
.map(|peers| peers.collect())
.unwrap_or(vec![])
match self.store.iter_batch() {
Ok(batch) => match batch.peers_iter() {
Ok(iter) => iter.collect(),
Err(e) => {
error!("failed to get all peer data: {:?}", e);
vec![]
}
},
Err(e) => {
error!("failed to get all peer data: {:?}", e);
vec![]
}
}
}
/// Find peers in store (not necessarily connected) and return their data
pub fn find_peers(&self, state: State, cap: Capabilities, count: usize) -> Vec<PeerData> {
match self.store.find_peers(state, cap, count) {
Ok(peers) => peers,
match self.store.iter_batch() {
Ok(batch) => batch.find_peers(state, cap, count).unwrap_or_else(|e| {
error!("failed to find peers: {:?}", e);
vec![]
}),
Err(e) => {
error!("failed to find peers: {:?}", e);
vec![]
@@ -445,24 +453,26 @@ impl Peers {
let now = Utc::now();
// Delete defunct peers from storage
let _ = self.store.delete_peers(|peer| {
let diff = now - Utc.timestamp_opt(peer.last_connected, 0).unwrap();
if let Ok(batch) = self.store.iter_batch() {
let _ = batch.delete_peers(|peer| {
let diff = now - Utc.timestamp_opt(peer.last_connected, 0).unwrap();
let should_remove = peer.flags == State::Defunct
&& diff > Duration::seconds(global::PEER_EXPIRATION_REMOVE_TIME);
let should_remove = peer.flags == State::Defunct
&& diff > Duration::seconds(global::PEER_EXPIRATION_REMOVE_TIME);
if should_remove {
debug!(
"removing peer {:?}: last connected {} days {} hours {} minutes ago.",
peer.addr,
diff.num_days(),
diff.num_hours(),
diff.num_minutes()
);
}
if should_remove {
debug!(
"removing peer {:?}: last connected {} days {} hours {} minutes ago.",
peer.addr,
diff.num_days(),
diff.num_hours(),
diff.num_minutes()
);
}
should_remove
});
should_remove
});
}
}
}
+51 -49
View File
@@ -119,19 +119,19 @@ impl PeerStore {
/// Instantiates a new peer store under the provided root path.
pub fn new(db_root: &str) -> Result<PeerStore, Error> {
let db = grin_store::Store::new(db_root, Some(DB_NAME), Some(STORE_SUBPATH), None)?;
Ok(PeerStore { db: db })
Ok(PeerStore { db })
}
pub fn save_peer(&self, p: &PeerData) -> Result<(), Error> {
debug!("save_peer: {:?} marked {:?}", p.addr, p.flags);
let batch = self.db.batch()?;
let mut batch = self.db.batch()?;
batch.put_ser(&peer_key(p.addr)[..], p)?;
batch.commit()
}
pub fn save_peers(&self, p: Vec<PeerData>) -> Result<(), Error> {
let batch = self.db.batch()?;
let mut batch = self.db.batch()?;
for pd in p {
debug!("save_peers: {:?} marked {:?}", pd.addr, pd.flags);
batch.put_ser(&peer_key(pd.addr)[..], &pd)?;
@@ -149,50 +149,11 @@ impl PeerStore {
self.db.exists(&peer_key(peer_addr)[..])
}
/// TODO - allow below added to avoid github issue reports
#[allow(dead_code)]
pub fn delete_peer(&self, peer_addr: PeerAddr) -> Result<(), Error> {
let batch = self.db.batch()?;
batch.delete(&peer_key(peer_addr)[..])?;
batch.commit()
}
/// Find some peers in our local db.
pub fn find_peers(
&self,
state: State,
cap: Capabilities,
count: usize,
) -> Result<Vec<PeerData>, Error> {
let peers = self
.peers_iter()?
.filter(|p| p.flags == state && p.capabilities.contains(cap))
.choose_multiple(&mut thread_rng(), count);
Ok(peers)
}
/// Iterator over all known peers.
pub fn peers_iter(&self) -> Result<impl Iterator<Item = PeerData>, Error> {
let key = to_key(PEER_PREFIX, "");
let protocol_version = self.db.protocol_version();
self.db.iter(&key, move |_, mut v| {
ser::deserialize(&mut v, protocol_version, DeserializationMode::default())
.map_err(From::from)
})
}
/// List all known peers
/// Used for /v1/peers/all api endpoint
pub fn all_peers(&self) -> Result<Vec<PeerData>, Error> {
let peers: Vec<PeerData> = self.peers_iter()?.collect();
Ok(peers)
}
/// Convenience method to load a peer data, update its status and save it
/// back. If new state is Banned its last banned time will be updated too.
/// If new state is Defunct last connection attempt will be updated too.
pub fn update_state(&self, peer_addr: PeerAddr, new_state: State) -> Result<(), Error> {
let batch = self.db.batch()?;
let mut batch = self.db.batch()?;
let mut peer = option_to_not_found(
batch.get_ser::<PeerData>(&peer_key(peer_addr)[..], None),
@@ -209,8 +170,52 @@ impl PeerStore {
batch.commit()
}
/// Builds a new iterator batch to be used with this store.
pub fn iter_batch(&self) -> Result<PeersIterBatch<'_>, Error> {
Ok(PeersIterBatch {
db: self.db.batch()?,
})
}
}
pub struct PeersIterBatch<'a> {
db: grin_store::Batch<'a>,
}
impl<'a> PeersIterBatch<'a> {
/// Iterator over all known peers.
pub fn peers_iter(&self) -> Result<impl Iterator<Item = PeerData> + 'a, Error> {
let key = to_key(PEER_PREFIX, "");
let protocol_version = self.db.protocol_version();
self.db.iter(&key, move |_, mut v| {
ser::deserialize(&mut v, protocol_version, DeserializationMode::default())
.map_err(From::from)
})
}
/// Find some peers in our local db.
pub fn find_peers(
&self,
state: State,
cap: Capabilities,
count: usize,
) -> Result<Vec<PeerData>, Error> {
let peers = self
.peers_iter()?
.filter(|p| p.flags == state && p.capabilities.contains(cap))
.choose_multiple(&mut thread_rng(), count);
Ok(peers)
}
/// List all known peers
/// Used for /v1/peers/all api endpoint
pub fn all_peers(&self) -> Result<Vec<PeerData>, Error> {
let peers: Vec<PeerData> = self.peers_iter()?.collect();
Ok(peers)
}
/// Deletes peers from the storage that satisfy some condition `predicate`
pub fn delete_peers<F>(&self, predicate: F) -> Result<(), Error>
pub fn delete_peers<F>(mut self, predicate: F) -> Result<(), Error>
where
F: Fn(&PeerData) -> bool,
{
@@ -224,13 +229,10 @@ impl PeerStore {
// Delete peers in single batch
if !to_remove.is_empty() {
let batch = self.db.batch()?;
for peer in to_remove {
batch.delete(&peer_key(peer.addr)[..])?;
self.db.delete(&peer_key(peer.addr)[..])?;
}
batch.commit()?;
self.db.commit()?;
}
Ok(())