mirror of
https://github.com/mikedilger/gossip.git
synced 2024-09-29 16:31:18 +00:00
storage: person_list_2 database, records if entry is 'public'
This commit is contained in:
parent
204bb4c145
commit
4b0b0e1602
@ -27,6 +27,7 @@ mod hashtags1;
|
||||
mod people1;
|
||||
mod people2;
|
||||
mod person_lists1;
|
||||
mod person_lists2;
|
||||
mod person_relays1;
|
||||
mod relationships1;
|
||||
mod relays1;
|
||||
|
158
gossip-lib/src/storage/person_lists2.rs
Normal file
158
gossip-lib/src/storage/person_lists2.rs
Normal file
@ -0,0 +1,158 @@
|
||||
use super::types::PersonList1;
|
||||
use crate::error::Error;
|
||||
use crate::storage::{RawDatabase, Storage};
|
||||
use heed::types::UnalignedSlice;
|
||||
use heed::RwTxn;
|
||||
use nostr_types::PublicKey;
|
||||
use speedy::{Readable, Writable};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Mutex;
|
||||
|
||||
// Pubkey -> Vec<(PersonList, bool)> // bool is if private or not
|
||||
// key: pubkey.as_bytes()
|
||||
|
||||
static PERSON_LISTS2_DB_CREATE_LOCK: Mutex<()> = Mutex::new(());
|
||||
static mut PERSON_LISTS2_DB: Option<RawDatabase> = None;
|
||||
|
||||
impl Storage {
|
||||
pub(super) fn db_person_lists2(&self) -> Result<RawDatabase, Error> {
|
||||
unsafe {
|
||||
if let Some(db) = PERSON_LISTS2_DB {
|
||||
Ok(db)
|
||||
} else {
|
||||
// Lock. This drops when anything returns.
|
||||
let _lock = PERSON_LISTS2_DB_CREATE_LOCK.lock();
|
||||
|
||||
// In case of a race, check again
|
||||
if let Some(db) = PERSON_LISTS2_DB {
|
||||
return Ok(db);
|
||||
}
|
||||
|
||||
// Create it. We know that nobody else is doing this and that
|
||||
// it cannot happen twice.
|
||||
let mut txn = self.env.write_txn()?;
|
||||
let db = self
|
||||
.env
|
||||
.database_options()
|
||||
.types::<UnalignedSlice<u8>, UnalignedSlice<u8>>()
|
||||
// no .flags needed
|
||||
.name("person_lists_2")
|
||||
.create(&mut txn)?;
|
||||
txn.commit()?;
|
||||
PERSON_LISTS2_DB = Some(db);
|
||||
Ok(db)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn read_person_lists2(
|
||||
&self,
|
||||
pubkey: &PublicKey,
|
||||
) -> Result<HashMap<PersonList1, bool>, Error> {
|
||||
let key: Vec<u8> = pubkey.to_bytes();
|
||||
let txn = self.env.read_txn()?;
|
||||
Ok(match self.db_person_lists2()?.get(&txn, &key)? {
|
||||
None => HashMap::new(),
|
||||
Some(bytes) => HashMap::<PersonList1, bool>::read_from_buffer(bytes)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn write_person_lists2<'a>(
|
||||
&'a self,
|
||||
pubkey: &PublicKey,
|
||||
map: HashMap<PersonList1, bool>,
|
||||
rw_txn: Option<&mut RwTxn<'a>>,
|
||||
) -> Result<(), Error> {
|
||||
let key: Vec<u8> = pubkey.to_bytes();
|
||||
let bytes: Vec<u8> = map.write_to_vec()?;
|
||||
|
||||
let f = |txn: &mut RwTxn<'a>| -> Result<(), Error> {
|
||||
self.db_person_lists2()?.put(txn, &key, &bytes)?;
|
||||
Ok(())
|
||||
};
|
||||
|
||||
match rw_txn {
|
||||
Some(txn) => f(txn)?,
|
||||
None => {
|
||||
let mut txn = self.env.write_txn()?;
|
||||
f(&mut txn)?;
|
||||
txn.commit()?;
|
||||
}
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn get_people_in_list2(
|
||||
&self,
|
||||
list: PersonList1,
|
||||
public: Option<bool>,
|
||||
) -> Result<Vec<PublicKey>, Error> {
|
||||
let txn = self.env.read_txn()?;
|
||||
let mut pubkeys: Vec<PublicKey> = Vec::new();
|
||||
for result in self.db_person_lists2()?.iter(&txn)? {
|
||||
let (key, val) = result?;
|
||||
let pubkey = PublicKey::from_bytes(key, true)?;
|
||||
let map = HashMap::<PersonList1, bool>::read_from_buffer(val)?;
|
||||
if let Some(p) = map.get(&list) {
|
||||
match public {
|
||||
Some(p2) => {
|
||||
if p2 == *p {
|
||||
pubkeys.push(pubkey);
|
||||
}
|
||||
}
|
||||
None => {
|
||||
pubkeys.push(pubkey);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(pubkeys)
|
||||
}
|
||||
|
||||
pub(crate) fn clear_person_list2<'a>(
|
||||
&'a self,
|
||||
list: PersonList1,
|
||||
rw_txn: Option<&mut RwTxn<'a>>,
|
||||
) -> Result<(), Error> {
|
||||
let f = |txn: &mut RwTxn<'a>| -> Result<(), Error> {
|
||||
let mut fixed: Vec<(PublicKey, HashMap<PersonList1, bool>)> = Vec::new();
|
||||
|
||||
// Collect records that require changing
|
||||
// (lmdb doesn't like changing them in place while iterating)
|
||||
for result in self.db_person_lists2()?.iter(txn)? {
|
||||
let (key, val) = result?;
|
||||
let pubkey = PublicKey::from_bytes(key, true)?;
|
||||
let mut map = HashMap::<PersonList1, bool>::read_from_buffer(val)?;
|
||||
if map.contains_key(&list) {
|
||||
map.remove(&list);
|
||||
fixed.push((pubkey, map));
|
||||
}
|
||||
}
|
||||
|
||||
// Change them
|
||||
for (pubkey, map) in fixed.drain(..) {
|
||||
let key: Vec<u8> = pubkey.to_bytes();
|
||||
if map.is_empty() {
|
||||
self.db_person_lists2()?.delete(txn, &key)?;
|
||||
} else {
|
||||
let bytes: Vec<u8> = map.write_to_vec()?;
|
||||
self.db_person_lists2()?.put(txn, &key, &bytes)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
};
|
||||
|
||||
match rw_txn {
|
||||
Some(txn) => f(txn)?,
|
||||
None => {
|
||||
let mut txn = self.env.write_txn()?;
|
||||
f(&mut txn)?;
|
||||
txn.commit()?;
|
||||
}
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
use speedy::{Readable, Writable};
|
||||
|
||||
/// Lists people can be added to
|
||||
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Readable, Writable)]
|
||||
#[repr(u8)]
|
||||
pub enum PersonList1 {
|
||||
Muted = 0,
|
||||
|
Loading…
Reference in New Issue
Block a user