diff options
author | Christian Mollekopf <chrigi_1@fastmail.fm> | 2015-07-24 17:26:25 +0200 |
---|---|---|
committer | Christian Mollekopf <chrigi_1@fastmail.fm> | 2015-07-27 23:22:10 +0200 |
commit | 7ae8c8719497ec7556f532bab061d3758976f792 (patch) | |
tree | 8ace2300cebcf6926c7053e3f23a5f68c304ad98 | |
parent | 4430eabdfeddf02c20424508a2a4207b6b4a764e (diff) | |
download | sink-7ae8c8719497ec7556f532bab061d3758976f792.tar.gz sink-7ae8c8719497ec7556f532bab061d3758976f792.zip |
Mode FacadeFactory to separate file, mutex protected it, and loaded
resource
The factory is potentially used from several queries simultaneously,
so it's now mutex protected.
Additionally we try to load the plugins directly in the factory.
-rw-r--r-- | common/CMakeLists.txt | 1 | ||||
-rw-r--r-- | common/clientapi.cpp | 6 | ||||
-rw-r--r-- | common/clientapi.h | 94 | ||||
-rw-r--r-- | common/facadefactory.cpp | 79 | ||||
-rw-r--r-- | common/facadefactory.h | 91 | ||||
-rw-r--r-- | common/facadeinterface.h | 51 |
6 files changed, 224 insertions, 98 deletions
diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 56ae59b..a69c62c 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt | |||
@@ -14,6 +14,7 @@ set(command_SRCS | |||
14 | log.cpp | 14 | log.cpp |
15 | entitybuffer.cpp | 15 | entitybuffer.cpp |
16 | clientapi.cpp | 16 | clientapi.cpp |
17 | facadefactory.cpp | ||
17 | commands.cpp | 18 | commands.cpp |
18 | facade.cpp | 19 | facade.cpp |
19 | pipeline.cpp | 20 | pipeline.cpp |
diff --git a/common/clientapi.cpp b/common/clientapi.cpp index c19ea4f..a98340c 100644 --- a/common/clientapi.cpp +++ b/common/clientapi.cpp | |||
@@ -28,13 +28,9 @@ namespace async | |||
28 | }; | 28 | }; |
29 | } // namespace async | 29 | } // namespace async |
30 | 30 | ||
31 | namespace Akonadi2 | ||
32 | { | ||
33 | 31 | ||
34 | void FacadeFactory::registerStaticFacades() | 32 | namespace Akonadi2 |
35 | { | 33 | { |
36 | registerFacade<Akonadi2::ApplicationDomain::AkonadiResource, ResourceFacade>("resourceconfig"); | ||
37 | } | ||
38 | 34 | ||
39 | void Store::shutdown(const QByteArray &identifier) | 35 | void Store::shutdown(const QByteArray &identifier) |
40 | { | 36 | { |
diff --git a/common/clientapi.h b/common/clientapi.h index 4644ae1..d860305 100644 --- a/common/clientapi.h +++ b/common/clientapi.h | |||
@@ -35,6 +35,7 @@ | |||
35 | #include "resultprovider.h" | 35 | #include "resultprovider.h" |
36 | #include "domain/applicationdomaintype.h" | 36 | #include "domain/applicationdomaintype.h" |
37 | #include "resourceconfig.h" | 37 | #include "resourceconfig.h" |
38 | #include "facadefactory.h" | ||
38 | #include "log.h" | 39 | #include "log.h" |
39 | 40 | ||
40 | namespace async { | 41 | namespace async { |
@@ -82,98 +83,6 @@ public: | |||
82 | }; | 83 | }; |
83 | 84 | ||
84 | 85 | ||
85 | /** | ||
86 | * Interface for the store facade. | ||
87 | * | ||
88 | * All methods are synchronous. | ||
89 | * Facades are stateful (they hold connections to resources and database). | ||
90 | * | ||
91 | * TODO: would it make sense to split the write, read and notification parts? (we could potentially save some connections) | ||
92 | */ | ||
93 | template<class DomainType> | ||
94 | class StoreFacade { | ||
95 | public: | ||
96 | virtual ~StoreFacade(){}; | ||
97 | QByteArray type() const { return ApplicationDomain::getTypeName<DomainType>(); } | ||
98 | virtual KAsync::Job<void> create(const DomainType &domainObject) = 0; | ||
99 | virtual KAsync::Job<void> modify(const DomainType &domainObject) = 0; | ||
100 | virtual KAsync::Job<void> remove(const DomainType &domainObject) = 0; | ||
101 | virtual KAsync::Job<void> load(const Query &query, const QSharedPointer<ResultProvider<typename DomainType::Ptr> > &resultProvider) = 0; | ||
102 | }; | ||
103 | |||
104 | |||
105 | /** | ||
106 | * Facade factory that returns a store facade implementation, by loading a plugin and providing the relevant implementation. | ||
107 | * | ||
108 | * If we were to provide default implementations for certain capabilities. Here would be the place to do so. | ||
109 | */ | ||
110 | |||
111 | class FacadeFactory { | ||
112 | public: | ||
113 | typedef std::function<std::shared_ptr<void>(const QByteArray &)> FactoryFunction; | ||
114 | |||
115 | void registerStaticFacades(); | ||
116 | |||
117 | //FIXME: proper singleton implementation | ||
118 | static FacadeFactory &instance() | ||
119 | { | ||
120 | static FacadeFactory factory; | ||
121 | return factory; | ||
122 | } | ||
123 | |||
124 | static QByteArray key(const QByteArray &resource, const QByteArray &type) | ||
125 | { | ||
126 | return resource + type; | ||
127 | } | ||
128 | |||
129 | template<class DomainType, class Facade> | ||
130 | void registerFacade(const QByteArray &resource) | ||
131 | { | ||
132 | const QByteArray typeName = ApplicationDomain::getTypeName<DomainType>(); | ||
133 | mFacadeRegistry.insert(key(resource, typeName), [](const QByteArray &instanceIdentifier){ return std::make_shared<Facade>(instanceIdentifier); }); | ||
134 | } | ||
135 | |||
136 | /* | ||
137 | * Allows the registrar to register a specific instance. | ||
138 | * | ||
139 | * Primarily for testing. | ||
140 | */ | ||
141 | template<class DomainType, class Facade> | ||
142 | void registerFacade(const QByteArray &resource, const FactoryFunction &customFactoryFunction) | ||
143 | { | ||
144 | const QByteArray typeName = ApplicationDomain::getTypeName<DomainType>(); | ||
145 | mFacadeRegistry.insert(key(resource, typeName), customFactoryFunction); | ||
146 | } | ||
147 | |||
148 | /* | ||
149 | * Can be used to clear the factory. | ||
150 | * | ||
151 | * Primarily for testing. | ||
152 | */ | ||
153 | void resetFactory() | ||
154 | { | ||
155 | mFacadeRegistry.clear(); | ||
156 | } | ||
157 | |||
158 | template<class DomainType> | ||
159 | std::shared_ptr<StoreFacade<DomainType> > getFacade(const QByteArray &resource, const QByteArray &instanceIdentifier) | ||
160 | { | ||
161 | const QByteArray typeName = ApplicationDomain::getTypeName<DomainType>(); | ||
162 | if (auto factoryFunction = mFacadeRegistry.value(key(resource, typeName))) { | ||
163 | return std::static_pointer_cast<StoreFacade<DomainType> >(factoryFunction(instanceIdentifier)); | ||
164 | } | ||
165 | qWarning() << "Failed to find facade for resource: " << resource << " and type: " << typeName; | ||
166 | return std::shared_ptr<StoreFacade<DomainType> >(); | ||
167 | } | ||
168 | |||
169 | private: | ||
170 | FacadeFactory() | ||
171 | { | ||
172 | registerStaticFacades(); | ||
173 | } | ||
174 | |||
175 | QHash<QByteArray, FactoryFunction> mFacadeRegistry; | ||
176 | }; | ||
177 | 86 | ||
178 | /** | 87 | /** |
179 | * Store interface used in the client API. | 88 | * Store interface used in the client API. |
@@ -231,7 +140,6 @@ public: | |||
231 | // Query all resources and aggregate results | 140 | // Query all resources and aggregate results |
232 | KAsync::iterate(getResources(query.resources)) | 141 | KAsync::iterate(getResources(query.resources)) |
233 | .template each<void, QByteArray>([query, resultSet](const QByteArray &resource, KAsync::Future<void> &future) { | 142 | .template each<void, QByteArray>([query, resultSet](const QByteArray &resource, KAsync::Future<void> &future) { |
234 | //TODO pass resource identifier to factory | ||
235 | auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceName(resource), resource); | 143 | auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceName(resource), resource); |
236 | if (facade) { | 144 | if (facade) { |
237 | facade->load(query, resultSet).template then<void>([&future](){future.setFinished();}).exec(); | 145 | facade->load(query, resultSet).template then<void>([&future](){future.setFinished();}).exec(); |
diff --git a/common/facadefactory.cpp b/common/facadefactory.cpp new file mode 100644 index 0000000..f833b06 --- /dev/null +++ b/common/facadefactory.cpp | |||
@@ -0,0 +1,79 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 Christian Mollekopf <chrigi_1@fastmail.fm> | ||
3 | * | ||
4 | * This library is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU Lesser General Public | ||
6 | * License as published by the Free Software Foundation; either | ||
7 | * version 2.1 of the License, or (at your option) version 3, or any | ||
8 | * later version accepted by the membership of KDE e.V. (or its | ||
9 | * successor approved by the membership of KDE e.V.), which shall | ||
10 | * act as a proxy defined in Section 6 of version 3 of the license. | ||
11 | * | ||
12 | * This library is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * Lesser General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU Lesser General Public | ||
18 | * License along with this library. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | ||
20 | #include "facadefactory.h" | ||
21 | |||
22 | #include "resourcefacade.h" | ||
23 | #include "resource.h" | ||
24 | |||
25 | using namespace Akonadi2; | ||
26 | |||
27 | QMutex FacadeFactory::sMutex; | ||
28 | |||
29 | FacadeFactory::FacadeFactory() | ||
30 | { | ||
31 | registerStaticFacades(); | ||
32 | } | ||
33 | |||
34 | FacadeFactory &FacadeFactory::instance() | ||
35 | { | ||
36 | QMutexLocker locker(&sMutex); | ||
37 | static FacadeFactory *instance = 0; | ||
38 | if (!instance) { | ||
39 | instance = new FacadeFactory; | ||
40 | } | ||
41 | return *instance; | ||
42 | } | ||
43 | |||
44 | QByteArray FacadeFactory::key(const QByteArray &resource, const QByteArray &type) | ||
45 | { | ||
46 | return resource + type; | ||
47 | } | ||
48 | |||
49 | void FacadeFactory::resetFactory() | ||
50 | { | ||
51 | QMutexLocker locker(&sMutex); | ||
52 | mFacadeRegistry.clear(); | ||
53 | } | ||
54 | |||
55 | void FacadeFactory::registerStaticFacades() | ||
56 | { | ||
57 | registerFacade<Akonadi2::ApplicationDomain::AkonadiResource, ResourceFacade>("resourceconfig"); | ||
58 | } | ||
59 | |||
60 | std::shared_ptr<void> FacadeFactory::getFacade(const QByteArray &resource, const QByteArray &instanceIdentifier, const QByteArray &typeName) | ||
61 | { | ||
62 | QMutexLocker locker(&sMutex); | ||
63 | |||
64 | const QByteArray k = key(resource, typeName); | ||
65 | if (!mFacadeRegistry.contains(k)) { | ||
66 | Akonadi2::ResourceFactory::load(QString::fromLatin1(resource)); | ||
67 | } | ||
68 | |||
69 | if (auto factoryFunction = mFacadeRegistry.value(k)) { | ||
70 | return factoryFunction(instanceIdentifier); | ||
71 | } | ||
72 | qWarning() << "Failed to find facade for resource: " << resource << " and type: " << typeName; | ||
73 | return std::shared_ptr<void>(); | ||
74 | } | ||
75 | |||
76 | void FacadeFactory::registerFacade(const QByteArray &resource, const FactoryFunction &customFactoryFunction, const QByteArray typeName) | ||
77 | { | ||
78 | mFacadeRegistry.insert(key(resource, typeName), customFactoryFunction); | ||
79 | } | ||
diff --git a/common/facadefactory.h b/common/facadefactory.h new file mode 100644 index 0000000..4a6a698 --- /dev/null +++ b/common/facadefactory.h | |||
@@ -0,0 +1,91 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 Christian Mollekopf <chrigi_1@fastmail.fm> | ||
3 | * | ||
4 | * This library is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU Lesser General Public | ||
6 | * License as published by the Free Software Foundation; either | ||
7 | * version 2.1 of the License, or (at your option) version 3, or any | ||
8 | * later version accepted by the membership of KDE e.V. (or its | ||
9 | * successor approved by the membership of KDE e.V.), which shall | ||
10 | * act as a proxy defined in Section 6 of version 3 of the license. | ||
11 | * | ||
12 | * This library is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * Lesser General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU Lesser General Public | ||
18 | * License along with this library. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | ||
20 | |||
21 | #pragma once | ||
22 | |||
23 | #include <QByteArray> | ||
24 | #include <QDebug> | ||
25 | #include <QMutex> | ||
26 | #include <functional> | ||
27 | #include <memory> | ||
28 | |||
29 | #include "facadeinterface.h" | ||
30 | #include "domain/applicationdomaintype.h" | ||
31 | #include "log.h" | ||
32 | |||
33 | namespace Akonadi2 { | ||
34 | |||
35 | /** | ||
36 | * Facade factory that returns a store facade implementation, by loading a plugin and providing the relevant implementation. | ||
37 | * | ||
38 | * If we were to provide default implementations for certain capabilities. Here would be the place to do so. | ||
39 | */ | ||
40 | class FacadeFactory { | ||
41 | public: | ||
42 | typedef std::function<std::shared_ptr<void>(const QByteArray &)> FactoryFunction; | ||
43 | |||
44 | void registerStaticFacades(); | ||
45 | |||
46 | static FacadeFactory &instance(); | ||
47 | |||
48 | static QByteArray key(const QByteArray &resource, const QByteArray &type); | ||
49 | |||
50 | template<class DomainType, class Facade> | ||
51 | void registerFacade(const QByteArray &resource) | ||
52 | { | ||
53 | registerFacade(resource, [](const QByteArray &instanceIdentifier){ return std::make_shared<Facade>(instanceIdentifier); }, ApplicationDomain::getTypeName<DomainType>()); | ||
54 | } | ||
55 | |||
56 | /* | ||
57 | * Allows the registrar to register a specific instance. | ||
58 | * | ||
59 | * Primarily for testing. | ||
60 | */ | ||
61 | template<class DomainType, class Facade> | ||
62 | void registerFacade(const QByteArray &resource, const FactoryFunction &customFactoryFunction) | ||
63 | { | ||
64 | registerFacade(resource, customFactoryFunction, ApplicationDomain::getTypeName<DomainType>()); | ||
65 | } | ||
66 | |||
67 | /* | ||
68 | * Can be used to clear the factory. | ||
69 | * | ||
70 | * Primarily for testing. | ||
71 | */ | ||
72 | void resetFactory(); | ||
73 | |||
74 | template<class DomainType> | ||
75 | std::shared_ptr<StoreFacade<DomainType> > getFacade(const QByteArray &resource, const QByteArray &instanceIdentifier) | ||
76 | { | ||
77 | const QByteArray typeName = ApplicationDomain::getTypeName<DomainType>(); | ||
78 | return std::static_pointer_cast<StoreFacade<DomainType> >(getFacade(resource, instanceIdentifier, typeName)); | ||
79 | } | ||
80 | |||
81 | private: | ||
82 | FacadeFactory(); | ||
83 | std::shared_ptr<void> getFacade(const QByteArray &resource, const QByteArray &instanceIdentifier, const QByteArray &typeName); | ||
84 | void registerFacade(const QByteArray &resource, const FactoryFunction &customFactoryFunction, const QByteArray typeName); | ||
85 | |||
86 | QHash<QByteArray, FactoryFunction> mFacadeRegistry; | ||
87 | static QMutex sMutex; | ||
88 | }; | ||
89 | |||
90 | } | ||
91 | |||
diff --git a/common/facadeinterface.h b/common/facadeinterface.h new file mode 100644 index 0000000..a88c104 --- /dev/null +++ b/common/facadeinterface.h | |||
@@ -0,0 +1,51 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 Christian Mollekopf <chrigi_1@fastmail.fm> | ||
3 | * | ||
4 | * This library is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU Lesser General Public | ||
6 | * License as published by the Free Software Foundation; either | ||
7 | * version 2.1 of the License, or (at your option) version 3, or any | ||
8 | * later version accepted by the membership of KDE e.V. (or its | ||
9 | * successor approved by the membership of KDE e.V.), which shall | ||
10 | * act as a proxy defined in Section 6 of version 3 of the license. | ||
11 | * | ||
12 | * This library is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * Lesser General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU Lesser General Public | ||
18 | * License along with this library. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | ||
20 | |||
21 | #pragma once | ||
22 | |||
23 | #include <Async/Async> | ||
24 | #include <QByteArray> | ||
25 | #include <QSharedPointer> | ||
26 | #include "domain/applicationdomaintype.h" | ||
27 | #include "resultprovider.h" | ||
28 | |||
29 | namespace Akonadi2 { | ||
30 | class Query; | ||
31 | |||
32 | /** | ||
33 | * Interface for the store facade. | ||
34 | * | ||
35 | * All methods are synchronous. | ||
36 | * Facades are stateful (they hold connections to resources and database). | ||
37 | * | ||
38 | * TODO: would it make sense to split the write, read and notification parts? (we could potentially save some connections) | ||
39 | */ | ||
40 | template<class DomainType> | ||
41 | class StoreFacade { | ||
42 | public: | ||
43 | virtual ~StoreFacade(){}; | ||
44 | QByteArray type() const { return ApplicationDomain::getTypeName<DomainType>(); } | ||
45 | virtual KAsync::Job<void> create(const DomainType &domainObject) = 0; | ||
46 | virtual KAsync::Job<void> modify(const DomainType &domainObject) = 0; | ||
47 | virtual KAsync::Job<void> remove(const DomainType &domainObject) = 0; | ||
48 | virtual KAsync::Job<void> load(const Query &query, const QSharedPointer<async::ResultProvider<typename DomainType::Ptr> > &resultProvider) = 0; | ||
49 | }; | ||
50 | |||
51 | } | ||