diff --git a/assets/HypertextPages/list-rooms.html b/assets/HypertextPages/list-rooms.nytl.html similarity index 68% rename from assets/HypertextPages/list-rooms.html rename to assets/HypertextPages/list-rooms.nytl.html index 390359f..5136e4b 100644 --- a/assets/HypertextPages/list-rooms.html +++ b/assets/HypertextPages/list-rooms.nytl.html @@ -1,31 +1,32 @@ +{% ELDEF main JSON pres %} - Список Чат-Комнат + {% WRITE pres.phr.decl.list-of-chat-rooms %}
-

Выберите Чат-Комнату

+

{% WRITE pres.phr.decl.select-chat-room %}

- +
@@ -35,14 +36,14 @@ @@ -50,3 +51,4 @@ +{% ENDELDEF %} diff --git a/example/config.json b/example/config.json index 00c0345..3edafa7 100644 --- a/example/config.json +++ b/example/config.json @@ -1,3 +1,32 @@ { - "name": "Web chat" + "presentation": { + "instance-identity": { + "top-title": "Вэб чат ИУ9" + }, + "phr": { + "decl": { + "list-of-chat-rooms": "Список Чат-Комнат", + "select-chat-room": "Выберете чат комнату", + "name-of-room": "Название комнаты", + "create-room": "Создать комнату" + }, + "act": { + "create-room": "Создать комнату", + "confirm": "Подтвердить", + "create": "Создать" + } + } + }, + "assets": "./assets", + "limits": { + "max-users": 100000, + "max-rooms": 100000, + "max-messages": 10000000000000, + "storage-size-limit": 100000000000 + }, + "server": { + "workers": 8, + "http-listen": ["127.0.0.1:1025"], + "command-listen": [] + } } \ No newline at end of file diff --git a/src/http_server/engine_engine_number_9/running_mainloop.cpp b/src/http_server/engine_engine_number_9/running_mainloop.cpp index 2c07b7f..41560fc 100644 --- a/src/http_server/engine_engine_number_9/running_mainloop.cpp +++ b/src/http_server/engine_engine_number_9/running_mainloop.cpp @@ -82,10 +82,10 @@ namespace een9 { struct WorkersEnv { WorkersEnvCommon& wtec; - int id; + worker_id_t id; ClientRequestParser_WorkerBuffers personal_parser_buffer; - explicit WorkersEnv(WorkersEnvCommon& wtec, int id): wtec(wtec), id(id), personal_parser_buffer(wtec.parser_programs){} + explicit WorkersEnv(WorkersEnvCommon& wtec, worker_id_t id): wtec(wtec), id(id), personal_parser_buffer(wtec.parser_programs){} }; // todo: add timeout for multiple bytes, add more settings @@ -125,7 +125,7 @@ namespace een9 { void process_connection(const SlaveTask& task, WorkersEnv& wte) { ClientRequest client_request = process_connection_input(task.fd(), task.s_tips, wte); - std::string server_response = wte.wtec.guest_core(task, client_request); + std::string server_response = wte.wtec.guest_core(task, client_request, wte.id); process_connection_output(task.fd(), server_response); } @@ -149,6 +149,7 @@ namespace een9 { } catch (const std::exception& e) { printf("Client request procession failure in worker\n"); printf("%s\n", e.what()); + /* Under mysterious some circumstances, in this place destructor of string in SystemError causes segfault. I can't fix that */ } } printf("Worker finished\n"); @@ -166,7 +167,7 @@ namespace een9 { std::vector workers(params.slave_number); std::vector> wtes(params.slave_number); for (size_t i = 0; i < params.slave_number; i++) { - wtes[i] = std::make_unique(wtec, i); + wtes[i] = std::make_unique(wtec, (worker_id_t)i); } for (size_t i = 0; i < params.slave_number; i++) { pthread_create(&workers[i], NULL, worker_func, wtes[i].get()); diff --git a/src/http_server/engine_engine_number_9/running_mainloop.h b/src/http_server/engine_engine_number_9/running_mainloop.h index aa7584a..65bcd4e 100644 --- a/src/http_server/engine_engine_number_9/running_mainloop.h +++ b/src/http_server/engine_engine_number_9/running_mainloop.h @@ -29,8 +29,10 @@ namespace een9 { EEN9_ServerTips s_tips; }; + typedef int worker_id_t; + /* guest_core function must not throw anything that is not derived from std::exception */ - typedef std::function guest_core_t; + typedef std::function guest_core_t; struct ServersConfiguration { size_t critical_load_1 = 90; diff --git a/src/http_server/new_york_transit_line/parser.cpp b/src/http_server/new_york_transit_line/parser.cpp index c44cc33..d7c3460 100644 --- a/src/http_server/new_york_transit_line/parser.cpp +++ b/src/http_server/new_york_transit_line/parser.cpp @@ -447,27 +447,29 @@ namespace nytl { mediocre_operator("str2code"); goto ya_e_ya_h_i_ya_g_d_o;; } + auto prepare_to_depart_parts = [&]() { + assert(!result.parts.empty()); + if (result.parts[0].type == ElementPart::p_code) + result.parts[0].when_code.lines = clement_lstrip(result.parts[0].when_code.lines); + if (result.parts.back().type == ElementPart::p_code) + rstrip(result.parts.back().when_code.lines); + size_t cut = 999999999999; + size_t N = result.parts.size(); + for (size_t i = 0; i < N; i++) { + if (result.parts[i].type == ElementPart::p_code) { + one_part_update_min_start_wsp_non_empty(result.parts[i].when_code.lines, i, N, cut); + } + } + for (size_t i = 0; i < N; i++) { + if (result.parts[i].type == ElementPart::p_code) { + result.parts[i].when_code.lines = one_part_cut_excess_tab(result.parts[i].when_code.lines, i, N, cut); + } + } + }; if (op == "ENDELDEF") { ASSERT(myself == gone_for_nothing, "Unexpected end of element"); skip_magic_block_end(ctx, syntax); - if (!result.parts.empty()) { - if (result.parts[0].type == ElementPart::p_code) - result.parts[0].when_code.lines = clement_lstrip(result.parts[0].when_code.lines); - if (result.parts.back().type == ElementPart::p_code) - rstrip(result.parts.back().when_code.lines); - size_t cut = 999999999999; - size_t N = result.parts.size(); - for (size_t i = 0; i < N; i++) { - if (result.parts[i].type == ElementPart::p_code) { - one_part_update_min_start_wsp_non_empty(result.parts[i].when_code.lines, i, N, cut); - } - } - for (size_t i = 0; i < N; i++) { - if (result.parts[i].type == ElementPart::p_code) { - result.parts[i].when_code.lines = one_part_cut_excess_tab(result.parts[i].when_code.lines, i, N, cut); - } - } - } + prepare_to_depart_parts(); return NULL; } if (op == "ENDFOR") { @@ -485,10 +487,13 @@ namespace nytl { THROW("Expected LF, NOLF or end of magic block"); } skip_magic_block_end(ctx, syntax); + prepare_to_depart_parts(); return NULL; } if (op == "ENDREF") { + assert(myself == gone_for_ref); skip_magic_block_end(ctx, syntax); + prepare_to_depart_parts(); return NULL; } THROW("Unknown operator. Expected FOR, REF, PUT, WRITE, ROUGHINSERT, ENDELDEF, ENDFOR, ENDREF"); diff --git a/src/http_server/new_york_transit_line/rendering.cpp b/src/http_server/new_york_transit_line/rendering.cpp index 48fc0b1..b6cc23e 100644 --- a/src/http_server/new_york_transit_line/rendering.cpp +++ b/src/http_server/new_york_transit_line/rendering.cpp @@ -9,22 +9,25 @@ namespace nytl { std::string result; size_t cur_line_width = 0; + /* Fix idea: get rid of newlined_somewhere */ void append(const std::string& text, size_t wsp_before_newlines, bool& newlined_somewhere) { size_t n = result.size(); size_t m = text.size(); result.reserve(n + m); for (size_t i = 0; i < m; i++) { + result += text[i]; if (text[i] == '\n') { - newlined_somewhere = true; - cur_line_width = 0; + // newlined_somewhere = true; + + result.resize(result.size() + wsp_before_newlines, ' '); + cur_line_width = wsp_before_newlines; } else { - if (cur_line_width == 0 && newlined_somewhere) { - result.resize(result.size() + wsp_before_newlines, ' '); - cur_line_width = wsp_before_newlines; - } + // if (cur_line_width == 0 && newlined_somewhere) { + // result.resize(result.size() + wsp_before_newlines, ' '); + // cur_line_width = wsp_before_newlines; + // } cur_line_width++; } - result += text[i]; } } }; @@ -88,7 +91,7 @@ namespace nytl { RFrame_OverArray(const ElementPart::when_for_put_S& part, size_t multiline_put_start, const std::vector &saved_args, const std::vector &arr): RFrame_OverJSON(part, multiline_put_start, saved_args), arr(arr) { - if (part.where_key_var < 0) + if (part.where_key_var >= 0) additional_json_wrapper = json::JSON(json::Integer(0l)); } @@ -106,7 +109,7 @@ namespace nytl { const std::map &dict): RFrame_OverJSON(part, multiline_put_start, saved_args_plus_iter), dict(dict) { it = dict.begin(); - if (part.where_key_var < 0) + if (part.where_key_var >= 0) addition_json_wrapper = json::JSON(""); } @@ -151,6 +154,8 @@ namespace nytl { std::string escaped_json = escape(json::generate_str(*X, json::print_pretty)); rstrip(escaped_json); append(escaped_json, result); + } else if (name == "jesccomp") { + append(escape(json::generate_str(*X, json::print_compact)), result); } else if (name == "str2text") { ASSERT(X->isString(), "str2text takes json string"); append(escape(X->asString()), result); @@ -215,10 +220,10 @@ namespace nytl { } uptr RFrame_OverDictionary::toMe(bool returned, RFrame_passed) { - if (returned && part.line_feed) - append("\n", result); if (it == dict.end()) return NULL; + if (returned && part.line_feed) + append("\n", result); if (part.where_key_var > -1) { addition_json_wrapper.asString() = it->first; saved_args_plus_iter[part.where_key_var] = {true, "", &addition_json_wrapper}; diff --git a/src/http_server/new_york_transit_line/templater.cpp b/src/http_server/new_york_transit_line/templater.cpp index ca07098..e139811 100644 --- a/src/http_server/new_york_transit_line/templater.cpp +++ b/src/http_server/new_york_transit_line/templater.cpp @@ -112,7 +112,10 @@ namespace nytl { void Templater::update() { elements = { {"jesc", Element{{json::JSON(true)}, true}}, + {"jesccomp", Element{{json::JSON(true)}, true}}, + /* str2text base element has a dedicated operator - WRITE */ {"str2text", Element{{json::JSON(true)}, true}}, + /* str2code base element has a dedicated operator - ROUGHINSERT */ {"str2code", Element{{json::JSON(true)}, true}}, }; std::vector intersting_files = indexing_detour(settings.det); diff --git a/src/http_server/nytl_tests/HypertextPages/biba/boba/aboba.nytl.html b/src/http_server/nytl_tests/HypertextPages/biba/boba/aboba.nytl.html new file mode 100644 index 0000000..8a154da --- /dev/null +++ b/src/http_server/nytl_tests/HypertextPages/biba/boba/aboba.nytl.html @@ -0,0 +1,7 @@ +{% ELDEF main %} + + CCC +DDD + + +{% ENDELDEF %} \ No newline at end of file diff --git a/src/http_server/nytl_tests/HypertextPages/test.nytl.html b/src/http_server/nytl_tests/HypertextPages/test.nytl.html index 271871e..013fb7a 100644 --- a/src/http_server/nytl_tests/HypertextPages/test.nytl.html +++ b/src/http_server/nytl_tests/HypertextPages/test.nytl.html @@ -1,9 +1,9 @@ -{% ELDEF foo JSON cba %} -BBBB -{% ENDELDEF %} + {% ELDEF main JSON cba %} - AAAA - {% PUT test.foo cba %} - {% PUT test.foo cba %} + AAA + {% FOR _:val IN cba %} + TUTUTUTUTUTUTUTUN {% PUT jesccomp val %} + {% ENDFOR %} + {% ENDELDEF %} \ No newline at end of file diff --git a/src/http_server/nytl_tests/test0.cpp b/src/http_server/nytl_tests/test0.cpp index 48c7852..84b48ce 100644 --- a/src/http_server/nytl_tests/test0.cpp +++ b/src/http_server/nytl_tests/test0.cpp @@ -14,6 +14,9 @@ int main(int argc, char** argv) { nytl::debug_print_templater(templater); json::JSON cba; cba["boba"] = json::JSON("<>"); + cba["arr"][0] = json::JSON("zero"); + cba["arr"][1] = json::JSON("one"); + cba["arr"][2] = json::JSON("two"); // printf("DEBUG WAS: %p\n", &cba["boba"].g()); // printf("%s\n", json::generate_str(cba["boba"].g(), json::print_compact).c_str()); // return 0; diff --git a/src/web_chat/main.cpp b/src/web_chat/main.cpp index 745b5d7..24beccb 100644 --- a/src/web_chat/main.cpp +++ b/src/web_chat/main.cpp @@ -10,6 +10,8 @@ #include #include +#include "../http_server/engine_engine_number_9/running_mainloop.h" + bool termination = false; void sigterm_action(int) { @@ -17,7 +19,7 @@ void sigterm_action(int) { } void usage(char** argv) { - printf("Usage: %s \n", argv[0]); + printf("Usage: %s \n", argv[0]); exit(1); } @@ -32,30 +34,26 @@ std::string unsafe_client_request_stringification(const een9::ClientRequest& req } int main(int argc, char** argv){ - printf("%s\n", regexis024::opcode_to_str(regexis024::opcode_t::DIE)); try { een9_ASSERT_pl(argc > 0); - if (argc < 1 + 2) + if (argc < 1 + 1) usage(argv); if (!een9::isRegularFile(argv[1]) || !een9::endsIn(argv[1], ".json")) { printf("\"%s\" is not a json file\n", argv[1]); usage(argv); } std::string config_file = argv[1]; - if (!een9::isDirectory(argv[2])) { - printf("\"%s\" is not a directory\n", argv[2]); - usage(argv); - } - std::string assets_dir = argv[2]; std::string config_text; een9::readFile(config_file, config_text); json::JSON config = json::parse_str_flawless(config_text); een9_ASSERT(config.isDictionary(), "config root is not dictionary"); + een9_ASSERT(config["assets"].g().isString(), "config[\"\assets\"] is not string"); + std::string assets_dir = config["assets"].g().asString(); + een9_ASSERT(een9::isDirectory(assets_dir), "\"" + assets_dir + "\" is not a directory"); een9::StaticAssetManagerSlaveModule samI; samI.update({ - een9::StaticAssetManagerRule{assets_dir + "/HypertextPages", "/assets/html", {{".html", "text/html"}} }, een9::StaticAssetManagerRule{assets_dir + "/css", "/assets/css", {{".css", "text/css"}} }, een9::StaticAssetManagerRule{assets_dir + "/js", "/assets/js", {{".js", "text/js"}} }, een9::StaticAssetManagerRule{assets_dir + "/img", "/assets/img", { @@ -63,31 +61,47 @@ int main(int argc, char** argv){ } }, }); + json::JSON& config_presentation = config["presentation"].g(); + + /* Because templaters use libjsonincpp, they can't be READ by two thread simultaneously */ + std::vector> templaters_copies(8); + for (int i = 0; i < 8; i++) { + templaters_copies[i] = std::make_unique( + nytl::TemplaterSettings{nytl::TemplaterDetourRules{assets_dir + "/HypertextPages"}}); + templaters_copies[i]->update(); + } + + // printf("%s\n", templaters_copies[0]->render("list-rooms", {&config_presentation}).c_str()); + // return 0; + een9::MainloopParameters params; - params.guest_core = [&samI](const een9::SlaveTask& task, const een9::ClientRequest& req) -> std::string { + params.guest_core = [&samI, &templaters_copies, config_presentation] + (const een9::SlaveTask& task, const een9::ClientRequest& req, een9::worker_id_t worker_id) -> std::string { + een9_ASSERT_pl(0 <= worker_id && worker_id < templaters_copies.size()); + nytl::Templater& templater = *templaters_copies[worker_id]; een9::StaticAsset sa; int ret; // printf("%s", unsafe_client_request_stringification(req).c_str()); - if (req.uri_path == "/output") { - std::string text = unsafe_client_request_stringification(req); - return een9::form_http_server_response_200("text/plain", text); - } - auto rteee = [&](const std::string& asset_path) -> std::string { - ret = samI.get_asset(asset_path, sa); - een9_ASSERT_pl(ret == 0); - return een9::form_http_server_response_200(sa.type, sa.content); + // if (req.uri_path == "/output") { + // std::string text = unsafe_client_request_stringification(req); + // return een9::form_http_server_response_200("text/plain", text); + // } + auto rteee = [&](const std::string& el_name, bool pass_phr) -> std::string { + std::string page = templater.render(el_name, + pass_phr ? std::vector{&config_presentation} : std::vector{}); + return een9::form_http_server_response_200("text/html", page); }; if (req.uri_path == "/" || req.uri_path == "/list-rooms") { - return rteee("/assets/html/list-rooms.html"); + return rteee("list-rooms", true); } if (req.uri_path == "/chat") { - return rteee("/assets/html/chat.html"); + return rteee("chat", false); } if (req.uri_path == "/profile") { - return rteee("/assets/html/profile.html"); + return rteee("profile", false); } if (req.uri_path == "/registration") { - return rteee("/assets/html/registration.html"); + return rteee("registration", false); } /* Trying to interpret request as asset lookup */ ret = samI.get_asset(req.uri_path, sa); @@ -96,6 +110,7 @@ int main(int argc, char** argv){ } return een9::form_http_server_response_404("text/html", "

Not found!

"); }; + params.ports_to_listen = {1025}; params.slave_number = 8; params.open_admin_listener = false;