From 9f6751df8e6f483b112c2b24c0bc725924f17356 Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Fri, 9 Dec 2016 16:31:30 +0100 Subject: Move the BLOB property handling to the entitystore. This is really part of the storage, and will help us to cleanly implement features like moving properties into a temporary place when reading in a clean way as well. --- common/storage/entitystore.cpp | 51 ++++++++++++++++++++++++++++++++++++++++++ common/storage/entitystore.h | 1 + 2 files changed, 52 insertions(+) (limited to 'common/storage') diff --git a/common/storage/entitystore.cpp b/common/storage/entitystore.cpp index 999bb2c..d8b1121 100644 --- a/common/storage/entitystore.cpp +++ b/common/storage/entitystore.cpp @@ -19,6 +19,9 @@ */ #include "entitystore.h" +#include +#include + #include "entitybuffer.h" #include "log.h" #include "typeindex.h" @@ -90,6 +93,11 @@ public: return ApplicationDomain::ApplicationDomainType{resourceContext.instanceId(), uid, revision, adaptor}; } + QString entityBlobStoragePath(const QByteArray &id) + { + return Sink::resourceStorageLocation(resourceContext.instanceId()) + "/blob/" + id; + } + }; EntityStore::EntityStore(const ResourceContext &context) @@ -120,6 +128,38 @@ void EntityStore::abortTransaction() d->transaction = Storage::DataStore::Transaction(); } +void EntityStore::copyBlobs(ApplicationDomain::ApplicationDomainType &entity, qint64 newRevision) +{ + const auto directory = d->entityBlobStoragePath(entity.identifier()); + if (!QDir().mkpath(directory)) { + SinkWarning() << "Failed to create the directory: " << directory; + } + + for (const auto &property : entity.changedProperties()) { + const auto value = entity.getProperty(property); + if (value.canConvert()) { + const auto blob = value.value(); + bool blobIsExternal = blob.isExternal; + //Any blob that is not part of the storage yet has to be moved there. + if (blob.isExternal) { + auto oldPath = blob.value; + auto filePath = directory + QString("/%1%2.blob").arg(QString::number(newRevision)).arg(QString::fromLatin1(property)); + //In case we hit the same revision again due to a rollback. + QFile::remove(filePath); + QFile origFile(oldPath); + if (!origFile.open(QIODevice::ReadWrite)) { + SinkWarning() << "Failed to open the original file with write rights: " << origFile.errorString(); + } + if (!origFile.rename(filePath)) { + SinkWarning() << "Failed to move the file from: " << oldPath << " to " << filePath << ". " << origFile.errorString(); + } + origFile.close(); + entity.setProperty(property, QVariant::fromValue(ApplicationDomain::BLOB{filePath})); + } + } + } +} + bool EntityStore::add(const QByteArray &type, const ApplicationDomain::ApplicationDomainType &entity_, bool replayToSource, const PreprocessCreation &preprocess) { if (entity_.identifier().isEmpty()) { @@ -138,6 +178,8 @@ bool EntityStore::add(const QByteArray &type, const ApplicationDomain::Applicati //The maxRevision may have changed meanwhile if the entity created sub-entities const qint64 newRevision = maxRevision() + 1; + copyBlobs(entity, newRevision); + // Add metadata buffer flatbuffers::FlatBufferBuilder metadataFbb; auto metadataBuilder = MetadataBuilder(metadataFbb); @@ -192,6 +234,8 @@ bool EntityStore::modify(const QByteArray &type, const ApplicationDomain::Applic const qint64 newRevision = DataStore::maxRevision(d->transaction) + 1; + copyBlobs(newEntity, newRevision); + // Add metadata buffer flatbuffers::FlatBufferBuilder metadataFbb; { @@ -297,6 +341,13 @@ void EntityStore::cleanupRevision(qint64 revision) DataStore::removeRevision(d->transaction, rev); DataStore::mainDatabase(d->transaction, bufferType).remove(key); } + if (metadata->operation() == Operation_Removal) { + const auto directory = d->entityBlobStoragePath(uid); + QDir dir(directory); + if (!dir.removeRecursively()) { + SinkError() << "Failed to cleanup: " << directory; + } + } } return true; diff --git a/common/storage/entitystore.h b/common/storage/entitystore.h index 06ca8c4..c626ebc 100644 --- a/common/storage/entitystore.h +++ b/common/storage/entitystore.h @@ -110,6 +110,7 @@ public: qint64 maxRevision(); private: + void copyBlobs(ApplicationDomain::ApplicationDomainType &entity, qint64 newRevision); class Private; const QSharedPointer d; }; -- cgit v1.2.3