getting closer to full port of web app starter

This commit is contained in:
udo
2026-04-19 19:44:18 +00:00
parent d1167aec3b
commit af642c8167
131 changed files with 900 additions and 80 deletions
+136 -25
View File
@@ -1,19 +1,112 @@
#include "compiler.h"
#include <algorithm>
#include <cstdlib>
#include <filesystem>
#include <sys/file.h>
namespace {
const char* UCE_SETUP_SYMBOL = "__uce_set_current_request";
const char* UCE_RENDER_SYMBOL = "__uce_render";
const char* UCE_COMPONENT_SYMBOL = "__uce_component";
const char* UCE_WEBSOCKET_SYMBOL = "__uce_websocket";
const u64 UCE_UNIT_ABI_VERSION = 1;
struct SharedUnitFilesystemState
{
bool source_exists = false;
bool metadata_exists = false;
bool metadata_parsed = false;
bool abi_compatible = false;
time_t source_time = 0;
time_t compiled_time = 0;
time_t metadata_time = 0;
time_t setup_template_time = 0;
time_t compiler_header_time = 0;
time_t compiler_source_time = 0;
time_t runtime_binary_time = 0;
time_t compiler_abi_time = 0;
time_t required_time = 0;
u64 metadata_abi_version = 0;
u64 runtime_abi_version = UCE_UNIT_ABI_VERSION;
};
bool compiler_is_u64_string(String value)
{
value = trim(value);
if(value == "")
return(false);
for(auto c : value)
{
if(c < '0' || c > '9')
return(false);
}
return(true);
}
bool compiler_parse_unit_metadata_abi(String content, u64& abi_out)
{
content = trim(content);
if(content == "")
return(false);
auto lines = split(content, "\n");
for(auto& raw_line : lines)
{
auto line = trim(raw_line);
if(line == "")
continue;
auto split_pos = line.find("=");
if(split_pos == String::npos)
continue;
auto key = trim(line.substr(0, split_pos));
auto value = trim(line.substr(split_pos + 1));
if(key != "unit_abi_version" || !compiler_is_u64_string(value))
continue;
abi_out = (u64)atoll(value.c_str());
return(true);
}
return(false);
}
String compiler_unit_metadata_text()
{
return(
"format=uce-unit-metadata-v1\n"
"unit_abi_version=" + std::to_string(UCE_UNIT_ABI_VERSION) + "\n"
);
}
bool shared_unit_filesystem_requires_recompile(const SharedUnitFilesystemState& state)
{
if(!state.source_exists)
return(true);
if(state.compiled_time == 0)
return(true);
if(state.compiled_time < state.required_time)
return(true);
if(!state.metadata_exists)
return(true);
if(!state.metadata_parsed)
return(true);
if(!state.abi_compatible)
return(true);
return(false);
}
time_t compiler_runtime_abi_time(Request* context)
{
if(!context || !context->server)
return(0);
String root = context->server->config["COMPILER_SYS_PATH"];
return(std::max({
file_mtime(root + "/src/lib/compiler.h"),
file_mtime(root + "/src/lib/compiler.cpp"),
file_mtime(root + "/bin/uce_fastcgi.linux.bin")
}));
}
String compiler_registry_file_name(Request* context)
{
return(context->server->config["BIN_DIRECTORY"] + "/known-uce-files.txt");
@@ -109,7 +202,19 @@ SharedUnitFilesystemState inspect_shared_unit_filesystem(Request* context, Share
state.setup_template_time = file_mtime(
context->server->config["COMPILER_SYS_PATH"] + "/" +
context->server->config["SETUP_TEMPLATE"]);
state.required_time = std::max(state.source_time, state.setup_template_time);
state.compiler_header_time = file_mtime(context->server->config["COMPILER_SYS_PATH"] + "/src/lib/compiler.h");
state.compiler_source_time = file_mtime(context->server->config["COMPILER_SYS_PATH"] + "/src/lib/compiler.cpp");
state.runtime_binary_time = file_mtime(context->server->config["COMPILER_SYS_PATH"] + "/bin/uce_fastcgi.linux.bin");
state.compiler_abi_time = compiler_runtime_abi_time(context);
state.metadata_time = file_mtime(su->meta_file_name);
state.metadata_exists = (state.metadata_time != 0);
if(state.metadata_exists)
state.metadata_parsed = compiler_parse_unit_metadata_abi(
file_get_contents(su->meta_file_name),
state.metadata_abi_version
);
state.abi_compatible = (state.metadata_parsed && state.metadata_abi_version == state.runtime_abi_version);
state.required_time = std::max({state.source_time, state.setup_template_time, state.compiler_abi_time});
state.compiled_time = file_mtime(su->so_name);
return(state);
}
@@ -120,11 +225,7 @@ bool shared_unit_cache_is_stale(Request* context, SharedUnit* su)
return(true);
auto state = inspect_shared_unit_filesystem(context, su);
if(!state.source_exists)
return(true);
if(state.compiled_time == 0)
return(true);
if(state.compiled_time < state.required_time)
if(shared_unit_filesystem_requires_recompile(state))
return(true);
if(su->last_compiled != 0 && state.compiled_time != su->last_compiled)
return(true);
@@ -251,9 +352,9 @@ String compiler_status_from_filesystem(const SharedUnitFilesystemState& state, S
{
if(!state.source_exists)
return("missing_source");
if(state.compiled_time == 0)
if(state.compiled_time == 0 || !state.metadata_exists)
return("not_compiled");
if(state.compiled_time < state.required_time)
if(shared_unit_filesystem_requires_recompile(state))
return("stale");
if(su && su->so_handle)
return("loaded");
@@ -506,7 +607,7 @@ String preprocess_named_render_syntax(String content)
String render_name = trim(signature.substr(0, open_paren_pos));
String render_signature = signature.substr(open_paren_pos);
if(render_name != "")
line = indent + "EXPORT void __unit_render_" + safe_name(render_name) + render_signature;
line = indent + "EXPORT void " + String(UCE_RENDER_SYMBOL) + "_" + safe_name(render_name) + render_signature;
}
}
else if(trimmed.rfind("COMPONENT:", 0) == 0)
@@ -518,7 +619,7 @@ String preprocess_named_render_syntax(String content)
String render_name = trim(signature.substr(0, open_paren_pos));
String render_signature = signature.substr(open_paren_pos);
if(render_name != "")
line = indent + "EXPORT void __unit_component_" + safe_name(render_name) + render_signature;
line = indent + "EXPORT void " + String(UCE_COMPONENT_SYMBOL) + "_" + safe_name(render_name) + render_signature;
}
}
@@ -670,6 +771,7 @@ void setup_unit_paths(Request* context, SharedUnit* su, String file_name)
su->so_name = su->bin_path + "/" + su->bin_file_name;
su->api_file_name = su->bin_path + "/" + su->src_file_name + ".exports.txt";
su->meta_file_name = su->bin_path + "/" + su->src_file_name + ".meta.txt";
//su->setup_file_name = su->bin_path + "/" + su->src_file_name + ".setup.h";
}
@@ -707,14 +809,14 @@ void load_shared_unit(Request* context, SharedUnit* su, String file_name)
su->compile_status = "loaded";
su->compile_error_status = "";
char *error;
su->on_setup = (request_handler)dlsym(su->so_handle, "set_current_request");
su->on_setup = (request_handler)dlsym(su->so_handle, UCE_SETUP_SYMBOL);
if ((error = dlerror()) != NULL)
printf("Error - %s in %s\n", error, su->file_name.c_str());
su->on_render = (request_ref_handler)dlsym(su->so_handle, "__unit_render");
su->on_render = (request_ref_handler)dlsym(su->so_handle, UCE_RENDER_SYMBOL);
dlerror();
su->on_component = (request_ref_handler)dlsym(su->so_handle, "__unit_component");
su->on_component = (request_ref_handler)dlsym(su->so_handle, UCE_COMPONENT_SYMBOL);
dlerror();
su->on_websocket = (request_ref_handler)dlsym(su->so_handle, "__unit_websocket");
su->on_websocket = (request_ref_handler)dlsym(su->so_handle, UCE_WEBSOCKET_SYMBOL);
dlerror();
su->api_declarations = split(file_get_contents(su->api_file_name), "\n");
//else
@@ -777,6 +879,8 @@ void compile_shared_unit(Request* context, SharedUnit* su, String file_name)
else
{
load_shared_unit(context, su, file_name);
if(su->so_handle)
file_put_contents(su->meta_file_name, compiler_unit_metadata_text());
compiler_record_compile_result(
su,
time_precise() - comp_start,
@@ -1055,6 +1159,7 @@ DTree unit_info(String path)
info["pre_file_name"] = su->pre_file_name;
info["so_name"] = su->so_name;
info["api_file_name"] = su->api_file_name;
info["meta_file_name"] = su->meta_file_name;
info["compile_status"] = (su->compile_status != "unknown" ? su->compile_status : compiler_status_from_filesystem(fs_state, su));
info["compile_error_status"] = su->compile_error_status;
info["runtime_error_status"] = su->runtime_error_status;
@@ -1080,14 +1185,20 @@ DTree unit_info(String path)
info["worst_render_time"] = su->worst_render_duration;
info["source_mtime"] = (f64)fs_state.source_time;
info["compiled_mtime"] = (f64)fs_state.compiled_time;
info["metadata_mtime"] = (f64)fs_state.metadata_time;
info["setup_template_mtime"] = (f64)fs_state.setup_template_time;
info["required_mtime"] = (f64)fs_state.required_time;
info["runtime_abi_version"] = (f64)fs_state.runtime_abi_version;
info["metadata_abi_version"] = (f64)fs_state.metadata_abi_version;
compiler_tree_set_bool(info, "known", context->server->known_unit_files[resolved_path]);
compiler_tree_set_bool(info, "current_unit", resolved_path == compiler_current_unit_path(context));
compiler_tree_set_bool(info, "loaded", su->so_handle != 0);
compiler_tree_set_bool(info, "source_exists", fs_state.source_exists);
compiler_tree_set_bool(info, "compiled_exists", fs_state.compiled_time != 0);
compiler_tree_set_bool(info, "stale", fs_state.source_exists && fs_state.compiled_time != 0 && fs_state.compiled_time < fs_state.required_time);
compiler_tree_set_bool(info, "metadata_exists", fs_state.metadata_exists);
compiler_tree_set_bool(info, "metadata_parsed", fs_state.metadata_parsed);
compiler_tree_set_bool(info, "abi_compatible", fs_state.abi_compatible);
compiler_tree_set_bool(info, "stale", shared_unit_cache_is_stale(context, su));
compiler_tree_set_bool(info, "has_render", su->on_render != 0);
compiler_tree_set_bool(info, "has_component", su->on_component != 0);
compiler_tree_set_bool(info, "has_websocket", su->on_websocket != 0);
@@ -1225,22 +1336,22 @@ String page_render_handler_symbol(String render_name)
{
render_name = trim(render_name);
if(render_name == "" || render_name == "render")
return("__unit_render");
return("__unit_render_" + safe_name(render_name));
return(UCE_RENDER_SYMBOL);
return(String(UCE_RENDER_SYMBOL) + "_" + safe_name(render_name));
}
String component_handler_symbol(String render_name)
{
render_name = trim(render_name);
if(render_name == "")
return("__unit_component");
return("__unit_component_" + safe_name(render_name));
return(UCE_COMPONENT_SYMBOL);
return(String(UCE_COMPONENT_SYMBOL) + "_" + safe_name(render_name));
}
request_ref_handler get_page_render_handler(SharedUnit* su, String render_name)
{
String symbol = page_render_handler_symbol(render_name);
if(symbol == "__unit_render")
if(symbol == UCE_RENDER_SYMBOL)
return(su->on_render);
auto it = su->api_functions.find(symbol);
@@ -1256,7 +1367,7 @@ request_ref_handler get_page_render_handler(SharedUnit* su, String render_name)
request_ref_handler get_component_handler(SharedUnit* su, String render_name)
{
String symbol = component_handler_symbol(render_name);
if(symbol == "__unit_component")
if(symbol == UCE_COMPONENT_SYMBOL)
return(su->on_component);
auto it = su->api_functions.find(symbol);
@@ -1278,7 +1389,7 @@ bool compiler_invoke_render(Request* context, String file_name, String render_na
if(!su->on_setup)
{
if(error_out)
*error_out = "internal error: set_current_request() not defined in " + file_name;
*error_out = "internal error: " + String(UCE_SETUP_SYMBOL) + "() not defined in " + file_name;
return(false);
}
@@ -1327,7 +1438,7 @@ bool compiler_invoke_component(Request* context, String file_name, String render
if(!su->on_setup)
{
if(error_out)
*error_out = "internal error: set_current_request() not defined in " + file_name;
*error_out = "internal error: " + String(UCE_SETUP_SYMBOL) + "() not defined in " + file_name;
return(false);
}
@@ -1386,7 +1497,7 @@ void compiler_invoke_websocket(Request* context, String file_name)
if(!su->on_setup)
{
printf("internal error: set_current_request() not defined in %s\n", file_name.c_str());
printf("internal error: %s() not defined in %s\n", UCE_SETUP_SYMBOL, file_name.c_str());
return;
}
@@ -1529,7 +1640,7 @@ DTree* unit_call(String file_name, String function_name, DTree* call_param)
{
if(!su->on_setup)
{
print("internal error: set_current_request() not defined in", file_name, "\n");
print("internal error: ", UCE_SETUP_SYMBOL, "() not defined in ", file_name, "\n");
}
else
{