diff options
Diffstat (limited to 'core.j2.c')
| -rw-r--r-- | core.j2.c | 65 |
1 files changed, 50 insertions, 15 deletions
@@ -39,7 +39,7 @@ struct Core { uint8_t *iviv; // Architecture specific custom fields - {% for type, val in arch_vars.core_fields %} + {% for type, val, _ in arch_vars.core_fields %} {{ type }} {{ val }}; {% endfor %} @@ -73,6 +73,8 @@ void (*g_warn)(const char *fmt, ...); void arch_core_init(struct Core *core); {% endif %} +void arch_core_free(struct Core *core); + {% if args.command in ["load", "new"] %} void arch_core_save(FILE *f, const struct Core *core); {% endif %} @@ -610,27 +612,58 @@ void salis_auto_save() { {% endif %} {% if data_push_path is defined %} -void salis_exec_sql(const char *sql) { - assert(sql); +void salis_exec_sql(int blob_cnt, const void **blobs, const int *blob_sizes, const char *sql_format, ...) { + assert(sql_format); + + va_list args; + va_start(args, sql_format); + int sql_len = vsnprintf(NULL, 0, sql_format, args) + 1; + char *sql_str = malloc(sql_len); + assert(sql_str); + va_end(args); + + va_start(args, sql_format); + vsprintf(sql_str, sql_format, args); + va_end(args); + + // Prepare statement + int sql_res; + sqlite3_stmt *sql_stmt; + + sql_res = sqlite3_prepare_v2(g_sim_data, sql_str, -1, &sql_stmt, NULL); + assert(sql_res == SQLITE_OK); + free(sql_str); + + // Caller may pass multiple binary blobs to the query + for (int i = 0; i < blob_cnt; ++i) { + assert(blobs[i]); + sql_res = sqlite3_bind_blob(sql_stmt, i + 1, blobs[i], blob_sizes[i], SQLITE_STATIC); + assert(sql_res == SQLITE_OK); + } - int sql_res; - char *sql_err; + // Execute the statement + // Only handle SQLITE_BUSY error, in which case we retry the query. + // In principle, setting 'journal_mode=wal;' should help prevent busy database errors. + while (true) { + sql_res = sqlite3_step(sql_stmt); + + if (sql_res == SQLITE_DONE || sql_res == SQLITE_ROW) { + break; + } - while ((sql_res = sqlite3_exec(g_sim_data, sql, NULL, NULL, &sql_err)) == SQLITE_BUSY) { g_warn("SQLite database returned error '%d' with message:", sql_res); - g_warn(sql_err); - sqlite3_free(sql_err); + g_warn(sqlite3_errmsg(g_sim_data)); - switch (sql_res) { - case SQLITE_BUSY: - // Only handle busy database errors + if (sql_res == SQLITE_BUSY) { g_info("Will retry query..."); continue; - default: - // Application should fail on all other error conditions - assert(false); } + + // Fail on unhandled error + assert(false); } + + sqlite3_finalize(sql_stmt); } {% endif %} @@ -659,7 +692,7 @@ void salis_init() { // Enable Write-Ahead Logging (WAL) // This seems to help prevent DB locks when displaying live data // See: https://sqlite.org/wal.html - salis_exec_sql("pragma journal_mode=wal;"); + salis_exec_sql(0, NULL, NULL, "pragma journal_mode=wal;"); arch_push_data_header(); arch_push_data_line(); @@ -871,6 +904,8 @@ void salis_free() { {% endif %} for (int i = 0; i < {{ args.cores }}; ++i) { + arch_core_free(&g_cores[i]); + assert(g_cores[i].pvec); assert(g_cores[i].iviv); assert(g_cores[i].ivav); |
