diff options
-rw-r--r-- | common/storage.h | 43 | ||||
-rw-r--r-- | common/storage_common.cpp | 13 | ||||
-rw-r--r-- | common/storage_lmdb.cpp | 269 |
3 files changed, 0 insertions, 325 deletions
diff --git a/common/storage.h b/common/storage.h index fb44c1c..9fe4e99 100644 --- a/common/storage.h +++ b/common/storage.h | |||
@@ -107,49 +107,6 @@ public: | |||
107 | Transaction createTransaction(AccessMode mode = ReadWrite, | 107 | Transaction createTransaction(AccessMode mode = ReadWrite, |
108 | const std::function<void(const Storage::Error &error)> &errorHandler = std::function<void(const Storage::Error &error)>()); | 108 | const std::function<void(const Storage::Error &error)> &errorHandler = std::function<void(const Storage::Error &error)>()); |
109 | 109 | ||
110 | |||
111 | //Old API | ||
112 | bool isInTransaction() const; | ||
113 | bool startTransaction(AccessMode mode = ReadWrite, const std::function<void(const Storage::Error &error)> &errorHandler = std::function<void(const Storage::Error &error)>()); | ||
114 | bool commitTransaction(const std::function<void(const Storage::Error &error)> &errorHandler = std::function<void(const Storage::Error &error)>()); | ||
115 | void abortTransaction(); | ||
116 | |||
117 | /** | ||
118 | * Write values. | ||
119 | */ | ||
120 | bool write(const void *key, size_t keySize, const void *value, size_t valueSize, const std::function<void(const Storage::Error &error)> &errorHandler = std::function<void(const Storage::Error &error)>()); | ||
121 | |||
122 | /** | ||
123 | * Convenience API | ||
124 | */ | ||
125 | bool write(const QByteArray &key, const QByteArray &value, const std::function<void(const Storage::Error &error)> &errorHandler = std::function<void(const Storage::Error &error)>()); | ||
126 | |||
127 | /** | ||
128 | * Read values with a give key. | ||
129 | * | ||
130 | * * An empty @param key results in a full scan | ||
131 | * * If duplicates are existing (revisions), all values are returned. | ||
132 | * * The pointers of the returned values are valid during the execution of the @param resultHandler | ||
133 | * | ||
134 | * @return The number of values retrieved. | ||
135 | */ | ||
136 | int scan(const QByteArray &key, const std::function<bool(void *keyPtr, int keySize, void *ptr, int size)> &resultHandler, const std::function<void(const Storage::Error &error)> &errorHandler = std::function<void(const Storage::Error &error)>()); | ||
137 | |||
138 | /** | ||
139 | * Convenience API | ||
140 | */ | ||
141 | int scan(const QByteArray &key, const std::function<bool(const QByteArray &value)> &resultHandler, const std::function<void(const Storage::Error &error)> &errorHandler = std::function<void(const Storage::Error &error)>()); | ||
142 | |||
143 | /** | ||
144 | * Remove a value | ||
145 | */ | ||
146 | void remove(void const *key, uint keySize, const std::function<void(const Storage::Error &error)> &errorHandler = std::function<void(const Storage::Error &error)>()); | ||
147 | |||
148 | /** | ||
149 | * Convenience API | ||
150 | */ | ||
151 | void remove(const QByteArray &key, const std::function<void(const Storage::Error &error)> &errorHandler = std::function<void(const Storage::Error &error)>()); | ||
152 | |||
153 | /** | 110 | /** |
154 | * Set the default error handler. | 111 | * Set the default error handler. |
155 | */ | 112 | */ |
diff --git a/common/storage_common.cpp b/common/storage_common.cpp index 8006a8e..4de585d 100644 --- a/common/storage_common.cpp +++ b/common/storage_common.cpp | |||
@@ -54,19 +54,6 @@ std::function<void(const Storage::Error &error)> Storage::defaultErrorHandler() | |||
54 | return basicErrorHandler(); | 54 | return basicErrorHandler(); |
55 | } | 55 | } |
56 | 56 | ||
57 | int Storage::scan(const QByteArray &key, const std::function<bool(const QByteArray &value)> &resultHandler, const std::function<void(const Storage::Error &error)> &errorHandler) | ||
58 | { | ||
59 | return scan(key, [&resultHandler](void *keyPtr, int keySize, void *valuePtr, int valueSize) { | ||
60 | return resultHandler(QByteArray::fromRawData((char*)(valuePtr), valueSize)); | ||
61 | }, | ||
62 | errorHandler); | ||
63 | } | ||
64 | |||
65 | bool Storage::write(const QByteArray &sKey, const QByteArray &sValue, const std::function<void(const Storage::Error &error)> &errorHandler) | ||
66 | { | ||
67 | return write(const_cast<char*>(sKey.data()), sKey.size(), const_cast<char*>(sValue.data()), sValue.size(), errorHandler); | ||
68 | } | ||
69 | |||
70 | void Storage::setMaxRevision(qint64 revision) | 57 | void Storage::setMaxRevision(qint64 revision) |
71 | { | 58 | { |
72 | auto transaction = createTransaction(Akonadi2::Storage::ReadWrite); | 59 | auto transaction = createTransaction(Akonadi2::Storage::ReadWrite); |
diff --git a/common/storage_lmdb.cpp b/common/storage_lmdb.cpp index d3c52b7..c02d523 100644 --- a/common/storage_lmdb.cpp +++ b/common/storage_lmdb.cpp | |||
@@ -397,275 +397,6 @@ Storage::Transaction Storage::createTransaction(AccessMode type, const std::func | |||
397 | return Transaction(); | 397 | return Transaction(); |
398 | } | 398 | } |
399 | 399 | ||
400 | bool Storage::startTransaction(AccessMode type, | ||
401 | const std::function<void(const Storage::Error &error)> &errorHandler) | ||
402 | { | ||
403 | if (!d->env) { | ||
404 | return false; | ||
405 | } | ||
406 | |||
407 | bool requestedRead = type == ReadOnly; | ||
408 | |||
409 | if (d->mode == ReadOnly && !requestedRead) { | ||
410 | Error error(d->name.toLatin1(), ErrorCodes::GenericError, "Requested read/write transaction in read-only mode."); | ||
411 | errorHandler ? errorHandler(error) : defaultErrorHandler()(error); | ||
412 | return false; | ||
413 | } | ||
414 | |||
415 | //We already have a transaction | ||
416 | if (d->transaction && (!d->readTransaction || requestedRead)) { | ||
417 | return true; | ||
418 | } | ||
419 | |||
420 | if (d->transaction) { | ||
421 | // we are about to turn a read transaction into a writable one | ||
422 | abortTransaction(); | ||
423 | } | ||
424 | |||
425 | if (d->firstOpen && requestedRead) { | ||
426 | //This is only required for named databases | ||
427 | |||
428 | //A write transaction is at least required the first time | ||
429 | // mdb_txn_begin(d->env, nullptr, 0, &d->transaction); | ||
430 | //Open the database | ||
431 | //With this we could open multiple named databases if we wanted to | ||
432 | // mdb_dbi_open(d->transaction, nullptr, 0, &d->dbi); | ||
433 | // mdb_txn_abort(d->transaction); | ||
434 | } | ||
435 | |||
436 | int rc; | ||
437 | rc = mdb_txn_begin(d->env, NULL, requestedRead ? MDB_RDONLY : 0, &d->transaction); | ||
438 | if (!rc) { | ||
439 | rc = mdb_dbi_open(d->transaction, NULL, d->allowDuplicates ? MDB_DUPSORT : 0, &d->dbi); | ||
440 | if (rc) { | ||
441 | Error error(d->name.toLatin1(), ErrorCodes::GenericError, "Error while opening transaction: " + QByteArray(mdb_strerror(rc))); | ||
442 | errorHandler ? errorHandler(error) : defaultErrorHandler()(error); | ||
443 | } | ||
444 | } else { | ||
445 | if (rc) { | ||
446 | Error error(d->name.toLatin1(), ErrorCodes::GenericError, "Error while beginning transaction: " + QByteArray(mdb_strerror(rc))); | ||
447 | errorHandler ? errorHandler(error) : defaultErrorHandler()(error); | ||
448 | } | ||
449 | } | ||
450 | |||
451 | d->firstOpen = false; | ||
452 | d->readTransaction = requestedRead; | ||
453 | return !rc; | ||
454 | } | ||
455 | |||
456 | bool Storage::commitTransaction(const std::function<void(const Storage::Error &error)> &errorHandler) | ||
457 | { | ||
458 | if (!d->env) { | ||
459 | return false; | ||
460 | } | ||
461 | |||
462 | if (!d->transaction) { | ||
463 | return false; | ||
464 | } | ||
465 | |||
466 | int rc; | ||
467 | rc = mdb_txn_commit(d->transaction); | ||
468 | d->transaction = 0; | ||
469 | |||
470 | if (rc) { | ||
471 | Error error(d->name.toLatin1(), ErrorCodes::GenericError, "Error during transaction commit: " + QByteArray(mdb_strerror(rc))); | ||
472 | errorHandler ? errorHandler(error) : defaultErrorHandler()(error); | ||
473 | } | ||
474 | |||
475 | return !rc; | ||
476 | } | ||
477 | |||
478 | void Storage::abortTransaction() | ||
479 | { | ||
480 | if (!d->env || !d->transaction) { | ||
481 | return; | ||
482 | } | ||
483 | |||
484 | mdb_txn_abort(d->transaction); | ||
485 | d->transaction = 0; | ||
486 | } | ||
487 | |||
488 | bool Storage::write(const void *keyPtr, size_t keySize, const void *valuePtr, size_t valueSize, | ||
489 | const std::function<void(const Storage::Error &error)> &errorHandler) | ||
490 | { | ||
491 | if (!d->env) { | ||
492 | Error error(d->name.toLatin1(), ErrorCodes::NotOpen, "Not open"); | ||
493 | errorHandler ? errorHandler(error) : defaultErrorHandler()(error); | ||
494 | return false; | ||
495 | } | ||
496 | |||
497 | if (d->mode == ReadOnly) { | ||
498 | Error error(d->name.toLatin1(), ErrorCodes::GenericError, "Tried to write in read-only mode."); | ||
499 | errorHandler ? errorHandler(error) : defaultErrorHandler()(error); | ||
500 | return false; | ||
501 | } | ||
502 | |||
503 | if (!keyPtr || keySize == 0) { | ||
504 | Error error(d->name.toLatin1(), ErrorCodes::GenericError, "Tried to write empty key."); | ||
505 | errorHandler ? errorHandler(error) : defaultErrorHandler()(error); | ||
506 | return false; | ||
507 | } | ||
508 | |||
509 | const bool implicitTransaction = !d->transaction || d->readTransaction; | ||
510 | if (implicitTransaction) { | ||
511 | if (!startTransaction()) { | ||
512 | Error error(d->name.toLatin1(), ErrorCodes::TransactionError, "Failed to start transaction."); | ||
513 | errorHandler ? errorHandler(error) : defaultErrorHandler()(error); | ||
514 | return false; | ||
515 | } | ||
516 | } | ||
517 | |||
518 | int rc; | ||
519 | MDB_val key, data; | ||
520 | key.mv_size = keySize; | ||
521 | key.mv_data = const_cast<void*>(keyPtr); | ||
522 | data.mv_size = valueSize; | ||
523 | data.mv_data = const_cast<void*>(valuePtr); | ||
524 | rc = mdb_put(d->transaction, d->dbi, &key, &data, 0); | ||
525 | |||
526 | if (rc) { | ||
527 | Error error(d->name.toLatin1(), ErrorCodes::GenericError, "mdb_put: " + QByteArray(mdb_strerror(rc))); | ||
528 | errorHandler ? errorHandler(error) : defaultErrorHandler()(error); | ||
529 | } | ||
530 | |||
531 | if (implicitTransaction) { | ||
532 | if (rc) { | ||
533 | Error error(d->name.toLatin1(), ErrorCodes::GenericError, "aborting transaction"); | ||
534 | errorHandler ? errorHandler(error) : defaultErrorHandler()(error); | ||
535 | abortTransaction(); | ||
536 | } else { | ||
537 | rc = commitTransaction(); | ||
538 | } | ||
539 | } | ||
540 | |||
541 | return !rc; | ||
542 | } | ||
543 | |||
544 | int Storage::scan(const QByteArray &k, | ||
545 | const std::function<bool(void *keyPtr, int keySize, void *valuePtr, int valueSize)> &resultHandler, | ||
546 | const std::function<void(const Storage::Error &error)> &errorHandler) | ||
547 | { | ||
548 | if (!d->env) { | ||
549 | Error error(d->name.toLatin1(), ErrorCodes::NotOpen, "Not open"); | ||
550 | errorHandler ? errorHandler(error) : defaultErrorHandler()(error); | ||
551 | return 0; | ||
552 | } | ||
553 | |||
554 | int rc; | ||
555 | MDB_val key; | ||
556 | MDB_val data; | ||
557 | MDB_cursor *cursor; | ||
558 | |||
559 | key.mv_data = (void*)k.constData(); | ||
560 | key.mv_size = k.size(); | ||
561 | |||
562 | const bool implicitTransaction = !d->transaction; | ||
563 | if (implicitTransaction) { | ||
564 | if (!startTransaction(ReadOnly)) { | ||
565 | Error error(d->name.toLatin1(), ErrorCodes::TransactionError, "Could not start transaction"); | ||
566 | errorHandler ? errorHandler(error) : defaultErrorHandler()(error); | ||
567 | return 0; | ||
568 | } | ||
569 | } | ||
570 | |||
571 | rc = mdb_cursor_open(d->transaction, d->dbi, &cursor); | ||
572 | if (rc) { | ||
573 | Error error(d->name.toLatin1(), getErrorCode(rc), QByteArray("Error during mdb_cursor open: ") + QByteArray(mdb_strerror(rc))); | ||
574 | errorHandler ? errorHandler(error) : defaultErrorHandler()(error); | ||
575 | return 0; | ||
576 | } | ||
577 | |||
578 | int numberOfRetrievedValues = 0; | ||
579 | |||
580 | if (k.isEmpty() || d->allowDuplicates) { | ||
581 | if ((rc = mdb_cursor_get(cursor, &key, &data, d->allowDuplicates ? MDB_SET_RANGE : MDB_FIRST)) == 0) { | ||
582 | numberOfRetrievedValues++; | ||
583 | if (resultHandler(key.mv_data, key.mv_size, data.mv_data, data.mv_size)) { | ||
584 | while ((rc = mdb_cursor_get(cursor, &key, &data, d->allowDuplicates ? MDB_NEXT_DUP : MDB_NEXT)) == 0) { | ||
585 | numberOfRetrievedValues++; | ||
586 | if (!resultHandler(key.mv_data, key.mv_size, data.mv_data, data.mv_size)) { | ||
587 | break; | ||
588 | } | ||
589 | } | ||
590 | } | ||
591 | } | ||
592 | |||
593 | //We never find the last value | ||
594 | if (rc == MDB_NOTFOUND) { | ||
595 | rc = 0; | ||
596 | } | ||
597 | } else { | ||
598 | if ((rc = mdb_cursor_get(cursor, &key, &data, MDB_SET)) == 0) { | ||
599 | numberOfRetrievedValues++; | ||
600 | resultHandler(key.mv_data, key.mv_size, data.mv_data, data.mv_size); | ||
601 | } | ||
602 | } | ||
603 | |||
604 | mdb_cursor_close(cursor); | ||
605 | |||
606 | if (rc) { | ||
607 | Error error(d->name.toLatin1(), getErrorCode(rc), QByteArray("Key: ") + k + " : " + QByteArray(mdb_strerror(rc))); | ||
608 | errorHandler ? errorHandler(error) : defaultErrorHandler()(error); | ||
609 | } | ||
610 | |||
611 | if (implicitTransaction) { | ||
612 | abortTransaction(); | ||
613 | } | ||
614 | return numberOfRetrievedValues; | ||
615 | } | ||
616 | |||
617 | void Storage::remove(const QByteArray &key, | ||
618 | const std::function<void(const Storage::Error &error)> &errorHandler) | ||
619 | { | ||
620 | remove(key.data(), key.size(), errorHandler); | ||
621 | } | ||
622 | |||
623 | void Storage::remove(const void *keyData, uint keySize, | ||
624 | const std::function<void(const Storage::Error &error)> &errorHandler) | ||
625 | { | ||
626 | if (!d->env) { | ||
627 | Error error(d->name.toLatin1(), ErrorCodes::GenericError, "Not open"); | ||
628 | errorHandler ? errorHandler(error) : defaultErrorHandler()(error); | ||
629 | return; | ||
630 | } | ||
631 | |||
632 | if (d->mode == ReadOnly) { | ||
633 | Error error(d->name.toLatin1(), ErrorCodes::ReadOnlyError, "Tried to write in read-only mode"); | ||
634 | errorHandler ? errorHandler(error) : defaultErrorHandler()(error); | ||
635 | return; | ||
636 | } | ||
637 | |||
638 | const bool implicitTransaction = !d->transaction || d->readTransaction; | ||
639 | if (implicitTransaction) { | ||
640 | if (!startTransaction()) { | ||
641 | Error error(d->name.toLatin1(), ErrorCodes::TransactionError, "Could not start transaction"); | ||
642 | errorHandler ? errorHandler(error) : defaultErrorHandler()(error); | ||
643 | return; | ||
644 | } | ||
645 | } | ||
646 | |||
647 | int rc; | ||
648 | MDB_val key; | ||
649 | key.mv_size = keySize; | ||
650 | key.mv_data = const_cast<void*>(keyData); | ||
651 | rc = mdb_del(d->transaction, d->dbi, &key, 0); | ||
652 | |||
653 | if (rc) { | ||
654 | Error error(d->name.toLatin1(), ErrorCodes::GenericError, QString("Error on mdb_del: %1 %2").arg(rc).arg(mdb_strerror(rc)).toLatin1()); | ||
655 | errorHandler ? errorHandler(error) : defaultErrorHandler()(error); | ||
656 | } | ||
657 | |||
658 | if (implicitTransaction) { | ||
659 | if (rc) { | ||
660 | abortTransaction(); | ||
661 | } else { | ||
662 | rc = commitTransaction(); | ||
663 | } | ||
664 | } | ||
665 | |||
666 | return; | ||
667 | } | ||
668 | |||
669 | qint64 Storage::diskUsage() const | 400 | qint64 Storage::diskUsage() const |
670 | { | 401 | { |
671 | QFileInfo info(d->storageRoot + '/' + d->name + "/data.mdb"); | 402 | QFileInfo info(d->storageRoot + '/' + d->name + "/data.mdb"); |