[haiku-commits] haiku: hrev48060 - in src/tests/add-ons/kernel: file_systems/bfs/btree kernelland_emu

  • From: mmlr@xxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Tue, 21 Oct 2014 00:27:11 +0200 (CEST)

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


Other related posts: