#include <iostream>
|
|
#include <fstream>
|
|
#include <sstream>
|
|
#include <variant>
|
|
#include <chrono>
|
|
#include <algorithm>
|
|
#include "database.hpp"
|
|
#include "network.hpp"
|
|
#include <memory>
|
|
#include <cstdlib>
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <netinet/in.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include "commander.hpp"
|
|
|
|
|
|
int main(
|
|
[[maybe_unused]] int argc,
|
|
[[maybe_unused]] char** argv
|
|
)
|
|
{
|
|
|
|
|
|
CMD::commander cmd_args(argc, argv);
|
|
|
|
std::string database_str = "/data/";
|
|
|
|
if(cmd_args.isFlagSet("-database"))
|
|
{
|
|
database_str = cmd_args.getFlagValue("-database");
|
|
}
|
|
|
|
std::string utest_str = "/tmp/";
|
|
|
|
if(cmd_args.isFlagSet("-utest"))
|
|
{
|
|
utest_str = cmd_args.getFlagValue("-utest");
|
|
}
|
|
|
|
size_t database_size = 4096;
|
|
|
|
if(cmd_args.isFlagSet("-page-count"))
|
|
{
|
|
try{
|
|
database_size = std::stoll(cmd_args.getFlagValue("-page-count"));
|
|
} catch (...) {
|
|
std::cerr << "Invalid page-count value" << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
}
|
|
|
|
size_t utest_size = 4096;
|
|
|
|
if(cmd_args.isFlagSet("-utest-count"))
|
|
{
|
|
try{
|
|
utest_size = std::stoll(cmd_args.getFlagValue("-utest-count"));
|
|
} catch (...) {
|
|
std::cerr << "Invalid utest-count value" << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
}
|
|
|
|
#ifdef UNITTEST
|
|
{
|
|
database db(database::create(utest_str, utest_size*2));
|
|
|
|
db_page v;
|
|
v.fill(1);
|
|
|
|
record_identifier tar;
|
|
|
|
auto begin = std::chrono::high_resolution_clock::now();
|
|
|
|
for(size_t idx=0;idx<utest_size;idx++)
|
|
{
|
|
tar.y.internal = idx;
|
|
db.write(tar, v);
|
|
}
|
|
|
|
auto durr = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - begin)/utest_size;
|
|
|
|
std::cerr << "durr/elem = " << durr.count() << "ns/op" << std::endl;
|
|
|
|
auto a = db.read(tar);
|
|
|
|
if(a.second[0] != 1) {
|
|
std::cerr << "read failed" << std::endl;
|
|
}
|
|
|
|
db.remove(tar);
|
|
|
|
a = db.read(tar);
|
|
if(a.second[0] == 1) {
|
|
std::cerr << "remove failed" << std::endl;
|
|
}
|
|
|
|
{
|
|
db.write(tar, v);
|
|
a = db.read(tar);
|
|
if(a.second[0] != 1) {
|
|
std::cerr << "read failed" << std::endl;
|
|
}
|
|
db.remove(tar);
|
|
a = db.read(tar);
|
|
if(a.second[0] != 0) {
|
|
std::cerr << "remove failed" << std::endl;
|
|
}
|
|
v.fill(2);
|
|
db.write(tar, v);
|
|
}
|
|
|
|
database reop(database::open(utest_str));
|
|
|
|
{
|
|
a = reop.read(tar);
|
|
|
|
if(a.second[0] != 2) {
|
|
std::cerr << "reopen read failed" << std::endl;
|
|
}
|
|
|
|
v.fill(3);
|
|
|
|
reop.write(tar, v);
|
|
|
|
a = reop.read(tar);
|
|
if(a.second[0] != 3) {
|
|
std::cerr << "reopen write failed" << std::endl;
|
|
}
|
|
}
|
|
reop.pages.clear();
|
|
reop.metadata.clear();
|
|
reop.records.clear();
|
|
reop.delete_table.clear();
|
|
|
|
db.pages.clear();
|
|
db.metadata.clear();
|
|
db.records.clear();
|
|
db.delete_table.clear();
|
|
}
|
|
#endif
|
|
|
|
|
|
if(cmd_args.isFlagSet("-create"))
|
|
{
|
|
try{
|
|
database creat(database::create(database_str, database_size));
|
|
std::cout << "Created" << std::endl;
|
|
return 0;
|
|
} catch (...) {
|
|
std::cerr << "Creating of " << database_str << " of " << database_size << " pages failed" << std::endl;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
try{
|
|
|
|
database run_db(database::open(database_str));
|
|
auto soc = socket(AF_INET, SOCK_DGRAM, 0);
|
|
struct sockaddr_in addr;
|
|
addr.sin_family = AF_INET;
|
|
addr.sin_port = htons(20450);
|
|
memset((void*)&addr.sin_addr, 0, sizeof(addr.sin_addr));
|
|
bind(soc,(struct sockaddr*)&addr,sizeof(addr));
|
|
|
|
do{
|
|
received_data recv;
|
|
sending_data reply;
|
|
sockaddr_in client;
|
|
socklen_t packet_sz;
|
|
size_t reply_size;
|
|
recvfrom(
|
|
soc,
|
|
(void*)&recv,
|
|
sizeof(received_data),
|
|
MSG_WAITFORONE,
|
|
(struct sockaddr*)&client,
|
|
&packet_sz
|
|
);
|
|
|
|
if(packet_sz < sizeof(db_op)) continue;
|
|
|
|
switch (static_cast<db_op>(recv.op))
|
|
{
|
|
case db_op::version:
|
|
reply.rep_id = recv.rep_id;
|
|
reply.identifier.x = 1;
|
|
reply_size = sizeof(reply.rep_id) + sizeof(reply.identifier.x);
|
|
break;
|
|
case db_op::read:
|
|
{
|
|
reply.rep_id = recv.rep_id;
|
|
auto req = run_db.read(recv.identifier);
|
|
if(req.first != 0)
|
|
{
|
|
reply.identifier = recv.identifier;
|
|
reply.page = req.second;
|
|
reply_size = sizeof(reply);
|
|
}
|
|
else
|
|
{
|
|
reply_size = sizeof(reply.rep_id) + sizeof(reply.identifier);
|
|
}
|
|
}
|
|
break;
|
|
case db_op::write:
|
|
{
|
|
reply.rep_id = recv.rep_id;
|
|
try{
|
|
run_db.write(recv.identifier, recv.page);
|
|
reply.identifier = recv.identifier;
|
|
} catch (...) {
|
|
std::cerr << "cluster overfull"<< std::endl;
|
|
}
|
|
reply_size = sizeof(reply.rep_id) + sizeof(reply.identifier);
|
|
}
|
|
break;
|
|
case db_op::remove:
|
|
{
|
|
reply.rep_id = recv.rep_id;
|
|
run_db.remove(recv.identifier);
|
|
reply.identifier = recv.identifier;
|
|
reply_size = sizeof(reply.rep_id) + sizeof(reply.identifier);
|
|
}
|
|
break;
|
|
default:
|
|
std::cerr << "bad_request " << (uint32_t)static_cast<db_op>(recv.op) << std::endl;
|
|
continue;
|
|
break;
|
|
}
|
|
sendto(
|
|
soc,
|
|
(void*)&reply,
|
|
reply_size,
|
|
0,
|
|
(struct sockaddr*)&client,
|
|
(socklen_t)sizeof(client)
|
|
);
|
|
//std::cerr << "reply to " << (uint32_t)static_cast<db_op>(recv.op) << std::endl;
|
|
}while(true);
|
|
} catch (...) {
|
|
std::cerr << "GoJDB crashed !" << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
}
|