diff --git a/ART/N.cpp b/ART/N.cpp index af88e93..96d9f51 100644 --- a/ART/N.cpp +++ b/ART/N.cpp @@ -89,7 +89,8 @@ void N::helpFlush(std::atomic *n) { N *now_node = n->load(); // printf("help\n"); if (N::isDirty(now_node)) { - printf("help, point to type is %d\n", ((BaseNode *)N::clearDirty(now_node))->type); + printf("help, point to type is %d\n", + ((BaseNode *)N::clearDirty(now_node))->type); flush_data((void *)n, sizeof(N *)); // clflush((char *)n, sizeof(N *), true, true); n->compare_exchange_strong(now_node, N::clearDirty(now_node)); @@ -124,7 +125,7 @@ void N::writeLockOrRestart(bool &needRestart) { return; } } while (!typeVersionLockObsolete->compare_exchange_weak(version, - version + 0b10)); + version + 0b10)); } void N::lockVersionOrRestart(uint64_t &version, bool &needRestart) { @@ -133,7 +134,7 @@ void N::lockVersionOrRestart(uint64_t &version, bool &needRestart) { return; } if (typeVersionLockObsolete->compare_exchange_strong(version, - version + 0b10)) { + version + 0b10)) { version = version + 0b10; } else { needRestart = true; diff --git a/ART/N.h b/ART/N.h index 7dc40d9..9c6df97 100644 --- a/ART/N.h +++ b/ART/N.h @@ -87,7 +87,7 @@ class N : public BaseNode { virtual ~N() {} // 3b type 60b version 1b lock 1b obsolete -// std::atomic typeVersionLockObsolete{0b100}; + // std::atomic typeVersionLockObsolete{0b100}; std::atomic *typeVersionLockObsolete; // version 1, unlocked, not obsolete alignas(64) std::atomic prefix; diff --git a/ART/Tree.cpp b/ART/Tree.cpp index 4d2d8cb..99ea388 100644 --- a/ART/Tree.cpp +++ b/ART/Tree.cpp @@ -111,7 +111,7 @@ void *Tree::lookup(const Key *k) const { typename Tree::OperationResults Tree::update(const Key *k) const { EpochGuard NewEpoch; - restart: +restart: bool needRestart = false; N *node = nullptr; @@ -131,59 +131,60 @@ typename Tree::OperationResults Tree::update(const Key *k) const { auto v = node->getVersion(); // check version switch (checkPrefix(node, k, level)) { // increases level - case CheckPrefixResult::NoMatch: + case CheckPrefixResult::NoMatch: + if (N::isObsolete(v) || !node->readUnlockOrRestart(v)) { + goto restart; + } + return OperationResults::NotFound; + case CheckPrefixResult::OptimisticMatch: + // fallthrough + case CheckPrefixResult::Match: { + // if (level >= k->getKeyLen()) { + // // key is too short + // // but it next fkey is 0 + // return OperationResults::NotFound; + // } + nodeKey = k->fkey[level]; + + parentref = curref; + curref = N::getChild(nodeKey, node); + if (curref == nullptr) + nextNode = nullptr; + else + nextNode = N::clearDirty(curref->load()); + + if (nextNode == nullptr) { if (N::isObsolete(v) || !node->readUnlockOrRestart(v)) { + // std::cout<<"retry\n"; goto restart; } return OperationResults::NotFound; - case CheckPrefixResult::OptimisticMatch: - // fallthrough - case CheckPrefixResult::Match: { - // if (level >= k->getKeyLen()) { - // // key is too short - // // but it next fkey is 0 - // return OperationResults::NotFound; - // } - nodeKey = k->fkey[level]; - - parentref = curref; - curref = N::getChild(nodeKey, node); - if (curref == nullptr) - nextNode = nullptr; - else - nextNode = N::clearDirty(curref->load()); - - if (nextNode == nullptr) { - if (N::isObsolete(v) || !node->readUnlockOrRestart(v)) { -// std::cout<<"retry\n"; - goto restart; - } - return OperationResults::NotFound; + } + if (N::isLeaf(nextNode)) { + node->lockVersionOrRestart(v, needRestart); + if (needRestart) { + // std::cout<<"retry\n"; + goto restart; } - if (N::isLeaf(nextNode)) { - node->lockVersionOrRestart(v, needRestart); - if (needRestart){ -// std::cout<<"retry\n"; - goto restart; - } - - Leaf *leaf = N::getLeaf(nextNode); - if (!leaf->checkKey(k)) { - node->writeUnlock(); - return OperationResults::NotFound; - } - // find key, update it - Leaf *newleaf = new (alloc_new_node_from_type(NTypes::Leaf)) - Leaf(leaf->fkey, k->key_len, (char *)k->value, k->val_len); -// std::cout<<(int)(((BaseNode *)newleaf)->type)<<"\n"; - flush_data((void *)newleaf, sizeof(Leaf)); - N::change(node, nodeKey, N::setLeaf(newleaf)); + Leaf *leaf = N::getLeaf(nextNode); + if (!leaf->checkKey(k)) { node->writeUnlock(); - return OperationResults::Success; + return OperationResults::NotFound; } - level++; + // find key, update it + Leaf *newleaf = new (alloc_new_node_from_type(NTypes::Leaf)) + Leaf(leaf->fkey, k->key_len, (char *)k->value, k->val_len); + // std::cout<<(int)(((BaseNode + // *)newleaf)->type)<<"\n"; + flush_data((void *)newleaf, sizeof(Leaf)); + + N::change(node, nodeKey, N::setLeaf(newleaf)); + node->writeUnlock(); + return OperationResults::Success; } + level++; + } } } } diff --git a/CMakeLists.txt b/CMakeLists.txt index 18aaf8e..690e198 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,3 +60,4 @@ target_link_libraries(malloc_diff Indexes) add_executable(unittest ${DIR_TEST_SRC}) target_link_libraries(unittest Indexes gtest) +add_executable(gen_mail script/gen_mail.cpp) \ No newline at end of file diff --git a/benchmark/config.h b/benchmark/config.h index df102e6..6b71945 100644 --- a/benchmark/config.h +++ b/benchmark/config.h @@ -39,6 +39,7 @@ struct Config { int num_threads; unsigned long long init_keys; int time; + int key_length; bool share_memory; float duration; @@ -85,6 +86,7 @@ static void usage_exit(FILE *out) { " -K --key_type : Key type : 0 (Integer) 1 (String) \n" " -n --num_threads : Number of workers \n" " -k --keys : Number of key-value pairs at begin\n" + " -L --key_length : Length of string key\n" " -s --non_share_memory : Use different index instances among " "different workers\n" " -d --duration : Execution time\n" @@ -104,6 +106,7 @@ static void parse_arguments(int argc, char *argv[], Config &state) { state.key_type = Integer; state.init_keys = 3000000; state.time = 5; + state.key_length = 15; state.share_memory = true; state.duration = 1; state.benchmark = READ_ONLY; @@ -118,7 +121,7 @@ static void parse_arguments(int argc, char *argv[], Config &state) { while (1) { int idx = 0; int c = - getopt_long(argc, argv, "f:t:K:n:k:sd:b:w:S:l:r:T:", opts, &idx); + getopt_long(argc, argv, "f:t:K:n:k:L:sd:b:w:S:l:r:T:", opts, &idx); if (c == -1) break; @@ -142,6 +145,9 @@ static void parse_arguments(int argc, char *argv[], Config &state) { case 'k': state.init_keys = (1llu << atoi(optarg)); break; + case 'L': + state.key_length = atoi(optarg); + break; case 's': state.share_memory = false; break; @@ -172,7 +178,11 @@ static void parse_arguments(int argc, char *argv[], Config &state) { usage_exit(stderr); } } + if(state.key_type == String){ + std::cout<<"key length: "< class Coordinator { res = art->insert(k); break; case REMOVE: -// art->insert(k); + // art->insert(k); art->remove(k); break; case GET: @@ -315,12 +315,14 @@ template class Coordinator { break; case REMOVE: // first insert then remove -// if (conf.key_type == Integer) { -// // std::cout<<"insert key "<btree_insert(d, value); -// } else if (conf.key_type == String) { -// bt->btree_insert((char *)s.c_str(), value); -// } + // if (conf.key_type == Integer) { + // // std::cout<<"insert + // key "<btree_insert(d, + // value); + // } else if (conf.key_type == String) { + // bt->btree_insert((char *)s.c_str(), + // value); + // } if (conf.key_type == Integer) { // std::cout<<"delete key "< class Coordinator { "%s, benchmark %d, zipfian %.2lf\n", (double)final_result.throughput / 1000000.0 / conf.duration, conf.num_threads, (conf.type == PART) ? "ART" : "FF", - (conf.key_type == Integer) ? "Int" : "Str", conf.benchmark,(conf.workload == RANDOM) ? 0:conf.skewness); + (conf.key_type == Integer) ? "Int" : "Str", conf.benchmark, + (conf.workload == RANDOM) ? 0 : conf.skewness); delete art; delete[] pid; @@ -473,7 +476,7 @@ template class Coordinator { if (conf.key_type == Integer) { long kk = benchmark->nextInitIntKey(); bt->btree_insert(kk, value); - std::cout << "insert key " << kk << "id: " << i << "\n"; + std::cout << "insert key " << kk << "id: " << i << "\n"; } else if (conf.key_type == String) { std::string s = benchmark->nextInitStrKey(); bt->btree_insert((char *)s.c_str(), value); @@ -503,7 +506,8 @@ template class Coordinator { "%s, benchmark %d, zipfian %.2lf\n", (double)final_result.throughput / 1000000.0 / conf.duration, conf.num_threads, (conf.type == PART) ? "ART" : "FF", - (conf.key_type == Integer) ? "Int" : "Str", conf.benchmark, (conf.workload == RANDOM) ? 0:conf.skewness); + (conf.key_type == Integer) ? "Int" : "Str", conf.benchmark, + (conf.workload == RANDOM) ? 0 : conf.skewness); delete[] pid; delete[] results; diff --git a/benchmark/generator.cpp b/benchmark/generator.cpp index eab342f..a4e87e2 100644 --- a/benchmark/generator.cpp +++ b/benchmark/generator.cpp @@ -1,13 +1,12 @@ -#include "util.h" #include "generator.h" +#include "util.h" std::mutex ZipfWrapper::gen_mtx; -std::map ZipfWrapper::wf_map; +std::map ZipfWrapper::wf_map; std::mutex dataset_mtx; -WorkloadFile::WorkloadFile(std::string filename) -{ +WorkloadFile::WorkloadFile(std::string filename) { std::ifstream fin; fin.open(filename, std::ios::in | std::ios::binary); fin.seekg(0, std::ios::end); @@ -35,64 +34,52 @@ unsigned int hashfunc(uint32_t val) { return hash; } -int ZipfGenerator::randomInt() -{ +int ZipfGenerator::randomInt() { double d = rdm.randomDouble(); int low = 0, high = size; - while (low < high - 1) - { + while (low < high - 1) { int mid = (low + high) / 2; - if (zipfs[mid] <= d && zipfs[mid + 1] > d) - { - low = mid; break; - } - else if (zipfs[mid] > d) - { + if (zipfs[mid] <= d && zipfs[mid + 1] > d) { + low = mid; + break; + } else if (zipfs[mid] > d) { high = mid; - } - else - { + } else { low = mid; } } return hashfunc(low) % size; } -void ZipfGenerator::init(double s, int inital) -{ +void ZipfGenerator::init(double s, int inital) { zipfs = new double[inital]; double sum = 0.0; - for (int i = 1; i < inital + 1; i++) - { + for (int i = 1; i < inital + 1; i++) { zipfs[i - 1] = 1.0 / (float)pow((double)i, s); sum += zipfs[i - 1]; } zipfs[0] = 1.0 / sum; - for (int i = 1; i < inital; i++) - { + for (int i = 1; i < inital; i++) { zipfs[i] = zipfs[i] / sum + zipfs[i - 1]; } } -ZipfGenerator::ZipfGenerator(double s, int inital) : size(inital) -{ +ZipfGenerator::ZipfGenerator(double s, int inital) : size(inital) { init(s, inital); } - -ZipfWrapper::ZipfWrapper(double s, int inital){ +ZipfWrapper::ZipfWrapper(double s, int inital) { cursor = random(); std::string filename = get_file_name(s); gen_mtx.lock(); - if (wf_map.find(filename) == wf_map.end()){ - if (access(filename.c_str(), 0)){ + if (wf_map.find(filename) == wf_map.end()) { + if (access(filename.c_str(), 0)) { std::cout << filename << " not exists, generate it now\n"; ZipfGenerator zipf(s, inital); std::ofstream myfile; myfile.open(filename, std::ios::out | std::ios::binary); - for (unsigned long long i = 0; i < inital * 16; i++) - { + for (unsigned long long i = 0; i < inital * 16; i++) { int d = zipf.randomInt(); myfile.write((char *)&d, sizeof(int)); } @@ -105,12 +92,12 @@ ZipfWrapper::ZipfWrapper(double s, int inital){ gen_mtx.unlock(); } -DataSet::DataSet(int size): data_size(size) { - std::string fn_str = get_file_name_str(); +DataSet::DataSet(int size, int key_length) : data_size(size), key_len(key_length) { + std::string fn_str = get_file_name_str(key_len); dataset_mtx.lock(); if (access(fn_str.c_str(), 0)) { std::cout << fn_str << " not exist, generate it now\n"; - RandomGenerator rdm; + RandomGenerator rdm(key_len); std::ofstream myfile; myfile.open(fn_str, std::ios::out); for (unsigned long long i = 0; i < data_size; i++) { diff --git a/benchmark/generator.h b/benchmark/generator.h index 27f3ad0..e4a6a91 100644 --- a/benchmark/generator.h +++ b/benchmark/generator.h @@ -16,113 +16,109 @@ #include "config.h" #include -class WorkloadGenerator{ -public: +class WorkloadGenerator { + public: virtual long long Next() = 0; }; /* - * Fast random number generator, using eran48/nrand48; All the functions work by generating - * a sequence of 48-bit integers, X[i], accourding to the liner congruential formula: - * Xn+1 = (aXn + c) mod m; where n >= 0 - * If you want to generate the same sequence again, you can call "reset" function. + * Fast random number generator, using eran48/nrand48; All the functions work by + * generating a sequence of 48-bit integers, X[i], accourding to the liner + * congruential formula: Xn+1 = (aXn + c) mod m; where n >= 0 If you want to + * generate the same sequence again, you can call "reset" function. */ -class RandomGenerator: public WorkloadGenerator{ +class RandomGenerator : public WorkloadGenerator { unsigned short seed[3]; unsigned short seed2[3]; unsigned short inital[3]; unsigned short inital2[3]; -public: - RandomGenerator(){ - for (int i=0; i<3; i++){ + int key_len; + + public: + RandomGenerator(int key_len_ = 8): key_len(key_len_) { + for (int i = 0; i < 3; i++) { inital[i] = seed[i] = rand(); inital2[i] = seed2[i] = rand(); } } - int randomInt(){ - return nrand48(seed) ^ nrand48(seed2); - } + int randomInt() { return nrand48(seed) ^ nrand48(seed2); } + + std::string RandomStr() { + int len = randomInt() % 10 + 5; // len 8-16 // 5-15 - std::string RandomStr(){ -#ifdef VARIABLE_LENGTH - int len = randomInt() % 10 + 5; -#else - int len = sizeof(long long); -#endif std::string res = ""; for (int i = 0; i < len; i++) { +// char c = randomInt() % 10 + '0'; // 0-9 char c = randomInt() % 94 + 33; res += c; } return res; } - double randomDouble(){ - return erand48(seed) * erand48(seed2); - } - void setSeed(unsigned short newseed[3]){ - memcpy(seed, newseed, sizeof(unsigned short)*3); + double randomDouble() { return erand48(seed) * erand48(seed2); } + void setSeed(unsigned short newseed[3]) { + memcpy(seed, newseed, sizeof(unsigned short) * 3); } - void reset(){ - memcpy(seed, inital, sizeof(unsigned short)*3); - memcpy(seed2, inital2, sizeof(unsigned short)*3); + void reset() { + memcpy(seed, inital, sizeof(unsigned short) * 3); + memcpy(seed2, inital2, sizeof(unsigned short) * 3); } - long long Next(){ - return randomInt(); - } -}__attribute__((aligned(64))); - + long long Next() { return randomInt(); } +} __attribute__((aligned(64))); -class WorkloadFile{ +class WorkloadFile { int bufsize; - int* buffer; -public: + int *buffer; + + public: WorkloadFile(std::string filename); - int get(uint32_t c){ - return buffer[c%bufsize]; - } + int get(uint32_t c) { return buffer[c % bufsize]; } }; -class ZipfGenerator{ - double* zipfs; +class ZipfGenerator { + double *zipfs; RandomGenerator rdm; int size; void init(double s, int inital); -public: - ZipfGenerator(double s, int inital = (1<<20)); - ~ZipfGenerator(){ - delete zipfs; - } + + public: + ZipfGenerator(double s, int inital = (1 << 20)); + ~ZipfGenerator() { delete zipfs; } int randomInt(); } __attribute__((aligned(64))); -class ZipfWrapper: public WorkloadGenerator{ +class ZipfWrapper : public WorkloadGenerator { static std::mutex gen_mtx; - static std::map wf_map; + static std::map wf_map; uint32_t cursor; - WorkloadFile* wf; + WorkloadFile *wf; - static std::string get_file_name(double s){ - std::stringstream ss; ss << (int)((s+0.001)*100); + static std::string get_file_name(double s) { + std::stringstream ss; + ss << (int)((s + 0.001) * 100); return "/tmp/" + ss.str() + "zipfian_data"; } -public: - ZipfWrapper(double s, int inital = (1<<20)); - long long Next(){ - return wf->get(cursor++); - } + + public: + ZipfWrapper(double s, int inital = (1 << 20)); + long long Next() { return wf->get(cursor++); } }; -class DataSet{ -public: +class DataSet { + public: std::string *wl_str; int data_size; + int key_len; - static std::string get_file_name_str() { return "/tmp/random_str_data"; } + static std::string get_file_name_str(int len) { + std::stringstream ss; + ss << len; + return "/tmp/random_str_data" + ss.str(); + } - DataSet(int size); + DataSet(int size, int key_length); }; #endif // GENERATOR_H \ No newline at end of file diff --git a/benchmark/microbench.h b/benchmark/microbench.h index 816d1b0..0c4f02c 100644 --- a/benchmark/microbench.h +++ b/benchmark/microbench.h @@ -2,8 +2,8 @@ #define _MICRO_BEHCN_H #include "config.h" -#include "util.h" #include "generator.h" +#include "util.h" #include #include @@ -43,9 +43,8 @@ class Benchmark { Config _conf; DataSet *dataset; - Benchmark(Config &conf) : init_key(0), _conf(conf) { - dataset = new DataSet(conf.init_keys); + dataset = new DataSet(conf.init_keys, conf.key_length); if (conf.workload == RANDOM) { workload = new RandomGenerator(); } else if (conf.workload == ZIPFIAN) { @@ -76,7 +75,9 @@ class Benchmark { // return init_key++ % _conf.init_keys; } - virtual std::string nextInitStrKey() { return dataset->wl_str[(init_key++) % _conf.init_keys]; } + virtual std::string nextInitStrKey() { + return dataset->wl_str[(init_key++) % _conf.init_keys]; + } } __attribute__((aligned(64))); class ReadOnlyBench : public Benchmark { @@ -112,7 +113,7 @@ class InsertOnlyBench : public Benchmark { } std::pair nextStrOperation() { - long long next = workload->Next()% _conf.init_keys; + long long next = workload->Next() % _conf.init_keys; std::string s = dataset->wl_str[next]; char p1 = rdm.randomInt() % 94 + 33; char p2 = rdm.randomInt() % 94 + 33; @@ -139,7 +140,7 @@ class UpdateOnlyBench : public Benchmark { } std::pair nextStrOperation() { - long long next = workload->Next()% _conf.init_keys; + long long next = workload->Next() % _conf.init_keys; return std::make_pair(UPDATE, dataset->wl_str[next]); } } __attribute__((aligned(64))); @@ -154,7 +155,7 @@ class DeleteOnlyBench : public Benchmark { } std::pair nextStrOperation() { - long long next = workload->Next()% _conf.init_keys; + long long next = workload->Next() % _conf.init_keys; return std::make_pair(REMOVE, dataset->wl_str[next]); } } __attribute__((aligned(64))); @@ -194,11 +195,11 @@ class MixedBench : public Benchmark { std::pair nextStrOperation() { std::pair result; - long long next = workload->Next()% _conf.init_keys; + long long next = workload->Next() % _conf.init_keys; std::string _key = dataset->wl_str[next]; switch (round) { case 0: - next = workload->Next()% _conf.init_keys; + next = workload->Next() % _conf.init_keys; skey = dataset->wl_str[next]; result = std::make_pair(REMOVE, skey); break; @@ -230,7 +231,7 @@ class ScanBench : public Benchmark { } std::pair nextStrOperation() { - long long next = workload->Next()% _conf.init_keys; + long long next = workload->Next() % _conf.init_keys; std::string s = dataset->wl_str[next]; return std::make_pair(SCAN, s); } @@ -249,17 +250,15 @@ class YSCBA : public Benchmark { virtual std::pair nextIntOperation() { int k = rdm.randomInt() % 100; if (k > read_ratio) { - return std::make_pair(UPDATE, - workload->Next() % _conf.init_keys); + return std::make_pair(UPDATE, workload->Next() % _conf.init_keys); } else { - return std::make_pair(GET, - workload->Next() % _conf.init_keys); + return std::make_pair(GET, workload->Next() % _conf.init_keys); } } virtual std::pair nextStrOperation() { int k = rdm.randomInt() % 100; - long long next = workload->Next()% _conf.init_keys; + long long next = workload->Next() % _conf.init_keys; std::string s = dataset->wl_str[next]; if (k > read_ratio) { return std::make_pair(UPDATE, s); @@ -281,17 +280,15 @@ class YSCBB : public Benchmark { virtual std::pair nextIntOperation() { int k = rdm.randomInt() % 100; if (k < read_ratio) { - return std::make_pair(GET, - workload->Next() % _conf.init_keys); + return std::make_pair(GET, workload->Next() % _conf.init_keys); } else { - return std::make_pair(UPDATE, - workload->Next() % _conf.init_keys); + return std::make_pair(UPDATE, workload->Next() % _conf.init_keys); } } virtual std::pair nextStrOperation() { int k = rdm.randomInt() % 100; - long long next = workload->Next()% _conf.init_keys; + long long next = workload->Next() % _conf.init_keys; std::string s = dataset->wl_str[next]; if (k > read_ratio) { return std::make_pair(UPDATE, s); @@ -310,17 +307,42 @@ class YSCBC : public Benchmark { } virtual std::pair nextStrOperation() { - long long next = workload->Next()% _conf.init_keys; + long long next = workload->Next() % _conf.init_keys; std::string s = dataset->wl_str[next]; return std::make_pair(GET, s); } } __attribute__((aligned(64))); -class YSCBD : public Benchmark { +class YSCBD : public Benchmark {// read + insert public: - YSCBD(Config &conf) : Benchmark(conf) {} + int read_ratio; + RandomGenerator rdm; - OperationType nextOp() { return GET; } + YSCBD(Config &conf) : Benchmark(conf), read_ratio(conf.read_ratio) {} + + virtual std::pair nextIntOperation() { + int k = rdm.randomInt() % 100; + if (k < read_ratio) { + return std::make_pair(GET, workload->Next() % _conf.init_keys); + } else { + int d = rdm.randomInt() % 128; + return std::make_pair(INSERT, workload->Next() * d); + } + } + + virtual std::pair nextStrOperation() { + int k = rdm.randomInt() % 100; + long long next = workload->Next() % _conf.init_keys; + std::string s = dataset->wl_str[next]; + if (k < read_ratio) { + return std::make_pair(GET, s); + } else { + char p1 = rdm.randomInt() % 94 + 33; + char p2 = rdm.randomInt() % 94 + 33; + s = p1 + s + p2; + return std::make_pair(INSERT, s); + } + } } __attribute__((aligned(64))); class YSCBE : public Benchmark { diff --git a/fast_fair/fast_fair.h b/fast_fair/fast_fair.h index 65cd8e0..c301afc 100644 --- a/fast_fair/fast_fair.h +++ b/fast_fair/fast_fair.h @@ -3,6 +3,7 @@ #include "pmdk_gc.h" #include "util.h" +#include #include #include #include @@ -11,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -128,19 +128,19 @@ class header { page *sibling_ptr; // 8 bytes uint32_t level; // 4 bytes uint32_t switch_counter; // 4 bytes -// std::mutex *mtx; // 8 bytes + // std::mutex *mtx; // 8 bytes boost::shared_mutex *mtx; - union Key highest; // 8 bytes - uint8_t is_deleted; // 1 bytes - int16_t last_index; // 2 bytes - uint8_t dummy[5]; // 5 bytes + union Key highest; // 8 bytes + uint8_t is_deleted; // 1 bytes + int16_t last_index; // 2 bytes + uint8_t dummy[5]; // 5 bytes friend class page; friend class btree; public: header() { -// mtx = new std::mutex(); + // mtx = new std::mutex(); mtx = new boost::shared_mutex(); leftmost_ptr = nullptr; @@ -436,13 +436,14 @@ class page { ++(*num_entries); } - key_item *make_new_key_item(key_item *key){ + key_item *make_new_key_item(key_item *key) { void *aligned_alloc; posix_memalign(&aligned_alloc, 64, sizeof(key_item) + key->key_len); key_item *new_key = (key_item *)aligned_alloc; new_key->key_len = key->key_len; // new_key->key = key; - memcpy(new_key->key, key, key->key_len); // copy including nullptr character + memcpy(new_key->key, key, + key->key_len); // copy including nullptr character flush_data((void *)new_key, sizeof(key_item) + key->key_len); return new_key; @@ -476,7 +477,7 @@ class page { TX_END #else -// new_entry->key.skey = make_new_key_item(key); + // new_entry->key.skey = make_new_key_item(key); new_entry->key.skey = key; #endif new_entry->ptr = (char *)ptr; @@ -542,7 +543,8 @@ class page { #else -// records[i + 1].key.skey = make_new_key_item(key); + // records[i + 1].key.skey = + // make_new_key_item(key); records[i + 1].key.skey = key; #endif records[i + 1].ptr = ptr; @@ -574,8 +576,8 @@ class page { } TX_END #else -// records[0].key.skey = make_new_key_item(key); - records[0].key.skey=key; + // records[0].key.skey = make_new_key_item(key); + records[0].key.skey = key; #endif records[0].ptr = ptr; flush_data((void *)&records[0], sizeof(entry)); @@ -1433,12 +1435,14 @@ class page { if (hdr.leftmost_ptr == nullptr) { // Search a leaf node do { - if(value == nullptr){ + if (value == nullptr) { // read - boost::shared_lock sharedlock(*hdr.mtx); - }else{ + boost::shared_lock sharedlock( + *hdr.mtx); + } else { // update - boost::unique_lock uniquelock(*hdr.mtx); + boost::unique_lock uniquelock( + *hdr.mtx); } previous_switch_counter = hdr.switch_counter; ret = nullptr; @@ -1564,188 +1568,6 @@ class page { return nullptr; } - char *linear_search(btree *bt, key_item *key) { - int i = 1; - uint32_t previous_switch_counter; - char *ret = nullptr; - char *t; - key_item *k; - - if (hdr.leftmost_ptr == nullptr) { // Search a leaf node - do { - previous_switch_counter = hdr.switch_counter; - ret = nullptr; - - // search from left ro right - if (IS_FORWARD(previous_switch_counter)) { - k = records[0].key.skey; - if (memcmp(k->key, key->key, - std::min(k->key_len, key->key_len)) == 0) { - if ((t = records[0].ptr) != nullptr) { - if (memcmp( - k->key, records[0].key.skey->key, - std::min(k->key_len, - records[0].key.skey->key_len)) == - 0) { - ret = t; - continue; - } - } - } - - for (i = 1; records[i].ptr != nullptr; ++i) { - k = records[i].key.skey; - if (memcmp(k->key, key->key, - std::min(k->key_len, key->key_len)) == 0) { - if (records[i - 1].ptr != (t = records[i].ptr)) { - if (memcmp(k->key, records[i].key.skey->key, - std::min( - k->key_len, - records[i].key.skey->key_len)) == - 0) { - ret = t; - break; - } - } - } - } - } else { // search from right to left - for (i = count() - 1; i > 0; --i) { - k = records[i].key.skey; - if (memcmp(k->key, key->key, - std::min(k->key_len, key->key_len)) == 0) { - if (records[i - 1].ptr != (t = records[i].ptr) && - t) { - if (memcmp(k->key, records[i].key.skey->key, - std::min( - k->key_len, - records[i].key.skey->key_len)) == - 0) { - ret = t; - break; - } - } - } - } - - if (!ret) { - k = records[0].key.skey; - if (memcmp(k->key, key->key, - std::min(k->key_len, key->key_len)) == 0) { - if (nullptr != (t = records[0].ptr) && t) { - if (memcmp(k->key, records[0].key.skey->key, - std::min( - k->key_len, - records[0].key.skey->key_len)) == - 0) { - ret = t; - continue; - } - } - } - } - } - } while (IS_FORWARD(hdr.switch_counter) != - IS_FORWARD(previous_switch_counter)); - - if (ret) { - return ret; - } - - if ((t = (char *)hdr.sibling_ptr) && - memcmp(key->key, ((page *)t)->hdr.highest.skey->key, - std::min(key->key_len, - ((page *)t)->hdr.highest.skey->key_len)) >= 0) { - hdr.mtx->lock(); - hdr.sibling_ptr->hdr.mtx->lock(); - bt->btree_insert_internal( - (char *)this, hdr.sibling_ptr->hdr.highest.skey, - (char *)hdr.sibling_ptr, hdr.level + 1); - hdr.sibling_ptr->hdr.mtx->unlock(); - hdr.mtx->unlock(); - return t; - } - - return nullptr; - } else { // internal node - do { - previous_switch_counter = hdr.switch_counter; - ret = nullptr; - - if (IS_FORWARD(previous_switch_counter)) { - k = records[0].key.skey; - if (memcmp(key->key, k->key, - std::min(key->key_len, k->key_len)) < 0) { - if ((t = (char *)hdr.leftmost_ptr) != records[0].ptr) { - ret = t; - continue; - } - } - - for (i = 1; records[i].ptr != nullptr; ++i) { - k = records[i].key.skey; - if (memcmp(key->key, k->key, - std::min(key->key_len, k->key_len)) < 0) { - if ((t = records[i - 1].ptr) != records[i].ptr) { - ret = t; - break; - } - } - } - - if (!ret) { - ret = records[i - 1].ptr; - continue; - } - } else { // search from right to left - for (i = count() - 1; i >= 0; --i) { - k = records[i].key.skey; - if (memcmp(key->key, k->key, - std::min(key->key_len, k->key_len)) >= 0) { - if (i == 0) { - if ((char *)hdr.leftmost_ptr != - (t = records[i].ptr)) { - ret = t; - break; - } - } else { - if (records[i - 1].ptr != - (t = records[i].ptr)) { - ret = t; - break; - } - } - } - } - } - } while (IS_FORWARD(hdr.switch_counter) != - IS_FORWARD(previous_switch_counter)); - - if ((t = (char *)hdr.sibling_ptr) != nullptr) { - if (memcmp(key->key, ((page *)t)->hdr.highest.skey->key, - std::min(key->key_len, - ((page *)t)->hdr.highest.skey->key_len)) >= - 0) { - hdr.mtx->lock(); - hdr.sibling_ptr->hdr.mtx->lock(); - bt->btree_insert_internal( - (char *)this, hdr.sibling_ptr->hdr.highest.skey, - (char *)hdr.sibling_ptr, hdr.level + 1); - hdr.sibling_ptr->hdr.mtx->unlock(); - hdr.mtx->unlock(); - return t; - } - } - - if (ret) { - return ret; - } else - return (char *)hdr.leftmost_ptr; - } - - return nullptr; - } - char *linear_search(key_item *key, char *value = nullptr) { int i = 1; uint32_t previous_switch_counter; @@ -1755,12 +1577,14 @@ class page { if (hdr.leftmost_ptr == nullptr) { // Search a leaf node do { - if(value == nullptr){ + if (value == nullptr) { // read - boost::shared_lock sharedlock(*hdr.mtx); - }else{ + boost::shared_lock sharedlock( + *hdr.mtx); + } else { // update - boost::unique_lock uniquelock(*hdr.mtx); + boost::unique_lock uniquelock( + *hdr.mtx); } previous_switch_counter = hdr.switch_counter; @@ -1773,18 +1597,21 @@ class page { std::cout << "boom!!!\n"; return nullptr; } - if (memcmp(k->key, key->key, - std::min(k->key_len, key->key_len)) == 0) { + if (memcmp(k->key, key->key, std::min(k->key_len, key->key_len)) == 0) { if ((t = records[0].ptr) != nullptr) { - if (memcmp( - k->key, records[0].key.skey->key, - std::min(k->key_len, - records[0].key.skey->key_len)) == - 0) { + if (memcmp(k->key, records[0].key.skey->key, std::min(k->key_len, + records[0].key.skey->key_len)) == 0) { ret = t; - if(value){ + if (value) { + char *garbage = records[0].ptr; records[0].ptr = value; - flush_data(&records[0].ptr, sizeof(uint64_t)); + flush_data(&records[0].ptr, + sizeof(uint64_t)); +#ifdef USE_PMDK +#ifdef FF_GC + ti->AddGarbageNode((void *)garbage); +#endif +#endif } continue; } @@ -1807,9 +1634,16 @@ class page { records[i].key.skey->key_len)) == 0) { ret = t; - if(value){ + if (value) { + char *garbage = records[i].ptr; records[i].ptr = value; - flush_data(&records[i].ptr, sizeof(uint64_t)); + flush_data(&records[i].ptr, + sizeof(uint64_t)); +#ifdef USE_PMDK +#ifdef FF_GC + ti->AddGarbageNode((void *)garbage); +#endif +#endif } break; } @@ -1835,9 +1669,16 @@ class page { records[i].key.skey->key_len)) == 0) { ret = t; - if(value){ + if (value) { + char *garbage = records[i].ptr; records[i].ptr = value; - flush_data(&records[i].ptr, sizeof(uint64_t)); + flush_data(&records[i].ptr, + sizeof(uint64_t)); +#ifdef USE_PMDK +#ifdef FF_GC + ti->AddGarbageNode((void *)garbage); +#endif +#endif } break; } @@ -1861,9 +1702,16 @@ class page { records[0].key.skey->key_len)) == 0) { ret = t; - if(value){ + if (value) { + char *garbage = records[0].ptr; records[0].ptr = value; - flush_data(&records[0].ptr, sizeof(uint64_t)); + flush_data(&records[0].ptr, + sizeof(uint64_t)); +#ifdef USE_PMDK +#ifdef FF_GC + ti->AddGarbageNode((void *)garbage); +#endif +#endif } continue; } @@ -2138,7 +1986,8 @@ char *btree::btree_search(char *key) { } page *t; - while ((t = (page *)p->linear_search(new_item, nullptr)) == p->hdr.sibling_ptr) { + while ((t = (page *)p->linear_search(new_item, nullptr)) == + p->hdr.sibling_ptr) { p = t; if (!p) { break; @@ -2165,8 +2014,8 @@ void btree::btree_update(uint64_t key, char *right) { TX_END #else value = new char[strlen(right) + 1]; - memcpy(value, right, strlen(right) + 1); - flush_data(value, strlen(right) + 1); + memcpy(value, right, strlen(right) + 1); + flush_data(value, strlen(right) + 1); #endif while (p->hdr.leftmost_ptr != nullptr) { @@ -2203,9 +2052,9 @@ void btree::btree_update(char *key, char *right) { } TX_END #else - value = new char[strlen(right) + 1]; - memcpy(value, right, strlen(right) + 1); - flush_data(value, strlen(right) + 1); + value = new char[strlen(right) + 1]; + memcpy(value, right, strlen(right) + 1); + flush_data(value, strlen(right) + 1); #endif while (p->hdr.leftmost_ptr != nullptr) { @@ -2213,7 +2062,8 @@ void btree::btree_update(char *key, char *right) { } page *t; - while ((t = (page *)p->linear_search(new_item, value)) == p->hdr.sibling_ptr) { + while ((t = (page *)p->linear_search(new_item, value)) == + p->hdr.sibling_ptr) { p = t; if (!p) { break; @@ -2243,7 +2093,7 @@ void btree::btree_insert(uint64_t key, char *right, #else char *value = new char[strlen(right) + 1]; memcpy(value, right, strlen(right) + 1); - flush_data(value, strlen(right) + 1); + flush_data(value, strlen(right) + 1); #endif } @@ -2278,9 +2128,9 @@ void btree::btree_insert(char *key, char *right, } TX_END #else - char *value = new char[strlen(right) + 1]; + char *value = new char[strlen(right) + 1]; memcpy(value, right, strlen(right) + 1); - flush_data(value, strlen(right) + 1); + flush_data(value, strlen(right) + 1); #endif } diff --git a/fast_fair/fast_fair_alloc.h b/fast_fair/fast_fair_alloc.h index c1b5e3c..4279b5f 100644 --- a/fast_fair/fast_fair_alloc.h +++ b/fast_fair/fast_fair_alloc.h @@ -113,7 +113,7 @@ class btree { char *btree_search(uint64_t); char *btree_search(char *); void btree_update(uint64_t key, char *right); - void btree_update(char * key, char *right); + void btree_update(char *key, char *right); void btree_search_range(uint64_t, uint64_t, unsigned long *, int, int &); void btree_search_range(char *, char *, unsigned long *, int, int &); key_item *make_key_item(char *, size_t, bool); @@ -2419,72 +2419,71 @@ char *btree::btree_search(char *key) { return (char *)t; } - void btree::btree_update(uint64_t key, char *right) { - ti->JoinEpoch(); - page *p = (page *)root; +void btree::btree_update(uint64_t key, char *right) { + ti->JoinEpoch(); + page *p = (page *)root; - char *value = right; + char *value = right; #ifdef USE_PMDK - TX_BEGIN(pmem_pool) { - pmemobj_tx_add_range_direct(&value, sizeof(uint64_t)); - PMEMoid p = pmemobj_tx_zalloc(strlen(right) + 1, TOID_TYPE_NUM(char)); - value = (char *)pmemobj_direct(p); - memcpy(value, right, strlen(right) + 1); - flush_data(value, strlen(right) + 1); - } - TX_END + TX_BEGIN(pmem_pool) { + pmemobj_tx_add_range_direct(&value, sizeof(uint64_t)); + PMEMoid p = pmemobj_tx_zalloc(strlen(right) + 1, TOID_TYPE_NUM(char)); + value = (char *)pmemobj_direct(p); + memcpy(value, right, strlen(right) + 1); + flush_data(value, strlen(right) + 1); + } + TX_END #endif - while (p->hdr.leftmost_ptr != nullptr) { - p = (page *)p->linear_search(key); - } + while (p->hdr.leftmost_ptr != nullptr) { + p = (page *)p->linear_search(key); + } - page *t; - while ((t = (page *)p->linear_search(key)) == p->hdr.sibling_ptr) { - p = t; - if (!p) { - break; - } + page *t; + while ((t = (page *)p->linear_search(key)) == p->hdr.sibling_ptr) { + p = t; + if (!p) { + break; } + } - if (t != nullptr) { - } - ti->LeaveEpoch(); + if (t != nullptr) { } + ti->LeaveEpoch(); +} - void btree::btree_update(char *key, char *right) { - ti->JoinEpoch(); - page *p = (page *)root; +void btree::btree_update(char *key, char *right) { + ti->JoinEpoch(); + page *p = (page *)root; - key_item *new_item = make_key_item(key, strlen(key) + 1, false); + key_item *new_item = make_key_item(key, strlen(key) + 1, false); - char *value = right; + char *value = right; #ifdef USE_PMDK - TX_BEGIN(pmem_pool) { - pmemobj_tx_add_range_direct(&value, sizeof(uint64_t)); - PMEMoid p = pmemobj_tx_zalloc(strlen(right) + 1, TOID_TYPE_NUM(char)); - value = (char *)pmemobj_direct(p); - memcpy(value, right, strlen(right) + 1); - flush_data(value, strlen(right) + 1); - } - TX_END + TX_BEGIN(pmem_pool) { + pmemobj_tx_add_range_direct(&value, sizeof(uint64_t)); + PMEMoid p = pmemobj_tx_zalloc(strlen(right) + 1, TOID_TYPE_NUM(char)); + value = (char *)pmemobj_direct(p); + memcpy(value, right, strlen(right) + 1); + flush_data(value, strlen(right) + 1); + } + TX_END #endif - while (p->hdr.leftmost_ptr != nullptr) { - p = (page *)p->linear_search(new_item); - } + while (p->hdr.leftmost_ptr != nullptr) { + p = (page *)p->linear_search(new_item); + } - page *t; - while ((t = (page *)p->linear_search(new_item)) == p->hdr.sibling_ptr) { - p = t; - if (!p) { - break; - } + page *t; + while ((t = (page *)p->linear_search(new_item)) == p->hdr.sibling_ptr) { + p = t; + if (!p) { + break; } - - ti->LeaveEpoch(); } + ti->LeaveEpoch(); +} // insert the key in the leaf node void btree::btree_insert(uint64_t key, char *right) { // need to be string