diff options
-rw-r--r-- | common/index.cpp | 14 | ||||
-rw-r--r-- | common/storage_lmdb.cpp | 6 | ||||
-rw-r--r-- | common/typeindex.cpp | 70 | ||||
-rw-r--r-- | common/typeindex.h | 5 |
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 | ||
19 | void Index::add(const QByteArray &key, const QByteArray &value) | 19 | void 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 | ||
24 | void Index::remove(const QByteArray &key, const QByteArray &value) | 26 | void 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 | ||
29 | void Index::lookup(const QByteArray &key, const std::function<void(const QByteArray &value)> &resultHandler, const std::function<void(const Error &error)> &errorHandler, bool matchSubStringKeys) | 33 | void 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 | |||
72 | template <> | 72 | template <> |
73 | void TypeIndex::addProperty<QByteArray>(const QByteArray &property) | 73 | void 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) | |||
83 | template <> | 87 | template <> |
84 | void TypeIndex::addProperty<QString>(const QByteArray &property) | 88 | void 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) | |||
94 | template <> | 102 | template <> |
95 | void TypeIndex::addProperty<QDateTime>(const QByteArray &property) | 103 | void 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 | |||
111 | template <> | 123 | template <> |
112 | void TypeIndex::addPropertyWithSorting<QByteArray, QDateTime>(const QByteArray &property, const QByteArray &sortProperty) | 124 | void 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 | ||
129 | void TypeIndex::add(const QByteArray &identifier, const Sink::ApplicationDomain::ApplicationDomainType &entity, Sink::Storage::DataStore::Transaction &transaction) | 146 | void 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 | |||
170 | void 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 | ||
149 | void TypeIndex::remove(const QByteArray &identifier, const Sink::ApplicationDomain::ApplicationDomainType &entity, Sink::Storage::DataStore::Transaction &transaction) | 175 | void 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 | ||
170 | static QVector<QByteArray> indexLookup(Index &index, QueryBase::Comparator filter) | 180 | static 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 | ||
99 | private: | 99 | private: |
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 | }; |