Releases: khonsulabs/nebari
v0.5.5
v0.5.4
Fixed
log::State::current_transaction_id()now behaves as documented. Previously,
it was returning the last transaction ID that the log file had allocated, but
the transaction ID returned may not have been committed. Now the ID returned
is guaranteed to be the last ID written to the log.
v0.5.3
Fixed
-
File operations are now fully persisted to disk to the best ability provided
by each operating system. @justinj discovered that nofsync()operations
were happening, and reported the finding. Nebari's TreeFile was usingFile::flush()instead ofFile::sync_data()/sync_all(). This means that it
would be possible for an OS-level buffer to not be flushed to disk before
Nebari reported a successful write.Interestingly, this change has no noticable impact on performance on Linux.
However, on Mac OS,File::sync_data()performs afcntlwithF_FULLFSYNC,
which has a significant impact on performance. This is the correct behavior,
however, as without this level of guarantee, sudden power loss could result in
data loss.Many people argue that using
F_BARRIERFSYNCis sufficient for most people,
but Apple's own documentation states this is
necessary:Only use F_FULLFSYNC when your app requires a strong expectation of data
persistence. Note that F_FULLFSYNC represents a best-effort guarantee that
iOS writes data to the disk, but data can still be lost in the case of
sudden power loss.For now, the stance of Nebari's authors is that
F_FULLFSYNCis the proper
way to implement true ACID-compliance.
v0.5.2
Fixed
-
Another edge case similar to the one found in v0.5.1 was discovered through
newly implemented fuzzer-based testing. When a node is fully absorbed to the
bottom of the next, in some cases, the modification iterator would not back up
to reconsider the node. When inserting a new key in this situation, if the new
key was greater than the lowest key in the next node, the tree would get out
of order.The exact circumstances of this bug are similarly as rare as described in
v0.5.1's entry.
Added
-
Feature
paranoidenables extra sanity checks. This feature flag was added
for purposes of fuzzing. It enables extra sanity checks in release builds that
are always present in debug builds. These sanity checks are useful in catching
bugs, but they represent that a database would be corrupted if the state was
persisted to disk.These checks slow down modifications to the database significantly.
v0.5.1
Fixed
-
modify()operations on larger trees (> 50k entries) that performed multiple
modification operations could trigger a debug_assert in debug builds, or
worse, yield incorrect databases in release builds.The offending situations occur with edge cases surrounding "absorbing" nodes
to rebalance trees as entries are deleted. This particular edge case only
arose when the absorb phase moved entries in both directions and performed
subsequent operations before the next save to disk occurred.This bug should only have been able to be experienced if you were using large
modify()operations that did many deletions as well as insertions, and even
then, only in certain circumstances.
v0.5.0
Breaking Changes
-
KeyEvaluationhas been renamed toScanEvaluation. -
All
scan()functions have been updated with thenode_evaluatorcallback
now returns aScanEvaluationinstead of abool. To preserve existing
behavior, returnScanEvaluation::ReadDatainstead of true andScanEvaluation::Stopinstead of false.The new functionality unlocked with this change is that scan operations can
now be directed as to whether to skip navigating into an interior node. The
newreduce()function uses this ability to skip scanning nodes when an
already reduced value is available on a node.
Added
TreeFile::reduce(),Tree::reduce(),TransactionTree::reduce()have been
added as a way to return aggregated information stored within the nodes. A
practical use case is the ability to retrieve the number of alive/deleted keys
over a given range, but this functionality extends to embedded indexes through
the existingReducertrait.
v0.4.0
Breaking Changes
-
get_multiplehas been changed to accept an Iterator over borrowed byte slices. -
ExecutingTransaction::treenow returns aLockedTransactionTree, which
holds a shared reference to the transaction now. Previouslytree()required
an exclusive reference to the transaction, preventing consumers of Nebari from
using multiple threads to process more complicated transactions.This API is paired by a new addition:
ExecutingTransaction::unlocked_tree.
This API returns anUnlockedTransactionTreewhich can be sent across thread
boundaries safely. It offers alock()function to return aLockedTransactionTreewhen the tread is ready to operate on the tree. -
TransactionManager::pushhas been made private. This is a result of the
previous breaking change.TransactionManager::new_transaction()is a new
function that returns aManagedTransaction.ManagedTransaction::commit()
is the new way to commit a transaction in a transaction manager.
Fixed
TransactionManagernow enforces that transaction log entries are written
sequentially. The ACID-compliance of Nebari was never broken when
non-sequential log entries are written, but scanning the log file could fail
to retrieve items as the scanning algorithm expects the file to be ordered
sequentially.
Added
ThreadPool::new(usize)allows creating a thread pool with a maximum number
of threads set.ThreadPool::default()continues to usenum_cpus::getto
configure this value automatically.
v0.3.2
Fixed
- Fixed potential infinite loop when scanning for a transaction ID that does not
exist. - Reading associated transaction log data now works when the data is larger than
the page size. Previously, the data returned included the extra bytes that the
transaction log inserts at page boundaries.
v0.3.1
Changed
BorrowedRangenow exposes its fields as public. Without this, there was no
way to implementBorrowByteRangeoutside of this crate.- This crate now explicitly states its minimum supported Rust version (MSRV).
The MSRV did not change as part of this update. It previously was not
documented.
v0.3.0
Breaking Changes
ManagedFilehas had its metadata functions moved to a new traitFilewhichManagedFilemust be an implementor of. This allowsdyn Fileto be used
internally. As a result,PagedWriterno longer takes a file type generic
parameter.ManagedFilehas had its functionsopen_for_readandopen_for_appendhave
been moved to a new trait,ManagedFileOpener.FileManager::replace_withnow takes the replacement file itself instead of
the file's Path.compare_and_swaphas had theoldparameter loosened to&[u8], avoiding
an extra allocation.TreeFile::push()has been renamedTreeFile::set()and now accepts any type
that can convert to `ArcBytes<'static>.
Added
AnyFileManagerhas been added to make it easy to select between memory or
standard files at runtime.Tree::first[_key](),TransactionTree::first[_key](), andTreeFile::first[_key]()have been added, pairing the functionality provided
bylast()andlast_key().