static void saveProgress( tr_benc * dict, const tr_torrent * tor ) { size_t i, n; time_t * mtimes; tr_benc * p; tr_benc * m; const tr_bitfield * bitfield; p = tr_bencDictAdd( dict, KEY_PROGRESS ); tr_bencInitDict( p, 2 ); /* add the mtimes */ mtimes = tr_torrentGetMTimes( tor, &n ); m = tr_bencDictAddList( p, KEY_PROGRESS_MTIMES, n ); for( i = 0; i < n; ++i ) { if( !tr_torrentIsFileChecked( tor, i ) ) mtimes[i] = ~(time_t)0; /* force a recheck */ tr_bencListAddInt( m, mtimes[i] ); } /* add the bitfield */ bitfield = tr_cpBlockBitfield( tor->completion ); tr_bencDictAddRaw( p, KEY_PROGRESS_BITFIELD, bitfield->bits, bitfield->byteCount ); /* cleanup */ tr_free( mtimes ); }
static tr_benc* get_node (struct jsonsl_st * jsn) { tr_benc * parent; tr_benc * node = NULL; struct json_wrapper_data * data = jsn->data; parent = tr_ptrArrayEmpty (&data->stack) ? NULL : tr_ptrArrayBack (&data->stack); if (!parent) { node = data->top; } else if (tr_bencIsList (parent)) { node = tr_bencListAdd (parent); } else if (tr_bencIsDict (parent) && (data->key!=NULL)) { node = tr_bencDictAdd (parent, data->key); tr_free (data->key); data->key = NULL; } return node; }
static tr_benc* getNode( struct json_benc_data * data ) { tr_benc * parent; tr_benc * node = NULL; if( tr_ptrArrayEmpty( data->stack ) ) parent = NULL; else parent = tr_ptrArrayBack( data->stack ); if( !parent ) node = data->top; else if( tr_bencIsList( parent ) ) node = tr_bencListAdd( parent ); else if( tr_bencIsDict( parent ) && data->key ) { node = tr_bencDictAdd( parent, data->key ); tr_free( data->key ); data->key = NULL; } return node; }
static void saveProgress( tr_benc * dict, tr_torrent * tor ) { tr_benc * l; tr_benc * prog; tr_file_index_t fi; const tr_info * inf = tr_torrentInfo( tor ); const time_t now = tr_time( ); prog = tr_bencDictAddDict( dict, KEY_PROGRESS, 3 ); /* add the file/piece check timestamps... */ l = tr_bencDictAddList( prog, KEY_PROGRESS_CHECKTIME, inf->fileCount ); for( fi=0; fi<inf->fileCount; ++fi ) { const tr_piece * p; const tr_piece * pend; time_t oldest_nonzero = now; time_t newest = 0; tr_bool has_zero = FALSE; const time_t mtime = tr_torrentGetFileMTime( tor, fi ); const tr_file * f = &inf->files[fi]; /* get the oldest and newest nonzero timestamps for pieces in this file */ for( p=&inf->pieces[f->firstPiece], pend=&inf->pieces[f->lastPiece]; p!=pend; ++p ) { if( !p->timeChecked ) has_zero = TRUE; else if( oldest_nonzero > p->timeChecked ) oldest_nonzero = p->timeChecked; if( newest < p->timeChecked ) newest = p->timeChecked; } /* If some of a file's pieces have been checked more recently than the file's mtime, and some lest recently, then that file will have a list containing timestamps for each piece. However, the most common use case is that the file doesn't change after it's downloaded. To reduce overhead in the .resume file, only a single timestamp is saved for the file if *all* or *none* of the pieces were tested more recently than the file's mtime. */ if( !has_zero && ( mtime <= oldest_nonzero ) ) /* all checked */ tr_bencListAddInt( l, oldest_nonzero ); else if( newest < mtime ) /* none checked */ tr_bencListAddInt( l, newest ); else { /* some are checked, some aren't... so list piece by piece */ const int offset = oldest_nonzero - 1; tr_benc * ll = tr_bencListAddList( l, 2 + f->lastPiece - f->firstPiece ); tr_bencListAddInt( ll, offset ); for( p=&inf->pieces[f->firstPiece], pend=&inf->pieces[f->lastPiece]+1; p!=pend; ++p ) tr_bencListAddInt( ll, p->timeChecked ? p->timeChecked - offset : 0 ); } } /* add the progress */ if( tor->completeness == TR_SEED ) tr_bencDictAddStr( prog, KEY_PROGRESS_HAVE, "all" ); /* add the blocks bitfield */ tr_bitsetToBenc( tr_cpBlockBitset( &tor->completion ), tr_bencDictAdd( prog, KEY_PROGRESS_BLOCKS ) ); }