diff options
-rw-r--r-- | src/hbtree/hbtree.cpp | 17 | ||||
-rw-r--r-- | src/hbtree/hbtree_p.h | 1 | ||||
-rw-r--r-- | tests/auto/hbtree/main.cpp | 12 |
3 files changed, 26 insertions, 4 deletions
diff --git a/src/hbtree/hbtree.cpp b/src/hbtree/hbtree.cpp index 5e8f0810..46b3585c 100644 --- a/src/hbtree/hbtree.cpp +++ b/src/hbtree/hbtree.cpp @@ -91,7 +91,7 @@ const quint32 HBtreePrivate::PageInfo::INVALID_PAGE = 0xFFFFFFFF; HBtreePrivate::HBtreePrivate(HBtree *q, const QString &name) : q_ptr(q), fileName_(name), fd_(-1), openMode_(HBtree::ReadOnly), size_(0), lastSyncedId_(0), cacheSize_(20), compareFunction_(0), - writeTransaction_(0), lastPage_(PageInfo::INVALID_PAGE), cursorDisrupted_(false) + writeTransaction_(0), readTransaction_(0), lastPage_(PageInfo::INVALID_PAGE), cursorDisrupted_(false) { } @@ -209,6 +209,8 @@ bool HBtreePrivate::open(int fd) void HBtreePrivate::close(bool doSync) { + HBTREE_ASSERT(!readTransaction_ && !writeTransaction_); + if (fd_ != -1) { HBTREE_DEBUG("closing btree with fd:" << fd_); if (doSync) @@ -931,9 +933,13 @@ void HBtreePrivate::abort(HBtreeTransaction *transaction) } dirtyPages_.clear(); if (transaction->isReadWrite()) { + HBTREE_ASSERT(transaction == writeTransaction_); if (::flock(fd_, LOCK_UN) != 0) HBTREE_ERROR("failed to unlock file with transaction @" << transaction); writeTransaction_ = 0; + } else { + HBTREE_ASSERT(transaction == readTransaction_); + readTransaction_ = 0; } delete transaction; cachePrune(); @@ -998,6 +1004,13 @@ HBtreeTransaction *HBtreePrivate::beginTransaction(HBtreeTransaction::Type type) { Q_Q(HBtree); + HBTREE_ASSERT(!writeTransaction_ && !readTransaction_); + + if (writeTransaction_ || readTransaction_) { + HBTREE_ERROR("Only one transaction type supported at a time"); + return 0; + } + if (type == HBtreeTransaction::ReadWrite && writeTransaction_) { HBTREE_ERROR("cannot open write transaction when one in progress"); return 0; @@ -1031,6 +1044,8 @@ HBtreeTransaction *HBtreePrivate::beginTransaction(HBtreeTransaction::Type type) transaction->revision_ = marker_.meta.revision; if (type == HBtreeTransaction::ReadWrite) writeTransaction_ = transaction; + else + readTransaction_ = transaction; HBTREE_DEBUG("began" << (transaction->isReadOnly() ? "read" : "write") << "transaction @" << transaction << "[root:" << transaction->rootPage_ diff --git a/src/hbtree/hbtree_p.h b/src/hbtree/hbtree_p.h index ab529797..8575db31 100644 --- a/src/hbtree/hbtree_p.h +++ b/src/hbtree/hbtree_p.h @@ -388,6 +388,7 @@ public: PageMap dirtyPages_; HBtree::CompareFunction compareFunction_; HBtreeTransaction *writeTransaction_; + HBtreeTransaction *readTransaction_; QSet<quint32> collectiblePages_; PageMap cache_; quint32 lastPage_; diff --git a/tests/auto/hbtree/main.cpp b/tests/auto/hbtree/main.cpp index 517feb04..41cf02c8 100644 --- a/tests/auto/hbtree/main.cpp +++ b/tests/auto/hbtree/main.cpp @@ -2107,6 +2107,7 @@ void TestHBtree::deleteReinsertVerify() keyValueMap.insert(it.key(), it.value()); ++it; } + txn->commit(0); // Verify in order. txn = db->beginTransaction(HBtreeTransaction::ReadOnly); @@ -2226,16 +2227,21 @@ void TestHBtree::tag() QVERIFY(txn); QVERIFY(txn->put(QByteArray("foo"), QByteArray("123"))); QCOMPARE(db->tag(), 42u); - // do not commit just yet + + // This test held off on a commit until the read was done. But for now we don't allow + // simultaneous reads and writes. + txn->abort(); HBtreeTransaction *rtxn = db->beginTransaction(HBtreeTransaction::ReadOnly); QVERIFY(rtxn); QCOMPARE(rtxn->tag(), 42u); + rtxn->abort(); + txn = db->beginTransaction(HBtreeTransaction::ReadWrite); + QVERIFY(txn); QVERIFY(txn->commit(64u)); QCOMPARE(db->tag(), 64u); - QCOMPARE(rtxn->tag(), 42u); - rtxn->abort(); + rtxn = db->beginTransaction(HBtreeTransaction::ReadOnly); QVERIFY(rtxn); QCOMPARE(rtxn->tag(), 64u); |