summaryrefslogtreecommitdiffstats
path: root/store/database.cpp
diff options
context:
space:
mode:
authorAaron Seigo <aseigo@kde.org>2014-12-05 10:05:19 +0100
committerAaron Seigo <aseigo@kde.org>2014-12-05 10:05:19 +0100
commit93d1c82ffd17df45a5cecd875a01ee3cb15d9983 (patch)
treecda5c31857362ce81f3a50959024f4270d149a07 /store/database.cpp
parent639fc60c100204c87b93112516cf3b3117cfff0d (diff)
parent351a66b5fb1c8659bff8ea20d60f5a6d2d3263ad (diff)
downloadsink-93d1c82ffd17df45a5cecd875a01ee3cb15d9983.tar.gz
sink-93d1c82ffd17df45a5cecd875a01ee3cb15d9983.zip
Merge branch 'kyoto'
Conflicts: common/storage.h common/storage_lmdb.cpp dummyresource/facade.cpp store/test/CMakeLists.txt tests/storagebenchmark.cpp
Diffstat (limited to 'store/database.cpp')
-rw-r--r--store/database.cpp274
1 files changed, 0 insertions, 274 deletions
diff --git a/store/database.cpp b/store/database.cpp
deleted file mode 100644
index c4dfbd6..0000000
--- a/store/database.cpp
+++ /dev/null
@@ -1,274 +0,0 @@
1#include "database.h"
2
3#include <iostream>
4
5#include <QAtomicInt>
6#include <QDebug>
7#include <QDir>
8#include <QReadWriteLock>
9#include <QString>
10#include <QTime>
11
12#include <lmdb.h>
13
14class Database::Private
15{
16public:
17 Private(const QString &s, const QString &name);
18 ~Private();
19
20 QString storageRoot;
21 QString name;
22 MDB_dbi dbi;
23 MDB_env *env;
24 MDB_txn *transaction;
25 bool readTransaction;
26 bool firstOpen;
27};
28
29Database::Private::Private(const QString &s, const QString &n)
30 : transaction(0),
31 readTransaction(false),
32 firstOpen(true),
33 storageRoot(s),
34 name(n)
35{
36 QDir dir;
37 dir.mkdir(storageRoot);
38
39 //create file
40 if (mdb_env_create(&env)) {
41 // TODO: handle error
42 } else {
43 int rc = mdb_env_open(env, storageRoot.toStdString().data(), 0, 0664);
44
45 if (rc) {
46 std::cerr << "mdb_env_open: " << rc << " " << mdb_strerror(rc) << std::endl;
47 mdb_env_close(env);
48 env = 0;
49 } else {
50 const size_t dbSize = 10485760 * 100; //10MB * 100
51 mdb_env_set_mapsize(env, dbSize);
52 }
53 }
54}
55
56Database::Private::~Private()
57{
58 if (transaction) {
59 mdb_txn_abort(transaction);
60 }
61
62 // it is still there and still unused, so we can shut it down
63 mdb_dbi_close(env, dbi);
64 mdb_env_close(env);
65}
66
67Database::Database(const QString &storageRoot, const QString &name)
68 : d(new Private(storageRoot, name))
69{
70}
71
72Database::~Database()
73{
74 delete d;
75}
76
77bool Database::isInTransaction() const
78{
79 return d->transaction;
80}
81
82bool Database::startTransaction(TransactionType type)
83{
84 if (!d->env) {
85 return false;
86 }
87
88 bool requestedRead = type == ReadOnly;
89 if (d->transaction && (!d->readTransaction || requestedRead)) {
90 return true;
91 }
92
93 if (d->transaction) {
94 // we are about to turn a read transaction into a writable one
95 abortTransaction();
96 }
97
98 if (d->firstOpen && requestedRead) {
99 //A write transaction is at least required the first time
100 mdb_txn_begin(d->env, nullptr, 0, &d->transaction);
101 //Open the database
102 //With this we could open multiple named databases if we wanted to
103 mdb_dbi_open(d->transaction, nullptr, 0, &d->dbi);
104 mdb_txn_abort(d->transaction);
105 }
106
107 int rc;
108 rc = mdb_txn_begin(d->env, NULL, requestedRead ? MDB_RDONLY : 0, &d->transaction);
109 if (!rc) {
110 rc = mdb_dbi_open(d->transaction, NULL, 0, &d->dbi);
111 }
112
113 d->firstOpen = false;
114 return !rc;
115}
116
117bool Database::commitTransaction()
118{
119 if (!d->env) {
120 return false;
121 }
122
123 if (!d->transaction) {
124 return false;
125 }
126
127 int rc;
128 rc = mdb_txn_commit(d->transaction);
129 d->transaction = 0;
130
131 if (rc) {
132 std::cerr << "mdb_txn_commit: " << rc << " " << mdb_strerror(rc) << std::endl;
133 }
134
135 return !rc;
136}
137
138void Database::abortTransaction()
139{
140 if (!d->env || !d->transaction) {
141 return;
142 }
143
144 mdb_txn_abort(d->transaction);
145 d->transaction = 0;
146}
147
148bool Database::write(const char *key, size_t keySize, const char *value, size_t valueSize)
149{
150 write(std::string(key, keySize), std::string(value, valueSize));
151}
152
153bool Database::write(const std::string &sKey, const std::string &sValue)
154{
155 if (!d->env) {
156 return false;
157 }
158
159 const bool implicitTransaction = !d->transaction || d->readTransaction;
160 if (implicitTransaction) {
161 // TODO: if this fails, still try the write below?
162 if (!startTransaction()) {
163 return false;
164 }
165 }
166
167 int rc;
168 MDB_val key, data;
169 key.mv_size = sKey.size();
170 key.mv_data = (void*)sKey.data();
171 data.mv_size = sValue.size();
172 data.mv_data = (void*)sValue.data();
173 rc = mdb_put(d->transaction, d->dbi, &key, &data, 0);
174
175 if (rc) {
176 std::cerr << "mdb_put: " << rc << " " << mdb_strerror(rc) << std::endl;
177 }
178
179 if (implicitTransaction) {
180 if (rc) {
181 abortTransaction();
182 } else {
183 rc = commitTransaction();
184 }
185 }
186
187 return !rc;
188}
189
190bool Database::read(const std::string &sKey, const std::function<void(const std::string &value)> &resultHandler)
191{
192 return read(sKey,
193 [&](void *ptr, int size) {
194 const std::string resultValue(static_cast<char*>(ptr), size);
195 resultHandler(resultValue);
196 });
197// std::cout << "key: " << resultKey << " data: " << resultValue << std::endl;
198}
199
200bool Database::read(const std::string &sKey, const std::function<void(void *ptr, int size)> &resultHandler)
201{
202 if (!d->env) {
203 return false;
204 }
205
206 int rc;
207 MDB_val key;
208 MDB_val data;
209 MDB_cursor *cursor;
210
211 key.mv_size = sKey.size();
212 key.mv_data = (void*)sKey.data();
213
214 const bool implicitTransaction = !d->transaction;
215 if (implicitTransaction) {
216 // TODO: if this fails, still try the write below?
217 if (!startTransaction(ReadOnly)) {
218 return false;
219 }
220 }
221
222 rc = mdb_cursor_open(d->transaction, d->dbi, &cursor);
223 if (rc) {
224 std::cerr << "mdb_cursor_get: " << rc << " " << mdb_strerror(rc) << std::endl;
225 return false;
226 }
227
228 if (sKey.empty()) {
229 std::cout << "Iterating over all values of store!" << std::endl;
230 rc = mdb_cursor_get(cursor, &key, &data, MDB_FIRST);
231 while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
232 resultHandler(key.mv_data, data.mv_size);
233 }
234
235 //We never find the last value
236 if (rc == MDB_NOTFOUND) {
237 rc = 0;
238 }
239 } else {
240 if ((rc = mdb_cursor_get(cursor, &key, &data, MDB_SET)) == 0) {
241 resultHandler(data.mv_data, data.mv_size);
242 } else {
243 std::cout << "couldn't find value " << sKey << " " << std::endl;
244 }
245 }
246
247 if (rc) {
248 std::cerr << "mdb_cursor_get: " << rc << " " << mdb_strerror(rc) << std::endl;
249 return false;
250 }
251
252 mdb_cursor_close(cursor);
253
254 /**
255 we don't abort the transaction since we need it for reading the values
256 if (implicitTransaction) {
257 abortTransaction();
258 }
259 */
260 return true;
261}
262
263qint64 Database::diskUsage() const
264{
265 QFileInfo info(d->storageRoot + "/data.mdb");
266 return info.size();
267}
268
269void Database::removeFromDisk() const
270{
271 QDir dir(d->storageRoot);
272 dir.remove("data.mdb");
273 dir.remove("lock.mdb");
274}