|
|
@ -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<uint64_t>::max();; |
|
|
|
size_t off = std::numeric_limits<size_t>::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<uint64_t, db_page> read(const record_identifier& target) { |
|
|
|
std::pair<uint64_t, db_page> ret; |
|
|
|
ret.first = 0; |
|
|
|
std::pair<record, db_page> read(const record_identifier& target) { |
|
|
|
std::pair<record, db_page> ret; |
|
|
|
ret.second.fill(0); |
|
|
|
|
|
|
|
uint64_t hashed = std::hash<record_identifier>{}(target); |
|
|
@ -174,9 +182,9 @@ public: |
|
|
|
if(records[pos].first == hashed) |
|
|
|
if(std::hash<record_identifier>{}(value.record_head.split) == hashed) |
|
|
|
{ |
|
|
|
if(ret.first<value.timestamp) |
|
|
|
if(ret.firstp">.timestamp<value.timestamp) |
|
|
|
{ |
|
|
|
ret.first = value.timestamp; |
|
|
|
ret.first = value; |
|
|
|
ret.second = pages[value.offset]; |
|
|
|
} |
|
|
|
break; |
|
|
@ -220,4 +228,139 @@ public: |
|
|
|
void rollback(const record_identifier&) { |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
* * |
|
|
|
* CONFIRM OPS * |
|
|
|
* * |
|
|
|
* * |
|
|
|
*************************************************************************/ |
|
|
|
|
|
|
|
record stepped_write(const record_identifier& target, const db_page& value){ |
|
|
|
uint64_t page = std::numeric_limits<uint64_t>::max();; |
|
|
|
size_t off = std::numeric_limits<size_t>::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<uint64_t>::max()) |
|
|
|
{ |
|
|
|
throw std::runtime_error("PAGE ERROR! MUST EXIT NOW"); |
|
|
|
} |
|
|
|
|
|
|
|
pages[page] = value; |
|
|
|
|
|
|
|
uint64_t hashed = std::hash<record_identifier>{}(target); |
|
|
|
uint64_t hashed_roll = hashed; |
|
|
|
bool succeed = false; |
|
|
|
|
|
|
|
|
|
|
|
uint64_t ts = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch()).count(); |
|
|
|
std::pair<bitops::regulated<uint64_t>,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<uint64_t>(records[pos].second.timestamp)) { |
|
|
|
case 0: |
|
|
|
[[fallthrough]]; |
|
|
|
case std::numeric_limits<uint64_t>::max(): |
|
|
|
records[pos] = tmp; |
|
|
|
succeed = true; |
|
|
|
break; |
|
|
|
default: |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
hashed_roll++; |
|
|
|
}while(!succeed); |
|
|
|
|
|
|
|
if(off != std::numeric_limits<size_t>::max()) |
|
|
|
{ |
|
|
|
(*metadata).last_delete += -1; |
|
|
|
delete_table[off] = std::numeric_limits<size_t>::max(); |
|
|
|
} else { |
|
|
|
(*metadata).last_page += (size_t)1; |
|
|
|
} |
|
|
|
return tmp.second; |
|
|
|
} |
|
|
|
|
|
|
|
std::pair<record, db_page> stepped_read(const record_identifier& target) { |
|
|
|
std::pair<record, db_page> ret; |
|
|
|
ret.second.fill(0); |
|
|
|
|
|
|
|
uint64_t hashed = std::hash<record_identifier>{}(target); |
|
|
|
uint64_t hashed_roll = hashed; |
|
|
|
|
|
|
|
do{ |
|
|
|
uint64_t pos = hashed_roll % records.size(); |
|
|
|
|
|
|
|
auto& value = records[pos].second; |
|
|
|
switch (static_cast<uint64_t>(value.timestamp)) { |
|
|
|
case 0: |
|
|
|
return ret; |
|
|
|
case std::numeric_limits<uint64_t>::max(): |
|
|
|
break; |
|
|
|
default: |
|
|
|
if(records[pos].first == hashed) |
|
|
|
if(std::hash<record_identifier>{}(value.record_head.split) == hashed) |
|
|
|
{ |
|
|
|
if(static_cast<uint32_t>(value.flags) & (uint32_t)record_flags::confirmation) |
|
|
|
if(ret.first.timestamp<value.timestamp) |
|
|
|
{ |
|
|
|
ret.first = value; |
|
|
|
ret.second = pages[value.offset]; |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
hashed_roll++; |
|
|
|
}while(true); |
|
|
|
return ret; |
|
|
|
} |
|
|
|
|
|
|
|
void stepped_remove(const record_identifier& target) { |
|
|
|
remove(target); |
|
|
|
} |
|
|
|
|
|
|
|
void confirm(const record_identifier& target, const bitops::regulated<uint64_t>& timestamp) { |
|
|
|
uint64_t hashed = std::hash<record_identifier>{}(target); |
|
|
|
uint64_t hashed_roll = hashed; |
|
|
|
|
|
|
|
do{ |
|
|
|
uint64_t pos = hashed_roll % records.size(); |
|
|
|
|
|
|
|
auto& value = records[pos].second; |
|
|
|
switch (static_cast<uint64_t>(value.timestamp)) { |
|
|
|
case 0: |
|
|
|
return; |
|
|
|
case std::numeric_limits<uint64_t>::max(): |
|
|
|
break; |
|
|
|
default: |
|
|
|
if(records[pos].first == hashed) |
|
|
|
if(std::hash<record_identifier>{}(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); |
|
|
|
} |
|
|
|
}; |