|
|
@ -12,17 +12,77 @@ |
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <atomic>
|
|
|
|
#include <thread>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "commander.hpp"
|
|
|
|
|
|
|
|
constexpr auto record_sync_freq = std::chrono::microseconds(500000); |
|
|
|
std::atomic<std::chrono::microseconds> last_cycle_ts; |
|
|
|
std::atomic<std::chrono::microseconds> last_cycle_durr; |
|
|
|
std::atomic<std::chrono::microseconds> max_cycle_durr; |
|
|
|
std::atomic<std::chrono::microseconds> avg_cycle_durr; |
|
|
|
std::atomic<bool> will_stop{false}; |
|
|
|
|
|
|
|
void sync_records_thread(const database& db) |
|
|
|
{ |
|
|
|
std::chrono::microseconds total{0}; |
|
|
|
uint16_t count = 0; |
|
|
|
do{ |
|
|
|
auto begin = std::chrono::high_resolution_clock::now(); |
|
|
|
fdatasync(db.records.fd_v()); |
|
|
|
auto durr = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - begin); |
|
|
|
total += durr; |
|
|
|
count++; |
|
|
|
auto avg = total/count; |
|
|
|
if(count>20) |
|
|
|
{ |
|
|
|
total -= avg; |
|
|
|
count--; |
|
|
|
} |
|
|
|
avg_cycle_durr.store(avg); |
|
|
|
last_cycle_durr.store(durr); |
|
|
|
if(max_cycle_durr.load() < durr) |
|
|
|
{ |
|
|
|
max_cycle_durr.store(durr); |
|
|
|
} |
|
|
|
if(durr<record_sync_freq) |
|
|
|
{ |
|
|
|
std::this_thread::sleep_for(record_sync_freq - durr); |
|
|
|
} |
|
|
|
}while(!will_stop); |
|
|
|
} |
|
|
|
|
|
|
|
enum class cleanup_type : size_t { |
|
|
|
normal = sizeof(received_data), |
|
|
|
complete = sizeof(received_bulk_data) |
|
|
|
}; |
|
|
|
|
|
|
|
template<cleanup_type mode> |
|
|
|
void buffer_cleanup(received_bulk_data& recv_impl) { |
|
|
|
constexpr size_t total = ((size_t)mode)/(((size_t)mode % 8 == 0) ? 8 : 4); |
|
|
|
|
|
|
|
for( |
|
|
|
size_t i = 0; |
|
|
|
i < total; |
|
|
|
i++ |
|
|
|
) |
|
|
|
{ |
|
|
|
if constexpr ((size_t)mode % 8 == 0) |
|
|
|
{ |
|
|
|
((uint64_t*)&recv_impl)[i] = 0; |
|
|
|
} else { |
|
|
|
((uint32_t*)&recv_impl)[i] = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int main( |
|
|
|
[[maybe_unused]] int argc, |
|
|
|
[[maybe_unused]] char** argv |
|
|
|
) |
|
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
CMD::commander cmd_args(argc, argv); |
|
|
|
|
|
|
|
std::string database_str = "/data/"; |
|
|
@ -179,17 +239,20 @@ int main( |
|
|
|
addr.sin_port = htons(db_port); |
|
|
|
memset((void*)&addr.sin_addr, 0, sizeof(addr.sin_addr)); |
|
|
|
bind(soc,(struct sockaddr*)&addr,sizeof(addr)); |
|
|
|
std::thread syncher(sync_records_thread, run_db); |
|
|
|
received_bulk_data recv_impl; |
|
|
|
buffer_cleanup<cleanup_type::complete>(recv_impl); |
|
|
|
|
|
|
|
do{ |
|
|
|
received_data recv; |
|
|
|
received_data& recv = *(received_data*)&recv_impl; |
|
|
|
sending_data reply; |
|
|
|
sockaddr_in client; |
|
|
|
socklen_t packet_sz; |
|
|
|
size_t reply_size; |
|
|
|
recvfrom( |
|
|
|
soc, |
|
|
|
(void*)&recv, |
|
|
|
sizeof(received_data), |
|
|
|
(void*)&recv_impl, |
|
|
|
sizeof(received_bulk_data), |
|
|
|
MSG_WAITFORONE, |
|
|
|
(struct sockaddr*)&client, |
|
|
|
&packet_sz |
|
|
@ -203,6 +266,7 @@ int main( |
|
|
|
reply.rep_id = recv.rep_id; |
|
|
|
reply.identifier.record_head.split.x = 1; |
|
|
|
reply_size = sizeof(reply.rep_id) + sizeof(reply.identifier.record_head.split.x); |
|
|
|
buffer_cleanup<cleanup_type::normal>(recv_impl); |
|
|
|
break; |
|
|
|
case db_op::read: |
|
|
|
{ |
|
|
@ -218,6 +282,7 @@ int main( |
|
|
|
{ |
|
|
|
reply_size = sizeof(reply.rep_id) + sizeof(reply.identifier); |
|
|
|
} |
|
|
|
buffer_cleanup<cleanup_type::normal>(recv_impl); |
|
|
|
} |
|
|
|
break; |
|
|
|
case db_op::write: |
|
|
@ -230,6 +295,7 @@ int main( |
|
|
|
std::cerr << "cluster overfull"<< std::endl; |
|
|
|
} |
|
|
|
reply_size = sizeof(reply.rep_id) + sizeof(reply.identifier); |
|
|
|
buffer_cleanup<cleanup_type::normal>(recv_impl); |
|
|
|
} |
|
|
|
break; |
|
|
|
// case db_op::sremove:
|
|
|
@ -239,6 +305,7 @@ int main( |
|
|
|
run_db.remove(recv.identifier); |
|
|
|
reply.identifier.record_head.split = recv.identifier; |
|
|
|
reply_size = sizeof(reply.rep_id) + sizeof(reply.identifier); |
|
|
|
buffer_cleanup<cleanup_type::normal>(recv_impl); |
|
|
|
} |
|
|
|
break; |
|
|
|
case db_op::stats: |
|
|
@ -253,15 +320,25 @@ int main( |
|
|
|
+ (*run_db.metadata).page_cnt |
|
|
|
- (*run_db.metadata).last_page; |
|
|
|
uint64_t cow_full = 0; |
|
|
|
uint64_t usable_records = 0; |
|
|
|
for(auto& elem : run_db.records) |
|
|
|
{ |
|
|
|
if(elem.second.timestamp == std::numeric_limits<uint64_t>::max()) |
|
|
|
if (elem.second.timestamp == std::numeric_limits<uint64_t>::max()) |
|
|
|
{ |
|
|
|
++cow_full; |
|
|
|
++usable_records; |
|
|
|
} else if(elem.second.timestamp == 0) { |
|
|
|
++usable_records; |
|
|
|
} |
|
|
|
} |
|
|
|
stats->cow_full = cow_full; |
|
|
|
stats->free_records = usable_records; |
|
|
|
stats->sync_rate_µs = record_sync_freq.count(); |
|
|
|
stats->sync_duration_µs = last_cycle_durr.load().count(); |
|
|
|
stats->max_sync_duration_µs = max_cycle_durr.load().count(); |
|
|
|
stats->avg_sync_duration_µs = avg_cycle_durr.load().count(); |
|
|
|
reply_size = sizeof(reply); |
|
|
|
buffer_cleanup<cleanup_type::normal>(recv_impl); |
|
|
|
} |
|
|
|
break; |
|
|
|
case db_op::sallocate: |
|
|
@ -269,6 +346,7 @@ int main( |
|
|
|
reply.rep_id = recv.rep_id; |
|
|
|
reply.identifier = run_db.try_allocate(recv.identifier); |
|
|
|
reply_size = sizeof(reply.rep_id) + sizeof(reply.identifier); |
|
|
|
buffer_cleanup<cleanup_type::normal>(recv_impl); |
|
|
|
} |
|
|
|
break; |
|
|
|
case db_op::sread: |
|
|
@ -285,6 +363,7 @@ int main( |
|
|
|
{ |
|
|
|
reply_size = sizeof(reply.rep_id) + sizeof(reply.identifier); |
|
|
|
} |
|
|
|
buffer_cleanup<cleanup_type::normal>(recv_impl); |
|
|
|
} |
|
|
|
break; |
|
|
|
case db_op::swrite: |
|
|
@ -297,6 +376,7 @@ int main( |
|
|
|
std::cerr << "cluster overfull"<< std::endl; |
|
|
|
} |
|
|
|
reply_size = sizeof(reply.rep_id) + sizeof(reply.identifier); |
|
|
|
buffer_cleanup<cleanup_type::normal>(recv_impl); |
|
|
|
} |
|
|
|
break; |
|
|
|
case db_op::confirm: |
|
|
@ -304,6 +384,7 @@ int main( |
|
|
|
reply.rep_id = recv.rep_id; |
|
|
|
run_db.confirm(recv.identifier, *(bitops::regulated<uint64_t>*)&recv.page); |
|
|
|
reply_size = sizeof(reply.rep_id); |
|
|
|
buffer_cleanup<cleanup_type::normal>(recv_impl); |
|
|
|
} |
|
|
|
break; |
|
|
|
default: |
|
|
|