Skip to content

Commit

Permalink
add untyped reader/writer pair for MmapTable
Browse files Browse the repository at this point in the history
  • Loading branch information
xorpse committed May 16, 2024
1 parent f033ebe commit c605c36
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 16 deletions.
10 changes: 4 additions & 6 deletions fugue-core/src/project/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub struct ProjectRawViewMmaped {
}

pub struct ProjectRawViewMmapedReader<'a> {
backing: MmapTableReader<'a, U64<LE>, Vec<u8>>,
backing: MmapTableReader<'a, U64<LE>>,
ranges: &'a [Range<Address>],
}

Expand Down Expand Up @@ -82,9 +82,7 @@ impl ProjectRawView for ProjectRawViewMmaped {
let mut ranges = Vec::new();
let mut backing =
MmapTable::temporary("binary-view").map_err(ProjectRawViewError::backing)?;
let mut tx = backing
.writer::<Vec<u8>>()
.map_err(ProjectRawViewError::backing)?;
let mut tx = backing.writer().map_err(ProjectRawViewError::backing)?;

// Load the segments into the backing store (and keep track of the ranges)
//
Expand All @@ -100,7 +98,7 @@ impl ProjectRawView for ProjectRawViewMmaped {
// TODO: can we avoid owning the data--it seems needless for what we want to do with
// it here?
//
tx.set(addr, data.into_owned())
tx.set(addr, data.as_ref())
.map_err(ProjectRawViewError::backing)?;

ranges.push(addr..addr + size);
Expand Down Expand Up @@ -283,7 +281,7 @@ mod test {
let input = BytesOrMapping::from_file("tests/ls.elf")?;

// Create the project from the mapping object
let _prj = Project::<ProjectRawViewInMemory>::new(&Object::new(input)?)?;
let _prj = Project::<ProjectRawViewMmaped>::new(&Object::new(input)?)?;

Ok(())
}
Expand Down
125 changes: 115 additions & 10 deletions fugue-core/src/util/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub struct MmapTable<K> {
temporary: Option<TempDir>,
}

pub struct MmapTableReader<'a, K, T>
pub struct MmapTypedTableReader<'a, K, T>
where
T: Archive,
{
Expand All @@ -23,7 +23,7 @@ where
_marker: PhantomData<T>,
}

pub struct MmapTableWriter<'a, K, T>
pub struct MmapTypedTableWriter<'a, K, T>
where
T: Archive,
{
Expand All @@ -32,6 +32,16 @@ where
_marker: PhantomData<T>,
}

pub struct MmapTableReader<'a, K> {
table: &'a MmapTable<K>,
txn: RoTxn<'a>,
}

pub struct MmapTableWriter<'a, K> {
table: &'a MmapTable<K>,
txn: RwTxn<'a>,
}

#[derive(Debug, Error)]
pub enum MmapTableError {
#[error(transparent)]
Expand Down Expand Up @@ -102,38 +112,60 @@ where
Ok(slf)
}

pub fn reader<'a, T>(&'a self) -> Result<MmapTableReader<'a, K, T>, MmapTableError>
pub fn reader<'a>(&'a self) -> Result<MmapTableReader<'a, K>, MmapTableError> {
let txn = self
.environment
.read_txn()
.map_err(MmapTableError::database)?;

Ok(MmapTableReader { table: self, txn })
}

pub fn writer<'a>(&'a mut self) -> Result<MmapTableWriter<'a, K>, MmapTableError> {
let txn = self
.environment
.write_txn()
.map_err(MmapTableError::database)?;

Ok(MmapTableWriter { table: self, txn })
}

