hrev48060 adds 5 changesets to branch 'master' old head: 33d9fb8663e384b7ad8edb015eac2b2ee88c2d3b new head: 24e159e1acd96ac16289038950cc0d52c0d64de2 overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=24e159e+%5E33d9fb8 ---------------------------------------------------------------------------- 4101aae: libkernelland_emu: Remove deleted scheduler.cpp from build. The file was removed in hrev47484, but the Jamfile wasn't updated. 893367c: libkernelland_emu: Sync _rw_lock_{read|write}_unlock API. The threadsLocked parameter was removed from the kernel API. 04ed610: libkernelland_emu: Fix missing using namespace std for GCC4. 9656eef: libkernelland_emu: Fix wrong return in ModuleList::AddModule(). 24e159e: btreeTest: Revive test for BPlusTree implementation. * Update pseudo cache with minimal set of block cache API. * Update Inode, Journal and Volume stubs to current API. * Add stubs for remaining VFS functions. * Extend tests to also call BPlusTree::Validate() and bail on errors. * Change duplicate tests to fill in the same value. While this isn't strictly allowed, the tree validation can't work unless the values match up. * Lots of coding style cleanup, but much more should still be done... The tests run through without errors. [ Michael Lotz <mmlr@xxxxxxxx> ] ---------------------------------------------------------------------------- 13 files changed, 332 insertions(+), 101 deletions(-) .../kernel/file_systems/bfs/btree/Inode.cpp | 7 +- .../kernel/file_systems/bfs/btree/Inode.h | 65 +++++++--- .../kernel/file_systems/bfs/btree/Jamfile | 13 +- .../kernel/file_systems/bfs/btree/Journal.h | 67 ++++++++-- .../kernel/file_systems/bfs/btree/Volume.cpp | 7 ++ .../kernel/file_systems/bfs/btree/Volume.h | 16 ++- .../kernel/file_systems/bfs/btree/cache.cpp | 125 ++++++++++++++----- .../kernel/file_systems/bfs/btree/cache.h | 23 +++- .../kernel/file_systems/bfs/btree/stubs.cpp | 15 +++ .../kernel/file_systems/bfs/btree/test.cpp | 62 +++++---- src/tests/add-ons/kernel/kernelland_emu/Jamfile | 1 - src/tests/add-ons/kernel/kernelland_emu/lock.cpp | 27 +++- .../add-ons/kernel/kernelland_emu/module.cpp | 5 +- ############################################################################ Commit: 4101aaedc72b496b08363e7165f1a106b052b7e5 URL: http://cgit.haiku-os.org/haiku/commit/?id=4101aae Author: Michael Lotz <mmlr@xxxxxxxx> Date: Mon Oct 20 22:00:54 2014 UTC libkernelland_emu: Remove deleted scheduler.cpp from build. The file was removed in hrev47484, but the Jamfile wasn't updated. ---------------------------------------------------------------------------- diff --git a/src/tests/add-ons/kernel/kernelland_emu/Jamfile b/src/tests/add-ons/kernel/kernelland_emu/Jamfile index ab75e0b..761394b 100644 --- a/src/tests/add-ons/kernel/kernelland_emu/Jamfile +++ b/src/tests/add-ons/kernel/kernelland_emu/Jamfile @@ -11,7 +11,6 @@ SharedLibrary libkernelland_emu.so : low_resource_manager.cpp misc.cpp module.cpp - scheduler.cpp slab.cpp smp.cpp vm.cpp ############################################################################ Commit: 893367cf3096e3344bf5d1bc27f4037628eed2a3 URL: http://cgit.haiku-os.org/haiku/commit/?id=893367c Author: Michael Lotz <mmlr@xxxxxxxx> Date: Mon Oct 20 22:04:24 2014 UTC libkernelland_emu: Sync _rw_lock_{read|write}_unlock API. The threadsLocked parameter was removed from the kernel API. ---------------------------------------------------------------------------- diff --git a/src/tests/add-ons/kernel/kernelland_emu/lock.cpp b/src/tests/add-ons/kernel/kernelland_emu/lock.cpp index 84efe8b..2d860ab 100644 --- a/src/tests/add-ons/kernel/kernelland_emu/lock.cpp +++ b/src/tests/add-ons/kernel/kernelland_emu/lock.cpp @@ -43,6 +43,9 @@ struct rw_lock_waiter { #define RW_LOCK_FLAG_OWNS_NAME RW_LOCK_FLAG_CLONE_NAME +static void _rw_lock_read_unlock_threads_locked(rw_lock* lock); +static void _rw_lock_write_unlock_threads_locked(rw_lock* lock); + static status_t _mutex_lock_threads_locked(mutex* lock); static void _mutex_unlock_threads_locked(mutex* lock); @@ -456,10 +459,16 @@ _rw_lock_read_lock_with_timeout(rw_lock* lock, uint32 timeoutFlags, void -_rw_lock_read_unlock(rw_lock* lock, bool threadsLocked) +_rw_lock_read_unlock(rw_lock* lock) { - AutoLocker<ThreadSpinlock> locker(sThreadSpinlock, false, !threadsLocked); + AutoLocker<ThreadSpinlock> locker(sThreadSpinlock); + _rw_lock_read_unlock_threads_locked(lock); +} + +static void +_rw_lock_read_unlock_threads_locked(rw_lock* lock) +{ // If we're still holding the write lock or if there are other readers, // no-one can be woken up. if (lock->holder == find_thread(NULL)) { @@ -521,10 +530,16 @@ rw_lock_write_lock(rw_lock* lock) void -_rw_lock_write_unlock(rw_lock* lock, bool threadsLocked) +_rw_lock_write_unlock(rw_lock* lock) { - AutoLocker<ThreadSpinlock> locker(sThreadSpinlock, false, !threadsLocked); + AutoLocker<ThreadSpinlock> locker(sThreadSpinlock); + _rw_lock_write_unlock_threads_locked(lock); +} + +static void +_rw_lock_write_unlock_threads_locked(rw_lock* lock) +{ if (find_thread(NULL) != lock->holder) { panic("rw_lock_write_unlock(): lock %p not write-locked by this thread", lock); @@ -650,11 +665,11 @@ mutex_switch_from_read_lock(rw_lock* from, mutex* to) AutoLocker<ThreadSpinlock> locker(sThreadSpinlock); #if KDEBUG_RW_LOCK_DEBUG - _rw_lock_write_unlock(from, true); + _rw_lock_write_unlock_threads_locked(from); #else int32 oldCount = atomic_add(&from->count, -1); if (oldCount >= RW_LOCK_WRITER_COUNT_BASE) - _rw_lock_read_unlock(from, true); + _rw_lock_read_unlock_threads_locked(from); #endif return _mutex_lock_threads_locked(to); ############################################################################ Commit: 04ed6105f182c761c9f4827b60eab0a5c153f961 URL: http://cgit.haiku-os.org/haiku/commit/?id=04ed610 Author: Michael Lotz <mmlr@xxxxxxxx> Date: Mon Oct 20 22:07:16 2014 UTC libkernelland_emu: Fix missing using namespace std for GCC4. ---------------------------------------------------------------------------- diff --git a/src/tests/add-ons/kernel/kernelland_emu/module.cpp b/src/tests/add-ons/kernel/kernelland_emu/module.cpp index 5d4b65f..ef6598e 100644 --- a/src/tests/add-ons/kernel/kernelland_emu/module.cpp +++ b/src/tests/add-ons/kernel/kernelland_emu/module.cpp @@ -29,6 +29,9 @@ //#define TRACE(x) printf x +using namespace std; + + static const char *gModuleDirs[] = { "generated/objects/haiku/x86/release/add-ons/userland", "generated/objects/haiku/x86/release/tests/add-ons/kernel", ############################################################################ Commit: 9656eef895f29132538a63a2dfdf9d76e655c537 URL: http://cgit.haiku-os.org/haiku/commit/?id=9656eef Author: Michael Lotz <mmlr@xxxxxxxx> Date: Mon Oct 20 22:08:48 2014 UTC libkernelland_emu: Fix wrong return in ModuleList::AddModule(). ---------------------------------------------------------------------------- diff --git a/src/tests/add-ons/kernel/kernelland_emu/module.cpp b/src/tests/add-ons/kernel/kernelland_emu/module.cpp index ef6598e..7f5e27c 100644 --- a/src/tests/add-ons/kernel/kernelland_emu/module.cpp +++ b/src/tests/add-ons/kernel/kernelland_emu/module.cpp @@ -364,7 +364,7 @@ ModuleList::AddModule(Module *module) bool result = false; if (module && !FindModule(module->Info()->name)) result = fModules.AddItem(module); - return module; + return result; } // RemoveModule ############################################################################ Revision: hrev48060 Commit: 24e159e1acd96ac16289038950cc0d52c0d64de2 URL: http://cgit.haiku-os.org/haiku/commit/?id=24e159e Author: Michael Lotz <mmlr@xxxxxxxx> Date: Mon Oct 20 22:11:23 2014 UTC btreeTest: Revive test for BPlusTree implementation. * Update pseudo cache with minimal set of block cache API. * Update Inode, Journal and Volume stubs to current API. * Add stubs for remaining VFS functions. * Extend tests to also call BPlusTree::Validate() and bail on errors. * Change duplicate tests to fill in the same value. While this isn't strictly allowed, the tree validation can't work unless the values match up. * Lots of coding style cleanup, but much more should still be done... The tests run through without errors. ---------------------------------------------------------------------------- diff --git a/src/tests/add-ons/kernel/file_systems/bfs/btree/Inode.cpp b/src/tests/add-ons/kernel/file_systems/bfs/btree/Inode.cpp index 2d38e76..61ed6a1 100644 --- a/src/tests/add-ons/kernel/file_systems/bfs/btree/Inode.cpp +++ b/src/tests/add-ons/kernel/file_systems/bfs/btree/Inode.cpp @@ -14,6 +14,7 @@ Inode::Inode(const char *name,int32 mode) : fMode(mode) { + rw_lock_init(&fLock, "inode lock"); fFile.SetTo(name,B_CREATE_FILE | B_READ_WRITE | B_ERASE_FILE); fSize = 0; fVolume = new Volume(&fFile); @@ -37,14 +38,14 @@ Inode::FindBlockRun(off_t pos, block_run &run, off_t &offset) status_t -Inode::Append(Transaction *transaction, off_t bytes) +Inode::Append(Transaction& transaction, off_t bytes) { - return SetFileSize(transaction,Size() + bytes); + return SetFileSize(transaction, Size() + bytes); } status_t -Inode::SetFileSize(Transaction *, off_t bytes) +Inode::SetFileSize(Transaction&, off_t bytes) { //printf("set size = %ld\n",bytes); fSize = bytes; diff --git a/src/tests/add-ons/kernel/file_systems/bfs/btree/Inode.h b/src/tests/add-ons/kernel/file_systems/bfs/btree/Inode.h index 4b1f5b7..c74153c 100644 --- a/src/tests/add-ons/kernel/file_systems/bfs/btree/Inode.h +++ b/src/tests/add-ons/kernel/file_systems/bfs/btree/Inode.h @@ -11,6 +11,11 @@ #include <File.h> #include "bfs.h" +#include "Utility.h" + + +#define ASSERT_READ_LOCKED_INODE(inode) inode->AssertReadLocked() +#define ASSERT_WRITE_LOCKED_INODE(inode) inode->AssertWriteLocked() class Volume; @@ -19,32 +24,36 @@ class Transaction; class Inode { public: - Inode(const char *name,int32 mode = S_STR_INDEX | S_ALLOW_DUPS); + Inode(const char* name, int32 mode = S_STR_INDEX | S_ALLOW_DUPS); ~Inode(); - rw_lock &Lock() { return fLock; } + rw_lock& Lock() { return fLock; } - status_t FindBlockRun(off_t pos,block_run &run,off_t &offset); - status_t Append(Transaction *,off_t bytes); - status_t SetFileSize(Transaction *,off_t bytes); + status_t FindBlockRun(off_t pos, block_run& run, off_t& offset); + status_t Append(Transaction&, off_t bytes); + status_t SetFileSize(Transaction&, off_t bytes); - Volume *GetVolume() const { return fVolume; } + Volume* GetVolume() const { return fVolume; } off_t ID() const { return 0; } int32 Mode() const { return fMode; } - char *Name() const { return "whatever"; } - block_run BlockRun() const { return block_run::Run(0,0,0); } - block_run Parent() const { return block_run::Run(0,0,0); } + const char* Name() const { return "whatever"; } + block_run BlockRun() const { return block_run::Run(0, 0, 0); } + block_run Parent() const { return block_run::Run(0, 0, 0); } off_t BlockNumber() const { return 0; } - bfs_inode *Node() { return (bfs_inode *)1; } + bfs_inode* Node() { return (bfs_inode*)1; } off_t Size() const { return fSize; } bool IsContainer() const { return true; } bool IsDirectory() const { return true; } + bool IsIndex() const { return is_index(Mode()); } + + void AssertReadLocked() { ASSERT_READ_LOCKED_RW_LOCK(&fLock); } + void AssertWriteLocked() { ASSERT_WRITE_LOCKED_RW_LOCK(&fLock); } private: - friend void dump_inode(Inode &inode); + friend void dump_inode(Inode& inode); - Volume *fVolume; + Volume* fVolume; BFile fFile; off_t fSize; rw_lock fLock; @@ -54,8 +63,36 @@ class Inode { off_t fOldSize; off_t fOldLastModified; off_t fBlockNumber; - void *fTree; - void *fAttributes; + void* fTree; + void* fAttributes; +}; + + +class InodeReadLocker { +public: + InodeReadLocker(Inode* inode) + : + fLock(&inode->Lock()) + { + rw_lock_read_lock(fLock); + } + + ~InodeReadLocker() + { + if (fLock != NULL) + rw_lock_read_unlock(fLock); + } + + void Unlock() + { + if (fLock != NULL) { + rw_lock_read_unlock(fLock); + fLock = NULL; + } + } + +private: + rw_lock* fLock; }; #endif /* INODE_H */ diff --git a/src/tests/add-ons/kernel/file_systems/bfs/btree/Jamfile b/src/tests/add-ons/kernel/file_systems/bfs/btree/Jamfile index 5f389f9..93241c2 100644 --- a/src/tests/add-ons/kernel/file_systems/bfs/btree/Jamfile +++ b/src/tests/add-ons/kernel/file_systems/bfs/btree/Jamfile @@ -9,20 +9,23 @@ rule FPreIncludes { return -include\ $(1:D=$(SUBDIR)) ; } { local defines = [ FDefines USER DEBUG ] ; # _NO_INLINE_ASM - local preIncludes = [ FPreIncludes Journal.h Inode.h ] ; + local preIncludes = [ FPreIncludes Inode.h Journal.h Volume.h ] ; SubDirC++Flags $(defines) $(preIncludes) -fno-exceptions ; #-fcheck-memory-usage } SimpleTest btreeTest - : #test.cpp + : test.cpp Volume.cpp Inode.cpp cache.cpp BPlusTree.cpp - Utility.cpp Debug.cpp - : be ; + QueryParserUtils.cpp + stubs.cpp + : be [ TargetLibstdc++ ] libkernelland_emu.so ; # Tell Jam where to find these sources -SEARCH on [ FGristFiles BPlusTree.cpp Utility.cpp Debug.cpp ] +SEARCH on [ FGristFiles BPlusTree.cpp Debug.cpp ] = [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems bfs ] ; +SEARCH on [ FGristFiles QueryParserUtils.cpp ] + = [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems shared ] ; diff --git a/src/tests/add-ons/kernel/file_systems/bfs/btree/Journal.h b/src/tests/add-ons/kernel/file_systems/bfs/btree/Journal.h index 375373e..e693a81 100644 --- a/src/tests/add-ons/kernel/file_systems/bfs/btree/Journal.h +++ b/src/tests/add-ons/kernel/file_systems/bfs/btree/Journal.h @@ -19,8 +19,13 @@ class TransactionListener : public DoublyLinkedListLinkImpl<TransactionListener> { public: - TransactionListener(); - virtual ~TransactionListener(); + TransactionListener() + { + } + + virtual ~TransactionListener() + { + } virtual void TransactionDone(bool success) = 0; virtual void RemovedFromTransaction() = 0; @@ -31,9 +36,10 @@ typedef DoublyLinkedList<TransactionListener> TransactionListeners; class Transaction { public: - Transaction(Volume *volume,off_t refBlock) + Transaction(Volume *volume, off_t refBlock) : - fVolume(volume) + fVolume(volume), + fID(volume->GenerateTransactionID()) { } @@ -41,17 +47,62 @@ class Transaction { { } - status_t WriteBlocks(off_t blockNumber,const uint8 *buffer,size_t numBlocks = 1) + int32 ID() const + { + return fID; + } + + Volume* GetVolume() + { + return fVolume; + } + + status_t WriteBlocks(off_t blockNumber, const uint8* buffer, + size_t numBlocks = 1) + { + return cached_write(fVolume->Device(), blockNumber, buffer, + numBlocks); + } + + + status_t Start(Volume* volume, off_t refBlock) + { + return B_OK; + } + + + status_t Done() + { + NotifyListeners(true); + return B_OK; + } + + void + AddListener(TransactionListener* listener) + { + fListeners.Add(listener); + } + + void + RemoveListener(TransactionListener* listener) { - return cached_write(fVolume->Device(),blockNumber,buffer,numBlocks,fVolume->BlockSize()); + fListeners.Remove(listener); + listener->RemovedFromTransaction(); } - void Done() + void + NotifyListeners(bool success) { + while (TransactionListener* listener = fListeners.RemoveHead()) { + listener->TransactionDone(success); + listener->RemovedFromTransaction(); + } } protected: - Volume *fVolume; + Volume* fVolume; + int32 fID; + TransactionListeners fListeners; }; diff --git a/src/tests/add-ons/kernel/file_systems/bfs/btree/Volume.cpp b/src/tests/add-ons/kernel/file_systems/bfs/btree/Volume.cpp index 3529d7d..17232f9 100644 --- a/src/tests/add-ons/kernel/file_systems/bfs/btree/Volume.cpp +++ b/src/tests/add-ons/kernel/file_systems/bfs/btree/Volume.cpp @@ -16,3 +16,10 @@ Volume::Panic() printf("PANIC!\n"); } + +int32 +Volume::GenerateTransactionID() +{ + static int32 sTransactionID = 1; + return sTransactionID++; +} diff --git a/src/tests/add-ons/kernel/file_systems/bfs/btree/Volume.h b/src/tests/add-ons/kernel/file_systems/bfs/btree/Volume.h index 82afc0b..029e420 100644 --- a/src/tests/add-ons/kernel/file_systems/bfs/btree/Volume.h +++ b/src/tests/add-ons/kernel/file_systems/bfs/btree/Volume.h @@ -19,14 +19,26 @@ class Volume { public: Volume(BFile *file) : fFile(file) {} + bool IsInitializing() const { return false; } + bool IsValidInodeBlock(off_t) const { return true; } + BFile *Device() { return fFile; } + void *BlockCache() { return fFile; } + fs_volume *FSVolume() { return NULL; } + + uint32 BlockSize() const { return 1024; } + uint32 BlockShift() const { return 10; /* 2^BlockShift == BlockSize */ } - int32 BlockSize() const { return 1024; } off_t ToBlock(block_run run) const { return run.start; } - block_run ToBlockRun(off_t block) const { return block_run::Run(0,0,block); } + block_run ToBlockRun(off_t block) const + { + return block_run::Run(0, 0, block); + } static void Panic(); + int32 GenerateTransactionID(); + private: BFile *fFile; }; diff --git a/src/tests/add-ons/kernel/file_systems/bfs/btree/cache.cpp b/src/tests/add-ons/kernel/file_systems/bfs/btree/cache.cpp index b826d64..6c91608 100644 --- a/src/tests/add-ons/kernel/file_systems/bfs/btree/cache.cpp +++ b/src/tests/add-ons/kernel/file_systems/bfs/btree/cache.cpp @@ -21,86 +21,143 @@ */ +#define TRACE(x) /*printf x*/ + + +static size_t sBlockSize; + + BList gBlocks; void -init_cache(BFile */*file*/,int32 /*blockSize*/) +init_cache(BFile* /*file*/, int32 blockSize) { + sBlockSize = blockSize; } void -shutdown_cache(BFile *file,int32 blockSize) +shutdown_cache(BFile* file, int32 blockSize) { - for (int32 i = 0;i < gBlocks.CountItems();i++) { - void *buffer = gBlocks.ItemAt(i); + for (int32 i = 0; i < gBlocks.CountItems(); i++) { + void* buffer = gBlocks.ItemAt(i); if (buffer == NULL) { - printf("cache is corrupt!\n"); + debugger("cache is corrupt!"); exit(-1); } - file->WriteAt(i * blockSize,buffer,blockSize); + + file->WriteAt(i * blockSize, buffer, blockSize); free(buffer); } } +status_t +cached_write(void* cache, off_t num, const void* _data, off_t numBlocks) +{ + if (num + numBlocks > gBlocks.CountItems()) { + debugger("cached write beyond loaded blocks"); + exit(1); + } + + for (off_t i = 0; i < numBlocks; i++) { + void* buffer = gBlocks.ItemAt(num + i); + const void* data = (uint8*)_data + i * sBlockSize; + if (buffer != data) + memcpy(buffer, data, sBlockSize); + } + + return B_OK; +} + + static status_t -readBlocks(BFile *file,uint32 num,uint32 size) +read_blocks(void* cache, off_t num) { + BFile* file = (BFile*)cache; for (uint32 i = gBlocks.CountItems(); i <= num; i++) { - void *buffer = malloc(size); + void* buffer = malloc(sBlockSize); if (buffer == NULL) return B_NO_MEMORY; gBlocks.AddItem(buffer); - if (file->ReadAt(i * size,buffer,size) < B_OK) + if (file->ReadAt(i * sBlockSize, buffer, sBlockSize) < 0) return B_IO_ERROR; } + return B_OK; } -int -cached_write(BFile *file, off_t num,const void *data,off_t numBlocks, int blockSize) +static void* +get_block(void* cache, off_t num) { - //printf("cached_write(num = %Ld,data = %p,numBlocks = %Ld,blockSize = %ld)\n",num,data,numBlocks,blockSize); - if (file == NULL) - return B_BAD_VALUE; - + //TRACE(("get_block(num = %" B_PRIdOFF ")\n", num); if (num >= gBlocks.CountItems()) - puts("Oh no!"); + read_blocks(cache, num); - void *buffer = gBlocks.ItemAt(num); - if (buffer == NULL) - return B_BAD_VALUE; + return gBlocks.ItemAt(num); +} - if (buffer != data && numBlocks == 1) - memcpy(buffer,data,blockSize); - return B_OK; +static void +release_block(void* cache, off_t num) +{ + //TRACE(("release_block(num = %" B_PRIdOFF ")\n", num)); } -void * -get_block(BFile *file, off_t num, int blockSize) +// #pragma mark - Block Cache API + + +const void* +block_cache_get(void* _cache, off_t blockNumber) { - //printf("get_block(num = %Ld,blockSize = %ld)\n",num,blockSize); - if (file == NULL) - return NULL; + TRACE(("block_cache_get(block = %" B_PRIdOFF ")\n", blockNumber)); + return get_block(_cache, blockNumber); +} - if (num >= gBlocks.CountItems()) - readBlocks(file,num,blockSize); - return gBlocks.ItemAt(num); +status_t +block_cache_make_writable(void* _cache, off_t blockNumber, int32 transaction) +{ + TRACE(("block_cache_make_writable(block = %" B_PRIdOFF ", transaction = %" + B_PRId32 ")\n", blockNumber, transaction)); + + // We're always writable... + return B_OK; } -int -release_block(BFile *file, off_t num) +void* +block_cache_get_writable(void* _cache, off_t blockNumber, int32 transaction) { - //printf("release_block(num = %Ld)\n",num); - return 0; + TRACE(("block_cache_get_writable(block = %" B_PRIdOFF + ", transaction = %" B_PRId32 ")\n", blockNumber, transaction)); + return get_block(_cache, blockNumber); } + +status_t +block_cache_set_dirty(void* _cache, off_t blockNumber, bool dirty, + int32 transaction) +{ + TRACE(("block_cache_set_dirty(block = %" B_PRIdOFF + ", dirty = %s, transaction = %" B_PRId32 ")\n", blockNumber, + dirty ? "yes" : "no", transaction)); + + if (dirty) + debugger("setting to dirty not implemented\n"); + + return B_OK; +} + + +void +block_cache_put(void* _cache, off_t blockNumber) +{ + TRACE(("block_cache_put(block = %" B_PRIdOFF ")\n", blockNumber)); + release_block(_cache, blockNumber); +} diff --git a/src/tests/add-ons/kernel/file_systems/bfs/btree/cache.h b/src/tests/add-ons/kernel/file_systems/bfs/btree/cache.h index 0b260f7..b71a900 100644 --- a/src/tests/add-ons/kernel/file_systems/bfs/btree/cache.h +++ b/src/tests/add-ons/kernel/file_systems/bfs/btree/cache.h @@ -12,11 +12,24 @@ class BFile; -extern void init_cache(BFile *file, int32 blockSize); -extern void shutdown_cache(BFile *file, int32 blockSize); +extern void init_cache(BFile* file, int32 blockSize); +extern void shutdown_cache(BFile* file, int32 blockSize); -extern int cached_write(BFile *file, off_t bnum, const void *data,off_t num_blocks, int bsize); -extern void *get_block(BFile *file, off_t bnum, int bsize); -extern int release_block(BFile *file, off_t bnum); +extern status_t cached_write(void* cache, off_t num, const void* _data, + off_t numBlocks); + + +// Block Cache API + +extern const void* block_cache_get(void* _cache, off_t blockNumber); + +extern status_t block_cache_make_writable(void* _cache, off_t blockNumber, + int32 transaction); +extern void* block_cache_get_writable(void* _cache, off_t blockNumber, + int32 transaction); + +extern status_t block_cache_set_dirty(void* _cache, off_t blockNumber, + bool dirty, int32 transaction); +extern void block_cache_put(void* _cache, off_t blockNumber); #endif /* CACHE_H */ diff --git a/src/tests/add-ons/kernel/file_systems/bfs/btree/stubs.cpp b/src/tests/add-ons/kernel/file_systems/bfs/btree/stubs.cpp new file mode 100644 index 0000000..262e483 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/bfs/btree/stubs.cpp @@ -0,0 +1,15 @@ +#include "fs_interface.h" + + +status_t +acquire_vnode(fs_volume* volume, ino_t vnodeID) +{ + return B_OK; +} + + +status_t +put_vnode(fs_volume* volume, ino_t vnodeID) +{ + return B_OK; +} diff --git a/src/tests/add-ons/kernel/file_systems/bfs/btree/test.cpp b/src/tests/add-ons/kernel/file_systems/bfs/btree/test.cpp index ea7ff2a..e06c363 100644 --- a/src/tests/add-ons/kernel/file_systems/bfs/btree/test.cpp +++ b/src/tests/add-ons/kernel/file_systems/bfs/btree/test.cpp @@ -134,7 +134,7 @@ dumpKey(void *key, int32 length) void dumpKeys() { - char *type; + const char *type; switch (gType) { case S_STR_INDEX: type = "string"; @@ -157,6 +157,9 @@ dumpKeys() case S_DOUBLE_INDEX: type = "double"; break; + default: + debugger("unknown type in gType"); + return; } printf("Dumping %ld keys of type %s\n",gNum,type); @@ -373,6 +376,7 @@ checkTreeContents(BPlusTree *tree) printf("Key "); dumpKey(gKeys[i].data,gKeys[i].length); printf(" found only %ld from %ld\n",gKeys[i].count,gKeys[i].in); + bailOut(); } } } @@ -381,16 +385,18 @@ checkTreeContents(BPlusTree *tree) void checkTreeIntegrity(BPlusTree *tree) { - // simple test, just seeks down to every key - if it couldn't - // be found, something must be wrong + // simple test, just seeks down to every key - if it's in and couldn't + // be found or it's not in and can be found, something must be wrong TreeIterator iterator(tree); for (int32 i = 0;i < gNum;i++) { - if (gKeys[i].in == 0) - continue; - status_t status = iterator.Find((uint8 *)gKeys[i].data,gKeys[i].length); - if (status != B_OK) { + if (gKeys[i].in == 0) { + if (status == B_OK) { + printf("found key %" B_PRId32 " even though it's not in!\n", i); + bailOutWithKey(gKeys[i].data, gKeys[i].length); + } + } else if (status != B_OK) { printf("TreeIterator::Find() returned: %s\n",strerror(status)); bailOutWithKey(gKeys[i].data,gKeys[i].length); } @@ -406,6 +412,13 @@ checkTree(BPlusTree *tree) checkTreeContents(tree); checkTreeIntegrity(tree); + + bool errorsFound = false; + tree->Validate(false, errorsFound); + if (errorsFound) { + printf("BPlusTree::Validate() found errors\n"); + bailOut(); + } } @@ -416,7 +429,7 @@ checkTree(BPlusTree *tree) void -addAllKeys(Transaction *transaction, BPlusTree *tree) +addAllKeys(Transaction &transaction, BPlusTree *tree) { printf("*** Adding all keys to the tree...\n"); for (int32 i = 0;i < gNum;i++) { @@ -437,7 +450,7 @@ addAllKeys(Transaction *transaction, BPlusTree *tree) void -removeAllKeys(Transaction *transaction, BPlusTree *tree) +removeAllKeys(Transaction &transaction, BPlusTree *tree) { printf("*** Removing all keys from the tree...\n"); for (int32 i = 0;i < gNum;i++) { @@ -462,7 +475,7 @@ removeAllKeys(Transaction *transaction, BPlusTree *tree) void -duplicateTest(Transaction *transaction,BPlusTree *tree) +duplicateTest(Transaction &transaction,BPlusTree *tree) { int32 index = int32(1.0 * gNum * rand() / RAND_MAX); if (index == gNum) @@ -481,14 +494,15 @@ duplicateTest(Transaction *transaction,BPlusTree *tree) printf("* insert %ld to %ld old entries...\n",insertCount,insertTotal + gKeys[index].in); for (int32 j = 0;j < insertCount;j++) { - status = tree->Insert(transaction,(uint8 *)gKeys[index].data,gKeys[index].length,insertTotal); + status = tree->Insert(transaction,(uint8 *)gKeys[index].data,gKeys[index].length,gKeys[index].value); if (status < B_OK) { printf("BPlusTree::Insert() returned: %s\n",strerror(status)); bailOutWithKey(gKeys[index].data,gKeys[index].length); } insertTotal++; gTreeCount++; - + gKeys[index].in++; + if (gExcessive) checkTree(tree); } @@ -505,26 +519,27 @@ duplicateTest(Transaction *transaction,BPlusTree *tree) printf("* remove %ld from %ld entries...\n",count,insertTotal + gKeys[index].in); for (int32 j = 0;j < count;j++) { - status_t status = tree->Remove(transaction,(uint8 *)gKeys[index].data,gKeys[index].length,insertTotal - 1); + status_t status = tree->Remove(transaction,(uint8 *)gKeys[index].data,gKeys[index].length,gKeys[index].value); if (status < B_OK) { printf("BPlusTree::Remove() returned: %s\n",strerror(status)); bailOutWithKey(gKeys[index].data,gKeys[index].length); } insertTotal--; gTreeCount--; + gKeys[index].in--; if (gExcessive) checkTree(tree); } } - if (!gExcessive) + if (gExcessive) checkTree(tree); } void -addRandomSet(Transaction *transaction,BPlusTree *tree,int32 num) +addRandomSet(Transaction &transaction,BPlusTree *tree,int32 num) { printf("*** Add random set to tree (%ld to %ld old entries)...\n",num,gTreeCount); @@ -553,7 +568,7 @@ addRandomSet(Transaction *transaction,BPlusTree *tree,int32 num) void -removeRandomSet(Transaction *transaction,BPlusTree *tree,int32 num) +removeRandomSet(Transaction &transaction,BPlusTree *tree,int32 num) { printf("*** Remove random set from tree (%ld from %ld entries)...\n",num,gTreeCount); @@ -708,6 +723,7 @@ main(int argc,char **argv) srand(gSeed); Inode inode("tree.data",gType | S_ALLOW_DUPS); + rw_lock_write_lock(&inode.Lock()); gVolume = inode.GetVolume(); Transaction transaction(gVolume,0); @@ -717,7 +733,7 @@ main(int argc,char **argv) // Create the tree, the keys, and add all keys to the tree initially // - BPlusTree tree(&transaction,&inode); + BPlusTree tree(transaction,&inode); status_t status; if ((status = tree.InitCheck()) < B_OK) { fprintf(stderr,"creating tree failed: %s\n",strerror(status)); @@ -733,7 +749,7 @@ main(int argc,char **argv) dumpKeys(); for (int32 j = 0; j < gHard; j++ ) { - addAllKeys(&transaction, &tree); + addAllKeys(transaction, &tree); // // Run the tests (they will exit the app, if an error occurs) @@ -742,14 +758,16 @@ main(int argc,char **argv) for (int32 i = 0;i < gIterations;i++) { printf("---------- Test iteration %ld ---------------------------------\n",i+1); - addRandomSet(&transaction,&tree,int32(1.0 * gNum * rand() / RAND_MAX)); - removeRandomSet(&transaction,&tree,int32(1.0 * gNum * rand() / RAND_MAX)); - duplicateTest(&transaction,&tree); + addRandomSet(transaction,&tree,int32(1.0 * gNum * rand() / RAND_MAX)); + removeRandomSet(transaction,&tree,int32(1.0 * gNum * rand() / RAND_MAX)); + duplicateTest(transaction,&tree); } - removeAllKeys(&transaction, &tree); + removeAllKeys(transaction, &tree); } + transaction.Done(); + // of course, we would have to free all our memory in a real application here... // write the cache back to the tree