summaryrefslogtreecommitdiffstats
path: root/store
diff options
context:
space:
mode:
Diffstat (limited to 'store')
-rw-r--r--store/CMakeLists.txt1
-rw-r--r--store/database.cpp164
-rw-r--r--store/database.h28
-rw-r--r--store/test/CMakeLists.txt21
-rw-r--r--store/test/calendar.fbs12
-rw-r--r--store/test/storagebenchmark.cpp157
6 files changed, 0 insertions, 383 deletions
diff --git a/store/CMakeLists.txt b/store/CMakeLists.txt
deleted file mode 100644
index 552439e..0000000
--- a/store/CMakeLists.txt
+++ /dev/null
@@ -1 +0,0 @@
1add_subdirectory(test)
diff --git a/store/database.cpp b/store/database.cpp
deleted file mode 100644
index 542667a..0000000
--- a/store/database.cpp
+++ /dev/null
@@ -1,164 +0,0 @@
1#include "database.h"
2
3#include <iostream>
4
5#include <QAtomicInt>
6#include <QDebug>
7#include <QDir>
8#include <QFileInfo>
9#include <QReadWriteLock>
10#include <QString>
11#include <QTime>
12
13#include <kchashdb.h>
14
15class Database::Private
16{
17public:
18 Private(const QString &storageRoot, const QString &name);
19 ~Private();
20
21 kyotocabinet::TreeDB db;
22 bool dbOpen;
23 bool inTransaction;
24};
25
26Database::Private::Private(const QString &storageRoot, const QString &name)
27 : inTransaction(false)
28{
29 QDir dir;
30 dir.mkdir(storageRoot);
31
32 //create file
33 dbOpen = db.open((storageRoot + "/" + name + ".kch").toStdString(), kyotocabinet::BasicDB::OWRITER | kyotocabinet::BasicDB::OCREATE);
34 if (!dbOpen) {
35 // TODO: handle error
36 }
37}
38
39Database::Private::~Private()
40{
41 if (dbOpen && inTransaction) {
42 db.end_transaction(false);
43 }
44}
45
46Database::Database(const QString &storageRoot, const QString &name)
47 : d(new Private(storageRoot, name))
48{
49}
50
51Database::~Database()
52{
53 delete d;
54}
55
56bool Database::isInTransaction() const
57{
58 return d->inTransaction;
59}
60
61bool Database::startTransaction(TransactionType type)
62{
63 if (!d->dbOpen) {
64 return false;
65 }
66
67 if (d->inTransaction) {
68 return true;
69 }
70
71 //TODO handle errors
72 d->inTransaction = d->db.begin_transaction();
73 return d->inTransaction;
74}
75
76bool Database::commitTransaction()
77{
78 if (!d->dbOpen) {
79 return false;
80 }
81
82 if (!d->inTransaction) {
83 return false;
84 }
85
86 bool success = d->db.end_transaction(true);
87 d->inTransaction = false;
88 return success;
89}
90
91void Database::abortTransaction()
92{
93 if (!d->dbOpen || !d->inTransaction) {
94 return;
95 }
96
97 d->db.end_transaction(false);
98 d->inTransaction = false;
99}
100
101bool Database::write(const char *key, size_t keySize, const char *value, size_t valueSize)
102{
103 if (!d->dbOpen) {
104 return false;
105 }
106
107 bool success = d->db.set(key, keySize, value, valueSize);
108 return success;
109}
110
111bool Database::write(const std::string &sKey, const std::string &sValue)
112{
113 if (!d->dbOpen) {
114 return false;
115 }
116
117 bool success = d->db.set(sKey, sValue);
118 return success;
119}
120
121void Database::read(const std::string &sKey, const std::function<void(const std::string &value)> &resultHandler)
122{
123 if (!d->dbOpen) {
124 return;
125 }
126
127 std::string value;
128 if (d->db.get(sKey, &value)) {
129 resultHandler(value);
130 }
131}
132
133void Database::read(const std::string &sKey, const std::function<void(void *ptr, int size)> &resultHandler)
134{
135 if (!d->dbOpen) {
136 return;
137 }
138
139 size_t valueSize;
140 char *valueBuffer = d->db.get(sKey.data(), sKey.size(), &valueSize);
141 resultHandler(valueBuffer, valueSize);
142 delete[] valueBuffer;
143}
144
145qint64 Database::diskUsage() const
146{
147 if (!d->dbOpen) {
148 return 0;
149 }
150
151 QFileInfo info(QString::fromStdString(d->db.path()));
152 return info.size();
153}
154
155void Database::removeFromDisk() const
156{
157 if (!d->dbOpen) {
158 return;
159 }
160
161 QFileInfo info(QString::fromStdString(d->db.path()));
162 QDir dir = info.dir();
163 dir.remove(info.fileName());
164}
diff --git a/store/database.h b/store/database.h
deleted file mode 100644
index e752ff5..0000000
--- a/store/database.h
+++ /dev/null
@@ -1,28 +0,0 @@
1#pragma once
2
3#include <string>
4#include <QString>
5
6class Database {
7public:
8 enum TransactionType { ReadOnly, ReadWrite };
9
10 Database(const QString &storageRoot, const QString &name);
11 ~Database();
12 bool isInTransaction() const;
13 bool startTransaction(TransactionType type = ReadWrite);
14 bool commitTransaction();
15 void abortTransaction();
16 bool write(const char *key, size_t keySize, const char *value, size_t valueSize);
17 bool write(const std::string &sKey, const std::string &sValue);
18 //Perhaps prefer iterators (assuming we need to be able to match multiple values
19 void read(const std::string &sKey, const std::function<void(const std::string &value)> &);
20 void read(const std::string &sKey, const std::function<void(void *ptr, int size)> &);
21
22 qint64 diskUsage() const;
23 void removeFromDisk() const;
24private:
25 class Private;
26 Private * const d;
27};
28
diff --git a/store/test/CMakeLists.txt b/store/test/CMakeLists.txt
deleted file mode 100644
index 1b9dc9e..0000000
--- a/store/test/CMakeLists.txt
+++ /dev/null
@@ -1,21 +0,0 @@
1set(CMAKE_AUTOMOC ON)
2include_directories(${CMAKE_CURRENT_BINARY_DIR})
3
4set(store_path "../")
5set(store_SRCS
6 ${store_path}/database.cpp
7)
8
9generate_flatbuffers(calendar)
10
11macro(manual_tests)
12 foreach(_testname ${ARGN})
13 add_executable(${_testname} ${_testname}.cpp ${store_SRCS})
14 qt5_use_modules(${_testname} Core Test)
15 target_link_libraries(${_testname} kyotocabinet)
16 endforeach(_testname)
17endmacro(auto_tests)
18
19manual_tests (
20 storagebenchmark
21)
diff --git a/store/test/calendar.fbs b/store/test/calendar.fbs
deleted file mode 100644
index 203ee43..0000000
--- a/store/test/calendar.fbs
+++ /dev/null
@@ -1,12 +0,0 @@
1// example IDL file
2
3namespace Calendar;
4
5table Event {
6 summary:string;
7 description:string;
8 attachment:[byte];
9}
10
11root_type Event;
12file_identifier "AKFB";
diff --git a/store/test/storagebenchmark.cpp b/store/test/storagebenchmark.cpp
deleted file mode 100644
index d42dea8..0000000
--- a/store/test/storagebenchmark.cpp
+++ /dev/null
@@ -1,157 +0,0 @@
1#include <QtTest>
2
3#include "calendar_generated.h"
4
5#include <iostream>
6#include <fstream>
7
8#include <QDebug>
9#include <QDir>
10#include <QString>
11#include <QTime>
12
13#include "store/database.h"
14
15using namespace Calendar;
16using namespace flatbuffers;
17
18static std::string createEvent()
19{
20 FlatBufferBuilder fbb;
21 {
22 auto summary = fbb.CreateString("summary");
23
24 const int attachmentSize = 1024*2; // 2KB
25 int8_t rawData[attachmentSize];
26 auto data = fbb.CreateVector(rawData, attachmentSize);
27
28 Calendar::EventBuilder eventBuilder(fbb);
29 eventBuilder.add_summary(summary);
30 eventBuilder.add_attachment(data);
31 auto eventLocation = eventBuilder.Finish();
32 FinishEventBuffer(fbb, eventLocation);
33 }
34 return std::string(reinterpret_cast<const char *>(fbb.GetBufferPointer()), fbb.GetSize());
35}
36
37// static void readEvent(const std::string &data)
38// {
39// auto readEvent = GetEvent(data.c_str());
40// std::cout << readEvent->summary()->c_str() << std::endl;
41// }
42
43class StorageBenchmark : public QObject
44{
45 Q_OBJECT
46private:
47 //This should point to a directory on disk and not a ramdisk (since we're measuring performance)
48 QString testDataPath;
49 QString dbName;
50 QString filePath;
51 const int count = 50000;
52
53private Q_SLOTS:
54 void initTestCase()
55 {
56 testDataPath = "./testdb";
57 dbName = "test";
58 filePath = testDataPath + "buffer.fb";
59 }
60
61 void testWriteRead_data()
62 {
63 QTest::addColumn<bool>("useDb");
64 QTest::addColumn<int>("count");
65
66 QTest::newRow("db, 50k") << true << count;
67 QTest::newRow("file, 50k") << false << count;
68 }
69
70 void testWriteRead()
71 {
72 QFETCH(bool, useDb);
73 QFETCH(int, count);
74
75 Database *db = 0;
76 if (useDb) {
77 db = new Database(testDataPath, dbName);
78 }
79
80 std::ofstream myfile;
81 myfile.open(filePath.toStdString());
82 const char *keyPrefix = "key";
83
84 QTime time;
85
86 time.start();
87 {
88 auto event = createEvent();
89 for (int i = 0; i < count; i++) {
90 if (db) {
91 if (i % 10000 == 0) {
92 if (i > 0) {
93 db->commitTransaction();
94 }
95 db->startTransaction();
96 }
97
98 db->write(keyPrefix + std::to_string(i), event);
99 } else {
100 myfile << event;
101 }
102 }
103
104 if (db) {
105 db->commitTransaction();
106 } else {
107 myfile.close();
108 }
109 }
110 const int writeDuration = time.restart();
111 qDebug() << "Writing took[ms]: " << writeDuration;
112
113 {
114 for (int i = 0; i < count; i++) {
115 if (db) {
116 db->read(keyPrefix + std::to_string(i), [](std::string value){});
117 }
118 }
119 }
120 const int readDuration = time.restart();
121
122 if (db) {
123 qDebug() << "Reading took[ms]: " << readDuration;
124 } else {
125 qDebug() << "File reading is not implemented.";
126 }
127
128 delete db;
129 }
130
131 void testBufferCreation()
132 {
133 QTime time;
134
135 time.start();
136 {
137 for (int i = 0; i < count; i++) {
138 auto event = createEvent();
139 }
140 }
141 const int bufferDuration = time.elapsed();
142 qDebug() << "Creating buffers took[ms]: " << bufferDuration;
143 }
144
145 void testSizes()
146 {
147 Database db(testDataPath, dbName);
148 qDebug() << "Database size [kb]: " << db.diskUsage()/1024;
149 db.removeFromDisk();
150
151 QFileInfo fileInfo(filePath);
152 qDebug() << "File size [kb]: " << fileInfo.size()/1024;
153 }
154};
155
156QTEST_MAIN(StorageBenchmark)
157#include "storagebenchmark.moc"