diff options
-rw-r--r-- | store/database.cpp | 74 | ||||
-rw-r--r-- | store/database.h | 18 |
2 files changed, 92 insertions, 0 deletions
diff --git a/store/database.cpp b/store/database.cpp index 7e2019e..2d93266 100644 --- a/store/database.cpp +++ b/store/database.cpp | |||
@@ -101,3 +101,77 @@ void Database::read(const std::string &sKey, const std::function<void(const std: | |||
101 | mdb_txn_abort(txn); | 101 | mdb_txn_abort(txn); |
102 | } | 102 | } |
103 | 103 | ||
104 | |||
105 | |||
106 | ReadTransaction::ReadTransaction(const QString &path) | ||
107 | { | ||
108 | int rc; | ||
109 | |||
110 | //create file | ||
111 | rc = mdb_env_create(&env); | ||
112 | //FIXME MDB_NOTLS required to so we can have multiple read-only transactions per resource? | ||
113 | rc = mdb_env_open(env, path.toStdString().data(), 0, 0664); | ||
114 | const int dbSize = 10485760*100; //10MB * 100 | ||
115 | mdb_env_set_mapsize(env, dbSize); | ||
116 | |||
117 | if (rc) { | ||
118 | std::cerr << "mdb_env_open: " << rc << mdb_strerror(rc) << std::endl; | ||
119 | } | ||
120 | } | ||
121 | |||
122 | ReadTransaction::~ReadTransaction() | ||
123 | { | ||
124 | mdb_txn_abort(txn); | ||
125 | |||
126 | mdb_dbi_close(env, dbi); | ||
127 | mdb_env_close(env); | ||
128 | } | ||
129 | |||
130 | void ReadTransaction::read(const std::string &sKey, const std::function<void(void *data, int size)> &resultHandler) | ||
131 | { | ||
132 | int rc; | ||
133 | MDB_val key; | ||
134 | MDB_val data; | ||
135 | MDB_cursor *cursor; | ||
136 | |||
137 | key.mv_size = sKey.size(); | ||
138 | key.mv_data = (void*)sKey.data(); | ||
139 | |||
140 | { | ||
141 | //A write transaction is at least required the first time | ||
142 | rc = mdb_txn_begin(env, nullptr, 0, &txn); | ||
143 | //Open the database | ||
144 | //With this we could open multiple named databases if we wanted to | ||
145 | rc = mdb_dbi_open(txn, nullptr, 0, &dbi); | ||
146 | mdb_txn_abort(txn); | ||
147 | } | ||
148 | |||
149 | rc = mdb_txn_begin(env, nullptr, MDB_RDONLY, &txn); | ||
150 | rc = mdb_cursor_open(txn, dbi, &cursor); | ||
151 | if (rc) { | ||
152 | std::cerr << "mdb_cursor_open: " << rc << mdb_strerror(rc) << std::endl; | ||
153 | } | ||
154 | if (sKey.empty()) { | ||
155 | std::cout << "Iterating over all values of store!" << std::endl; | ||
156 | rc = mdb_cursor_get(cursor, &key, &data, MDB_FIRST); | ||
157 | while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { | ||
158 | resultHandler(data.mv_data, data.mv_size); | ||
159 | } | ||
160 | //We never find the last value | ||
161 | if (rc == MDB_NOTFOUND) { | ||
162 | rc = 0; | ||
163 | } | ||
164 | } else { | ||
165 | if ((rc = mdb_cursor_get(cursor, &key, &data, MDB_SET)) == 0) { | ||
166 | resultHandler(data.mv_data, data.mv_size); | ||
167 | } else { | ||
168 | std::cout << "couldn't find value " << sKey << std::endl; | ||
169 | } | ||
170 | } | ||
171 | if (rc) { | ||
172 | std::cerr << "mdb_cursor_get: " << rc << mdb_strerror(rc) << std::endl; | ||
173 | } | ||
174 | mdb_cursor_close(cursor); | ||
175 | //We keep the transaction open since we want to keep the returned values alive | ||
176 | } | ||
177 | |||
diff --git a/store/database.h b/store/database.h index 999a89e..ab398a4 100644 --- a/store/database.h +++ b/store/database.h | |||
@@ -18,3 +18,21 @@ private: | |||
18 | MDB_env *env; | 18 | MDB_env *env; |
19 | MDB_dbi dbi; | 19 | MDB_dbi dbi; |
20 | }; | 20 | }; |
21 | |||
22 | /* | ||
23 | * This opens the db for a single read transaction. | ||
24 | * | ||
25 | * The lifetime of all read values is tied to this transaction. | ||
26 | */ | ||
27 | class ReadTransaction { | ||
28 | public: | ||
29 | ReadTransaction(const QString &path); | ||
30 | ~ReadTransaction(); | ||
31 | |||
32 | void read(const std::string &sKey, const std::function<void(void *ptr, int size)> &); | ||
33 | |||
34 | private: | ||
35 | MDB_env *env; | ||
36 | MDB_dbi dbi; | ||
37 | MDB_txn *txn; | ||
38 | }; | ||