diff --git a/src/httpd.js.c b/src/httpd.js.c index e7e2a20d..3c347ad6 100644 --- a/src/httpd.js.c +++ b/src/httpd.js.c @@ -1170,7 +1170,12 @@ static void _httpd_endpoint_view_work(tf_ssb_t* ssb, void* user_data) } else { - tf_ssb_db_blob_get(ssb, blob_id, (uint8_t**)&view->data, &view->size); + if (!tf_ssb_db_blob_get(ssb, blob_id, (uint8_t**)&view->data, &view->size)) + { + sqlite3* db = tf_ssb_acquire_db_writer(ssb); + tf_ssb_db_add_blob_wants(db, blob_id); + tf_ssb_release_db_writer(ssb, db); + } } } } diff --git a/src/ssb.db.c b/src/ssb.db.c index f2cbf48c..35aa533c 100644 --- a/src/ssb.db.c +++ b/src/ssb.db.c @@ -379,6 +379,15 @@ void tf_ssb_db_init(tf_ssb_t* ssb) _tf_ssb_db_exec(db, "COMMIT TRANSACTION"); tf_printf("Done.\n"); } + if (!_tf_ssb_db_has_rows(db, "SELECT * FROM sqlite_schema WHERE type = 'index' AND name = 'blob_wants_cache_source_id_unique_index'")) + { + tf_printf("Creating blob_wants_cache UNIQUE constraint.\n"); + _tf_ssb_db_exec(db, "BEGIN TRANSACTION"); + _tf_ssb_db_exec(db, "DELETE FROM blob_wants_cache WHERE source IS NULL"); + _tf_ssb_db_exec(db, "CREATE UNIQUE INDEX blob_wants_cache_source_id_unique_index ON blob_wants_cache (COALESCE(source, ''), id)"); + _tf_ssb_db_exec(db, "COMMIT TRANSACTION"); + tf_printf("Done.\n"); + } _tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS blob_wants_cache_id_idx ON blob_wants_cache (id)"); _tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS blob_wants_cache_timestamp_id_idx ON blob_wants_cache (timestamp, id)"); @@ -840,6 +849,31 @@ bool tf_ssb_db_blob_get(tf_ssb_t* ssb, const char* id, uint8_t** out_blob, size_ return result; } +void tf_ssb_db_add_blob_wants(sqlite3* db, const char* id) +{ + sqlite3_stmt* statement; + if (sqlite3_prepare(db, "INSERT OR REPLACE INTO blob_wants_cache (id, timestamp) VALUES (?, unixepoch() * 1000) ON CONFLICT DO UPDATE SET timestamp = excluded.timestamp", -1, + &statement, NULL) == SQLITE_OK) + { + if (sqlite3_bind_text(statement, 1, id, -1, NULL) == SQLITE_OK) + { + if (sqlite3_step(statement) != SQLITE_DONE) + { + tf_printf("blob wants cache update failed: %s.\n", sqlite3_errmsg(db)); + } + else + { + tf_printf("want: %s\n", id); + } + } + sqlite3_finalize(statement); + } + else + { + tf_printf("prepare failed: %s\n", sqlite3_errmsg(db)); + } +} + typedef struct _blob_get_async_t { tf_ssb_t* ssb; diff --git a/src/ssb.db.h b/src/ssb.db.h index 1b10b60e..c7f40030 100644 --- a/src/ssb.db.h +++ b/src/ssb.db.h @@ -599,4 +599,11 @@ typedef struct _tf_ssb_identity_info_t */ tf_ssb_identity_info_t* tf_ssb_db_get_identity_info(tf_ssb_t* ssb, const char* user, const char* package_owner, const char* package_name); +/** +** Add or update a blob wants cache entry. +** @param db The database. +** @param id The wanted blob ID. +*/ +void tf_ssb_db_add_blob_wants(sqlite3* db, const char* id); + /** @} */