I think I fixed following calculations, again. Revived the test, though it's still very not thorough.

git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@4662 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
2023-12-07 02:28:49 +00:00
parent f0984b19f2
commit b1714cf554
2 changed files with 141 additions and 93 deletions

View File

@ -1301,6 +1301,7 @@ typedef struct _following_t
int depth;
int ref_count;
int block_ref_count;
bool populated;
} following_t;
static int _following_compare(const void* a, const void* b)
@ -1310,6 +1311,11 @@ static int _following_compare(const void* a, const void* b)
return strcmp(ida, (*followingb)->id);
}
static bool _has_following_entry(const char* id, following_t** list, int count)
{
return bsearch(id, list, count, sizeof(following_t*), _following_compare) != 0;
}
static bool _add_following_entry(following_t*** list, int* count, following_t* add)
{
int index = tf_util_insert_index(add->id, *list, *count, sizeof(following_t*), _following_compare);
@ -1343,19 +1349,37 @@ static bool _remove_following_entry(following_t*** list, int* count, following_t
return false;
}
static following_t* _get_following(tf_ssb_t* ssb, const char* id, following_t*** following, int* following_count, int depth, int max_depth)
typedef struct _block_node_t block_node_t;
typedef struct _block_node_t
{
following_t* entry;
block_node_t* parent;
} block_node_t;
static bool _is_blocked_by_active_blocks(const char* id, const block_node_t* blocks)
{
for (const block_node_t* b = blocks; b; b = b->parent)
{
if (_has_following_entry(id, b->entry->blocking, b->entry->blocking_count))
{
return true;
}
}
return false;
}
static following_t* _make_following_node(const char* id, following_t*** following, int* following_count, block_node_t* blocks)
{
if (_is_blocked_by_active_blocks(id, blocks))
{
return NULL;
}
int index = tf_util_insert_index(id, *following, *following_count, sizeof(following_t*), _following_compare);
following_t* entry = NULL;
bool already_populated = false;
if (index < *following_count && strcmp(id, (*following)[index]->id) == 0)
{
entry = (*following)[index];
already_populated = entry->depth < max_depth;
if (depth < entry->depth)
{
entry->depth = depth;
}
}
else
{
@ -1368,29 +1392,34 @@ static following_t* _get_following(tf_ssb_t* ssb, const char* id, following_t***
(*following)[index] = entry;
(*following_count)++;
memset(entry, 0, sizeof(*entry));
entry->depth = INT_MAX;
snprintf(entry->id, sizeof(entry->id), "%s", id);
entry->depth = depth;
}
return entry;
}
if (depth < max_depth && !already_populated)
static void _populate_follows_and_blocks(tf_ssb_t* ssb, following_t* entry, following_t*** following, int* following_count, block_node_t* active_blocks)
{
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
sqlite3_stmt* statement = NULL;
if (sqlite3_prepare(db,
"SELECT json_extract(content, '$.contact') AS contact, json_extract(content, '$.following'), json_extract(content, '$.blocking') "
"FROM messages "
"WHERE contact IS NOT NULL AND author = ? AND json_extract(content, '$.type') = 'contact' "
"ORDER BY sequence",
-1, &statement, NULL) == SQLITE_OK)
{
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
sqlite3_stmt* statement = NULL;
if (sqlite3_prepare(db, "SELECT json_extract(content, '$.contact'), json_extract(content, '$.following'), json_extract(content, '$.blocking') FROM messages WHERE author = ? AND json_extract(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, 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 (!contact)
bool is_following = sqlite3_column_int(statement, 1) != 0;
following_t* next = _make_following_node(contact, following, following_count, active_blocks);
if (next)
{
continue;
}
if (sqlite3_column_type(statement, 1) != SQLITE_NULL)
{
bool is_following = sqlite3_column_int(statement, 1) != 0;
following_t* next = _get_following(ssb, contact, following, following_count, depth + 1, max_depth);
if (is_following)
{
if (_add_following_entry(&entry->following, &entry->following_count, next))
@ -1406,10 +1435,13 @@ static following_t* _get_following(tf_ssb_t* ssb, const char* id, following_t***
}
}
}
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);
if (next)
{
bool is_blocking = sqlite3_column_int(statement, 2) != 0;
following_t* next = _get_following(ssb, contact, following, following_count, depth + 1, 0 /* don't dig deeper into blocked users */);
if (is_blocking)
{
if (_add_following_entry(&entry->blocking, &entry->blocking_count, next))
@ -1427,11 +1459,32 @@ static following_t* _get_following(tf_ssb_t* ssb, const char* id, following_t***
}
}
}
sqlite3_finalize(statement);
}
tf_ssb_release_db_reader(ssb, db);
sqlite3_finalize(statement);
}
tf_ssb_release_db_reader(ssb, db);
}
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)
{
entry->depth = tf_min(depth, entry->depth);
if (depth < max_depth && !entry->populated && !_is_blocked_by_active_blocks(entry->id, active_blocks))
{
entry->populated = true;
_populate_follows_and_blocks(ssb, entry, following, following_count, active_blocks);
if (depth < max_depth)
{
block_node_t blocks = { .entry = entry, .parent = active_blocks };
for (int i = 0; i < entry->following_count; i++)
{
if (!_has_following_entry(entry->following[i]->id, entry->blocking, entry->blocking_count))
{
_get_following(ssb, entry->following[i], following, following_count, depth + 1, max_depth, &blocks);
}
}
}
}
return entry;
}
tf_ssb_following_t* tf_ssb_db_following_deep(tf_ssb_t* ssb, const char** ids, int count, int depth)
@ -1440,7 +1493,8 @@ tf_ssb_following_t* tf_ssb_db_following_deep(tf_ssb_t* ssb, const char** ids, in
int following_count = 0;
for (int i = 0; i < count; i++)
{
following_t* entry = _get_following(ssb, ids[i], &following, &following_count, 0, depth);
following_t* entry = _make_following_node(ids[i], &following, &following_count, NULL);
_get_following(ssb, entry, &following, &following_count, 0, depth, NULL);
entry->ref_count++;
}
@ -1487,7 +1541,8 @@ const char** tf_ssb_db_following_deep_ids(tf_ssb_t* ssb, const char** ids, int c
int following_count = 0;
for (int i = 0; i < count; i++)
{
following_t* entry = _get_following(ssb, ids[i], &following, &following_count, 0, depth);
following_t* entry = _make_following_node(ids[i], &following, &following_count, NULL);
_get_following(ssb, entry, &following, &following_count, 0, depth, NULL);
entry->ref_count++;
}