1
我試圖實現使用Berkeley DB的併發持久的隊列。作爲首發我試圖做兩個過程,這兩個追加到DB:的Berkeley DB,併發隊列
#include <unistd.h>
#include <sstream>
#include <db_cxx.h>
class Queue : public DbEnv
{
public:
Queue () :
DbEnv(0),
db(0)
{
set_flags(DB_CDB_ALLDB, 1);
open("/tmp/db", DB_INIT_LOCK |
DB_INIT_LOG |
DB_INIT_TXN |
DB_INIT_MPOOL |
DB_RECOVER |
DB_CREATE |
DB_THREAD,
0);
db = new Db(this, 0);
db->set_flags(DB_RENUMBER);
db->open(NULL, "db", NULL, DB_RECNO, DB_CREATE | DB_AUTO_COMMIT | DB_THREAD, 0);
}
virtual ~Queue()
{
db->close(0);
delete db;
close(0);
}
protected:
Db * db;
};
class Enqueue : public Queue
{
public:
Enqueue () : Queue() { }
virtual ~Enqueue() { }
bool push(const std::string& s)
{
int res;
DbTxn * txn;
try {
txn_begin(NULL, &txn, DB_TXN_SYNC | DB_TXN_WAIT);
db_recno_t k0[4]; // not sure how mutch data is needs???
k0[0] = 0;
Dbt val((void*)s.c_str(), s.length());
Dbt key((void*)&k0, sizeof(k0[0]));
key.set_ulen(sizeof(k0));
key.set_flags(DB_DBT_USERMEM);
res = db->put(txn, &key, &val, DB_APPEND);
if(res == 0) {
txn->commit(0);
return true;
} else {
std::cerr << "push failed: " << res << std::endl;
txn->abort();
return false;
}
} catch(DbException e) {
std::cerr << "DB What()" << e.what() << std::endl;
txn->abort();
return false;
} catch(std::exception e) {
std::cerr << "What()" << e.what() << std::endl;
txn->abort();
return false;
} catch(...) {
std::cerr << "Unknown error" << std::endl;
txn->abort();
return false;
}
}
};
using namespace std;
int main(int argc, const char *argv[])
{
fork();
Enqueue e;
stringstream ss;
for(int i = 0; i < 10; i++){
ss.str("");
ss << "asdf" << i;
cout << ss.str() << endl;
if(! e.push(ss.str()))
break;
}
return 0;
}
編譯它:
g++ test.cxx -I/usr/include/db4.8 -ldb_cxx-4.8
創建DB-DIR
mkdir /tmp/db
當我運行我得到的所有樣的錯誤(分段故障,分配錯誤,有的時候它的實際工作)
我我確定我錯過了一些鎖定,但我不知道該怎麼做。所以,任何提示和/或建議來解決這個問題是最受歡迎的。