Ticket #1521: block-cache-rc1.diff

File block-cache-rc1.diff, 32.4 KB (added by charles, 6 years ago)

Add support to transmission-remote; code cleanup; replace printf messages with tr_dbg calls

  • libtransmission/peer-msgs.c

     
    2222
    2323#include "transmission.h"
    2424#include "bencode.h"
     25#include "cache.h"
    2526#include "completion.h"
    2627#include "crypto.h"
    27 #include "inout.h"
    2828#ifdef WIN32
    2929#include "net.h" /* for ECONN */
    3030#endif
     
    12111211    for( i=msgs->prefetchCount; i<msgs->peer->pendingReqsToClient && i<12; ++i )
    12121212    {
    12131213        const struct peer_request * req = msgs->peerAskedFor + i;
    1214         tr_ioPrefetch( msgs->torrent, req->index, req->offset, req->length );
     1214        tr_cachePrefetchBlock( getSession(msgs)->cache, msgs->torrent, req->index, req->offset, req->length );
    12151215        ++msgs->prefetchCount;
    12161216    }
    12171217}
     
    16011601    ***  Save the block
    16021602    **/
    16031603
    1604     if(( err = tr_ioWrite( tor, req->index, req->offset, req->length, data )))
     1604    if(( err = tr_cacheWriteBlock( getSession(msgs)->cache, tor, req->index, req->offset, req->length, data )))
    16051605        return err;
    16061606
    16071607    addPeerToBlamefield( msgs, req->index );
     
    19131913            tr_peerIoWriteUint32( io, out, req.index );
    19141914            tr_peerIoWriteUint32( io, out, req.offset );
    19151915
    1916             err = tr_ioRead( msgs->torrent, req.index, req.offset, req.length, EVBUFFER_DATA(out)+EVBUFFER_LENGTH(out) );
     1916            err = tr_cacheReadBlock( getSession(msgs)->cache, msgs->torrent, req.index, req.offset, req.length, EVBUFFER_DATA(out)+EVBUFFER_LENGTH(out) );
    19171917            if( err )
    19181918            {
    19191919                if( fext )
  • libtransmission/peer-mgr.c

     
    2121#include "bandwidth.h"
    2222#include "bencode.h"
    2323#include "blocklist.h"
     24#include "cache.h"
    2425#include "clients.h"
    2526#include "completion.h"
    2627#include "crypto.h"
     
    14601461
    14611462                        for( fileIndex=0; fileIndex<tor->info.fileCount; ++fileIndex ) {
    14621463                            const tr_file * file = &tor->info.files[fileIndex];
    1463                             if( ( file->firstPiece <= p ) && ( p <= file->lastPiece ) )
    1464                                 if( tr_cpFileIsComplete( &tor->completion, fileIndex ) )
     1464                            if( ( file->firstPiece <= p ) && ( p <= file->lastPiece ) ) {
     1465                                if( tr_cpFileIsComplete( &tor->completion, fileIndex ) ) {
     1466fprintf( stderr, "flushing complete file %d (%s)\n", fileIndex, tor->info.files[fileIndex].name );
     1467                                    tr_cacheFlushFile( tor->session->cache, tor, fileIndex );
    14651468                                    tr_torrentFileCompleted( tor, fileIndex );
     1469                                }
     1470                            }
    14661471                        }
    14671472
    14681473                        pieceListRemovePiece( t, p );
  • libtransmission/ptrarray.c

     
    102102    return ret;
    103103}
    104104
    105 static void
     105void
    106106tr_ptrArrayErase( tr_ptrArray * t,
    107107                  int           begin,
    108108                  int           end )
     
    123123***
    124124**/
    125125
    126 static int
     126int
    127127tr_ptrArrayLowerBound( const tr_ptrArray *                t,
    128128                       const void *                       ptr,
    129129                       int                 compare( const void *,
     
    184184    const int pos = tr_ptrArrayLowerBound( t, ptr, compare, NULL );
    185185    const int ret = tr_ptrArrayInsert( t, ptr, pos );
    186186
    187     assertSortedAndUnique( t, compare );
     187    //assertSortedAndUnique( t, compare );
    188188    return ret;
    189189}
    190190
  • libtransmission/rpcimpl.c

     
    11841184
    11851185    assert( idle_data == NULL );
    11861186
     1187    if( tr_bencDictFindReal( args_in, TR_PREFS_KEY_MAX_CACHE_SIZE_MiB, &d ) )
     1188        tr_sessionSetCacheLimit( session, d );
    11871189    if( tr_bencDictFindInt( args_in, TR_PREFS_KEY_ALT_SPEED_UP, &i ) )
    11881190        tr_sessionSetAltSpeed( session, TR_UP, i );
    11891191    if( tr_bencDictFindInt( args_in, TR_PREFS_KEY_ALT_SPEED_DOWN, &i ) )
     
    13231325    tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_TIME_DAY,tr_sessionGetAltSpeedDay(s) );
    13241326    tr_bencDictAddBool( d, TR_PREFS_KEY_ALT_SPEED_TIME_ENABLED, tr_sessionUsesAltSpeedTime(s) );
    13251327    tr_bencDictAddBool( d, TR_PREFS_KEY_BLOCKLIST_ENABLED, tr_blocklistIsEnabled( s ) );
     1328    tr_bencDictAddReal( d, TR_PREFS_KEY_MAX_CACHE_SIZE_MiB, tr_sessionGetCacheLimit( s ) );
    13261329    tr_bencDictAddInt ( d, "blocklist-size", tr_blocklistGetRuleCount( s ) );
    13271330    tr_bencDictAddStr ( d, "config-dir", tr_sessionGetConfigDir( s ) );
    13281331    tr_bencDictAddStr ( d, TR_PREFS_KEY_DOWNLOAD_DIR, tr_sessionGetDownloadDir( s ) );
  • libtransmission/ptrarray.h

     
    6565                              : NULL;
    6666}
    6767
     68void tr_ptrArrayErase( tr_ptrArray * t, int begin, int end );
    6869
     70
     71
    6972/** @brief Peek at the array pointer and its size, for easy iteration */
    7073void** tr_ptrArrayPeek( tr_ptrArray * array, int * size );
    7174
     
    100103    return tr_ptrArraySize(a) == 0;
    101104}
    102105
     106int tr_ptrArrayLowerBound( const tr_ptrArray * array,
     107                           const void * key,
     108                           int compare( const void * arrayItem, const void * key ),
     109                           tr_bool * exact_match );
     110
    103111/** @brief Insert a pointer into the array at the position determined by the sort function
    104112    @return the index of the stored pointer */
    105113int tr_ptrArrayInsertSorted( tr_ptrArray * array,
  • libtransmission/inout.c

     
    2626#include <openssl/sha.h>
    2727
    2828#include "transmission.h"
     29#include "cache.h"
    2930#include "crypto.h"
    3031#include "fdlimit.h"
    3132#include "inout.h"
     33#include "peer-common.h" /* MAX_BLOCK_SIZE */
    3234#include "platform.h"
    3335#include "stats.h"
    3436#include "torrent.h"
     
    8486    int             err = 0;
    8587    const tr_bool doWrite = ioMode >= TR_IO_WRITE;
    8688
     89if( doWrite )
     90    fprintf( stderr, "in file %s at offset %zu, writing %zu bytes; file length is %zu\n", file->name, (size_t)fileOffset, buflen, (size_t)file->length );
     91
    8792    assert( fileIndex < info->fileCount );
    8893    assert( !file->length || ( fileOffset < file->length ) );
    8994    assert( fileOffset + buflen <= file->length );
     
    223228
    224229    if( pieceIndex >= tor->info.pieceCount )
    225230        return EINVAL;
    226     if( pieceOffset + buflen > tr_torPieceCountBytes( tor, pieceIndex ) )
    227         return EINVAL;
     231    //if( pieceOffset + buflen > tr_torPieceCountBytes( tor, pieceIndex ) )
     232    //    return EINVAL;
    228233
    229234    tr_ioFindFileLocation( tor, pieceIndex, pieceOffset,
    230235                           &fileIndex, &fileOffset );
     
    237242        err = readOrWriteBytes( tor->session, tor, ioMode, fileIndex, fileOffset, buf, bytesThisPass );
    238243        buf += bytesThisPass;
    239244        buflen -= bytesThisPass;
     245//fprintf( stderr, "++fileIndex to %d\n", (int)fileIndex );
    240246        ++fileIndex;
    241247        fileOffset = 0;
    242248
     
    295301    size_t   bytesLeft;
    296302    uint32_t offset = 0;
    297303    tr_bool  success = TRUE;
    298     uint8_t * buffer = tr_sessionGetBuffer( tor->session );
    299     const size_t buflen = SESSION_BUFFER_SIZE;
     304    const size_t buflen = MAX_BLOCK_SIZE;
     305    uint8_t * buffer = tr_new( uint8_t, buflen );
    300306    SHA_CTX  sha;
    301307
    302308    assert( tor != NULL );
     
    313319    while( bytesLeft )
    314320    {
    315321        const int len = MIN( bytesLeft, buflen );
    316         success = !tr_ioRead( tor, pieceIndex, offset, len, buffer );
     322        success = !tr_cacheReadBlock( tor->session->cache, tor, pieceIndex, offset, len, buffer );
    317323        if( !success )
    318324            break;
    319325        SHA1_Update( &sha, buffer, len );
     
    324330    if( success )
    325331        SHA1_Final( setme, &sha );
    326332
    327     tr_sessionReleaseBuffer( tor->session );
     333    tr_free( buffer );
    328334    return success;
    329335}
    330336
  • libtransmission/transmission.h

     
    163163#define TR_PREFS_KEY_BIND_ADDRESS_IPV4             "bind-address-ipv4"
    164164#define TR_PREFS_KEY_BIND_ADDRESS_IPV6             "bind-address-ipv6"
    165165#define TR_PREFS_KEY_BLOCKLIST_ENABLED             "blocklist-enabled"
     166#define TR_PREFS_KEY_MAX_CACHE_SIZE_MiB            "cache-size-MiB"
    166167#define TR_PREFS_KEY_DHT_ENABLED                   "dht-enabled"
    167168#define TR_PREFS_KEY_LPD_ENABLED                   "lpd-enabled"
    168169#define TR_PREFS_KEY_DOWNLOAD_DIR                  "download-dir"
     
    586587 * PEX is always disabled in private torrents regardless of this.
    587588 * In public torrents, PEX is enabled by default.
    588589 */
    589 void tr_sessionSetPexEnabled( tr_session  * session, tr_bool isEnabled );
     590void     tr_sessionSetPexEnabled( tr_session  * session, tr_bool isEnabled );
     591tr_bool  tr_sessionIsPexEnabled( const tr_session * session );
    590592
    591 tr_bool            tr_sessionIsPexEnabled( const tr_session * session );
     593tr_bool  tr_sessionIsDHTEnabled( const tr_session * session );
     594void     tr_sessionSetDHTEnabled( tr_session * session, tr_bool );
    592595
    593 tr_bool            tr_sessionIsDHTEnabled( const tr_session * session );
     596tr_bool  tr_sessionIsLPDEnabled( const tr_session * session );
     597void     tr_sessionSetLPDEnabled( tr_session * session, tr_bool enabled );
    594598
    595 void               tr_sessionSetDHTEnabled( tr_session * session, tr_bool );
     599void     tr_sessionSetCacheLimit( tr_session * session, double MiB );
     600double   tr_sessionGetCacheLimit( const tr_session * session );
    596601
    597 tr_bool            tr_sessionIsLPDEnabled( const tr_session * session );
     602void     tr_sessionSetLazyBitfieldEnabled( tr_session * session, tr_bool enabled );
     603tr_bool  tr_sessionIsLazyBitfieldEnabled( const tr_session * session );
    598604
    599 void               tr_sessionSetLPDEnabled( tr_session * session, tr_bool enabled );
    600 
    601 void               tr_sessionSetLazyBitfieldEnabled( tr_session * session,
    602                                                      tr_bool       enabled );
    603 
    604 tr_bool            tr_sessionIsLazyBitfieldEnabled( const tr_session * session );
    605 
    606605tr_encryption_mode tr_sessionGetEncryption( tr_session * session );
    607 
    608 void               tr_sessionSetEncryption( tr_session          * session,
     606void               tr_sessionSetEncryption( tr_session * session,
    609607                                            tr_encryption_mode    mode );
    610608
    611609
  • libtransmission/cache.c

     
     1/*
     2 * This file Copyright (C) 2010 Mnemosyne LLC
     3 *
     4 * This file is licensed by the GPL version 2.  Works owned by the
     5 * Transmission project are granted a special exemption to clause 2(b)
     6 * so that the bulk of its code can remain under the MIT license.
     7 * This exemption does not extend to derived works not owned by
     8 * the Transmission project.
     9 *
     10 * $Id$
     11 */
     12
     13#include "transmission.h"
     14#include "cache.h"
     15#include "inout.h"
     16#include "peer-common.h" /* MAX_BLOCK_SIZE */
     17#include "ptrarray.h"
     18#include "torrent.h"
     19#include "utils.h"
     20
     21#define MY_NAME "Cache"
     22
     23/****
     24*****
     25****/
     26
     27struct cache_block
     28{
     29    tr_torrent * tor;
     30
     31    tr_piece_index_t piece;
     32    uint32_t offset;
     33    uint32_t length;
     34
     35    tr_block_index_t block;
     36
     37    uint8_t * buf;
     38};
     39
     40struct tr_cache
     41{
     42    tr_ptrArray blocks;
     43    int maxBlocks;
     44    size_t maxMiB;
     45
     46    size_t disk_writes;
     47    size_t disk_write_bytes;
     48    size_t cache_writes;
     49    size_t cache_write_bytes;
     50};
     51
     52/****
     53*****
     54****/
     55
     56/* return a count of how many contiguous blocks there are starting at this pos */
     57static int
     58getBlockRun( const tr_cache * cache, int pos )
     59{
     60    int i;
     61    const int n = tr_ptrArraySize( &cache->blocks );
     62    const struct cache_block ** blocks = (const struct cache_block**) tr_ptrArrayBase( &cache->blocks );
     63    const struct cache_block * ref = blocks[pos];
     64    tr_block_index_t block = ref->block;
     65
     66    for( i=pos; i<n; ++i, ++block ) {
     67        const struct cache_block * b = blocks[i];
     68        if( b->block != block ) break;
     69        if( b->tor != ref->tor ) break;
     70//fprintf( stderr, "pos %d tor %d block %zu\n", i, b->tor->uniqueId, (size_t)b->block );
     71    }
     72
     73//fprintf( stderr, "run is %d long from [%d to %d)\n", (int)(i-pos), i, (int)pos );
     74    return i-pos;
     75}
     76
     77/* return the starting index of the longest contiguous run of blocks */
     78static int
     79findLargestChunk( tr_cache * cache, int * setme_n )
     80{
     81    const int n = tr_ptrArraySize( &cache->blocks );
     82    int pos;
     83    int bestpos = 0;
     84    int bestlen = getBlockRun( cache, bestpos );
     85
     86    for( pos=bestlen; pos<n; )
     87    {
     88        const int len = getBlockRun( cache, pos );
     89
     90        if( bestlen < len ) {
     91            bestlen = len;
     92            bestpos = pos;
     93        }
     94
     95        pos += len;
     96    }
     97
     98//fprintf( stderr, "LONGEST run is %d long from [%d to %d)\n", bestlen, bestpos, bestpos+bestlen );
     99    *setme_n = bestlen;
     100    return bestpos;
     101}
     102
     103static int
     104flushContiguous( tr_cache * cache, int pos, int n )
     105{
     106    int i;
     107    int err = 0;
     108    uint8_t * buf = tr_new( uint8_t, n * MAX_BLOCK_SIZE );
     109    uint8_t * walk = buf;
     110    struct cache_block ** blocks = (struct cache_block**) tr_ptrArrayBase( &cache->blocks );
     111
     112    struct cache_block * b = blocks[pos];
     113    tr_torrent * tor             = b->tor;
     114    const tr_piece_index_t piece = b->piece;
     115    const uint32_t offset        = b->offset;
     116
     117//fprintf( stderr, "flushing %d contiguous blocks from [%d to %d)\n", n, pos, n+pos );
     118
     119    for( i=pos; i<pos+n; ++i ) {
     120        b = blocks[i];
     121        memcpy( walk, b->buf, b->length );
     122        walk += b->length;
     123        tr_free( b->buf );
     124        tr_free( b );
     125    }
     126    tr_ptrArrayErase( &cache->blocks, pos, pos+n );
     127
     128    tr_tordbg( tor, "Writing to disk piece %d, offset %d, len %d", (int)piece, (int)offset, (int)(walk-buf) );
     129    tr_ndbg( MY_NAME, "Removing %d blocks from cache; %d left", n, tr_ptrArraySize(&cache->blocks) );
     130    //fprintf( stderr, "%s - Writing to disk piece %d, offset %d, len %d\n", tr_torrentName(tor), (int)piece, (int)offset, (int)(walk-buf) );
     131    //fprintf( stderr, "%s - Removing %d blocks from cache; %d left\n", MY_NAME, n, tr_ptrArraySize(&cache->blocks) );
     132
     133    err = tr_ioWrite( tor, piece, offset, walk-buf, buf );
     134    tr_free( buf );
     135
     136    ++cache->disk_writes;
     137    cache->disk_write_bytes += walk-buf;
     138    return err;
     139}
     140
     141static int
     142cacheTrim( tr_cache * cache )
     143{
     144    int err = 0;
     145
     146    while( !err && ( tr_ptrArraySize( &cache->blocks ) > cache->maxBlocks ) )
     147    {
     148        int n;
     149        const int i = findLargestChunk( cache, &n );
     150        err = flushContiguous( cache, i, n );
     151    }
     152
     153    return err;
     154}
     155
     156/***
     157****
     158***/
     159
     160static int
     161getMaxBlocks( size_t maxMiB )
     162{
     163    const double maxBytes = maxMiB * 1024 * 1024;
     164    return maxBytes / MAX_BLOCK_SIZE;
     165}
     166
     167int
     168tr_cacheSetLimit( tr_cache * cache, double maxMiB )
     169{
     170    cache->maxMiB = maxMiB;
     171    cache->maxBlocks = getMaxBlocks( maxMiB );
     172    tr_ndbg( MY_NAME, "Maximum cache size set to %.2f MiB (%d blocks)", maxMiB, cache->maxBlocks );
     173    return cacheTrim( cache );
     174}
     175
     176double
     177tr_cacheGetLimit( const tr_cache * cache )
     178{
     179    return cache->maxMiB;
     180}
     181
     182tr_cache *
     183tr_cacheNew( double maxMiB )
     184{
     185    tr_cache * cache = tr_new( tr_cache, 1 );
     186    cache->blocks = TR_PTR_ARRAY_INIT;
     187    cache->maxBlocks = getMaxBlocks( maxMiB );
     188    return cache;
     189}
     190
     191void
     192tr_cacheFree( tr_cache * cache )
     193{
     194    assert( tr_ptrArrayEmpty( &cache->blocks ) );
     195    tr_ptrArrayDestruct( &cache->blocks, NULL );
     196    tr_free( cache );
     197}
     198
     199/***
     200****
     201***/
     202
     203static int
     204cache_block_compare( const void * va, const void * vb )
     205{
     206    const struct cache_block * a = va;
     207    const struct cache_block * b = vb;
     208
     209    /* primary key: torrent id */
     210    if( a->tor->uniqueId != b->tor->uniqueId )
     211        return a->tor->uniqueId < b->tor->uniqueId ? -1 : 1;
     212
     213    /* secondary key: block # */
     214    if( a->block != b->block )
     215        return a->block < b->block ? -1 : 1;
     216
     217    if( a->block < b->block ) return -1;
     218    if( a->block > b->block ) return  1;
     219
     220    /* they'r eequal */
     221    return 0;
     222}
     223
     224static struct cache_block *
     225findBlock( tr_cache           * cache,
     226           tr_torrent         * torrent,
     227           tr_piece_index_t     piece,
     228           uint32_t             offset )
     229{
     230    struct cache_block key;
     231    key.tor = torrent;
     232    key.block = _tr_block( torrent, piece, offset );
     233    return tr_ptrArrayFindSorted( &cache->blocks, &key, cache_block_compare );
     234}
     235
     236int
     237tr_cacheWriteBlock( tr_cache         * cache,
     238                    tr_torrent       * torrent,
     239                    tr_piece_index_t   piece,
     240                    uint32_t           offset,
     241                    uint32_t           length,
     242                    const uint8_t    * writeme )
     243{
     244    struct cache_block * cb = findBlock( cache, torrent, piece, offset );
     245
     246    if( cb == NULL )
     247    {
     248        cb = tr_new( struct cache_block, 1 );
     249        cb->tor = torrent;
     250        cb->piece = piece;
     251        cb->offset = offset;
     252        cb->length = length;
     253        cb->block = _tr_block( torrent, piece, offset );
     254        cb->buf = NULL;
     255        tr_ptrArrayInsertSorted( &cache->blocks, cb, cache_block_compare );
     256    }
     257
     258    tr_free( cb->buf );
     259    cb->buf = tr_memdup( writeme, cb->length );
     260
     261    ++cache->cache_writes;
     262    cache->cache_write_bytes += cb->length;
     263
     264    return cacheTrim( cache );
     265}
     266
     267int
     268tr_cacheReadBlock( tr_cache         * cache,
     269                   tr_torrent       * torrent,
     270                   tr_piece_index_t   piece,
     271                   uint32_t           offset,
     272                   uint32_t           len,
     273                   uint8_t          * setme )
     274{
     275    int err = 0;
     276    struct cache_block * cb = findBlock( cache, torrent, piece, offset );
     277
     278    if( cb )
     279        memcpy( setme, cb->buf, len );
     280    else
     281        err = tr_ioRead( torrent, piece, offset, len, setme );
     282
     283    return err;
     284}
     285
     286int
     287tr_cachePrefetchBlock( tr_cache         * cache,
     288                       tr_torrent       * torrent,
     289                       tr_piece_index_t   piece,
     290                       uint32_t           offset,
     291                       uint32_t           len )
     292{
     293    int err = 0;
     294    struct cache_block * cb = findBlock( cache, torrent, piece, offset );
     295
     296    if( cb == NULL )
     297        err = tr_ioPrefetch( torrent, piece, offset, len );
     298
     299    return err;
     300}
     301
     302/***
     303****
     304***/
     305
     306static int
     307findPiece( tr_cache * cache, tr_torrent * torrent, tr_piece_index_t piece )
     308{
     309    struct cache_block key;
     310    key.tor = torrent;
     311    key.block = tr_torPieceFirstBlock( torrent, piece );
     312    return tr_ptrArrayLowerBound( &cache->blocks, &key, cache_block_compare, NULL );
     313}
     314
     315int
     316tr_cacheFlushFile( tr_cache * cache, tr_torrent * torrent, tr_file_index_t i )
     317{
     318    int err = 0;
     319    const tr_file * file = &torrent->info.files[i];
     320    const tr_block_index_t begin = tr_torPieceFirstBlock( torrent, file->firstPiece );
     321    const tr_block_index_t end  = tr_torPieceFirstBlock( torrent, file->lastPiece ) + tr_torPieceCountBlocks( torrent, file->lastPiece );
     322    const int pos = findPiece( cache, torrent, file->firstPiece );
     323//fprintf( stderr, "flushing file %d, which is blocks [%zu...%zu)\n", (int)i, (size_t)begin, (size_t)end );
     324
     325    /* flush out all the blocks in that file */
     326    while( !err && ( pos < tr_ptrArraySize( &cache->blocks ) ) )
     327    {
     328        const struct cache_block * b = tr_ptrArrayNth( &cache->blocks, pos );
     329        if( b->tor != torrent ) break;
     330        if( ( b->block < begin ) || ( b->block >= end ) ) break;
     331        err = flushContiguous( cache, pos, getBlockRun( cache, pos ) );
     332    }
     333
     334    return err;
     335}
     336
     337int
     338tr_cacheFlushTorrent( tr_cache * cache, tr_torrent * torrent )
     339{
     340    int err = 0;
     341    const int pos = findPiece( cache, torrent, 0 );
     342
     343    /* flush out all the blocks in that torrent */
     344    while( !err && ( pos < tr_ptrArraySize( &cache->blocks ) ) )
     345    {
     346        const struct cache_block * b = tr_ptrArrayNth( &cache->blocks, pos );
     347        if( b->tor != torrent ) break;
     348        err = flushContiguous( cache, pos, getBlockRun( cache, pos ) );
     349    }
     350
     351    return err;
     352}
  • libtransmission/cache.h

     
     1/*
     2 * This file Copyright (C) 2010 Mnemosyne LLC
     3 *
     4 * This file is licensed by the GPL version 2.  Works owned by the
     5 * Transmission project are granted a special exemption to clause 2(b)
     6 * so that the bulk of its code can remain under the MIT license.
     7 * This exemption does not extend to derived works not owned by
     8 * the Transmission project.
     9 *
     10 * $Id$
     11 */
     12
     13#ifndef __TRANSMISSION__
     14 #error only libtransmission should #include this header.
     15#endif
     16
     17#ifndef TR_CACHE_H
     18#define TR_CACHE_H
     19
     20typedef struct tr_cache tr_cache;
     21
     22/***
     23****
     24***/
     25
     26tr_cache * tr_cacheNew( double max_MiB );
     27
     28void tr_cacheFree( tr_cache * );
     29
     30/***
     31****
     32***/
     33
     34int tr_cacheSetLimit( tr_cache * cache, double max_MiB );
     35
     36double tr_cacheGetLimit( const tr_cache * );
     37
     38int tr_cacheWriteBlock( tr_cache         * cache,
     39                        tr_torrent       * torrent,
     40                        tr_piece_index_t   piece,
     41                        uint32_t           offset,
     42                        uint32_t           len,
     43                        const uint8_t    * writeme );
     44
     45int tr_cacheReadBlock( tr_cache         * cache,
     46                       tr_torrent       * torrent,
     47                       tr_piece_index_t   piece,
     48                       uint32_t           offset,
     49                       uint32_t           len,
     50                       uint8_t          * setme );
     51
     52int tr_cachePrefetchBlock( tr_cache         * cache,
     53                           tr_torrent       * torrent,
     54                           tr_piece_index_t   piece,
     55                           uint32_t           offset,
     56                           uint32_t           len );
     57
     58/***
     59****
     60***/
     61
     62int tr_cacheFlushTorrent( tr_cache    * cache,
     63                          tr_torrent  * torrent );
     64
     65int tr_cacheFlushFile( tr_cache         * cache,
     66                       tr_torrent       * torrent,
     67                       tr_file_index_t    file );
     68
     69#endif
  • libtransmission/session.c

     
    2828#include "bandwidth.h"
    2929#include "bencode.h"
    3030#include "blocklist.h"
     31#include "cache.h"
    3132#include "crypto.h"
    3233#include "fdlimit.h"
    3334#include "list.h"
     
    5152
    5253enum
    5354{
    54     SAVE_INTERVAL_SECS = 120
     55    SAVE_INTERVAL_SECS = 120,
     56
     57    DEFAULT_CACHE_SIZE_MiB = 2 /* 2 MiB */
    5558};
    5659
    5760
     
    242245{
    243246    assert( tr_bencIsDict( d ) );
    244247
    245     tr_bencDictReserve( d, 35 );
     248    tr_bencDictReserve( d, 60 );
    246249    tr_bencDictAddBool( d, TR_PREFS_KEY_BLOCKLIST_ENABLED,        FALSE );
     250    tr_bencDictAddReal( d, TR_PREFS_KEY_MAX_CACHE_SIZE_MiB,       DEFAULT_CACHE_SIZE_MiB );
    247251    tr_bencDictAddBool( d, TR_PREFS_KEY_DHT_ENABLED,              TRUE );
    248252    tr_bencDictAddBool( d, TR_PREFS_KEY_LPD_ENABLED,              FALSE );
    249253    tr_bencDictAddStr ( d, TR_PREFS_KEY_DOWNLOAD_DIR,             tr_getDefaultDownloadDir( ) );
     
    307311{
    308312    assert( tr_bencIsDict( d ) );
    309313
    310     tr_bencDictReserve( d, 30 );
     314    tr_bencDictReserve( d, 60 );
    311315    tr_bencDictAddBool( d, TR_PREFS_KEY_BLOCKLIST_ENABLED,        tr_blocklistIsEnabled( s ) );
     316    tr_bencDictAddReal( d, TR_PREFS_KEY_MAX_CACHE_SIZE_MiB,       tr_cacheGetLimit( s->cache ) );
    312317    tr_bencDictAddBool( d, TR_PREFS_KEY_DHT_ENABLED,              s->isDHTEnabled );
    313318    tr_bencDictAddBool( d, TR_PREFS_KEY_LPD_ENABLED,              s->isLPDEnabled );
    314319    tr_bencDictAddStr ( d, TR_PREFS_KEY_DOWNLOAD_DIR,             s->downloadDir );
     
    506511    session = tr_new0( tr_session, 1 );
    507512    session->bandwidth = tr_bandwidthNew( session, NULL );
    508513    session->lock = tr_lockNew( );
     514    session->cache = tr_cacheNew( DEFAULT_CACHE_SIZE_MiB );
    509515    session->tag = tr_strdup( tag );
    510516    session->magicNumber = SESSION_MAGIC_NUMBER;
    511517    session->buffer = tr_valloc( SESSION_BUFFER_SIZE );
     
    671677    }
    672678
    673679    /* misc features */
     680    if( tr_bencDictFindReal( settings, TR_PREFS_KEY_MAX_CACHE_SIZE_MiB, &d ) )
     681        tr_sessionSetCacheLimit( session, d );
    674682    if( tr_bencDictFindBool( settings, TR_PREFS_KEY_LAZY_BITFIELD, &boolVal ) )
    675683        tr_sessionSetLazyBitfieldEnabled( session, boolVal );
    676684    if( tr_bencDictFindInt( settings, TR_PREFS_KEY_PEER_LIMIT_TORRENT, &i ) )
     
    16051613        tr_torrentFree( torrents[i] );
    16061614    tr_free( torrents );
    16071615
     1616    tr_cacheFree( session->cache );
     1617    session->cache = NULL;
    16081618    tr_announcerClose( session );
    16091619    tr_statsClose( session );
    16101620    tr_peerMgrFree( session->peerMgr );
     
    18401850***/
    18411851
    18421852void
     1853tr_sessionSetCacheLimit( tr_session * session, double maxMiB )
     1854{
     1855    assert( tr_isSession( session ) );
     1856
     1857    tr_cacheSetLimit( session->cache, maxMiB );
     1858}
     1859
     1860double
     1861tr_sessionGetCacheLimit( const tr_session * session )
     1862{
     1863    assert( tr_isSession( session ) );
     1864
     1865    return tr_cacheGetLimit( session->cache );
     1866}
     1867
     1868/***
     1869****
     1870***/
     1871
     1872void
    18431873tr_sessionSetLazyBitfieldEnabled( tr_session * session,
    18441874                                  tr_bool      enabled )
    18451875{
  • libtransmission/Makefile.am

     
    2121    bencode.c \
    2222    bitfield.c \
    2323    blocklist.c \
     24    cache.c \
    2425    clients.c \
    2526    completion.c \
    2627    ConvertUTF.c \
     
    7273    bitfield.h \
    7374    bitset.h \
    7475    blocklist.h \
     76    cache.h \
    7577    clients.h \
    7678    ConvertUTF.h \
    7779    crypto.h \
  • libtransmission/session.h

     
    4040struct tr_announcer;
    4141struct tr_bandwidth;
    4242struct tr_bindsockets;
     43struct tr_cache;
    4344struct tr_fdInfo;
    4445
    4546struct tr_turtle_info
     
    149150    struct tr_peerMgr *          peerMgr;
    150151    struct tr_shared *           shared;
    151152
     153    struct tr_cache *            cache;
     154
    152155    struct tr_lock *             lock;
    153156
    154157    struct tr_web *              web;
  • libtransmission/torrent.c

     
    2929#include "announcer.h"
    3030#include "bandwidth.h"
    3131#include "bencode.h"
     32#include "cache.h"
    3233#include "completion.h"
    3334#include "crypto.h" /* for tr_sha1 */
    3435#include "resume.h"
     
    15191520    tr_verifyRemove( tor );
    15201521    tr_peerMgrStopTorrent( tor );
    15211522    tr_announcerTorrentStopped( tor );
     1523    tr_cacheFlushTorrent( tor->session->cache, tor );
    15221524
    15231525    tr_fdTorrentClose( tor->session, tor->uniqueId );
    15241526
  • gtk/my-valgrind.sh

     
    22export G_SLICE=always-malloc
    33export G_DEBUG=gc-friendly
    44export GLIBCXX_FORCE_NEW=1
    5 valgrind --tool=memcheck --leak-check=full --leak-resolution=high --num-callers=48 --log-file=x-valgrind --show-reachable=yes ./transmission -p 2>&1 | tee runlog
     5valgrind --tool=cachegrind ./transmission -p -g /tmp/transmission-test/what 2>&1 | tee runlog
     6#valgrind --tool=memcheck --leak-check=full --leak-resolution=high --num-callers=48 --log-file=x-valgrind --show-reachable=yes ./transmission -p -g /tmp/transmission-test/what 2>&1 | tee runlog
  • daemon/transmission-remote.1

     
    2121.Op Fl b
    2222.Op Fl c Ar path | Fl C
    2323.Op Fl d Ar number | Fl D
     24.Op Fl e Ar size
    2425.Op Fl er | ep | et
    2526.Op Fl f
    2627.Op Fl g Ar files
     
    124125.It Fl D Fl -no-downlimit
    125126Disable download speed limits.
    126127If current torrent(s) are selected this operates on them.  Otherwise, it changes the global setting.
     128.It Fl e Fl -cache Ar size
     129Set the session's maximum memory cache size in MiB.  This cache is used to reduce disk IO.
    127130.It Fl er Fl -encryption-required
    128131Encrypt all peer connections.
    129132.It Fl ep Fl -encryption-preferred
  • daemon/remote.c

     
    207207    { 'b', "debug",                  "Print debugging information", "b",  0, NULL },
    208208    { 'd', "downlimit",              "Set the max download speed in KiB/s for the current torrent(s) or globally", "d", 1, "<speed>" },
    209209    { 'D', "no-downlimit",           "Disable max download speed for the current torrent(s) or globally", "D", 0, NULL },
     210    { 'e', "cache",                  "Set the maximum size of the session's memory cache (in MiB)", "e", 1, "<size>" },
    210211    { 910, "encryption-required",    "Encrypt all peer connections", "er", 0, NULL },
    211212    { 911, "encryption-preferred",   "Prefer encrypted peer connections", "ep", 0, NULL },
    212213    { 912, "encryption-tolerated",   "Prefer unencrypted peer connections", "et", 0, NULL },
     
    322323
    323324        case 'c': /* incomplete-dir */
    324325        case 'C': /* no-incomplete-dir */
     326        case 'e': /* cache */
    325327        case 'm': /* portmap */
    326328        case 'M': /* "no-portmap */
    327329        case 'o': /* dht */
     
    13291331    tr_benc *args;
    13301332    if( ( tr_bencDictFindDict( top, "arguments", &args ) ) )
    13311333    {
     1334        double d;
    13321335        const char * str;
    13331336        int64_t      i;
    13341337        tr_bool      boolVal;
     1338        char buf[64];
    13351339
    13361340        printf( "VERSION\n" );
    13371341        if( tr_bencDictFindStr( args,  "version", &str ) )
     
    13591363            printf( "  Peer exchange allowed: %s\n", ( boolVal ? "Yes" : "No" ) );
    13601364        if( tr_bencDictFindStr( args,  TR_PREFS_KEY_ENCRYPTION, &str ) )
    13611365            printf( "  Encryption: %s\n", str );
     1366        if( tr_bencDictFindReal( args, TR_PREFS_KEY_MAX_CACHE_SIZE_MiB, &d ) )
     1367            printf( "  Maximum memory cache size: %s\n", strlsize( buf, d*MiB, sizeof( buf ) ) );
    13621368        printf( "\n" );
    13631369
    13641370        {
     
    18161822                          break;
    18171823                case 'C': tr_bencDictAddBool( args, TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED, FALSE );
    18181824                          break;
     1825                case 'e': tr_bencDictAddReal( args, TR_PREFS_KEY_MAX_CACHE_SIZE_MiB, atof(optarg) );
     1826                          break;
    18191827                case 910: tr_bencDictAddStr( args, TR_PREFS_KEY_ENCRYPTION, "required" );
    18201828                          break;
    18211829                case 911: tr_bencDictAddStr( args, TR_PREFS_KEY_ENCRYPTION, "preferred" );
  • doc/rpc-spec.txt

     
    399399   "alt-speed-up"                | number     max global upload speed (in K/s)
    400400   "blocklist-enabled"           | boolean    true means enabled
    401401   "blocklist-size"              | number     number of rules in the blocklist
     402   "cache-size-MiB"              | number     size (in MiB) of the disk cache
    402403   "config-dir"                  | string     location of transmission's configuration directory
    403404   "download-dir"                | string     default path to download torrents
    404405   "dht-enabled"                 | boolean    true means allow dht in public torrents
     
    597598         | 2.00    | yes       | session-set    | new arg "trash-original-torrent-files"
    598599         | 2.00    | yes       | session-get    | new arg "start-added-torrents"
    599600         | 2.00    | yes       | session-get    | new arg "trash-original-torrent-files"
     601         | 2.00    | yes       | session-get    | new arg "cache-size-MiB"
    600602         | 2.00    | yes       | torrent-get    | new arg "isFinished"