Skip to content
This repository has been archived by the owner on Nov 8, 2023. It is now read-only.

Commit

Permalink
change file position after read/write
Browse files Browse the repository at this point in the history
  • Loading branch information
burmecia committed Apr 24, 2018
1 parent 35abd2b commit 6f40396
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 26 deletions.
46 changes: 36 additions & 10 deletions src/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ impl<'a> Seek for VersionReader<'a> {
/// ```
/// # use zbox::{init_env, Result, RepoOpener};
/// use std::io::prelude::*;
/// use std::io::{Seek, SeekFrom};
/// # use zbox::OpenOptions;
///
/// # fn foo() -> Result<()> {
Expand All @@ -137,6 +138,7 @@ impl<'a> Seek for VersionReader<'a> {
/// file.finish()?;
///
/// let mut content = String::new();
/// file.seek(SeekFrom::Start(0))?;
/// file.read_to_string(&mut content)?;
/// assert_eq!(content, "foo bar");
///
Expand All @@ -154,7 +156,7 @@ impl<'a> Seek for VersionReader<'a> {
/// ```
/// # #![allow(unused_mut, unused_variables)]
/// # use zbox::{init_env, Result, RepoOpener};
/// use std::io::Read;
/// use std::io::{Read, Seek, SeekFrom};
/// # use zbox::OpenOptions;
///
/// # fn foo() -> Result<()> {
Expand All @@ -166,6 +168,7 @@ impl<'a> Seek for VersionReader<'a> {
/// file.write_once(b"foo bar")?;
///
/// let mut content = String::new();
/// file.seek(SeekFrom::Start(0))?;
/// file.read_to_string(&mut content)?;
/// assert_eq!(content, "foo bar");
///
Expand Down Expand Up @@ -208,7 +211,7 @@ impl<'a> Seek for VersionReader<'a> {
/// let mut rdr = file.version_reader(curr_ver)?;
/// let mut content = String::new();
/// rdr.read_to_string(&mut content)?;
/// assert_eq!(content, "bar");
/// assert_eq!(content, "foobar");
///
/// let mut rdr = file.version_reader(curr_ver - 1)?;
/// let mut content = String::new();
Expand All @@ -225,6 +228,7 @@ impl<'a> Seek for VersionReader<'a> {
///
/// ```
/// use std::io::prelude::*;
/// use std::io::{Seek, SeekFrom};
/// # use zbox::{init_env, Result, RepoOpener};
/// # use zbox::OpenOptions;
///
Expand All @@ -235,15 +239,16 @@ impl<'a> Seek for VersionReader<'a> {
/// file.write_once(&[1, 2, 3, 4])?;
///
/// let mut buf = [0; 2];
/// file.seek(SeekFrom::Start(0))?;
/// file.read_exact(&mut buf)?;
/// assert_eq!(&buf[..], &[1, 2]);
///
/// // create a new version
/// file.write_once(&[5, 6, 7])?;
/// // file.write_once(&[5, 6, 7])?;
///
/// // notice this read still continues on previous version
/// file.read_exact(&mut buf)?;
/// assert_eq!(&buf[..], &[3, 4]);
/// // file.read_exact(&mut buf)?;
/// // assert_eq!(&buf[..], &[3, 4]);
///
/// # Ok(())
/// # }
Expand Down Expand Up @@ -410,12 +415,16 @@ impl File {
match self.wtr.take() {
Some(wtr) => {
let tx_handle = self.tx_handle.take().unwrap();
let mut end_pos = 0;

tx_handle.run(|| wtr.finish())?;
tx_handle.run(|| {
end_pos = wtr.finish()?;
Ok(())
})?;
tx_handle.commit()?;

// reset position
self.pos = SeekFrom::Start(0);
// set position
self.pos = SeekFrom::Start(end_pos as u64);

Ok(())
}
Expand Down Expand Up @@ -492,15 +501,32 @@ impl Read for File {
Error::CannotRead.description(),
));
}
if self.rdr.is_none() {

let has_new_ver = match self.rdr {
Some(ref rdr) => {
let fnode = self.handle.fnode.read().unwrap();
fnode.curr_ver_num() > rdr.ver()
}
None => false,
};

// if reader is not created yet or there is a new version,
// create a new reader and seek to current file position
if self.rdr.is_none() || has_new_ver {
let mut rdr = map_io_err!(FnodeReader::new_current(
self.handle.fnode.clone()
))?;
rdr.seek(self.pos)?;
self.rdr = Some(rdr);
}

match self.rdr {
Some(ref mut rdr) => rdr.read(buf),
Some(ref mut rdr) => {
let read = rdr.read(buf)?;
let new_pos = rdr.seek(SeekFrom::Current(0)).unwrap();
self.pos = SeekFrom::Start(new_pos);
Ok(read)
}
None => unreachable!(),
}
}
Expand Down
17 changes: 12 additions & 5 deletions src/fs/fnode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -678,22 +678,29 @@ pub type FnodeWeakRef = CowWeakRef<Fnode>;
/// Fnode Reader
#[derive(Debug)]
pub struct Reader {
ver: usize,
rdr: ContentReader,
}

impl Reader {
#[inline]
pub fn ver(&self) -> usize {
self.ver
}

/// Create a reader for specified version
pub fn new(fnode: FnodeRef, ver: usize) -> Result<Self> {
let fnode = fnode.read().unwrap();
let rdr = fnode.version_reader(ver)?;
Ok(Reader { rdr })
Ok(Reader { ver, rdr })
}

/// Create a reader for current version
pub fn new_current(fnode: FnodeRef) -> Result<Self> {
let fnode = fnode.read().unwrap();
let rdr = fnode.version_reader(fnode.curr_ver_num())?;
Ok(Reader { rdr })
let ver = fnode.curr_ver_num();
let rdr = fnode.version_reader(ver)?;
Ok(Reader { ver, rdr })
}
}

Expand Down Expand Up @@ -727,7 +734,7 @@ impl Writer {
Ok(Writer { inner, handle })
}

pub fn finish(self) -> Result<()> {
pub fn finish(self) -> Result<usize> {
let stg_ctn = self.inner.finish()?;
let handle = &self.handle;

Expand All @@ -747,7 +754,7 @@ impl Writer {
Content::unlink(&ctn, &mut fnode.chk_map, &handle.store)?;
}

Ok(())
Ok(stg_ctn.end_offset())
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/fs/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,8 @@ impl Fs {
let mut rdr = FnodeReader::new_current(src.fnode.clone())?;
let mut wtr = FnodeWriter::new(tgt.clone(), tx_handle.txid)?;
io::copy(&mut rdr, &mut wtr)?;
wtr.finish()
wtr.finish()?;
Ok(())
})?;

Ok(())
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
//! ```
//! # use zbox::{init_env, RepoOpener};
//! use std::io::prelude::*;
//! use std::io::{Seek, SeekFrom};
//! use zbox::OpenOptions;
//! # init_env();
//! # let mut repo = RepoOpener::new()
Expand All @@ -61,6 +62,7 @@
//!
//! // read file content using std::io::Read trait
//! let mut content = String::new();
//! file.seek(SeekFrom::Start(0)).unwrap();
//! file.read_to_string(&mut content).unwrap();
//! assert_eq!(content, "Hello, world!");
//! ```
Expand Down
5 changes: 5 additions & 0 deletions tests/ffi.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,11 +188,16 @@ int test_file() {
// read
uint8_t dst[3] = { 0 };
ret = zbox_file_read(dst, 3, file);
assert(ret == 0);
ret = zbox_file_seek(file, 0, SEEK_SET);
assert(ret == 0);
ret = zbox_file_read(dst, 3, file);
assert(ret == 3);
assert(!memcmp(dst, buf, 3));

// write once
buf[0] = 4; buf[1] = 5; buf[2] = 6;
assert(zbox_file_seek(file, 0, SEEK_SET) == 0);
ret = zbox_file_write_once(file, buf, 3);
assert(!ret);

Expand Down
50 changes: 40 additions & 10 deletions tests/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ fn file_read_write() {

let buf = [1u8, 2u8, 3u8];
let buf2 = [4u8, 5u8, 6u8, 7u8, 8u8];
let mut buf3 = Vec::new();
buf3.extend_from_slice(&buf);
buf3.extend_from_slice(&buf2);

// #1, create and write a new file
{
Expand Down Expand Up @@ -203,13 +206,12 @@ fn file_read_write() {
.unwrap();

f.write_once(&buf[..]).unwrap();

f.write_once(&buf2[..]).unwrap();

verify_content(&mut f, &buf2);
verify_content(&mut f, &buf3);

let meta = f.metadata().unwrap();
assert_eq!(meta.len(), buf2.len());
assert_eq!(meta.len(), buf3.len());
assert_eq!(f.history().unwrap().len(), 1);
}

Expand All @@ -222,22 +224,21 @@ fn file_read_write() {
.unwrap();

f.write_once(&buf[..]).unwrap();

f.write_once(&buf2[..]).unwrap();

verify_content(&mut f, &buf2);
verify_content(&mut f, &buf3);

let meta = f.metadata().unwrap();
let history = f.history().unwrap();
assert_eq!(meta.len(), buf2.len());
assert_eq!(meta.len(), buf3.len());
assert_eq!(history.len(), 2);

let ver_num = history.last().unwrap().num();
let mut rdr = f.version_reader(ver_num).unwrap();
let mut dst = Vec::new();
let result = rdr.read_to_end(&mut dst).unwrap();
assert_eq!(result, buf2.len());
assert_eq!(&dst[..], &buf2[..]);
assert_eq!(result, buf3.len());
assert_eq!(&dst[..], &buf3[..]);

let mut rdr = f.version_reader(ver_num - 1).unwrap();
let mut dst = Vec::new();
Expand All @@ -261,7 +262,7 @@ fn file_read_write() {
let mut rdr = f.version_reader(curr_ver).unwrap();
let mut dst = Vec::new();
rdr.read_to_end(&mut dst).unwrap();
assert_eq!(&dst[..], &buf2[..]);
assert_eq!(&dst[..], &buf3[..]);

let mut rdr = f.version_reader(curr_ver - 1).unwrap();
let mut dst = Vec::new();
Expand Down Expand Up @@ -301,8 +302,11 @@ fn file_read_write() {
verify_content(&mut f, &buf[..]);
f.set_len(1).unwrap();
verify_content(&mut f, &buf[..1]);

// note here file position is 3 which is beyond EOF,
// the file is extended with zero and then write with data
f.write_once(&buf[..]).unwrap();
verify_content(&mut f, &buf[..]);
verify_content(&mut f, &[1, 0, 0, 1, 2, 3]);
}

// #15, test create open flag
Expand All @@ -324,6 +328,30 @@ fn file_read_write() {
.open(&mut repo, "/file9")
.unwrap();
}

// #16, read while file is in writing
{
let mut f = OpenOptions::new()
.create(true)
.open(&mut repo, "/file16")
.unwrap();
f.write_once(&[0, 1, 2, 3, 4, 5, 6]).unwrap();

f.seek(SeekFrom::Start(1)).unwrap();
f.write_once(&[20, 21]).unwrap();

// now the file position is 3
let mut buf = [0u8; 1];
f.read_exact(&mut buf).unwrap();
assert_eq!(&buf[..], &[3]);

// create a new version and continue read
f.write_once(&[30, 31]).unwrap();
f.read_exact(&mut buf).unwrap();
assert_eq!(&buf[..], &[6]);

verify_content(&mut f, &[0, 20, 21, 3, 30, 31, 6]);
}
}

#[test]
Expand Down Expand Up @@ -620,6 +648,7 @@ fn file_seek() {

// verify
let mut dst = Vec::new();
f.seek(SeekFrom::Start(0)).unwrap();
let result = f.read_to_end(&mut dst).unwrap();
assert_eq!(result, buf.len() + 1);
assert_eq!(&dst[..], &[1, 1, 2, 3]);
Expand Down Expand Up @@ -649,6 +678,7 @@ fn file_seek() {

// verify
let mut dst = Vec::new();
f.seek(SeekFrom::Start(0)).unwrap();
let result = f.read_to_end(&mut dst).unwrap();
assert_eq!(result, buf.len() * 2 + 1);
assert_eq!(&dst[..], &[1, 2, 3, 0, 1, 2, 3]);
Expand Down

0 comments on commit 6f40396

Please sign in to comment.