5 #include <boost/functional/hash.hpp>
18 MemoryBackend::~MemoryBackend()
22 bool MemoryBackend::Put(const string &key,
29 bool MemoryBackend::Get(const string &key,
32 map_t::iterator it = _map.find(key);
45 void set_DBT(DBT *thing, const string &str)
47 bzero(thing, sizeof(DBT));
48 thing->data = (void*)str.data();
49 thing->size = str.size();
50 thing->ulen = str.size();
53 class BDBBackend::BDBDatabase
56 BDBDatabase(const string &path,
62 int res = db_env_create(&_dbenv, 0);
66 cerr << db_strerror(res) << endl;
67 throw std::runtime_error("db_env_create fail");
70 /* Set Cache Size To Total Memory */
73 double use_fraction = 0.1;
74 uint64_t pages = sysconf(_SC_PHYS_PAGES);
75 uint64_t page_size = sysconf(_SC_PAGE_SIZE);
77 uint64_t bytes = pages * page_size * use_fraction / num_dbs;
79 uint32_t gbytes = bytes / (1024uLL * 1024uLL * 1024uLL);
80 uint32_t nbytes = bytes % (1024uLL * 1024uLL * 1024uLL);
81 uint32_t ncache = bytes / (1024uLL * 1024uLL * 1024uLL * 4uLL) + 1;
83 res = _dbenv->set_cachesize(_dbenv, gbytes, nbytes, ncache);
87 cerr << db_strerror(res) << endl;
88 throw std::runtime_error("set_cachesize");
94 res = _dbenv->set_flags(_dbenv, DB_LOG_IN_MEMORY, 1);
98 cerr << db_strerror(res) << endl;
99 throw std::runtime_error("BDB ENV DB_LOG_IN_MEMORY");
104 res = _dbenv->set_flags(_dbenv, DB_LOG_AUTO_REMOVE, 1);
108 cerr << db_strerror(res) << endl;
109 throw std::runtime_error("BDB ENV DB_LOG_AUTO_REMOVE");
112 res = _dbenv->open(_dbenv,
123 cerr << db_strerror(res) << endl;
124 throw std::runtime_error("BDB ENV Open Fail");
127 string dbfilename = _path + "/test.db";
132 res = _dbenv->dbremove(_dbenv, NULL, dbfilename.c_str(), "test", 0);
134 if (res != 0 && res != ENOENT)
136 cerr << db_strerror(res) << endl;
137 throw std::runtime_error("db remove failed");
141 res = db_create(&_db, _dbenv, 0);
145 cerr << db_strerror(res) << endl;
146 throw std::runtime_error("db_create fail");
149 uint32_t flags = DB_CREATE | DB_THREAD;
161 cerr << db_strerror(res) << endl;
162 throw std::runtime_error("BDB Open Fail");
174 if ((res = _db->close(_db, 0)) < 0)
176 cerr << db_strerror(res) << endl;
182 if ((res = _dbenv->close(_dbenv, 0)) < 0)
184 cerr << db_strerror(res) << endl;
189 bool Put(const string &key,
192 DBT bdb_key, bdb_value;
194 set_DBT(&bdb_key, key);
195 set_DBT(&bdb_value, value);
197 if (_db->put(_db, NULL, &bdb_key, &bdb_value, 0) != 0)
208 bool Get(const string &key,
211 DBT bdb_key, bdb_value;
213 set_DBT(&bdb_key, key);
215 bzero(&bdb_value, sizeof(DBT));
216 bdb_value.flags = DB_DBT_MALLOC;
218 int res = _db->get(_db, NULL, &bdb_key, &bdb_value, 0);
222 *value = string((char*)bdb_value.data, bdb_value.size);
223 free(bdb_value.data);
224 bdb_value.data = NULL;
227 else if (res == DB_NOTFOUND || res == DB_KEYEMPTY)
234 cerr << db_strerror(res) << endl;
245 BDBBackend::BDBBackend(const vector<string> &paths,
249 if (paths.size() < 1)
251 cerr << "Insufficient BDB Paths supplied (need at least 1)";
252 throw std::runtime_error("not enough paths");
256 for (size_t i = 0; i < paths.size(); ++i)
258 cerr << "db for " << paths[i] << endl;
259 _dbs.push_back(shared_ptr<BDBDatabase>(new BDBDatabase(paths[i],
266 BDBBackend::~BDBBackend()
271 static boost::hash<string> hasher;
273 inline size_t BDBBackend::LookupKeyDB(const string &key)
275 uint32_t hash = (uint32_t)hasher(key);
276 return hash % _dbs.size();
279 bool BDBBackend::Put(const string &key,
282 size_t i = LookupKeyDB(key);
284 return _dbs[i]->Put(key, value);
287 bool BDBBackend::Get(const string &key,
290 size_t i = LookupKeyDB(key);
291 return _dbs[i]->Get(key, value);
295 } // namespace kvstore