From b322061c4597f206068ced207c78a9d89d0846e7 Mon Sep 17 00:00:00 2001 From: Michael Vlach Date: Tue, 6 Sep 2022 20:11:50 +0200 Subject: [PATCH] [storage] Add resize_value() to Storage #156 (#157) * Update file_storage.rs * Update storage.rs * Update pr.yaml --- .github/workflows/pr.yaml | 2 +- src/storage.rs | 16 +++++++++ src/storage/file_storage.rs | 72 +++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 073b300f..df58aa67 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -44,7 +44,7 @@ jobs: - uses: actions/checkout@v3 - uses: taiki-e/install-action@cargo-llvm-cov - run: rustup component add llvm-tools-preview - - run: cargo llvm-cov --fail-uncovered-regions 81 --fail-uncovered-functions 0 --fail-uncovered-lines 0 + - run: cargo llvm-cov --fail-uncovered-regions 83 --fail-uncovered-functions 0 --fail-uncovered-lines 0 test: runs-on: ubuntu-latest diff --git a/src/storage.rs b/src/storage.rs index 087bfe59..6d656589 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -57,6 +57,22 @@ pub(crate) trait Storage: StorageImpl { self.commit() } + fn resize_value(&mut self, index: i64, new_size: u64) -> Result<(), DbError> { + if new_size == 0 { + return Err(DbError::Storage("value size cannot be 0".to_string())); + } + + let mut record = self.record(index)?; + + if record.size != new_size { + self.transaction(); + self.move_record_to_end(index, new_size, new_size, &mut record)?; + self.commit()?; + } + + Ok(()) + } + fn shrink_to_fit(&mut self) -> Result<(), DbError> { self.transaction(); let indexes = self.indexes_by_position(); diff --git a/src/storage/file_storage.rs b/src/storage/file_storage.rs index 0c37de9c..c869b4bd 100644 --- a/src/storage/file_storage.rs +++ b/src/storage/file_storage.rs @@ -252,6 +252,78 @@ mod tests { ); } + #[test] + fn resize_value_greater() { + let test_file = TestFile::from("./file_storage-resize_value_greater.agdb"); + let mut storage = FileStorage::try_from(test_file.file_name().clone()).unwrap(); + + let index = storage.insert(&10_i64).unwrap(); + let expected_size = std::mem::size_of::() as u64; + + assert_eq!(storage.value_size(index), Ok(expected_size)); + + storage.resize_value(index, expected_size * 2).unwrap(); + + assert_eq!(storage.value_size(index), Ok(expected_size * 2)); + } + + #[test] + fn resize_value_missing_index() { + let test_file = TestFile::from("./file_storage-resize_value_missing_index.agdb"); + let mut storage = FileStorage::try_from(test_file.file_name().clone()).unwrap(); + + assert_eq!( + storage.resize_value(1, 1), + Err(DbError::Storage("index '1' not found".to_string())) + ); + } + + #[test] + fn resize_value_same() { + let test_file = TestFile::from("./file_storage-resize_value_same.agdb"); + let mut storage = FileStorage::try_from(test_file.file_name().clone()).unwrap(); + + let index = storage.insert(&10_i64).unwrap(); + let expected_size = std::mem::size_of::() as u64; + + assert_eq!(storage.value_size(index), Ok(expected_size)); + + storage.resize_value(index, expected_size).unwrap(); + + assert_eq!(storage.value_size(index), Ok(expected_size)); + } + + #[test] + fn resize_value_smaller() { + let test_file = TestFile::from("./file_storage-resize_value_smaller.agdb"); + let mut storage = FileStorage::try_from(test_file.file_name().clone()).unwrap(); + + let index = storage.insert(&10_i64).unwrap(); + let expected_size = std::mem::size_of::() as u64; + + assert_eq!(storage.value_size(index), Ok(expected_size)); + + storage.resize_value(index, expected_size / 2).unwrap(); + + assert_eq!(storage.value_size(index), Ok(expected_size / 2)); + } + + #[test] + fn resize_value_zero() { + let test_file = TestFile::from("./file_storage-resize_value_zero.agdb"); + let mut storage = FileStorage::try_from(test_file.file_name().clone()).unwrap(); + + let index = storage.insert(&10_i64).unwrap(); + let expected_size = std::mem::size_of::() as u64; + + assert_eq!(storage.value_size(index), Ok(expected_size)); + + assert_eq!( + storage.resize_value(index, 0), + Err(DbError::Storage("value size cannot be 0".to_string())) + ); + } + #[test] fn restore_from_open_file() { let test_file = TestFile::from("./file_storage-restore_from_open_file.agdb");