@ -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 ) ) ;
}