Goddess of Justice DB, the database used for storage on IzaroDFS
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

250 lines
5.1 KiB

#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;
}
}