Browse Source

Works

master
Ludovic 'Archivist' Lagouardette 5 years ago
parent
commit
0c1d77af6b
12 changed files with 787 additions and 13643 deletions
  1. +2
    -1
      .gitignore
  2. +1
    -1
      .gitmodules
  3. +20
    -8
      Makefile
  4. +1
    -0
      README.md
  5. +0
    -13478
      include/catch.hpp
  6. +221
    -0
      include/database.hpp
  7. +80
    -0
      include/endian.hpp
  8. +188
    -0
      include/fsized_map.h
  9. +24
    -0
      include/network.hpp
  10. +159
    -154
      src/izaro-storage.cpp
  11. +90
    -0
      src/test_client.cpp
  12. +1
    -1
      tiny-js

+ 2
- 1
.gitignore View File

@ -1,2 +1,3 @@
*.orig
build/apps/sh_render
build/*
vgcore.*

+ 1
- 1
.gitmodules View File

@ -6,4 +6,4 @@
url = https://github.com/nlohmann/json
[submodule "tiny-js"]
path = tiny-js
url = https://github.com/gfwilliams/tiny-js
url = https://github.com/Zenohate/tiny-js

+ 20
- 8
Makefile View File

@ -19,35 +19,47 @@
#
CXX := -c++
CXXFLAGS := -pedantic-errors -Wall -Wextra -Werror -g -std=c++17
LDFLAGS := -L/usr/lib -lstdc++ -lm -lpthread -lGL -lGLEW -lglfw
CXX := -clang++
DEBUG := -g -O2 -DUNITTEST
RELEASE := -s -O3 -fno-rtti
CXXFLAGS := $(DEBUG) -Wno-unknown-warning-option -Wno-address-of-packed-member -pedantic-errors -Wall -Wextra -Werror -Wfatal-errors -std=c++17 -m64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
LDFLAGS := -L/usr/lib
BUILD := build
OBJ_DIR := $(BUILD)/objects
APP_DIR := $(BUILD)/apps
TARGET := izaro-storage.cpp
INCLUDE := -Iinclude/ -I./CommandEr/src -I./json/single_include
INCLUDE := -Iinclude/ -I./CommandEr/src -I./json/single_include -Itiny-js/
SRC := \
TJS_SRC :=
#pool_allocator.cpp TinyJS.cpp TinyJS_Functions.cpp TinyJS_MathFunctions.cpp TinyJS_StringFunctions.cpp TinyJS_Threading.cpp
TJS_OBJECTS := $(TJS_SRC:%.cpp=$(OBJ_DIR)/%.tjs.o)
OBJECTS := $(SRC:%.cpp=$(OBJ_DIR)/%.o) ./CommandEr/build/commander.o
OBJECTS := $(SRC:%.cpp=$(OBJ_DIR)/%.o)
TEST_OBJECTS := $(SRC:%.cpp=$(OBJ_DIR)/%.test.o)
TARGETNAME := $(TARGET:%.cpp=%)
all: build $(TARGET)
$(OBJ_DIR)/%.tjs.o: tiny-js/%.cpp
@mkdir -p $(@D)
$(CXX) $(CXXFLAGS) -fpermissive -w -Wno-pedantic $(INCLUDE) -o $@ -c $<
$(OBJ_DIR)/%.test.o: %.cpp
@mkdir -p $(@D)
$(CXX) $(CXXFLAGS) -fopenmp -DUSE_CATCH $(INCLUDE) -o $@ -c $<
$(CXX) $(CXXFLAGS) -DUSE_CATCH $(INCLUDE) -o $@ -c $<
$(OBJ_DIR)/%.o: %.cpp
@mkdir -p $(@D)
$(CXX) $(CXXFLAGS) $(INCLUDE) -o $@ -c $<
$(TARGET): $(OBJECTS) build
$(TARGET): $(OBJECTS) k">$(TJS_OBJECTS) build
make -C CommandEr
@mkdir -p $(@D)
$(CXX) -fopenmp $(CXXFLAGS) $(INCLUDE) $(LDFLAGS) -o $(APP_DIR)/$(TARGETNAME) src/$(TARGET) $(OBJECTS)
$(CXX) $(CXXFLAGS) $(INCLUDE) $(LDFLAGS) -o $(APP_DIR)/$(TARGETNAME) src/$(TARGET) $(OBJECTS) $(TJS_OBJECTS)
$(CXX) $(CXXFLAGS) $(INCLUDE) $(LDFLAGS) -o $(APP_DIR)/test_client src/test_client.cpp
.PHONY: all build clean

+ 1
- 0
README.md View File

@ -0,0 +1 @@
# sh_render

+ 0
- 13478
include/catch.hpp
File diff suppressed because it is too large
View File


+ 221
- 0
include/database.hpp View File

@ -0,0 +1,221 @@
#pragma once
#include "fsized_map.h"
#include <chrono>
struct metadata_t{
bitops::regulated<uint64_t> record_cnt;
bitops::regulated<uint64_t> page_cnt;
bitops::regulated<uint64_t> delete_cnt;
bitops::regulated<uint64_t> last_page;
bitops::regulated<uint64_t> last_delete;
};
class database {
database(){}
public:
mmap_array<std::pair<bitops::regulated<uint64_t>, record>> records;
mmap_array<db_page> pages;
mmap_array<metadata_t> metadata;
mmap_array<size_t> delete_table;
database(
const std::string& records,
const std::string& pages,
const std::string& deletions,
const std::string& meta,
const size_t& record_cnt = 4096,
const size_t& page_cnt = 4096,
const size_t& delete_cnt = 512
)
: records{record_cnt, records}
, pages{page_cnt, pages}
, metadata{(size_t)1, meta}
, delete_table{delete_cnt, deletions}
{}
static database&& create(const std::string dir, size_t page_nb) {
database ret{
dir+"records",
dir+"pages",
dir+"deleted",
dir+"meta",
page_nb+page_nb/2,
page_nb,
page_nb/8
};
for(auto& n : ret.records)
{
n.second.timestamp = 0;
n.second.offset = 0;
}
for(auto& n : ret.delete_table)
{
n = std::numeric_limits<size_t>::max();
}
(*ret.metadata).last_page = 0;
(*ret.metadata).last_delete = 0;
(*ret.metadata).record_cnt = page_nb+page_nb/2;
(*ret.metadata).page_cnt = page_nb;
(*ret.metadata).delete_cnt = page_nb/8;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wreturn-local-addr"
return std::move(ret);
#pragma GCC diagnostic pop
}
static database&& open(const std::string dir) {
mmap_array<metadata_t> tmp{(size_t)1, dir+"meta"};
database ret{
dir+"records",
dir+"pages",
dir+"deleted",
dir+"meta",
(*tmp).record_cnt,
(*tmp).page_cnt,
(*tmp).delete_cnt
};
tmp.clear();
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wreturn-local-addr"
return std::move(ret);
#pragma GCC diagnostic pop
}
void 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;
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;
}
}
std::pair<uint64_t, db_page> read(const record_identifier& target) {
std::pair<uint64_t, db_page> ret;
ret.first = 0;
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(ret.first<value.timestamp)
{
ret.first = value.timestamp;
ret.second = pages[value.offset];
}
break;
}
}
hashed_roll++;
}while(true);
return ret;
}
void remove(const record_identifier& target) {
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)
{
value.timestamp = std::numeric_limits<uint64_t>::max();
(*metadata).last_delete+=1;
delete_table[(*metadata).last_delete-1] = value.offset;
value.offset = 0;
break;
}
}
hashed_roll++;
}while(true); // return only happens on hitting a case 0
}
void rollback(const record_identifier&) {
}
};

+ 80
- 0
include/endian.hpp View File

@ -0,0 +1,80 @@
#pragma once
#include <stdint.h>
#include <stddef.h>
#include <array>
#include <algorithm>
#if __cplusplus <= 201703L
namespace _hidden{
enum class endian
{
#ifdef _WIN32
little = 0,
big = 1,
native = little
#else
little = __ORDER_LITTLE_ENDIAN__,
big = __ORDER_BIG_ENDIAN__,
native = __BYTE_ORDER__
#endif
};
}
namespace bitops{
using endian = _hidden::endian;
}
#else
#include <type_traits>
namespace bitops{
using endian = std::endian;
}
#endif
namespace bitops{
template<typename T, size_t sz = sizeof(T)>
constexpr std::array<uint8_t,sizeof(T)> swap_if_little_raw(T xsz)
{
std::array<uint8_t,sizeof(T)> ret = {0};
auto abstract = (std::array<uint8_t,sizeof(T)>*)&xsz;
if constexpr (endian::native == endian::little)
{
std::copy(abstract->rbegin(), abstract->rend(), ret.begin());
}
else
{
std::copy(abstract->begin(), abstract->end(), ret.begin());
}
return ret;
}
template<typename T, size_t sz = sizeof(T)>
constexpr T swap_if_little(T xsz)
{
auto tmp = swap_if_little_raw(xsz);
return *(T*)&tmp;
}
template<typename T>
struct [[gnu::packed]] regulated{
T internal = 0;
constexpr regulated(T value)
: internal{swap_if_little(value)}
{ }
constexpr void operator=(T value)
{
internal = swap_if_little(value);
}
constexpr void operator+=(const int& v)
{
internal = swap_if_little(T(*this)+v);
}
constexpr operator T() {
return swap_if_little(internal);
}
};
}

+ 188
- 0
include/fsized_map.h View File

@ -0,0 +1,188 @@
#pragma once
#include <stdint.h>
#include <endian.hpp>
#include <string>
#include <iostream>
#include <assert.h>
// Unix-y stuff
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
struct errno_exception : public std::runtime_error {
errno_exception(int err)
: runtime_error{std::string{"errno with value "}+std::to_string(err)}
{}
};
void throw_errno_if(bool pred)
{
if(pred)
{
throw errno_exception{errno};
}
}
constexpr size_t page_size = 4096;
struct [[gnu::packed]] record_identifier{
bitops::regulated<uint32_t> x = 0;
bitops::regulated<uint32_t> y = 0;
std::array<uint8_t, 16> uuid = {0};
};
template<>
struct std::hash<record_identifier> {
uint64_t operator() (const record_identifier& value) {
uint64_t v = *(uint32_t*)&value.x.internal;
v <<= 4;
v += *(uint32_t*)&value.y.internal;
v ^= *(uint64_t*)&value.uuid;
v ^= *(((uint64_t*)&value.uuid)+1);
return v;
}
};
struct record{
record()
{}
union{
std::array<uint8_t, 24> full;
record_identifier split = record_identifier();
} record_head;
bitops::regulated<uint64_t> timestamp = 0;
size_t offset = 0;
};
using db_page = std::array<uint8_t, 16384>;
template<typename T>
struct mmap_ptr{
T* start = nullptr;
size_t offset = 0;
T& operator*(){
return start[offset];
}
T& operator[](const size_t& n){
return start[offset+n];
}
mmap_ptr operator+(size_t offset) {
mmap_ptr ret;
ret.start = start;
ret.offset = offset + this->offset;
return ret;
}
mmap_ptr operator++() {
offset+=1;
mmap_ptr ret = *this;
return ret;
}
mmap_ptr operator++(int) {
mmap_ptr ret = *this;
offset+=1;
return ret;
}
bool operator==(const mmap_ptr& oth) {
return (start == oth.start) && (offset == oth.offset);
}
bool operator!=(const mmap_ptr& oth) {
return !(*this == oth);
}
};
template<typename T>
class mmap_array : public mmap_ptr<T>
{
size_t mapping_size = 0;
int fd = 0;
size_t item_size = 0;
public:
mmap_array() = default;
mmap_array(size_t nb_elem, const std::string& filename)
: mmap_ptr<T>() {
const size_t expected_size = nb_elem*sizeof(T);
const size_t expected_size_mod = expected_size + (
(expected_size%page_size != 0)?
page_size - expected_size%page_size
: 0
);
fd = open(
filename.c_str(),
O_RDWR | O_CREAT,
S_ISUID + S_ISGID + S_IRUSR + S_IWUSR + S_IRGRP + S_IWGRP
);
throw_errno_if(fd < 0);
struct stat data;
int status = fstat(fd, &data);
throw_errno_if(status < 0);
if((size_t)data.st_size < expected_size_mod)
{
status = ftruncate(fd, expected_size_mod);
throw_errno_if(status < 0);
}
this->start = (T*)mmap(NULL, expected_size_mod, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
throw_errno_if(this->start == nullptr);
mapping_size = expected_size_mod;
item_size = mapping_size / sizeof(T);
auto map_access = MADV_RANDOM;
if(expected_size_mod <= 1 << 20) {
map_access |= MADV_WILLNEED;
}
#ifdef MADV_DONTDUMP
map_access |= MADV_DONTDUMP;
#endif
this->offset = 0;
posix_madvise(this->start, mapping_size, map_access);
}
constexpr size_t size() {
return item_size;
}
constexpr mmap_ptr<T> begin() const {
mmap_ptr<T> ret = *this;
return ret;
}
constexpr mmap_ptr<T> end() const {
mmap_ptr<T> ret = *this;
return ret+item_size;
}
void clear() {
munmap(this->start, mapping_size);
close(fd);
}
~mmap_array() {
//std::cerr << "unmapping disabled" << std::endl;
if(false)//this->start != nullptr)
{
munmap(this->start, mapping_size);
close(fd);
}
}
};

+ 24
- 0
include/network.hpp View File

@ -0,0 +1,24 @@
#pragma once
#include "endian.hpp"
#include "database.hpp"
enum class db_op : uint32_t {
version = 0,
read = 1,
write = 2,
remove = 3
};
struct [[gnu::packed]] received_data {
bitops::regulated<db_op> op = db_op::version;
bitops::regulated<uint64_t> rep_id = 0;
record_identifier identifier = record_identifier{};
db_page page = {0};
};
struct [[gnu::packed]] sending_data {
bitops::regulated<uint64_t> rep_id = 0;
record_identifier identifier = record_identifier{};
db_page page = {0};
};

+ 159
- 154
src/izaro-storage.cpp View File

@ -3,179 +3,184 @@
#include <sstream>
#include <variant>
#include <chrono>
#include "commander.hpp"
#include "nlohmann/json.hpp"
#include <GL/glew.h>
#define GLFW_DLL
#include <GLFW/glfw3.h>
std::variant<std::array<float,18>, std::vector<float>> points = std::array<float,18> {
-1.0f, 1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f
};
std::string check_shader(GLuint shader)
#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>
int main(
[[maybe_unused]] int argc,
[[maybe_unused]] char** argv
)
{
std::array<char,4096> text_buffer;
GLsizei size;
glGetShaderInfoLog(shader, text_buffer.size(),&size,text_buffer.data());
return std::string{text_buffer.begin(), text_buffer.begin()+size};
}
std::string vertex_shader =
"#version 400\n"
"in vec3 vp;"
"void main() {"
" gl_Position = vec4(vp, 1.0);"
"}";
std::string fragment_shader =
"#version 400\n"
"out vec4 frag_colour;"
"void main() {"
" frag_colour = vec4(1.0, 0.0, 0.0, 1.0);"
"}";
std::pair<int,int> parse_resolution(const std::string& str)
{
auto x_it = std::find(str.begin(),str.end(),'x');
auto x_str = std::string{str.begin(),x_it};
auto y_str = std::string(x_it+1,str.end());
return std::make_pair(std::stoi(x_str),std::stoi(y_str));
}
std::string slurp_file(const std::string& path)
{
std::ifstream input(path);
std::stringstream sstr;
while(input >> sstr.rdbuf());
#ifdef UNITTEST
{
database db(database::create("/tmp/", 4096));
return sstr.str();
}
db_page v;
v.fill(1);
int main(int argc, char** argv)
{
// start GL context and O/S window using the GLFW helper library
if (!glfwInit()) {
std::cerr<<"ERROR: could not start GLFW3\n";
return 1;
}
record_identifier tar;
CMD::commander cli_args{argc,argv};
auto res_str = cli_args.getFlagValue("-r");
auto res = parse_resolution(res_str.empty()?"800x800":res_str);
auto mesh_path = cli_args.getFlagValue("--mesh");
auto begin = std::chrono::high_resolution_clock::now();
if(!mesh_path.empty()) {
auto mesh = nlohmann::json::parse(slurp_file(mesh_path));
assert(mesh.is_array());
points = std::vector<float>{mesh.begin(), mesh.end()};
}
size_t tot = 2048;
for(size_t idx=0;idx<tot;idx++)
{
tar.y.internal = idx;
db.write(tar, v);
}
auto vertshad_path = cli_args.getFlagValue("--vshader");
auto durr = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - begin)/tot;
if(!vertshad_path.empty()) {
vertex_shader = slurp_file(vertshad_path);
}
std::cerr << "durr/elem = " << durr.count() << "ns/op" << std::endl;
auto fragshad_path = cli_args.getFlagValue("--fshader");
auto a = db.read(tar);
if(o">!fragshad_path.empty()) {
fragment_shader = slurp_file(fragshad_path);
}
if(a.second[0] != 1) {
std::cerr << "read failed" << std::endl;
}
// uncomment these lines if on Apple OS X
/*glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);*/
db.remove(tar);
GLFWwindow* window = glfwCreateWindow(res.first, res.second, "sh_render", NULL, NULL);
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);
}
if (!window) {
std::cerr<<"ERROR: could not open window with GLFW3\n";
glfwTerminate();
return 1;
}
database reop(database::open("/tmp/"));
glfwMakeContextCurrent(window);
{
a = reop.read(tar);
// start GLEW extension handler
glewExperimental = GL_TRUE;
glewInit();
if(a.second[0] != 2) {
std::cerr << "reopen read failed" << std::endl;
}
// get version info
const GLubyte* renderer = glGetString(GL_RENDERER); // get renderer string
const GLubyte* version = glGetString(GL_VERSION); // version as a string
std::cout <<"Renderer: "<<renderer<<"\n"
<<"OpenGL version supported "<<version<<"\n";
v.fill(3);
// tell GL to only draw onto a pixel if the shape is closer to the viewer
glEnable(GL_DEPTH_TEST); // enable depth-testing
glDepthFunc(GL_LESS); // depth-testing interprets a smaller value as "closer"
reop.write(tar, v);
{
GLuint vbo = 0;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(
GL_ARRAY_BUFFER,
std::visit([](auto& v)->size_t{return v.size();},points) * sizeof(float),
std::visit([](auto& v)->float* {return (float*)v.data();},points),
GL_STATIC_DRAW
);
auto num_triangles = std::visit([](auto& v)->size_t{return v.size();},points)/9;
GLuint vao = 0;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
auto vsh = vertex_shader.data();
glShaderSource(vs, 1, &vsh, NULL);
glCompileShader(vs);
std::cout<<"Vertex shader:"<<check_shader(vs)<<"\n";
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
auto fsh = fragment_shader.data();
glShaderSource(fs, 1, &fsh, NULL);
glCompileShader(fs);
std::cout<<"Fragment shader:"<<check_shader(fs)<<"\n";
GLuint shader_programme = glCreateProgram();
glAttachShader(shader_programme, fs);
glAttachShader(shader_programme, vs);
glLinkProgram(shader_programme);
while(!glfwWindowShouldClose(window)) {
// wipe the drawing surface clear
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shader_programme);
glBindVertexArray(vao);
// draw points 0-4 from the currently bound VAO with current in-use shader
for(size_t tri_it = 0; tri_it<num_triangles; tri_it++) {
glDrawArrays(GL_TRIANGLES, tri_it*3, 3);
a = reop.read(tar);
if(a.second[0] != 3) {
std::cerr << "reopen write failed" << std::endl;
}
// update other events like input handling
glfwPollEvents();
// put the stuff we've been drawing onto the display
glfwSwapBuffers(window);
}
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
database run_db(database::create("/tmp/", 4096));
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 (...) {
}
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);
// close GL context and any other GLFW resources
glfwTerminate();
return 0;
}

