[rhmessaging-commits] rhmessaging commits: r2433 - in store/trunk/cpp: lib and 1 other directories.

rhmessaging-commits at lists.jboss.org rhmessaging-commits at lists.jboss.org
Tue Sep 9 15:25:47 EDT 2008


Author: kpvdr
Date: 2008-09-09 15:25:47 -0400 (Tue, 09 Sep 2008)
New Revision: 2433

Added:
   store/trunk/cpp/lib/MessageStoreImpl.cpp
   store/trunk/cpp/lib/MessageStoreImpl.h
Removed:
   store/trunk/cpp/lib/BdbMessageStore.cpp
   store/trunk/cpp/lib/BdbMessageStore.h
Modified:
   store/trunk/cpp/configure.ac
   store/trunk/cpp/lib/Makefile.am
   store/trunk/cpp/lib/StorePlugin.cpp
   store/trunk/cpp/tests/OrderingTest.cpp
   store/trunk/cpp/tests/SimpleTest.cpp
   store/trunk/cpp/tests/TransactionalTest.cpp
   store/trunk/cpp/tests/TwoPhaseCommitTest.cpp
Log:
Changed name of class "BdbMessageStore" to class "MessageStoreImpl". This reflects the recent changes which remove BDB from the journal message path, and the goal of eventually removing BDB from the store altogether.

Modified: store/trunk/cpp/configure.ac
===================================================================
--- store/trunk/cpp/configure.ac	2008-09-09 13:39:28 UTC (rev 2432)
+++ store/trunk/cpp/configure.ac	2008-09-09 19:25:47 UTC (rev 2433)
@@ -29,7 +29,7 @@
 AC_PREREQ(2.59)
 
 AC_CONFIG_HEADERS([config.h:config.in])
-AC_CONFIG_SRCDIR([lib/BdbMessageStore.cpp])
+AC_CONFIG_SRCDIR([lib/MessageStoreImpl.cpp])
 
 AC_PROG_CC_STDC
 AM_PROG_CC_C_O

