Change timeline to use trie that allows arbitrary insertions and deletions instead of list of lists (which doesn't), make all routes other than /api return Soapbox index.html on error

master
teknomunk 1 year ago
parent 6340400943
commit 6954de32d9

@ -153,11 +153,7 @@ bool route_media( struct http_request* req )
bool route_request( struct http_request* req )
{
bool inner( struct http_request* req ) {
if( http_request_route( req, "/api/v1/" ) ) {
return route_mastodon_api( req );
} else if( http_request_route( req, "/api/pleroma" ) ) {
return route_pleroma_api2( req );
} else if( http_request_route( req, "/oauth" ) ) {
if( http_request_route( req, "/oauth" ) ) {
return route_oauth( req );
} else if( http_request_route( req, "/owner" ) ) {
return route_owner( req );
@ -181,7 +177,11 @@ bool route_request( struct http_request* req )
}
}
if( inner( req ) ) {
if( http_request_route( req, "/api/v1/" ) ) {
return route_mastodon_api( req );
} else if( http_request_route( req, "/api/pleroma" ) ) {
return route_pleroma_api2( req );
} else if( inner( req ) ) {
return true;
} else {
return send_asset( req, "assets/soapbox/index.html" );

@ -1 +1 @@
Subproject commit 8e678021ff7804778ad32d0c11dd9ceb47b647fa
Subproject commit 2cc90f4bdfe7b5add8c737075cbc90ae2ba1baee

@ -2,79 +2,24 @@
#include "json/json.h"
#include "json/layout.h"
#include "ffdb/trie.h"
#include "format.h"
#include "model/status.h"
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
enum {
STATUSES_PER_BLOCK = 256,
};
#define OBJ_TYPE struct timeline
static struct json_object_field timeline_block_layout[] = {
JSON_FIELD_ARRAY_OF_INTS( status_ids, true ),
JSON_FIELD_END,
};
struct timeline* timeline_block_load( int id, unsigned int head, unsigned int block )
struct timeline* timeline_from_id( int id )
{
struct timeline* tl = NULL;
FILE* f = NULL;
struct json_pull_parser* jpp = NULL;
printf( "timeline_block_load( %d, %u, %u )\n", id, head, block );
char filename[512];
snprintf( filename, 512, "data/accounts/%d/timeline/%u.json", id, block );
tl = malloc(sizeof(struct timeline));
struct timeline* tl;
tl = malloc(sizeof(*tl));
memset(tl,0,sizeof(*tl));
tl->id = id;
tl->block = head;
tl->head = head;
tl->status_ids.items = NULL;
tl->status_ids.count = 0;
f = fopen( filename, "r" );
if( !f ) {
// New timeline
if( head == block && head == 0 ) {
return tl;
}
goto failed;
}
if( !json_read_object_layout_from_FILE( f, timeline_block_layout, tl ) ) {
f = NULL;
goto failed;
}
cleanup:
return tl;
failed:
fclose(f);
free(tl);
tl = NULL;
goto cleanup;
}
struct timeline* timeline_from_id( int id )
{
char filename[512];
snprintf( filename, 512, "data/accounts/%d/timeline/HEAD", id );
FILE* f = fopen(filename,"r");
unsigned int head = 0;
if( f ) {
fscanf( f, "%u", &head );
fclose(f);
}
return timeline_block_load( id, head, head );
}
struct timeline* timeline_new()
{
@ -83,79 +28,53 @@ void timeline_free( struct timeline* tl )
{
if( !tl ) { return; }
free(tl->status_ids.items);
free(tl);
}
int timeline_load_statuses( struct timeline* tl, int offset_from_head, int count, struct status** result )
{
if( offset_from_head != 0 ) {
return 0;
}
// TODO: take offset_from_head into account to get starting position
if( count > tl->status_ids.count ) {
count = tl->status_ids.count;
}
//printf( "count=%d\n", count );
int found = 0;
for( int i = 0; i < count; ++i ) {
int idx = tl->status_ids.count - ( i + 1 );
struct {
char** items;
int count;
} values;
memset(&values,0,sizeof(values));
result[found] = status_from_id( tl->status_ids.items[idx] );
if( result[found] ) {
found += 1;
} else {
printf( "Couldn't load status with id %d\n", tl->status_ids.items[idx] );
char filename[512];
snprintf( filename, sizeof(filename), "data/accounts/%d/timeline", tl->id );
ffdb_trie_list( filename, offset_from_head, count, NULL, &values );
int result_count = 0;
for( int i = 0; i < values.count && result_count < count; ++i ) {
char* id_str = values.items[i];
struct status* s = status_from_id( atoi(id_str) );
free( id_str );
if( s ) {
result[result_count] = s;
result_count += 1;
}
}
return found;
free(values.items);
return result_count;
}
void timeline_add_post( struct timeline* tl, struct status* s )
{
if( tl->head != tl->block ) {
struct timeline* tl_head = timeline_block_load( tl->id, tl->head, tl->head );
timeline_add_post( tl_head, s );
timeline_free( tl_head );
return;
}
if( tl->status_ids.count >= STATUSES_PER_BLOCK ) {
int new_head = tl->head + 1;
int id = tl->id;
char filename[512];
snprintf( filename, 512, "data/accounts/%d/timeline/HEAD", id );
char tmp_filename[512+32];
snprintf( tmp_filename, 512+32, "%s.tmp", filename );
FILE* head = fopen( filename, "w" );
fprintf( head, "%d", new_head );
fclose(head);
rename( tmp_filename, filename );
tl = malloc(sizeof(struct timeline));
tl->status_ids.count = 0;
tl->status_ids.items = NULL;
tl->id = id;
tl->head = new_head;
tl->block = new_head;
timeline_add_post( tl, s );
timeline_free(tl);
return;
}
tl->status_ids.count += 1;
tl->status_ids.items = realloc( tl->status_ids.items, sizeof(int) * tl->status_ids.count );
tl->status_ids.items[ tl->status_ids.count - 1 ] = s->id;
char filename[512];
snprintf( filename, 512, "data/accounts/%d/timeline/%u.json", tl->id, tl->block );
json_write_object_layout_to_file( filename, "\t", timeline_block_layout, tl );
snprintf( filename, sizeof(filename), "data/accounts/%d/timeline", tl->id );
struct tm gmtime_data;
gmtime_r( &s->published, &gmtime_data );
char key[512];
snprintf( key, sizeof(key), "%04d-%02d-%02dT%02d:%02d:%02dZ",
gmtime_data.tm_year + 1900,
gmtime_data.tm_mon + 1,
gmtime_data.tm_mday,
gmtime_data.tm_hour,
gmtime_data.tm_min,
gmtime_data.tm_sec
);
char value[32];
ffdb_trie_set( filename, key, format( value, sizeof(value), "%d", s->id ) );
}

@ -1,23 +1,9 @@
#pragma once
struct status;
struct timeline_block_ref
{
int starting_offset;
int block_id;
};
struct timeline
{
int id;
unsigned int block;
unsigned int head;
struct {
int* items;
int count;
} status_ids;
};
struct timeline* timeline_from_id( int id );

Loading…
Cancel
Save