summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/index.cpp14
-rw-r--r--common/storage_lmdb.cpp6
-rw-r--r--common/typeindex.cpp70
-rw-r--r--common/typeindex.h5
4 files changed, 57 insertions, 38 deletions
diff --git a/common/index.cpp b/common/index.cpp
index f3d05f1..f09e265 100644
--- a/common/index.cpp
+++ b/common/index.cpp
@@ -18,22 +18,26 @@ Index::Index(const QByteArray &name, Sink::Storage::DataStore::Transaction &tran
18 18
19void Index::add(const QByteArray &key, const QByteArray &value) 19void Index::add(const QByteArray &key, const QByteArray &value)
20{ 20{
21 mDb.write(key, value); 21 mDb.write(key, value, [&] (const Sink::Storage::DataStore::Error &error) {
22 SinkWarning() << "Error while writing value" << error;
23 });
22} 24}
23 25
24void Index::remove(const QByteArray &key, const QByteArray &value) 26void Index::remove(const QByteArray &key, const QByteArray &value)
25{ 27{
26 mDb.remove(key, value); 28 mDb.remove(key, value, [&] (const Sink::Storage::DataStore::Error &error) {
29 SinkWarning() << "Error while removing value: " << key << value << error << error.store;
30 });
27} 31}
28 32
29void Index::lookup(const QByteArray &key, const std::function<void(const QByteArray &value)> &resultHandler, const std::function<void(const Error &error)> &errorHandler, bool matchSubStringKeys) 33void Index::lookup(const QByteArray &key, const std::function<void(const QByteArray &value)> &resultHandler, const std::function<void(const Error &error)> &errorHandler, bool matchSubStringKeys)
30{ 34{
31 mDb.scan(key, 35 mDb.scan(key,
32 [this, resultHandler](const QByteArray &key, const QByteArray &value) -> bool { 36 [&](const QByteArray &key, const QByteArray &value) -> bool {
33 resultHandler(value); 37 resultHandler(value);
34 return true; 38 return true;
35 }, 39 },
36 [this, errorHandler](const Sink::Storage::DataStore::Error &error) { 40 [&](const Sink::Storage::DataStore::Error &error) {
37 SinkWarning() << "Error while retrieving value" << error.message; 41 SinkWarning() << "Error while retrieving value" << error.message;
38 errorHandler(Error(error.store, error.code, error.message)); 42 errorHandler(Error(error.store, error.code, error.message));
39 }, 43 },
@@ -44,6 +48,6 @@ QByteArray Index::lookup(const QByteArray &key)
44{ 48{
45 QByteArray result; 49 QByteArray result;
46 //We have to create a deep copy, otherwise the returned data may become invalid when the transaction ends. 50 //We have to create a deep copy, otherwise the returned data may become invalid when the transaction ends.
47 lookup(key, [&result](const QByteArray &value) { result = QByteArray(value.constData(), value.size()); }, [this](const Index::Error &error) { SinkWarning() << "Error while retrieving value" << error.message; }); 51 lookup(key, [&](const QByteArray &value) { result = QByteArray(value.constData(), value.size()); }, [this](const Index::Error &error) { SinkWarning() << "Error while retrieving value" << error.message; });
48 return result; 52 return result;
49} 53}
diff --git a/common/storage_lmdb.cpp b/common/storage_lmdb.cpp
index f534029..b389e58 100644
--- a/common/storage_lmdb.cpp
+++ b/common/storage_lmdb.cpp
@@ -195,7 +195,11 @@ void DataStore::NamedDatabase::remove(const QByteArray &k, const QByteArray &val
195 } 195 }
196 196
197 if (rc) { 197 if (rc) {
198 Error error(d->name.toLatin1() + d->db, ErrorCodes::GenericError, QString("Error on mdb_del: %1 %2").arg(rc).arg(mdb_strerror(rc)).toLatin1()); 198 auto errorCode = ErrorCodes::GenericError;
199 if (rc == MDB_NOTFOUND) {
200 errorCode = ErrorCodes::NotFound;
201 }
202 Error error(d->name.toLatin1() + d->db, errorCode, QString("Error on mdb_del: %1 %2").arg(rc).arg(mdb_strerror(rc)).toLatin1());
199 errorHandler ? errorHandler(error) : d->defaultErrorHandler(error); 203 errorHandler ? errorHandler(error) : d->defaultErrorHandler(error);
200 } 204 }
201} 205}
diff --git a/common/typeindex.cpp b/common/typeindex.cpp
index a65c676..a0d6d43 100644
--- a/common/typeindex.cpp
+++ b/common/typeindex.cpp
@@ -72,9 +72,13 @@ QByteArray TypeIndex::indexName(const QByteArray &property, const QByteArray &so
72template <> 72template <>
73void TypeIndex::addProperty<QByteArray>(const QByteArray &property) 73void TypeIndex::addProperty<QByteArray>(const QByteArray &property)
74{ 74{
75 auto indexer = [this, property](const QByteArray &identifier, const QVariant &value, Sink::Storage::DataStore::Transaction &transaction) { 75 auto indexer = [this, property](bool add, const QByteArray &identifier, const QVariant &value, Sink::Storage::DataStore::Transaction &transaction) {
76 // SinkTraceCtx(mLogCtx) << "Indexing " << mType + ".index." + property << value.toByteArray(); 76 // SinkTraceCtx(mLogCtx) << "Indexing " << mType + ".index." + property << value.toByteArray();
77 Index(indexName(property), transaction).add(getByteArray(value), identifier); 77 if (add) {
78 Index(indexName(property), transaction).add(getByteArray(value), identifier);
79 } else {
80 Index(indexName(property), transaction).remove(getByteArray(value), identifier);
81 }
78 }; 82 };
79 mIndexer.insert(property, indexer); 83 mIndexer.insert(property, indexer);
80 mProperties << property; 84 mProperties << property;
@@ -83,9 +87,13 @@ void TypeIndex::addProperty<QByteArray>(const QByteArray &property)
83template <> 87template <>
84void TypeIndex::addProperty<QString>(const QByteArray &property) 88void TypeIndex::addProperty<QString>(const QByteArray &property)
85{ 89{
86 auto indexer = [this, property](const QByteArray &identifier, const QVariant &value, Sink::Storage::DataStore::Transaction &transaction) { 90 auto indexer = [this, property](bool add, const QByteArray &identifier, const QVariant &value, Sink::Storage::DataStore::Transaction &transaction) {
87 // SinkTraceCtx(mLogCtx) << "Indexing " << mType + ".index." + property << value.toByteArray(); 91 // SinkTraceCtx(mLogCtx) << "Indexing " << mType + ".index." + property << value.toByteArray();
88 Index(indexName(property), transaction).add(getByteArray(value), identifier); 92 if (add) {
93 Index(indexName(property), transaction).add(getByteArray(value), identifier);
94 } else {
95 Index(indexName(property), transaction).remove(getByteArray(value), identifier);
96 }
89 }; 97 };
90 mIndexer.insert(property, indexer); 98 mIndexer.insert(property, indexer);
91 mProperties << property; 99 mProperties << property;
@@ -94,9 +102,13 @@ void TypeIndex::addProperty<QString>(const QByteArray &property)
94template <> 102template <>
95void TypeIndex::addProperty<QDateTime>(const QByteArray &property) 103void TypeIndex::addProperty<QDateTime>(const QByteArray &property)
96{ 104{
97 auto indexer = [this, property](const QByteArray &identifier, const QVariant &value, Sink::Storage::DataStore::Transaction &transaction) { 105 auto indexer = [this, property](bool add, const QByteArray &identifier, const QVariant &value, Sink::Storage::DataStore::Transaction &transaction) {
98 //SinkTraceCtx(mLogCtx) << "Indexing " << mType + ".index." + property << getByteArray(value); 106 //SinkTraceCtx(mLogCtx) << "Indexing " << mType + ".index." + property << getByteArray(value);
99 Index(indexName(property), transaction).add(getByteArray(value), identifier); 107 if (add) {
108 Index(indexName(property), transaction).add(getByteArray(value), identifier);
109 } else {
110 Index(indexName(property), transaction).remove(getByteArray(value), identifier);
111 }
100 }; 112 };
101 mIndexer.insert(property, indexer); 113 mIndexer.insert(property, indexer);
102 mProperties << property; 114 mProperties << property;
@@ -111,10 +123,15 @@ void TypeIndex::addProperty<ApplicationDomain::Reference>(const QByteArray &prop
111template <> 123template <>
112void TypeIndex::addPropertyWithSorting<QByteArray, QDateTime>(const QByteArray &property, const QByteArray &sortProperty) 124void TypeIndex::addPropertyWithSorting<QByteArray, QDateTime>(const QByteArray &property, const QByteArray &sortProperty)
113{ 125{
114 auto indexer = [=](const QByteArray &identifier, const QVariant &value, const QVariant &sortValue, Sink::Storage::DataStore::Transaction &transaction) { 126 auto indexer = [=](bool add, const QByteArray &identifier, const QVariant &value, const QVariant &sortValue, Sink::Storage::DataStore::Transaction &transaction) {
115 const auto date = sortValue.toDateTime(); 127 const auto date = sortValue.toDateTime();
116 const auto propertyValue = getByteArray(value); 128 const auto propertyValue = getByteArray(value);
117 Index(indexName(property, sortProperty), transaction).add(propertyValue + toSortableByteArray(date), identifier); 129 SinkWarning() << "Adding sorted value " << indexName(property, sortProperty);
130 if (add) {
131 Index(indexName(property, sortProperty), transaction).add(propertyValue + toSortableByteArray(date), identifier);
132 } else {
133 Index(indexName(property, sortProperty), transaction).remove(propertyValue + toSortableByteArray(date), identifier);
134 }
118 }; 135 };
119 mSortIndexer.insert(property + sortProperty, indexer); 136 mSortIndexer.insert(property + sortProperty, indexer);
120 mSortedProperties.insert(property, sortProperty); 137 mSortedProperties.insert(property, sortProperty);
@@ -126,45 +143,38 @@ void TypeIndex::addPropertyWithSorting<ApplicationDomain::Reference, QDateTime>(
126 addPropertyWithSorting<QByteArray, QDateTime>(property, sortProperty); 143 addPropertyWithSorting<QByteArray, QDateTime>(property, sortProperty);
127} 144}
128 145
129void TypeIndex::add(const QByteArray &identifier, const Sink::ApplicationDomain::ApplicationDomainType &entity, Sink::Storage::DataStore::Transaction &transaction) 146void TypeIndex::updateIndex(bool add, const QByteArray &identifier, const Sink::ApplicationDomain::ApplicationDomainType &entity, Sink::Storage::DataStore::Transaction &transaction)
130{ 147{
131 SinkTrace() << "add " << identifier;
132 for (const auto &property : mProperties) { 148 for (const auto &property : mProperties) {
133 const auto value = entity.getProperty(property); 149 const auto value = entity.getProperty(property);
134 auto indexer = mIndexer.value(property); 150 auto indexer = mIndexer.value(property);
135 indexer(identifier, value, transaction); 151 indexer(add, identifier, value, transaction);
136 } 152 }
137 for (auto it = mSortedProperties.constBegin(); it != mSortedProperties.constEnd(); it++) { 153 for (auto it = mSortedProperties.constBegin(); it != mSortedProperties.constEnd(); it++) {
138 const auto value = entity.getProperty(it.key()); 154 const auto value = entity.getProperty(it.key());
139 const auto sortValue = entity.getProperty(it.value()); 155 const auto sortValue = entity.getProperty(it.value());
140 auto indexer = mSortIndexer.value(it.key() + it.value()); 156 auto indexer = mSortIndexer.value(it.key() + it.value());
141 indexer(identifier, value, sortValue, transaction); 157 indexer(add, identifier, value, sortValue, transaction);
142 } 158 }
143 for (const auto &indexer : mCustomIndexer) { 159 for (const auto &indexer : mCustomIndexer) {
144 indexer->setup(this, &transaction); 160 indexer->setup(this, &transaction);
145 indexer->add(entity); 161 if (add) {
162 indexer->add(entity);
163 } else {
164 indexer->remove(entity);
165 }
146 } 166 }
167
168}
169
170void TypeIndex::add(const QByteArray &identifier, const Sink::ApplicationDomain::ApplicationDomainType &entity, Sink::Storage::DataStore::Transaction &transaction)
171{
172 updateIndex(true, identifier, entity, transaction);
147} 173}
148 174
149void TypeIndex::remove(const QByteArray &identifier, const Sink::ApplicationDomain::ApplicationDomainType &entity, Sink::Storage::DataStore::Transaction &transaction) 175void TypeIndex::remove(const QByteArray &identifier, const Sink::ApplicationDomain::ApplicationDomainType &entity, Sink::Storage::DataStore::Transaction &transaction)
150{ 176{
151 for (const auto &property : mProperties) { 177 updateIndex(false, identifier, entity, transaction);
152 const auto value = entity.getProperty(property);
153 Index(indexName(property), transaction).remove(getByteArray(value), identifier);
154 }
155 for (auto it = mSortedProperties.constBegin(); it != mSortedProperties.constEnd(); it++) {
156 const auto propertyValue = entity.getProperty(it.key());
157 const auto sortValue = entity.getProperty(it.value());
158 if (sortValue.type() == QVariant::DateTime) {
159 Index(indexName(it.key(), it.value()), transaction).remove(propertyValue.toByteArray() + toSortableByteArray(sortValue.toDateTime()), identifier);
160 } else {
161 Index(indexName(it.key(), it.value()), transaction).remove(propertyValue.toByteArray() + sortValue.toByteArray(), identifier);
162 }
163 }
164 for (const auto &indexer : mCustomIndexer) {
165 indexer->setup(this, &transaction);
166 indexer->remove(entity);
167 }
168} 178}
169 179
170static QVector<QByteArray> indexLookup(Index &index, QueryBase::Comparator filter) 180static QVector<QByteArray> indexLookup(Index &index, QueryBase::Comparator filter)
diff --git a/common/typeindex.h b/common/typeindex.h
index 7ff2029..1f216a7 100644
--- a/common/typeindex.h
+++ b/common/typeindex.h
@@ -98,6 +98,7 @@ public:
98 98
99private: 99private:
100 friend class Sink::Storage::EntityStore; 100 friend class Sink::Storage::EntityStore;
101 void updateIndex(bool add, const QByteArray &identifier, const Sink::ApplicationDomain::ApplicationDomainType &entity, Sink::Storage::DataStore::Transaction &transaction);
101 QByteArray indexName(const QByteArray &property, const QByteArray &sortProperty = QByteArray()) const; 102 QByteArray indexName(const QByteArray &property, const QByteArray &sortProperty = QByteArray()) const;
102 Sink::Log::Context mLogCtx; 103 Sink::Log::Context mLogCtx;
103 QByteArray mType; 104 QByteArray mType;
@@ -107,6 +108,6 @@ private:
107 QMap<QByteArray, QByteArray> mSecondaryProperties; 108 QMap<QByteArray, QByteArray> mSecondaryProperties;
108 QList<Sink::Indexer::Ptr> mCustomIndexer; 109 QList<Sink::Indexer::Ptr> mCustomIndexer;
109 Sink::Storage::DataStore::Transaction *mTransaction; 110 Sink::Storage::DataStore::Transaction *mTransaction;
110 QHash<QByteArray, std::function<void(const QByteArray &identifier, const QVariant &value, Sink::Storage::DataStore::Transaction &transaction)>> mIndexer; 111 QHash<QByteArray, std::function<void(bool, const QByteArray &identifier, const QVariant &value, Sink::Storage::DataStore::Transaction &transaction)>> mIndexer;
111 QHash<QByteArray, std::function<void(const QByteArray &identifier, const QVariant &value, const QVariant &sortValue, Sink::Storage::DataStore::Transaction &transaction)>> mSortIndexer; 112 QHash<QByteArray, std::function<void(bool, const QByteArray &identifier, const QVariant &value, const QVariant &sortValue, Sink::Storage::DataStore::Transaction &transaction)>> mSortIndexer;
112}; 113};