2 * Copyright (C) 2017 Cisco Inc.
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License, version 2,
6 * as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 // @author Changxue Deng <chadeng@cisco.com>
25 #include <mabain/db.h>
29 using namespace mabain;
31 #define DB_SIZE 128ULL*1024*1024
33 static int max_key = 10000000;
34 static std::atomic<int> write_index;
35 static bool stop_processing = false;
36 static std::string mbdir = "/var/tmp/mabain_test/";
38 static int key_list_size = 10;
39 std::string key_list[] = {
52 static void* insert_thread(void *arg)
55 TestKey mkey(MABAIN_TEST_KEY_TYPE_SHA_256);
57 DB *db_r = new DB(mbdir.c_str(), CONSTS::ReaderOptions(), 128LL*1024*1024, 128LL*1024*1024);
58 // If a reader wants to perform DB update, the async writer pointer must be set.
59 assert(db_r->is_open());
60 assert(db_r->SetAsyncWriterPtr((DB *) arg) == MBError::SUCCESS);
61 assert(db_r->AsyncWriterEnabled());
63 while(!stop_processing) {
64 curr_key = write_index.fetch_add(1, std::memory_order_release);
65 kv = mkey.get_key(curr_key);
66 if(curr_key < max_key) {
67 assert(db_r->Add(kv, kv) == MBError::SUCCESS);
69 stop_processing = true;
74 // Reader must unregister the async writer pointer
75 assert(db_r->UnsetAsyncWriterPtr((DB *) arg) == MBError::SUCCESS);
81 static void SetTestStatus(bool success)
85 cmd = std::string("touch ") + mbdir + "/_success";
87 cmd = std::string("rm ") + mbdir + "/_success >" + mbdir + "/out 2>" + mbdir + "/err";
89 if(system(cmd.c_str()) != 0) {
95 TestKey mkey(MABAIN_TEST_KEY_TYPE_SHA_256);
97 DB *db_r = new DB(mbdir.c_str(), CONSTS::ReaderOptions(), 128LL*1024*1024, 128LL*1024*1024);
98 assert(db_r->is_open());
101 for(int i = 0; i < 100; i++) {
102 kv = mkey.get_key(i);
103 assert(db_r->Find(kv, mbd) == MBError::SUCCESS);
104 assert(kv == std::string((const char *)mbd.buff, mbd.data_len));
110 static void GarbageLookup()
112 std::cout << "\nCalling Lookups during Garbage Collection" << std::endl;
114 DB *db_r = new DB(mbdir.c_str(), CONSTS::ReaderOptions(), 128LL*1024*1024, 128LL*1024*1024);
115 assert(db_r->is_open());
118 for(int i = 0; i < key_list_size; i++) {
119 int rval = db_r->Find(key_list[i], mbd);
120 if(rval != MBError::SUCCESS) {
121 std::cout << key_list[i] << ": " << MBError::get_error_str(rval) << std::endl;
123 std::cout << key_list[i] << ": " << std::string((const char *)mbd.buff, mbd.data_len) << std::endl;
124 assert(rval == MBError::SUCCESS);
125 assert(key_list[i] == std::string((const char *)mbd.buff, mbd.data_len));
133 static void Deletekeys()
135 std::cout << "\nStart Deletekeys ()" << std::endl;
138 int options = CONSTS::WriterOptions() | CONSTS::ReaderOptions() | CONSTS::ASYNC_WRITER_MODE;
139 DB *db = new DB(mbdir.c_str(), options, 128LL*1024*1024, 128LL*1024*1024);
140 assert(db->is_open());
143 TestKey mkey(MABAIN_TEST_KEY_TYPE_SHA_256);
144 for(int i = 0; i < 10000; i++) {
145 kv = mkey.get_key(i);
146 assert(db->Remove(kv) == MBError::SUCCESS);
154 static void GarbageCollectResources()
156 std::cout << "\nKick-start Garbage Collection" << std::endl;
157 TestKey mkey(MABAIN_TEST_KEY_TYPE_SHA_256);
160 int options = CONSTS::WriterOptions() | CONSTS::ReaderOptions() | CONSTS::ASYNC_WRITER_MODE;
161 DB *db = new DB(mbdir.c_str(), options, 128LL*1024*1024, 128LL*1024*1024);
162 assert(db->is_open());
165 db->CollectResource(1, 1);
167 for(int i = 0; i < key_list_size; i++) {
168 assert(db->Add(key_list[i], key_list[i]) == MBError::SUCCESS);
176 // Multiple threads performing DB insertion/deletion/updating
177 int main(int argc, char *argv[])
179 std::string cmd = std::string("rm -rf ") + mbdir;
180 if(system(cmd.c_str()) != 0) {}
182 cmd = std::string("mkdir -p ") + mbdir;
183 if(system(cmd.c_str()) != 0) {}
192 mbdir = std::string(argv[1]);
193 std::cout << "Mabain test db directory " << mbdir << "\n";
196 max_key = atoi(argv[2]);
197 std::cout << "Setting number of keys to be " << max_key << "\n";
200 SetTestStatus(false);
201 mabain::DB::SetLogFile(mbdir + "/mabain.log");
203 write_index.store(0, std::memory_order_release);
204 // Writer needs to enable async writer mode.
205 int options = CONSTS::WriterOptions() | CONSTS::ASYNC_WRITER_MODE;
206 DB *db = new DB(mbdir.c_str(), options, 128LL*1024*1024, 128LL*1024*1024);
207 assert(db->is_open());
210 for(int i = 0; i < nthread; i++) {
211 if(pthread_create(&pid[i], NULL, insert_thread, db) != 0) {
212 std::cout << "failed to create thread\n";
217 while(!stop_processing) {
221 for(int i = 0; i < nthread; i++) {
222 pthread_join(pid[i], NULL);
225 // Writer handle must be the last one to close if reader handles are used for DB update.
226 assert(db->Close() == MBError::SUCCESS);
229 // at this timer we added all required keys, verify all those keys
232 // delete keys so that we can create some garbage data to be reclaimed
235 // kick start the garbage collection task
236 GarbageCollectResources();
238 // lookup few keys that we added during garbage collection
241 mabain::DB::CloseLogFile();