summaryrefslogtreecommitdiffstats
path: root/common/storage_unqlite.cpp
diff options
context:
space:
mode:
authorAaron Seigo <aseigo@kde.org>2015-12-25 21:04:39 +0100
committerAaron Seigo <aseigo@kde.org>2015-12-25 21:04:39 +0100
commit94385710e45c6289809934aecaffe793ad2f6369 (patch)
tree8fc64034268143c63d321b54c754135173c702df /common/storage_unqlite.cpp
parentb259728a4f63e022526ef86e6b5d6c62d9938d13 (diff)
downloadsink-94385710e45c6289809934aecaffe793ad2f6369.tar.gz
sink-94385710e45c6289809934aecaffe793ad2f6369.zip
unqlite is a dead end; time to start pruning these things
Diffstat (limited to 'common/storage_unqlite.cpp')
-rw-r--r--common/storage_unqlite.cpp340
1 files changed, 0 insertions, 340 deletions
diff --git a/common/storage_unqlite.cpp b/common/storage_unqlite.cpp
deleted file mode 100644
index 6950acd..0000000
--- a/common/storage_unqlite.cpp
+++ /dev/null
@@ -1,340 +0,0 @@
1/*
2 * Copyright (C) 2014 Aaron Seigo <aseigo@kde.org>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) version 3, or any
8 * later version accepted by the membership of KDE e.V. (or its
9 * successor approved by the membership of KDE e.V.), which shall
10 * act as a proxy defined in Section 6 of version 3 of the license.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include "storage.h"
22
23#include <iostream>
24
25#include <QAtomicInt>
26#include <QDebug>
27#include <QDir>
28#include <QReadWriteLock>
29#include <QString>
30#include <QTime>
31
32extern "C" {
33 #include "unqlite/unqlite.h"
34}
35
36namespace Akonadi2
37{
38
39static const char *s_unqliteDir = "/unqlite/";
40
41class Storage::Private
42{
43public:
44 Private(const QString &s, const QString &name, AccessMode m, bool allowDuplicates);
45 ~Private();
46
47 void reportDbError(const char *functionName);
48 void reportDbError(const char *functionName, int errorCode,
49 const std::function<void(const Storage::Error &error)> &errorHandler);
50
51 QString storageRoot;
52 QString name;
53 AccessMode mode;
54
55 unqlite *db;
56 bool allowDuplicates;
57 bool inTransaction;
58};
59
60Storage::Private::Private(const QString &s, const QString &n, AccessMode m, bool duplicates)
61 : storageRoot(s),
62 name(n),
63 mode(m),
64 db(0),
65 allowDuplicates(duplicates), //FIXME: currently does nothing ... should do what it says
66 inTransaction(false)
67{
68 const QString fullPath(storageRoot + s_unqliteDir + name);
69 QDir dir;
70 dir.mkpath(storageRoot + s_unqliteDir);
71
72 //create file
73 int openFlags = UNQLITE_OPEN_CREATE;
74 if (mode == ReadOnly) {
75 openFlags |= UNQLITE_OPEN_READONLY | UNQLITE_OPEN_MMAP;
76 } else {
77 openFlags |= UNQLITE_OPEN_READWRITE;
78 }
79
80 int rc = unqlite_open(&db, fullPath.toStdString().data(), openFlags);
81
82 if (rc != UNQLITE_OK) {
83 reportDbError("unqlite_open");
84 }
85}
86
87Storage::Private::~Private()
88{
89 unqlite_close(db);
90}
91
92void Storage::Private::reportDbError(const char *functionName)
93{
94 std::cerr << "ERROR: " << functionName;
95 if (db) {
96 const char *errorMessage;
97 int length;
98 /* Something goes wrong, extract database error log */
99 unqlite_config(db, UNQLITE_CONFIG_ERR_LOG, &errorMessage, &length);
100 if (length > 0) {
101 std::cerr << ": " << errorMessage;
102 }
103 }
104 std::cerr << std::endl;
105}
106
107void Storage::Private::reportDbError(const char *functionName, int errorCode,
108 const std::function<void(const Storage::Error &error)> &errorHandler)
109{
110 if (db) {
111 const char *errorMessage;
112 int length;
113 /* Something goes wrong, extract database error log */
114 unqlite_config(db, UNQLITE_CONFIG_ERR_LOG, &errorMessage, &length);
115 if (length > 0) {
116 Error error(name.toStdString(), errorCode, errorMessage);
117 errorHandler(error);
118 return;
119 }
120 }
121
122 Error error(name.toStdString(), errorCode, functionName);
123 errorHandler(error);
124}
125
126Storage::Storage(const QString &storageRoot, const QString &name, AccessMode mode, bool allowDuplicates)
127 : d(new Private(storageRoot, name, mode, allowDuplicates))
128{
129}
130
131Storage::~Storage()
132{
133 if (d->inTransaction) {
134 abortTransaction();
135 }
136
137 delete d;
138}
139
140bool Storage::isInTransaction() const
141{
142 return d->inTransaction;
143}
144
145bool Storage::startTransaction(AccessMode type)
146{
147 if (!d->db) {
148 return false;
149 }
150
151 if (d->inTransaction) {
152 return true;
153 }
154
155 d->inTransaction = unqlite_begin(d->db) == UNQLITE_OK;
156
157 if (!d->inTransaction) {
158 d->reportDbError("unqlite_begin");
159 }
160
161 return d->inTransaction;
162}
163
164bool Storage::commitTransaction()
165{
166 if (!d->db) {
167 return false;
168 }
169
170 if (!d->inTransaction) {
171 return true;
172 }
173
174 int rc = unqlite_commit(d->db);
175 d->inTransaction = false;
176
177 if (rc != UNQLITE_OK) {
178 d->reportDbError("unqlite_commit");
179 }
180
181 return rc == UNQLITE_OK;
182}
183
184void Storage::abortTransaction()
185{
186 if (!d->db || !d->inTransaction) {
187 return;
188 }
189
190 unqlite_rollback(d->db);
191 d->inTransaction = false;
192}
193
194bool Storage::write(const void *key, size_t keySize, const void *value, size_t valueSize)
195{
196 if (!d->db) {
197 return false;
198 }
199
200 int rc = unqlite_kv_store(d->db, key, keySize, value, valueSize);
201
202 if (rc != UNQLITE_OK) {
203 d->reportDbError("unqlite_kv_store");
204 }
205
206 return !rc;
207}
208
209bool Storage::write(const std::string &sKey, const std::string &sValue)
210{
211 return write(sKey.data(), sKey.size(), sValue.data(), sKey.size());
212}
213
214void Storage::read(const std::string &sKey,
215 const std::function<bool(const std::string &value)> &resultHandler,
216 const std::function<void(const Storage::Error &error)> &errorHandler)
217{
218 read(sKey,
219 [&](void *ptr, int size) -> bool {
220 if (ptr) {
221 const std::string resultValue(static_cast<char*>(ptr), size);
222 return resultHandler(resultValue);
223 }
224
225 return true;
226 }, errorHandler);
227}
228
229void Storage::read(const std::string &sKey,
230 const std::function<bool(void *ptr, int size)> &resultHandler,
231 const std::function<void(const Storage::Error &error)> &errorHandler)
232{
233 scan(sKey.data(), sKey.size(), [resultHandler](void *keyPtr, int keySize, void *valuePtr, int valueSize) {
234 return resultHandler(valuePtr, valueSize);
235 }, errorHandler);
236}
237
238void Storage::remove(const void *keyData, uint keySize)
239{
240 remove(keyData, keySize, basicErrorHandler());
241}
242
243void Storage::remove(const void *keyData, uint keySize,
244 const std::function<void(const Storage::Error &error)> &errorHandler)
245{
246 if (!d->db) {
247 Error error(d->name.toStdString(), -1, "Not open");
248 errorHandler(error);
249 return;
250 }
251
252 unqlite_kv_delete(d->db, keyData, keySize);
253}
254
255
256void fetchCursorData(unqlite_kv_cursor *cursor,
257 void **keyBuffer, int *keyBufferLength, void **dataBuffer, unqlite_int64 *dataBufferLength,
258 const std::function<bool(void *keyPtr, int keySize, void *valuePtr, int valueSize)> &resultHandler)
259{
260 int keyLength = 0;
261 unqlite_int64 dataLength = 0;
262 // now fetch the data sizes
263 if (unqlite_kv_cursor_key(cursor, nullptr, &keyLength) == UNQLITE_OK &&
264 unqlite_kv_cursor_data(cursor, nullptr, &dataLength) == UNQLITE_OK) {
265 if (keyLength > *keyBufferLength) {
266 *keyBuffer = realloc(*keyBuffer, keyLength);
267 *keyBufferLength = keyLength;
268 }
269
270 if (dataLength > *dataBufferLength) {
271 *dataBuffer = realloc(*dataBuffer, dataLength);
272 *dataBufferLength = dataLength;
273 }
274
275 if (unqlite_kv_cursor_key(cursor, *keyBuffer, &keyLength) == UNQLITE_OK &&
276 unqlite_kv_cursor_data(cursor, *dataBuffer, &dataLength) == UNQLITE_OK) {
277 resultHandler(*keyBuffer, keyLength, *dataBuffer, dataLength);
278 }
279 }
280}
281
282void Storage::scan(const char *keyData, uint keySize,
283 const std::function<bool(void *keyPtr, int keySize, void *valuePtr, int valueSize)> &resultHandler,
284 const std::function<void(const Storage::Error &error)> &errorHandler)
285{
286 if (!d->db) {
287 Error error(d->name.toStdString(), -1, "Not open");
288 errorHandler(error);
289 return;
290 }
291
292 unqlite_kv_cursor *cursor;
293
294 int rc = unqlite_kv_cursor_init(d->db, &cursor);
295 if (rc != UNQLITE_OK) {
296 d->reportDbError("unqlite_kv_cursor_init", rc, errorHandler);
297 return;
298 }
299
300 void *keyBuffer = nullptr;
301 int keyBufferLength = 0;
302 void *dataBuffer = nullptr;
303 //FIXME: 64bit ints, but feeding int lenghts to the callbacks. can result in truncation
304 unqlite_int64 dataBufferLength = 0;
305 if (!keyData || keySize == 0) {
306 for (unqlite_kv_cursor_first_entry(cursor); unqlite_kv_cursor_valid_entry(cursor); unqlite_kv_cursor_next_entry(cursor)) {
307 fetchCursorData(cursor, &keyBuffer, &keyBufferLength, &dataBuffer, &dataBufferLength, resultHandler);
308 }
309 } else {
310 rc = unqlite_kv_cursor_seek(cursor, keyData, keySize, UNQLITE_CURSOR_MATCH_EXACT);
311 if (rc == UNQLITE_OK) {
312 fetchCursorData(cursor, &keyBuffer, &keyBufferLength, &dataBuffer, &dataBufferLength, resultHandler);
313 } else {
314 std::cout << "couldn't find value " << std::string(keyData, keySize) << std::endl;
315 }
316
317 }
318
319 free(keyBuffer);
320 free(dataBuffer);
321 unqlite_kv_cursor_release(d->db, cursor);
322}
323
324qint64 Storage::diskUsage() const
325{
326 QFileInfo info(d->storageRoot + s_unqliteDir + d->name);
327 return info.size();
328}
329
330bool Storage::exists() const
331{
332 return d->db != 0;
333}
334
335void Storage::removeFromDisk() const
336{
337 QFile::remove(d->storageRoot + s_unqliteDir + d->name);
338}
339
340} // namespace Akonadi2