jcs
/subtext
/amendments
/418
board: Fix local boards, cache date with post ids in index
jcs made amendment 418 about 1 year ago
--- board.c Tue Mar 14 10:53:46 2023
+++ board.c Wed Mar 15 14:02:33 2023
@@ -159,6 +159,7 @@ short board_post_read(struct session *s, struct board
size_t board_find_post_ids(struct session *s, struct board *board,
size_t *npost_ids, unsigned long **post_ids, size_t offset,
size_t limit);
+void board_delete_cached_index(struct board *board);
void
board_list_ftn_areas(struct session *s)
@@ -467,7 +468,7 @@ board_list_posts(struct session *s, struct board *boar
board_post_object_fields, nboard_post_object_fields, data,
size, &post, sizeof(post), false);
xfree(&data);
- if (ret == BILE_ERR_NO_MEMORY)
+ if (ret != 0)
break;
if (post.thread_id != thread.thread_id) {
@@ -869,11 +870,11 @@ board_post_read(struct session *s, struct board *board
session_flush(s);
if (board->ftn_area[0]) {
- board_delete_ftn_post(s, board, &fpost);
+ board_delete_ftn_post(board, &fpost);
session_logf(s, "Deleted %s post %ld",
db->config.ftn_network, post.id);
} else {
- board_delete_post(s, board, &post, &thread);
+ board_delete_post(board, &post, &thread);
session_logf(s, "Deleted post %ld (thread %ld)",
post.id, thread.thread_id);
}
@@ -942,25 +943,26 @@ size_t
board_find_post_ids(struct session *s, struct board *board,
size_t *npost_ids, unsigned long **post_ids, size_t offset, size_t limit)
{
- unsigned long *all_post_ids;
+ struct board_id_time_map *all_post_id_map;
size_t n, size, nall_post_ids;
*post_ids = NULL;
*npost_ids = 0;
- size = bile_read_alloc(board->bile, BOARD_SORTED_IDS_RTYPE, 1,
- &all_post_ids);
- if (all_post_ids == NULL) {
+ size = bile_read_alloc(board->bile, BOARD_SORTED_ID_MAP_RTYPE, 1,
+ &all_post_id_map);
+ if (all_post_id_map == NULL) {
session_printf(s, "%sPlease wait, re-indexing board posts...%s",
ansi(s, ANSI_BOLD, ANSI_END), ansi(s, ANSI_RESET, ANSI_END));
session_flush(s);
- nall_post_ids = board_index_sorted_post_ids(board, &all_post_ids);
+ nall_post_ids = board_index_sorted_post_ids(board,
+ &all_post_id_map);
session_output(s, "\r\n", 2);
session_flush(s);
if (nall_post_ids == 0)
return 0;
} else
- nall_post_ids = size / sizeof(long);
+ nall_post_ids = size / sizeof(struct board_id_time_map);
*post_ids = xcalloc(sizeof(long), MIN(limit, nall_post_ids));
if (*post_ids == NULL)
@@ -970,15 +972,15 @@ board_find_post_ids(struct session *s, struct board *b
if (n < offset)
continue;
- (*post_ids)[*npost_ids] = all_post_ids[n];
+ (*post_ids)[*npost_ids] = all_post_id_map[n].id;
(*npost_ids)++;
if (*npost_ids >= limit)
break;
}
- if (all_post_ids != NULL)
- xfree(&all_post_ids);
+ if (all_post_id_map != NULL)
+ xfree(&all_post_id_map);
return nall_post_ids;
}
@@ -997,23 +999,24 @@ board_post_create(struct board *board, struct board_th
size_t size, insert, npost_ids;
ssize_t n, j;
unsigned long *post_ids, *parent_post_ids;
+ struct board_id_time_map *id_map;
if (board->ftn_area[0]) {
- post->id = bile_next_id(board->bile, BOARD_FTN_POST_RTYPE);
-
+ if (!post->id)
+ post->id = bile_next_id(board->bile, BOARD_FTN_POST_RTYPE);
if (!post->time)
post->time = Time;
if (!fidopkt_parse_address(db->config.ftn_node_addr,
&our_address)) {
- logger_printf("[board] invalid FTN local node address, can't "
+ logger_printf("[board] Invalid FTN local node address, can't "
"create board post");
post->id = 0;
goto done;
}
if (!fidopkt_parse_address(db->config.ftn_hub_addr,
&hub_address)) {
- logger_printf("[board] invalid FTN hub address, can't "
+ logger_printf("[board] Invalid FTN hub address, can't "
"create board post");
post->id = 0;
goto done;
@@ -1102,24 +1105,10 @@ board_post_create(struct board *board, struct board_th
}
xfree(&data);
- /* assume our post is now the newest, prepend its id */
- o = bile_find(board->bile, BOARD_SORTED_IDS_RTYPE, 1);
- size = (o ? o->size : 0) + sizeof(unsigned long);
- npost_ids = (o ? (o->size / sizeof(unsigned long)) : 0) + 1;
- post_ids = xmalloc(size);
- if (post_ids == NULL) {
- if (o)
- xfree(&o);
- goto done;
- }
- post_ids[0] = post->id;
- if (o) {
- bile_read(board->bile, BOARD_SORTED_IDS_RTYPE, 1,
- post_ids + 1, o->size);
- xfree(&o);
- }
- bile_write(board->bile, BOARD_SORTED_IDS_RTYPE, 1, post_ids, size);
+ board_delete_cached_index(board);
} else {
+ if (!post->id)
+ post->id = bile_next_id(board->bile, BOARD_POST_RTYPE);
if (!post->time)
post->time = Time;
@@ -1153,7 +1142,7 @@ board_post_create(struct board *board, struct board_th
sizeof(long));
if (post_ids == NULL)
return 0;
- thread->post_ids == post_ids;
+ thread->post_ids = post_ids;
parent_post_ids = xreallocarray(thread->parent_post_ids,
thread->nposts, sizeof(long));
if (parent_post_ids == NULL)
@@ -1209,8 +1198,8 @@ done:
}
void
-board_delete_post(struct session *s, struct board *board,
- struct board_post *post, struct board_thread *thread)
+board_delete_post(struct board *board, struct board_post *post,
+ struct board_thread *thread)
{
size_t size, n, nn;
char *data, *body;
@@ -1225,6 +1214,7 @@ board_delete_post(struct session *s, struct board *boa
0);
bile_delete(board->bile, BOARD_POST_RTYPE, post->id,
BILE_DELETE_FLAG_PURGE);
+ board_delete_cached_index(board);
return;
}
@@ -1285,6 +1275,7 @@ board_delete_post(struct session *s, struct board *boa
bile_delete(board->bile, BOARD_POST_RTYPE, post->id,
BILE_DELETE_FLAG_ZERO | BILE_DELETE_FLAG_PURGE);
+ board_delete_cached_index(board);
bile_flush(board->bile, true);
return;
@@ -1293,8 +1284,7 @@ board_delete_post(struct session *s, struct board *boa
/* all we can do is change the post to say deleted */
if (post->body != NULL)
xfree(&post->body);
- snprintf(del, sizeof(del), "[ Post deleted by %s ]",
- s->user ? s->user->username : "unknown");
+ snprintf(del, sizeof(del), "[ Post deleted ]");
body = xstrdup(del);
if (body == NULL)
return;
@@ -1319,49 +1309,50 @@ board_delete_post(struct session *s, struct board *boa
}
void
-board_delete_ftn_post(struct session *s, struct board *board,
- struct board_ftn_post *post)
+board_delete_ftn_post(struct board *board, struct board_ftn_post *post)
{
size_t size, npost_ids, n;
- unsigned long *post_ids;
+ struct board_id_time_map *id_map;
bile_delete(board->bile, BOARD_FTN_POST_RTYPE, post->id,
BILE_DELETE_FLAG_PURGE);
- size = bile_read_alloc(board->bile, BOARD_SORTED_IDS_RTYPE, 1,
- &post_ids);
- if (size == 0 || post_ids == NULL)
+ size = bile_read_alloc(board->bile, BOARD_SORTED_ID_MAP_RTYPE, 1,
+ &id_map);
+ if (size == 0 || id_map == NULL)
return;
- npost_ids = size / sizeof(long);
+ npost_ids = size / sizeof(struct board_id_time_map);
for (n = 0; n < npost_ids; n++) {
- if (post_ids[n] == post->id) {
+ if (id_map[n].id == post->id) {
for (; n < npost_ids - 1; n++)
- post_ids[n] = post_ids[n + 1];
+ id_map[n] = id_map[n + 1];
npost_ids--;
break;
}
}
- bile_write(board->bile, BOARD_SORTED_IDS_RTYPE, 1, post_ids,
- sizeof(long) * npost_ids);
+ bile_write(board->bile, BOARD_SORTED_ID_MAP_RTYPE, 1, id_map,
+ sizeof(struct board_id_time_map) * npost_ids);
}
size_t
board_index_sorted_post_ids(struct board *board,
- unsigned long **sorted_ids)
+ struct board_id_time_map **sorted_id_map)
{
- struct board_id_time_map {
+ struct thread_time_map {
unsigned long id;
time_t time;
size_t nposts;
};
struct board_ftn_post fpost;
+ struct board_post post;
struct board_thread thread;
size_t ret, size, i, j, n, npost_ids, nthread_ids;
unsigned long *post_ids, *thread_ids;
- struct board_id_time_map *id_map, *thread_map, tmp_map;
+ struct board_id_time_map *id_map, tmp_id_map;
+ struct thread_time_map *thread_map, tmp_thread_map;
char *data;
if (board->ftn_area[0]) {
@@ -1391,25 +1382,19 @@ board_index_sorted_post_ids(struct board *board,
for (i = 0; i < npost_ids; i++) {
for (j = 0; j < npost_ids - i - 1; j++) {
if (id_map[j].time < id_map[j + 1].time) {
- tmp_map = id_map[j];
+ tmp_id_map = id_map[j];
id_map[j] = id_map[j + 1];
- id_map[j + 1] = tmp_map;
+ id_map[j + 1] = tmp_id_map;
}
}
}
-
- for (j = 0; j < npost_ids; j++)
- post_ids[j] = id_map[j].id;
-
- xfree(&id_map);
} else {
nthread_ids = bile_ids_by_type(board->bile, BOARD_THREAD_RTYPE,
&thread_ids);
if (nthread_ids == 0)
goto write_out;
- thread_map = xcalloc(sizeof(struct board_id_time_map),
- nthread_ids);
+ thread_map = xcalloc(sizeof(struct thread_time_map), nthread_ids);
if (thread_map == NULL)
goto write_out;
@@ -1421,7 +1406,7 @@ board_index_sorted_post_ids(struct board *board,
board_thread_object_fields, nboard_thread_object_fields, data,
size, &thread, sizeof(thread), false);
xfree(&data);
- if (ret == BILE_ERR_NO_MEMORY)
+ if (ret != 0)
goto write_out;
thread_map[n].id = thread.thread_id;
@@ -1436,15 +1421,15 @@ board_index_sorted_post_ids(struct board *board,
for (i = 0; i < nthread_ids; i++) {
for (j = 0; j < nthread_ids - i - 1; j++) {
if (thread_map[j].time < thread_map[j + 1].time) {
- tmp_map = thread_map[j];
+ tmp_thread_map = thread_map[j];
thread_map[j] = thread_map[j + 1];
- thread_map[j + 1] = tmp_map;
+ thread_map[j + 1] = tmp_thread_map;
}
}
}
- post_ids = xcalloc(sizeof(long), npost_ids);
- if (post_ids == NULL)
+ id_map = xcalloc(sizeof(struct board_id_time_map), npost_ids);
+ if (id_map == NULL)
goto write_out;
npost_ids = 0;
@@ -1457,12 +1442,27 @@ board_index_sorted_post_ids(struct board *board,
board_thread_object_fields, nboard_thread_object_fields, data,
size, &thread, sizeof(thread), true);
xfree(&data);
- if (ret == 0)
+ if (ret != 0)
goto write_out;
/* these are already sorted, and we want to keep thread sort */
- for (i = 0; i < thread.nposts; i++)
- post_ids[npost_ids++] = thread.post_ids[i];
+ for (i = 0; i < thread.nposts; i++) {
+ /* only read as far as the time */
+ size = bile_read(board->bile, BOARD_POST_RTYPE,
+ thread.post_ids[i], &post,
+ offsetof(struct board_post, time) +
+ member_size(struct board_post, time));
+ if (size == 0) {
+ logger_printf("[board] Board %s thread %ld post %ld "
+ "is missing", board->name, thread.thread_id,
+ thread.post_ids[i]);
+ continue;
+ }
+
+ id_map[npost_ids].id = post.id;
+ id_map[npost_ids].time = post.time;
+ npost_ids++;
+ }
if (thread.subject != NULL)
xfree(&thread.subject);
@@ -1477,19 +1477,18 @@ board_index_sorted_post_ids(struct board *board,
write_out:
if (npost_ids == 0) {
- bile_delete(board->bile, BOARD_SORTED_IDS_RTYPE, 1,
- BILE_DELETE_FLAG_PURGE);
- if (sorted_ids != NULL)
- *sorted_ids = NULL;
+ board_delete_cached_index(board);
+ if (sorted_id_map != NULL)
+ *sorted_id_map = NULL;
return 0;
}
- bile_write(board->bile, BOARD_SORTED_IDS_RTYPE, 1, post_ids,
- sizeof(long) * npost_ids);
- if (sorted_ids == NULL)
- xfree(&post_ids);
+ bile_write(board->bile, BOARD_SORTED_ID_MAP_RTYPE, 1, id_map,
+ sizeof(struct board_id_time_map) * npost_ids);
+ if (sorted_id_map == NULL)
+ xfree(&id_map);
else
- *sorted_ids = post_ids;
+ *sorted_id_map = id_map;
return npost_ids;
}
@@ -1518,7 +1517,7 @@ board_toss_ftn_message(struct board *board,
asize = o->size + sizeof(struct board_ftn_msgid_cache);
msgid_cache = xmalloc(asize);
if (msgid_cache == NULL) {
- logger_printf("[board] board_ingest_fidopkt: malloc(%ld) failed",
+ logger_printf("[board] toss: malloc(%ld) failed",
asize);
return -1;
}
@@ -1531,7 +1530,8 @@ board_toss_ftn_message(struct board *board,
msgid_cache = xcalloc(sizeof(struct board_ftn_msgid_cache),
npost_ids + 1);
if (msgid_cache == NULL) {
- logger_printf("[board] board_ingest_fidopkt: calloc failed");
+ logger_printf("[board] toss: calloc(%ld, %ld) failed",
+ sizeof(struct board_ftn_msgid_cache), npost_ids + 1);
return -1;
}
for (n = 0; n < npost_ids; n++) {
@@ -1551,7 +1551,7 @@ board_toss_ftn_message(struct board *board,
for (n = 0; n < npost_ids; n++) {
if (memcmp(&msgid_cache[n].msgid, &msgid, sizeof(msgid)) == 0) {
- logger_printf("[board] already have %s EchoMail %s in %s "
+ logger_printf("[board] Already have %s EchoMail %s in %s "
"(%ld), skipping", db->config.ftn_network,
fidomsg->msgid_orig, board->name, msgid_cache[n].id);
ret = 0;
@@ -1573,7 +1573,7 @@ board_toss_ftn_message(struct board *board,
post.id = bile_next_id(board->bile, BOARD_FTN_POST_RTYPE);
if (!post.id) {
- logger_printf("[board] failed get next id for %s", board->name);
+ logger_printf("[board] Failed get next id for %s", board->name);
ret = -1;
goto done;
}
@@ -1582,14 +1582,14 @@ board_toss_ftn_message(struct board *board,
board_ftn_post_object_fields, nboard_ftn_post_object_fields,
&post, &pdata, &psize);
if (bret != 0 || psize == 0) {
- logger_printf("[board] failed to marshall new post %s %s",
+ logger_printf("[board] Failed to marshall new post %s %s",
fidomsg->area, fidomsg->msgid_orig);
ret = -1;
goto done;
}
if (bile_write(board->bile, BOARD_FTN_POST_RTYPE, post.id, pdata,
psize) != psize) {
- logger_printf("[fidopkt] failed to save new post %s %s: %d",
+ logger_printf("[fidopkt] Failed to save new post %s %s: %d",
fidomsg->area, fidomsg->msgid_orig, bile_error(board->bile));
ret = -1;
xfree(&pdata);
@@ -1605,11 +1605,9 @@ board_toss_ftn_message(struct board *board,
npost_ids++;
dirty_cache = true;
- /* force rebuild of board ID cache the next time someone views it */
- bile_delete(board->bile, BOARD_SORTED_IDS_RTYPE, 1,
- BILE_DELETE_FLAG_PURGE);
+ board_delete_cached_index(board);
- logger_printf("[board] tossed %s EchoMail %s as %ld",
+ logger_printf("[board] Tossed %s EchoMail %s as %ld",
fidomsg->area, fidomsg->msgid_orig, post.id);
uthread_yield();
@@ -1618,7 +1616,7 @@ done:
cache_size = npost_ids * sizeof(struct board_ftn_msgid_cache);
if (bile_write(board->bile, BOARD_FTN_MSGID_CACHE_RTYPE, 1,
msgid_cache, cache_size) != cache_size) {
- logger_printf("[board] failed to save msgid cache for %s: %d",
+ logger_printf("[board] Failed to save msgid cache for %s: %d",
fidomsg->area, bile_error(board->bile));
ret = -1;
}
@@ -1627,4 +1625,95 @@ done:
free(msgid_cache);
return ret;
+}
+
+void
+board_delete_cached_index(struct board *board)
+{
+ bile_delete(board->bile, BOARD_SORTED_ID_MAP_RTYPE, 1,
+ BILE_DELETE_FLAG_PURGE);
+}
+
+void
+board_prune_old_posts(struct board *board)
+{
+ size_t nposts, n;
+ struct board_id_time_map *sorted_id_map;
+ struct board_ftn_post fpost;
+ struct board_post post;
+ struct board_thread thread;
+ time_t oldest;
+ size_t size, deleted;
+ char *data;
+ short ret;
+
+ if (board->retention_days == 0)
+ return;
+
+ deleted = 0;
+
+ nposts = board_index_sorted_post_ids(board, &sorted_id_map);
+ if (nposts == 0)
+ goto done;
+
+ oldest = Time - ((unsigned long)(board->retention_days) *
+ (60UL * 60UL * 24UL));
+
+ for (n = 0; n < nposts; n++) {
+ if (sorted_id_map[n].time >= oldest)
+ continue;
+
+ if (board->ftn_area[0]) {
+ size = bile_read_alloc(board->bile, BOARD_FTN_POST_RTYPE,
+ sorted_id_map[n].id, &data);
+ if (!size)
+ continue;
+ ret = bile_unmarshall_object(board->bile,
+ board_ftn_post_object_fields, nboard_ftn_post_object_fields,
+ data, size, &fpost, sizeof(fpost), false);
+ xfree(&data);
+ if (ret == BILE_ERR_NO_MEMORY)
+ goto done;
+
+ //board_delete_ftn_post(board, &fpost);
+ } else {
+ size = bile_read_alloc(board->bile, BOARD_POST_RTYPE,
+ sorted_id_map[n].id, &data);
+ if (!size)
+ continue;
+ ret = bile_unmarshall_object(board->bile,
+ board_post_object_fields, nboard_post_object_fields,
+ data, size, &post, sizeof(post), false);
+ xfree(&data);
+ if (ret == BILE_ERR_NO_MEMORY)
+ goto done;
+
+ size = bile_read_alloc(board->bile, BOARD_THREAD_RTYPE,
+ post.thread_id, &data);
+ if (!size)
+ continue;
+ ret = bile_unmarshall_object(board->bile,
+ board_thread_object_fields, nboard_thread_object_fields,
+ data, size, &thread, sizeof(thread), false);
+ xfree(&data);
+ if (ret == BILE_ERR_NO_MEMORY)
+ goto done;
+
+ //board_delete_post(board, &post, &thread);
+ }
+
+ deleted++;
+ uthread_yield();
+ }
+
+done:
+ if (sorted_id_map != NULL)
+ xfree(&sorted_id_map);
+
+ if (deleted) {
+ board_index_sorted_post_ids(board, NULL);
+
+ logger_printf("[board] Pruned %lu posts in %s older than %d days",
+ deleted, board->name, board->retention_days);
+ }
}
--- board.h Mon Mar 13 23:40:31 2023
+++ board.h Tue Mar 14 16:57:15 2023
@@ -82,15 +82,21 @@ struct board_thread {
extern const struct bile_object_field board_thread_object_fields[];
extern const size_t nboard_thread_object_fields;
+struct board_id_time_map {
+ unsigned long id;
+ time_t time;
+};
+
void board_list_ftn_areas(struct session *s);
void board_show(struct session *s, short id, char *prompt_prefix);
-void board_delete_post(struct session *s, struct board *board,
- struct board_post *post, struct board_thread *thread);
-void board_delete_ftn_post(struct session *s, struct board *board,
+void board_delete_post(struct board *board, struct board_post *post,
+ struct board_thread *thread);
+void board_delete_ftn_post(struct board *board,
struct board_ftn_post *post);
size_t board_index_sorted_post_ids(struct board *board,
- unsigned long **sorted_ids);
+ struct board_id_time_map **sorted_id_map);
short board_toss_ftn_message(struct board *board,
struct fidopkt_message *fidomsg);
+void board_prune_old_posts(struct board *board);
#endif