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:
parent
63c344112d
commit
9e1bab03eb
@ -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,
|
||||||
};
|
};
|
||||||
|
115
src/main.c
115
src/main.c
@ -298,34 +298,83 @@ xopt_help:
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _tf_command_run(const char* file, int argc, char* argv[])
|
typedef struct tf_run_args_t {
|
||||||
{
|
|
||||||
typedef struct args_t {
|
|
||||||
const char* script;
|
const char* script;
|
||||||
int ssb_port;
|
int ssb_port;
|
||||||
int http_port;
|
int http_port;
|
||||||
int https_port;
|
int https_port;
|
||||||
const char* db_path;
|
const char* db_path;
|
||||||
const char* secrets_path;
|
const char* secrets_path;
|
||||||
|
int count;
|
||||||
bool help;
|
bool help;
|
||||||
} args_t;
|
} 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[])
|
||||||
|
{
|
||||||
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:
|
||||||
|
33
src/task.c
33
src/task.c
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user