aboutsummaryrefslogtreecommitdiff
path: root/core.j2.c
diff options
context:
space:
mode:
authorPaul Oliver <contact@pauloliver.dev>2025-12-03 22:14:38 +0100
committerPaul Oliver <contact@pauloliver.dev>2025-12-05 01:57:20 +0100
commit24811b4c6a6592b08dbb41243db188a8b310312d (patch)
tree3c2751b0ba74e498f64a0bab1e75fdd6af314692 /core.j2.c
parentc7c5925d86fd3e36069ee3689b1c0a1f6df600f9 (diff)
Improve SQL handling & aggregate memory events (WIP)data_improvements
Diffstat (limited to 'core.j2.c')
-rw-r--r--core.j2.c65
1 files changed, 50 insertions, 15 deletions
diff --git a/core.j2.c b/core.j2.c
index bd4b266..a7bd9cc 100644
--- a/core.j2.c
+++ b/core.j2.c
@@ -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);