Deleted: store/trunk/cpp/lib/BdbMessageStore.cpp
===================================================================
--- store/trunk/cpp/lib/BdbMessageStore.cpp	2008-09-09 13:39:28 UTC (rev 2432)
+++ store/trunk/cpp/lib/BdbMessageStore.cpp	2008-09-09 19:25:47 UTC (rev 2433)
@@ -1,1693 +0,0 @@
-/*
-  Copyright (C) 2007 Red Hat Software
-
-  This file is part of Red Hat Messaging.
-
-  Red Hat Messaging is free software; you can redistribute it and/or
-  modify it under the terms of the GNU Lesser General Public
-  License as published by the Free Software Foundation; either
-  version 2.1 of the License, or (at your option) any later version.
-
-  This library is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public
-  License along with this library; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
-  USA
-
-  The GNU Lesser General Public License is available in the file COPYING.
-*/
-
-#include "BdbMessageStore.h"
-
-#include "BindingDbt.h"
-#include "BufferValue.h"
-#include "IdPairDbt.h"
-#include "jrnl/txn_map.hpp"
-#include "qpid/log/Statement.h"
-#include "PackageMrgstore.h"
-
-#define MAX_AIO_SLEEPS 1000 // ~1 second
-#define AIO_SLEEP_TIME 1000 // 1 milisecond
-
-using namespace rhm::bdbstore;
-using namespace qpid::broker;
-using boost::static_pointer_cast;
-using boost::intrusive_ptr;
-
-using std::auto_ptr;
-using std::max;
-using qpid::framing::Buffer;
-using qpid::framing::FieldTable;
-using qpid::management::ManagementAgent;
-
-static const u_int8_t MESSAGE_MESSAGE = 1;
-static const u_int8_t BASIC_MESSAGE = 2;
-qpid::sys::Duration BdbMessageStore::defJournalGetEventsTimeout(10 * qpid::sys::TIME_MSEC); // 10ms
-qpid::sys::Duration BdbMessageStore::defJournalFlushTimeout(500 * qpid::sys::TIME_MSEC); // 0.5s
-qpid::sys::Mutex TxnCtxt::globalSerialiser;
-
-BdbMessageStore::TplRecoverStruct::TplRecoverStruct(const u_int64_t _rid,
-                                                              const bool _deq_flag,
-                                                              const bool _commit_flag,
-                                                              const bool _tpc_flag) :
-                                                              rid(_rid),
-                                                              deq_flag(_deq_flag),
-                                                              commit_flag(_commit_flag),
-                                                              tpc_flag(_tpc_flag)
-{}
-
-BdbMessageStore::BdbMessageStore(const char* envpath) :
-                                 env(0),
-                                 queueDb(&env, 0),
-                                 configDb(&env, 0),
-                                 exchangeDb(&env, 0),
-                                 messageDb(&env, 0),
-                                 mappingDb(&env, 0),
-                                 bindingDb(&env, 0),
-                                 generalDb(&env, 0),
-                                 numJrnlFiles(0),
-                                 jrnlFsizeSblks(0),
-                                 wCachePgSizeSblks(0),
-                                 wCacheNumPages(0),
-                                 tplNumJrnlFiles(0),
-                                 tplJrnlFsizeSblks(0),
-                                 tplWCachePgSizeSblks(0),
-                                 tplWCacheNumPages(0),
-                                 highestRid(0),
-                                 isInit(false),
-                                 envPath(envpath),
-                                 mgmtObject(0)
-{}
-
-u_int16_t BdbMessageStore::chkJrnlNumFilesParam(const u_int16_t param, const std::string paramName)
-{
-    u_int16_t p = param;
-    if (p < JRNL_MIN_NUM_FILES) {
-        p = JRNL_MIN_NUM_FILES;
-        QPID_LOG(warning, "parameter " << paramName << " (" << param << ") is below allowable minimum (" << JRNL_MIN_NUM_FILES << "); changing this parameter to minimum value.");
-    } else if (p > JRNL_MAX_NUM_FILES) {
-        p = JRNL_MAX_NUM_FILES;
-        QPID_LOG(warning, "parameter " << paramName << " (" << param << ") is above allowable maximum (" << JRNL_MAX_NUM_FILES << "); changing this parameter to maximum value.");
-    }
-    return p;
-}
-
-u_int32_t BdbMessageStore::chkJrnlFileSizeParam(const u_int32_t param, const std::string paramName)
-{
-    u_int32_t p = param;
-    u_int32_t min = JRNL_MIN_FILE_SIZE / JRNL_RMGR_PAGE_SIZE;
-    u_int32_t max = JRNL_MAX_FILE_SIZE / JRNL_RMGR_PAGE_SIZE;
-    if (p < min) {
-        p = min;
-        QPID_LOG(warning, "parameter " << paramName << " (" << param << ") is below allowable minimum (" << min << "); changing this parameter to minimum value.");
-    } else if (p > max) {
-        p = max;
-        QPID_LOG(warning, "parameter " << paramName << " (" << param << ") is above allowable maximum (" << max << "); changing this parameter to maximum value.");
-    }
-    return p;
-}
-
-u_int32_t BdbMessageStore::chkJrnlWrPageCacheSize(const u_int32_t param, const std::string paramName)
-{
-    u_int32_t p = param;
-    switch (p)
-    {
-      case 1:
-      case 2:
-      case 4:
-      case 8:
-      case 16:
-      case 32:
-      case 64:
-      case 128:
-        break;
-      default:
-        if (p == 0) {
-            // For zero value, use default
-            p = JRNL_WMGR_DEF_PAGE_SIZE * JRNL_DBLK_SIZE * JRNL_SBLK_SIZE / 1024;
-            QPID_LOG(warning, "parameter " << paramName << " (" << param << ") must be a power of 2 between 1 and 128; changing this parameter to default value (" << p << ")");
-        } else {
-            // For any positive value, use closest value
-            if      (p <   6)   p =   4;
-            else if (p <  12)   p =   8;
-            else if (p <  24)   p =  16;
-            else if (p <  48)   p =  32;
-            else if (p <  96)   p =  64;
-            else if (p > 128)   p = 128;
-            QPID_LOG(warning, "parameter " << paramName << " (" << param << ") must be a power of 2 between 1 and 128; changing this parameter to closest allowable value (" << p << ")");
-        }
-    }
-    return p;
-}
-
-u_int16_t BdbMessageStore::getJrnlWrNumPages(const u_int32_t wrPageSizeKib)
-{
-    u_int32_t wrPageSizeSblks = wrPageSizeKib * 1024 / JRNL_DBLK_SIZE / JRNL_SBLK_SIZE; // convert from KiB to number sblks
-    u_int32_t defTotWCacheSize = JRNL_WMGR_DEF_PAGE_SIZE * JRNL_WMGR_DEF_PAGES; // in sblks. Currently 2014 sblks (1 MiB).
-    switch (wrPageSizeKib)
-    {
-      case 1:
-      case 2:
-      case 4:
-        // 256 KiB total cache
-        return defTotWCacheSize / wrPageSizeSblks / 4;
-      case 8:
-      case 16:
-        // 512 KiB total cache
-        return defTotWCacheSize / wrPageSizeSblks / 2;
-      default: // 32, 64, 128
-        // 1 MiB total cache
-        return defTotWCacheSize / wrPageSizeSblks;
-    }
-}
-
-void BdbMessageStore::initManagement (Broker* broker)
-{
-    if (broker != 0) {
-        ManagementAgent* agent = ManagementAgent::Singleton::getInstance();
-        if (agent != 0) {
-            qpid::management::PackageMrgstore packageInitializer(agent);
-            mgmtObject = new qpid::management::Store(agent, this, broker);
-
-            mgmtObject->set_location(storeDir);
-            mgmtObject->set_defaultInitialFileCount(numJrnlFiles);
-            mgmtObject->set_defaultDataFileSize(jrnlFsizeSblks / JRNL_RMGR_PAGE_SIZE);
-            mgmtObject->set_tplIsInitialized(false);
-            mgmtObject->set_tplDirectory(getTplBaseDir());
-            mgmtObject->set_tplWritePageSize(tplWCachePgSizeSblks * JRNL_SBLK_SIZE * JRNL_DBLK_SIZE);
-            mgmtObject->set_tplWritePages(tplWCacheNumPages);
-            mgmtObject->set_tplInitialFileCount(tplNumJrnlFiles);
-            mgmtObject->set_tplDataFileSize(tplJrnlFsizeSblks * JRNL_SBLK_SIZE * JRNL_DBLK_SIZE);
-            mgmtObject->set_tplCurrentFileCount(tplNumJrnlFiles);
-
-            agent->addObject(mgmtObject, 0x1000000000000050LL);
-        }
-    }
-}
-
-bool BdbMessageStore::init(const qpid::Options* options)
-{
-    // Extract and check options
-    const Options* opts = static_cast<const Options*>(options);
-    u_int16_t numJrnlFiles = chkJrnlNumFilesParam(opts->numJrnlFiles, "num-jfiles");
-    u_int32_t jrnlFsizePgs = chkJrnlFileSizeParam(opts->jrnlFsizePgs, "jfile-size-pgs");
-    u_int32_t jrnlWrCachePageSizeKib = chkJrnlWrPageCacheSize(opts->wCachePageSizeKib, "wcache-page-size");
-    u_int16_t tplNumJrnlFiles = chkJrnlNumFilesParam(opts->tplNumJrnlFiles, "tpl-num-jfiles");
-    u_int32_t tplJrnlFSizePgs = chkJrnlFileSizeParam(opts->tplJrnlFsizePgs, "tpl-jfile-size-pgs");
-    u_int32_t tplJrnlWrCachePageSizeKib = chkJrnlWrPageCacheSize(opts->tplWCachePageSizeKib, "tpl-wcache-page-size");
-    
-    // Pass option values to init(...)
-    return init(opts->storeDir, numJrnlFiles, jrnlFsizePgs, jrnlWrCachePageSizeKib, tplNumJrnlFiles, tplJrnlFSizePgs, tplJrnlWrCachePageSizeKib);
-}
-
-// These params, taken from options, are assumed to be correct and verified
-bool BdbMessageStore::init(const std::string& dir,
-                           u_int16_t jfiles,
-                           u_int32_t jfileSizePgs,
-                           u_int32_t wCachePageSizeKib,
-                           u_int16_t tplJfiles,
-                           u_int32_t tplJfileSizePgs,
-                           u_int32_t tplWCachePageSizeKib)
-{
-    if (isInit) return true;
-
-    // Set geometry members (converting to correct units where req'd)
-    numJrnlFiles = jfiles;
-    jrnlFsizeSblks = jfileSizePgs * JRNL_RMGR_PAGE_SIZE;
-    wCachePgSizeSblks = wCachePageSizeKib * 1024 / JRNL_DBLK_SIZE / JRNL_SBLK_SIZE; // convert from KiB to number sblks
-    wCacheNumPages = getJrnlWrNumPages(wCachePageSizeKib);
-    tplNumJrnlFiles = tplJfiles;
-    tplJrnlFsizeSblks = tplJfileSizePgs * JRNL_RMGR_PAGE_SIZE;
-    tplWCachePgSizeSblks = tplWCachePageSizeKib * 1024 / JRNL_DBLK_SIZE / JRNL_SBLK_SIZE; // convert from KiB to number sblks
-    tplWCacheNumPages = getJrnlWrNumPages(tplWCachePageSizeKib);
-
-    if (dir.size()>0) storeDir = dir;
-
-    journal::jdir::create_dir(getBdbBaseDir());
-
-    try {
-        env.open(getBdbBaseDir().c_str(), DB_THREAD | DB_CREATE | DB_INIT_TXN | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_USE_ENVIRON, 0);
-    } catch (const DbException& e) {
-        if (e.get_errno() == DB_VERSION_MISMATCH)
-            THROW_STORE_EXCEPTION_2("Database environment mismatch: This version of bd4 does not match that which created the store database. "
-                                    "(If recovery is not important, delete the contents of the store directory. Otherwise, try upgrading the database using "
-                                    "db_upgrade or using db_recover - but the db4-utils package must also be installed to use these utilities.)", e);
-        THROW_STORE_EXCEPTION_2("Error opening environment", e);
-    }
-
-    TxnCtxt txn;
-    try {
-        txn.begin(env, false);
-        open(queueDb, txn.get(), "queues.db", false);
-        open(configDb, txn.get(), "config.db", false);
-        open(exchangeDb, txn.get(), "exchanges.db", false);
-        open(messageDb, txn.get(), "messages.db", false);
-        open(mappingDb, txn.get(), "mappings.db", true);
-        open(bindingDb, txn.get(), "bindings.db", true);
-        open(generalDb, txn.get(), "general.db",  false);
-        tplStorePtr.reset(new TplJournalImpl("TplStore", getTplBaseDir(), "tpl", defJournalGetEventsTimeout, defJournalFlushTimeout));
-        txn.commit();
-    } catch (const journal::jexception& e) {
-        txn.abort();
-        THROW_STORE_EXCEPTION_2("Error opening tplStore instance", e.what());
-    } catch (const DbException& e) {
-        txn.abort();
-        THROW_STORE_EXCEPTION_2("Error opening databases", e);
-    } catch (...) {
-        txn.abort();
-        throw;
-    }
-
-    isInit = true;
-    QPID_LOG(notice, "Store module initialized; dir=" << dir);
-    QPID_LOG(info,   "> Default files per journal: " << jfiles);
-    QPID_LOG(info,   "> Default jrournal file size: " << jfileSizePgs << " (wpgs)");
-    QPID_LOG(info,   "> Default write cache page size: " << wCachePageSizeKib << " (Kib)");
-    QPID_LOG(info,   "> Default number of write cache pages: " << wCacheNumPages);
-    QPID_LOG(info,   "> TPL files per journal: " << tplNumJrnlFiles);
-    QPID_LOG(info,   "> TPL jrournal file size: " << tplJfileSizePgs << " (wpgs)");
-    QPID_LOG(info,   "> TPL write cache page size: " << tplWCachePageSizeKib << " (Kib)");
-    QPID_LOG(info,   "> TPL number of write cache pages: " << tplWCacheNumPages);
-    return true;
-}
-
-void BdbMessageStore::chkTplStoreInit()
-{
-    if (!tplStorePtr->is_ready()) {
-        qpid::sys::Mutex::ScopedLock sl(jrnlCreateLock);
-        if (!tplStorePtr->is_ready()) {
-            journal::jdir::create_dir(getTplBaseDir());
-            tplStorePtr->initialize(tplNumJrnlFiles, tplJrnlFsizeSblks, tplWCacheNumPages, tplWCachePgSizeSblks);
-            if (mgmtObject != 0) mgmtObject->set_tplIsInitialized(true);
-        }
-    }
-}
-
-void BdbMessageStore::open(Db& db,
-                           DbTxn* txn,
-                           const char* file,
-                           bool dupKey)
-{
-    if(dupKey) db.set_flags(DB_DUPSORT);
-    db.open(txn, file, 0, DB_BTREE, DB_CREATE | DB_THREAD, 0);
-    dbs.push_back(&db);
-}
-
-BdbMessageStore::~BdbMessageStore()
-{
-    try {
-        for (std::list<Db*>::iterator i = dbs.begin(); i != dbs.end(); i++) {
-            (*i)->close(0);
-        }
-        if (tplStorePtr->is_ready()) tplStorePtr->stop(true);
-    } catch (const DbException& e) {
-        QPID_LOG(error, "Error closing BDB databases: " <<  e.what());
-    } catch (const journal::jexception& e) {
-        QPID_LOG(error, "Error: " << e.what());
-    } catch (const std::exception& e) {
-        QPID_LOG(error, "Error: " << e.what());
-    } catch (...) {
-        QPID_LOG(error, "Unknown error in BdbMessageStore::~BdbMessageStore()");
-    }
-
-    if (mgmtObject != 0)
-        mgmtObject->resourceDestroy();
-}
-
-void BdbMessageStore::truncate()
-{
-    DbTxn* txn;
-    env.txn_begin(0, &txn, 0);
-    u_int32_t count;
-
-    for (std::list<Db*>::iterator i = dbs.begin(); i != dbs.end(); i++) {
-        (*i)->truncate(txn, &count, 0);
-    }
-
-    txn->commit(0);
-    try {
-        journal::jdir::delete_dir(getJrnlBaseDir(),true);
-        journal::jdir::delete_dir(getTplBaseDir(),true);
-    }
-    catch (const journal::jexception& e) {
-        THROW_STORE_EXCEPTION(std::string("truncate() failed: ") + e.what() );
-    }
-}
-
-void BdbMessageStore::create(PersistableQueue& queue,
-                             const FieldTable& args)
-{
-    checkInit();
-    if (queue.getPersistenceId()) {
-        THROW_STORE_EXCEPTION("Queue already created: " + queue.getName());
-    }
-    JournalImpl* jQueue = 0;
-    FieldTable::ValuePtr value;
-
-    u_int16_t localFileCount = numJrnlFiles;
-    u_int32_t localFileSizeSblks  = jrnlFsizeSblks;
-
-    value = args.get ("qpid.file_count");
-    if (value.get() != 0 && !value->empty() && value->convertsTo<int>())
-        localFileCount = (u_int16_t) value->get<int>();
-
-    value = args.get ("qpid.file_size");
-    if (value.get() != 0 && !value->empty() && value->convertsTo<int>())
-        localFileSizeSblks = (u_int32_t) value->get<int>() * JRNL_RMGR_PAGE_SIZE;
-
-    {
-        // TODO: Is this mutex necessary?
-        qpid::sys::Mutex::ScopedLock sl(jrnlCreateLock);
-        jQueue = new JournalImpl(queue.getName(), getJrnlDir(queue),
-                                 std::string("JournalData"), defJournalGetEventsTimeout,
-                                 defJournalFlushTimeout);
-    }
-
-    queue.setExternalQueueStore(dynamic_cast<ExternalQueueStore*>(jQueue));
-    try {
-        // init will create the deque's for the init...
-        jQueue->initialize(localFileCount, localFileSizeSblks, wCacheNumPages, wCachePgSizeSblks);
-    } catch (const journal::jexception& e) {
-        THROW_STORE_EXCEPTION(std::string("Queue ") + queue.getName() + ": create() failed: " + e.what());
-    }
-    try {
-        if (!create(queueDb, queueIdSequence, queue)) {
-            THROW_STORE_EXCEPTION("Queue already exists: " + queue.getName());
-        }
-    } catch (const DbException& e) {
-        THROW_STORE_EXCEPTION_2("Error creating queue named  " + queue.getName(), e);
-    }
-}
-
-void BdbMessageStore::destroy(PersistableQueue& queue)
-{
-    checkInit();
-    destroy(queueDb, queue);
-    deleteBindingsForQueue(queue);
-    qpid::broker::ExternalQueueStore* eqs = queue.getExternalQueueStore();
-    if (eqs) {
-        JournalImpl* jQueue = static_cast<JournalImpl*>(eqs);
-        jQueue->delete_jrnl_files();
-        queue.setExternalQueueStore(0); // will delete the journal if exists
-    }
-}
-
-void BdbMessageStore::create(const PersistableExchange& exchange,
-                             const FieldTable& /*args*/)
-{
-    checkInit();
-    if (exchange.getPersistenceId()) {
-        THROW_STORE_EXCEPTION("Exchange already created: " + exchange.getName());
-    }
-    try {
-        if (!create(exchangeDb, exchangeIdSequence, exchange)) {
-            THROW_STORE_EXCEPTION("Exchange already exists: " + exchange.getName());
-        }
-    } catch (const DbException& e) {
-        THROW_STORE_EXCEPTION_2("Error creating exchange named " + exchange.getName(), e);
-    }
-}
-
-void BdbMessageStore::destroy(const PersistableExchange& exchange)
-{
-    checkInit();
-    destroy(exchangeDb, exchange);
-    //need to also delete bindings
-    IdDbt key(exchange.getPersistenceId());
-    bindingDb.del(0, &key, DB_AUTO_COMMIT);
-}
-
-void BdbMessageStore::create(const PersistableConfig& general)
-{
-    checkInit();
-    if (general.getPersistenceId()) {
-        THROW_STORE_EXCEPTION("General configuration item already created");
-    }
-    try {
-        if (!create(generalDb, generalIdSequence, general)) {
-            THROW_STORE_EXCEPTION("General configuration already exists");
-        }
-    } catch (const DbException& e) {
-        THROW_STORE_EXCEPTION_2("Error creating general configuration", e);
-    }
-}
-
-void BdbMessageStore::destroy(const PersistableConfig& general)
-{
-    checkInit();
-    destroy(generalDb, general);
-}
-
-bool BdbMessageStore::create(Db& db,
-                             IdSequence& seq,
-                             const Persistable& p)
-{
-    u_int64_t id (seq.next());
-    Dbt key(&id, sizeof(id));
-    BufferValue value (p);
-
-    int status;
-    TxnCtxt txn;
-    txn.begin(env, true);
-    try {
-        status = db.put(txn.get(), &key, &value, DB_NOOVERWRITE);
-        txn.commit();
-    } catch (...) {
-        txn.abort();
-        throw;
-    }
-    if (status == DB_KEYEXIST) {
-        return false;
-    } else {
-        p.setPersistenceId(id);
-        return true;
-    }
-}
-
-void BdbMessageStore::destroy(Db& db, const Persistable& p)
-{
-    IdDbt key(p.getPersistenceId());
-    db.del(0, &key, DB_AUTO_COMMIT);
-}
-
-
-void BdbMessageStore::bind(const PersistableExchange& e,
-                           const PersistableQueue& q,
-                           const std::string& k,
-                           const FieldTable& a)
-{
-    checkInit();
-    IdDbt key(e.getPersistenceId());
-    BindingDbt value(e, q, k, a);
-    TxnCtxt txn;
-    txn.begin(env, true);
-    try {
-        put(bindingDb, txn.get(), key, value);
-        txn.commit();
-    } catch (...) {
-        txn.abort();
-        throw;
-    }
-}
-
-void BdbMessageStore::unbind(const PersistableExchange& e,
-                             const PersistableQueue& q,
-                             const std::string& k,
-                             const FieldTable&)
-{
-    checkInit();
-    deleteBinding(e, q, k);
-}
-
-void BdbMessageStore::recover(RecoveryManager& registry)
-{
-    checkInit();
-    txn_list prepared;
-    recoverLockedMappings(prepared);
-
-    queue_index queues;//id->queue
-    exchange_index exchanges;//id->exchange
-    message_index messages;//id->message
-
-    TxnCtxt txn;
-    txn.begin(env, false);
-    try {
-        //read all queues, calls recoversMessages
-        recoverQueues(txn, registry, queues, prepared, messages);
-
-        //recover exchange & bindings:
-        recoverExchanges(txn, registry, exchanges);
-        recoverBindings(txn, exchanges, queues);
-
-        //recover general-purpose configuration
-        recoverGeneral(txn, registry);
-
-        txn.commit();
-    } catch (const DbException& e) {
-        txn.abort();
-        THROW_STORE_EXCEPTION_2("Error on recovery", e);
-    } catch (...) {
-        txn.abort();
-        throw;
-    }
-
-    //recover transactions:
-    for (txn_list::iterator i = prepared.begin(); i != prepared.end(); i++) {
-        if (mgmtObject != 0) {
-            mgmtObject->inc_tplTransactionDepth();
-            mgmtObject->inc_tplTxnPrepares();
-        }
-
-        std::string xid = i->xid;
-
-        // Restore data token state in TxnCtxt
-        TplRecoverMapCitr citr = tplRecoverMap.find(xid);
-        if (citr == tplRecoverMap.end()) THROW_STORE_EXCEPTION("XID not found in tplRecoverMap");
-
-        // If a record is found that is dequeued but not committed/aborted from tplStore, then a complete() call
-        // was interrupted part way through committing/aborting the impacted queues. Complete this process.
-        bool incomplTplTxnFlag = citr->second.deq_flag;
-
-        if (citr->second.tpc_flag) {
-            // Dtx (2PC) transaction
-            TPCTxnCtxt* tpcc = new TPCTxnCtxt(xid, &messageIdSequence);
-            std::auto_ptr<TPCTransactionContext> txn(tpcc);
-            tpcc->recoverDtok(citr->second.rid, xid);
-            tpcc->prepare(tplStorePtr.get());
-
-            RecoverableTransaction::shared_ptr dtx;
-            if (!incomplTplTxnFlag) dtx = registry.recoverTransaction(xid, txn);
-            if (i->enqueues.get()) {
-                for (LockedMappings::iterator j = i->enqueues->begin(); j != i->enqueues->end(); j++) {
-                    tpcc->addXidRecord(queues[j->first]->getExternalQueueStore());
-                    if (!incomplTplTxnFlag) dtx->enqueue(queues[j->first], messages[j->second]);
-                }
-            }
-            if (i->dequeues.get()) {
-                for (LockedMappings::iterator j = i->dequeues->begin(); j != i->dequeues->end(); j++) {
-                    tpcc->addXidRecord(queues[j->first]->getExternalQueueStore());
-                    if (!incomplTplTxnFlag) dtx->dequeue(queues[j->first], messages[j->second]);
-                }
-            }
-
-            if (incomplTplTxnFlag) {
-                tpcc->complete(citr->second.commit_flag);
-            }
-        } else {
-            // Local (1PC) transaction
-            boost::shared_ptr<TxnCtxt> opcc(new TxnCtxt(xid, &messageIdSequence));
-            opcc->recoverDtok(citr->second.rid, xid);
-            opcc->prepare(tplStorePtr.get());
-
-            if (i->enqueues.get()) {
-                for (LockedMappings::iterator j = i->enqueues->begin(); j != i->enqueues->end(); j++) {
-                    opcc->addXidRecord(queues[j->first]->getExternalQueueStore());
-                }
-            }
-            if (i->dequeues.get()) {
-                for (LockedMappings::iterator j = i->dequeues->begin(); j != i->dequeues->end(); j++) {
-                    opcc->addXidRecord(queues[j->first]->getExternalQueueStore());
-                }
-            }
-            if (incomplTplTxnFlag) {
-                opcc->complete(citr->second.commit_flag);
-            } else {
-                completed(*opcc.get(), citr->second.commit_flag);
-            }
-        }
-    }
-    registry.recoveryComplete();
-}
-
-void BdbMessageStore::recoverQueues(TxnCtxt& txn,
-                                    RecoveryManager& registry,
-                                    queue_index& queue_index,
-                                    txn_list& prepared,
-                                    message_index& messages)
-{
-    Cursor queues;
-    queues.open(queueDb, txn.get());
-
-    u_int64_t maxQueueId(1);
-
-    IdDbt key;
-    Dbt value;
-    //read all queues
-    while (queues.next(key, value)) {
-        Buffer buffer(reinterpret_cast<char*>(value.get_data()), value.get_size());
-        //create a Queue instance
-        RecoverableQueue::shared_ptr queue = registry.recoverQueue(buffer);
-        //set the persistenceId and update max as required
-        queue->setPersistenceId(key.id);
-
-        const char* queueName = queue->getName().c_str();
-        JournalImpl* jQueue = 0;
-        {
-            qpid::sys::Mutex::ScopedLock sl(jrnlCreateLock);
-            jQueue = new JournalImpl(queueName, getJrnlDir(queueName), std::string("JournalData"), defJournalGetEventsTimeout, defJournalFlushTimeout);
-        }
-        queue->setExternalQueueStore(dynamic_cast<ExternalQueueStore*>(jQueue));
-
-        try
-        {
-            u_int64_t thisHighestRid = 0;
-            jQueue->recover(numJrnlFiles, jrnlFsizeSblks, wCacheNumPages, wCachePgSizeSblks, &prepared, thisHighestRid, key.id); // start recovery
-            if (thisHighestRid > highestRid)
-                highestRid = thisHighestRid;
-            recoverMessages(txn, registry, queue, prepared, messages);
-            jQueue->recover_complete(); // start journal.
-        } catch (const journal::jexception& e) {
-            THROW_STORE_EXCEPTION(std::string("Queue ") + queueName + ": recoverQueues() failed: " + e.what());
-        }
-        //read all messages: done on a per queue basis if using Journal
-
-        queue_index[key.id] = queue;
-        maxQueueId = max(key.id, maxQueueId);
-    }
-
-    // NOTE: highestRid is set by both recoverQueues() and recoverTplStore() as
-    // the messageIdSequence is used for both queue journals and the tpl journal.
-    messageIdSequence.reset(highestRid + 1);
-
-    queueIdSequence.reset(maxQueueId + 1);
-}
-
-
-void BdbMessageStore::recoverExchanges(TxnCtxt& txn,
-                                       RecoveryManager& registry,
-                                       exchange_index& index)
-{
-    //TODO: this is a copy&paste from recoverQueues - refactor!
-    Cursor exchanges;
-    exchanges.open(exchangeDb, txn.get());
-
-    u_int64_t maxExchangeId(1);
-    IdDbt key;
-    Dbt value;
-    //read all exchanges
-    while (exchanges.next(key, value)) {
-        Buffer buffer(reinterpret_cast<char*>(value.get_data()), value.get_size());
-        //create a Exchange instance
-        RecoverableExchange::shared_ptr exchange = registry.recoverExchange(buffer);
-        //set the persistenceId and update max as required
-        exchange->setPersistenceId(key.id);
-        index[key.id] = exchange;
-        maxExchangeId = max(key.id, maxExchangeId);
-    }
-    exchangeIdSequence.reset(maxExchangeId + 1);
-}
-
-void BdbMessageStore::recoverBindings(TxnCtxt& txn,
-                                      exchange_index& exchanges,
-                                      queue_index& queues)
-{
-    Cursor bindings;
-    bindings.open(bindingDb, txn.get());
-
-    IdDbt key;
-    Dbt value;
-    while (bindings.next(key, value)) {
-        Buffer buffer(reinterpret_cast<char*>(value.get_data()), value.get_size());
-        if (buffer.available() < 8) {
-            QPID_LOG(error, "Not enough data for binding: " << buffer.available());
-            THROW_STORE_EXCEPTION("Not enough data for binding");
-        }
-        uint64_t queueId = buffer.getLongLong();
-        std::string queueName;
-        std::string routingkey;
-        FieldTable args;
-        buffer.getShortString(queueName);
-        buffer.getShortString(routingkey);
-        buffer.get(args);
-        exchange_index::iterator exchange = exchanges.find(key.id);
-        queue_index::iterator queue = queues.find(queueId);
-        if (exchange != exchanges.end() && queue != queues.end()) {
-            //could use the recoverable queue here rather than the name...
-            exchange->second->bind(queueName, routingkey, args);
-        } else {
-            //stale binding, delete it
-            QPID_LOG(warning, "Deleting stale binding");
-            bindings->del(0);
-        }
-    }
-}
-
-void BdbMessageStore::recoverGeneral(TxnCtxt& txn,
-                                     RecoveryManager& registry)
-{
-    Cursor items;
-    items.open(generalDb, txn.get());
-
-    u_int64_t maxGeneralId(1);
-    IdDbt key;
-    Dbt value;
-    //read all items
-    while (items.next(key, value)) {
-        Buffer buffer(reinterpret_cast<char*>(value.get_data()), value.get_size());
-        //create instance
-        RecoverableConfig::shared_ptr config = registry.recoverConfig(buffer);
-        //set the persistenceId and update max as required
-        config->setPersistenceId(key.id);
-        maxGeneralId = max(key.id, maxGeneralId);
-    }
-    generalIdSequence.reset(maxGeneralId + 1);
-}
-
-void BdbMessageStore::recoverMessages(TxnCtxt& /*txn*/,
-                                      qpid::broker::RecoveryManager& recovery,
-                                      qpid::broker::RecoverableQueue::shared_ptr& queue,
-                                      txn_list& prepared,
-                                      message_index& messages)
-{
-    size_t preambleLength = sizeof(u_int32_t)/*header size*/;
-
-    JournalImpl* jc = static_cast<JournalImpl*>(queue->getExternalQueueStore());
-    DataTokenImpl dtok;
-    size_t readSize = 0;
-    unsigned msg_count = 0;
-
-    // TODO: This optimization to skip reading if there are no enqueued messages to read
-    // breaks the python system test in phase 6 with "Exception: Cannot write lock file"
-    // Figure out what is breaking.
-    //bool read = jc->get_enq_cnt() > 0;
-    bool read = true;
-
-    void* dbuff = NULL; size_t dbuffSize = 0;
-    void* xidbuff = NULL; size_t xidbuffSize = 0;
-    bool transientFlag = false;
-    bool externalFlag = false;
-
-    dtok.set_wstate(DataTokenImpl::ENQ);
-
-    // Read the message from the Journal.
-    try {
-        unsigned aio_sleep_cnt = 0;
-        while (read) {
-            rhm::journal::iores res = jc->read_data_record(&dbuff, dbuffSize, &xidbuff, xidbuffSize, transientFlag, externalFlag, &dtok);
-            readSize = dtok.dsize();
-
-            switch (res)
-            {
-              case rhm::journal::RHM_IORES_SUCCESS: {
-                msg_count++;
-                RecoverableMessage::shared_ptr msg;
-                char* data = (char*)dbuff;
-
-                unsigned headerSize;
-                if (externalFlag) {
-                    msg = getExternMessage(recovery, dtok.rid(), headerSize); // large message external to jrnl
-                } else {
-                    headerSize = Buffer(data, preambleLength).getLong();
-                    Buffer headerBuff(data+ preambleLength, headerSize); /// do we want read size or header size ????
-                    msg = recovery.recoverMessage(headerBuff);
-                }
-                msg->setPersistenceId(dtok.rid());
-
-                u_int32_t contentOffset = headerSize + preambleLength;
-                u_int64_t contentSize = readSize - contentOffset;
-                if (msg->loadContent(contentSize) && !externalFlag) {
-                    //now read the content
-                    Buffer contentBuff(data + contentOffset, contentSize);
-                    msg->decodeContent(contentBuff);
-                }
-
-                PreparedTransaction::list::iterator i = PreparedTransaction::getLockedPreparedTransaction(prepared, queue->getPersistenceId(), dtok.rid());
-                if (i == prepared.end()) { // not in prepared list
-                    queue->recover(msg);
-                } else {
-                    u_int64_t rid = dtok.rid();
-                    std::string xid(i->xid);
-                    TplRecoverMapCitr citr = tplRecoverMap.find(xid);
-                    if (citr == tplRecoverMap.end()) THROW_STORE_EXCEPTION("XID not found in tplRecoverMap");
-
-                    // deq present in prepared list, this xid is part of incomplete txn commit/abort
-                    // or this is a 1PC txn that must be rolled forward
-                    if (citr->second.deq_flag || !citr->second.tpc_flag) {
-                        if (jc->is_enqueued(rid, true)) {
-                            // Enqueue is non-tx, dequeue tx
-                            assert(jc->is_locked(rid)); // This record MUST be locked by a txn dequeue
-                            if (!citr->second.commit_flag) {
-                                queue->recover(msg); // recover message in abort case only
-                            }
-                        } else {
-                            // Enqueue and/or dequeue tx
-                            journal::txn_map& tmap = jc->get_txn_map();
-                            journal::txn_data_list txnList = tmap.get_tdata_list(xid);
-                            bool enq = false;
-                            bool deq = false;
-                            for (journal::tdl_itr j = txnList.begin(); j<txnList.end(); j++) {
-                                if (j->_enq_flag && j->_rid == rid) enq = true;
-                                else if (!j->_enq_flag && j->_drid == rid) deq = true;
-                            }
-                            if (enq && !deq && citr->second.commit_flag) {
-                                queue->recover(msg); // recover txn message in commit case only
-                            }
-                        }
-                    } else {
-                        messages[rid] = msg;
-                    }
-                }
-
-                dtok.reset();
-                dtok.set_wstate(DataTokenImpl::ENQ);
-
-                if (xidbuff)
-                    ::free(xidbuff);
-                else if (dbuff)
-                    ::free(dbuff);
-                aio_sleep_cnt = 0;
-                break;
-              }
-              case rhm::journal::RHM_IORES_PAGE_AIOWAIT:
-                if (++aio_sleep_cnt > MAX_AIO_SLEEPS)
-                    THROW_STORE_EXCEPTION("Timeout waiting for AIO in BdbMessageStore::recoverMessages()");
-                ::usleep(AIO_SLEEP_TIME);
-                break;
-              case rhm::journal::RHM_IORES_EMPTY:
-                read = false;
-                break; // done with all messages. (add call in jrnl to test that _emap is empty.)
-              default:
-                assert("Store Error: Unexpected msg state");
-            } // switch
-        } // while
-    } catch (const journal::jexception& e) {
-        THROW_STORE_EXCEPTION(std::string("Queue ") + queue->getName() +
-                              ": recoverMessages() failed: " + e.what());
-    }
-}
-
-RecoverableMessage::shared_ptr BdbMessageStore::getExternMessage(qpid::broker::RecoveryManager& recovery,
-                                                                 uint64_t messageId,
-                                                                 unsigned& headerSize)
-{
-    RecoverableMessage::shared_ptr ret;
-    Dbt key (&messageId, sizeof(messageId));
-    size_t preamble_length = sizeof(u_int32_t); /*header size*/
-
-    BufferValue value(preamble_length, 0);
-    value.buffer.record();
-
-    TxnCtxt txn;
-    txn.begin(env, true);
-    try {
-        if (messageDb.get(txn.get(), &key, &value, 0) == DB_NOTFOUND) {
-            txn.abort();
-            THROW_STORE_EXCEPTION("Cannot load content. Message not known to store!");
-        }
-
-        //read header only to begin with
-        headerSize = value.buffer.getLong();
-
-        BufferValue header(headerSize, preamble_length);
-        if (messageDb.get(txn.get(), &key, &header, 0) == DB_NOTFOUND) {
-            txn.abort();
-            THROW_STORE_EXCEPTION("Cannot load content. Message not known to store!");
-        }
-        ret = recovery.recoverMessage(header.buffer);
-        txn.commit();
-    } catch (const DbException& e) {
-        txn.abort();
-        THROW_STORE_EXCEPTION("Unexpected BDB error in BdbMessageStore::getExternMessage(): " + std::string(e.what()));
-    } catch (...) {
-        txn.abort();
-        throw;
-    }
-    return ret;
-}
-
-int BdbMessageStore::enqueueMessage(TxnCtxt& txn,
-                                    IdDbt& msgId,
-                                    RecoverableMessage::shared_ptr& msg,
-                                    queue_index& index,
-                                    txn_list& prepared,
-                                    message_index& messages)
-{
-    Cursor mappings;
-    mappings.open(mappingDb, txn.get());
-
-    IdDbt value;
-
-    int count(0);
-    for (int status = mappings->get(&msgId, &value, DB_SET); status == 0; status = mappings->get(&msgId, &value, DB_NEXT_DUP)) {
-        if (index.find(value.id) == index.end()) {
-            QPID_LOG(warning, "Recovered message for queue that no longer exists");
-            mappings->del(0);
-        } else {
-            RecoverableQueue::shared_ptr queue = index[value.id];
-            if (PreparedTransaction::isLocked(prepared, value.id, msgId.id)) {
-                messages[msgId.id] = msg;
-            } else {
-                queue->recover(msg);
-            }
-            count++;
-        }
-    }
-    mappings.close();
-    return count;
-}
-
-void BdbMessageStore::readTplStore()
-{
-    tplRecoverMap.clear();
-    journal::txn_map& tmap = tplStorePtr->get_txn_map();
-    DataTokenImpl dtok;
-    void* dbuff = NULL; size_t dbuffSize = 0;
-    void* xidbuff = NULL; size_t xidbuffSize = 0;
-    bool transientFlag = false;
-    bool externalFlag = false;
-    bool done = false;
-    try {
-        unsigned aio_sleep_cnt = 0;
-        while (!done) {
-            dtok.reset();
-            dtok.set_wstate(DataTokenImpl::ENQ);
-            switch (tplStorePtr->read_data_record(&dbuff, dbuffSize, &xidbuff, xidbuffSize, transientFlag, externalFlag, &dtok)) {
-              case rhm::journal::RHM_IORES_SUCCESS: {
-                // Every TPL record contains both data and an XID
-                assert(dbuffSize>0);
-                assert(xidbuffSize>0);
-                std::string xid(static_cast<const char*>(xidbuff), xidbuffSize);
-                bool is2PC = *(static_cast<char*>(dbuff)) != 0;
-
-                // Check transaction details; add to recover map
-                journal::txn_data_list txnList = tmap.get_tdata_list(xid);
-                unsigned enqCnt = 0;
-                unsigned deqCnt = 0;
-                u_int64_t rid = 0;
-
-                // Assume commit (roll forward) in cases where only prepare has been called - ie only enqueue record exists.
-                // Note: will apply to both 1PC and 2PC transactions.
-                bool commitFlag = true;
-
-                for (journal::tdl_itr j = txnList.begin(); j<txnList.end(); j++) {
-                    if (j->_enq_flag) {
-                        rid = j->_rid;
-                        enqCnt++;
-                    } else {
-                        commitFlag = j->_commit_flag;
-                        deqCnt++;
-                    }
-                }
-                assert(enqCnt == 1);
-                assert(deqCnt <= 1);
-                tplRecoverMap.insert(TplRecoverMapPair(xid, TplRecoverStruct(rid, deqCnt == 1, commitFlag, is2PC)));
-
-                ::free(xidbuff);
-                aio_sleep_cnt = 0;
-                break;
-                }
-              case rhm::journal::RHM_IORES_PAGE_AIOWAIT:
-                if (++aio_sleep_cnt > MAX_AIO_SLEEPS)
-                    THROW_STORE_EXCEPTION("Timeout waiting for AIO in BdbMessageStore::recoverTplStore()");
-                ::usleep(AIO_SLEEP_TIME);
-                break;
-              case rhm::journal::RHM_IORES_EMPTY:
-                done = true;
-                break; // done with all messages. (add call in jrnl to test that _emap is empty.)
-              default:
-                assert("Store Error: Unexpected msg state");
-            } // switch
-        }
-    } catch (const journal::jexception& e) {
-        THROW_STORE_EXCEPTION(std::string("TPL recoverTplStore() failed: ") + e.what());
-    }
-}
-
-void BdbMessageStore::recoverTplStore()
-{
-    if (journal::jdir::exists(tplStorePtr->jrnl_dir() + tplStorePtr->base_filename() + ".jinf")) {
-        u_int64_t thisHighestRid;
-        tplStorePtr->recover(tplNumJrnlFiles, tplJrnlFsizeSblks, tplWCachePgSizeSblks, tplWCacheNumPages, 0, thisHighestRid, 0);
-        if (thisHighestRid > highestRid)
-            highestRid = thisHighestRid;
-
-        // Load tplRecoverMap by reading the TPL store
-        readTplStore();
-
-        tplStorePtr->recover_complete(); // start journal.
-    }
-}
-
-void BdbMessageStore::recoverLockedMappings(txn_list& txns)
-{
-    if (!tplStorePtr->is_ready())
-        recoverTplStore();
-
-    // Abort unprepaired xids and populate the locked maps
-    for (TplRecoverMapCitr i = tplRecoverMap.begin(); i != tplRecoverMap.end(); i++) {
-        LockedMappings::shared_ptr enq_ptr;
-        enq_ptr.reset(new LockedMappings);
-        LockedMappings::shared_ptr deq_ptr;
-        deq_ptr.reset(new LockedMappings);
-        txns.push_back(new PreparedTransaction(i->first, enq_ptr, deq_ptr));
-    }
-}
-
-void BdbMessageStore::collectPreparedXids(std::set<std::string>& xids)
-{
-    if (tplStorePtr->is_ready()) {
-        tplStorePtr->read_reset();
-        readTplStore();
-    } else {
-        recoverTplStore();
-    }
-    for (TplRecoverMapCitr i = tplRecoverMap.begin(); i != tplRecoverMap.end(); i++) {
-        // Discard all txns that are to be rolled forward/back and 1PC transactions
-        if (!i->second.deq_flag && i->second.tpc_flag)
-            xids.insert(i->first);
-    }
-}
-
-void BdbMessageStore::stage(const intrusive_ptr<PersistableMessage>& msg)
-{
-    checkInit();
-    TxnCtxt txn;
-    txn.begin(env, true);
-
-    u_int64_t messageId (msg->getPersistenceId());
-    if (messageId == 0 || !msg->isContentReleased()) {
-        try {
-            Dbt key (&messageId, sizeof(messageId));
-            messageId = messageIdSequence.next();
-            store(NULL, &txn, key, msg, true);
-            msg->setPersistenceId(messageId);
-            txn.commit();
-        } catch (...) {
-            txn.abort();
-            throw;
-        }
-    }
-}
-
-void BdbMessageStore::destroy(PersistableMessage& msg)
-{
-    checkInit();
-    u_int64_t messageId (msg.getPersistenceId());
-    if (messageId) {
-        Dbt key (&messageId, sizeof(messageId));
-        TxnCtxt txn;
-        txn.begin(env, true);
-        try {
-            deleteIfUnused(txn.get(), key);
-            txn.commit();
-        } catch (const DbException& e) {
-            txn.abort();
-            THROW_STORE_EXCEPTION_2("Error destroying message", e);
-        } catch (...) {
-            txn.abort();
-            throw;
-        }
-    }
-}
-
-u_int64_t BdbMessageStore::getRecordSize(Db& db,
-                                         Dbt& key)
-{
-    u_int64_t ret = 0;
-    TxnCtxt txn;
-    txn.begin(env, true);
-    try {
-        ret = getRecordSize(txn.get(), db, key);
-        txn.commit();
-    } catch (...) {
-        txn.abort();
-        throw;
-    }
-    return ret;
-}
-
-u_int64_t BdbMessageStore::getRecordSize(DbTxn* txn,
-                                         Db& db,
-                                         Dbt& key)
-{
-    Dbt peek;
-    peek.set_flags(DB_DBT_USERMEM);
-    peek.set_ulen(0);
-    try {
-        int status = db.get(txn, &key, &peek, 0);
-        if (status != DB_BUFFER_SMALL) {
-            THROW_STORE_EXCEPTION("Unexpected status code when determining record length: " + std::string(DbEnv::strerror(status)));
-        }
-    } catch (const DbMemoryException& expected) {
-        //api doc indicates may throw exception instead of status = DB_BUFFER_SMALL;
-    }
-    return peek.get_size();
-}
-
-void BdbMessageStore::appendContent(const intrusive_ptr<const PersistableMessage>& msg,
-                                    const std::string& data)
-{
-    checkInit();
-    u_int64_t messageId (msg->getPersistenceId());
-    if (messageId != 0) {
-        TxnCtxt txn;
-        txn.begin(env, true);
-        try {
-            Dbt key (&messageId, sizeof(messageId));
-            u_int64_t offset = getRecordSize(messageDb, key);
-            const int size(data.length());
-
-            //don't want to have to copy this and shouldn't need to as
-            //it will be used for reading only. but have to cast away
-            //the const-ness, which is nasty...
-            //alternative involves copying:
-            //char buffer[size];
-            //data.copy(buffer, size);
-            Dbt value((void*) data.data(), size);
-            value.set_flags(DB_DBT_USERMEM | DB_DBT_PARTIAL);
-            value.set_doff(offset);
-            value.set_dlen(size);
-            messageDb.put(txn.get(), &key, &value, 0);
-            txn.commit();
-        } catch (const DbException& e) {
-            txn.abort();
-            THROW_STORE_EXCEPTION_2("Error appending content", e);
-        } catch (...) {
-            txn.abort();
-            throw;
-        }
-    } else {
-        THROW_STORE_EXCEPTION("Cannot append content. Message not known to store!");
-    }
-}
-
-void BdbMessageStore::loadContent(const qpid::broker::PersistableQueue& queue,
-                                  const intrusive_ptr<const PersistableMessage>& msg,
-                                  std::string& data,
-                                  u_int64_t offset,
-                                  u_int32_t length)
-{
-    checkInit();
-    u_int64_t realOffset = offset + sizeof(u_int32_t)/*header length*/ + msg->encodedHeaderSize();
-    u_int64_t messageId (msg->getPersistenceId());
-
-    if (messageId != 0) {
-        try {
-            JournalImpl* jc = static_cast<JournalImpl*>(queue.getExternalQueueStore());
-            if (jc && jc->is_enqueued(messageId) ) {
-                if (jc->loadMsgContent(messageId, data, realOffset, length)) {
-                    return;
-                }
-            }
-        } catch (const journal::jexception& e) {
-            THROW_STORE_EXCEPTION(std::string("Queue ") + queue.getName() +
-                                  ": loadContent() failed: " + e.what());
-        }
-        TxnCtxt txn;
-        txn.begin(env, true);
-        try {
-            Dbt key (&messageId, sizeof(messageId));
-            char *buffer = new char[length];
-            Dbt value(buffer, length);
-            value.set_flags(DB_DBT_USERMEM | DB_DBT_PARTIAL);
-            value.set_ulen(length);
-            value.set_doff(realOffset);
-            value.set_dlen(length);
-            int status = messageDb.get(txn.get(), &key, &value, 0);
-            if (status == DB_NOTFOUND) {
-                delete [] buffer;
-                THROW_STORE_EXCEPTION("Cannot load content. Message not known to store!");
-            }
-            data.assign(buffer, value.get_size());
-            delete [] buffer;
-            txn.commit();
-        } catch (const DbException& e) {
-            txn.abort();
-            THROW_STORE_EXCEPTION_2("Error loading content", e);
-        } catch (...) {
-            txn.abort();
-            throw;
-        }
-    } else {
-        THROW_STORE_EXCEPTION("Cannot load content. Message not known to store!");
-    }
-}
-
-void BdbMessageStore::flush(const qpid::broker::PersistableQueue& queue)
-{
-    if (queue.getExternalQueueStore() == 0) return;
-    checkInit();
-    std::string qn = queue.getName();
-    try {
-        JournalImpl* jc = static_cast<JournalImpl*>(queue.getExternalQueueStore());
-        if (jc) {
-            // TODO: check if this result should be used...
-            /*rhm::journal::iores res =*/ jc->flush();
-        }
-    } catch (const journal::jexception& e) {
-        THROW_STORE_EXCEPTION(std::string("Queue ") + qn + ": flush() failed: " + e.what() );
-    }
-}
-
-void BdbMessageStore::enqueue(TransactionContext* ctxt,
-                              const intrusive_ptr<PersistableMessage>& msg,
-                              const PersistableQueue& queue)
-{
-    checkInit();
-    u_int64_t queueId (queue.getPersistenceId());
-    u_int64_t messageId (msg->getPersistenceId());
-    if (queueId == 0) {
-        THROW_STORE_EXCEPTION("Queue not created: " + queue.getName());
-    }
-    Dbt key (&messageId, sizeof(messageId));
-
-    TxnCtxt implicit;
-    TxnCtxt* txn = 0;
-    if (ctxt) {
-        txn = check(ctxt);
-    } else {
-        txn = &implicit;
-    }
-
-    bool newId = false;
-    if (messageId == 0) {
-        messageId = messageIdSequence.next();
-        msg->setPersistenceId(messageId);
-        newId = true;
-    }
-    store(&queue, txn, key, msg, newId);
-
-    // add queue* to the txn map..
-    if (ctxt) txn->addXidRecord(queue.getExternalQueueStore());
-}
-
-void BdbMessageStore::store(const PersistableQueue* queue,
-                            TxnCtxt* txn, Dbt& messageId,
-                            const intrusive_ptr<PersistableMessage>& message,
-                            bool newId)
-{
-    u_int32_t headerSize = message->encodedHeaderSize();
-    u_int64_t size = message->encodedSize() + sizeof(u_int32_t);
-    char* buff = 0;
-    if (!message->isContentReleased() )
-    {
-        buff = static_cast<char*>(::alloca(size)); // long + headers + content
-        Buffer buffer(buff,size);
-        buffer.putLong(headerSize);
-        message->encode(buffer);
-    }
-
-    try {
-        if (queue) {
-            boost::intrusive_ptr<DataTokenImpl> dtokp(new DataTokenImpl);
-            dtokp->addRef();
-            dtokp->setSourceMessage(message);
-            dtokp->set_external_rid(true);
-            dtokp->set_rid(message->getPersistenceId()); // set the messageID into the Journal header (record-id)
-
-            JournalImpl* jc = static_cast<JournalImpl*>(queue->getExternalQueueStore());
-            if (txn->getXid().empty()) {
-                if (message->isContentReleased()) {
-                    jc->enqueue_extern_data_record(size, dtokp.get(), false);
-                } else {
-                    jc->enqueue_data_record(buff, size, size, dtokp.get(), false);
-                }
-            } else {
-                if (message->isContentReleased()) {
-                    jc->enqueue_extern_txn_data_record(size, dtokp.get(), txn->getXid(), false);
-                } else {
-                    jc->enqueue_txn_data_record(buff, size, size, dtokp.get(), txn->getXid(), false);
-                }
-            }
-        } else {
-            /// cct message db
-            if (newId) {  // only store in Bd if first time message is stored
-                Dbt data(buff,size);
-                messageDb.put(txn->get(), &messageId, &data, DB_NOOVERWRITE);
-            }
-        }
-    } catch (const journal::jexception& e) {
-        THROW_STORE_EXCEPTION(std::string("Queue ") + queue->getName() + ": store() failed: " +
-                              e.what());
-    }
-}
-
-void BdbMessageStore::dequeue(TransactionContext* ctxt,
-                              const intrusive_ptr<PersistableMessage>& msg,
-                              const PersistableQueue& queue)
-{
-    checkInit();
-    u_int64_t queueId (queue.getPersistenceId());
-    u_int64_t messageId (msg->getPersistenceId());
-    if (messageId == 0) {
-        THROW_STORE_EXCEPTION("Error dequeing message, persistence id not set");
-    }
-    if (queueId == 0) {
-        THROW_STORE_EXCEPTION("Queue not created: " + queue.getName());
-    }
-
-    TxnCtxt implicit;
-    TxnCtxt* txn = 0;
-    if (ctxt) {
-        txn = check(ctxt);
-    } else {
-        txn = &implicit;
-    }
-
-    // add queue* to the txn map..
-    if (ctxt) txn->addXidRecord(queue.getExternalQueueStore());
-    async_dequeue(ctxt, msg, queue);
-
-    msg->dequeueComplete();
-}
-
-void BdbMessageStore::async_dequeue(TransactionContext* ctxt,
-                                    const intrusive_ptr<PersistableMessage>& msg,
-                                    const PersistableQueue& queue)
-{
-    boost::intrusive_ptr<DataTokenImpl> ddtokp(new DataTokenImpl);
-    ddtokp->addRef();
-    ddtokp->setSourceMessage(msg);
-    ddtokp->set_external_rid(true);
-    ddtokp->set_rid(messageIdSequence.next());
-    ddtokp->set_dequeue_rid(msg->getPersistenceId());
-    ddtokp->set_wstate(DataTokenImpl::ENQ);
-    std::string tid;
-    if (ctxt) {
-        TxnCtxt* txn = check(ctxt);
-        tid = txn->getXid();
-    }
-    try {
-        JournalImpl* jc = static_cast<JournalImpl*>(queue.getExternalQueueStore());
-        if (tid.empty()) {
-            jc->dequeue_data_record(ddtokp.get());
-        } else {
-            jc->dequeue_txn_data_record(ddtokp.get(), tid);
-        }
-    } catch (const journal::jexception& e) {
-        THROW_STORE_EXCEPTION(std::string("Queue ") + queue.getName() + ": async_dequeue() failed: " + e.what());
-    }
-}
-
-u_int32_t BdbMessageStore::outstandingQueueAIO(const qpid::broker::PersistableQueue& /*queue*/)
-{
-    checkInit();
-    return 0;
-}
-
-bool BdbMessageStore::deleteIfUnused(DbTxn* txn,
-                                     Dbt& messageId)
-{
-    Cursor cursor;
-    cursor.open(mappingDb, txn);
-    return deleteIfUnused(cursor, txn, messageId);
-}
-
-bool BdbMessageStore::deleteIfUnused(Cursor& cursor,
-                                     DbTxn* txn,
-                                     Dbt& messageId)
-{
-    if (isUnused(cursor, messageId)) {
-        messageDb.del(txn, &messageId, 0);
-        return true;
-    } else {
-        return false;
-    }
-}
-
-bool BdbMessageStore::isUnused(Cursor& cursor, Dbt& messageId)
-{
-    Dbt empty;
-    int status = cursor->get(&messageId, &empty, DB_SET);
-    if (status == DB_NOTFOUND) {
-        return true;
-    } else if (status == 0) {
-        return false;
-    } else {
-        THROW_STORE_EXCEPTION("Dequeue failed (in isUnused()) with status = " + status);
-    }
-}
-
-void BdbMessageStore::completed(TxnCtxt& txn,
-                                bool commit)
-{
-    try {
-        chkTplStoreInit(); // Late initialize (if needed)
-
-        // Nothing to do if not prepared
-        if (txn.getDtok()->is_enqueued()) {
-            txn.incrDtokRef();
-            DataTokenImpl* dtokp = txn.getDtok();
-            dtokp->set_dequeue_rid(dtokp->rid());
-            dtokp->set_rid(messageIdSequence.next());
-            tplStorePtr->dequeue_txn_data_record(txn.getDtok(), txn.getXid(), commit);
-        }
-        txn.complete(commit);
-        if (mgmtObject != 0) {
-            mgmtObject->dec_tplTransactionDepth();
-            if (commit)
-                mgmtObject->inc_tplTxnCommits();
-            else
-                mgmtObject->inc_tplTxnAborts();
-        }
-    } catch (const std::exception& e) {
-        QPID_LOG(error, "Error completing xid " << txn.getXid() << ": " << e.what());
-        throw;
-    }
-}
-
-auto_ptr<TransactionContext> BdbMessageStore::begin()
-{
-    checkInit();
-    // pass sequence number for c/a
-    return auto_ptr<TransactionContext>(new TxnCtxt(&messageIdSequence));
-}
-
-std::auto_ptr<qpid::broker::TPCTransactionContext> BdbMessageStore::begin(const std::string& xid)
-{
-    checkInit();
-    IdSequence* jtx = &messageIdSequence;
-    // pass sequence number for c/a
-    return auto_ptr<TPCTransactionContext>(new TPCTxnCtxt(xid, jtx));
-}
-
-void BdbMessageStore::prepare(qpid::broker::TPCTransactionContext& ctxt)
-{
-    checkInit();
-    TxnCtxt* txn = dynamic_cast<TxnCtxt*>(&ctxt);
-    if(!txn) throw InvalidTransactionContextException();
-    localPrepare(txn);
-}
-
-void BdbMessageStore::localPrepare(TxnCtxt* ctxt)
-{
-    try {
-        chkTplStoreInit(); // Late initialize (if needed)
-
-        // This sync is requred to ensure multi-queue atomicity - ie all txn data
-        // must hit the disk on *all* queues before the TPL prepare (enq) is written.
-        ctxt->sync();
-
-        ctxt->incrDtokRef();
-        DataTokenImpl* dtokp = ctxt->getDtok();
-        dtokp->set_external_rid(true);
-        dtokp->set_rid(messageIdSequence.next());
-        char tpcFlag = static_cast<char>(ctxt->isTPC());
-        tplStorePtr->enqueue_txn_data_record(&tpcFlag, sizeof(char), sizeof(char), dtokp, ctxt->getXid(), false);
-        ctxt->prepare(tplStorePtr.get());
-        // make sure all the data is written to disk before returning
-        ctxt->sync();
-        if (mgmtObject != 0) {
-            mgmtObject->inc_tplTransactionDepth();
-            mgmtObject->inc_tplTxnPrepares();
-        }
-    } catch (const std::exception& e) {
-        QPID_LOG(error, "Error preparing xid " << ctxt->getXid() << ": " << e.what());
-        throw;
-    }
-}
-
-void BdbMessageStore::commit(TransactionContext& ctxt)
-{
-    checkInit();
-    TxnCtxt* txn(check(&ctxt));
-    if (!txn->isTPC()) {
-        if (txn->impactedQueuesEmpty()) return;
-        localPrepare(dynamic_cast<TxnCtxt*>(txn));
-    }
-    completed(*dynamic_cast<TxnCtxt*>(txn), true);
-}
-
-void BdbMessageStore::abort(TransactionContext& ctxt)
-{
-    checkInit();
-    TxnCtxt* txn(check(&ctxt));
-    if (!txn->isTPC()) {
-        if (txn->impactedQueuesEmpty()) return;
-        localPrepare(dynamic_cast<TxnCtxt*>(txn));
-    }
-    completed(*dynamic_cast<TxnCtxt*>(txn), false);
-}
-
-TxnCtxt* BdbMessageStore::check(TransactionContext* ctxt)
-{
-    TxnCtxt* txn = dynamic_cast<TxnCtxt*>(ctxt);
-    if(!txn) throw InvalidTransactionContextException();
-    return txn;
-}
-
-void BdbMessageStore::put(Db& db,
-                          DbTxn* txn,
-                          Dbt& key,
-                          Dbt& value)
-{
-    try {
-        int status = db.put(txn, &key, &value, DB_NODUPDATA);
-        if (status == DB_KEYEXIST) {
-            THROW_STORE_EXCEPTION("duplicate data");
-        } else if (status) {
-            THROW_STORE_EXCEPTION(DbEnv::strerror(status));
-        }
-    } catch (const DbException& e) {
-        THROW_STORE_EXCEPTION(e.what());
-    }
-}
-
-bool BdbMessageStore::deleteKeyValuePair(Db& db,
-                                         DbTxn* txn,
-                                         Dbt& key,
-                                         Dbt& value)
-{
-    Cursor cursor;
-    cursor.open(db, txn);
-    int status = cursor->get(&key, &value, DB_GET_BOTH | DB_RMW);
-    if (status == 0) {
-        cursor->del(0);
-        return true;
-    } else if (status == DB_NOTFOUND) {
-        return false;
-    } else {
-        THROW_STORE_EXCEPTION("Deletion failed: " + std::string(DbEnv::strerror(status)));
-    }
-}
-
-void BdbMessageStore::deleteBindingsForQueue(const PersistableQueue& queue)
-{
-    TxnCtxt txn;
-    txn.begin(env, true);
-    try {
-        {
-            Cursor bindings;
-            bindings.open(bindingDb, txn.get());
-
-            IdDbt key;
-            Dbt value;
-            while (bindings.next(key, value)) {
-                Buffer buffer(reinterpret_cast<char*>(value.get_data()), value.get_size());
-                if (buffer.available() < 8) {
-                    THROW_STORE_EXCEPTION("Not enough data for binding");
-                }
-                uint64_t queueId = buffer.getLongLong();
-                if (queue.getPersistenceId() == queueId) {
-                    bindings->del(0);
-                    QPID_LOG(debug, "Deleting binding for " << queue.getName() << " " << key.id << "->" << queueId);
-                }
-            }
-        }
-        txn.commit();
-    } catch (const std::exception& e) {
-        txn.abort();
-        THROW_STORE_EXCEPTION_2("Error deleting bindings", e.what());
-    } catch (...) {
-        txn.abort();
-        throw;
-    }
-    QPID_LOG(debug, "Deleted all bindings for " << queue.getName() << ":" << queue.getPersistenceId());
-}
-
-void BdbMessageStore::deleteBinding(const PersistableExchange& exchange,
-                                    const PersistableQueue& queue,
-                                    const std::string& bkey)
-{
-    TxnCtxt txn;
-    txn.begin(env, true);
-    try {
-        {
-            Cursor bindings;
-            bindings.open(bindingDb, txn.get());
-
-            IdDbt key(exchange.getPersistenceId());
-            Dbt value;
-
-            for (int status = bindings->get(&key, &value, DB_SET); status == 0; status = bindings->get(&key, &value, DB_NEXT_DUP)) {
-                Buffer buffer(reinterpret_cast<char*>(value.get_data()), value.get_size());
-                if (buffer.available() < 8) {
-                    THROW_STORE_EXCEPTION("Not enough data for binding");
-                }
-                uint64_t queueId = buffer.getLongLong();
-                if (queue.getPersistenceId() == queueId) {
-                    std::string q;
-                    std::string k;
-                    buffer.getShortString(q);
-                    buffer.getShortString(k);
-                    if (bkey == k) {
-                        bindings->del(0);
-                        QPID_LOG(debug, "Deleting binding for " << queue.getName() << " " << key.id << "->" << queueId);
-                    }
-                }
-            }
-        }
-        txn.commit();
-    } catch (const std::exception& e) {
-        txn.abort();
-        THROW_STORE_EXCEPTION_2("Error deleting bindings", e.what());
-    } catch (...) {
-        txn.abort();
-        throw;
-    }
-}
-
-std::string BdbMessageStore::getJrnlBaseDir()
-{
-    std::stringstream dir;
-    dir << storeDir << "/rhm/jrnl/" ;
-    return dir.str();
-}
-
-std::string BdbMessageStore::getBdbBaseDir()
-{
-    std::stringstream dir;
-    dir << storeDir << "/rhm/dat/" ;
-    return dir.str();
-}
-
-std::string BdbMessageStore::getTplBaseDir()
-{
-    std::stringstream dir;
-    dir << storeDir << "/rhm/tpl/" ;
-    return dir.str();
-}
-
-std::string BdbMessageStore::getJrnlDir(const qpid::broker::PersistableQueue& queue) //for exmaple /var/rhm/ + queueDir/
-{
-    return getJrnlDir(queue.getName().c_str());
-}
-
-std::string BdbMessageStore::getJrnlDir(const char* queueName) //for exmaple /var/rhm/ + queueDir/
-{
-    std::stringstream dir;
-    dir << getJrnlBaseDir() << std::hex << std::setfill('0') << std::setw(4);
-    u_int32_t count = 0;
-    for (u_int32_t i = 0; i < strlen(queueName); i++) {
-        count += queueName[i];
-    }
-    dir << (count % 29); // Use a prime number for better distribution across dirs
-    dir << "/" << queueName << "/";
-    return dir.str();
-}
-
-BdbMessageStore::Options::Options(const std::string& name) :
-                                  qpid::Options(name),
-                                  numJrnlFiles(defNumJrnlFiles),
-                                  jrnlFsizePgs(defJrnlFileSizePgs),
-                                  wCachePageSizeKib(defWCachePageSize),
-                                  tplNumJrnlFiles(defTplNumJrnlFiles),
-                                  tplJrnlFsizePgs(defTplJrnlFileSizePgs),
-                                  tplWCachePageSizeKib(defTplWCachePageSize)
-{
-    addOptions()
-        ("store-dir", qpid::optValue(storeDir, "DIR"),
-         "Store directory location for persistence (instead of using --data-dir value). "
-         "Must be supplied if --no-data-dir is also used.")
-        ("num-jfiles", qpid::optValue(numJrnlFiles, "N"),
-         "Default number of files for each journal instance")
-        ("jfile-size-pgs", qpid::optValue(jrnlFsizePgs, "N"),
-         "Default size for each journal file in multiples of read pages (1 read page = 64kiB)")
-        ("wcache-page-size", qpid::optValue(wCachePageSizeKib, "N"),
-         "Size of the pages in the write page cache in KiB. "
-         "Allowable values - powers of 2: 1, 2, 4, ... , 128. "
-         "Lower values decrease latency at the expense of throughput.")
-        ("tpl-num-jfiles", qpid::optValue(tplNumJrnlFiles, "N"),
-         "Number of files for transaction prepared list journal instance")
-        ("tpl-jfile-size-pgs", qpid::optValue(tplJrnlFsizePgs, "N"),
-         "Size of each transaction prepared list journal file in multiples of read pages (1 read page = 64kiB)")
-        ("tpl-wcache-page-size", qpid::optValue(tplWCachePageSizeKib, "N"),
-         "Size of the pages in the transaction prepared list write page cache in KiB. "
-         "Allowable values - powers of 2: 1, 2, 4, ... , 128. "
-         "Lower values decrease latency at the expense of throughput.")
-        ;
-}

