Made it easier to run multiple instances.

git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3687 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
Cory McWilliams 2021-11-14 22:55:21 +00:00
parent 63c344112d
commit 9e1bab03eb
3 changed files with 113 additions and 50 deletions

View File

@ -30,7 +30,8 @@ static JSValue _database_get_like(JSContext* context, JSValueConst this_val, int
void tf_database_register(JSContext* context, sqlite3* sqlite) void tf_database_register(JSContext* context, sqlite3* sqlite)
{ {
JS_NewClassID(&_database_class_id); JS_NewClassID(&_database_class_id);
JSClassDef def = { JSClassDef def =
{
.class_name = "Database", .class_name = "Database",
.finalizer = &_database_finalizer, .finalizer = &_database_finalizer,
}; };

View File

@ -298,34 +298,83 @@ xopt_help:
return 1; return 1;
} }
typedef struct tf_run_args_t {
const char* script;
int ssb_port;
int http_port;
int https_port;
const char* db_path;
const char* secrets_path;
int count;
bool help;
} tf_run_args_t;
typedef struct _tf_run_thread_data_t
{
tf_run_args_t args;
int index;
int result;
} tf_run_thread_data_t;
static int _tf_run_task(const tf_run_args_t* args, int index)
{
int result = -1;
tf_task_t* task = tf_task_create();
tf_task_set_trusted(task, true);
tf_task_set_ssb_port(task, args->ssb_port ? args->ssb_port + index : 0);
tf_task_set_http_port(task, args->http_port ? args->http_port + index : 0);
tf_task_set_https_port(task, args->https_port ? args->https_port + index : 0);
const char* db_path = args->db_path;
const char* secrets_path = args->secrets_path;
char db_path_buffer[256];
char secrets_path_buffer[256];
if (index)
{
snprintf(db_path_buffer, sizeof(db_path_buffer), "%s.%d", args->db_path, index);
db_path = db_path_buffer;
snprintf(secrets_path_buffer, sizeof(secrets_path_buffer), "%s.%d", args->secrets_path, index);
secrets_path = secrets_path_buffer;
}
tf_task_set_db_path(task, db_path);
tf_task_set_secrets_path(task, secrets_path);
tf_task_activate(task);
if (tf_task_execute(task, args->script))
{
tf_task_run(task);
result = 0;
}
tf_task_destroy(task);
return result;
}
static void _tf_run_task_thread(void* data)
{
tf_run_thread_data_t* info = data;
info->result = _tf_run_task(&info->args, info->index);
}
static int _tf_command_run(const char* file, int argc, char* argv[]) static int _tf_command_run(const char* file, int argc, char* argv[])
{ {
typedef struct args_t {
const char* script;
int ssb_port;
int http_port;
int https_port;
const char* db_path;
const char* secrets_path;
bool help;
} args_t;
xoptOption options[] = { xoptOption options[] = {
{ "script", 's', offsetof(args_t, script), NULL, XOPT_TYPE_STRING, NULL, "Script to run (default: core/core.js)." }, { "script", 's', offsetof(tf_run_args_t, script), NULL, XOPT_TYPE_STRING, NULL, "Script to run (default: core/core.js)." },
{ "ssb-port", 'b', offsetof(args_t, ssb_port), NULL, XOPT_TYPE_INT, NULL, "Port on which to run SSB (default: 8009)." }, { "ssb-port", 'b', offsetof(tf_run_args_t, ssb_port), NULL, XOPT_TYPE_INT, NULL, "Port on which to run SSB (default: 8009)." },
{ "http-port", 'p', offsetof(args_t, http_port), NULL, XOPT_TYPE_INT, NULL, "Port on which to run Tilde Friends web server (default: 12345)." }, { "http-port", 'p', offsetof(tf_run_args_t, http_port), NULL, XOPT_TYPE_INT, NULL, "Port on which to run Tilde Friends web server (default: 12345)." },
{ "https-port", 'q', offsetof(args_t, https_port), NULL, XOPT_TYPE_INT, NULL, "Port on which to run secure Tilde Friends web server (default: 12346)." }, { "https-port", 'q', offsetof(tf_run_args_t, https_port), NULL, XOPT_TYPE_INT, NULL, "Port on which to run secure Tilde Friends web server (default: 12346)." },
{ "db-path", 'd', offsetof(args_t, db_path), NULL, XOPT_TYPE_STRING, NULL, "Sqlite database path (default: db.sqlite)." }, { "db-path", 'd', offsetof(tf_run_args_t, db_path), NULL, XOPT_TYPE_STRING, NULL, "Sqlite database path (default: db.sqlite)." },
{ "secrets-path", 'i', offsetof(args_t, secrets_path), NULL, XOPT_TYPE_STRING, NULL, "Secrets/identity path." }, { "secrets-path", 'i', offsetof(tf_run_args_t, secrets_path), NULL, XOPT_TYPE_STRING, NULL, "Secrets/identity path." },
{ "help", 'h', offsetof(args_t, help), NULL, XOPT_TYPE_BOOL, NULL, "Shows this help message." }, { "count", 'n', offsetof(tf_run_args_t, count), NULL, XOPT_TYPE_INT, NULL, "Number of instances to run." },
{ "help", 'h', offsetof(tf_run_args_t, help), NULL, XOPT_TYPE_BOOL, NULL, "Shows this help message." },
XOPT_NULLOPTION, XOPT_NULLOPTION,
}; };
args_t args = { tf_run_args_t args =
{
.count = 1,
.script = "core/core.js", .script = "core/core.js",
.http_port = 12345, .http_port = 12345,
.ssb_port = 8009, .ssb_port = 8009,
.db_path = "db.sqlite", .db_path = "db.sqlite",
.secrets_path = "/.config/tildefriends/secret",
}; };
const char** extras = NULL; const char** extras = NULL;
int extra_count = 0; int extra_count = 0;
@ -350,24 +399,36 @@ static int _tf_command_run(const char* file, int argc, char* argv[])
#if !defined (_WIN32) && !defined (__MACH__) #if !defined (_WIN32) && !defined (__MACH__)
setpgid(0, 0); setpgid(0, 0);
#endif #endif
tf_task_t* task = tf_task_create();
tf_task_set_trusted(task, true); if (args.count == 1)
tf_task_set_ssb_port(task, args.ssb_port);
tf_task_set_http_port(task, args.http_port);
tf_task_set_https_port(task, args.https_port);
tf_task_set_db_path(task, args.db_path);
tf_task_set_secrets_path(task, args.secrets_path);
tf_task_activate(task);
if (!tf_task_execute(task, args.script))
{ {
result = -1; _tf_run_task(&args, 0);
}
if (args.count > 1)
{
uv_thread_t* threads = malloc(sizeof(uv_thread_t) * args.count);
tf_run_thread_data_t* data = malloc(sizeof(tf_run_thread_data_t) * args.count);
for (int i = 0 ; i < args.count; i++)
{
data[i] = (tf_run_thread_data_t)
{
.args = args,
.index = i,
};
uv_thread_create(&threads[i], _tf_run_task_thread, &data[i]);
}
for (int i = 0; i < args.count; i++)
{
uv_thread_join(&threads[i]);
if (data[i].result != 0)
{
result = data[i].result;
}
}
free(data);
free(threads);
} }
if (result == 0)
{
tf_task_run(task);
}
tf_task_destroy(task);
return result; return result;
xopt_help: xopt_help:

View File

@ -91,7 +91,7 @@ typedef struct _tf_task_t {
promise_t* _promises; promise_t* _promises;
int _promise_count; int _promise_count;
promiseid_t _nextPromise; promiseid_t _nextPromise;
uv_loop_t* _loop; uv_loop_t _loop;
export_record_t* _exports; export_record_t* _exports;
int _export_count; int _export_count;
@ -105,8 +105,8 @@ typedef struct _tf_task_t {
int _ssb_port; int _ssb_port;
int _http_port; int _http_port;
int _https_port; int _https_port;
const char* _db_path; char _db_path[256];
const char* _secrets_path; char _secrets_path[256];
} tf_task_t; } tf_task_t;
typedef struct _export_record_t { typedef struct _export_record_t {
@ -294,7 +294,7 @@ static JSValue _task_setTimeout(JSContext* context, JSValueConst this_val, int a
uv_timer_t* timer = malloc(sizeof(uv_timer_t)); uv_timer_t* timer = malloc(sizeof(uv_timer_t));
memset(timer, 0, sizeof(uv_timer_t)); memset(timer, 0, sizeof(uv_timer_t));
uv_timer_init(task->_loop, timer); uv_timer_init(&task->_loop, timer);
timer->data = timeout; timer->data = timeout;
int64_t duration; int64_t duration;
@ -882,7 +882,7 @@ static const char* _tf_task_resolveRequire(tf_task_t* task, const char* require)
snprintf(test, sizeof(test), "%s/%s%s", task->_path, require, strstr(require, ".js") ? "" : ".js"); snprintf(test, sizeof(test), "%s/%s%s", task->_path, require, strstr(require, ".js") ? "" : ".js");
printf("Testing %s\n", test); printf("Testing %s\n", test);
uv_fs_t request; uv_fs_t request;
if (uv_fs_access(task->_loop, &request, test, R_OK, 0) == 0) if (uv_fs_access(&task->_loop, &request, test, R_OK, 0) == 0)
{ {
return strdup(test); return strdup(test);
} }
@ -1049,7 +1049,7 @@ JSValue _tf_task_sandbox_require(JSContext* context, JSValueConst this_val, int
uv_loop_t* tf_task_get_loop(tf_task_t* task) uv_loop_t* tf_task_get_loop(tf_task_t* task)
{ {
return task->_loop; return &task->_loop;
} }
static promise_t* _tf_task_find_promise(tf_task_t* task, promiseid_t id) static promise_t* _tf_task_find_promise(tf_task_t* task, promiseid_t id)
@ -1219,8 +1219,6 @@ tf_task_t* tf_task_create()
{ {
tf_task_t* task = malloc(sizeof(tf_task_t)); tf_task_t* task = malloc(sizeof(tf_task_t));
*task = (tf_task_t) { 0 }; *task = (tf_task_t) { 0 };
task->_loop = uv_loop_new();
task->_loop->data = task;
++_count; ++_count;
task->_runtime = JS_NewRuntime(); task->_runtime = JS_NewRuntime();
task->_context = JS_NewContext(task->_runtime); task->_context = JS_NewContext(task->_runtime);
@ -1229,7 +1227,8 @@ tf_task_t* tf_task_create()
JS_SetHostPromiseRejectionTracker(task->_runtime, _tf_task_promise_rejection_tracker, task); JS_SetHostPromiseRejectionTracker(task->_runtime, _tf_task_promise_rejection_tracker, task);
JS_NewClassID(&_import_class_id); JS_NewClassID(&_import_class_id);
JSClassDef def = { JSClassDef def =
{
.class_name = "imported_function", .class_name = "imported_function",
.finalizer = _import_finalizer, .finalizer = _import_finalizer,
.gc_mark = _import_mark_func, .gc_mark = _import_mark_func,
@ -1237,6 +1236,8 @@ tf_task_t* tf_task_create()
}; };
JS_NewClass(task->_runtime, _import_class_id, &def); JS_NewClass(task->_runtime, _import_class_id, &def);
task->_loadedFiles = JS_NewObject(task->_context); task->_loadedFiles = JS_NewObject(task->_context);
uv_loop_init(&task->_loop);
task->_loop.data = task;
return task; return task;
} }
@ -1263,7 +1264,7 @@ void tf_task_activate(tf_task_t* task)
if (task->_trusted) if (task->_trusted)
{ {
sqlite3_open(task->_db_path ? task->_db_path : "db.sqlite", &task->_db); sqlite3_open(*task->_db_path ? task->_db_path : "db.sqlite", &task->_db);
JS_SetPropertyStr(context, global, "require", JS_NewCFunction(context, _tf_task_require, "require", 1)); JS_SetPropertyStr(context, global, "require", JS_NewCFunction(context, _tf_task_require, "require", 1));
JS_SetPropertyStr(context, global, "Task", tf_taskstub_register(context)); JS_SetPropertyStr(context, global, "Task", tf_taskstub_register(context));
@ -1274,7 +1275,7 @@ void tf_task_activate(tf_task_t* task)
task->_trace = tf_trace_create(); task->_trace = tf_trace_create();
task->_ssb = tf_ssb_create(task->_loop, task->_context, task->_db, task->_secrets_path); task->_ssb = tf_ssb_create(&task->_loop, task->_context, task->_db, *task->_secrets_path ? task->_secrets_path : NULL);
tf_ssb_set_trace(task->_ssb, task->_trace); tf_ssb_set_trace(task->_ssb, task->_trace);
tf_ssb_register(context, task->_ssb); tf_ssb_register(context, task->_ssb);
@ -1302,7 +1303,7 @@ void tf_task_activate(tf_task_t* task)
void tf_task_run(tf_task_t* task) void tf_task_run(tf_task_t* task)
{ {
uv_run(task->_loop, UV_RUN_DEFAULT); uv_run(&task->_loop, UV_RUN_DEFAULT);
} }
void tf_task_set_trusted(tf_task_t* task, bool trusted) void tf_task_set_trusted(tf_task_t* task, bool trusted)
@ -1377,8 +1378,8 @@ void tf_task_destroy(tf_task_t* task)
sqlite3_close(task->_db); sqlite3_close(task->_db);
} }
uv_print_all_handles(task->_loop, stdout); uv_print_all_handles(&task->_loop, stdout);
uv_loop_delete(task->_loop); uv_loop_close(&task->_loop);
--_count; --_count;
free((void*)task->_path); free((void*)task->_path);
free(task); free(task);
@ -1454,12 +1455,12 @@ void tf_task_set_https_port(tf_task_t* task, int port)
void tf_task_set_db_path(tf_task_t* task, const char* db_path) void tf_task_set_db_path(tf_task_t* task, const char* db_path)
{ {
task->_db_path = db_path; snprintf(task->_db_path, sizeof(task->_db_path), "%s", db_path);
} }
void tf_task_set_secrets_path(tf_task_t* task, const char* secrets_path) void tf_task_set_secrets_path(tf_task_t* task, const char* secrets_path)
{ {
task->_secrets_path = secrets_path; snprintf(task->_secrets_path, sizeof(task->_secrets_path), "%s", secrets_path);
} }
const char* tf_task_get_name(tf_task_t* task) const char* tf_task_get_name(tf_task_t* task)