From 44744e281a56488c7ef257e12ca379ec4ceb2cdd Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Mon, 8 Feb 2016 21:34:06 +0100 Subject: Executed database removal in the resource instead of the client. The resource doesn't really notify all clients properly about the removal, but the tests all still pass. --- common/clientapi.cpp | 22 ++++++++++++++++------ common/clientapi.h | 5 +++++ common/commands.cpp | 2 ++ common/commands.h | 1 + common/genericresource.cpp | 6 ++++++ common/genericresource.h | 1 + common/listener.cpp | 8 ++++++++ common/resource.cpp | 5 +++++ common/resource.h | 5 +++++ common/storage.h | 7 +++++++ common/storage_lmdb.cpp | 8 ++++++++ examples/dummyresource/resourcefactory.cpp | 5 +++++ examples/dummyresource/resourcefactory.h | 1 + tests/dummyresourcetest.cpp | 6 +----- 14 files changed, 71 insertions(+), 11 deletions(-) diff --git a/common/clientapi.cpp b/common/clientapi.cpp index 5eb4b55..73bc194 100644 --- a/common/clientapi.cpp +++ b/common/clientapi.cpp @@ -197,12 +197,22 @@ KAsync::Job Store::start(const QByteArray &identifier) void Store::removeFromDisk(const QByteArray &identifier) { - //TODO By calling the resource executable with a --remove option instead - //we can ensure that no other resource process is running at the same time - QDir dir(Sink::storageLocation()); - for (const auto &folder : dir.entryList(QStringList() << identifier + "*")) { - Sink::Storage(Sink::storageLocation(), folder, Sink::Storage::ReadWrite).removeFromDisk(); - } + removeDataFromDisk(identifier).exec().waitForFinished(); +} + +KAsync::Job Store::removeDataFromDisk(const QByteArray &identifier) +{ + //All databases are going to become invalid, nuke the environments + //TODO: all clients should react to a notification the resource + Sink::Storage::clearEnv(); + Trace() << "Remove data from disk " << identifier; + auto time = QSharedPointer::create(); + time->start(); + auto resourceAccess = QSharedPointer::create(identifier); + resourceAccess->open(); + return resourceAccess->sendCommand(Sink::Commands::RemoveFromDiskCommand).then([resourceAccess, time]() { + Trace() << "Remove from disk complete." << Log::TraceTime(time->elapsed()); + }); } KAsync::Job Store::synchronize(const Sink::Query &query) diff --git a/common/clientapi.h b/common/clientapi.h index d0910df..45c5390 100644 --- a/common/clientapi.h +++ b/common/clientapi.h @@ -110,6 +110,11 @@ public: */ static void removeFromDisk(const QByteArray &resourceIdentifier); + /** + * Removes a resource from disk. + */ + static KAsync::Job removeDataFromDisk(const QByteArray &resourceIdentifier); + template static KAsync::Job fetchOne(const Sink::Query &query); diff --git a/common/commands.cpp b/common/commands.cpp index 8b915f0..5d38afa 100644 --- a/common/commands.cpp +++ b/common/commands.cpp @@ -61,6 +61,8 @@ QByteArray name(int commandId) return "RevisionReplayed"; case InspectionCommand: return "Inspection"; + case RemoveFromDiskCommand: + return "RemoveFromDisk"; case CustomCommand: return "Custom"; }; diff --git a/common/commands.h b/common/commands.h index fa4712b..adf2094 100644 --- a/common/commands.h +++ b/common/commands.h @@ -48,6 +48,7 @@ enum CommandIds { PingCommand, RevisionReplayedCommand, InspectionCommand, + RemoveFromDiskCommand, CustomCommand = 0xffff }; diff --git a/common/genericresource.cpp b/common/genericresource.cpp index 6087896..c097893 100644 --- a/common/genericresource.cpp +++ b/common/genericresource.cpp @@ -396,12 +396,18 @@ KAsync::Job GenericResource::replay(Sink::Storage &synchronizationStore, c return KAsync::null(); } +void GenericResource::removeDataFromDisk() +{ + removeFromDisk(mResourceInstanceIdentifier); +} + void GenericResource::removeFromDisk(const QByteArray &instanceIdentifier) { Sink::Storage(Sink::storageLocation(), instanceIdentifier, Sink::Storage::ReadWrite).removeFromDisk(); Sink::Storage(Sink::storageLocation(), instanceIdentifier + ".userqueue", Sink::Storage::ReadWrite).removeFromDisk(); Sink::Storage(Sink::storageLocation(), instanceIdentifier + ".synchronizerqueue", Sink::Storage::ReadWrite).removeFromDisk(); Sink::Storage(Sink::storageLocation(), instanceIdentifier + ".changereplay", Sink::Storage::ReadWrite).removeFromDisk(); + Sink::Storage(Sink::storageLocation(), instanceIdentifier + ".synchronization", Sink::Storage::ReadWrite).removeFromDisk(); } qint64 GenericResource::diskUsage(const QByteArray &instanceIdentifier) diff --git a/common/genericresource.h b/common/genericresource.h index 1bbb0f5..ae505a6 100644 --- a/common/genericresource.h +++ b/common/genericresource.h @@ -52,6 +52,7 @@ public: int error() const; + void removeDataFromDisk() Q_DECL_OVERRIDE; static void removeFromDisk(const QByteArray &instanceIdentifier); static qint64 diskUsage(const QByteArray &instanceIdentifier); diff --git a/common/listener.cpp b/common/listener.cpp index 323252b..d2fa266 100644 --- a/common/listener.cpp +++ b/common/listener.cpp @@ -275,6 +275,14 @@ void Listener::processCommand(int commandId, uint messageId, const QByteArray &c loadResource()->setLowerBoundRevision(lowerBoundRevision()); } break; + case Sink::Commands::RemoveFromDiskCommand: { + Log() << QString("\tReceived a remove from disk command from %1").arg(client.name); + m_resource->removeDataFromDisk(); + delete m_resource; + m_resource = nullptr; + loadResource()->setLowerBoundRevision(0); + } + break; default: if (commandId > Sink::Commands::CustomCommand) { Log() << QString("\tReceived custom command from %1: ").arg(client.name) << commandId; diff --git a/common/resource.cpp b/common/resource.cpp index 6972efe..5cbb2f2 100644 --- a/common/resource.cpp +++ b/common/resource.cpp @@ -63,6 +63,11 @@ void Resource::setLowerBoundRevision(qint64 revision) Q_UNUSED(revision) } +void Resource::removeDataFromDisk() +{ +} + + class ResourceFactory::Private { public: diff --git a/common/resource.h b/common/resource.h index f6ca039..368759c 100644 --- a/common/resource.h +++ b/common/resource.h @@ -55,6 +55,11 @@ public: */ virtual void setLowerBoundRevision(qint64 revision); + /** + * Remove the data from disk + */ + virtual void removeDataFromDisk(); + Q_SIGNALS: void revisionUpdated(qint64); void notify(Notification); diff --git a/common/storage.h b/common/storage.h index 84175b3..8ec3f1d 100644 --- a/common/storage.h +++ b/common/storage.h @@ -180,6 +180,13 @@ public: qint64 diskUsage() const; void removeFromDisk() const; + /** + * Clears all cached environments. + * + * This only ever has to be called if a database was removed from another process. + */ + static void clearEnv(); + static qint64 maxRevision(const Sink::Storage::Transaction &); static void setMaxRevision(Sink::Storage::Transaction &, qint64 revision); diff --git a/common/storage_lmdb.cpp b/common/storage_lmdb.cpp index e2c623e..1efffc4 100644 --- a/common/storage_lmdb.cpp +++ b/common/storage_lmdb.cpp @@ -615,4 +615,12 @@ void Storage::removeFromDisk() const mdb_env_close(env); } +void Storage::clearEnv() +{ + for (auto env : Storage::Private::sEnvironments) { + mdb_env_close(env); + } + Storage::Private::sEnvironments.clear(); +} + } // namespace Sink diff --git a/examples/dummyresource/resourcefactory.cpp b/examples/dummyresource/resourcefactory.cpp index 31633d7..36866ec 100644 --- a/examples/dummyresource/resourcefactory.cpp +++ b/examples/dummyresource/resourcefactory.cpp @@ -128,6 +128,11 @@ KAsync::Job DummyResource::replay(Sink::Storage &synchronizationStore, con return KAsync::null(); } +void DummyResource::removeDataFromDisk() +{ + removeFromDisk(mResourceInstanceIdentifier); +} + void DummyResource::removeFromDisk(const QByteArray &instanceIdentifier) { GenericResource::removeFromDisk(instanceIdentifier); diff --git a/examples/dummyresource/resourcefactory.h b/examples/dummyresource/resourcefactory.h index 240bb9f..865f6e5 100644 --- a/examples/dummyresource/resourcefactory.h +++ b/examples/dummyresource/resourcefactory.h @@ -39,6 +39,7 @@ public: DummyResource(const QByteArray &instanceIdentifier, const QSharedPointer &pipeline = QSharedPointer()); KAsync::Job synchronizeWithSource(Sink::Storage &mainStore, Sink::Storage &synchronizationStore) Q_DECL_OVERRIDE; using GenericResource::synchronizeWithSource; + void removeDataFromDisk() Q_DECL_OVERRIDE; static void removeFromDisk(const QByteArray &instanceIdentifier); KAsync::Job inspect(int inspectionType, const QByteArray &inspectionId, const QByteArray &domainType, const QByteArray &entityId, const QByteArray &property, const QVariant &expectedValue) Q_DECL_OVERRIDE; private: diff --git a/tests/dummyresourcetest.cpp b/tests/dummyresourcetest.cpp index 82c713d..c5b2f30 100644 --- a/tests/dummyresourcetest.cpp +++ b/tests/dummyresourcetest.cpp @@ -31,11 +31,7 @@ private Q_SLOTS: void cleanup() { - Sink::Store::shutdown(QByteArray("org.kde.dummy.instance1")).exec().waitForFinished(); - DummyResource::removeFromDisk("org.kde.dummy.instance1"); - auto factory = Sink::ResourceFactory::load("org.kde.dummy"); - QVERIFY(factory); - Sink::Store::start(QByteArray("org.kde.dummy.instance1")).exec().waitForFinished(); + Sink::Store::removeDataFromDisk(QByteArray("org.kde.dummy.instance1")).exec().waitForFinished(); } void init() -- cgit v1.2.3