Deleted: store/trunk/cpp/lib/BdbMessageStore.h
===================================================================
--- store/trunk/cpp/lib/BdbMessageStore.h	2008-09-09 13:39:28 UTC (rev 2432)
+++ store/trunk/cpp/lib/BdbMessageStore.h	2008-09-09 19:25:47 UTC (rev 2433)
@@ -1,348 +0,0 @@
-/*
-  Copyright (C) 2007 Red Hat Software
-
-  This file is part of Red Hat Messaging.
-
-  Red Hat Messaging is free software; you can redistribute it and/or
-  modify it under the terms of the GNU Lesser General Public
-  License as published by the Free Software Foundation; either
-  version 2.1 of the License, or (at your option) any later version.
-
-  This library is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public
-  License along with this library; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
-  USA
-
-  The GNU Lesser General Public License is available in the file COPYING.
-*/
-
-#ifndef _BdbMessageStore_
-#define _BdbMessageStore_
-
-#include <string>
-
-#include "db-inc.h"
-#include "Cursor.h"
-#include "IdDbt.h"
-#include "IdSequence.h"
-#include "JournalImpl.h"
-#include "jrnl/jcfg.hpp"
-#include "PreparedTransaction.h"
-#include "qpid/broker/Broker.h"
-#include "qpid/broker/MessageStore.h"
-#include "qpid/management/Manageable.h"
-#include "Store.h"
-#include "TxnCtxt.h"
-
-// Assume DB_VERSION_MAJOR == 4
-#if (DB_VERSION_MINOR == 2)
-#include <errno.h>
-#define DB_BUFFER_SMALL ENOMEM
-#endif
-
-namespace rhm {
-namespace bdbstore {
-
-/**
- * An implementation of the MessageStore interface based on Berkeley DB
- */
-class BdbMessageStore : public qpid::broker::MessageStore, public qpid::management::Manageable
-{
-  protected:
-    typedef std::map<u_int64_t, qpid::broker::RecoverableQueue::shared_ptr> queue_index;
-    typedef std::map<u_int64_t, qpid::broker::RecoverableExchange::shared_ptr> exchange_index;
-    typedef std::map<u_int64_t, qpid::broker::RecoverableMessage::shared_ptr> message_index;
-
-    typedef LockedMappings::map txn_lock_map;
-    typedef boost::ptr_list<PreparedTransaction> txn_list;
-
-    // Structs for Transaction Recover List (TPL) recover state
-    struct TplRecoverStruct {
-        u_int64_t rid; // rid of TPL record
-        bool deq_flag;
-        bool commit_flag;
-        bool tpc_flag;
-        TplRecoverStruct(const u_int64_t _rid, const bool _deq_flag, const bool _commit_flag, const bool _tpc_flag);
-    };
-    typedef TplRecoverStruct TplRecover;
-    typedef std::pair<std::string, TplRecover> TplRecoverMapPair;
-    typedef std::map<std::string, TplRecover> TplRecoverMap;
-    typedef TplRecoverMap::const_iterator TplRecoverMapCitr;
-
-    // Default store settings
-    static const u_int16_t defNumJrnlFiles = 8;
-    static const u_int32_t defJrnlFileSizePgs = 24;
-    static const u_int32_t defWCachePageSize = JRNL_WMGR_DEF_PAGE_SIZE * JRNL_DBLK_SIZE * JRNL_SBLK_SIZE / 1024;
-    static const u_int16_t defTplNumJrnlFiles = 8;
-    static const u_int32_t defTplJrnlFileSizePgs = 24;
-    static const u_int32_t defTplWCachePageSize = defWCachePageSize / 8;
-
-    std::list<Db*> dbs;
-    DbEnv env;
-    Db queueDb;
-    Db configDb;
-    Db exchangeDb;
-    Db messageDb;
-    Db mappingDb;
-    Db bindingDb;
-    Db generalDb;
-
-    // Pointer to Transaction Prepared List (TPL) journal instance
-    boost::shared_ptr<TplJournalImpl> tplStorePtr;
-    TplRecoverMap tplRecoverMap;
-
-    IdSequence queueIdSequence;
-    IdSequence exchangeIdSequence;
-    IdSequence generalIdSequence;
-    IdSequence messageIdSequence;
-    std::string storeDir;
-    u_int16_t numJrnlFiles;
-    u_int32_t jrnlFsizeSblks;
-    u_int32_t wCachePgSizeSblks;
-    u_int16_t wCacheNumPages;
-    u_int16_t tplNumJrnlFiles;
-    u_int32_t tplJrnlFsizeSblks;
-    u_int32_t tplWCachePgSizeSblks;
-    u_int16_t tplWCacheNumPages;
-    u_int64_t highestRid;
-    bool isInit;
-    const char* envPath;
-    static qpid::sys::Duration defJournalGetEventsTimeout;
-    static qpid::sys::Duration defJournalFlushTimeout;
-    qpid::management::Store* mgmtObject;
-    qpid::sys::Mutex jrnlCreateLock;
-
-    // Parameter validation and calculation
-    static u_int16_t chkJrnlNumFilesParam(const u_int16_t param,
-                                          const std::string paramName);
-    static u_int32_t chkJrnlFileSizeParam(const u_int32_t param,
-                                          const std::string paramName);
-    static u_int32_t chkJrnlWrPageCacheSize(const u_int32_t param,
-                                            const std::string paramName);
-    static u_int16_t getJrnlWrNumPages(const u_int32_t wrPageSizeKib);
-
-    void recoverQueues(TxnCtxt& txn,
-                       qpid::broker::RecoveryManager& recovery,
-                       queue_index& index,
-                       txn_list& locked,
-                       message_index& messages);
-    void recoverMessages(TxnCtxt& txn,
-                         qpid::broker::RecoveryManager& recovery,
-                         queue_index& index,
-                         txn_list& locked,
-                         message_index& prepared);
-    void recoverMessages(TxnCtxt& txn,
-                         qpid::broker::RecoveryManager& recovery,
-                         qpid::broker::RecoverableQueue::shared_ptr& queue,
-                         txn_list& locked,
-                         message_index& prepared);
-    qpid::broker::RecoverableMessage::shared_ptr getExternMessage(qpid::broker::RecoveryManager& recovery,
-                                                                  uint64_t mId,
-                                                                  unsigned& headerSize);
-    void recoverExchanges(TxnCtxt& txn,
-                          qpid::broker::RecoveryManager& recovery,
-                          exchange_index& index);
-    void recoverBindings(TxnCtxt& txn,
-                         exchange_index& exchanges,
-                         queue_index& queues);
-    void recoverGeneral(TxnCtxt& txn,
-                        qpid::broker::RecoveryManager& recovery);
-    int enqueueMessage(TxnCtxt& txn,
-                       IdDbt& msgId,
-                       qpid::broker::RecoverableMessage::shared_ptr& msg,
-                       queue_index& index,
-                       txn_list& locked,
-                       message_index& prepared);
-    void readTplStore();
-    void recoverTplStore();
-    void recoverLockedMappings(txn_list& txns);
-    TxnCtxt* check(qpid::broker::TransactionContext* ctxt);
-    void store(const qpid::broker::PersistableQueue* queue,
-               TxnCtxt* txn,
-               Dbt& messageId,
-               const boost::intrusive_ptr<qpid::broker::PersistableMessage>& message,
-               bool newId);
-    void async_dequeue(qpid::broker::TransactionContext* ctxt,
-                       const boost::intrusive_ptr<qpid::broker::PersistableMessage>& msg,
-                       const qpid::broker::PersistableQueue& queue);
-    bool deleteIfUnused(Cursor& cursor,
-                        DbTxn* txn,
-                        Dbt& messageId);
-    bool deleteIfUnused(DbTxn* txn,
-                        Dbt& messageId);
-    bool isUnused(Cursor& cursor,
-                  Dbt& messageId);
-    void destroy(Db& db,
-                 const qpid::broker::Persistable& p);
-    bool create(Db& db,
-                IdSequence& seq,
-                const qpid::broker::Persistable& p);
-    void completed(TxnCtxt& txn,
-                   bool commit);
-    void record2pcOp(Db& db,
-                     TPCTxnCtxt& txn,
-                     u_int64_t messageId,
-                     u_int64_t queueId);
-    void deleteBindingsForQueue(const qpid::broker::PersistableQueue& queue);
-    void deleteBinding(const qpid::broker::PersistableExchange& exchange,
-                       const qpid::broker::PersistableQueue& queue,
-                       const std::string& key);
-
-    u_int64_t getRecordSize(Db& db,
-                            Dbt& key);
-    u_int64_t getRecordSize(DbTxn* txn,
-                            Db& db,
-                            Dbt& key);
-    void put(Db& db,
-             DbTxn* txn,
-             Dbt& key,
-             Dbt& value);
-    bool deleteKeyValuePair(Db& db,
-                            DbTxn* txn,
-                            Dbt& key,
-                            Dbt& value);
-    void open(Db& db,
-              DbTxn* txn,
-              const char* file,
-              bool dupKey);
-
-    // journal functions
-    void createJrnlQueue(const qpid::broker::PersistableQueue& queue);
-    std::string getJrnlDir(const qpid::broker::PersistableQueue& queue); //for exmaple /var/rhm/ + queueDir/
-    std::string getJrnlDir(const char* queueName);
-    std::string getJrnlBaseDir();
-    std::string getBdbBaseDir();
-    std::string getTplBaseDir();
-    inline void checkInit() {
-        // TODO: change the default dir to ~/.qpidd
-        if (!isInit) init("/tmp", defNumJrnlFiles, defJrnlFileSizePgs, defWCachePageSize); isInit = true;
-    }
-    void chkTplStoreInit();
-
-    // debug aid for printing XIDs that may contain non-printable chars
-    static std::string xid2str(const std::string xid) {
-        std::ostringstream oss;
-        oss << std::hex << std::setfill('0');
-        for (unsigned i=0; i<xid.size(); i++) {
-            if (isprint(xid[i]))
-                oss << xid[i];
-            else
-                oss << "/" << std::setw(2) << (int)((char)xid[i]);
-        }
-        return oss.str();
-    }
-
-  public:
-    struct Options : public qpid::Options {
-        Options(const std::string& name="Store Options");
-        std::string clusterName;
-        std::string storeDir;
-        u_int16_t numJrnlFiles;
-        u_int32_t jrnlFsizePgs;
-        u_int32_t wCachePageSizeKib;
-        u_int16_t tplNumJrnlFiles;
-        u_int32_t tplJrnlFsizePgs;
-        u_int32_t tplWCachePageSizeKib;
-    };
-
-    typedef boost::shared_ptr<BdbMessageStore> shared_ptr;
-
-    BdbMessageStore(const char* envpath = 0);
-
-    virtual ~BdbMessageStore();
-
-    bool init(const qpid::Options* options);
-
-    bool init(const std::string& dir,
-              u_int16_t jfiles = defNumJrnlFiles,
-              u_int32_t jfileSizePgs = defJrnlFileSizePgs,
-              u_int32_t wCachePageSize = defWCachePageSize,
-              u_int16_t tplJfiles = defTplNumJrnlFiles,
-              u_int32_t tplJfileSizePgs = defTplJrnlFileSizePgs,
-              u_int32_t tplWCachePageSize = defTplWCachePageSize);
-
-    void initManagement (qpid::broker::Broker* broker);
-
-    void truncate();
-
-    void create(qpid::broker::PersistableQueue& queue,
-                const qpid::framing::FieldTable& args);
-
-    void destroy(qpid::broker::PersistableQueue& queue);
-
-    void create(const qpid::broker::PersistableExchange& queue,
-                const qpid::framing::FieldTable& args);
-
-    void destroy(const qpid::broker::PersistableExchange& queue);
-
-    void bind(const qpid::broker::PersistableExchange& exchange,
-              const qpid::broker::PersistableQueue& queue,
-              const std::string& key,
-              const qpid::framing::FieldTable& args);
-
-    void unbind(const qpid::broker::PersistableExchange& exchange,
-                const qpid::broker::PersistableQueue& queue,
-                const std::string& key,
-                const qpid::framing::FieldTable& args);
-
-    void create(const qpid::broker::PersistableConfig& config);
-
-    void destroy(const qpid::broker::PersistableConfig& config);
-
-    void recover(qpid::broker::RecoveryManager& queues);
-
-    void stage(const boost::intrusive_ptr<qpid::broker::PersistableMessage>& msg);
-
-    void destroy(qpid::broker::PersistableMessage& msg);
-
-    void appendContent(const boost::intrusive_ptr<const qpid::broker::PersistableMessage>& msg,
-                       const std::string& data);
-
-    void loadContent(const qpid::broker::PersistableQueue& queue,
-                     const boost::intrusive_ptr<const qpid::broker::PersistableMessage>& msg,
-                     std::string& data,
-                     u_int64_t offset,
-                     u_int32_t length);
-
-    void enqueue(qpid::broker::TransactionContext* ctxt,
-                 const boost::intrusive_ptr<qpid::broker::PersistableMessage>& msg,
-                 const qpid::broker::PersistableQueue& queue);
-
-    void dequeue(qpid::broker::TransactionContext* ctxt,
-                 const boost::intrusive_ptr<qpid::broker::PersistableMessage>& msg,
-                 const qpid::broker::PersistableQueue& queue);
-
-    void flush(const qpid::broker::PersistableQueue& queue);
-
-    u_int32_t outstandingQueueAIO(const qpid::broker::PersistableQueue& queue);
-
-    void collectPreparedXids(std::set<std::string>& xids);
-
-    std::auto_ptr<qpid::broker::TransactionContext> begin();
-
-    std::auto_ptr<qpid::broker::TPCTransactionContext> begin(const std::string& xid);
-
-    void prepare(qpid::broker::TPCTransactionContext& ctxt);
-
-    void localPrepare(TxnCtxt* ctxt);
-
-    void commit(qpid::broker::TransactionContext& ctxt);
-
-    void abort(qpid::broker::TransactionContext& ctxt);
-
-    qpid::management::ManagementObject* GetManagementObject (void) const
-        { return mgmtObject; }
-
-    inline qpid::management::Manageable::status_t ManagementMethod (u_int32_t, qpid::management::Args&)
-        { return qpid::management::Manageable::STATUS_OK; }
-}; // class BdbMessageStore
-
-} // namespace bdbstore
-} // namespace rhm
-
-#endif

