diff options
author | Aaron Seigo <aseigo@kde.org> | 2014-12-07 10:08:07 +0100 |
---|---|---|
committer | Aaron Seigo <aseigo@kde.org> | 2014-12-11 01:07:08 +0100 |
commit | 9ee8378d393778ac67314be7ea8d5bcbaeee9ee0 (patch) | |
tree | cf93471a69f9f4bbb4940de55ae134106fcd8380 /common/storage_unqlite.cpp | |
parent | ee6f068dff6b15441e553ffbfb2bf8aa97b26f57 (diff) | |
download | sink-9ee8378d393778ac67314be7ea8d5bcbaeee9ee0.tar.gz sink-9ee8378d393778ac67314be7ea8d5bcbaeee9ee0.zip |
try out unqlite
Diffstat (limited to 'common/storage_unqlite.cpp')
-rw-r--r-- | common/storage_unqlite.cpp | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/common/storage_unqlite.cpp b/common/storage_unqlite.cpp new file mode 100644 index 0000000..d0eaa38 --- /dev/null +++ b/common/storage_unqlite.cpp | |||
@@ -0,0 +1,221 @@ | |||
1 | #include "storage.h" | ||
2 | |||
3 | #include <iostream> | ||
4 | |||
5 | #include <QAtomicInt> | ||
6 | #include <QDebug> | ||
7 | #include <QDir> | ||
8 | #include <QFileInfo> | ||
9 | #include <QReadWriteLock> | ||
10 | #include <QString> | ||
11 | #include <QTime> | ||
12 | |||
13 | #include <unqlite/unqlite.h> | ||
14 | |||
15 | class Storage::Private | ||
16 | { | ||
17 | public: | ||
18 | Private(const QString &storageRoot, const QString &name, AccessMode m); | ||
19 | ~Private(); | ||
20 | |||
21 | QString name; | ||
22 | kyotocabinet::TreeDB db; | ||
23 | AccessMode mode; | ||
24 | bool dbOpen; | ||
25 | bool inTransaction; | ||
26 | }; | ||
27 | |||
28 | Storage::Private::Private(const QString &storageRoot, const QString &n, AccessMode m) | ||
29 | : name(n), | ||
30 | mode(m), | ||
31 | dbOpen(false), | ||
32 | inTransaction(false) | ||
33 | { | ||
34 | QDir dir; | ||
35 | dir.mkdir(storageRoot); | ||
36 | |||
37 | //create file | ||
38 | uint32_t openMode = kyotocabinet::BasicDB::OCREATE | | ||
39 | (mode == ReadOnly ? kyotocabinet::BasicDB::OREADER | ||
40 | : kyotocabinet::BasicDB::OWRITER); | ||
41 | dbOpen = db.open((storageRoot + "/" + name + ".kch").toStdString(), openMode); | ||
42 | if (!dbOpen) { | ||
43 | std::cerr << "Could not open database: " << db.error().codename(db.error().code()) << " " << db.error().message() << std::endl; | ||
44 | // TODO: handle error | ||
45 | } | ||
46 | } | ||
47 | |||
48 | Storage::Private::~Private() | ||
49 | { | ||
50 | if (dbOpen && inTransaction) { | ||
51 | db.end_transaction(false); | ||
52 | } | ||
53 | } | ||
54 | |||
55 | Storage::Storage(const QString &storageRoot, const QString &name, AccessMode mode) | ||
56 | : d(new Private(storageRoot, name, mode)) | ||
57 | { | ||
58 | } | ||
59 | |||
60 | Storage::~Storage() | ||
61 | { | ||
62 | delete d; | ||
63 | } | ||
64 | |||
65 | bool Storage::isInTransaction() const | ||
66 | { | ||
67 | return d->inTransaction; | ||
68 | } | ||
69 | |||
70 | bool Storage::startTransaction(AccessMode type) | ||
71 | { | ||
72 | if (!d->dbOpen) { | ||
73 | return false; | ||
74 | } | ||
75 | |||
76 | if (type == ReadWrite && d->mode != ReadWrite) { | ||
77 | return false; | ||
78 | } | ||
79 | |||
80 | if (d->inTransaction) { | ||
81 | return true; | ||
82 | } | ||
83 | |||
84 | //TODO handle errors | ||
85 | d->inTransaction = d->db.begin_transaction(); | ||
86 | return d->inTransaction; | ||
87 | } | ||
88 | |||
89 | bool Storage::commitTransaction() | ||
90 | { | ||
91 | if (!d->dbOpen) { | ||
92 | return false; | ||
93 | } | ||
94 | |||
95 | if (!d->inTransaction) { | ||
96 | return false; | ||
97 | } | ||
98 | |||
99 | bool success = d->db.end_transaction(true); | ||
100 | d->inTransaction = false; | ||
101 | return success; | ||
102 | } | ||
103 | |||
104 | void Storage::abortTransaction() | ||
105 | { | ||
106 | if (!d->dbOpen || !d->inTransaction) { | ||
107 | return; | ||
108 | } | ||
109 | |||
110 | d->db.end_transaction(false); | ||
111 | d->inTransaction = false; | ||
112 | } | ||
113 | |||
114 | bool Storage::write(const char *key, size_t keySize, const char *value, size_t valueSize) | ||
115 | { | ||
116 | if (!d->dbOpen) { | ||
117 | return false; | ||
118 | } | ||
119 | |||
120 | bool success = d->db.set(key, keySize, value, valueSize); | ||
121 | return success; | ||
122 | } | ||
123 | |||
124 | bool Storage::write(const std::string &sKey, const std::string &sValue) | ||
125 | { | ||
126 | if (!d->dbOpen) { | ||
127 | return false; | ||
128 | } | ||
129 | |||
130 | bool success = d->db.set(sKey, sValue); | ||
131 | return success; | ||
132 | } | ||
133 | |||
134 | void Storage::read(const std::string &sKey, | ||
135 | const std::function<bool(const std::string &value)> &resultHandler, | ||
136 | const std::function<void(const Storage::Error &error)> &errorHandler) | ||
137 | { | ||
138 | if (!d->dbOpen) { | ||
139 | Error error(d->name.toStdString(), -1, "Not open"); | ||
140 | errorHandler(error); | ||
141 | return; | ||
142 | } | ||
143 | |||
144 | std::string value; | ||
145 | if (sKey.empty()) { | ||
146 | kyotocabinet::DB::Cursor *cursor = d->db.cursor(); | ||
147 | cursor->jump(); | ||
148 | |||
149 | std::string key, value; | ||
150 | while (cursor->get_value(&value, true) && resultHandler(value)) {} | ||
151 | |||
152 | delete cursor; | ||
153 | return; | ||
154 | } else { | ||
155 | if (d->db.get(sKey, &value)) { | ||
156 | resultHandler(value); | ||
157 | return; | ||
158 | } | ||
159 | } | ||
160 | |||
161 | Error error(d->name.toStdString(), d->db.error().code(), d->db.error().message()); | ||
162 | errorHandler(error); | ||
163 | } | ||
164 | |||
165 | void Storage::read(const std::string &sKey, | ||
166 | const std::function<bool(void *ptr, int size)> &resultHandler, | ||
167 | const std::function<void(const Storage::Error &error)> &errorHandler) | ||
168 | { | ||
169 | if (!d->dbOpen) { | ||
170 | Error error(d->name.toStdString(), -1, "Not open"); | ||
171 | errorHandler(error); | ||
172 | return; | ||
173 | } | ||
174 | |||
175 | size_t valueSize; | ||
176 | char *valueBuffer; | ||
177 | if (sKey.empty()) { | ||
178 | kyotocabinet::DB::Cursor *cursor = d->db.cursor(); | ||
179 | cursor->jump(); | ||
180 | |||
181 | while ((valueBuffer = cursor->get_value(&valueSize, true))) { | ||
182 | bool ok = resultHandler(valueBuffer, valueSize); | ||
183 | delete[] valueBuffer; | ||
184 | if (!ok) { | ||
185 | break; | ||
186 | } | ||
187 | } | ||
188 | |||
189 | delete cursor; | ||
190 | } else { | ||
191 | valueBuffer = d->db.get(sKey.data(), sKey.size(), &valueSize); | ||
192 | if (valueBuffer) { | ||
193 | resultHandler(valueBuffer, valueSize); | ||
194 | } else { | ||
195 | Error error(d->name.toStdString(), d->db.error().code(), d->db.error().message()); | ||
196 | errorHandler(error); | ||
197 | } | ||
198 | delete[] valueBuffer; | ||
199 | } | ||
200 | } | ||
201 | |||
202 | qint64 Storage::diskUsage() const | ||
203 | { | ||
204 | if (!d->dbOpen) { | ||
205 | return 0; | ||
206 | } | ||
207 | |||
208 | QFileInfo info(QString::fromStdString(d->db.path())); | ||
209 | return info.size(); | ||
210 | } | ||
211 | |||
212 | void Storage::removeFromDisk() const | ||
213 | { | ||
214 | if (!d->dbOpen) { | ||
215 | return; | ||
216 | } | ||
217 | |||
218 | QFileInfo info(QString::fromStdString(d->db.path())); | ||
219 | QDir dir = info.dir(); | ||
220 | dir.remove(info.fileName()); | ||
221 | } | ||