1 #include "common/platform.h"
2
3 #include <cassert>
4 #include <cstdlib>
5 #include <cstring>
6 #include <stdexcept>
7
8 #include "master/hstring_bdbstorage.h"
9
10 using namespace hstorage;
11
12 static const int kGigabyte = (1024 * 1024 * 1024);
13
BDBStorage(const std::string & path,uint64_t cachesize,int ncache,uint32_t pagesize)14 BDBStorage::BDBStorage(const std::string &path, uint64_t cachesize, int ncache, uint32_t pagesize)
15 : path_(path) {
16
17 int err;
18
19 err = db_create(&dbp_, NULL, 0);
20 if (err) {
21 throw std::runtime_error("Could not create database");
22 }
23
24 if (pagesize != 0) {
25 err = dbp_->set_pagesize(dbp_, pagesize);
26 if (err) {
27 throw std::runtime_error("Could not set pagesize for database");
28 }
29 }
30
31 err = dbp_->set_cachesize(dbp_, cachesize / kGigabyte, cachesize % kGigabyte , ncache);
32 if (err) {
33 throw std::runtime_error("Could not set cachesize for database");
34 }
35
36 err = dbp_->open(dbp_, NULL, path.c_str(), NULL, DB_HEAP, DB_CREATE | DB_TRUNCATE, 0);
37 if (err) {
38 throw std::runtime_error("Could not open database");
39 }
40 }
41
~BDBStorage()42 BDBStorage::~BDBStorage() {
43 if (dbp_) {
44 dbp_->close(dbp_, DB_NOSYNC);
45 dbp_ = nullptr;
46 }
47 }
48
compare(const Handle & handle,const HString & str)49 bool BDBStorage::compare(const Handle &handle, const HString &str) {
50 if (hash(handle) == static_cast<HashType>(str.hash())) {
51 return str == get(handle);
52 }
53 return false;
54 }
55
get(const Handle & handle)56 ::std::string BDBStorage::get(const Handle &handle) {
57 int err;
58 DBT key, data;
59 DB_HEAP_RID rid = decode(handle);
60
61 memset(&key, 0, sizeof(DBT));
62 memset(&data, 0, sizeof(DBT));
63
64 key.data = &rid;
65 key.size = sizeof(rid);
66 key.ulen = sizeof(rid);
67 key.flags = DB_DBT_USERMEM;
68
69 err = dbp_->get(dbp_, 0, &key, &data, 0);
70
71 if (err) {
72 throw std::runtime_error("Getting from database failed");
73 }
74
75 return static_cast<const char *>(data.data);
76 }
77
copy(Handle & handle,const Handle & other)78 void BDBStorage::copy(Handle &handle, const Handle &other) {
79 bind(handle, get(other), hash(other));
80 }
81
bind(Handle & handle,const HString & str)82 void BDBStorage::bind(Handle &handle, const HString &str) {
83 bind(handle, str, str.hash());
84 }
85
bind(Handle & handle,const std::string & str,HashType hash)86 void BDBStorage::bind(Handle &handle, const std::string &str, HashType hash) {
87 int err;
88 DBT key, data;
89 DB_HEAP_RID rid;
90 memset(&key, 0, sizeof(DBT));
91 memset(&data, 0, sizeof(DBT));
92 memset(&rid, 0, sizeof(rid));
93
94 data.size = (str.size() + 1) * sizeof(char);
95 data.data = const_cast<char *>(str.c_str());
96 data.flags = DB_DBT_USERMEM;
97
98 key.data = &rid;
99 key.size = key.ulen = sizeof(rid);
100 key.flags = DB_DBT_USERMEM;
101
102 err = dbp_->put(dbp_, nullptr, &key, &data, DB_APPEND);
103 if (err) {
104 throw std::runtime_error("Putting to database failed");
105 }
106
107 handle.data() = encode(rid, hash);
108 }
109
encode(const DB_HEAP_RID & rid,HashType hash) const110 BDBStorage::ValueType BDBStorage::encode(const DB_HEAP_RID &rid, HashType hash) const {
111 ValueType ret = static_cast<ValueType>(hash) << 48;
112 ret += static_cast<ValueType>(rid.pgno + kSalt) << 16;
113 ret += rid.indx;
114 return ret;
115 }
116
decode(const Handle & handle) const117 DB_HEAP_RID BDBStorage::decode(const Handle &handle) const {
118 /*
119 * Structure of DB_HEAP_RID is
120 * {
121 * db_pgno_t pgno;
122 * db_indx_t indx;
123 * }
124 */
125 return {static_cast<db_pgno_t>(((handle.data() << 16) >> 32) - kSalt),
126 static_cast<db_indx_t>((handle.data() << 48) >> 48)};
127 }
128
unbind(Handle & handle)129 void BDBStorage::unbind(Handle &handle) {
130 DBT key, data;
131 DB_HEAP_RID rid = decode(handle);
132
133 memset(&key, 0, sizeof(DBT));
134 memset(&data, 0, sizeof(DBT));
135
136 key.data = &rid;
137 key.size = sizeof(rid);
138 key.ulen = sizeof(rid);
139 key.flags = DB_DBT_USERMEM;
140
141 /* Ignore errors, unbind is used in the destructor */
142 dbp_->del(dbp_, nullptr, &key, 0);
143 }
144
name() const145 ::std::string BDBStorage::name() const {
146 return kName;
147 }
148