diff --git a/Makefile b/Makefile index c605a84..572cacd 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ # -CXX := -clang++ +CXX := -g++ DEBUG := -g -O0 -DUNITTEST RELEASE := -s -O3 -fno-rtti diff --git a/include/database.hpp b/include/database.hpp index 78bf0b2..ce8dd1c 100644 --- a/include/database.hpp +++ b/include/database.hpp @@ -95,7 +95,14 @@ public: #pragma GCC diagnostic pop } - void write(const record_identifier& target, const db_page& value){ + /************************************************************************** + * * + * NO CONFIRM OPS * + * * + * * + *************************************************************************/ + + record write(const record_identifier& target, const db_page& value){ uint64_t page = std::numeric_limits::max();; size_t off = std::numeric_limits::max(); if(metadata[0].last_delete>0) @@ -127,6 +134,7 @@ public: tmp.second.record_head.split = target; tmp.second.timestamp = ts; tmp.second.offset = page; + tmp.second.flags = (uint32_t)record_flags::confirmation; do{ uint64_t pos = hashed_roll % records.size(); @@ -151,11 +159,11 @@ public: } else { (*metadata).last_page += (size_t)1; } + return tmp.second; } - std::pair read(const record_identifier& target) { - std::pair ret; - ret.first = 0; + std::pair read(const record_identifier& target) { + std::pair ret; ret.second.fill(0); uint64_t hashed = std::hash{}(target); @@ -174,9 +182,9 @@ public: if(records[pos].first == hashed) if(std::hash{}(value.record_head.split) == hashed) { - if(ret.first::max();; + size_t off = std::numeric_limits::max(); + if(metadata[0].last_delete>0) + { + off = (*metadata).last_delete; + page = delete_table[off-1]; + } else { + page = (*metadata).last_page; + if(page>=pages.size()) { + throw std::runtime_error("PAGE STARVATION! MUST EXIT NOW"); + } + } + + if(page == std::numeric_limits::max()) + { + throw std::runtime_error("PAGE ERROR! MUST EXIT NOW"); + } + + pages[page] = value; + + uint64_t hashed = std::hash{}(target); + uint64_t hashed_roll = hashed; + bool succeed = false; + + + uint64_t ts = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + std::pair,record> tmp{0, record{}}; + tmp.first = hashed; + tmp.second.record_head.split = target; + tmp.second.timestamp = ts; + tmp.second.offset = page; + tmp.second.flags = 0; + do{ + uint64_t pos = hashed_roll % records.size(); + + switch (static_cast(records[pos].second.timestamp)) { + case 0: + [[fallthrough]]; + case std::numeric_limits::max(): + records[pos] = tmp; + succeed = true; + break; + default: + break; + } + + hashed_roll++; + }while(!succeed); + + if(off != std::numeric_limits::max()) + { + (*metadata).last_delete += -1; + delete_table[off] = std::numeric_limits::max(); + } else { + (*metadata).last_page += (size_t)1; + } + return tmp.second; + } + + std::pair stepped_read(const record_identifier& target) { + std::pair ret; + ret.second.fill(0); + + uint64_t hashed = std::hash{}(target); + uint64_t hashed_roll = hashed; + + do{ + uint64_t pos = hashed_roll % records.size(); + + auto& value = records[pos].second; + switch (static_cast(value.timestamp)) { + case 0: + return ret; + case std::numeric_limits::max(): + break; + default: + if(records[pos].first == hashed) + if(std::hash{}(value.record_head.split) == hashed) + { + if(static_cast(value.flags) & (uint32_t)record_flags::confirmation) + if(ret.first.timestamp& timestamp) { + uint64_t hashed = std::hash{}(target); + uint64_t hashed_roll = hashed; + + do{ + uint64_t pos = hashed_roll % records.size(); + + auto& value = records[pos].second; + switch (static_cast(value.timestamp)) { + case 0: + return; + case std::numeric_limits::max(): + break; + default: + if(records[pos].first == hashed) + if(std::hash{}(value.record_head.split) == hashed) + { + if(timestamp == value.timestamp) + { + value.flags = (uint32_t)value.flags | (uint32_t)record_flags::confirmation; + } + break; + } + } + + hashed_roll++; + }while(true); + } }; \ No newline at end of file diff --git a/include/endian.hpp b/include/endian.hpp index 5cd965f..39e5330 100644 --- a/include/endian.hpp +++ b/include/endian.hpp @@ -73,7 +73,7 @@ namespace bitops{ internal = swap_if_little(T(*this)+v); } - constexpr operator T() { + constexpr operator T() const { return swap_if_little(internal); } }; diff --git a/include/fsized_map.h b/include/fsized_map.h index 9f4ea08..c0437aa 100644 --- a/include/fsized_map.h +++ b/include/fsized_map.h @@ -36,10 +36,10 @@ struct [[gnu::packed]] record_identifier{ template<> struct std::hash { uint64_t operator() (const record_identifier& value) { - uint64_t v = *(uint32_t*)&value.x.internal; + uint64_t v = static_cast(value.x); v <<= 4; - v += *(uint32_t*)&value.y.internal; + v += static_cast(value.y); v ^= *(uint64_t*)&value.uuid; v ^= *(((uint64_t*)&value.uuid)+1); @@ -47,15 +47,20 @@ struct std::hash { } }; -struct record{ +enum class record_flags : uint32_t { + confirmation = 1 +}; + +struct [[gnu::packed]] record{ record() {} - union{ + union [[gnu::packed]] { std::array full; record_identifier split = record_identifier(); } record_head; bitops::regulated timestamp = 0; - size_t offset = 0; + bitops::regulated offset = 0; + bitops::regulated flags = 0; }; using db_page = std::array; diff --git a/include/network.hpp b/include/network.hpp index 73ac0ee..972ebbb 100644 --- a/include/network.hpp +++ b/include/network.hpp @@ -20,7 +20,7 @@ struct [[gnu::packed]] received_data { struct [[gnu::packed]] sending_data { bitops::regulated rep_id = 0; - record_identifier identifier = record_identifier{}; + record identifier = record{}; db_page page = {0}; }; diff --git a/src/izaro-storage.cpp b/src/izaro-storage.cpp index 8f83d74..0b3cc62 100644 --- a/src/izaro-storage.cpp +++ b/src/izaro-storage.cpp @@ -202,16 +202,16 @@ int main( { case db_op::version: reply.rep_id = recv.rep_id; - reply.identifier.x = 1; - reply_size = sizeof(reply.rep_id) + sizeof(reply.identifier.x); + reply.identifier.record_head.split.x = 1; + reply_size = sizeof(reply.rep_id) + sizeof(reply.identifier.record_head.split.x); break; case db_op::read: { reply.rep_id = recv.rep_id; auto req = run_db.read(recv.identifier); - if(req.first != 0) + if(req.first.timestamp != 0) { - reply.identifier = recv.identifier; + reply.identifier = req.first; reply.page = req.second; reply_size = sizeof(reply); } @@ -225,8 +225,8 @@ int main( { reply.rep_id = recv.rep_id; try{ - run_db.write(recv.identifier, recv.page); - reply.identifier = recv.identifier; + auto req = run_db.write(recv.identifier, recv.page); + reply.identifier = req; } catch (...) { std::cerr << "cluster overfull"<< std::endl; } @@ -237,7 +237,7 @@ int main( { reply.rep_id = recv.rep_id; run_db.remove(recv.identifier); - reply.identifier = recv.identifier; + reply.identifier.record_head.split = recv.identifier; reply_size = sizeof(reply.rep_id) + sizeof(reply.identifier); } break;