diff options
-rw-r--r-- | common/storage.h | 4 | ||||
-rw-r--r-- | common/storage_lmdb.cpp | 48 | ||||
-rw-r--r-- | examples/client/main.cpp | 90 |
3 files changed, 120 insertions, 22 deletions
diff --git a/common/storage.h b/common/storage.h index a4137ce..22bf06c 100644 --- a/common/storage.h +++ b/common/storage.h | |||
@@ -106,6 +106,8 @@ public: | |||
106 | return (d != nullptr); | 106 | return (d != nullptr); |
107 | } | 107 | } |
108 | 108 | ||
109 | qint64 getSize(); | ||
110 | |||
109 | private: | 111 | private: |
110 | friend Transaction; | 112 | friend Transaction; |
111 | NamedDatabase(NamedDatabase& other); | 113 | NamedDatabase(NamedDatabase& other); |
@@ -123,6 +125,8 @@ public: | |||
123 | bool commit(const std::function<void(const Storage::Error &error)> &errorHandler = std::function<void(const Storage::Error &error)>()); | 125 | bool commit(const std::function<void(const Storage::Error &error)> &errorHandler = std::function<void(const Storage::Error &error)>()); |
124 | void abort(); | 126 | void abort(); |
125 | 127 | ||
128 | QList<QByteArray> getDatabaseNames() const; | ||
129 | |||
126 | NamedDatabase openDatabase(const QByteArray &name = QByteArray("default"), const std::function<void(const Storage::Error &error)> &errorHandler = std::function<void(const Storage::Error &error)>(), bool allowDuplicates = false) const; | 130 | NamedDatabase openDatabase(const QByteArray &name = QByteArray("default"), const std::function<void(const Storage::Error &error)> &errorHandler = std::function<void(const Storage::Error &error)>(), bool allowDuplicates = false) const; |
127 | 131 | ||
128 | Transaction(Transaction&& other) : d(other.d) | 132 | Transaction(Transaction&& other) : d(other.d) |
diff --git a/common/storage_lmdb.cpp b/common/storage_lmdb.cpp index a247e38..e32618b 100644 --- a/common/storage_lmdb.cpp +++ b/common/storage_lmdb.cpp | |||
@@ -318,6 +318,27 @@ void Storage::NamedDatabase::findLatest(const QByteArray &k, | |||
318 | return; | 318 | return; |
319 | } | 319 | } |
320 | 320 | ||
321 | qint64 Storage::NamedDatabase::getSize() | ||
322 | { | ||
323 | if (!d || !d->transaction) { | ||
324 | return -1; | ||
325 | } | ||
326 | |||
327 | int rc; | ||
328 | MDB_stat stat; | ||
329 | rc = mdb_stat(d->transaction, d->dbi, &stat); | ||
330 | if (rc) { | ||
331 | qWarning() << "Something went wrong " << rc; | ||
332 | } | ||
333 | // std::cout << "overflow_pages: " << stat.ms_overflow_pages << std::endl; | ||
334 | // std::cout << "page size: " << stat.ms_psize << std::endl; | ||
335 | // std::cout << "branch_pages: " << stat.ms_branch_pages << std::endl; | ||
336 | // std::cout << "leaf_pages: " << stat.ms_leaf_pages << std::endl; | ||
337 | // std::cout << "depth: " << stat.ms_depth << std::endl; | ||
338 | // std::cout << "entries: " << stat.ms_entries << std::endl; | ||
339 | return stat.ms_psize * (stat.ms_leaf_pages + stat.ms_branch_pages + stat.ms_overflow_pages); | ||
340 | } | ||
341 | |||
321 | 342 | ||
322 | 343 | ||
323 | 344 | ||
@@ -428,9 +449,34 @@ Storage::NamedDatabase Storage::Transaction::openDatabase(const QByteArray &db, | |||
428 | return Storage::NamedDatabase(p); | 449 | return Storage::NamedDatabase(p); |
429 | } | 450 | } |
430 | 451 | ||
452 | QList<QByteArray> Storage::Transaction::getDatabaseNames() const | ||
453 | { | ||
454 | if (!d) { | ||
455 | qWarning() << "Invalid transaction"; | ||
456 | return QList<QByteArray>(); | ||
457 | } | ||
431 | 458 | ||
459 | int rc; | ||
460 | QList<QByteArray> list; | ||
461 | if ((rc = mdb_dbi_open(d->transaction, nullptr, 0, &d->dbi) == 0)) { | ||
462 | MDB_val key; | ||
463 | MDB_val data; | ||
464 | MDB_cursor *cursor; | ||
432 | 465 | ||
433 | 466 | rc = mdb_cursor_open(d->transaction, d->dbi, &cursor); | |
467 | if ((rc = mdb_cursor_get(cursor, &key, &data, MDB_FIRST)) == 0) { | ||
468 | list << QByteArray::fromRawData((char*)key.mv_data, key.mv_size); | ||
469 | while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { | ||
470 | list << QByteArray::fromRawData((char*)key.mv_data, key.mv_size); | ||
471 | } | ||
472 | } else { | ||
473 | qWarning() << "Failed to get a value" << rc; | ||
474 | } | ||
475 | } else { | ||
476 | qWarning() << "Failed to open db" << rc << QByteArray(mdb_strerror(rc)); | ||
477 | } | ||
478 | return list; | ||
479 | } | ||
434 | 480 | ||
435 | 481 | ||
436 | 482 | ||
diff --git a/examples/client/main.cpp b/examples/client/main.cpp index 7bbac56..f2fb237 100644 --- a/examples/client/main.cpp +++ b/examples/client/main.cpp | |||
@@ -144,14 +144,11 @@ int main(int argc, char *argv[]) | |||
144 | QObject::tr("A type to work with")); | 144 | QObject::tr("A type to work with")); |
145 | cliOptions.addPositionalArgument(QObject::tr("[resource]"), | 145 | cliOptions.addPositionalArgument(QObject::tr("[resource]"), |
146 | QObject::tr("A resource to connect to")); | 146 | QObject::tr("A resource to connect to")); |
147 | cliOptions.addOption(QCommandLineOption("clear")); | 147 | cliOptions.addOption(QCommandLineOption("debuglevel", "A debuglevel from 0-6", "debuglevel")); |
148 | cliOptions.addOption(QCommandLineOption("debuglevel")); | ||
149 | cliOptions.addHelpOption(); | 148 | cliOptions.addHelpOption(); |
150 | cliOptions.process(app); | 149 | cliOptions.process(app); |
151 | QStringList args = cliOptions.positionalArguments(); | 150 | QStringList args = cliOptions.positionalArguments(); |
152 | auto command = args.takeFirst(); | 151 | auto command = args.takeFirst(); |
153 | auto type = !args.isEmpty() ? args.takeFirst() : QByteArray(); | ||
154 | auto resources = args; | ||
155 | 152 | ||
156 | if (cliOptions.isSet("debuglevel")) { | 153 | if (cliOptions.isSet("debuglevel")) { |
157 | Akonadi2::Log::setDebugOutputLevel(static_cast<Akonadi2::Log::DebugLevel>(cliOptions.value("debuglevel").toInt())); | 154 | Akonadi2::Log::setDebugOutputLevel(static_cast<Akonadi2::Log::DebugLevel>(cliOptions.value("debuglevel").toInt())); |
@@ -163,31 +160,31 @@ int main(int argc, char *argv[]) | |||
163 | // ResourceConfig::addResource(resource.toLatin1(), Akonadi2::Store::resourceName(resource.toLatin1())); | 160 | // ResourceConfig::addResource(resource.toLatin1(), Akonadi2::Store::resourceName(resource.toLatin1())); |
164 | // } | 161 | // } |
165 | 162 | ||
166 | Akonadi2::Query query; | ||
167 | for (const auto &res : resources) { | ||
168 | query.resources << res.toLatin1(); | ||
169 | } | ||
170 | query.syncOnDemand = false; | ||
171 | query.processAll = false; | ||
172 | query.liveQuery = true; | ||
173 | |||
174 | qDebug() << "Type: " << type; | ||
175 | |||
176 | if (command == "list") { | 163 | if (command == "list") { |
164 | auto type = !args.isEmpty() ? args.takeFirst() : QByteArray(); | ||
165 | auto resources = args; | ||
166 | |||
167 | Akonadi2::Query query; | ||
168 | for (const auto &res : resources) { | ||
169 | query.resources << res.toLatin1(); | ||
170 | } | ||
171 | query.syncOnDemand = false; | ||
172 | query.processAll = false; | ||
177 | query.liveQuery = false; | 173 | query.liveQuery = false; |
174 | |||
178 | auto model = loadModel(type, query); | 175 | auto model = loadModel(type, query); |
179 | qDebug() << "Listing"; | 176 | qDebug() << "Listing"; |
180 | std::cout << "\tColumn\t "; | 177 | std::cout << "\tColumn\t\t Identifier\t\t\t\t"; |
181 | for (int i = 0; i < model->columnCount(QModelIndex()); i++) { | 178 | for (int i = 0; i < model->columnCount(QModelIndex()); i++) { |
182 | std::cout << "\t" << model->headerData(i, Qt::Horizontal).toString().toStdString(); | 179 | std::cout << "\t|" << model->headerData(i, Qt::Horizontal).toString().toStdString(); |
183 | } | 180 | } |
184 | std::cout << std::endl; | 181 | std::cout << std::endl; |
185 | QObject::connect(model.data(), &QAbstractItemModel::rowsInserted, [model](const QModelIndex &index, int start, int end) { | 182 | QObject::connect(model.data(), &QAbstractItemModel::rowsInserted, [model](const QModelIndex &index, int start, int end) { |
186 | for (int i = start; i <= end; i++) { | 183 | for (int i = start; i <= end; i++) { |
187 | std::cout << "\tRow " << model->rowCount() << ":\t "; | 184 | std::cout << "\tRow " << model->rowCount() << ":\t "; |
188 | std::cout << "\t" << model->data(model->index(i, 0, index), Akonadi2::Store::DomainObjectBaseRole).value<Akonadi2::ApplicationDomain::ApplicationDomainType::Ptr>()->identifier().toStdString(); | 185 | std::cout << "\t" << model->data(model->index(i, 0, index), Akonadi2::Store::DomainObjectBaseRole).value<Akonadi2::ApplicationDomain::ApplicationDomainType::Ptr>()->identifier().toStdString() << "\t"; |
189 | for (int col = 0; col < model->columnCount(QModelIndex()); col++) { | 186 | for (int col = 0; col < model->columnCount(QModelIndex()); col++) { |
190 | std::cout << "\t" << model->data(model->index(i, col, index)).toString().toStdString(); | 187 | std::cout << "\t|" << model->data(model->index(i, col, index)).toString().toStdString(); |
191 | } | 188 | } |
192 | std::cout << std::endl; | 189 | std::cout << std::endl; |
193 | } | 190 | } |
@@ -201,6 +198,15 @@ int main(int argc, char *argv[]) | |||
201 | return app.exec(); | 198 | return app.exec(); |
202 | } | 199 | } |
203 | } else if (command == "count") { | 200 | } else if (command == "count") { |
201 | auto type = !args.isEmpty() ? args.takeFirst() : QByteArray(); | ||
202 | auto resources = args; | ||
203 | |||
204 | Akonadi2::Query query; | ||
205 | for (const auto &res : resources) { | ||
206 | query.resources << res.toLatin1(); | ||
207 | } | ||
208 | query.syncOnDemand = false; | ||
209 | query.processAll = false; | ||
204 | query.liveQuery = false; | 210 | query.liveQuery = false; |
205 | auto model = loadModel(type, query); | 211 | auto model = loadModel(type, query); |
206 | QObject::connect(model.data(), &QAbstractItemModel::dataChanged, [model, &app](const QModelIndex &, const QModelIndex &, const QVector<int> &roles) { | 212 | QObject::connect(model.data(), &QAbstractItemModel::dataChanged, [model, &app](const QModelIndex &, const QModelIndex &, const QVector<int> &roles) { |
@@ -211,6 +217,11 @@ int main(int argc, char *argv[]) | |||
211 | }); | 217 | }); |
212 | return app.exec(); | 218 | return app.exec(); |
213 | } else if (command == "synchronize") { | 219 | } else if (command == "synchronize") { |
220 | auto resources = args; | ||
221 | Akonadi2::Query query; | ||
222 | for (const auto &res : resources) { | ||
223 | query.resources << res.toLatin1(); | ||
224 | } | ||
214 | query.syncOnDemand = true; | 225 | query.syncOnDemand = true; |
215 | query.processAll = true; | 226 | query.processAll = true; |
216 | Akonadi2::Store::synchronize(query).then<void>([&app]() { | 227 | Akonadi2::Store::synchronize(query).then<void>([&app]() { |
@@ -218,6 +229,15 @@ int main(int argc, char *argv[]) | |||
218 | }).exec(); | 229 | }).exec(); |
219 | app.exec(); | 230 | app.exec(); |
220 | } else if (command == "show") { | 231 | } else if (command == "show") { |
232 | auto type = !args.isEmpty() ? args.takeFirst() : QByteArray(); | ||
233 | auto resources = args; | ||
234 | |||
235 | Akonadi2::Query query; | ||
236 | for (const auto &res : resources) { | ||
237 | query.resources << res.toLatin1(); | ||
238 | } | ||
239 | query.syncOnDemand = false; | ||
240 | query.processAll = false; | ||
221 | query.liveQuery = true; | 241 | query.liveQuery = true; |
222 | if (type == "folder") { | 242 | if (type == "folder") { |
223 | query.parentProperty = "parent"; | 243 | query.parentProperty = "parent"; |
@@ -239,17 +259,45 @@ int main(int argc, char *argv[]) | |||
239 | app.exec(); | 259 | app.exec(); |
240 | } | 260 | } |
241 | } else if (command == "clear") { | 261 | } else if (command == "clear") { |
262 | auto resources = args; | ||
263 | |||
242 | qDebug() << "Clearing"; | 264 | qDebug() << "Clearing"; |
243 | for (const auto &resource : resources) { | 265 | for (const auto &resource : resources) { |
244 | Akonadi2::Store::removeFromDisk(resource.toLatin1()); | 266 | Akonadi2::Store::removeFromDisk(resource.toLatin1()); |
245 | } | 267 | } |
246 | } else if (command == "create") { | 268 | } else if (command == "create") { |
269 | auto type = !args.isEmpty() ? args.takeFirst() : QByteArray(); | ||
247 | if (type == "resource") { | 270 | if (type == "resource") { |
248 | Akonadi2::ApplicationDomain::AkonadiResource resource; | 271 | Akonadi2::ApplicationDomain::AkonadiResource resource; |
249 | resource.setProperty("identifier", resources.at(0)); | 272 | resource.setProperty("identifier", args.at(0)); |
250 | resource.setProperty("type", resources.at(1)); | 273 | resource.setProperty("type", args.at(1)); |
251 | Akonadi2::Store::create<Akonadi2::ApplicationDomain::AkonadiResource>(resource).exec().waitForFinished(); | 274 | Akonadi2::Store::create<Akonadi2::ApplicationDomain::AkonadiResource>(resource).exec().waitForFinished(); |
252 | qDebug() << "Created resource " << resources; | 275 | qDebug() << "Created resource " << args; |
276 | } | ||
277 | } else if (command == "remove") { | ||
278 | auto type = !args.isEmpty() ? args.takeFirst() : QByteArray(); | ||
279 | if (type == "resource") { | ||
280 | Akonadi2::ApplicationDomain::AkonadiResource resource; | ||
281 | resource.setProperty("identifier", args.at(0)); | ||
282 | Akonadi2::Store::remove<Akonadi2::ApplicationDomain::AkonadiResource>(resource).exec().waitForFinished(); | ||
283 | qDebug() << "Created resource " << args; | ||
284 | } | ||
285 | } else if (command == "stat") { | ||
286 | auto resources = args; | ||
287 | for (const auto &resource : resources) { | ||
288 | Akonadi2::Storage::Storage storage(Akonadi2::storageLocation(), resource, Akonadi2::Storage::ReadOnly); | ||
289 | auto transaction = storage.createTransaction(Akonadi2::Storage::ReadOnly); | ||
290 | |||
291 | QList<QByteArray> databases = transaction.getDatabaseNames(); | ||
292 | qint64 total = 0; | ||
293 | for (const auto &databaseName : databases) { | ||
294 | std::cout << "Database: " << databaseName.toStdString() << std::endl; | ||
295 | auto db = transaction.openDatabase(databaseName); | ||
296 | auto size = db.getSize(); | ||
297 | std::cout << "\tSize [kb]: " << size / 1024 << std::endl; | ||
298 | total += size; | ||
299 | } | ||
300 | std::cout << "Total [kb]: " << total / 1024 << std::endl; | ||
253 | } | 301 | } |
254 | } else { | 302 | } else { |
255 | qWarning() << "Unknown command " << command; | 303 | qWarning() << "Unknown command " << command; |