From 1f2664e5a8ab03d90c169bec93aa25b08a199fbe Mon Sep 17 00:00:00 2001 From: Cory McWilliams Date: Sun, 11 May 2025 22:20:16 -0400 Subject: [PATCH] ssb: Reduce redundant work in ssb.following. --- src/ssb.db.c | 110 +++++++++++++++++++++++++++++---------------------- 1 file changed, 62 insertions(+), 48 deletions(-) diff --git a/src/ssb.db.c b/src/ssb.db.c index 550a4049..fe23d208 100644 --- a/src/ssb.db.c +++ b/src/ssb.db.c @@ -1577,75 +1577,65 @@ static following_t* _make_following_node(const char* id, following_t*** followin return entry; } -static void _populate_follows_and_blocks(tf_ssb_t* ssb, following_t* entry, following_t*** following, int* following_count, block_node_t* active_blocks, bool include_blocks) +static void _populate_follows_and_blocks( + sqlite3* db, sqlite3_stmt* statement, following_t* entry, following_t*** following, int* following_count, block_node_t* active_blocks, bool include_blocks) { - sqlite3* db = tf_ssb_acquire_db_reader(ssb); - sqlite3_stmt* statement = NULL; - if (sqlite3_prepare(db, - "SELECT content ->> '$.contact' AS contact, content ->> '$.following', content ->> '$.blocking' " - "FROM messages " - "WHERE contact IS NOT NULL AND author = ? AND content ->> '$.type' = 'contact' " - "ORDER BY sequence", - -1, &statement, NULL) == SQLITE_OK) + if (sqlite3_bind_text(statement, 1, entry->id, -1, NULL) == SQLITE_OK) { - if (sqlite3_bind_text(statement, 1, entry->id, -1, NULL) == SQLITE_OK) + while (sqlite3_step(statement) == SQLITE_ROW) { - while (sqlite3_step(statement) == SQLITE_ROW) + const char* contact = (const char*)sqlite3_column_text(statement, 0); + if (sqlite3_column_type(statement, 1) != SQLITE_NULL) { - const char* contact = (const char*)sqlite3_column_text(statement, 0); - if (sqlite3_column_type(statement, 1) != SQLITE_NULL) + bool is_following = sqlite3_column_int(statement, 1) != 0; + following_t* next = _make_following_node(contact, following, following_count, active_blocks, include_blocks); + if (next) { - bool is_following = sqlite3_column_int(statement, 1) != 0; - following_t* next = _make_following_node(contact, following, following_count, active_blocks, include_blocks); - if (next) + if (is_following) { - if (is_following) + if (_add_following_entry(&entry->following, &entry->following_count, next)) { - if (_add_following_entry(&entry->following, &entry->following_count, next)) - { - next->ref_count++; - } + next->ref_count++; } - else + } + else + { + if (_remove_following_entry(&entry->following, &entry->following_count, next)) { - if (_remove_following_entry(&entry->following, &entry->following_count, next)) - { - next->ref_count--; - } + next->ref_count--; } } } - if (sqlite3_column_type(statement, 2) != SQLITE_NULL) + } + if (sqlite3_column_type(statement, 2) != SQLITE_NULL) + { + bool is_blocking = sqlite3_column_int(statement, 2) != 0; + following_t* next = _make_following_node(contact, following, following_count, active_blocks, include_blocks); + if (next) { - bool is_blocking = sqlite3_column_int(statement, 2) != 0; - following_t* next = _make_following_node(contact, following, following_count, active_blocks, include_blocks); - if (next) + if (is_blocking) { - if (is_blocking) + if (_add_following_entry(&entry->blocking, &entry->blocking_count, next)) { - if (_add_following_entry(&entry->blocking, &entry->blocking_count, next)) - { - next->block_ref_count++; - } + next->block_ref_count++; } - else + } + else + { + if (_remove_following_entry(&entry->blocking, &entry->blocking_count, next)) { - if (_remove_following_entry(&entry->blocking, &entry->blocking_count, next)) - { - next->block_ref_count--; - } + next->block_ref_count--; } } } } } - sqlite3_finalize(statement); } - tf_ssb_release_db_reader(ssb, db); + sqlite3_reset(statement); } -static void _get_following( - tf_ssb_t* ssb, following_t* entry, following_t*** following, int* following_count, int depth, int max_depth, block_node_t* active_blocks, bool include_blocks) +static void _get_following(sqlite3* db, sqlite3_stmt* statement, following_t* entry, following_t*** following, int* following_count, int depth, int max_depth, + block_node_t* active_blocks, bool include_blocks) { int old_depth = entry->depth; entry->depth = tf_min(depth, entry->depth); @@ -1656,28 +1646,47 @@ static void _get_following( if (!entry->populated) { entry->populated = true; - _populate_follows_and_blocks(ssb, entry, following, following_count, active_blocks, include_blocks); + _populate_follows_and_blocks(db, statement, entry, following, following_count, active_blocks, include_blocks); } block_node_t blocks = { .entry = entry, .parent = active_blocks }; for (int i = 0; i < entry->following_count; i++) { - _get_following(ssb, entry->following[i], following, following_count, depth + 1, max_depth, &blocks, include_blocks); + _get_following(db, statement, entry->following[i], following, following_count, depth + 1, max_depth, &blocks, include_blocks); } } } } +static sqlite3_stmt* _make_following_statement(sqlite3* db) +{ + sqlite3_stmt* statement = NULL; + if (sqlite3_prepare(db, + "SELECT content ->> '$.contact' AS contact, content ->> '$.following', content ->> '$.blocking' " + "FROM messages " + "WHERE contact IS NOT NULL AND author = ? AND content ->> '$.type' = 'contact' " + "ORDER BY sequence", + -1, &statement, NULL) != SQLITE_OK) + { + tf_printf("prepare failed: %s", sqlite3_errmsg(db)); + } + return statement; +} + tf_ssb_following_t* tf_ssb_db_following_deep(tf_ssb_t* ssb, const char** ids, int count, int depth, bool include_blocks) { following_t** following = NULL; int following_count = 0; + sqlite3* db = tf_ssb_acquire_db_reader(ssb); + sqlite3_stmt* statement = _make_following_statement(db); for (int i = 0; i < count; i++) { following_t* entry = _make_following_node(ids[i], &following, &following_count, NULL, include_blocks); - _get_following(ssb, entry, &following, &following_count, 0, depth, NULL, include_blocks); + _get_following(db, statement, entry, &following, &following_count, 0, depth, NULL, include_blocks); entry->ref_count++; } + sqlite3_finalize(statement); + tf_ssb_release_db_reader(ssb, db); int actual_following_count = 0; for (int i = 0; i < following_count; i++) @@ -1721,12 +1730,17 @@ const char** tf_ssb_db_following_deep_ids(tf_ssb_t* ssb, const char** ids, int c { following_t** following = NULL; int following_count = 0; + + sqlite3* db = tf_ssb_acquire_db_reader(ssb); + sqlite3_stmt* statement = _make_following_statement(db); for (int i = 0; i < count; i++) { following_t* entry = _make_following_node(ids[i], &following, &following_count, NULL, false); - _get_following(ssb, entry, &following, &following_count, 0, depth, NULL, false); + _get_following(db, statement, entry, &following, &following_count, 0, depth, NULL, false); entry->ref_count++; } + sqlite3_finalize(statement); + tf_ssb_release_db_reader(ssb, db); int actual_following_count = 0; for (int i = 0; i < following_count; i++)