diff options
author | Christian Mollekopf <chrigi_1@fastmail.fm> | 2014-12-03 20:36:37 +0100 |
---|---|---|
committer | Christian Mollekopf <chrigi_1@fastmail.fm> | 2014-12-03 20:36:37 +0100 |
commit | 44757d932abac6c8346366dfa3c0fb94e5ee0d06 (patch) | |
tree | c9120c3b4faf1b8e33dc04fee7347bc91c956977 | |
parent | 21138cfb7a4537626e11bdf084fcf9d672361059 (diff) | |
download | sink-44757d932abac6c8346366dfa3c0fb94e5ee0d06.tar.gz sink-44757d932abac6c8346366dfa3c0fb94e5ee0d06.zip |
dummyresource that doesn't work yet
-rw-r--r-- | CMakeLists.txt | 3 | ||||
-rw-r--r-- | dummyresource/CMakeLists.txt | 15 | ||||
-rw-r--r-- | dummyresource/dummycalendar.fbs | 12 | ||||
-rw-r--r-- | dummyresource/facade.cpp | 92 | ||||
-rw-r--r-- | dummyresource/facade.h | 22 | ||||
-rw-r--r-- | dummyresource/syncronizer.cpp | 0 | ||||
-rw-r--r-- | store/database.cpp | 27 | ||||
-rw-r--r-- | store/database.h | 5 |
8 files changed, 168 insertions, 8 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 0313b65..392ca39 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
@@ -50,4 +50,7 @@ add_subdirectory(resource) | |||
50 | # the store | 50 | # the store |
51 | add_subdirectory(store) | 51 | add_subdirectory(store) |
52 | 52 | ||
53 | # a simple dummy resource implementation | ||
54 | add_subdirectory(dummyresource) | ||
55 | |||
53 | feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) | 56 | feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) |
diff --git a/dummyresource/CMakeLists.txt b/dummyresource/CMakeLists.txt new file mode 100644 index 0000000..9d28c0b --- /dev/null +++ b/dummyresource/CMakeLists.txt | |||
@@ -0,0 +1,15 @@ | |||
1 | project(akonadinext_dummyresource) | ||
2 | |||
3 | include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) | ||
4 | |||
5 | generate_flatbuffers(dummycalendar) | ||
6 | |||
7 | #Client plugin | ||
8 | add_library(${PROJECT_NAME}_facade SHARED facade.cpp) | ||
9 | target_link_libraries(${PROJECT_NAME}_facade akonadinextcommon) | ||
10 | qt5_use_modules(${PROJECT_NAME}_facade Widgets Network) | ||
11 | #install(TARGETS ${PROJECT_NAME}_facade DESTINATION bin) | ||
12 | |||
13 | #Syncronizer | ||
14 | |||
15 | #add_subdirectory(test) | ||
diff --git a/dummyresource/dummycalendar.fbs b/dummyresource/dummycalendar.fbs new file mode 100644 index 0000000..551f5cb --- /dev/null +++ b/dummyresource/dummycalendar.fbs | |||
@@ -0,0 +1,12 @@ | |||
1 | // example IDL file | ||
2 | |||
3 | namespace DummyCalendar; | ||
4 | |||
5 | table DummyEvent { | ||
6 | summary:string; | ||
7 | description:string; | ||
8 | attachment:[byte]; | ||
9 | } | ||
10 | |||
11 | root_type DummyEvent; | ||
12 | file_identifier "AKFB"; | ||
diff --git a/dummyresource/facade.cpp b/dummyresource/facade.cpp new file mode 100644 index 0000000..288552c --- /dev/null +++ b/dummyresource/facade.cpp | |||
@@ -0,0 +1,92 @@ | |||
1 | #include "facade.h" | ||
2 | |||
3 | #include <QDebug> | ||
4 | #include <functional> | ||
5 | #include "client/resourceaccess.h" | ||
6 | #include "dummycalendar_generated.h" | ||
7 | |||
8 | using namespace DummyCalendar; | ||
9 | using namespace flatbuffers; | ||
10 | |||
11 | DummyResourceFacade::DummyResourceFacade() | ||
12 | : Akonadi2::StoreFacade<Akonadi2::Domain::Event>(), | ||
13 | mResourceAccess(new ResourceAccess("dummyresource")), | ||
14 | mDatabase(new Database("dummyresource")) | ||
15 | { | ||
16 | // connect(mResourceAccess.data(), &ResourceAccess::ready, this, onReadyChanged); | ||
17 | } | ||
18 | |||
19 | DummyResourceFacade::~DummyResourceFacade() | ||
20 | { | ||
21 | } | ||
22 | |||
23 | void DummyResourceFacade::create(const Akonadi2::Domain::Event &domainObject) | ||
24 | { | ||
25 | //Create message buffer and send to resource | ||
26 | } | ||
27 | |||
28 | void DummyResourceFacade::modify(const Akonadi2::Domain::Event &domainObject) | ||
29 | { | ||
30 | //Create message buffer and send to resource | ||
31 | } | ||
32 | |||
33 | void DummyResourceFacade::remove(const Akonadi2::Domain::Event &domainObject) | ||
34 | { | ||
35 | //Create message buffer and send to resource | ||
36 | } | ||
37 | |||
38 | //Key.value property map using enum or strings with qvariant, or rather typesafe API? | ||
39 | //typesafe is a shitload more work that we can avoid | ||
40 | // | ||
41 | //The Event base implementaiton could take a pointer to a single property mapper, | ||
42 | //and a void pointer to the mmapped region. => event is copyable and stack allocatable and we avoid large amounts of heap allocated objects | ||
43 | //-The mapper should in this case live in the other thread | ||
44 | //-default property mapper implementation can answer "is property X supported?" | ||
45 | //-how do we free/munmap the data if we don't know when no one references it any longer? => no munmap needed, but read transaction to keep pointer alive | ||
46 | //-we could bind the lifetime to the query | ||
47 | //=> perhaps do heap allocate and use smart pointer? | ||
48 | class DummyEventAdaptor : public Akonadi2::Domain::Event { | ||
49 | public: | ||
50 | DummyEventAdaptor(const QString &resource, const QString &identifier, qint64 revision):Akonadi2::Domain::Event(resource, identifier, revision){}; | ||
51 | |||
52 | // void setProperty(const QString &key, const QVariant &value) | ||
53 | // { | ||
54 | // //Record changes to send to resource? | ||
55 | // //The buffer is readonly | ||
56 | // } | ||
57 | |||
58 | virtual QVariant getProperty(const QString &key) const | ||
59 | { | ||
60 | if (key == "summary") { | ||
61 | //FIXME how do we check availability for on-demand request? | ||
62 | return QString::fromStdString(buffer->summary()->c_str()); | ||
63 | } | ||
64 | return QVariant(); | ||
65 | } | ||
66 | |||
67 | //Data is read-only | ||
68 | DummyEvent const *buffer; | ||
69 | }; | ||
70 | |||
71 | static Akonadi2::Domain::Event::Ptr createEvent(const std::string &data) | ||
72 | { | ||
73 | //We will have to buffers stored after each other | ||
74 | auto eventBuffer = GetDummyEvent(data.c_str()); | ||
75 | auto event = QSharedPointer<DummyEventAdaptor>::create("dummyresource", "key", 0); | ||
76 | event->buffer = eventBuffer; | ||
77 | // qDebug() << readEvent->summary()->c_str(); | ||
78 | return event; | ||
79 | } | ||
80 | |||
81 | void DummyResourceFacade::load(const Akonadi2::Query &query, const std::function<void(const Akonadi2::Domain::Event::Ptr &)> &resultCallback) | ||
82 | { | ||
83 | qDebug() << "load called"; | ||
84 | //TODO only read values matching the query | ||
85 | //FIXME the interface should probably simply return a void pointer + size | ||
86 | mDatabase->read("", [resultCallback](const std::string &result) { | ||
87 | resultCallback(createEvent(result)); | ||
88 | }); | ||
89 | } | ||
90 | |||
91 | //TODO call in plugin loader | ||
92 | // Akonadi2::FacadeFactory::instance().registerFacade<Akonadi2::Domain::Event, DummyResourceFacade>("dummyresource", [facade](){ return new DummyResourceFacade(facade); }); | ||
diff --git a/dummyresource/facade.h b/dummyresource/facade.h new file mode 100644 index 0000000..7a516de --- /dev/null +++ b/dummyresource/facade.h | |||
@@ -0,0 +1,22 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #include "client/clientapi.h" | ||
4 | #include "store/database.h" | ||
5 | |||
6 | class ResourceAccess; | ||
7 | |||
8 | class DummyResourceFacade : public Akonadi2::StoreFacade<Akonadi2::Domain::Event> | ||
9 | { | ||
10 | public: | ||
11 | DummyResourceFacade(); | ||
12 | virtual ~DummyResourceFacade(); | ||
13 | virtual void create(const Akonadi2::Domain::Event &domainObject); | ||
14 | virtual void modify(const Akonadi2::Domain::Event &domainObject); | ||
15 | virtual void remove(const Akonadi2::Domain::Event &domainObject); | ||
16 | // virtual void load(const Akonadi2::Query &query, const std::function<void(const Akonadi2::Domain::Event &)> &resultCallback); | ||
17 | virtual void load(const Akonadi2::Query &query, const std::function<void(const Akonadi2::Domain::Event::Ptr &)> &resultCallback); | ||
18 | |||
19 | private: | ||
20 | QSharedPointer<ResourceAccess> mResourceAccess; | ||
21 | QSharedPointer<Database> mDatabase; | ||
22 | }; | ||
diff --git a/dummyresource/syncronizer.cpp b/dummyresource/syncronizer.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/dummyresource/syncronizer.cpp | |||
diff --git a/store/database.cpp b/store/database.cpp index c16a077..7e2019e 100644 --- a/store/database.cpp +++ b/store/database.cpp | |||
@@ -63,7 +63,7 @@ void Database::write(const std::string &sKey, const std::string &sValue, MDB_txn | |||
63 | } | 63 | } |
64 | } | 64 | } |
65 | 65 | ||
66 | void Database::read(const std::string &sKey) | 66 | void Database::read(const std::string &sKey, const std::function<void(const std::string)> &resultHandler) |
67 | { | 67 | { |
68 | int rc; | 68 | int rc; |
69 | MDB_txn *txn; | 69 | MDB_txn *txn; |
@@ -76,13 +76,26 @@ void Database::read(const std::string &sKey) | |||
76 | 76 | ||
77 | rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn); | 77 | rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn); |
78 | rc = mdb_cursor_open(txn, dbi, &cursor); | 78 | rc = mdb_cursor_open(txn, dbi, &cursor); |
79 | // while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { | 79 | if (sKey.empty()) { |
80 | if ((rc = mdb_cursor_get(cursor, &key, &data, MDB_SET)) == 0) { | 80 | std::cout << "Iterating over all values of store!" << std::endl; |
81 | const std::string resultKey(static_cast<char*>(key.mv_data), key.mv_size); | 81 | while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { |
82 | const std::string resultValue(static_cast<char*>(data.mv_data), data.mv_size); | 82 | const std::string resultKey(static_cast<char*>(key.mv_data), key.mv_size); |
83 | // std::cout << "key: " << resultKey << " data: " << resultValue << std::endl; | 83 | const std::string resultValue(static_cast<char*>(data.mv_data), data.mv_size); |
84 | // std::cout << "key: " << resultKey << " data: " << resultValue << std::endl; | ||
85 | resultHandler(resultValue); | ||
86 | } | ||
84 | } else { | 87 | } else { |
85 | std::cout << "couldn't find value " << sKey << std::endl; | 88 | if ((rc = mdb_cursor_get(cursor, &key, &data, MDB_SET)) == 0) { |
89 | const std::string resultKey(static_cast<char*>(key.mv_data), key.mv_size); | ||
90 | const std::string resultValue(static_cast<char*>(data.mv_data), data.mv_size); | ||
91 | // std::cout << "key: " << resultKey << " data: " << resultValue << std::endl; | ||
92 | resultHandler(resultValue); | ||
93 | } else { | ||
94 | std::cout << "couldn't find value " << sKey << std::endl; | ||
95 | } | ||
96 | } | ||
97 | if (rc) { | ||
98 | std::cerr << "mdb_cursor_get: " << rc << mdb_strerror(rc) << std::endl; | ||
86 | } | 99 | } |
87 | mdb_cursor_close(cursor); | 100 | mdb_cursor_close(cursor); |
88 | mdb_txn_abort(txn); | 101 | mdb_txn_abort(txn); |
diff --git a/store/database.h b/store/database.h index 1a124be..999a89e 100644 --- a/store/database.h +++ b/store/database.h | |||
@@ -1,3 +1,5 @@ | |||
1 | #pragma once | ||
2 | |||
1 | #include <lmdb.h> | 3 | #include <lmdb.h> |
2 | #include <string> | 4 | #include <string> |
3 | #include <QString> | 5 | #include <QString> |
@@ -9,7 +11,8 @@ public: | |||
9 | MDB_txn *startTransaction(); | 11 | MDB_txn *startTransaction(); |
10 | void endTransaction(MDB_txn *transaction); | 12 | void endTransaction(MDB_txn *transaction); |
11 | void write(const std::string &sKey, const std::string &sValue, MDB_txn *transaction); | 13 | void write(const std::string &sKey, const std::string &sValue, MDB_txn *transaction); |
12 | void read(const std::string &sKey); | 14 | //Perhaps prefer iterators (assuming we need to be able to match multiple values |
15 | void read(const std::string &sKey, const std::function<void(const std::string)> &); | ||
13 | 16 | ||
14 | private: | 17 | private: |
15 | MDB_env *env; | 18 | MDB_env *env; |