pub fn typed_reader<'a, T>(&'a self) -> Result<MmapTypedTableReader<'a, K, T>, MmapTableError>
where
T: Archive,
{
let txn = self
.environment
.read_txn()
.map_err(MmapTableError::database)?;
Ok(MmapTableReader {

Ok(MmapTypedTableReader {
table: self,
txn,
_marker: PhantomData,
})
}

pub fn writer<'a, T>(&'a mut self) -> Result<MmapTableWriter<'a, K, T>, MmapTableError>
pub fn typed_writer<'a, T>(
&'a mut self,
) -> Result<MmapTypedTableWriter<'a, K, T>, MmapTableError>
where
T: Archive,
{
let txn = self
.environment
.write_txn()
.map_err(MmapTableError::database)?;
Ok(MmapTableWriter {

Ok(MmapTypedTableWriter {
table: self,
txn,
_marker: PhantomData,
})
}
}

impl<'a, K, T> MmapTableReader<'a, K, T>
impl<'a, K, T> MmapTypedTableReader<'a, K, T>
where
T: Archive,
{
Expand All @@ -152,7 +184,20 @@ where
}
}

impl<'a, K, T> MmapTableWriter<'a, K, T>
impl<'a, K> MmapTableReader<'a, K> {
pub fn get<KE>(&self, key: impl AsRef<KE>) -> Result<Option<&[u8]>, MmapTableError>
where
K: for<'b> BytesEncode<'b, EItem = KE>,
KE: ?Sized + 'static,
{
self.table
.database
.get(&self.txn, key.as_ref())
.map_err(MmapTableError::database)
}
}

impl<'a, K, T> MmapTypedTableWriter<'a, K, T>
where
T: Archive + Serialize<AllocSerializer<1024>>,
{
Expand Down Expand Up @@ -216,6 +261,66 @@ where
}
}

impl<'a, K> MmapTableWriter<'a, K> {
pub fn get<KE>(&self, key: impl AsRef<KE>) -> Result<Option<&[u8]>, MmapTableError>
where
K: for<'b> BytesEncode<'b, EItem = KE>,
KE: ?Sized + 'static,
{
self.table
.database
.get(&self.txn, key.as_ref())
.map_err(MmapTableError::database)
}

pub fn set<KE>(
&mut self,
key: impl AsRef<KE>,
val: impl AsRef<[u8]>,
) -> Result<(), MmapTableError>
where
K: for<'b> BytesEncode<'b, EItem = KE>,
KE: ?Sized + 'static,
{
self.table
.database
.put(&mut self.txn, key.as_ref(), val.as_ref())
.map_err(MmapTableError::database)?;

Ok(())
}

pub fn clear(&mut self) -> Result<(), MmapTableError> {
self.table
.database
.clear(&mut self.txn)
.map_err(MmapTableError::database)?;

Ok(())
}

pub fn remove<KE>(&mut self, key: impl AsRef<KE>) -> Result<(), MmapTableError>
where
K: for<'b> BytesEncode<'b, EItem = KE>,
KE: ?Sized + 'static,
{
self.table
.database
.delete(&mut self.txn, key.as_ref())
.map_err(MmapTableError::database)?;

Ok(())
}

pub fn abort(self) {
self.txn.abort()
}

pub fn commit(self) -> Result<(), MmapTableError> {
self.txn.commit().map_err(MmapTableError::database)
}
}

#[cfg(test)]
mod test {
use heed::types::Str;
Expand All @@ -227,7 +332,7 @@ mod test {
let mut pt = MmapTable::<Str>::temporary("project")?;

{
let mut writer = pt.writer::<Vec<u8>>()?;
let mut writer = pt.writer()?;

writer.set("mapping1", vec![0u8; 10])?;
writer.set("mapping2", vec![0u8; 100 * 1024 * 1024])?;
Expand All @@ -237,7 +342,7 @@ mod test {
}

{
let reader = pt.reader::<Vec<u8>>()?;
let reader = pt.reader()?;

let bytes = reader.get("mapping2")?.unwrap();

Expand Down
12 changes: 12 additions & 0 deletions fugue-ir/src/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,18 @@ impl Address {
}
}

impl AsRef<Address> for Address {
fn as_ref(&self) -> &Address {
self
}
}

impl AsRef<u64> for Address {
fn as_ref(&self) -> &u64 {
&self.0
}
}

impl PartialEq<u8> for Address {
fn eq(&self, other: &u8) -> bool {
self.0 == *other as u64
Expand Down

0 comments on commit c605c36

Please sign in to comment.