diff options
Diffstat (limited to 'data.c')
| -rw-r--r-- | data.c | 121 |
1 files changed, 110 insertions, 11 deletions
| @@ -328,6 +328,51 @@ int index_add(const char *fn, const char *id) | |||
| 328 | } | 328 | } |
| 329 | 329 | ||
| 330 | 330 | ||
| 331 | int index_del_md5(const char *fn, const char *md5) | ||
| 332 | /* deletes an md5 from an index */ | ||
| 333 | { | ||
| 334 | int status = 404; | ||
| 335 | FILE *f; | ||
| 336 | |||
| 337 | pthread_mutex_lock(&data_mutex); | ||
| 338 | |||
| 339 | if ((f = fopen(fn, "r+")) != NULL) { | ||
| 340 | char line[256]; | ||
| 341 | |||
| 342 | while (fgets(line, sizeof(line), f) != NULL) { | ||
| 343 | line[32] = '\0'; | ||
| 344 | |||
| 345 | if (strcmp(line, md5) == 0) { | ||
| 346 | /* found! just rewind, overwrite it with garbage | ||
| 347 | and an eventual call to index_gc() will clean it | ||
| 348 | [yes: this breaks index_len()] */ | ||
| 349 | fseek(f, -33, SEEK_CUR); | ||
| 350 | fwrite("-", 1, 1, f); | ||
| 351 | status = 200; | ||
| 352 | |||
| 353 | break; | ||
| 354 | } | ||
| 355 | } | ||
| 356 | |||
| 357 | fclose(f); | ||
| 358 | } | ||
| 359 | else | ||
| 360 | status = 500; | ||
| 361 | |||
| 362 | pthread_mutex_unlock(&data_mutex); | ||
| 363 | |||
| 364 | return status; | ||
| 365 | } | ||
| 366 | |||
| 367 | |||
| 368 | int index_del(const char *fn, const char *id) | ||
| 369 | /* deletes an id from an index */ | ||
| 370 | { | ||
| 371 | xs *md5 = xs_md5_hex(id, strlen(id)); | ||
| 372 | return index_del_md5(fn, md5); | ||
| 373 | } | ||
| 374 | |||
| 375 | |||
| 331 | int index_gc(const char *fn) | 376 | int index_gc(const char *fn) |
| 332 | /* garbage-collects an index, deleting objects that are not here */ | 377 | /* garbage-collects an index, deleting objects that are not here */ |
| 333 | { | 378 | { |
| @@ -772,6 +817,23 @@ int object_admire(const char *id, const char *actor, int like) | |||
| 772 | } | 817 | } |
| 773 | 818 | ||
| 774 | 819 | ||
| 820 | int object_unadmire(const char *id, const char *actor, int like) | ||
| 821 | /* actor no longer likes or announces this object */ | ||
| 822 | { | ||
| 823 | int status; | ||
| 824 | xs *fn = _object_fn(id); | ||
| 825 | |||
| 826 | fn = xs_replace_i(fn, ".json", like ? "_l.idx" : "_a.idx"); | ||
| 827 | |||
| 828 | status = index_del(fn, actor); | ||
| 829 | |||
| 830 | srv_debug(0, | ||
| 831 | xs_fmt("object_unadmire (%s) %s %s %d", like ? "Like" : "Announce", actor, fn, status)); | ||
| 832 | |||
| 833 | return status; | ||
| 834 | } | ||
| 835 | |||
| 836 | |||
| 775 | int _object_user_cache(snac *snac, const char *id, const char *cachedir, int del) | 837 | int _object_user_cache(snac *snac, const char *id, const char *cachedir, int del) |
| 776 | /* adds or deletes from a user cache */ | 838 | /* adds or deletes from a user cache */ |
| 777 | { | 839 | { |
| @@ -969,8 +1031,13 @@ void timeline_update_indexes(snac *snac, const char *id) | |||
| 969 | 1031 | ||
| 970 | if (valid_status(object_get(id, &msg))) { | 1032 | if (valid_status(object_get(id, &msg))) { |
| 971 | /* if its ours and is public, also store in public */ | 1033 | /* if its ours and is public, also store in public */ |
| 972 | if (is_msg_public(snac, msg)) | 1034 | if (is_msg_public(snac, msg)) { |
| 973 | object_user_cache_add(snac, id, "public"); | 1035 | object_user_cache_add(snac, id, "public"); |
| 1036 | |||
| 1037 | /* also add it to the instance public timeline */ | ||
| 1038 | xs *ipt = xs_fmt("%s/public.idx", srv_basedir); | ||
| 1039 | index_add(ipt, id); | ||
| 1040 | } | ||
| 974 | } | 1041 | } |
| 975 | } | 1042 | } |
| 976 | } | 1043 | } |
| @@ -1041,7 +1108,7 @@ xs_list *timeline_top_level(snac *snac, xs_list *list) | |||
| 1041 | } | 1108 | } |
| 1042 | 1109 | ||
| 1043 | 1110 | ||
| 1044 | d_char *timeline_simple_list(snac *snac, const char *idx_name, int skip, int show) | 1111 | xs_list *timeline_simple_list(snac *snac, const char *idx_name, int skip, int show) |
| 1045 | /* returns a timeline (with all entries) */ | 1112 | /* returns a timeline (with all entries) */ |
| 1046 | { | 1113 | { |
| 1047 | int c_max; | 1114 | int c_max; |
| @@ -1059,7 +1126,7 @@ d_char *timeline_simple_list(snac *snac, const char *idx_name, int skip, int sho | |||
| 1059 | } | 1126 | } |
| 1060 | 1127 | ||
| 1061 | 1128 | ||
| 1062 | d_char *timeline_list(snac *snac, const char *idx_name, int skip, int show) | 1129 | xs_list *timeline_list(snac *snac, const char *idx_name, int skip, int show) |
| 1063 | /* returns a timeline (only top level entries) */ | 1130 | /* returns a timeline (only top level entries) */ |
| 1064 | { | 1131 | { |
| 1065 | xs *list = timeline_simple_list(snac, idx_name, skip, show); | 1132 | xs *list = timeline_simple_list(snac, idx_name, skip, show); |
| @@ -1068,6 +1135,15 @@ d_char *timeline_list(snac *snac, const char *idx_name, int skip, int show) | |||
| 1068 | } | 1135 | } |
| 1069 | 1136 | ||
| 1070 | 1137 | ||
| 1138 | xs_list *timeline_instance_list(int skip, int show) | ||
| 1139 | /* returns the timeline for the full instance */ | ||
| 1140 | { | ||
| 1141 | xs *idx = xs_fmt("%s/public.idx", srv_basedir); | ||
| 1142 | |||
| 1143 | return index_list_desc(idx, skip, show); | ||
| 1144 | } | ||
| 1145 | |||
| 1146 | |||
| 1071 | /** following **/ | 1147 | /** following **/ |
| 1072 | 1148 | ||
| 1073 | /* this needs special treatment and cannot use the object db as is, | 1149 | /* this needs special treatment and cannot use the object db as is, |
| @@ -1273,30 +1349,49 @@ int is_hidden(snac *snac, const char *id) | |||
| 1273 | } | 1349 | } |
| 1274 | 1350 | ||
| 1275 | 1351 | ||
| 1276 | int actor_add(snac *snac, const char *actor, d_char *msg) | 1352 | int actor_add(const char *actor, xs_dict *msg) |
| 1277 | /* adds an actor */ | 1353 | /* adds an actor */ |
| 1278 | { | 1354 | { |
| 1279 | return object_add_ow(actor, msg); | 1355 | return object_add_ow(actor, msg); |
| 1280 | } | 1356 | } |
| 1281 | 1357 | ||
| 1282 | 1358 | ||
| 1283 | int actor_get(snac *snac, const char *actor, d_char **data) | 1359 | int actor_get(snac *snac1, const char *actor, xs_dict **data) |
| 1284 | /* returns an already downloaded actor */ | 1360 | /* returns an already downloaded actor */ |
| 1285 | { | 1361 | { |
| 1286 | int status = 200; | 1362 | int status = 200; |
| 1287 | d_char *d; | 1363 | xs_dict *d = NULL; |
| 1288 | 1364 | ||
| 1289 | if (strcmp(actor, snac->actor) == 0) { | 1365 | if (strcmp(actor, snac1->actor) == 0) { |
| 1290 | /* this actor */ | 1366 | /* this actor */ |
| 1291 | if (data) | 1367 | if (data) |
| 1292 | *data = msg_actor(snac); | 1368 | *data = msg_actor(snac1); |
| 1293 | 1369 | ||
| 1294 | return status; | 1370 | return status; |
| 1295 | } | 1371 | } |
| 1296 | 1372 | ||
| 1373 | if (xs_startswith(actor, srv_baseurl)) { | ||
| 1374 | /* it's a (possible) local user */ | ||
| 1375 | xs *l = xs_split(actor, "/"); | ||
| 1376 | const char *uid = xs_list_get(l, -1); | ||
| 1377 | snac user; | ||
| 1378 | |||
| 1379 | if (!xs_is_null(uid) && user_open(&user, uid)) { | ||
| 1380 | if (data) | ||
| 1381 | *data = msg_actor(&user); | ||
| 1382 | |||
| 1383 | user_free(&user); | ||
| 1384 | return 200; | ||
| 1385 | } | ||
| 1386 | else | ||
| 1387 | return 404; | ||
| 1388 | } | ||
| 1389 | |||
| 1297 | /* read the object */ | 1390 | /* read the object */ |
| 1298 | if (!valid_status(status = object_get(actor, &d))) | 1391 | if (!valid_status(status = object_get(actor, &d))) { |
| 1392 | d = xs_free(d); | ||
| 1299 | return status; | 1393 | return status; |
| 1394 | } | ||
| 1300 | 1395 | ||
| 1301 | if (data) | 1396 | if (data) |
| 1302 | *data = d; | 1397 | *data = d; |
| @@ -1719,7 +1814,7 @@ static xs_dict *_new_qmsg(const char *type, const xs_val *msg, int retries) | |||
| 1719 | } | 1814 | } |
| 1720 | 1815 | ||
| 1721 | 1816 | ||
| 1722 | void enqueue_input(snac *snac, xs_dict *msg, xs_dict *req, int retries) | 1817 | void enqueue_input(snac *snac, const xs_dict *msg, const xs_dict *req, int retries) |
| 1723 | /* enqueues an input message */ | 1818 | /* enqueues an input message */ |
| 1724 | { | 1819 | { |
| 1725 | xs *qmsg = _new_qmsg("input", msg, retries); | 1820 | xs *qmsg = _new_qmsg("input", msg, retries); |
| @@ -2020,7 +2115,11 @@ void purge_server(void) | |||
| 2020 | xs *ib_dir = xs_fmt("%s/inbox", srv_basedir); | 2115 | xs *ib_dir = xs_fmt("%s/inbox", srv_basedir); |
| 2021 | _purge_dir(ib_dir, 7); | 2116 | _purge_dir(ib_dir, 7); |
| 2022 | 2117 | ||
| 2023 | srv_debug(1, xs_fmt("purge: global (obj: %d, idx: %d)", cnt, icnt)); | 2118 | /* purge the instance timeline */ |
| 2119 | xs *itl_fn = xs_fmt("%s/public.idx", srv_basedir); | ||
| 2120 | int itl_gc = index_gc(itl_fn); | ||
| 2121 | |||
| 2122 | srv_debug(1, xs_fmt("purge: global (obj: %d, idx: %d, itl: %d)", cnt, icnt, itl_gc)); | ||
| 2024 | } | 2123 | } |
| 2025 | 2124 | ||
| 2026 | 2125 | ||