source: trunk/libtransmission/resume.c @ 8254

Last change on this file since 8254 was 8254, checked in by charles, 13 years ago

(trunk) experimental support for tr_torrentSetPriority()

  • Property svn:keywords set to Date Rev Author Id
File size: 20.3 KB
Line 
1/*
2 * This file Copyright (C) 2008-2009 Charles Kerr <charles@transmissionbt.com>
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: resume.c 8254 2009-04-18 23:17:30Z charles $
11 */
12
13#include <unistd.h> /* unlink */
14
15#include <string.h>
16
17#include "transmission.h"
18#include "session.h"
19#include "bencode.h"
20#include "completion.h"
21#include "fastresume.h"
22#include "peer-mgr.h" /* pex */
23#include "platform.h" /* tr_getResumeDir */
24#include "resume.h"
25#include "torrent.h"
26#include "utils.h" /* tr_buildPath */
27
28#define KEY_ACTIVITY_DATE       "activity-date"
29#define KEY_ADDED_DATE          "added-date"
30#define KEY_CORRUPT             "corrupt"
31#define KEY_DONE_DATE           "done-date"
32#define KEY_DOWNLOAD_DIR        "destination"
33#define KEY_DND                 "dnd"
34#define KEY_DOWNLOADED          "downloaded"
35#define KEY_MAX_PEERS           "max-peers"
36#define KEY_PAUSED              "paused"
37#define KEY_PEERS               "peers"
38#define KEY_PEERS6              "peers6"
39#define KEY_FILE_PRIORITIES     "priority"
40#define KEY_BANDWIDTH_PRIORITY  "bandwidth-priority"
41#define KEY_PROGRESS            "progress"
42#define KEY_SPEEDLIMIT_OLD      "speed-limit"
43#define KEY_SPEEDLIMIT_UP       "speed-limit-up"
44#define KEY_SPEEDLIMIT_DOWN     "speed-limit-down"
45#define KEY_RATIOLIMIT          "ratio-limit"
46#define KEY_UPLOADED            "uploaded"
47
48#define KEY_SPEED                  "speed"
49#define KEY_USE_GLOBAL_SPEED_LIMIT "use-global-speed-limit"
50#define KEY_USE_SPEED_LIMIT        "use-speed-limit"
51#define KEY_SPEEDLIMIT_DOWN_SPEED  "down-speed"
52#define KEY_SPEEDLIMIT_DOWN_MODE   "down-mode"
53#define KEY_SPEEDLIMIT_UP_SPEED    "up-speed"
54#define KEY_SPEEDLIMIT_UP_MODE     "up-mode"
55#define KEY_RATIOLIMIT_RATIO       "ratio-limit"
56#define KEY_RATIOLIMIT_MODE        "ratio-mode"
57
58#define KEY_PROGRESS_MTIMES   "mtimes"
59#define KEY_PROGRESS_BITFIELD "bitfield"
60
61static char*
62getResumeFilename( const tr_torrent * tor )
63{
64    return tr_strdup_printf( "%s%c%s.%16.16s.resume",
65                             tr_getResumeDir( tor->session ),
66                             TR_PATH_DELIMITER,
67                             tor->info.name,
68                             tor->info.hashString );
69}
70
71/***
72****
73***/
74
75static void
76savePeers( tr_benc *          dict,
77           const tr_torrent * tor )
78{
79    tr_pex * pex = NULL;
80    int count = tr_peerMgrGetPeers( (tr_torrent*) tor, &pex, TR_AF_INET );
81
82    if( count > 0 )
83        tr_bencDictAddRaw( dict, KEY_PEERS, pex, sizeof( tr_pex ) * count );
84
85    tr_free( pex );
86    pex = NULL;
87   
88    count = tr_peerMgrGetPeers( (tr_torrent*) tor, &pex, TR_AF_INET6 );
89    if( count > 0 )
90        tr_bencDictAddRaw( dict, KEY_PEERS6, pex, sizeof( tr_pex ) * count );
91   
92    tr_free( pex );
93}
94
95static uint64_t
96loadPeers( tr_benc *    dict,
97           tr_torrent * tor )
98{
99    uint64_t        ret = 0;
100    const uint8_t * str;
101    size_t          len;
102
103    if( tr_bencDictFindRaw( dict, KEY_PEERS, &str, &len ) )
104    {
105        int       i;
106        const int count = len / sizeof( tr_pex );
107        for( i = 0; i < count; ++i )
108        {
109            tr_pex pex;
110            memcpy( &pex, str + ( i * sizeof( tr_pex ) ), sizeof( tr_pex ) );
111            tr_peerMgrAddPex( tor, TR_PEER_FROM_CACHE, &pex );
112        }
113        tr_tordbg( tor, "Loaded %d IPv4 peers from resume file", count );
114        ret = TR_FR_PEERS;
115    }
116   
117    if( tr_bencDictFindRaw( dict, KEY_PEERS6, &str, &len ) )
118    {
119        int       i;
120        const int count = len / sizeof( tr_pex );
121        for( i = 0; i < count; ++i )
122        {
123            tr_pex pex;
124            memcpy( &pex, str + ( i * sizeof( tr_pex ) ), sizeof( tr_pex ) );
125            tr_peerMgrAddPex( tor, TR_PEER_FROM_CACHE, &pex );
126        }
127        tr_tordbg( tor, "Loaded %d IPv6 peers from resume file", count );
128        ret = TR_FR_PEERS;
129    }
130
131    return ret;
132}
133
134/***
135****
136***/
137
138static void
139saveDND( tr_benc *          dict,
140         const tr_torrent * tor )
141{
142    const tr_info *       inf = tr_torrentInfo( tor );
143    const tr_file_index_t n = inf->fileCount;
144    tr_file_index_t       i;
145    tr_benc *             list;
146
147    list = tr_bencDictAddList( dict, KEY_DND, n );
148    for( i = 0; i < n; ++i )
149        tr_bencListAddInt( list, inf->files[i].dnd ? 1 : 0 );
150}
151
152static uint64_t
153loadDND( tr_benc *    dict,
154         tr_torrent * tor )
155{
156    uint64_t              ret = 0;
157    tr_info *             inf = &tor->info;
158    const tr_file_index_t n = inf->fileCount;
159    tr_benc *             list = NULL;
160
161    if( tr_bencDictFindList( dict, KEY_DND, &list )
162      && ( tr_bencListSize( list ) == n ) )
163    {
164        int64_t           tmp;
165        tr_file_index_t * dl = tr_new( tr_file_index_t, n );
166        tr_file_index_t * dnd = tr_new( tr_file_index_t, n );
167        tr_file_index_t   i, dlCount = 0, dndCount = 0;
168
169        for( i = 0; i < n; ++i )
170        {
171            if( tr_bencGetInt( tr_bencListChild( list, i ), &tmp ) && tmp )
172                dnd[dndCount++] = i;
173            else
174                dl[dlCount++] = i;
175        }
176
177        if( dndCount )
178        {
179            tr_torrentInitFileDLs ( tor, dnd, dndCount, FALSE );
180            tr_tordbg( tor, "Resume file found %d files listed as dnd",
181                       dndCount );
182        }
183        if( dlCount )
184        {
185            tr_torrentInitFileDLs ( tor, dl, dlCount, TRUE );
186            tr_tordbg( tor,
187                       "Resume file found %d files marked for download",
188                       dlCount );
189        }
190
191        tr_free( dnd );
192        tr_free( dl );
193        ret = TR_FR_DND;
194    }
195    else
196    {
197        tr_tordbg(
198            tor,
199            "Couldn't load DND flags.  dnd list (%p) has %zu children; torrent has %d files",
200            list, tr_bencListSize( list ), (int)n );
201    }
202
203    return ret;
204}
205
206/***
207****
208***/
209
210static void
211saveFilePriorities( tr_benc * dict, const tr_torrent * tor )
212{
213    const tr_info *       inf = tr_torrentInfo( tor );
214    const tr_file_index_t n = inf->fileCount;
215    tr_file_index_t       i;
216    tr_benc *             list;
217
218    list = tr_bencDictAddList( dict, KEY_FILE_PRIORITIES, n );
219    for( i = 0; i < n; ++i )
220        tr_bencListAddInt( list, inf->files[i].priority );
221}
222
223static uint64_t
224loadFilePriorities( tr_benc * dict, tr_torrent * tor )
225{
226    uint64_t              ret = 0;
227    tr_info *             inf = &tor->info;
228    const tr_file_index_t n = inf->fileCount;
229    tr_benc *             list;
230
231    if( tr_bencDictFindList( dict, KEY_FILE_PRIORITIES, &list )
232      && ( tr_bencListSize( list ) == n ) )
233    {
234        int64_t priority;
235        tr_file_index_t i;
236        for( i = 0; i < n; ++i )
237            if( tr_bencGetInt( tr_bencListChild( list, i ), &priority ) )
238                tr_torrentInitFilePriority( tor, i, priority );
239        ret = TR_FR_FILE_PRIORITIES;
240    }
241
242    return ret;
243}
244
245/***
246****
247***/
248
249static void
250saveSingleSpeedLimit( tr_benc * d, const tr_torrent * tor, tr_direction dir )
251{
252    tr_bencDictReserve( d, 3 );
253    tr_bencDictAddInt( d, KEY_SPEED, tr_torrentGetSpeedLimit( tor, dir ) );
254    tr_bencDictAddBool( d, KEY_USE_GLOBAL_SPEED_LIMIT, tr_torrentUsesSessionLimits( tor ) );
255    tr_bencDictAddBool( d, KEY_USE_SPEED_LIMIT, tr_torrentUsesSpeedLimit( tor, dir ) );
256}
257
258static void
259saveSpeedLimits( tr_benc * dict, const tr_torrent * tor )
260{
261    saveSingleSpeedLimit( tr_bencDictAddDict( dict, KEY_SPEEDLIMIT_DOWN, 0 ), tor, TR_DOWN );
262    saveSingleSpeedLimit( tr_bencDictAddDict( dict, KEY_SPEEDLIMIT_UP, 0 ), tor, TR_UP );
263}
264
265static void
266saveRatioLimits( tr_benc * dict, const tr_torrent * tor )
267{
268    tr_benc * d = tr_bencDictAddDict( dict, KEY_RATIOLIMIT, 2 );
269    tr_bencDictAddReal( d, KEY_RATIOLIMIT_RATIO, tr_torrentGetRatioLimit( tor ) );
270    tr_bencDictAddInt( d, KEY_RATIOLIMIT_MODE, tr_torrentGetRatioMode( tor ) );
271}
272
273static void
274loadSingleSpeedLimit( tr_benc * d, tr_direction dir, tr_torrent * tor )
275{
276    int64_t i;
277    tr_bool boolVal;
278
279    if( tr_bencDictFindInt( d, KEY_SPEED, &i ) )
280        tr_torrentSetSpeedLimit( tor, dir, i );
281
282    if( tr_bencDictFindBool( d, KEY_USE_SPEED_LIMIT, &boolVal ) )
283        tr_torrentUseSpeedLimit( tor, dir, boolVal );
284
285    if( tr_bencDictFindBool( d, KEY_USE_GLOBAL_SPEED_LIMIT, &boolVal ) )
286        tr_torrentUseSessionLimits( tor, boolVal );
287}
288
289enum old_speed_modes
290{
291    TR_SPEEDLIMIT_GLOBAL,   /* only follow the overall speed limit */
292    TR_SPEEDLIMIT_SINGLE    /* only follow the per-torrent limit */
293};
294
295static uint64_t
296loadSpeedLimits( tr_benc * dict, tr_torrent * tor )
297{
298    uint64_t  ret = 0;
299    tr_benc * d;
300
301    if( tr_bencDictFindDict( dict, KEY_SPEEDLIMIT_UP, &d ) )
302    {
303        loadSingleSpeedLimit( d, TR_UP, tor );
304        ret = TR_FR_SPEEDLIMIT;
305    }
306    if( tr_bencDictFindDict( dict, KEY_SPEEDLIMIT_DOWN, &d ) )
307    {
308        loadSingleSpeedLimit( d, TR_DOWN, tor );
309        ret = TR_FR_SPEEDLIMIT;
310    }
311
312    /* older speedlimit structure */
313    if( !ret && tr_bencDictFindDict( dict, KEY_SPEEDLIMIT_OLD, &d ) )
314    {
315
316        int64_t i;
317        if( tr_bencDictFindInt( d, KEY_SPEEDLIMIT_DOWN_SPEED, &i ) )
318            tr_torrentSetSpeedLimit( tor, TR_DOWN, i );
319        if( tr_bencDictFindInt( d, KEY_SPEEDLIMIT_DOWN_MODE, &i ) ) {
320            tr_torrentUseSpeedLimit( tor, TR_DOWN, i==TR_SPEEDLIMIT_SINGLE );
321            tr_torrentUseSessionLimits( tor, i==TR_SPEEDLIMIT_GLOBAL );
322         }
323        if( tr_bencDictFindInt( d, KEY_SPEEDLIMIT_UP_SPEED, &i ) )
324            tr_torrentSetSpeedLimit( tor, TR_UP, i );
325        if( tr_bencDictFindInt( d, KEY_SPEEDLIMIT_UP_MODE, &i ) ) {
326            tr_torrentUseSpeedLimit( tor, TR_UP, i==TR_SPEEDLIMIT_SINGLE );
327            tr_torrentUseSessionLimits( tor, i==TR_SPEEDLIMIT_GLOBAL );
328        }
329        ret = TR_FR_SPEEDLIMIT;
330    }
331
332    return ret;
333}
334
335static uint64_t
336loadRatioLimits( tr_benc *    dict,
337                 tr_torrent * tor )
338{
339    uint64_t  ret = 0;
340    tr_benc * d;
341
342    if( tr_bencDictFindDict( dict, KEY_RATIOLIMIT, &d ) )
343    {
344        int64_t i;
345        double dratio;
346        if( tr_bencDictFindReal( d, KEY_RATIOLIMIT_RATIO, &dratio ) )
347            tr_torrentSetRatioLimit( tor, dratio );
348        if( tr_bencDictFindInt( d, KEY_RATIOLIMIT_MODE, &i ) )
349            tr_torrentSetRatioMode( tor, i );
350      ret = TR_FR_RATIOLIMIT;
351    }
352
353    return ret;
354}
355/***
356****
357***/
358
359static void
360saveProgress( tr_benc *          dict,
361              const tr_torrent * tor )
362{
363    size_t              i, n;
364    time_t *            mtimes;
365    tr_benc *           p;
366    tr_benc *           m;
367    const tr_bitfield * bitfield;
368
369    p = tr_bencDictAdd( dict, KEY_PROGRESS );
370    tr_bencInitDict( p, 2 );
371
372    /* add the mtimes */
373    mtimes = tr_torrentGetMTimes( tor, &n );
374    m = tr_bencDictAddList( p, KEY_PROGRESS_MTIMES, n );
375    for( i = 0; i < n; ++i )
376    {
377        if( !tr_torrentIsFileChecked( tor, i ) )
378            mtimes[i] = ~(time_t)0; /* force a recheck */
379        tr_bencListAddInt( m, mtimes[i] );
380    }
381
382    /* add the bitfield */
383    bitfield = tr_cpBlockBitfield( &tor->completion );
384    tr_bencDictAddRaw( p, KEY_PROGRESS_BITFIELD,
385                       bitfield->bits, bitfield->byteCount );
386
387    /* cleanup */
388    tr_free( mtimes );
389}
390
391static uint64_t
392loadProgress( tr_benc *    dict,
393              tr_torrent * tor )
394{
395    uint64_t  ret = 0;
396    tr_benc * p;
397
398    if( tr_bencDictFindDict( dict, KEY_PROGRESS, &p ) )
399    {
400        const uint8_t * raw;
401        size_t          rawlen;
402        tr_benc *       m;
403        size_t          n;
404        time_t *        curMTimes = tr_torrentGetMTimes( tor, &n );
405
406        if( tr_bencDictFindList( p, KEY_PROGRESS_MTIMES, &m )
407          && ( n == tor->info.fileCount )
408          && ( n == tr_bencListSize( m ) ) )
409        {
410            size_t i;
411            for( i = 0; i < n; ++i )
412            {
413                int64_t tmp;
414                if( !tr_bencGetInt( tr_bencListChild( m, i ), &tmp ) )
415                {
416                    tr_tordbg(
417                        tor,
418                        "File #%zu needs to be verified - couldn't find benc entry",
419                        i );
420                    tr_torrentSetFileChecked( tor, i, FALSE );
421                }
422                else
423                {
424                    const time_t t = (time_t) tmp;
425                    if( t == curMTimes[i] )
426                        tr_torrentSetFileChecked( tor, i, TRUE );
427                    else
428                    {
429                        tr_tordbg(
430                            tor,
431                            "File #%zu needs to be verified - times %lu and %lu don't match",
432                            i, t, curMTimes[i] );
433                        tr_torrentSetFileChecked( tor, i, FALSE );
434                    }
435                }
436            }
437        }
438        else
439        {
440            tr_torrentUncheck( tor );
441            tr_tordbg(
442                tor, "Torrent needs to be verified - unable to find mtimes" );
443        }
444
445        if( tr_bencDictFindRaw( p, KEY_PROGRESS_BITFIELD, &raw, &rawlen ) )
446        {
447            tr_bitfield tmp;
448            tmp.byteCount = rawlen;
449            tmp.bitCount = tmp.byteCount * 8;
450            tmp.bits = (uint8_t*) raw;
451            if( !tr_cpBlockBitfieldSet( &tor->completion, &tmp ) )
452            {
453                tr_torrentUncheck( tor );
454                tr_tordbg(
455                    tor,
456                    "Torrent needs to be verified - error loading bitfield" );
457            }
458        }
459        else
460        {
461            tr_torrentUncheck( tor );
462            tr_tordbg(
463                tor,
464                "Torrent needs to be verified - unable to find bitfield" );
465        }
466
467        tr_free( curMTimes );
468        ret = TR_FR_PROGRESS;
469    }
470
471    return ret;
472}
473
474/***
475****
476***/
477
478void
479tr_torrentSaveResume( const tr_torrent * tor )
480{
481    tr_benc top;
482    char *  filename;
483
484    if( !tor )
485        return;
486
487    tr_bencInitDict( &top, 14 );
488    tr_bencDictAddInt( &top, KEY_ACTIVITY_DATE,
489                       tor->activityDate );
490    tr_bencDictAddInt( &top, KEY_ADDED_DATE,
491                       tor->addedDate );
492    tr_bencDictAddInt( &top, KEY_CORRUPT,
493                       tor->corruptPrev + tor->corruptCur );
494    tr_bencDictAddInt( &top, KEY_DONE_DATE,
495                       tor->doneDate );
496    tr_bencDictAddStr( &top, KEY_DOWNLOAD_DIR,
497                       tor->downloadDir );
498    tr_bencDictAddInt( &top, KEY_DOWNLOADED,
499                       tor->downloadedPrev + tor->downloadedCur );
500    tr_bencDictAddInt( &top, KEY_UPLOADED,
501                       tor->uploadedPrev + tor->uploadedCur );
502    tr_bencDictAddInt( &top, KEY_MAX_PEERS,
503                       tor->maxConnectedPeers );
504    tr_bencDictAddInt( &top, KEY_BANDWIDTH_PRIORITY,
505                       tr_torrentGetPriority( tor ) );
506    tr_bencDictAddBool( &top, KEY_PAUSED, !tor->isRunning );
507    savePeers( &top, tor );
508    saveFilePriorities( &top, tor );
509    saveDND( &top, tor );
510    saveProgress( &top, tor );
511    saveSpeedLimits( &top, tor );
512    saveRatioLimits( &top, tor );
513
514    filename = getResumeFilename( tor );
515    tr_bencSaveFile( filename, &top );
516    tr_free( filename );
517
518    tr_bencFree( &top );
519}
520
521static uint64_t
522loadFromFile( tr_torrent * tor,
523              uint64_t     fieldsToLoad )
524{
525    int64_t      i;
526    const char * str;
527    uint64_t     fieldsLoaded = 0;
528    char *       filename;
529    tr_benc      top;
530    tr_bool      boolVal;
531
532    filename = getResumeFilename( tor );
533
534    if( tr_bencLoadFile( filename, &top ) )
535    {
536        tr_tordbg( tor, "Couldn't read \"%s\"; trying old format.",
537                   filename );
538        fieldsLoaded = tr_fastResumeLoad( tor, fieldsToLoad );
539
540        if( ( fieldsLoaded != 0 ) && ( fieldsToLoad == ~(uint64_t)0 ) )
541        {
542            tr_torrentSaveResume( tor );
543            tr_fastResumeRemove( tor );
544            tr_tordbg( tor, "Migrated resume file to \"%s\"", filename );
545        }
546
547        tr_free( filename );
548        return fieldsLoaded;
549    }
550
551    tr_tordbg( tor, "Read resume file \"%s\"", filename );
552
553    if( ( fieldsToLoad & TR_FR_CORRUPT )
554      && tr_bencDictFindInt( &top, KEY_CORRUPT, &i ) )
555    {
556        tor->corruptPrev = i;
557        fieldsLoaded |= TR_FR_CORRUPT;
558    }
559
560    if( ( fieldsToLoad & ( TR_FR_PROGRESS | TR_FR_DOWNLOAD_DIR ) )
561      && ( tr_bencDictFindStr( &top, KEY_DOWNLOAD_DIR, &str ) )
562      && ( str && *str ) )
563    {
564        tr_free( tor->downloadDir );
565        tor->downloadDir = tr_strdup( str );
566        fieldsLoaded |= TR_FR_DOWNLOAD_DIR;
567    }
568
569    if( ( fieldsToLoad & TR_FR_DOWNLOADED )
570      && tr_bencDictFindInt( &top, KEY_DOWNLOADED, &i ) )
571    {
572        tor->downloadedPrev = i;
573        fieldsLoaded |= TR_FR_DOWNLOADED;
574    }
575
576    if( ( fieldsToLoad & TR_FR_UPLOADED )
577      && tr_bencDictFindInt( &top, KEY_UPLOADED, &i ) )
578    {
579        tor->uploadedPrev = i;
580        fieldsLoaded |= TR_FR_UPLOADED;
581    }
582
583    if( ( fieldsToLoad & TR_FR_MAX_PEERS )
584      && tr_bencDictFindInt( &top, KEY_MAX_PEERS, &i ) )
585    {
586        tor->maxConnectedPeers = i;
587        fieldsLoaded |= TR_FR_MAX_PEERS;
588    }
589
590    if( ( fieldsToLoad & TR_FR_RUN )
591      && tr_bencDictFindBool( &top, KEY_PAUSED, &boolVal ) )
592    {
593        tor->isRunning = !boolVal;
594        fieldsLoaded |= TR_FR_RUN;
595    }
596
597    if( ( fieldsToLoad & TR_FR_ADDED_DATE )
598      && tr_bencDictFindInt( &top, KEY_ADDED_DATE, &i ) )
599    {
600        tor->addedDate = i;
601        fieldsLoaded |= TR_FR_ADDED_DATE;
602    }
603
604    if( ( fieldsToLoad & TR_FR_DONE_DATE )
605      && tr_bencDictFindInt( &top, KEY_DONE_DATE, &i ) )
606    {
607        tor->doneDate = i;
608        fieldsLoaded |= TR_FR_DONE_DATE;
609    }
610
611    if( ( fieldsToLoad & TR_FR_ACTIVITY_DATE )
612      && tr_bencDictFindInt( &top, KEY_ACTIVITY_DATE, &i ) )
613    {
614        tr_torrentSetActivityDate( tor, i );
615        fieldsLoaded |= TR_FR_ACTIVITY_DATE;
616    }
617
618    if( ( fieldsToLoad & TR_FR_BANDWIDTH_PRIORITY )
619      && tr_bencDictFindInt( &top, KEY_BANDWIDTH_PRIORITY, &i )
620      && tr_isPriority( i ) )
621    {
622        tr_torrentSetPriority( tor, i );
623        fieldsLoaded |= TR_FR_BANDWIDTH_PRIORITY;
624    }
625
626    if( fieldsToLoad & TR_FR_PEERS )
627        fieldsLoaded |= loadPeers( &top, tor );
628
629    if( fieldsToLoad & TR_FR_FILE_PRIORITIES )
630        fieldsLoaded |= loadFilePriorities( &top, tor );
631
632    if( fieldsToLoad & TR_FR_PROGRESS )
633        fieldsLoaded |= loadProgress( &top, tor );
634
635    if( fieldsToLoad & TR_FR_DND )
636        fieldsLoaded |= loadDND( &top, tor );
637
638    if( fieldsToLoad & TR_FR_SPEEDLIMIT )
639        fieldsLoaded |= loadSpeedLimits( &top, tor );
640   
641    if( fieldsToLoad & TR_FR_RATIOLIMIT )
642        fieldsLoaded |= loadRatioLimits( &top, tor );
643
644    tr_bencFree( &top );
645    tr_free( filename );
646    return fieldsLoaded;
647}
648
649static uint64_t
650setFromCtor( tr_torrent *    tor,
651             uint64_t        fields,
652             const tr_ctor * ctor,
653             int             mode )
654{
655    uint64_t ret = 0;
656
657    if( fields & TR_FR_RUN )
658    {
659        uint8_t isPaused;
660        if( !tr_ctorGetPaused( ctor, mode, &isPaused ) )
661        {
662            tor->isRunning = !isPaused;
663            ret |= TR_FR_RUN;
664        }
665    }
666
667    if( fields & TR_FR_MAX_PEERS )
668        if( !tr_ctorGetPeerLimit( ctor, mode, &tor->maxConnectedPeers ) )
669            ret |= TR_FR_MAX_PEERS;
670
671    if( fields & TR_FR_DOWNLOAD_DIR )
672    {
673        const char * path;
674        if( !tr_ctorGetDownloadDir( ctor, mode, &path ) && path && *path )
675        {
676            ret |= TR_FR_DOWNLOAD_DIR;
677            tr_free( tor->downloadDir );
678            tor->downloadDir = tr_strdup( path );
679        }
680    }
681
682    return ret;
683}
684
685static uint64_t
686useManditoryFields( tr_torrent *    tor,
687                    uint64_t        fields,
688                    const tr_ctor * ctor )
689{
690    return setFromCtor( tor, fields, ctor, TR_FORCE );
691}
692
693static uint64_t
694useFallbackFields( tr_torrent *    tor,
695                   uint64_t        fields,
696                   const tr_ctor * ctor )
697{
698    return setFromCtor( tor, fields, ctor, TR_FALLBACK );
699}
700
701uint64_t
702tr_torrentLoadResume( tr_torrent *    tor,
703                      uint64_t        fieldsToLoad,
704                      const tr_ctor * ctor )
705{
706    uint64_t ret = 0;
707
708    ret |= useManditoryFields( tor, fieldsToLoad, ctor );
709    fieldsToLoad &= ~ret;
710    ret |= loadFromFile( tor, fieldsToLoad );
711    fieldsToLoad &= ~ret;
712    ret |= useFallbackFields( tor, fieldsToLoad, ctor );
713
714    return ret;
715}
716
717void
718tr_torrentRemoveResume( const tr_torrent * tor )
719{
720    char * filename = getResumeFilename( tor );
721
722    unlink( filename );
723    tr_fastResumeRemove( tor );
724    tr_free( filename );
725}
726
Note: See TracBrowser for help on using the repository browser.