+ 90
- 0
src/test_client.cpp View File

@ -0,0 +1,90 @@
#include "network.hpp"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main() {
{
auto soc = socket(AF_INET, SOCK_DGRAM, 0);
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_addr.s_addr = *(in_addr_t*)std::array<unsigned char, 4>{127,0,0,1}.data();
server.sin_port = htons(20450);
connect(soc, (struct sockaddr*)&server, sizeof(server));
sending_data reply;
received_data request;
db_page& v = request.page;
v.fill(1);
record_identifier& tar = request.identifier;
auto begin = std::chrono::high_resolution_clock::now();
size_t tot = 2048;
for(size_t idx=0;idx<tot;idx++)
{
tar.y.internal = idx;
request.op = db_op::write;
sendto(
soc,
(void*)&request,
sizeof(request),
0,
(struct sockaddr*)&server,
(socklen_t)sizeof(server)
);
recv(soc, &reply, sizeof(reply), 0);
}
auto durr = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - begin)/tot;
std::cerr << "durr/elem = " << durr.count() << "ns/op" << std::endl;
request.op = db_op::read;
sendto(
soc,
(void*)&request,
sizeof(request),
0,
(struct sockaddr*)&server,
(socklen_t)sizeof(server)
);
recv(soc, &reply, sizeof(reply), 0);
if(reply.page[0] != 1) {
std::cerr << "read failed" << std::endl;
}
request.op = db_op::remove;
sendto(
soc,
(void*)&request,
sizeof(request),
0,
(struct sockaddr*)&server,
(socklen_t)sizeof(server)
);
recv(soc, &reply, sizeof(reply), 0);
request.op = db_op::read;
sendto(
soc,
(void*)&request,
sizeof(request),
0,
(struct sockaddr*)&server,
(socklen_t)sizeof(server)
);
reply.page.fill(0);
recv(soc, &reply, sizeof(reply), 0);
if(reply.page[0] == 1) {
std::cerr << "remove failed" << std::endl;
}
}
}

+ 1
- 1
tiny-js

@ -1 +1 @@
Subproject commit d61b911e56801489e2f72bd27304dcd15eeb60c1
Subproject commit 67ad37dd1c7753911c470d26aa97e553866ae2e9

Loading…
Cancel
Save