Modified: store/trunk/cpp/lib/Makefile.am
===================================================================
--- store/trunk/cpp/lib/Makefile.am	2008-09-09 13:39:28 UTC (rev 2432)
+++ store/trunk/cpp/lib/Makefile.am	2008-09-09 19:25:47 UTC (rev 2433)
@@ -16,7 +16,6 @@
 
 libbdbstore_la_SOURCES =        \
   StorePlugin.cpp               \
-  BdbMessageStore.cpp           \
   BindingDbt.cpp                \
   BufferValue.cpp               \
   DataTokenImpl.cpp             \
@@ -24,9 +23,9 @@
   IdPairDbt.cpp                 \
   IdSequence.cpp                \
   JournalImpl.cpp               \
+  MessageStoreImpl.cpp          \
   PreparedTransaction.cpp       \
   StringDbt.cpp                 \
-  BdbMessageStore.h             \
   BindingDbt.h                  \
   BufferValue.h                 \
   Cursor.h                      \
@@ -35,6 +34,7 @@
   IdPairDbt.h                   \
   IdSequence.h                  \
   JournalImpl.h                 \
+  MessageStoreImpl.h            \
   PreparedTransaction.h         \
   StoreException.h              \
   StringDbt.h                   \

Copied: store/trunk/cpp/lib/MessageStoreImpl.cpp (from rev 2432, store/trunk/cpp/lib/BdbMessageStore.cpp)
===================================================================
--- store/trunk/cpp/lib/MessageStoreImpl.cpp	                        (rev 0)
+++ store/trunk/cpp/lib/MessageStoreImpl.cpp	2008-09-09 19:25:47 UTC (rev 2433)
@@ -0,0 +1,1693 @@
+/*
+  Copyright (C) 2007 Red Hat Software
+
+  This file is part of Red Hat Messaging.
+
+  Red Hat Messaging is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+  USA
+
+  The GNU Lesser General Public License is available in the file COPYING.
+*/
+
+#include "MessageStoreImpl.h"
+
+#include "BindingDbt.h"
+#include "BufferValue.h"
+#include "IdPairDbt.h"
+#include "jrnl/txn_map.hpp"
+#include "qpid/log/Statement.h"
+#include "PackageMrgstore.h"
+
+#define MAX_AIO_SLEEPS 1000 // ~1 second
+#define AIO_SLEEP_TIME 1000 // 1 milisecond
+
+using namespace rhm::bdbstore;
+using namespace qpid::broker;
+using boost::static_pointer_cast;
+using boost::intrusive_ptr;
+
+using std::auto_ptr;
+using std::max;
+using qpid::framing::Buffer;
+using qpid::framing::FieldTable;
+using qpid::management::ManagementAgent;
+
+static const u_int8_t MESSAGE_MESSAGE = 1;
+static const u_int8_t BASIC_MESSAGE = 2;
+qpid::sys::Duration MessageStoreImpl::defJournalGetEventsTimeout(10 * qpid::sys::TIME_MSEC); // 10ms
+qpid::sys::Duration MessageStoreImpl::defJournalFlushTimeout(500 * qpid::sys::TIME_MSEC); // 0.5s
+qpid::sys::Mutex TxnCtxt::globalSerialiser;
+
+MessageStoreImpl::TplRecoverStruct::TplRecoverStruct(const u_int64_t _rid,
+                                                              const bool _deq_flag,
+                                                              const bool _commit_flag,
+                                                              const bool _tpc_flag) :
+                                                              rid(_rid),
+                                                              deq_flag(_deq_flag),
+                                                              commit_flag(_commit_flag),
+                                                              tpc_flag(_tpc_flag)
+{}
+
+MessageStoreImpl::MessageStoreImpl(const char* envpath) :
+                                 env(0),
+                                 queueDb(&env, 0),
+                                 configDb(&env, 0),
+                                 exchangeDb(&env, 0),
+                                 messageDb(&env, 0),
+                                 mappingDb(&env, 0),
+                                 bindingDb(&env, 0),
+                                 generalDb(&env, 0),
+                                 numJrnlFiles(0),
+                                 jrnlFsizeSblks(0),
+                                 wCachePgSizeSblks(0),
+                                 wCacheNumPages(0),
+                                 tplNumJrnlFiles(0),
+                                 tplJrnlFsizeSblks(0),
+                                 tplWCachePgSizeSblks(0),
+                                 tplWCacheNumPages(0),
+                                 highestRid(0),
+                                 isInit(false),
+                                 envPath(envpath),
+                                 mgmtObject(0)
+{}
+
+u_int16_t MessageStoreImpl::chkJrnlNumFilesParam(const u_int16_t param, const std::string paramName)
+{
+    u_int16_t p = param;
+    if (p < JRNL_MIN_NUM_FILES) {
+        p = JRNL_MIN_NUM_FILES;
+        QPID_LOG(warning, "parameter " << paramName << " (" << param << ") is below allowable minimum (" << JRNL_MIN_NUM_FILES << "); changing this parameter to minimum value.");
+    } else if (p > JRNL_MAX_NUM_FILES) {
+        p = JRNL_MAX_NUM_FILES;
+        QPID_LOG(warning, "parameter " << paramName << " (" << param << ") is above allowable maximum (" << JRNL_MAX_NUM_FILES << "); changing this parameter to maximum value.");
+    }
+    return p;
+}
+
+u_int32_t MessageStoreImpl::chkJrnlFileSizeParam(const u_int32_t param, const std::string paramName)
+{
+    u_int32_t p = param;
+    u_int32_t min = JRNL_MIN_FILE_SIZE / JRNL_RMGR_PAGE_SIZE;
+    u_int32_t max = JRNL_MAX_FILE_SIZE / JRNL_RMGR_PAGE_SIZE;
+    if (p < min) {
+        p = min;
+        QPID_LOG(warning, "parameter " << paramName << " (" << param << ") is below allowable minimum (" << min << "); changing this parameter to minimum value.");
+    } else if (p > max) {
+        p = max;
+        QPID_LOG(warning, "parameter " << paramName << " (" << param << ") is above allowable maximum (" << max << "); changing this parameter to maximum value.");
+    }
+    return p;
+}
+
+u_int32_t MessageStoreImpl::chkJrnlWrPageCacheSize(const u_int32_t param, const std::string paramName)
+{
+    u_int32_t p = param;
+    switch (p)
+    {
+      case 1:
+      case 2:
+      case 4:
+      case 8:
+      case 16:
+      case 32:
+      case 64:
+      case 128:
+        break;
+      default:
+        if (p == 0) {
+            // For zero value, use default
+            p = JRNL_WMGR_DEF_PAGE_SIZE * JRNL_DBLK_SIZE * JRNL_SBLK_SIZE / 1024;
+            QPID_LOG(warning, "parameter " << paramName << " (" << param << ") must be a power of 2 between 1 and 128; changing this parameter to default value (" << p << ")");
+        } else {
+            // For any positive value, use closest value
+            if      (p <   6)   p =   4;
+            else if (p <  12)   p =   8;
+            else if (p <  24)   p =  16;
+            else if (p <  48)   p =  32;
+            else if (p <  96)   p =  64;
+            else if (p > 128)   p = 128;
+            QPID_LOG(warning, "parameter " << paramName << " (" << param << ") must be a power of 2 between 1 and 128; changing this parameter to closest allowable value (" << p << ")");
+        }
+    }
+    return p;
+}
+
+u_int16_t MessageStoreImpl::getJrnlWrNumPages(const u_int32_t wrPageSizeKib)
+{
+    u_int32_t wrPageSizeSblks = wrPageSizeKib * 1024 / JRNL_DBLK_SIZE / JRNL_SBLK_SIZE; // convert from KiB to number sblks
+    u_int32_t defTotWCacheSize = JRNL_WMGR_DEF_PAGE_SIZE * JRNL_WMGR_DEF_PAGES; // in sblks. Currently 2014 sblks (1 MiB).
+    switch (wrPageSizeKib)
+    {
+      case 1:
+      case 2:
+      case 4:
+        // 256 KiB total cache
+        return defTotWCacheSize / wrPageSizeSblks / 4;
+      case 8:
+      case 16:
+        // 512 KiB total cache
+        return defTotWCacheSize / wrPageSizeSblks / 2;
+      default: // 32, 64, 128
+        // 1 MiB total cache
+        return defTotWCacheSize / wrPageSizeSblks;
+    }
+}
+
+void MessageStoreImpl::initManagement (Broker* broker)
+{
+    if (broker != 0) {
+        ManagementAgent* agent = ManagementAgent::Singleton::getInstance();
+        if (agent != 0) {
+            qpid::management::PackageMrgstore packageInitializer(agent);
+            mgmtObject = new qpid::management::Store(agent, this, broker);
+
+            mgmtObject->set_location(storeDir);
+            mgmtObject->set_defaultInitialFileCount(numJrnlFiles);
+            mgmtObject->set_defaultDataFileSize(jrnlFsizeSblks / JRNL_RMGR_PAGE_SIZE);
+            mgmtObject->set_tplIsInitialized(false);
+            mgmtObject->set_tplDirectory(getTplBaseDir());
+            mgmtObject->set_tplWritePageSize(tplWCachePgSizeSblks * JRNL_SBLK_SIZE * JRNL_DBLK_SIZE);
+            mgmtObject->set_tplWritePages(tplWCacheNumPages);
+            mgmtObject->set_tplInitialFileCount(tplNumJrnlFiles);
+            mgmtObject->set_tplDataFileSize(tplJrnlFsizeSblks * JRNL_SBLK_SIZE * JRNL_DBLK_SIZE);
+            mgmtObject->set_tplCurrentFileCount(tplNumJrnlFiles);
+
+            agent->addObject(mgmtObject, 0x1000000000000050LL);
+        }
+    }
+}
+
+bool MessageStoreImpl::init(const qpid::Options* options)
+{
+    // Extract and check options
+    const Options* opts = static_cast<const Options*>(options);
+    u_int16_t numJrnlFiles = chkJrnlNumFilesParam(opts->numJrnlFiles, "num-jfiles");
+    u_int32_t jrnlFsizePgs = chkJrnlFileSizeParam(opts->jrnlFsizePgs, "jfile-size-pgs");
+    u_int32_t jrnlWrCachePageSizeKib = chkJrnlWrPageCacheSize(opts->wCachePageSizeKib, "wcache-page-size");
+    u_int16_t tplNumJrnlFiles = chkJrnlNumFilesParam(opts->tplNumJrnlFiles, "tpl-num-jfiles");
+    u_int32_t tplJrnlFSizePgs = chkJrnlFileSizeParam(opts->tplJrnlFsizePgs, "tpl-jfile-size-pgs");
+    u_int32_t tplJrnlWrCachePageSizeKib = chkJrnlWrPageCacheSize(opts->tplWCachePageSizeKib, "tpl-wcache-page-size");
+    
+    // Pass option values to init(...)
+    return init(opts->storeDir, numJrnlFiles, jrnlFsizePgs, jrnlWrCachePageSizeKib, tplNumJrnlFiles, tplJrnlFSizePgs, tplJrnlWrCachePageSizeKib);
+}
+
+// These params, taken from options, are assumed to be correct and verified
+bool MessageStoreImpl::init(const std::string& dir,
+                           u_int16_t jfiles,
+                           u_int32_t jfileSizePgs,
+                           u_int32_t wCachePageSizeKib,
+                           u_int16_t tplJfiles,
+                           u_int32_t tplJfileSizePgs,
+                           u_int32_t tplWCachePageSizeKib)
+{
+    if (isInit) return true;
+
+    // Set geometry members (converting to correct units where req'd)
+    numJrnlFiles = jfiles;
+    jrnlFsizeSblks = jfileSizePgs * JRNL_RMGR_PAGE_SIZE;
+    wCachePgSizeSblks = wCachePageSizeKib * 1024 / JRNL_DBLK_SIZE / JRNL_SBLK_SIZE; // convert from KiB to number sblks
+    wCacheNumPages = getJrnlWrNumPages(wCachePageSizeKib);
+    tplNumJrnlFiles = tplJfiles;
+    tplJrnlFsizeSblks = tplJfileSizePgs * JRNL_RMGR_PAGE_SIZE;
+    tplWCachePgSizeSblks = tplWCachePageSizeKib * 1024 / JRNL_DBLK_SIZE / JRNL_SBLK_SIZE; // convert from KiB to number sblks
+    tplWCacheNumPages = getJrnlWrNumPages(tplWCachePageSizeKib);
+
+    if (dir.size()>0) storeDir = dir;
+
+    journal::jdir::create_dir(getBdbBaseDir());
+
+    try {
+        env.open(getBdbBaseDir().c_str(), DB_THREAD | DB_CREATE | DB_INIT_TXN | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_USE_ENVIRON, 0);
+    } catch (const DbException& e) {
+        if (e.get_errno() == DB_VERSION_MISMATCH)
+            THROW_STORE_EXCEPTION_2("Database environment mismatch: This version of bd4 does not match that which created the store database. "
+                                    "(If recovery is not important, delete the contents of the store directory. Otherwise, try upgrading the database using "
+                                    "db_upgrade or using db_recover - but the db4-utils package must also be installed to use these utilities.)", e);
+        THROW_STORE_EXCEPTION_2("Error opening environment", e);
+    }
+
+    TxnCtxt txn;
+    try {
+        txn.begin(env, false);
+        open(queueDb, txn.get(), "queues.db", false);
+        open(configDb, txn.get(), "config.db", false);
+        open(exchangeDb, txn.get(), "exchanges.db", false);
+        open(messageDb, txn.get(), "messages.db", false);
+        open(mappingDb, txn.get(), "mappings.db", true);
+        open(bindingDb, txn.get(), "bindings.db", true);
+        open(generalDb, txn.get(), "general.db",  false);
+        tplStorePtr.reset(new TplJournalImpl("TplStore", getTplBaseDir(), "tpl", defJournalGetEventsTimeout, defJournalFlushTimeout));
+        txn.commit();
+    } catch (const journal::jexception& e) {
+        txn.abort();
+        THROW_STORE_EXCEPTION_2("Error opening tplStore instance", e.what());
+    } catch (const DbException& e) {
+        txn.abort();
+        THROW_STORE_EXCEPTION_2("Error opening databases", e);
+    } catch (...) {
+        txn.abort();
+        throw;
+    }
+
+    isInit = true;
+    QPID_LOG(notice, "Store module initialized; dir=" << dir);
+    QPID_LOG(info,   "> Default files per journal: " << jfiles);
+    QPID_LOG(info,   "> Default jrournal file size: " << jfileSizePgs << " (wpgs)");
+    QPID_LOG(info,   "> Default write cache page size: " << wCachePageSizeKib << " (Kib)");
+    QPID_LOG(info,   "> Default number of write cache pages: " << wCacheNumPages);
+    QPID_LOG(info,   "> TPL files per journal: " << tplNumJrnlFiles);
+    QPID_LOG(info,   "> TPL jrournal file size: " << tplJfileSizePgs << " (wpgs)");
+    QPID_LOG(info,   "> TPL write cache page size: " << tplWCachePageSizeKib << " (Kib)");
+    QPID_LOG(info,   "> TPL number of write cache pages: " << tplWCacheNumPages);
+    return true;
+}
+
+void MessageStoreImpl::chkTplStoreInit()
+{
+    if (!tplStorePtr->is_ready()) {
+        qpid::sys::Mutex::ScopedLock sl(jrnlCreateLock);
+        if (!tplStorePtr->is_ready()) {
+            journal::jdir::create_dir(getTplBaseDir());
+            tplStorePtr->initialize(tplNumJrnlFiles, tplJrnlFsizeSblks, tplWCacheNumPages, tplWCachePgSizeSblks);
+            if (mgmtObject != 0) mgmtObject->set_tplIsInitialized(true);
+        }
+    }
+}
+
+void MessageStoreImpl::open(Db& db,
+                           DbTxn* txn,
+                           const char* file,
+                           bool dupKey)
+{
+    if(dupKey) db.set_flags(DB_DUPSORT);
+    db.open(txn, file, 0, DB_BTREE, DB_CREATE | DB_THREAD, 0);
+    dbs.push_back(&db);
+}
+
+MessageStoreImpl::~MessageStoreImpl()
+{
+    try {
+        for (std::list<Db*>::iterator i = dbs.begin(); i != dbs.end(); i++) {
+            (*i)->close(0);
+        }
+        if (tplStorePtr->is_ready()) tplStorePtr->stop(true);
+    } catch (const DbException& e) {
+        QPID_LOG(error, "Error closing BDB databases: " <<  e.what());
+    } catch (const journal::jexception& e) {
+        QPID_LOG(error, "Error: " << e.what());
+    } catch (const std::exception& e) {
+        QPID_LOG(error, "Error: " << e.what());
+    } catch (...) {
+        QPID_LOG(error, "Unknown error in MessageStoreImpl::~MessageStoreImpl()");
+    }
+
+    if (mgmtObject != 0)
+        mgmtObject->resourceDestroy();
+}
+
+void MessageStoreImpl::truncate()
+{
+    DbTxn* txn;
+    env.txn_begin(0, &txn, 0);
+    u_int32_t count;
+
+    for (std::list<Db*>::iterator i = dbs.begin(); i != dbs.end(); i++) {
+        (*i)->truncate(txn, &count, 0);
+    }
+
+    txn->commit(0);
+    try {
+        journal::jdir::delete_dir(getJrnlBaseDir(),true);
+        journal::jdir::delete_dir(getTplBaseDir(),true);
+    }
+    catch (const journal::jexception& e) {
+        THROW_STORE_EXCEPTION(std::string("truncate() failed: ") + e.what() );
+    }
+}
+
+void MessageStoreImpl::create(PersistableQueue& queue,
+                             const FieldTable& args)
+{
+    checkInit();
+    if (queue.getPersistenceId()) {
+        THROW_STORE_EXCEPTION("Queue already created: " + queue.getName());
+    }
+    JournalImpl* jQueue = 0;
+    FieldTable::ValuePtr value;
+
+    u_int16_t localFileCount = numJrnlFiles;
+    u_int32_t localFileSizeSblks  = jrnlFsizeSblks;
+
+    value = args.get ("qpid.file_count");
+    if (value.get() != 0 && !value->empty() && value->convertsTo<int>())
+        localFileCount = (u_int16_t) value->get<int>();
+
+    value = args.get ("qpid.file_size");
+    if (value.get() != 0 && !value->empty() && value->convertsTo<int>())
+        localFileSizeSblks = (u_int32_t) value->get<int>() * JRNL_RMGR_PAGE_SIZE;
+
+    {
+        // TODO: Is this mutex necessary?
+        qpid::sys::Mutex::ScopedLock sl(jrnlCreateLock);
+        jQueue = new JournalImpl(queue.getName(), getJrnlDir(queue),
+                                 std::string("JournalData"), defJournalGetEventsTimeout,
+                                 defJournalFlushTimeout);
+    }
+
+    queue.setExternalQueueStore(dynamic_cast<ExternalQueueStore*>(jQueue));
+    try {
+        // init will create the deque's for the init...
+        jQueue->initialize(localFileCount, localFileSizeSblks, wCacheNumPages, wCachePgSizeSblks);
+    } catch (const journal::jexception& e) {
+        THROW_STORE_EXCEPTION(std::string("Queue ") + queue.getName() + ": create() failed: " + e.what());
+    }
+    try {
+        if (!create(queueDb, queueIdSequence, queue)) {
+            THROW_STORE_EXCEPTION("Queue already exists: " + queue.getName());
+        }
+    } catch (const DbException& e) {
+        THROW_STORE_EXCEPTION_2("Error creating queue named  " + queue.getName(), e);
+    }
+}
+
+void MessageStoreImpl::destroy(PersistableQueue& queue)
+{
+    checkInit();
+    destroy(queueDb, queue);
+    deleteBindingsForQueue(queue);
+    qpid::broker::ExternalQueueStore* eqs = queue.getExternalQueueStore();
+    if (eqs) {
+        JournalImpl* jQueue = static_cast<JournalImpl*>(eqs);
+        jQueue->delete_jrnl_files();
+        queue.setExternalQueueStore(0); // will delete the journal if exists
+    }
+}
+
+void MessageStoreImpl::create(const PersistableExchange& exchange,
+                             const FieldTable& /*args*/)
+{
+    checkInit();
+    if (exchange.getPersistenceId()) {
+        THROW_STORE_EXCEPTION("Exchange already created: " + exchange.getName());
+    }
+    try {
+        if (!create(exchangeDb, exchangeIdSequence, exchange)) {
+            THROW_STORE_EXCEPTION("Exchange already exists: " + exchange.getName());
+        }
+    } catch (const DbException& e) {
+        THROW_STORE_EXCEPTION_2("Error creating exchange named " + exchange.getName(), e);
+    }
+}
+
+void MessageStoreImpl::destroy(const PersistableExchange& exchange)
+{
+    checkInit();
+    destroy(exchangeDb, exchange);
+    //need to also delete bindings
+    IdDbt key(exchange.getPersistenceId());
+    bindingDb.del(0, &key, DB_AUTO_COMMIT);
+}
+
+void MessageStoreImpl::create(const PersistableConfig& general)
+{
+    checkInit();
+    if (general.getPersistenceId()) {
+        THROW_STORE_EXCEPTION("General configuration item already created");
+    }
+    try {
+        if (!create(generalDb, generalIdSequence, general)) {
+            THROW_STORE_EXCEPTION("General configuration already exists");
+        }
+    } catch (const DbException& e) {
+        THROW_STORE_EXCEPTION_2("Error creating general configuration", e);
+    }
+}
+
+void MessageStoreImpl::destroy(const PersistableConfig& general)
+{
+    checkInit();
+    destroy(generalDb, general);
+}
+
+bool MessageStoreImpl::create(Db& db,
+                             IdSequence& seq,
+                             const Persistable& p)
+{
+    u_int64_t id (seq.next());
+    Dbt key(&id, sizeof(id));
+    BufferValue value (p);
+
+    int status;
+    TxnCtxt txn;
+    txn.begin(env, true);
+    try {
+        status = db.put(txn.get(), &key, &value, DB_NOOVERWRITE);
+        txn.commit();
+    } catch (...) {
+        txn.abort();
+        throw;
+    }
+    if (status == DB_KEYEXIST) {
+        return false;
+    } else {
+        p.setPersistenceId(id);
+        return true;
+    }
+}
+
+void MessageStoreImpl::destroy(Db& db, const Persistable& p)
+{
+    IdDbt key(p.getPersistenceId());
+    db.del(0, &key, DB_AUTO_COMMIT);
+}
+
+
+void MessageStoreImpl::bind(const PersistableExchange& e,
+                           const PersistableQueue& q,
+                           const std::string& k,
+                           const FieldTable& a)
+{
+    checkInit();
+    IdDbt key(e.getPersistenceId());
+    BindingDbt value(e, q, k, a);
+    TxnCtxt txn;
+    txn.begin(env, true);
+    try {
+        put(bindingDb, txn.get(), key, value);
+        txn.commit();
+    } catch (...) {
+        txn.abort();
+        throw;
+    }
+}
+
+void MessageStoreImpl::unbind(const PersistableExchange& e,
+                             const PersistableQueue& q,
+                             const std::string& k,
+                             const FieldTable&)
+{
+    checkInit();
+    deleteBinding(e, q, k);
+}
+
+void MessageStoreImpl::recover(RecoveryManager& registry)
+{
+    checkInit();
+    txn_list prepared;
+    recoverLockedMappings(prepared);
+
+    queue_index queues;//id->queue
+    exchange_index exchanges;//id->exchange
+    message_index messages;//id->message
+
+    TxnCtxt txn;
+    txn.begin(env, false);
+    try {
+        //read all queues, calls recoversMessages
+        recoverQueues(txn, registry, queues, prepared, messages);
+
+        //recover exchange & bindings:
+        recoverExchanges(txn, registry, exchanges);
+        recoverBindings(txn, exchanges, queues);
+
+        //recover general-purpose configuration
+        recoverGeneral(txn, registry);
+
+        txn.commit();
+    } catch (const DbException& e) {
+        txn.abort();
+        THROW_STORE_EXCEPTION_2("Error on recovery", e);
+    } catch (...) {
+        txn.abort();
+        throw;
+    }
+
+    //recover transactions:
+    for (txn_list::iterator i = prepared.begin(); i != prepared.end(); i++) {
+        if (mgmtObject != 0) {
+            mgmtObject->inc_tplTransactionDepth();
+            mgmtObject->inc_tplTxnPrepares();
+        }
+
+        std::string xid = i->xid;
+
+        // Restore data token state in TxnCtxt
+        TplRecoverMapCitr citr = tplRecoverMap.find(xid);
+        if (citr == tplRecoverMap.end()) THROW_STORE_EXCEPTION("XID not found in tplRecoverMap");
+
+        // If a record is found that is dequeued but not committed/aborted from tplStore, then a complete() call
+        // was interrupted part way through committing/aborting the impacted queues. Complete this process.
+        bool incomplTplTxnFlag = citr->second.deq_flag;
+
+        if (citr->second.tpc_flag) {
+            // Dtx (2PC) transaction
+            TPCTxnCtxt* tpcc = new TPCTxnCtxt(xid, &messageIdSequence);
+            std::auto_ptr<TPCTransactionContext> txn(tpcc);
+            tpcc->recoverDtok(citr->second.rid, xid);
+            tpcc->prepare(tplStorePtr.get());
+
+            RecoverableTransaction::shared_ptr dtx;
+            if (!incomplTplTxnFlag) dtx = registry.recoverTransaction(xid, txn);
+            if (i->enqueues.get()) {
+                for (LockedMappings::iterator j = i->enqueues->begin(); j != i->enqueues->end(); j++) {
+                    tpcc->addXidRecord(queues[j->first]->getExternalQueueStore());
+                    if (!incomplTplTxnFlag) dtx->enqueue(queues[j->first], messages[j->second]);
+                }
+            }
+            if (i->dequeues.get()) {
+                for (LockedMappings::iterator j = i->dequeues->begin(); j != i->dequeues->end(); j++) {
+                    tpcc->addXidRecord(queues[j->first]->getExternalQueueStore());
+                    if (!incomplTplTxnFlag) dtx->dequeue(queues[j->first], messages[j->second]);
+                }
+            }
+
+            if (incomplTplTxnFlag) {
+                tpcc->complete(citr->second.commit_flag);
+            }
+        } else {
+            // Local (1PC) transaction
+            boost::shared_ptr<TxnCtxt> opcc(new TxnCtxt(xid, &messageIdSequence));
+            opcc->recoverDtok(citr->second.rid, xid);
+            opcc->prepare(tplStorePtr.get());
+
+            if (i->enqueues.get()) {
+                for (LockedMappings::iterator j = i->enqueues->begin(); j != i->enqueues->end(); j++) {
+                    opcc->addXidRecord(queues[j->first]->getExternalQueueStore());
+                }
+            }
+            if (i->dequeues.get()) {
+                for (LockedMappings::iterator j = i->dequeues->begin(); j != i->dequeues->end(); j++) {
+                    opcc->addXidRecord(queues[j->first]->getExternalQueueStore());
+                }
+            }
+            if (incomplTplTxnFlag) {
+                opcc->complete(citr->second.commit_flag);
+            } else {
+                completed(*opcc.get(), citr->second.commit_flag);
+            }
+        }
+    }
+    registry.recoveryComplete();
+}
+
+void MessageStoreImpl::recoverQueues(TxnCtxt& txn,
+                                    RecoveryManager& registry,
+                                    queue_index& queue_index,
+                                    txn_list& prepared,
+                                    message_index& messages)
+{
+    Cursor queues;
+    queues.open(queueDb, txn.get());
+
+    u_int64_t maxQueueId(1);
+
+    IdDbt key;
+    Dbt value;
+    //read all queues
+    while (queues.next(key, value)) {
+        Buffer buffer(reinterpret_cast<char*>(value.get_data()), value.get_size());
+        //create a Queue instance
+        RecoverableQueue::shared_ptr queue = registry.recoverQueue(buffer);
+        //set the persistenceId and update max as required
+        queue->setPersistenceId(key.id);
+
+        const char* queueName = queue->getName().c_str();
+        JournalImpl* jQueue = 0;
+        {
+            qpid::sys::Mutex::ScopedLock sl(jrnlCreateLock);
+            jQueue = new JournalImpl(queueName, getJrnlDir(queueName), std::string("JournalData"), defJournalGetEventsTimeout, defJournalFlushTimeout);
+        }
+        queue->setExternalQueueStore(dynamic_cast<ExternalQueueStore*>(jQueue));
+
+        try
+        {
+            u_int64_t thisHighestRid = 0;
+            jQueue->recover(numJrnlFiles, jrnlFsizeSblks, wCacheNumPages, wCachePgSizeSblks, &prepared, thisHighestRid, key.id); // start recovery
+            if (thisHighestRid > highestRid)
+                highestRid = thisHighestRid;
+            recoverMessages(txn, registry, queue, prepared, messages);
+            jQueue->recover_complete(); // start journal.
+        } catch (const journal::jexception& e) {
+            THROW_STORE_EXCEPTION(std::string("Queue ") + queueName + ": recoverQueues() failed: " + e.what());
+        }
+        //read all messages: done on a per queue basis if using Journal
+
+        queue_index[key.id] = queue;
+        maxQueueId = max(key.id, maxQueueId);
+    }
+
+    // NOTE: highestRid is set by both recoverQueues() and recoverTplStore() as
+    // the messageIdSequence is used for both queue journals and the tpl journal.
+    messageIdSequence.reset(highestRid + 1);
+
+    queueIdSequence.reset(maxQueueId + 1);
+}
+
+
+void MessageStoreImpl::recoverExchanges(TxnCtxt& txn,
+                                       RecoveryManager& registry,
+                                       exchange_index& index)
+{
+    //TODO: this is a copy&paste from recoverQueues - refactor!
+    Cursor exchanges;
+    exchanges.open(exchangeDb, txn.get());
+
+    u_int64_t maxExchangeId(1);
+    IdDbt key;
+    Dbt value;
+    //read all exchanges
+    while (exchanges.next(key, value)) {
+        Buffer buffer(reinterpret_cast<char*>(value.get_data()), value.get_size());
+        //create a Exchange instance
+        RecoverableExchange::shared_ptr exchange = registry.recoverExchange(buffer);
+        //set the persistenceId and update max as required
+        exchange->setPersistenceId(key.id);
+        index[key.id] = exchange;
+        maxExchangeId = max(key.id, maxExchangeId);
+    }
+    exchangeIdSequence.reset(maxExchangeId + 1);
+}
+
+void MessageStoreImpl::recoverBindings(TxnCtxt& txn,
+                                      exchange_index& exchanges,
+                                      queue_index& queues)
+{
+    Cursor bindings;
+    bindings.open(bindingDb, txn.get());
+
+    IdDbt key;
+    Dbt value;
+    while (bindings.next(key, value)) {
+        Buffer buffer(reinterpret_cast<char*>(value.get_data()), value.get_size());
+        if (buffer.available() < 8) {
+            QPID_LOG(error, "Not enough data for binding: " << buffer.available());
+            THROW_STORE_EXCEPTION("Not enough data for binding");
+        }
+        uint64_t queueId = buffer.getLongLong();
+        std::string queueName;
+        std::string routingkey;
+        FieldTable args;
+        buffer.getShortString(queueName);
+        buffer.getShortString(routingkey);
+        buffer.get(args);
+        exchange_index::iterator exchange = exchanges.find(key.id);
+        queue_index::iterator queue = queues.find(queueId);
+        if (exchange != exchanges.end() && queue != queues.end()) {
+            //could use the recoverable queue here rather than the name...
+            exchange->second->bind(queueName, routingkey, args);
+        } else {
+            //stale binding, delete it
+            QPID_LOG(warning, "Deleting stale binding");
+            bindings->del(0);
+        }
+    }
+}
+
+void MessageStoreImpl::recoverGeneral(TxnCtxt& txn,
+                                     RecoveryManager& registry)
+{
+    Cursor items;
+    items.open(generalDb, txn.get());
+
+    u_int64_t maxGeneralId(1);
+    IdDbt key;
+    Dbt value;
+    //read all items
+    while (items.next(key, value)) {
+        Buffer buffer(reinterpret_cast<char*>(value.get_data()), value.get_size());
+        //create instance
+        RecoverableConfig::shared_ptr config = registry.recoverConfig(buffer);
+        //set the persistenceId and update max as required
+        config->setPersistenceId(key.id);
+        maxGeneralId = max(key.id, maxGeneralId);
+    }
+    generalIdSequence.reset(maxGeneralId + 1);
+}
+
+void MessageStoreImpl::recoverMessages(TxnCtxt& /*txn*/,
+                                      qpid::broker::RecoveryManager& recovery,
+                                      qpid::broker::RecoverableQueue::shared_ptr& queue,
+                                      txn_list& prepared,
+                                      message_index& messages)
+{
+    size_t preambleLength = sizeof(u_int32_t)/*header size*/;
+
+    JournalImpl* jc = static_cast<JournalImpl*>(queue->getExternalQueueStore());
+    DataTokenImpl dtok;
+    size_t readSize = 0;
+    unsigned msg_count = 0;
+
+    // TODO: This optimization to skip reading if there are no enqueued messages to read
+    // breaks the python system test in phase 6 with "Exception: Cannot write lock file"
+    // Figure out what is breaking.
+    //bool read = jc->get_enq_cnt() > 0;
+    bool read = true;
+
+    void* dbuff = NULL; size_t dbuffSize = 0;
+    void* xidbuff = NULL; size_t xidbuffSize = 0;
+    bool transientFlag = false;
+    bool externalFlag = false;
+
+    dtok.set_wstate(DataTokenImpl::ENQ);
+
+    // Read the message from the Journal.
+    try {
+        unsigned aio_sleep_cnt = 0;
+        while (read) {
+            rhm::journal::iores res = jc->read_data_record(&dbuff, dbuffSize, &xidbuff, xidbuffSize, transientFlag, externalFlag, &dtok);
+            readSize = dtok.dsize();
+
+            switch (res)
+            {
+              case rhm::journal::RHM_IORES_SUCCESS: {
+                msg_count++;
+                RecoverableMessage::shared_ptr msg;
+                char* data = (char*)dbuff;
+
+                unsigned headerSize;
+                if (externalFlag) {
+                    msg = getExternMessage(recovery, dtok.rid(), headerSize); // large message external to jrnl
+                } else {
+                    headerSize = Buffer(data, preambleLength).getLong();
+                    Buffer headerBuff(data+ preambleLength, headerSize); /// do we want read size or header size ????
+                    msg = recovery.recoverMessage(headerBuff);
+                }
+                msg->setPersistenceId(dtok.rid());
+
+                u_int32_t contentOffset = headerSize + preambleLength;
+                u_int64_t contentSize = readSize - contentOffset;
+                if (msg->loadContent(contentSize) && !externalFlag) {
+                    //now read the content
+                    Buffer contentBuff(data + contentOffset, contentSize);
+                    msg->decodeContent(contentBuff);
+                }
+
+                PreparedTransaction::list::iterator i = PreparedTransaction::getLockedPreparedTransaction(prepared, queue->getPersistenceId(), dtok.rid());
+                if (i == prepared.end()) { // not in prepared list
+                    queue->recover(msg);
+                } else {
+                    u_int64_t rid = dtok.rid();
+                    std::string xid(i->xid);
+                    TplRecoverMapCitr citr = tplRecoverMap.find(xid);
+                    if (citr == tplRecoverMap.end()) THROW_STORE_EXCEPTION("XID not found in tplRecoverMap");
+
+                    // deq present in prepared list, this xid is part of incomplete txn commit/abort
+                    // or this is a 1PC txn that must be rolled forward
+                    if (citr->second.deq_flag || !citr->second.tpc_flag) {
+                        if (jc->is_enqueued(rid, true)) {
+                            // Enqueue is non-tx, dequeue tx
+                            assert(jc->is_locked(rid)); // This record MUST be locked by a txn dequeue
+                            if (!citr->second.commit_flag) {
+                                queue->recover(msg); // recover message in abort case only
+                            }
+                        } else {
+                            // Enqueue and/or dequeue tx
+                            journal::txn_map& tmap = jc->get_txn_map();
+                            journal::txn_data_list txnList = tmap.get_tdata_list(xid);
+                            bool enq = false;
+                            bool deq = false;
+                            for (journal::tdl_itr j = txnList.begin(); j<txnList.end(); j++) {
+                                if (j->_enq_flag && j->_rid == rid) enq = true;
+                                else if (!j->_enq_flag && j->_drid == rid) deq = true;
+                            }
+                            if (enq && !deq && citr->second.commit_flag) {
+                                queue->recover(msg); // recover txn message in commit case only
+                            }
+                        }
+                    } else {
+                        messages[rid] = msg;
+                    }
+                }
+
+                dtok.reset();
+                dtok.set_wstate(DataTokenImpl::ENQ);
+
+                if (xidbuff)
+                    ::free(xidbuff);
+                else if (dbuff)
+                    ::free(dbuff);
+                aio_sleep_cnt = 0;
+                break;
+              }
+              case rhm::journal::RHM_IORES_PAGE_AIOWAIT:
+                if (++aio_sleep_cnt > MAX_AIO_SLEEPS)
+                    THROW_STORE_EXCEPTION("Timeout waiting for AIO in MessageStoreImpl::recoverMessages()");
+                ::usleep(AIO_SLEEP_TIME);
+                break;
+              case rhm::journal::RHM_IORES_EMPTY:
+                read = false;
+                break; // done with all messages. (add call in jrnl to test that _emap is empty.)
+              default:
+                assert("Store Error: Unexpected msg state");
+            } // switch
+        } // while
+    } catch (const journal::jexception& e) {
+        THROW_STORE_EXCEPTION(std::string("Queue ") + queue->getName() +
+                              ": recoverMessages() failed: " + e.what());
+    }
+}
+
+RecoverableMessage::shared_ptr MessageStoreImpl::getExternMessage(qpid::broker::RecoveryManager& recovery,
+                                                                 uint64_t messageId,
+                                                                 unsigned& headerSize)
+{
+    RecoverableMessage::shared_ptr ret;
+    Dbt key (&messageId, sizeof(messageId));
+    size_t preamble_length = sizeof(u_int32_t); /*header size*/
+
+    BufferValue value(preamble_length, 0);
+    value.buffer.record();
+
+    TxnCtxt txn;
+    txn.begin(env, true);
+    try {
+        if (messageDb.get(txn.get(), &key, &value, 0) == DB_NOTFOUND) {
+            txn.abort();
+            THROW_STORE_EXCEPTION("Cannot load content. Message not known to store!");
+        }
+
+        //read header only to begin with
+        headerSize = value.buffer.getLong();
+
+        BufferValue header(headerSize, preamble_length);
+        if (messageDb.get(txn.get(), &key, &header, 0) == DB_NOTFOUND) {
+            txn.abort();
+            THROW_STORE_EXCEPTION("Cannot load content. Message not known to store!");
+        }
+        ret = recovery.recoverMessage(header.buffer);
+        txn.commit();
+    } catch (const DbException& e) {
+        txn.abort();
+        THROW_STORE_EXCEPTION("Unexpected BDB error in MessageStoreImpl::getExternMessage(): " + std::string(e.what()));
+    } catch (...) {
+        txn.abort();
+        throw;
+    }
+    return ret;
+}
+
+int MessageStoreImpl::enqueueMessage(TxnCtxt& txn,
+                                    IdDbt& msgId,
+                                    RecoverableMessage::shared_ptr& msg,
+                                    queue_index& index,
+                                    txn_list& prepared,
+                                    message_index& messages)
+{
+    Cursor mappings;
+    mappings.open(mappingDb, txn.get());
+
+    IdDbt value;
+
+    int count(0);
+    for (int status = mappings->get(&msgId, &value, DB_SET); status == 0; status = mappings->get(&msgId, &value, DB_NEXT_DUP)) {
+        if (index.find(value.id) == index.end()) {
+            QPID_LOG(warning, "Recovered message for queue that no longer exists");
+            mappings->del(0);
+        } else {
+            RecoverableQueue::shared_ptr queue = index[value.id];
+            if (PreparedTransaction::isLocked(prepared, value.id, msgId.id)) {
+                messages[msgId.id] = msg;
+            } else {
+                queue->recover(msg);
+            }
+            count++;
+        }
+    }
+    mappings.close();
+    return count;
+}
+
+void MessageStoreImpl::readTplStore()
+{
+    tplRecoverMap.clear();
+    journal::txn_map& tmap = tplStorePtr->get_txn_map();
+    DataTokenImpl dtok;
+    void* dbuff = NULL; size_t dbuffSize = 0;
+    void* xidbuff = NULL; size_t xidbuffSize = 0;
+    bool transientFlag = false;
+    bool externalFlag = false;
+    bool done = false;
+    try {
+        unsigned aio_sleep_cnt = 0;
+        while (!done) {
+            dtok.reset();
+            dtok.set_wstate(DataTokenImpl::ENQ);
+            switch (tplStorePtr->read_data_record(&dbuff, dbuffSize, &xidbuff, xidbuffSize, transientFlag, externalFlag, &dtok)) {
+              case rhm::journal::RHM_IORES_SUCCESS: {
+                // Every TPL record contains both data and an XID
+                assert(dbuffSize>0);
+                assert(xidbuffSize>0);
+                std::string xid(static_cast<const char*>(xidbuff), xidbuffSize);
+                bool is2PC = *(static_cast<char*>(dbuff)) != 0;
+
+                // Check transaction details; add to recover map
+                journal::txn_data_list txnList = tmap.get_tdata_list(xid);
+                unsigned enqCnt = 0;
+                unsigned deqCnt = 0;
+                u_int64_t rid = 0;
+
+                // Assume commit (roll forward) in cases where only prepare has been called - ie only enqueue record exists.
+                // Note: will apply to both 1PC and 2PC transactions.
+                bool commitFlag = true;
+
+                for (journal::tdl_itr j = txnList.begin(); j<txnList.end(); j++) {
+                    if (j->_enq_flag) {
+                        rid = j->_rid;
+                        enqCnt++;
+                    } else {
+                        commitFlag = j->_commit_flag;
+                        deqCnt++;
+                    }
+                }
+                assert(enqCnt == 1);
+                assert(deqCnt <= 1);
+                tplRecoverMap.insert(TplRecoverMapPair(xid, TplRecoverStruct(rid, deqCnt == 1, commitFlag, is2PC)));
+
+                ::free(xidbuff);
+                aio_sleep_cnt = 0;
+                break;
+                }
+              case rhm::journal::RHM_IORES_PAGE_AIOWAIT:
+                if (++aio_sleep_cnt > MAX_AIO_SLEEPS)
+                    THROW_STORE_EXCEPTION("Timeout waiting for AIO in MessageStoreImpl::recoverTplStore()");
+                ::usleep(AIO_SLEEP_TIME);
+                break;
+              case rhm::journal::RHM_IORES_EMPTY:
+                done = true;
+                break; // done with all messages. (add call in jrnl to test that _emap is empty.)
+              default:
+                assert("Store Error: Unexpected msg state");
+            } // switch
+        }
+    } catch (const journal::jexception& e) {
+        THROW_STORE_EXCEPTION(std::string("TPL recoverTplStore() failed: ") + e.what());
+    }
+}
+
+void MessageStoreImpl::recoverTplStore()
+{
+    if (journal::jdir::exists(tplStorePtr->jrnl_dir() + tplStorePtr->base_filename() + ".jinf")) {
+        u_int64_t thisHighestRid;
+        tplStorePtr->recover(tplNumJrnlFiles, tplJrnlFsizeSblks, tplWCachePgSizeSblks, tplWCacheNumPages, 0, thisHighestRid, 0);
+        if (thisHighestRid > highestRid)
+            highestRid = thisHighestRid;
+
+        // Load tplRecoverMap by reading the TPL store
+        readTplStore();
+
+        tplStorePtr->recover_complete(); // start journal.
+    }
+}
+
+void MessageStoreImpl::recoverLockedMappings(txn_list& txns)
+{
+    if (!tplStorePtr->is_ready())
+        recoverTplStore();
+
+    // Abort unprepaired xids and populate the locked maps
+    for (TplRecoverMapCitr i = tplRecoverMap.begin(); i != tplRecoverMap.end(); i++) {
+        LockedMappings::shared_ptr enq_ptr;
+        enq_ptr.reset(new LockedMappings);
+        LockedMappings::shared_ptr deq_ptr;
+        deq_ptr.reset(new LockedMappings);
+        txns.push_back(new PreparedTransaction(i->first, enq_ptr, deq_ptr));
+    }
+}
+
+void MessageStoreImpl::collectPreparedXids(std::set<std::string>& xids)
+{
+    if (tplStorePtr->is_ready()) {
+        tplStorePtr->read_reset();
+        readTplStore();
+    } else {
+        recoverTplStore();
+    }
+    for (TplRecoverMapCitr i = tplRecoverMap.begin(); i != tplRecoverMap.end(); i++) {
+        // Discard all txns that are to be rolled forward/back and 1PC transactions
+        if (!i->second.deq_flag && i->second.tpc_flag)
+            xids.insert(i->first);
+    }
+}
+
+void MessageStoreImpl::stage(const intrusive_ptr<PersistableMessage>& msg)
+{
+    checkInit();
+    TxnCtxt txn;
+    txn.begin(env, true);
+
+    u_int64_t messageId (msg->getPersistenceId());
+    if (messageId == 0 || !msg->isContentReleased()) {
+        try {
+            Dbt key (&messageId, sizeof(messageId));
+            messageId = messageIdSequence.next();
+            store(NULL, &txn, key, msg, true);
+            msg->setPersistenceId(messageId);
+            txn.commit();
+        } catch (...) {
+            txn.abort();
+            throw;
+        }
+    }
+}
+
+void MessageStoreImpl::destroy(PersistableMessage& msg)
+{
+    checkInit();
+    u_int64_t messageId (msg.getPersistenceId());
+    if (messageId) {
+        Dbt key (&messageId, sizeof(messageId));
+        TxnCtxt txn;
+        txn.begin(env, true);
+        try {
+            deleteIfUnused(txn.get(), key);
+            txn.commit();
+        } catch (const DbException& e) {
+            txn.abort();
+            THROW_STORE_EXCEPTION_2("Error destroying message", e);
+        } catch (...) {
+            txn.abort();
+            throw;
+        }
+    }
+}
+
+u_int64_t MessageStoreImpl::getRecordSize(Db& db,
+                                         Dbt& key)
+{
+    u_int64_t ret = 0;
+    TxnCtxt txn;
+    txn.begin(env, true);
+    try {
+        ret = getRecordSize(txn.get(), db, key);
+        txn.commit();
+    } catch (...) {
+        txn.abort();
+        throw;
+    }
+    return ret;
+}
+
+u_int64_t MessageStoreImpl::getRecordSize(DbTxn* txn,
+                                         Db& db,
+                                         Dbt& key)
+{
+    Dbt peek;
+    peek.set_flags(DB_DBT_USERMEM);
+    peek.set_ulen(0);
+    try {
+        int status = db.get(txn, &key, &peek, 0);
+        if (status != DB_BUFFER_SMALL) {
+            THROW_STORE_EXCEPTION("Unexpected status code when determining record length: " + std::string(DbEnv::strerror(status)));
+        }
+    } catch (const DbMemoryException& expected) {
+        //api doc indicates may throw exception instead of status = DB_BUFFER_SMALL;
+    }
+    return peek.get_size();
+}
+
+void MessageStoreImpl::appendContent(const intrusive_ptr<const PersistableMessage>& msg,
+                                    const std::string& data)
+{
+    checkInit();
+    u_int64_t messageId (msg->getPersistenceId());
+    if (messageId != 0) {
+        TxnCtxt txn;
+        txn.begin(env, true);
+        try {
+            Dbt key (&messageId, sizeof(messageId));
+            u_int64_t offset = getRecordSize(messageDb, key);
+            const int size(data.length());
+
+            //don't want to have to copy this and shouldn't need to as
+            //it will be used for reading only. but have to cast away
+            //the const-ness, which is nasty...
+            //alternative involves copying:
+            //char buffer[size];
+            //data.copy(buffer, size);
+            Dbt value((void*) data.data(), size);
+            value.set_flags(DB_DBT_USERMEM | DB_DBT_PARTIAL);
+            value.set_doff(offset);
+            value.set_dlen(size);
+            messageDb.put(txn.get(), &key, &value, 0);
+            txn.commit();
+        } catch (const DbException& e) {
+            txn.abort();
+            THROW_STORE_EXCEPTION_2("Error appending content", e);
+        } catch (...) {
+            txn.abort();
+            throw;
+        }
+    } else {
+        THROW_STORE_EXCEPTION("Cannot append content. Message not known to store!");
+    }
+}
+
+void MessageStoreImpl::loadContent(const qpid::broker::PersistableQueue& queue,
+                                  const intrusive_ptr<const PersistableMessage>& msg,
+                                  std::string& data,
+                                  u_int64_t offset,
+                                  u_int32_t length)
+{
+    checkInit();
+    u_int64_t realOffset = offset + sizeof(u_int32_t)/*header length*/ + msg->encodedHeaderSize();
+    u_int64_t messageId (msg->getPersistenceId());
+
+    if (messageId != 0) {
+        try {
+            JournalImpl* jc = static_cast<JournalImpl*>(queue.getExternalQueueStore());
+            if (jc && jc->is_enqueued(messageId) ) {
+                if (jc->loadMsgContent(messageId, data, realOffset, length)) {
+                    return;
+                }
+            }
+        } catch (const journal::jexception& e) {
+            THROW_STORE_EXCEPTION(std::string("Queue ") + queue.getName() +
+                                  ": loadContent() failed: " + e.what());
+        }
+        TxnCtxt txn;
+        txn.begin(env, true);
+        try {
+            Dbt key (&messageId, sizeof(messageId));
+            char *buffer = new char[length];
+            Dbt value(buffer, length);
+            value.set_flags(DB_DBT_USERMEM | DB_DBT_PARTIAL);
+            value.set_ulen(length);
+            value.set_doff(realOffset);
+            value.set_dlen(length);
+            int status = messageDb.get(txn.get(), &key, &value, 0);
+            if (status == DB_NOTFOUND) {
+                delete [] buffer;
+                THROW_STORE_EXCEPTION("Cannot load content. Message not known to store!");
+            }
+            data.assign(buffer, value.get_size());
+            delete [] buffer;
+            txn.commit();
+        } catch (const DbException& e) {
+            txn.abort();
+            THROW_STORE_EXCEPTION_2("Error loading content", e);
+        } catch (...) {
+            txn.abort();
+            throw;
+        }
+    } else {
+        THROW_STORE_EXCEPTION("Cannot load content. Message not known to store!");
+    }
+}
+
+void MessageStoreImpl::flush(const qpid::broker::PersistableQueue& queue)
+{
+    if (queue.getExternalQueueStore() == 0) return;
+    checkInit();
+    std::string qn = queue.getName();
+    try {
+        JournalImpl* jc = static_cast<JournalImpl*>(queue.getExternalQueueStore());
+        if (jc) {
+            // TODO: check if this result should be used...
+            /*rhm::journal::iores res =*/ jc->flush();
+        }
+    } catch (const journal::jexception& e) {
+        THROW_STORE_EXCEPTION(std::string("Queue ") + qn + ": flush() failed: " + e.what() );
+    }
+}
+
+void MessageStoreImpl::enqueue(TransactionContext* ctxt,
+                              const intrusive_ptr<PersistableMessage>& msg,
+                              const PersistableQueue& queue)
+{
+    checkInit();
+    u_int64_t queueId (queue.getPersistenceId());
+    u_int64_t messageId (msg->getPersistenceId());
+    if (queueId == 0) {
+        THROW_STORE_EXCEPTION("Queue not created: " + queue.getName());
+    }
+    Dbt key (&messageId, sizeof(messageId));
+
+    TxnCtxt implicit;
+    TxnCtxt* txn = 0;
+    if (ctxt) {
+        txn = check(ctxt);
+    } else {
+        txn = &implicit;
+    }
+
+    bool newId = false;
+    if (messageId == 0) {
+        messageId = messageIdSequence.next();
+        msg->setPersistenceId(messageId);
+        newId = true;
+    }
+    store(&queue, txn, key, msg, newId);
+
+    // add queue* to the txn map..
+    if (ctxt) txn->addXidRecord(queue.getExternalQueueStore());
+}
+
+void MessageStoreImpl::store(const PersistableQueue* queue,
+                            TxnCtxt* txn, Dbt& messageId,
+                            const intrusive_ptr<PersistableMessage>& message,
+                            bool newId)
+{
+    u_int32_t headerSize = message->encodedHeaderSize();
+    u_int64_t size = message->encodedSize() + sizeof(u_int32_t);
+    char* buff = 0;
+    if (!message->isContentReleased() )
+    {
+        buff = static_cast<char*>(::alloca(size)); // long + headers + content
+        Buffer buffer(buff,size);
+        buffer.putLong(headerSize);
+        message->encode(buffer);
+    }
+
+    try {
+        if (queue) {
+            boost::intrusive_ptr<DataTokenImpl> dtokp(new DataTokenImpl);
+            dtokp->addRef();
+            dtokp->setSourceMessage(message);
+            dtokp->set_external_rid(true);
+            dtokp->set_rid(message->getPersistenceId()); // set the messageID into the Journal header (record-id)
+
+            JournalImpl* jc = static_cast<JournalImpl*>(queue->getExternalQueueStore());
+            if (txn->getXid().empty()) {
+                if (message->isContentReleased()) {
+                    jc->enqueue_extern_data_record(size, dtokp.get(), false);
+                } else {
+                    jc->enqueue_data_record(buff, size, size, dtokp.get(), false);
+                }
+            } else {
+                if (message->isContentReleased()) {
+                    jc->enqueue_extern_txn_data_record(size, dtokp.get(), txn->getXid(), false);
+                } else {
+                    jc->enqueue_txn_data_record(buff, size, size, dtokp.get(), txn->getXid(), false);
+                }
+            }
+        } else {
+            /// cct message db
+            if (newId) {  // only store in Bd if first time message is stored
+                Dbt data(buff,size);
+                messageDb.put(txn->get(), &messageId, &data, DB_NOOVERWRITE);
+            }
+        }
+    } catch (const journal::jexception& e) {
+        THROW_STORE_EXCEPTION(std::string("Queue ") + queue->getName() + ": store() failed: " +
+                              e.what());
+    }
+}
+
+void MessageStoreImpl::dequeue(TransactionContext* ctxt,
+                              const intrusive_ptr<PersistableMessage>& msg,
+                              const PersistableQueue& queue)
+{
+    checkInit();
+    u_int64_t queueId (queue.getPersistenceId());
+    u_int64_t messageId (msg->getPersistenceId());
+    if (messageId == 0) {
+        THROW_STORE_EXCEPTION("Error dequeing message, persistence id not set");
+    }
+    if (queueId == 0) {
+        THROW_STORE_EXCEPTION("Queue not created: " + queue.getName());
+    }
+
+    TxnCtxt implicit;
+    TxnCtxt* txn = 0;
+    if (ctxt) {
+        txn = check(ctxt);
+    } else {
+        txn = &implicit;
+    }
+
+    // add queue* to the txn map..
+    if (ctxt) txn->addXidRecord(queue.getExternalQueueStore());
+    async_dequeue(ctxt, msg, queue);
+
+    msg->dequeueComplete();
+}
+
+void MessageStoreImpl::async_dequeue(TransactionContext* ctxt,
+                                    const intrusive_ptr<PersistableMessage>& msg,
+                                    const PersistableQueue& queue)
+{
+    boost::intrusive_ptr<DataTokenImpl> ddtokp(new DataTokenImpl);
+    ddtokp->addRef();
+    ddtokp->setSourceMessage(msg);
+    ddtokp->set_external_rid(true);
+    ddtokp->set_rid(messageIdSequence.next());
+    ddtokp->set_dequeue_rid(msg->getPersistenceId());
+    ddtokp->set_wstate(DataTokenImpl::ENQ);
+    std::string tid;
+    if (ctxt) {
+        TxnCtxt* txn = check(ctxt);
+        tid = txn->getXid();
+    }
+    try {
+        JournalImpl* jc = static_cast<JournalImpl*>(queue.getExternalQueueStore());
+        if (tid.empty()) {
+            jc->dequeue_data_record(ddtokp.get());
+        } else {
+            jc->dequeue_txn_data_record(ddtokp.get(), tid);
+        }
+    } catch (const journal::jexception& e) {
+        THROW_STORE_EXCEPTION(std::string("Queue ") + queue.getName() + ": async_dequeue() failed: " + e.what());
+    }
+}
+
+u_int32_t MessageStoreImpl::outstandingQueueAIO(const qpid::broker::PersistableQueue& /*queue*/)
+{
+    checkInit();
+    return 0;
+}
+
+bool MessageStoreImpl::deleteIfUnused(DbTxn* txn,
+                                     Dbt& messageId)
+{
+    Cursor cursor;
+    cursor.open(mappingDb, txn);
+    return deleteIfUnused(cursor, txn, messageId);
+}
+
+bool MessageStoreImpl::deleteIfUnused(Cursor& cursor,
+                                     DbTxn* txn,
+                                     Dbt& messageId)
+{
+    if (isUnused(cursor, messageId)) {
+        messageDb.del(txn, &messageId, 0);
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool MessageStoreImpl::isUnused(Cursor& cursor, Dbt& messageId)
+{
+    Dbt empty;
+    int status = cursor->get(&messageId, &empty, DB_SET);
+    if (status == DB_NOTFOUND) {
+        return true;
+    } else if (status == 0) {
+        return false;
+    } else {
+        THROW_STORE_EXCEPTION("Dequeue failed (in isUnused()) with status = " + status);
+    }
+}
+
+void MessageStoreImpl::completed(TxnCtxt& txn,
+                                bool commit)
+{
+    try {
+        chkTplStoreInit(); // Late initialize (if needed)
+
+        // Nothing to do if not prepared
+        if (txn.getDtok()->is_enqueued()) {
+            txn.incrDtokRef();
+            DataTokenImpl* dtokp = txn.getDtok();
+            dtokp->set_dequeue_rid(dtokp->rid());
+            dtokp->set_rid(messageIdSequence.next());
+            tplStorePtr->dequeue_txn_data_record(txn.getDtok(), txn.getXid(), commit);
+        }
+        txn.complete(commit);
+        if (mgmtObject != 0) {
+            mgmtObject->dec_tplTransactionDepth();
+            if (commit)
+                mgmtObject->inc_tplTxnCommits();
+            else
+                mgmtObject->inc_tplTxnAborts();
+        }
+    } catch (const std::exception& e) {
+        QPID_LOG(error, "Error completing xid " << txn.getXid() << ": " << e.what());
+        throw;
+    }
+}
+
+auto_ptr<TransactionContext> MessageStoreImpl::begin()
+{
+    checkInit();
+    // pass sequence number for c/a
+    return auto_ptr<TransactionContext>(new TxnCtxt(&messageIdSequence));
+}
+
+std::auto_ptr<qpid::broker::TPCTransactionContext> MessageStoreImpl::begin(const std::string& xid)
+{
+    checkInit();
+    IdSequence* jtx = &messageIdSequence;
+    // pass sequence number for c/a
+    return auto_ptr<TPCTransactionContext>(new TPCTxnCtxt(xid, jtx));
+}
+
+void MessageStoreImpl::prepare(qpid::broker::TPCTransactionContext& ctxt)
+{
+    checkInit();
+    TxnCtxt* txn = dynamic_cast<TxnCtxt*>(&ctxt);
+    if(!txn) throw InvalidTransactionContextException();
+    localPrepare(txn);
+}
+
+void MessageStoreImpl::localPrepare(TxnCtxt* ctxt)
+{
+    try {
+        chkTplStoreInit(); // Late initialize (if needed)
+
+        // This sync is requred to ensure multi-queue atomicity - ie all txn data
+        // must hit the disk on *all* queues before the TPL prepare (enq) is written.
+        ctxt->sync();
+
+        ctxt->incrDtokRef();
+        DataTokenImpl* dtokp = ctxt->getDtok();
+        dtokp->set_external_rid(true);
+        dtokp->set_rid(messageIdSequence.next());
+        char tpcFlag = static_cast<char>(ctxt->isTPC());
+        tplStorePtr->enqueue_txn_data_record(&tpcFlag, sizeof(char), sizeof(char), dtokp, ctxt->getXid(), false);
+        ctxt->prepare(tplStorePtr.get());
+        // make sure all the data is written to disk before returning
+        ctxt->sync();
+        if (mgmtObject != 0) {
+            mgmtObject->inc_tplTransactionDepth();
+            mgmtObject->inc_tplTxnPrepares();
+        }
+    } catch (const std::exception& e) {
+        QPID_LOG(error, "Error preparing xid " << ctxt->getXid() << ": " << e.what());
+        throw;
+    }
+}
+
+void MessageStoreImpl::commit(TransactionContext& ctxt)
+{
+    checkInit();
+    TxnCtxt* txn(check(&ctxt));
+    if (!txn->isTPC()) {
+        if (txn->impactedQueuesEmpty()) return;
+        localPrepare(dynamic_cast<TxnCtxt*>(txn));
+    }
+    completed(*dynamic_cast<TxnCtxt*>(txn), true);
+}
+
+void MessageStoreImpl::abort(TransactionContext& ctxt)
+{
+    checkInit();
+    TxnCtxt* txn(check(&ctxt));
+    if (!txn->isTPC()) {
+        if (txn->impactedQueuesEmpty()) return;
+        localPrepare(dynamic_cast<TxnCtxt*>(txn));
+    }
+    completed(*dynamic_cast<TxnCtxt*>(txn), false);
+}
+
+TxnCtxt* MessageStoreImpl::check(TransactionContext* ctxt)
+{
+    TxnCtxt* txn = dynamic_cast<TxnCtxt*>(ctxt);
+    if(!txn) throw InvalidTransactionContextException();
+    return txn;
+}
+
+void MessageStoreImpl::put(Db& db,
+                          DbTxn* txn,
+                          Dbt& key,
+                          Dbt& value)
+{
+    try {
+        int status = db.put(txn, &key, &value, DB_NODUPDATA);
+        if (status == DB_KEYEXIST) {
+            THROW_STORE_EXCEPTION("duplicate data");
+        } else if (status) {
+            THROW_STORE_EXCEPTION(DbEnv::strerror(status));
+        }
+    } catch (const DbException& e) {
+        THROW_STORE_EXCEPTION(e.what());
+    }
+}
+
+bool MessageStoreImpl::deleteKeyValuePair(Db& db,
+                                         DbTxn* txn,
+                                         Dbt& key,
+                                         Dbt& value)
+{
+    Cursor cursor;
+    cursor.open(db, txn);
+    int status = cursor->get(&key, &value, DB_GET_BOTH | DB_RMW);
+    if (status == 0) {
+        cursor->del(0);
+        return true;
+    } else if (status == DB_NOTFOUND) {
+        return false;
+    } else {
+        THROW_STORE_EXCEPTION("Deletion failed: " + std::string(DbEnv::strerror(status)));
+    }
+}
+
+void MessageStoreImpl::deleteBindingsForQueue(const PersistableQueue& queue)
+{
+    TxnCtxt txn;
+    txn.begin(env, true);
+    try {
+        {
+            Cursor bindings;
+            bindings.open(bindingDb, txn.get());
+
+            IdDbt key;
+            Dbt value;
+            while (bindings.next(key, value)) {
+                Buffer buffer(reinterpret_cast<char*>(value.get_data()), value.get_size());
+                if (buffer.available() < 8) {
+                    THROW_STORE_EXCEPTION("Not enough data for binding");
+                }
+                uint64_t queueId = buffer.getLongLong();
+                if (queue.getPersistenceId() == queueId) {
+                    bindings->del(0);
+                    QPID_LOG(debug, "Deleting binding for " << queue.getName() << " " << key.id << "->" << queueId);
+                }
+            }
+        }
+        txn.commit();
+    } catch (const std::exception& e) {
+        txn.abort();
+        THROW_STORE_EXCEPTION_2("Error deleting bindings", e.what());
+    } catch (...) {
+        txn.abort();
+        throw;
+    }
+    QPID_LOG(debug, "Deleted all bindings for " << queue.getName() << ":" << queue.getPersistenceId());
+}
+
+void MessageStoreImpl::deleteBinding(const PersistableExchange& exchange,
+                                    const PersistableQueue& queue,
+                                    const std::string& bkey)
+{
+    TxnCtxt txn;
+    txn.begin(env, true);
+    try {
+        {
+            Cursor bindings;
+            bindings.open(bindingDb, txn.get());
+
+            IdDbt key(exchange.getPersistenceId());
+            Dbt value;
+
+            for (int status = bindings->get(&key, &value, DB_SET); status == 0; status = bindings->get(&key, &value, DB_NEXT_DUP)) {
+                Buffer buffer(reinterpret_cast<char*>(value.get_data()), value.get_size());
+                if (buffer.available() < 8) {
+                    THROW_STORE_EXCEPTION("Not enough data for binding");
+                }
+                uint64_t queueId = buffer.getLongLong();
+                if (queue.getPersistenceId() == queueId) {
+                    std::string q;
+                    std::string k;
+                    buffer.getShortString(q);
+                    buffer.getShortString(k);
+                    if (bkey == k) {
+                        bindings->del(0);
+                        QPID_LOG(debug, "Deleting binding for " << queue.getName() << " " << key.id << "->" << queueId);
+                    }
+                }
+            }
+        }
+        txn.commit();
+    } catch (const std::exception& e) {
+        txn.abort();
+        THROW_STORE_EXCEPTION_2("Error deleting bindings", e.what());
+    } catch (...) {
+        txn.abort();
+        throw;
+    }
+}
+
+std::string MessageStoreImpl::getJrnlBaseDir()
+{
+    std::stringstream dir;
+    dir << storeDir << "/rhm/jrnl/" ;
+    return dir.str();
+}
+
+std::string MessageStoreImpl::getBdbBaseDir()
+{
+    std::stringstream dir;
+    dir << storeDir << "/rhm/dat/" ;
+    return dir.str();
+}
+
+std::string MessageStoreImpl::getTplBaseDir()
+{
+    std::stringstream dir;
+    dir << storeDir << "/rhm/tpl/" ;
+    return dir.str();
+}
+
+std::string MessageStoreImpl::getJrnlDir(const qpid::broker::PersistableQueue& queue) //for exmaple /var/rhm/ + queueDir/
+{
+    return getJrnlDir(queue.getName().c_str());
+}
+
+std::string MessageStoreImpl::getJrnlDir(const char* queueName) //for exmaple /var/rhm/ + queueDir/
+{
+    std::stringstream dir;
+    dir << getJrnlBaseDir() << std::hex << std::setfill('0') << std::setw(4);
+    u_int32_t count = 0;
+    for (u_int32_t i = 0; i < strlen(queueName); i++) {
+        count += queueName[i];
+    }
+    dir << (count % 29); // Use a prime number for better distribution across dirs
+    dir << "/" << queueName << "/";
+    return dir.str();
+}
+
+MessageStoreImpl::Options::Options(const std::string& name) :
+                                  qpid::Options(name),
+                                  numJrnlFiles(defNumJrnlFiles),
+                                  jrnlFsizePgs(defJrnlFileSizePgs),
+                                  wCachePageSizeKib(defWCachePageSize),
+                                  tplNumJrnlFiles(defTplNumJrnlFiles),
+                                  tplJrnlFsizePgs(defTplJrnlFileSizePgs),
+                                  tplWCachePageSizeKib(defTplWCachePageSize)
+{
+    addOptions()
+        ("store-dir", qpid::optValue(storeDir, "DIR"),
+         "Store directory location for persistence (instead of using --data-dir value). "
+         "Must be supplied if --no-data-dir is also used.")
+        ("num-jfiles", qpid::optValue(numJrnlFiles, "N"),
+         "Default number of files for each journal instance")
+        ("jfile-size-pgs", qpid::optValue(jrnlFsizePgs, "N"),
+         "Default size for each journal file in multiples of read pages (1 read page = 64kiB)")
+        ("wcache-page-size", qpid::optValue(wCachePageSizeKib, "N"),
+         "Size of the pages in the write page cache in KiB. "
+         "Allowable values - powers of 2: 1, 2, 4, ... , 128. "
+         "Lower values decrease latency at the expense of throughput.")
+        ("tpl-num-jfiles", qpid::optValue(tplNumJrnlFiles, "N"),
+         "Number of files for transaction prepared list journal instance")
+        ("tpl-jfile-size-pgs", qpid::optValue(tplJrnlFsizePgs, "N"),
+         "Size of each transaction prepared list journal file in multiples of read pages (1 read page = 64kiB)")
+        ("tpl-wcache-page-size", qpid::optValue(tplWCachePageSizeKib, "N"),
+         "Size of the pages in the transaction prepared list write page cache in KiB. "
+         "Allowable values - powers of 2: 1, 2, 4, ... , 128. "
+         "Lower values decrease latency at the expense of throughput.")
+        ;
+}

Copied: store/trunk/cpp/lib/MessageStoreImpl.h (from rev 2432, store/trunk/cpp/lib/BdbMessageStore.h)
===================================================================
--- store/trunk/cpp/lib/MessageStoreImpl.h	                        (rev 0)
+++ store/trunk/cpp/lib/MessageStoreImpl.h	2008-09-09 19:25:47 UTC (rev 2433)
@@ -0,0 +1,348 @@
+/*
+  Copyright (C) 2007 Red Hat Software
+
+  This file is part of Red Hat Messaging.
+
+  Red Hat Messaging is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+  USA
+
+  The GNU Lesser General Public License is available in the file COPYING.
+*/
+
+#ifndef _MessageStoreImpl_
+#define _MessageStoreImpl_
+
+#include <string>
+
+#include "db-inc.h"
+#include "Cursor.h"
+#include "IdDbt.h"
+#include "IdSequence.h"
+#include "JournalImpl.h"
+#include "jrnl/jcfg.hpp"
+#include "PreparedTransaction.h"
+#include "qpid/broker/Broker.h"
+#include "qpid/broker/MessageStore.h"
+#include "qpid/management/Manageable.h"
+#include "Store.h"
+#include "TxnCtxt.h"
+
+// Assume DB_VERSION_MAJOR == 4
+#if (DB_VERSION_MINOR == 2)
+#include <errno.h>
+#define DB_BUFFER_SMALL ENOMEM
+#endif
+
+namespace rhm {
+namespace bdbstore {
+
+/**
+ * An implementation of the MessageStore interface based on Berkeley DB
+ */
+class MessageStoreImpl : public qpid::broker::MessageStore, public qpid::management::Manageable
+{
+  protected:
+    typedef std::map<u_int64_t, qpid::broker::RecoverableQueue::shared_ptr> queue_index;
+    typedef std::map<u_int64_t, qpid::broker::RecoverableExchange::shared_ptr> exchange_index;
+    typedef std::map<u_int64_t, qpid::broker::RecoverableMessage::shared_ptr> message_index;
+
+    typedef LockedMappings::map txn_lock_map;
+    typedef boost::ptr_list<PreparedTransaction> txn_list;
+
+    // Structs for Transaction Recover List (TPL) recover state
+    struct TplRecoverStruct {
+        u_int64_t rid; // rid of TPL record
+        bool deq_flag;
+        bool commit_flag;
+        bool tpc_flag;
+        TplRecoverStruct(const u_int64_t _rid, const bool _deq_flag, const bool _commit_flag, const bool _tpc_flag);
+    };
+    typedef TplRecoverStruct TplRecover;
+    typedef std::pair<std::string, TplRecover> TplRecoverMapPair;
+    typedef std::map<std::string, TplRecover> TplRecoverMap;
+    typedef TplRecoverMap::const_iterator TplRecoverMapCitr;
+
+    // Default store settings
+    static const u_int16_t defNumJrnlFiles = 8;
+    static const u_int32_t defJrnlFileSizePgs = 24;
+    static const u_int32_t defWCachePageSize = JRNL_WMGR_DEF_PAGE_SIZE * JRNL_DBLK_SIZE * JRNL_SBLK_SIZE / 1024;
+    static const u_int16_t defTplNumJrnlFiles = 8;
+    static const u_int32_t defTplJrnlFileSizePgs = 24;
+    static const u_int32_t defTplWCachePageSize = defWCachePageSize / 8;
+
+    std::list<Db*> dbs;
+    DbEnv env;
+    Db queueDb;
+    Db configDb;
+    Db exchangeDb;
+    Db messageDb;
+    Db mappingDb;
+    Db bindingDb;
+    Db generalDb;
+
+    // Pointer to Transaction Prepared List (TPL) journal instance
+    boost::shared_ptr<TplJournalImpl> tplStorePtr;
+    TplRecoverMap tplRecoverMap;
+
+    IdSequence queueIdSequence;
+    IdSequence exchangeIdSequence;
+    IdSequence generalIdSequence;
+    IdSequence messageIdSequence;
+    std::string storeDir;
+    u_int16_t numJrnlFiles;
+    u_int32_t jrnlFsizeSblks;
+    u_int32_t wCachePgSizeSblks;
+    u_int16_t wCacheNumPages;
+    u_int16_t tplNumJrnlFiles;
+    u_int32_t tplJrnlFsizeSblks;
+    u_int32_t tplWCachePgSizeSblks;
+    u_int16_t tplWCacheNumPages;
+    u_int64_t highestRid;
+    bool isInit;
+    const char* envPath;
+    static qpid::sys::Duration defJournalGetEventsTimeout;
+    static qpid::sys::Duration defJournalFlushTimeout;
+    qpid::management::Store* mgmtObject;
+    qpid::sys::Mutex jrnlCreateLock;
+
+    // Parameter validation and calculation
+    static u_int16_t chkJrnlNumFilesParam(const u_int16_t param,
+                                          const std::string paramName);
+    static u_int32_t chkJrnlFileSizeParam(const u_int32_t param,
+                                          const std::string paramName);
+    static u_int32_t chkJrnlWrPageCacheSize(const u_int32_t param,
+                                            const std::string paramName);
+    static u_int16_t getJrnlWrNumPages(const u_int32_t wrPageSizeKib);
+
+    void recoverQueues(TxnCtxt& txn,
+                       qpid::broker::RecoveryManager& recovery,
+                       queue_index& index,
+                       txn_list& locked,
+                       message_index& messages);
+    void recoverMessages(TxnCtxt& txn,
+                         qpid::broker::RecoveryManager& recovery,
+                         queue_index& index,
+                         txn_list& locked,
+                         message_index& prepared);
+    void recoverMessages(TxnCtxt& txn,
+                         qpid::broker::RecoveryManager& recovery,
+                         qpid::broker::RecoverableQueue::shared_ptr& queue,
+                         txn_list& locked,
+                         message_index& prepared);
+    qpid::broker::RecoverableMessage::shared_ptr getExternMessage(qpid::broker::RecoveryManager& recovery,
+                                                                  uint64_t mId,
+                                                                  unsigned& headerSize);
+    void recoverExchanges(TxnCtxt& txn,
+                          qpid::broker::RecoveryManager& recovery,
+                          exchange_index& index);
+    void recoverBindings(TxnCtxt& txn,
+                         exchange_index& exchanges,
+                         queue_index& queues);
+    void recoverGeneral(TxnCtxt& txn,
+                        qpid::broker::RecoveryManager& recovery);
+    int enqueueMessage(TxnCtxt& txn,
+                       IdDbt& msgId,
+                       qpid::broker::RecoverableMessage::shared_ptr& msg,
+                       queue_index& index,
+                       txn_list& locked,
+                       message_index& prepared);
+    void readTplStore();
+    void recoverTplStore();
+    void recoverLockedMappings(txn_list& txns);
+    TxnCtxt* check(qpid::broker::TransactionContext* ctxt);
+    void store(const qpid::broker::PersistableQueue* queue,
+               TxnCtxt* txn,
+               Dbt& messageId,
+               const boost::intrusive_ptr<qpid::broker::PersistableMessage>& message,
+               bool newId);
+    void async_dequeue(qpid::broker::TransactionContext* ctxt,
+                       const boost::intrusive_ptr<qpid::broker::PersistableMessage>& msg,
+                       const qpid::broker::PersistableQueue& queue);
+    bool deleteIfUnused(Cursor& cursor,
+                        DbTxn* txn,
+                        Dbt& messageId);
+    bool deleteIfUnused(DbTxn* txn,
+                        Dbt& messageId);
+    bool isUnused(Cursor& cursor,
+                  Dbt& messageId);
+    void destroy(Db& db,
+                 const qpid::broker::Persistable& p);
+    bool create(Db& db,
+                IdSequence& seq,
+                const qpid::broker::Persistable& p);
+    void completed(TxnCtxt& txn,
+                   bool commit);
+    void record2pcOp(Db& db,
+                     TPCTxnCtxt& txn,
+                     u_int64_t messageId,
+                     u_int64_t queueId);
+    void deleteBindingsForQueue(const qpid::broker::PersistableQueue& queue);
+    void deleteBinding(const qpid::broker::PersistableExchange& exchange,
+                       const qpid::broker::PersistableQueue& queue,
+                       const std::string& key);
+
+    u_int64_t getRecordSize(Db& db,
+                            Dbt& key);
+    u_int64_t getRecordSize(DbTxn* txn,
+                            Db& db,
+                            Dbt& key);
+    void put(Db& db,
+             DbTxn* txn,
+             Dbt& key,
+             Dbt& value);
+    bool deleteKeyValuePair(Db& db,
+                            DbTxn* txn,
+                            Dbt& key,
+                            Dbt& value);
+    void open(Db& db,
+              DbTxn* txn,
+              const char* file,
+              bool dupKey);
+
+    // journal functions
+    void createJrnlQueue(const qpid::broker::PersistableQueue& queue);
+    std::string getJrnlDir(const qpid::broker::PersistableQueue& queue); //for exmaple /var/rhm/ + queueDir/
+    std::string getJrnlDir(const char* queueName);
+    std::string getJrnlBaseDir();
+    std::string getBdbBaseDir();
+    std::string getTplBaseDir();
+    inline void checkInit() {
+        // TODO: change the default dir to ~/.qpidd
+        if (!isInit) init("/tmp", defNumJrnlFiles, defJrnlFileSizePgs, defWCachePageSize); isInit = true;
+    }
+    void chkTplStoreInit();
+
+    // debug aid for printing XIDs that may contain non-printable chars
+    static std::string xid2str(const std::string xid) {
+        std::ostringstream oss;
+        oss << std::hex << std::setfill('0');
+        for (unsigned i=0; i<xid.size(); i++) {
+            if (isprint(xid[i]))
+                oss << xid[i];
+            else
+                oss << "/" << std::setw(2) << (int)((char)xid[i]);
+        }
+        return oss.str();
+    }
+
+  public:
+    struct Options : public qpid::Options {
+        Options(const std::string& name="Store Options");
+        std::string clusterName;
+        std::string storeDir;
+        u_int16_t numJrnlFiles;
+        u_int32_t jrnlFsizePgs;
+        u_int32_t wCachePageSizeKib;
+        u_int16_t tplNumJrnlFiles;
+        u_int32_t tplJrnlFsizePgs;
+        u_int32_t tplWCachePageSizeKib;
+    };
+
+    typedef boost::shared_ptr<MessageStoreImpl> shared_ptr;
+
+    MessageStoreImpl(const char* envpath = 0);
+
+    virtual ~MessageStoreImpl();
+
+    bool init(const qpid::Options* options);
+
+    bool init(const std::string& dir,
+              u_int16_t jfiles = defNumJrnlFiles,
+              u_int32_t jfileSizePgs = defJrnlFileSizePgs,
+              u_int32_t wCachePageSize = defWCachePageSize,
+              u_int16_t tplJfiles = defTplNumJrnlFiles,
+              u_int32_t tplJfileSizePgs = defTplJrnlFileSizePgs,
+              u_int32_t tplWCachePageSize = defTplWCachePageSize);
+
+    void initManagement (qpid::broker::Broker* broker);
+
+    void truncate();
+
+    void create(qpid::broker::PersistableQueue& queue,
+                const qpid::framing::FieldTable& args);
+
+    void destroy(qpid::broker::PersistableQueue& queue);
+
+    void create(const qpid::broker::PersistableExchange& queue,
+                const qpid::framing::FieldTable& args);
+
+    void destroy(const qpid::broker::PersistableExchange& queue);
+
+    void bind(const qpid::broker::PersistableExchange& exchange,
+              const qpid::broker::PersistableQueue& queue,
+              const std::string& key,
+              const qpid::framing::FieldTable& args);
+
+    void unbind(const qpid::broker::PersistableExchange& exchange,
+                const qpid::broker::PersistableQueue& queue,
+                const std::string& key,
+                const qpid::framing::FieldTable& args);
+
+    void create(const qpid::broker::PersistableConfig& config);
+
+    void destroy(const qpid::broker::PersistableConfig& config);
+
+    void recover(qpid::broker::RecoveryManager& queues);
+
+    void stage(const boost::intrusive_ptr<qpid::broker::PersistableMessage>& msg);
+
+    void destroy(qpid::broker::PersistableMessage& msg);
+
+    void appendContent(const boost::intrusive_ptr<const qpid::broker::PersistableMessage>& msg,
+                       const std::string& data);
+
+    void loadContent(const qpid::broker::PersistableQueue& queue,
+                     const boost::intrusive_ptr<const qpid::broker::PersistableMessage>& msg,
+                     std::string& data,
+                     u_int64_t offset,
+                     u_int32_t length);
+
+    void enqueue(qpid::broker::TransactionContext* ctxt,
+                 const boost::intrusive_ptr<qpid::broker::PersistableMessage>& msg,
+                 const qpid::broker::PersistableQueue& queue);
+
+    void dequeue(qpid::broker::TransactionContext* ctxt,
+                 const boost::intrusive_ptr<qpid::broker::PersistableMessage>& msg,
+                 const qpid::broker::PersistableQueue& queue);
+
+    void flush(const qpid::broker::PersistableQueue& queue);
+
+    u_int32_t outstandingQueueAIO(const qpid::broker::PersistableQueue& queue);
+
+    void collectPreparedXids(std::set<std::string>& xids);
+
+    std::auto_ptr<qpid::broker::TransactionContext> begin();
+
+    std::auto_ptr<qpid::broker::TPCTransactionContext> begin(const std::string& xid);
+
+    void prepare(qpid::broker::TPCTransactionContext& ctxt);
+
+    void localPrepare(TxnCtxt* ctxt);
+
+    void commit(qpid::broker::TransactionContext& ctxt);
+
+    void abort(qpid::broker::TransactionContext& ctxt);
+
+    qpid::management::ManagementObject* GetManagementObject (void) const
+        { return mgmtObject; }
+
+    inline qpid::management::Manageable::status_t ManagementMethod (u_int32_t, qpid::management::Args&)
+        { return qpid::management::Manageable::STATUS_OK; }
+}; // class MessageStoreImpl
+
+} // namespace bdbstore
+} // namespace rhm
+
+#endif

Modified: store/trunk/cpp/lib/StorePlugin.cpp
===================================================================
--- store/trunk/cpp/lib/StorePlugin.cpp	2008-09-09 13:39:28 UTC (rev 2432)
+++ store/trunk/cpp/lib/StorePlugin.cpp	2008-09-09 19:25:47 UTC (rev 2433)
@@ -25,7 +25,7 @@
 #include "qpid/Plugin.h"
 #include "qpid/Options.h"
 #include "qpid/DataDir.h"
-#include "BdbMessageStore.h"
+#include "MessageStoreImpl.h"
 
 
 namespace qpid {
@@ -35,7 +35,7 @@
 
 struct StorePlugin : public Plugin {
 
-    rhm::bdbstore::BdbMessageStore::Options options;
+    rhm::bdbstore::MessageStoreImpl::Options options;
     MessageStore *store;
 
     Options* getOptions() { return &options; }
@@ -43,7 +43,7 @@
     void earlyInitialize (Plugin::Target& target)
     {
         Broker* broker = dynamic_cast<Broker*>(&target);
-        store = new rhm::bdbstore::BdbMessageStore ();
+        store = new rhm::bdbstore::MessageStoreImpl ();
         DataDir& dataDir = broker->getDataDir ();
 
         if (options.storeDir.empty ())
@@ -60,7 +60,7 @@
     void initialize(Plugin::Target& target)
     {
         Broker* broker = dynamic_cast<Broker*>(&target);
-        ((rhm::bdbstore::BdbMessageStore*) store)->initManagement (broker);
+        ((rhm::bdbstore::MessageStoreImpl*) store)->initManagement (broker);
     }
 };
 

Modified: store/trunk/cpp/tests/OrderingTest.cpp
===================================================================
--- store/trunk/cpp/tests/OrderingTest.cpp	2008-09-09 13:39:28 UTC (rev 2432)
+++ store/trunk/cpp/tests/OrderingTest.cpp	2008-09-09 19:25:47 UTC (rev 2433)
@@ -27,7 +27,7 @@
 
 #include "unit_test.h"
 
-#include "BdbMessageStore.h"
+#include "MessageStoreImpl.h"
 #include <iostream>
 #include "MessageUtils.h"
 #include <qpid/broker/Queue.h>
@@ -47,7 +47,7 @@
 // === Helper fns ===
 
 const string name("OrderingQueue");
-std::auto_ptr<BdbMessageStore> store;
+std::auto_ptr<MessageStoreImpl> store;
 QueueRegistry queues;
 Queue::shared_ptr queue;
 std::queue<Uuid> ids;
@@ -55,7 +55,7 @@
 
 void setup()
 {
-    store = std::auto_ptr<BdbMessageStore>(new BdbMessageStore());
+    store = std::auto_ptr<MessageStoreImpl>(new MessageStoreImpl());
     store->init(test_dir, 4, 1, 8);
 	store->truncate();
 
@@ -93,7 +93,7 @@
     queue.reset();
     store.reset();
 
-    store = std::auto_ptr<BdbMessageStore>(new BdbMessageStore());
+    store = std::auto_ptr<MessageStoreImpl>(new MessageStoreImpl());
     store->init(test_dir, 4, 1, 8);
     ExchangeRegistry exchanges;
     LinkRegistry links(0);

Modified: store/trunk/cpp/tests/SimpleTest.cpp
===================================================================
--- store/trunk/cpp/tests/SimpleTest.cpp	2008-09-09 13:39:28 UTC (rev 2432)
+++ store/trunk/cpp/tests/SimpleTest.cpp	2008-09-09 19:25:47 UTC (rev 2433)
@@ -27,7 +27,7 @@
 
 #include "unit_test.h"
 
-#include "BdbMessageStore.h"
+#include "MessageStoreImpl.h"
 #include <iostream>
 #include "MessageUtils.h"
 #include <qpid/broker/Queue.h>
@@ -60,7 +60,7 @@
     }
 };
 
-void recover(BdbMessageStore& store, QueueRegistry& queues, ExchangeRegistry& exchanges, LinkRegistry& links)
+void recover(MessageStoreImpl& store, QueueRegistry& queues, ExchangeRegistry& exchanges, LinkRegistry& links)
 {
     DtxManager mgr;
     mgr.setStore (&store);
@@ -68,14 +68,14 @@
     store.recover(recovery);
 }
 
-void recover(BdbMessageStore& store, ExchangeRegistry& exchanges)
+void recover(MessageStoreImpl& store, ExchangeRegistry& exchanges)
 {
     QueueRegistry queues;
     LinkRegistry links(0);
     recover(store, queues, exchanges, links);
 }
 
-void recover(BdbMessageStore& store, QueueRegistry& queues)
+void recover(MessageStoreImpl& store, QueueRegistry& queues)
 {
     ExchangeRegistry exchanges;
     LinkRegistry links(0);
@@ -86,7 +86,7 @@
                    const string& key, const FieldTable& args)
 {
     {
-        BdbMessageStore store;
+        MessageStoreImpl store;
         store.init(test_dir, 4, 1, 8);
         store.truncate();//make sure it is empty to begin with
         Exchange::shared_ptr exchange(new DirectExchange(exchangeName, true, args));
@@ -97,7 +97,7 @@
         store.bind(*exchange, *queue, key, args);
     }//db will be closed
     {
-        BdbMessageStore store;
+        MessageStoreImpl store;
         store.init(test_dir, 4, 1, 8);
         ExchangeRegistry exchanges;
         QueueRegistry queues;
@@ -112,7 +112,7 @@
         store.unbind(*exchange, *queue, key, args);
     }
     {
-        BdbMessageStore store;
+        MessageStoreImpl store;
         store.init(test_dir, 4, 1, 8);
         ExchangeRegistry exchanges;
         QueueRegistry queues;
@@ -134,7 +134,7 @@
 {
     cout << test_filename << ".CreateDelete: " << flush;
 
-    BdbMessageStore store;
+    MessageStoreImpl store;
     store.init(test_dir, 4, 1, 8);
     store.truncate();//make sure it is empty to begin with
     string name("CreateDeleteQueue");
@@ -152,7 +152,7 @@
 {
     cout << test_filename << ".EmptyRecover: " << flush;
 
-    BdbMessageStore store;
+    MessageStoreImpl store;
     store.init(test_dir, 4, 1, 8);
     store.truncate();//make sure it is empty to begin with
     QueueRegistry registry;
@@ -170,7 +170,7 @@
     uint64_t id(0);
     string name("MyDurableQueue");
     {
-        BdbMessageStore store;
+        MessageStoreImpl store;
         store.init(test_dir, 4, 1, 8);
         store.truncate();//make sure it is empty to begin with
         Queue queue(name, 0, &store, 0);
@@ -179,7 +179,7 @@
         id = queue.getPersistenceId();
     }//db will be closed
     {
-        BdbMessageStore store;
+        MessageStoreImpl store;
         store.init(test_dir, 4, 1, 8);
         QueueRegistry registry;
         registry.setStore (&store);
@@ -199,7 +199,7 @@
     QueuePolicy policy(101, 202);
     string name("MyDurableQueue");
     {
-        BdbMessageStore store;
+        MessageStoreImpl store;
         store.init(test_dir, 4, 1, 8);
         store.truncate();//make sure it is empty to begin with
         Queue queue(name, 0, &store, 0);
@@ -209,7 +209,7 @@
         BOOST_REQUIRE(queue.getPersistenceId());
     }//db will be closed
     {
-        BdbMessageStore store;
+        MessageStoreImpl store;
         store.init(test_dir, 4, 1, 8);
         QueueRegistry registry;
         registry.setStore (&store);
@@ -230,7 +230,7 @@
 
     string name("MyDurableQueue");
     {
-        BdbMessageStore store;
+        MessageStoreImpl store;
         store.init(test_dir, 4, 1, 8);
         store.truncate();//make sure it is empty to begin with
         Queue queue(name, 0, &store, 0);
@@ -238,7 +238,7 @@
         store.destroy(queue);
     }//db will be closed
     {
-        BdbMessageStore store;
+        MessageStoreImpl store;
         store.init(test_dir, 4, 1, 8);
         QueueRegistry registry;
         registry.setStore (&store);
@@ -264,7 +264,7 @@
     string data1("abcdefg");
     string data2("hijklmn");
     {
-        BdbMessageStore store;
+        MessageStoreImpl store;
         store.init(test_dir, 4, 1, 8);
         store.truncate();//make sure it is empty to begin with
         Queue::shared_ptr queue(new Queue(name, 0, &store, 0));
@@ -283,7 +283,7 @@
         queue->enqueue(0, msg);
     }//db will be closed
     {
-        BdbMessageStore store;
+        MessageStoreImpl store;
         store.init(test_dir, 4, 1, 8);
         QueueRegistry registry;
         registry.setStore (&store);
@@ -324,7 +324,7 @@
         string routingKey("MyRoutingKey");
         Uuid messageId(true);
         string data("abcdefg");
-        BdbMessageStore store;
+        MessageStoreImpl store;
         store.init(test_dir, 4, 1, 8);
         store.truncate();//make sure it is empty to begin with
         Queue::shared_ptr queue(new Queue(name, 0, &store, 0));
@@ -339,7 +339,7 @@
         queue->dequeue(0, msg);
     }//db will be closed
     {
-        BdbMessageStore store;
+        MessageStoreImpl store;
         store.init(test_dir, 4, 1, 8);
         QueueRegistry registry;
         registry.setStore (&store);
@@ -363,7 +363,7 @@
     const string data1("abcdefghijklmnopqrstuvwxyz");
     const string data2("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
     {
-        BdbMessageStore store;
+        MessageStoreImpl store;
         store.init(test_dir, 4, 1, 8);
         store.truncate();//make sure it is empty to begin with
 
@@ -405,7 +405,7 @@
     }//db will be closed
     {
         //recover
-        BdbMessageStore store;
+        MessageStoreImpl store;
         store.init(test_dir, 4, 1, 8);
         QueueRegistry registry;
         registry.setStore (&store);
@@ -457,7 +457,7 @@
 {
     cout << test_filename << ".DestroyStagedMessage: " << flush;
 
-    BdbMessageStore store;
+    MessageStoreImpl store;
     store.init(test_dir, 4, 1, 8);
     store.truncate();//make sure it is empty to begin with
     
@@ -485,7 +485,7 @@
 {
     cout << test_filename << ".DestroyEnqueuedMessage: " << flush;
 
-    BdbMessageStore store;
+    MessageStoreImpl store;
     store.init(test_dir, 4, 1, 8);
     store.truncate();//make sure it is empty to begin with
     
@@ -521,7 +521,7 @@
     FieldTable args;
     args.setString("a", "A");
     {
-        BdbMessageStore store;
+        MessageStoreImpl store;
         store.init(test_dir, 4, 1, 8);
         store.truncate();//make sure it is empty to begin with
         ExchangeRegistry registry;
@@ -531,7 +531,7 @@
         BOOST_REQUIRE(id);
     }//db will be closed
     {
-        BdbMessageStore store;
+        MessageStoreImpl store;
         store.init(test_dir, 4, 1, 8);
         ExchangeRegistry registry;
 
@@ -545,7 +545,7 @@
         store.destroy(*exchange);
     }
     {
-        BdbMessageStore store;
+        MessageStoreImpl store;
         store.init(test_dir, 4, 1, 8);
         ExchangeRegistry registry;
 
@@ -593,7 +593,7 @@
     string key("my-routing-key");
     FieldTable args;
     {
-        BdbMessageStore store;
+        MessageStoreImpl store;
         store.init(test_dir, 4, 1, 8);
         store.truncate();//make sure it is empty to begin with
         Exchange::shared_ptr exchange(new DirectExchange(exchangeName, true, args));
@@ -608,7 +608,7 @@
         store.destroy(*queue1);
     }//db will be closed
     {
-        BdbMessageStore store;
+        MessageStoreImpl store;
         store.init(test_dir, 4, 1, 8);
         ExchangeRegistry exchanges;
         QueueRegistry queues;
@@ -625,7 +625,7 @@
         store.destroy(*exchange);
     }
     {
-        BdbMessageStore store;
+        MessageStoreImpl store;
         store.init(test_dir, 4, 1, 8);
         ExchangeRegistry exchanges;
         QueueRegistry queues;

Modified: store/trunk/cpp/tests/TransactionalTest.cpp
===================================================================
--- store/trunk/cpp/tests/TransactionalTest.cpp	2008-09-09 13:39:28 UTC (rev 2432)
+++ store/trunk/cpp/tests/TransactionalTest.cpp	2008-09-09 19:25:47 UTC (rev 2433)
@@ -27,7 +27,7 @@
 
 #include "unit_test.h"
 
-#include "BdbMessageStore.h"
+#include "MessageStoreImpl.h"
 #include <iostream>
 #include "MessageUtils.h"
 #include "qpid/broker/Queue.h"
@@ -61,10 +61,10 @@
 
 // Test store which has sepcial begin() which returns a TestTPCTxnCtxt, and a method to check for
 // reamining open transactions
-class TestMessageStore: public BdbMessageStore
+class TestMessageStore: public MessageStoreImpl
 {
   public:
-    TestMessageStore(const char* envpath = 0) : BdbMessageStore(envpath) {}
+    TestMessageStore(const char* envpath = 0) : MessageStoreImpl(envpath) {}
     std::auto_ptr<qpid::broker::TransactionContext> begin() {
         checkInit();
         // pass sequence number for c/a
@@ -96,7 +96,7 @@
 const string nameA("queueA");
 const string nameB("queueB");
 //const Uuid messageId(true);
-std::auto_ptr<BdbMessageStore> store;
+std::auto_ptr<MessageStoreImpl> store;
 std::auto_ptr<QueueRegistry> queues;
 Queue::shared_ptr queueA;
 Queue::shared_ptr queueB;
@@ -159,7 +159,7 @@
 
 void swap(bool commit)
 {
-    setup<BdbMessageStore>();
+    setup<MessageStoreImpl>();
 
     //create message and enqueue it onto first queue:
     boost::intrusive_ptr<Message> msgA = createMessage("Message", "exchange", "routing_key");
@@ -177,7 +177,7 @@
         store->abort(*txn);
     }
 
-    restart<BdbMessageStore>();
+    restart<MessageStoreImpl>();
 
     // Check outcome
     BOOST_REQUIRE(queueA);

Modified: store/trunk/cpp/tests/TwoPhaseCommitTest.cpp
===================================================================
--- store/trunk/cpp/tests/TwoPhaseCommitTest.cpp	2008-09-09 13:39:28 UTC (rev 2432)
+++ store/trunk/cpp/tests/TwoPhaseCommitTest.cpp	2008-09-09 19:25:47 UTC (rev 2433)
@@ -27,7 +27,7 @@
 
 #include "unit_test.h"
 
-#include "BdbMessageStore.h"
+#include "MessageStoreImpl.h"
 #include <iostream>
 #include "MessageUtils.h"
 #include "qpid/broker/Queue.h"
@@ -175,10 +175,10 @@
 
     // Test store which has sepcial begin() which returns a TestTPCTxnCtxt, and a method to check for
     // reamining open transactions
-    class TestMessageStore: public BdbMessageStore
+    class TestMessageStore: public MessageStoreImpl
     {
       public:
-        TestMessageStore(const char* envpath = 0) : BdbMessageStore(envpath) {}
+        TestMessageStore(const char* envpath = 0) : MessageStoreImpl(envpath) {}
         std::auto_ptr<qpid::broker::TPCTransactionContext> begin(const std::string& xid) {
             checkInit();
             IdSequence* jtx = &messageIdSequence;
@@ -195,7 +195,7 @@
 
     const string nameA;
     const string nameB;
-    std::auto_ptr<BdbMessageStore> store;
+    std::auto_ptr<MessageStoreImpl> store;
     std::auto_ptr<DtxManager> dtxmgr;
     std::auto_ptr<QueueRegistry> queues;
     std::auto_ptr<LinkRegistry> links;
@@ -207,14 +207,14 @@
 
     void recoverPrepared(bool commit)
     {
-        setup<BdbMessageStore>();
+        setup<MessageStoreImpl>();
 
         Swap swap(this, "RecoverPrepared");
         swap.init();
         std::auto_ptr<TPCTransactionContext> txn(store->begin("my-xid"));
         swap.run(txn.get());
         store->prepare(*txn);
-        restart<BdbMessageStore>();
+        restart<MessageStoreImpl>();
 
         //check that the message is not available from either queue
         BOOST_CHECK_EQUAL((u_int32_t) 0, queueA->getMessageCount());
@@ -228,7 +228,7 @@
         }
 
         swap.check(commit);        
-        restart<BdbMessageStore>();
+        restart<MessageStoreImpl>();
         swap.check(commit);
     }
     
@@ -256,27 +256,27 @@
 
     void commit(Strategy& strategy)
     {
-        setup<BdbMessageStore>();
+        setup<MessageStoreImpl>();
         strategy.init();
 
         std::auto_ptr<TPCTransactionContext> txn(store->begin("my-xid"));
         strategy.run(txn.get());
         store->prepare(*txn);
         store->commit(*txn);
-        restart<BdbMessageStore>();
+        restart<MessageStoreImpl>();
         strategy.check(true);
     }
 
     void abort(Strategy& strategy, bool prepare)
     {
-        setup<BdbMessageStore>();
+        setup<MessageStoreImpl>();
         strategy.init();
 
         std::auto_ptr<TPCTransactionContext> txn(store->begin("my-xid"));
         strategy.run(txn.get());
         if (prepare) store->prepare(*txn);
         store->abort(*txn);
-        restart<BdbMessageStore>();
+        restart<MessageStoreImpl>();
         strategy.check(false);
     }
 




More information about the rhmessaging-commits mailing list