blob: 91754b3d6b97fa05d4cf7fd616946c4a737121ac [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use {
crate::{
object_handle::{
GetProperties, ObjectHandle, ObjectProperties, ReadObjectHandle, WriteObjectHandle,
},
object_store::{
transaction::{
LockKey, LockManager, MetadataReservation, Options, ReadGuard, Transaction,
TransactionHandler, TransactionLocks, WriteGuard,
},
Timestamp,
},
},
anyhow::Error,
async_trait::async_trait,
std::{
cmp::min,
convert::TryInto,
sync::{Arc, Mutex},
vec::Vec,
},
storage_device::{
buffer::{Buffer, BufferRef, MutableBufferRef},
buffer_allocator::{BufferAllocator, MemBufferSource},
},
};
pub struct FakeObject {
buf: Mutex<Vec<u8>>,
lock_manager: LockManager,
}
impl FakeObject {
pub fn new() -> Self {
FakeObject { buf: Mutex::new(Vec::new()), lock_manager: LockManager::new() }
}
fn read(&self, offset: u64, mut buf: MutableBufferRef<'_>) -> Result<usize, Error> {
let our_buf = self.buf.lock().unwrap();
let to_do = min(buf.len(), our_buf.len() - offset as usize);
buf.as_mut_slice()[0..to_do]
.copy_from_slice(&our_buf[offset as usize..offset as usize + to_do]);
Ok(to_do)
}
fn write_or_append(&self, offset: Option<u64>, buf: BufferRef<'_>) -> Result<u64, Error> {
let mut our_buf = self.buf.lock().unwrap();
let offset = offset.unwrap_or(our_buf.len() as u64);
let required_len = offset as usize + buf.len();
if our_buf.len() < required_len {
our_buf.resize(required_len, 0);
}
our_buf[offset as usize..offset as usize + buf.len()].copy_from_slice(buf.as_slice());
Ok(our_buf.len() as u64)
}
fn truncate(&self, size: u64) {
self.buf.lock().unwrap().resize(size as usize, 0);
}
pub fn get_size(&self) -> u64 {
self.buf.lock().unwrap().len() as u64
}
}
#[async_trait]
impl TransactionHandler for FakeObject {
async fn new_transaction<'a>(
self: Arc<Self>,
locks: &[LockKey],
_options: Options<'a>,
) -> Result<Transaction<'a>, Error> {
Ok(Transaction::new(self, MetadataReservation::Borrowed, &[], locks).await)
}
async fn transaction_lock<'a>(&'a self, lock_keys: &[LockKey]) -> TransactionLocks<'a> {
let lock_manager: &LockManager = self.as_ref();
TransactionLocks(lock_manager.txn_lock(lock_keys).await)
}
async fn commit_transaction(
self: Arc<Self>,
transaction: &mut Transaction<'_>,
) -> Result<u64, Error> {
std::mem::take(&mut transaction.mutations);
Ok(0)
}
fn drop_transaction(&self, transaction: &mut Transaction<'_>) {
self.lock_manager.drop_transaction(transaction);
}
async fn read_lock<'a>(&'a self, lock_keys: &[LockKey]) -> ReadGuard<'a> {
self.lock_manager.read_lock(lock_keys).await
}
async fn write_lock<'a>(&'a self, lock_keys: &[LockKey]) -> WriteGuard<'a> {
self.lock_manager.write_lock(lock_keys).await
}
}
impl AsRef<LockManager> for FakeObject {
fn as_ref(&self) -> &LockManager {
&self.lock_manager
}
}
pub struct FakeObjectHandle {
object: Arc<FakeObject>,
allocator: BufferAllocator,
}
impl FakeObjectHandle {
pub fn new_with_block_size(object: Arc<FakeObject>, block_size: usize) -> Self {
let allocator =
BufferAllocator::new(block_size, Box::new(MemBufferSource::new(32 * 1024 * 1024)));
Self { object, allocator }
}
pub fn new(object: Arc<FakeObject>) -> Self {
Self::new_with_block_size(object, 512)
}
}
#[async_trait]
impl ObjectHandle for FakeObjectHandle {
fn object_id(&self) -> u64 {
0
}
fn block_size(&self) -> u64 {
self.allocator.block_size().try_into().unwrap()
}
fn get_size(&self) -> u64 {
self.object.get_size()
}
fn allocate_buffer(&self, size: usize) -> Buffer<'_> {
self.allocator.allocate_buffer(size)
}
}
#[async_trait]
impl GetProperties for FakeObjectHandle {
async fn get_properties(&self) -> Result<ObjectProperties, Error> {
let size = self.object.get_size();
Ok(ObjectProperties {
refs: 1u64,
allocated_size: size,
data_attribute_size: size,
creation_time: Timestamp::zero(),
modification_time: Timestamp::zero(),
sub_dirs: 0,
})
}
}
#[async_trait]
impl ReadObjectHandle for FakeObjectHandle {
async fn read(&self, offset: u64, buf: MutableBufferRef<'_>) -> Result<usize, Error> {
self.object.read(offset, buf)
}
}
#[async_trait]
impl WriteObjectHandle for FakeObjectHandle {
async fn write_or_append(&self, offset: Option<u64>, buf: BufferRef<'_>) -> Result<u64, Error> {
self.object.write_or_append(offset, buf)
}
async fn truncate(&self, size: u64) -> Result<(), Error> {
self.object.truncate(size);
Ok(())
}
async fn write_timestamps<'a>(
&'a self,
_crtime: Option<Timestamp>,
_mtime: Option<Timestamp>,
) -> Result<(), Error> {
Ok(())
}
async fn flush(&self) -> Result<(), Error> {
Ok(())
}
}