diff options
Diffstat (limited to 'common/store.cpp')
-rw-r--r-- | common/store.cpp | 145 |
1 files changed, 71 insertions, 74 deletions
diff --git a/common/store.cpp b/common/store.cpp index 6847d22..68f73c8 100644 --- a/common/store.cpp +++ b/common/store.cpp | |||
@@ -38,8 +38,7 @@ | |||
38 | #undef DEBUG_AREA | 38 | #undef DEBUG_AREA |
39 | #define DEBUG_AREA "client.store" | 39 | #define DEBUG_AREA "client.store" |
40 | 40 | ||
41 | namespace Sink | 41 | namespace Sink { |
42 | { | ||
43 | 42 | ||
44 | QString Store::storageLocation() | 43 | QString Store::storageLocation() |
45 | { | 44 | { |
@@ -48,7 +47,7 @@ QString Store::storageLocation() | |||
48 | 47 | ||
49 | static QList<QByteArray> getResources(const QList<QByteArray> &resourceFilter, const QByteArray &type) | 48 | static QList<QByteArray> getResources(const QList<QByteArray> &resourceFilter, const QByteArray &type) |
50 | { | 49 | { |
51 | //Return the global resource (signified by an empty name) for types that don't eblong to a specific resource | 50 | // Return the global resource (signified by an empty name) for types that don't eblong to a specific resource |
52 | if (type == "sinkresource") { | 51 | if (type == "sinkresource") { |
53 | return QList<QByteArray>() << ""; | 52 | return QList<QByteArray>() << ""; |
54 | } | 53 | } |
@@ -56,7 +55,7 @@ static QList<QByteArray> getResources(const QList<QByteArray> &resourceFilter, c | |||
56 | const auto configuredResources = ResourceConfig::getResources(); | 55 | const auto configuredResources = ResourceConfig::getResources(); |
57 | if (resourceFilter.isEmpty()) { | 56 | if (resourceFilter.isEmpty()) { |
58 | for (const auto &res : configuredResources.keys()) { | 57 | for (const auto &res : configuredResources.keys()) { |
59 | //TODO filter by entity type | 58 | // TODO filter by entity type |
60 | resources << res; | 59 | resources << res; |
61 | } | 60 | } |
62 | } else { | 61 | } else { |
@@ -82,7 +81,7 @@ QSharedPointer<QAbstractItemModel> Store::loadModel(Query query) | |||
82 | Trace() << " Ids: " << query.ids; | 81 | Trace() << " Ids: " << query.ids; |
83 | Trace() << " IsLive: " << query.liveQuery; | 82 | Trace() << " IsLive: " << query.liveQuery; |
84 | Trace() << " Sorting: " << query.sortProperty; | 83 | Trace() << " Sorting: " << query.sortProperty; |
85 | auto model = QSharedPointer<ModelResult<DomainType, typename DomainType::Ptr> >::create(query, query.requestedProperties); | 84 | auto model = QSharedPointer<ModelResult<DomainType, typename DomainType::Ptr>>::create(query, query.requestedProperties); |
86 | 85 | ||
87 | //* Client defines lifetime of model | 86 | //* Client defines lifetime of model |
88 | //* The model lifetime defines the duration of live-queries | 87 | //* The model lifetime defines the duration of live-queries |
@@ -95,120 +94,117 @@ QSharedPointer<QAbstractItemModel> Store::loadModel(Query query) | |||
95 | auto aggregatingEmitter = AggregatingResultEmitter<typename DomainType::Ptr>::Ptr::create(); | 94 | auto aggregatingEmitter = AggregatingResultEmitter<typename DomainType::Ptr>::Ptr::create(); |
96 | model->setEmitter(aggregatingEmitter); | 95 | model->setEmitter(aggregatingEmitter); |
97 | KAsync::iterate(resources) | 96 | KAsync::iterate(resources) |
98 | .template each<void, QByteArray>([query, aggregatingEmitter](const QByteArray &resource, KAsync::Future<void> &future) { | 97 | .template each<void, QByteArray>([query, aggregatingEmitter](const QByteArray &resource, KAsync::Future<void> &future) { |
99 | auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceName(resource), resource); | 98 | auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceName(resource), resource); |
100 | if (facade) { | 99 | if (facade) { |
101 | Trace() << "Trying to fetch from resource " << resource; | 100 | Trace() << "Trying to fetch from resource " << resource; |
102 | auto result = facade->load(query); | 101 | auto result = facade->load(query); |
103 | aggregatingEmitter->addEmitter(result.second); | 102 | aggregatingEmitter->addEmitter(result.second); |
104 | result.first.template then<void>([&future](){future.setFinished();}).exec(); | 103 | result.first.template then<void>([&future]() { future.setFinished(); }).exec(); |
105 | } else { | 104 | } else { |
106 | Trace() << "Couldn' find a facade for " << resource; | 105 | Trace() << "Couldn' find a facade for " << resource; |
107 | //Ignore the error and carry on | 106 | // Ignore the error and carry on |
108 | future.setFinished(); | 107 | future.setFinished(); |
109 | } | 108 | } |
110 | }).exec(); | 109 | }) |
110 | .exec(); | ||
111 | model->fetchMore(QModelIndex()); | 111 | model->fetchMore(QModelIndex()); |
112 | 112 | ||
113 | return model; | 113 | return model; |
114 | } | 114 | } |
115 | 115 | ||
116 | template <class DomainType> | 116 | template <class DomainType> |
117 | static std::shared_ptr<StoreFacade<DomainType> > getFacade(const QByteArray &resourceInstanceIdentifier) | 117 | static std::shared_ptr<StoreFacade<DomainType>> getFacade(const QByteArray &resourceInstanceIdentifier) |
118 | { | 118 | { |
119 | if (auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceName(resourceInstanceIdentifier), resourceInstanceIdentifier)) { | 119 | if (auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceName(resourceInstanceIdentifier), resourceInstanceIdentifier)) { |
120 | return facade; | 120 | return facade; |
121 | } | 121 | } |
122 | return std::make_shared<NullFacade<DomainType> >(); | 122 | return std::make_shared<NullFacade<DomainType>>(); |
123 | } | 123 | } |
124 | 124 | ||
125 | template <class DomainType> | 125 | template <class DomainType> |
126 | KAsync::Job<void> Store::create(const DomainType &domainObject) { | 126 | KAsync::Job<void> Store::create(const DomainType &domainObject) |
127 | //Potentially move to separate thread as well | 127 | { |
128 | // Potentially move to separate thread as well | ||
128 | auto facade = getFacade<DomainType>(domainObject.resourceInstanceIdentifier()); | 129 | auto facade = getFacade<DomainType>(domainObject.resourceInstanceIdentifier()); |
129 | return facade->create(domainObject).template then<void>([facade](){}, [](int errorCode, const QString &error) { | 130 | return facade->create(domainObject).template then<void>([facade]() {}, [](int errorCode, const QString &error) { Warning() << "Failed to create"; }); |
130 | Warning() << "Failed to create"; | ||
131 | }); | ||
132 | } | 131 | } |
133 | 132 | ||
134 | template <class DomainType> | 133 | template <class DomainType> |
135 | KAsync::Job<void> Store::modify(const DomainType &domainObject) | 134 | KAsync::Job<void> Store::modify(const DomainType &domainObject) |
136 | { | 135 | { |
137 | //Potentially move to separate thread as well | 136 | // Potentially move to separate thread as well |
138 | auto facade = getFacade<DomainType>(domainObject.resourceInstanceIdentifier()); | 137 | auto facade = getFacade<DomainType>(domainObject.resourceInstanceIdentifier()); |
139 | return facade->modify(domainObject).template then<void>([facade](){}, [](int errorCode, const QString &error) { | 138 | return facade->modify(domainObject).template then<void>([facade]() {}, [](int errorCode, const QString &error) { Warning() << "Failed to modify"; }); |
140 | Warning() << "Failed to modify"; | ||
141 | }); | ||
142 | } | 139 | } |
143 | 140 | ||
144 | template <class DomainType> | 141 | template <class DomainType> |
145 | KAsync::Job<void> Store::remove(const DomainType &domainObject) | 142 | KAsync::Job<void> Store::remove(const DomainType &domainObject) |
146 | { | 143 | { |
147 | //Potentially move to separate thread as well | 144 | // Potentially move to separate thread as well |
148 | auto facade = getFacade<DomainType>(domainObject.resourceInstanceIdentifier()); | 145 | auto facade = getFacade<DomainType>(domainObject.resourceInstanceIdentifier()); |
149 | return facade->remove(domainObject).template then<void>([facade](){}, [](int errorCode, const QString &error) { | 146 | return facade->remove(domainObject).template then<void>([facade]() {}, [](int errorCode, const QString &error) { Warning() << "Failed to remove"; }); |
150 | Warning() << "Failed to remove"; | ||
151 | }); | ||
152 | } | 147 | } |
153 | 148 | ||
154 | KAsync::Job<void> Store::removeDataFromDisk(const QByteArray &identifier) | 149 | KAsync::Job<void> Store::removeDataFromDisk(const QByteArray &identifier) |
155 | { | 150 | { |
156 | //All databases are going to become invalid, nuke the environments | 151 | // All databases are going to become invalid, nuke the environments |
157 | //TODO: all clients should react to a notification the resource | 152 | // TODO: all clients should react to a notification the resource |
158 | Sink::Storage::clearEnv(); | 153 | Sink::Storage::clearEnv(); |
159 | Trace() << "Remove data from disk " << identifier; | 154 | Trace() << "Remove data from disk " << identifier; |
160 | auto time = QSharedPointer<QTime>::create(); | 155 | auto time = QSharedPointer<QTime>::create(); |
161 | time->start(); | 156 | time->start(); |
162 | auto resourceAccess = ResourceAccessFactory::instance().getAccess(identifier); | 157 | auto resourceAccess = ResourceAccessFactory::instance().getAccess(identifier); |
163 | resourceAccess->open(); | 158 | resourceAccess->open(); |
164 | return resourceAccess->sendCommand(Sink::Commands::RemoveFromDiskCommand).then<void>([resourceAccess, time]() { | 159 | return resourceAccess->sendCommand(Sink::Commands::RemoveFromDiskCommand) |
165 | Trace() << "Remove from disk complete." << Log::TraceTime(time->elapsed()); | 160 | .then<void>([resourceAccess, time]() { Trace() << "Remove from disk complete." << Log::TraceTime(time->elapsed()); }); |
166 | }); | ||
167 | } | 161 | } |
168 | 162 | ||
169 | KAsync::Job<void> Store::synchronize(const Sink::Query &query) | 163 | KAsync::Job<void> Store::synchronize(const Sink::Query &query) |
170 | { | 164 | { |
171 | Trace() << "synchronize" << query.resources; | 165 | Trace() << "synchronize" << query.resources; |
172 | return KAsync::iterate(query.resources) | 166 | return KAsync::iterate(query.resources) |
173 | .template each<void, QByteArray>([query](const QByteArray &resource, KAsync::Future<void> &future) { | 167 | .template each<void, QByteArray>([query](const QByteArray &resource, KAsync::Future<void> &future) { |
174 | Trace() << "Synchronizing " << resource; | 168 | Trace() << "Synchronizing " << resource; |
175 | auto resourceAccess = ResourceAccessFactory::instance().getAccess(resource); | 169 | auto resourceAccess = ResourceAccessFactory::instance().getAccess(resource); |
176 | resourceAccess->open(); | 170 | resourceAccess->open(); |
177 | resourceAccess->synchronizeResource(true, false).then<void>([&future, resourceAccess]() { | 171 | resourceAccess->synchronizeResource(true, false).then<void>([&future, resourceAccess]() { future.setFinished(); }).exec(); |
178 | future.setFinished(); | 172 | }); |
179 | }).exec(); | ||
180 | }); | ||
181 | } | 173 | } |
182 | 174 | ||
183 | template <class DomainType> | 175 | template <class DomainType> |
184 | KAsync::Job<DomainType> Store::fetchOne(const Sink::Query &query) | 176 | KAsync::Job<DomainType> Store::fetchOne(const Sink::Query &query) |
185 | { | 177 | { |
186 | return KAsync::start<DomainType>([query](KAsync::Future<DomainType> &future) { | 178 | return KAsync::start<DomainType>([query](KAsync::Future<DomainType> &future) { |
187 | //FIXME We could do this more elegantly if composed jobs would have the correct type (In that case we'd simply return the value from then continuation, and could avoid the outer job entirely) | 179 | // FIXME We could do this more elegantly if composed jobs would have the correct type (In that case we'd simply return the value from then continuation, and could avoid the |
180 | // outer job entirely) | ||
188 | fetch<DomainType>(query, 1) | 181 | fetch<DomainType>(query, 1) |
189 | .template then<void, QList<typename DomainType::Ptr> >([&future](const QList<typename DomainType::Ptr> &list){ | 182 | .template then<void, QList<typename DomainType::Ptr>>( |
190 | future.setValue(*list.first()); | 183 | [&future](const QList<typename DomainType::Ptr> &list) { |
191 | future.setFinished(); | 184 | future.setValue(*list.first()); |
192 | }, [&future](int errorCode, const QString &errorMessage) { | 185 | future.setFinished(); |
193 | future.setError(errorCode, errorMessage); | 186 | }, |
194 | future.setFinished(); | 187 | [&future](int errorCode, const QString &errorMessage) { |
195 | }).exec(); | 188 | future.setError(errorCode, errorMessage); |
189 | future.setFinished(); | ||
190 | }) | ||
191 | .exec(); | ||
196 | }); | 192 | }); |
197 | } | 193 | } |
198 | 194 | ||
199 | template <class DomainType> | 195 | template <class DomainType> |
200 | KAsync::Job<QList<typename DomainType::Ptr> > Store::fetchAll(const Sink::Query &query) | 196 | KAsync::Job<QList<typename DomainType::Ptr>> Store::fetchAll(const Sink::Query &query) |
201 | { | 197 | { |
202 | return fetch<DomainType>(query); | 198 | return fetch<DomainType>(query); |
203 | } | 199 | } |
204 | 200 | ||
205 | template <class DomainType> | 201 | template <class DomainType> |
206 | KAsync::Job<QList<typename DomainType::Ptr> > Store::fetch(const Sink::Query &query, int minimumAmount) | 202 | KAsync::Job<QList<typename DomainType::Ptr>> Store::fetch(const Sink::Query &query, int minimumAmount) |
207 | { | 203 | { |
208 | auto model = loadModel<DomainType>(query); | 204 | auto model = loadModel<DomainType>(query); |
209 | auto list = QSharedPointer<QList<typename DomainType::Ptr> >::create(); | 205 | auto list = QSharedPointer<QList<typename DomainType::Ptr>>::create(); |
210 | auto context = QSharedPointer<QObject>::create(); | 206 | auto context = QSharedPointer<QObject>::create(); |
211 | return KAsync::start<QList<typename DomainType::Ptr> >([model, list, context, minimumAmount](KAsync::Future<QList<typename DomainType::Ptr> > &future) { | 207 | return KAsync::start<QList<typename DomainType::Ptr>>([model, list, context, minimumAmount](KAsync::Future<QList<typename DomainType::Ptr>> &future) { |
212 | if (model->rowCount() >= 1) { | 208 | if (model->rowCount() >= 1) { |
213 | for (int i = 0; i < model->rowCount(); i++) { | 209 | for (int i = 0; i < model->rowCount(); i++) { |
214 | list->append(model->index(i, 0, QModelIndex()).data(Sink::Store::DomainObjectRole).template value<typename DomainType::Ptr>()); | 210 | list->append(model->index(i, 0, QModelIndex()).data(Sink::Store::DomainObjectRole).template value<typename DomainType::Ptr>()); |
@@ -219,16 +215,17 @@ KAsync::Job<QList<typename DomainType::Ptr> > Store::fetch(const Sink::Query &qu | |||
219 | list->append(model->index(i, 0, QModelIndex()).data(Sink::Store::DomainObjectRole).template value<typename DomainType::Ptr>()); | 215 | list->append(model->index(i, 0, QModelIndex()).data(Sink::Store::DomainObjectRole).template value<typename DomainType::Ptr>()); |
220 | } | 216 | } |
221 | }); | 217 | }); |
222 | QObject::connect(model.data(), &QAbstractItemModel::dataChanged, context.data(), [model, &future, list, minimumAmount](const QModelIndex &, const QModelIndex &, const QVector<int> &roles) { | 218 | QObject::connect(model.data(), &QAbstractItemModel::dataChanged, context.data(), |
223 | if (roles.contains(ModelResult<DomainType, typename DomainType::Ptr>::ChildrenFetchedRole)) { | 219 | [model, &future, list, minimumAmount](const QModelIndex &, const QModelIndex &, const QVector<int> &roles) { |
224 | if (list->size() < minimumAmount) { | 220 | if (roles.contains(ModelResult<DomainType, typename DomainType::Ptr>::ChildrenFetchedRole)) { |
225 | future.setError(1, "Not enough values."); | 221 | if (list->size() < minimumAmount) { |
226 | } else { | 222 | future.setError(1, "Not enough values."); |
227 | future.setValue(*list); | 223 | } else { |
224 | future.setValue(*list); | ||
225 | } | ||
226 | future.setFinished(); | ||
228 | } | 227 | } |
229 | future.setFinished(); | 228 | }); |
230 | } | ||
231 | }); | ||
232 | } | 229 | } |
233 | if (model->data(QModelIndex(), ModelResult<DomainType, typename DomainType::Ptr>::ChildrenFetchedRole).toBool()) { | 230 | if (model->data(QModelIndex(), ModelResult<DomainType, typename DomainType::Ptr>::ChildrenFetchedRole).toBool()) { |
234 | if (list->size() < minimumAmount) { | 231 | if (list->size() < minimumAmount) { |
@@ -241,13 +238,14 @@ KAsync::Job<QList<typename DomainType::Ptr> > Store::fetch(const Sink::Query &qu | |||
241 | }); | 238 | }); |
242 | } | 239 | } |
243 | 240 | ||
244 | #define REGISTER_TYPE(T) template KAsync::Job<void> Store::remove<T>(const T &domainObject); \ | 241 | #define REGISTER_TYPE(T) \ |
245 | template KAsync::Job<void> Store::create<T>(const T &domainObject); \ | 242 | template KAsync::Job<void> Store::remove<T>(const T &domainObject); \ |
246 | template KAsync::Job<void> Store::modify<T>(const T &domainObject); \ | 243 | template KAsync::Job<void> Store::create<T>(const T &domainObject); \ |
244 | template KAsync::Job<void> Store::modify<T>(const T &domainObject); \ | ||
247 | template QSharedPointer<QAbstractItemModel> Store::loadModel<T>(Query query); \ | 245 | template QSharedPointer<QAbstractItemModel> Store::loadModel<T>(Query query); \ |
248 | template KAsync::Job<T> Store::fetchOne<T>(const Query &); \ | 246 | template KAsync::Job<T> Store::fetchOne<T>(const Query &); \ |
249 | template KAsync::Job<QList<T::Ptr> > Store::fetchAll<T>(const Query &); \ | 247 | template KAsync::Job<QList<T::Ptr>> Store::fetchAll<T>(const Query &); \ |
250 | template KAsync::Job<QList<T::Ptr> > Store::fetch<T>(const Query &, int); \ | 248 | template KAsync::Job<QList<T::Ptr>> Store::fetch<T>(const Query &, int); |
251 | 249 | ||
252 | REGISTER_TYPE(ApplicationDomain::Event); | 250 | REGISTER_TYPE(ApplicationDomain::Event); |
253 | REGISTER_TYPE(ApplicationDomain::Mail); | 251 | REGISTER_TYPE(ApplicationDomain::Mail); |
@@ -255,4 +253,3 @@ REGISTER_TYPE(ApplicationDomain::Folder); | |||
255 | REGISTER_TYPE(ApplicationDomain::SinkResource); | 253 | REGISTER_TYPE(ApplicationDomain::SinkResource); |
256 | 254 | ||
257 | } // namespace Sink | 255 | } // namespace Sink |
258 | |||