Changeset 11832


Ignore:
Timestamp:
Feb 5, 2011, 4:45:06 PM (11 years ago)
Author:
jordan
Message:

(trunk libT) announcer.c cleanup, part 1

Separating this commit into a few different stages. This one is superficial/readability changes, such as grouping related functions together.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/announcer.c

    r11790 r11832  
    235235}
    236236
    237 static void
    238 onUpkeepTimer( int foo UNUSED, short bar UNUSED, void * vannouncer );
    239 
    240237static inline time_t
    241238calcRescheduleWithJitter( const int minPeriod )
     
    250247}
    251248
     249static void
     250onUpkeepTimer( int foo UNUSED, short bar UNUSED, void * vannouncer );
     251
    252252void
    253253tr_announcerInit( tr_session * session )
     
    255255    tr_announcer * a;
    256256
    257     const time_t relaxUntil =
     257    const time_t lpdAt =
    258258        calcRescheduleWithJitter( LPD_HOUSEKEEPING_INTERVAL_SECS / 3 );
    259259
     
    265265    a->session = session;
    266266    a->slotsAvailable = MAX_CONCURRENT_TASKS;
    267     a->lpdHouseKeepingAt = relaxUntil;
     267    a->lpdHouseKeepingAt = lpdAt;
    268268    a->upkeepTimer = evtimer_new( session->event_base, onUpkeepTimer, a );
    269269    tr_timerAdd( a->upkeepTimer, UPKEEP_INTERVAL_SECS, 0 );
     
    314314    uint32_t id;
    315315
    316     /* sent as the "key" argument in tracker requests
     316    /* Sent as the "key" argument in tracker requests
    317317     * to verify us if our IP address changes.
    318318     * This is immutable for the life of the tracker object.
     
    321321}
    322322tr_tracker_item;
    323 
    324 static void
    325 trackerItemCopyAttributes( tr_tracker_item * t, const tr_tracker_item * o )
    326 {
    327     assert( t != o );
    328     assert( t != NULL );
    329     assert( o != NULL );
    330 
    331     t->seederCount = o->seederCount;
    332     t->leecherCount = o->leecherCount;
    333     t->downloadCount = o->downloadCount;
    334     t->downloaderCount = o->downloaderCount;
    335     memcpy( t->key_param, o->key_param, sizeof( t->key_param ) );
    336 }
    337323
    338324static void
     
    373359
    374360    tr_free( tracker->tracker_id );
     361    tr_free( tracker->scrape );
    375362    tr_free( tracker->announce );
    376     tr_free( tracker->scrape );
    377363    tr_free( tracker );
    378364}
     
    463449
    464450static void
    465 tierCopyAttributes( tr_tier * t, const tr_tier * o )
    466 {
    467     int i, n;
    468     tr_tier bak;
    469 
    470     assert( t != NULL );
    471     assert( o != NULL );
    472     assert( t != o );
    473 
    474     bak = *t;
    475     *t = *o;
    476     t->tor = bak.tor;
    477     t->trackers = bak.trackers;
    478     t->announceEvents = bak.announceEvents;
    479     t->currentTracker = bak.currentTracker;
    480     t->currentTrackerIndex = bak.currentTrackerIndex;
    481 
    482     tr_ptrArrayClear( &t->announceEvents );
    483     for( i=0, n=tr_ptrArraySize(&o->announceEvents); i<n; ++i )
    484         tr_ptrArrayAppend( &t->announceEvents, tr_ptrArrayNth((tr_ptrArray*)&o->announceEvents,i) );
    485 }
    486 
    487 static void
    488451tierIncrementTracker( tr_tier * tier )
    489452{
     
    532495typedef struct tr_torrent_tiers
    533496{
    534     tr_ptrArray tiers;
     497    tr_ptrArray tiers; /* tr_tier */
    535498    tr_tracker_callback * callback;
    536499    void * callbackData;
     
    782745
    783746static void
    784 addTorrentToTier( tr_announcer * announcer, tr_torrent_tiers * tiers, tr_torrent * tor )
     747addTorrentToTier( tr_announcer      * announcer,
     748                  tr_torrent_tiers  * tiers,
     749                  tr_torrent        * tor )
    785750{
    786751    int i, n;
     
    841806}
    842807
    843 static void
    844 tierAddAnnounce( tr_tier * tier, const char * announceEvent, time_t announceAt );
    845 
    846 void
    847 tr_announcerResetTorrent( tr_announcer * announcer, tr_torrent * tor )
    848 {
    849     tr_ptrArray oldTiers = TR_PTR_ARRAY_INIT;
    850 
    851     /* if we had tiers already, make a backup of them */
    852     if( tor->tiers != NULL )
    853     {
    854         oldTiers = tor->tiers->tiers;
    855         tor->tiers->tiers = TR_PTR_ARRAY_INIT;
    856     }
    857 
    858     /* create the new tier/tracker structs */
    859     addTorrentToTier( announcer, tor->tiers, tor );
    860 
    861     /* if we had tiers already, merge their state into the new structs */
    862     if( !tr_ptrArrayEmpty( &oldTiers ) )
    863     {
    864         int i, in;
    865         for( i=0, in=tr_ptrArraySize(&oldTiers); i<in; ++i )
    866         {
    867             int j, jn;
    868             const tr_tier * o = tr_ptrArrayNth( &oldTiers, i );
    869 
    870             if( o->currentTracker == NULL )
    871                 continue;
    872 
    873             for( j=0, jn=tr_ptrArraySize(&tor->tiers->tiers); j<jn; ++j )
    874             {
    875                 int k, kn;
    876                 tr_tier * t = tr_ptrArrayNth(&tor->tiers->tiers,j);
    877 
    878                 for( k=0, kn=tr_ptrArraySize(&t->trackers); k<kn; ++k )
    879                 {
    880                     tr_tracker_item * item = tr_ptrArrayNth(&t->trackers,k);
    881                     if( strcmp( o->currentTracker->announce, item->announce ) )
    882                         continue;
    883                     tierCopyAttributes( t, o );
    884                     t->currentTracker = item;
    885                     t->currentTrackerIndex = k;
    886                     t->wasCopied = TRUE;
    887                     trackerItemCopyAttributes( item, o->currentTracker );
    888                     dbgmsg( t, "attributes copied to tier %d, tracker %d"
    889                                                "from tier %d, tracker %d",
    890                             i, o->currentTrackerIndex, j, k );
    891 
    892                 }
    893             }
    894         }
    895     }
    896 
    897     /* kickstart any tiers that didn't get started */
    898     if( tor->isRunning )
    899     {
    900         int i, n;
    901         const time_t now = tr_time( );
    902         tr_tier ** tiers = (tr_tier**) tr_ptrArrayPeek( &tor->tiers->tiers, &n );
    903         for( i=0; i<n; ++i ) {
    904             tr_tier * tier = tiers[i];
    905             if( !tier->wasCopied )
    906                 tierAddAnnounce( tier, STARTED, now );
    907         }
    908     }
    909 
    910     /* cleanup */
    911     tr_ptrArrayDestruct( &oldTiers, tierFree );
    912 }
     808/***
     809****
     810***/
    913811
    914812static tr_bool
     
    1069967}
    1070968
    1071 /* return true if (1) we've tried it recently AND (2) it didn't respond... */
     969/***
     970****
     971***/
     972
    1072973static tr_bool
    1073 hostIsNotResponding( const tr_host * host, const time_t now )
    1074 {
    1075     tr_bool b = ( host->lastRequestTime )
    1076              && ( host->lastRequestTime >= ( now - SLOW_HOST_PENALTY_SECS ) )
    1077              && ( host->lastResponseInterval > MAX_TRACKER_RESPONSE_TIME_SECS );
    1078     return b;
    1079 }
    1080 
    1081 static tr_bool
    1082 tierIsNotResponding( const tr_tier * tier, const time_t now )
    1083 {
    1084     return !tier->currentTracker
    1085         || hostIsNotResponding( tier->currentTracker->host, now );
    1086 }
     974parseAnnounceResponse( tr_tier     * tier,
     975                       const char  * response,
     976                       size_t        responseLen,
     977                       tr_bool     * gotScrape )
     978{
     979    tr_benc benc;
     980    tr_bool success = FALSE;
     981    int scrapeFields = 0;
     982    const int bencLoaded = !tr_bencLoad( response, responseLen, &benc, NULL );
     983
     984    if( getenv( "TR_CURL_VERBOSE" ) != NULL )
     985    {
     986        char * str = tr_bencToStr( &benc, TR_FMT_JSON, NULL );
     987        fprintf( stderr, "Announce response:\n< %s\n", str );
     988        tr_free( str );
     989    }
     990
     991    dbgmsg( tier, "response len: %d, isBenc: %d", (int)responseLen, (int)bencLoaded );
     992    publishErrorClear( tier );
     993    if( bencLoaded && tr_bencIsDict( &benc ) )
     994    {
     995        size_t rawlen;
     996        int64_t i;
     997        tr_benc * tmp;
     998        const char * str;
     999        const uint8_t * raw;
     1000        tr_bool gotPeers = FALSE;
     1001        int peerCount = 0;
     1002
     1003        success = TRUE;
     1004
     1005        if( tr_bencDictFindStr( &benc, "failure reason", &str ) )
     1006        {
     1007            tr_strlcpy( tier->lastAnnounceStr, str,
     1008                        sizeof( tier->lastAnnounceStr ) );
     1009            dbgmsg( tier, "tracker gave \"%s\"", str );
     1010            publishMessage( tier, str, TR_TRACKER_ERROR );
     1011            success = FALSE;
     1012        }
     1013
     1014        if( tr_bencDictFindStr( &benc, "warning message", &str ) )
     1015        {
     1016            tr_strlcpy( tier->lastAnnounceStr, str,
     1017                        sizeof( tier->lastAnnounceStr ) );
     1018            dbgmsg( tier, "tracker gave \"%s\"", str );
     1019            publishWarning( tier, str );
     1020        }
     1021
     1022        if( tr_bencDictFindInt( &benc, "interval", &i ) )
     1023        {
     1024            dbgmsg( tier, "setting interval to %d", (int)i );
     1025            tier->announceIntervalSec = i;
     1026        }
     1027
     1028        if( tr_bencDictFindInt( &benc, "min interval", &i ) )
     1029        {
     1030            dbgmsg( tier, "setting min interval to %d", (int)i );
     1031            tier->announceMinIntervalSec = i;
     1032        }
     1033
     1034        if( tr_bencDictFindStr( &benc, "tracker id", &str ) )
     1035        {
     1036            tier->currentTracker->tracker_id = tr_strdup( str );
     1037        }
     1038
     1039        if( !tr_bencDictFindInt( &benc, "complete", &i ) )
     1040            tier->currentTracker->seederCount = 0;
     1041        else {
     1042            ++scrapeFields;
     1043            tier->currentTracker->seederCount = i;
     1044        }
     1045
     1046        if( !tr_bencDictFindInt( &benc, "incomplete", &i ) )
     1047            tier->currentTracker->leecherCount = 0;
     1048        else {
     1049            ++scrapeFields;
     1050            tier->currentTracker->leecherCount = i;
     1051        }
     1052
     1053        if( tr_bencDictFindInt( &benc, "downloaded", &i ) )
     1054        {
     1055            ++scrapeFields;
     1056            tier->currentTracker->downloadCount = i;
     1057        }
     1058
     1059        if( tr_bencDictFindRaw( &benc, "peers", &raw, &rawlen ) )
     1060        {
     1061            /* "compact" extension */
     1062            const int seeders = tier->currentTracker->seederCount;
     1063            const int leechers = tier->currentTracker->leecherCount;
     1064            peerCount += publishPeersCompact( tier, seeders, leechers, raw, rawlen );
     1065            gotPeers = TRUE;
     1066        }
     1067        else if( tr_bencDictFindList( &benc, "peers", &tmp ) )
     1068        {
     1069            /* original version of peers */
     1070            const int seeders = tier->currentTracker->seederCount;
     1071            const int leechers = tier->currentTracker->leecherCount;
     1072            peerCount += publishPeersDict( tier, seeders, leechers, tmp );
     1073            gotPeers = TRUE;
     1074        }
     1075
     1076        if( tr_bencDictFindRaw( &benc, "peers6", &raw, &rawlen ) )
     1077        {
     1078            /* "compact" extension */
     1079            const int seeders = tier->currentTracker->seederCount;
     1080            const int leechers = tier->currentTracker->leecherCount;
     1081            peerCount += publishPeersCompact6( tier, seeders, leechers, raw, rawlen );
     1082            gotPeers = TRUE;
     1083        }
     1084
     1085        if( tier->lastAnnounceStr[0] == '\0' )
     1086            tr_strlcpy( tier->lastAnnounceStr, _( "Success" ),
     1087                        sizeof( tier->lastAnnounceStr ) );
     1088
     1089        if( gotPeers )
     1090            tier->lastAnnouncePeerCount = peerCount;
     1091    }
     1092
     1093    if( bencLoaded )
     1094        tr_bencFree( &benc );
     1095
     1096    *gotScrape = scrapeFields >= 2;
     1097
     1098    return success;
     1099}
     1100
     1101struct announce_data
     1102{
     1103    int torrentId;
     1104    int tierId;
     1105    time_t timeSent;
     1106    const char * event;
     1107
     1108    /** If the request succeeds, the value for tier's "isRunning" flag */
     1109    tr_bool isRunningOnSuccess;
     1110};
    10871111
    10881112static int
     
    11031127    return ( minutes * 60 ) + jitter_seconds;
    11041128}
    1105 
    1106 static int
    1107 compareTiers( const void * va, const void * vb )
    1108 {
    1109     int ret = 0;
    1110     tr_bool af, bf;
    1111     const tr_tier * a = *(const tr_tier**)va;
    1112     const tr_tier * b = *(const tr_tier**)vb;
    1113 
    1114     /* working domains come before non-working */
    1115     if( !ret ) {
    1116         const time_t now = tr_time( );
    1117         af = tierIsNotResponding( a, now );
    1118         bf = tierIsNotResponding( b, now );
    1119         if( af != bf )
    1120             ret = !af ? -1 : 1;
    1121     }
    1122 
    1123     /* stops come before starts */
    1124     if( !ret ) {
    1125         af = a->tor->isRunning;
    1126         bf = b->tor->isRunning;
    1127         if( af != bf )
    1128             ret = af ? 1 : -1;
    1129     }
    1130 
    1131     /* upload comes before download */
    1132     if( !ret )
    1133         ret = compareTransfer( a->byteCounts[TR_ANN_UP], a->byteCounts[TR_ANN_DOWN],
    1134                                b->byteCounts[TR_ANN_UP], b->byteCounts[TR_ANN_DOWN] );
    1135 
    1136     /* incomplete comes before complete */
    1137     if( !ret ) {
    1138         af = a->tor->completeness == TR_LEECH;
    1139         bf = b->tor->completeness == TR_LEECH;
    1140         if( af != bf )
    1141             return af ? -1 : 1;
    1142     }
    1143 
    1144     /* private before public */
    1145     if( !ret ) {
    1146         af = tr_torrentIsPrivate( a->tor );
    1147         bf = tr_torrentIsPrivate( b->tor );
    1148         if( af != bf )
    1149             ret = af ? -1 : 1;
    1150     }
    1151 
    1152     return ret;
    1153 }
    1154 
    1155 
    1156 static tr_bool
    1157 parseAnnounceResponse( tr_tier     * tier,
    1158                        const char  * response,
    1159                        size_t        responseLen,
    1160                        tr_bool     * gotScrape )
    1161 {
    1162     tr_benc benc;
    1163     tr_bool success = FALSE;
    1164     int scrapeFields = 0;
    1165     const int bencLoaded = !tr_bencLoad( response, responseLen, &benc, NULL );
    1166 
    1167     if( getenv( "TR_CURL_VERBOSE" ) != NULL )
    1168     {
    1169         char * str = tr_bencToStr( &benc, TR_FMT_JSON, NULL );
    1170         fprintf( stderr, "Announce response:\n< %s\n", str );
    1171         tr_free( str );
    1172     }
    1173 
    1174     dbgmsg( tier, "response len: %d, isBenc: %d", (int)responseLen, (int)bencLoaded );
    1175     publishErrorClear( tier );
    1176     if( bencLoaded && tr_bencIsDict( &benc ) )
    1177     {
    1178         int peerCount = 0;
    1179         size_t rawlen;
    1180         int64_t i;
    1181         tr_benc * tmp;
    1182         const char * str;
    1183         const uint8_t * raw;
    1184         tr_bool gotPeers = FALSE;
    1185 
    1186         success = TRUE;
    1187 
    1188         if( tr_bencDictFindStr( &benc, "failure reason", &str ) )
    1189         {
    1190             tr_strlcpy( tier->lastAnnounceStr, str,
    1191                         sizeof( tier->lastAnnounceStr ) );
    1192             dbgmsg( tier, "tracker gave \"%s\"", str );
    1193             publishMessage( tier, str, TR_TRACKER_ERROR );
    1194             success = FALSE;
    1195         }
    1196 
    1197         if( tr_bencDictFindStr( &benc, "warning message", &str ) )
    1198         {
    1199             tr_strlcpy( tier->lastAnnounceStr, str,
    1200                         sizeof( tier->lastAnnounceStr ) );
    1201             dbgmsg( tier, "tracker gave \"%s\"", str );
    1202             publishWarning( tier, str );
    1203         }
    1204 
    1205         if( tr_bencDictFindInt( &benc, "interval", &i ) )
    1206         {
    1207             dbgmsg( tier, "setting interval to %d", (int)i );
    1208             tier->announceIntervalSec = i;
    1209         }
    1210 
    1211         if( tr_bencDictFindInt( &benc, "min interval", &i ) )
    1212         {
    1213             dbgmsg( tier, "setting min interval to %d", (int)i );
    1214             tier->announceMinIntervalSec = i;
    1215         }
    1216 
    1217         if( tr_bencDictFindStr( &benc, "tracker id", &str ) )
    1218         {
    1219             tier->currentTracker->tracker_id = tr_strdup( str );
    1220         }
    1221 
    1222         if( !tr_bencDictFindInt( &benc, "complete", &i ) )
    1223             tier->currentTracker->seederCount = 0;
    1224         else {
    1225             ++scrapeFields;
    1226             tier->currentTracker->seederCount = i;
    1227         }
    1228 
    1229         if( !tr_bencDictFindInt( &benc, "incomplete", &i ) )
    1230             tier->currentTracker->leecherCount = 0;
    1231         else {
    1232             ++scrapeFields;
    1233             tier->currentTracker->leecherCount = i;
    1234         }
    1235 
    1236         if( tr_bencDictFindInt( &benc, "downloaded", &i ) )
    1237         {
    1238             ++scrapeFields;
    1239             tier->currentTracker->downloadCount = i;
    1240         }
    1241 
    1242         if( tr_bencDictFindRaw( &benc, "peers", &raw, &rawlen ) )
    1243         {
    1244             /* "compact" extension */
    1245             const int seeders = tier->currentTracker->seederCount;
    1246             const int leechers = tier->currentTracker->leecherCount;
    1247             peerCount += publishPeersCompact( tier, seeders, leechers, raw, rawlen );
    1248             gotPeers = TRUE;
    1249         }
    1250         else if( tr_bencDictFindList( &benc, "peers", &tmp ) )
    1251         {
    1252             /* original version of peers */
    1253             const int seeders = tier->currentTracker->seederCount;
    1254             const int leechers = tier->currentTracker->leecherCount;
    1255             peerCount += publishPeersDict( tier, seeders, leechers, tmp );
    1256             gotPeers = TRUE;
    1257         }
    1258 
    1259         if( tr_bencDictFindRaw( &benc, "peers6", &raw, &rawlen ) )
    1260         {
    1261             /* "compact" extension */
    1262             const int seeders = tier->currentTracker->seederCount;
    1263             const int leechers = tier->currentTracker->leecherCount;
    1264             peerCount += publishPeersCompact6( tier, seeders, leechers, raw, rawlen );
    1265             gotPeers = TRUE;
    1266         }
    1267 
    1268         if( tier->lastAnnounceStr[0] == '\0' )
    1269             tr_strlcpy( tier->lastAnnounceStr, _( "Success" ),
    1270                         sizeof( tier->lastAnnounceStr ) );
    1271 
    1272         if( gotPeers )
    1273             tier->lastAnnouncePeerCount = peerCount;
    1274     }
    1275 
    1276     if( bencLoaded )
    1277         tr_bencFree( &benc );
    1278 
    1279     *gotScrape = scrapeFields >= 2;
    1280 
    1281     return success;
    1282 }
    1283 
    1284 struct announce_data
    1285 {
    1286     int torrentId;
    1287     int tierId;
    1288     time_t timeSent;
    1289     const char * event;
    1290 
    1291     /** If the request succeeds, the value for tier's "isRunning" flag */
    1292     tr_bool isRunningOnSuccess;
    1293 };
    12941129
    12951130static void
     
    15131348}
    15141349
     1350/***
     1351****
     1352***/
     1353
    15151354static tr_bool
    15161355parseScrapeResponse( tr_tier     * tier,
     
    16611500    const char * scrape;
    16621501    struct announce_data * data;
    1663     const time_t now = tr_time( );
    16641502
    16651503    assert( tier );
     
    16801518
    16811519    tier->isScraping = TRUE;
    1682     tier->lastScrapeStartTime = now;
     1520    tier->lastScrapeStartTime = tr_time( );
    16831521    --announcer->slotsAvailable;
    16841522    dbgmsg( tier, "scraping \"%s\"", url );
     
    17231561        && ( tier->currentTracker->scrape != NULL );
    17241562}
     1563
     1564/* return true if (1) we've tried it recently AND (2) it didn't respond... */
     1565static tr_bool
     1566hostIsNotResponding( const tr_host * host, const time_t now )
     1567{
     1568    tr_bool b = ( host->lastRequestTime )
     1569             && ( host->lastRequestTime >= ( now - SLOW_HOST_PENALTY_SECS ) )
     1570             && ( host->lastResponseInterval > MAX_TRACKER_RESPONSE_TIME_SECS );
     1571    return b;
     1572}
     1573
     1574static tr_bool
     1575tierIsNotResponding( const tr_tier * tier, const time_t now )
     1576{
     1577    return !tier->currentTracker
     1578        || hostIsNotResponding( tier->currentTracker->host, now );
     1579}
     1580
     1581static int
     1582compareTiers( const void * va, const void * vb )
     1583{
     1584    int ret = 0;
     1585    tr_bool af, bf;
     1586    const tr_tier * a = *(const tr_tier**)va;
     1587    const tr_tier * b = *(const tr_tier**)vb;
     1588
     1589    /* working domains come before non-working */
     1590    if( !ret ) {
     1591        const time_t now = tr_time( );
     1592        af = tierIsNotResponding( a, now );
     1593        bf = tierIsNotResponding( b, now );
     1594        if( af != bf )
     1595            ret = !af ? -1 : 1;
     1596    }
     1597
     1598    /* stops come before starts */
     1599    if( !ret ) {
     1600        af = a->tor->isRunning;
     1601        bf = b->tor->isRunning;
     1602        if( af != bf )
     1603            ret = af ? 1 : -1;
     1604    }
     1605
     1606    /* upload comes before download */
     1607    if( !ret )
     1608        ret = compareTransfer( a->byteCounts[TR_ANN_UP], a->byteCounts[TR_ANN_DOWN],
     1609                               b->byteCounts[TR_ANN_UP], b->byteCounts[TR_ANN_DOWN] );
     1610
     1611    /* incomplete comes before complete */
     1612    if( !ret ) {
     1613        af = a->tor->completeness == TR_LEECH;
     1614        bf = b->tor->completeness == TR_LEECH;
     1615        if( af != bf )
     1616            return af ? -1 : 1;
     1617    }
     1618
     1619    /* private before public */
     1620    if( !ret ) {
     1621        af = tr_torrentIsPrivate( a->tor );
     1622        bf = tr_torrentIsPrivate( b->tor );
     1623        if( af != bf )
     1624            ret = af ? -1 : 1;
     1625    }
     1626
     1627    return ret;
     1628}
     1629
    17251630
    17261631static void
     
    19571862    tr_free( trackers );
    19581863}
     1864
     1865/***
     1866****
     1867***/
     1868
     1869static void
     1870trackerItemCopyAttributes( tr_tracker_item * t, const tr_tracker_item * o )
     1871{
     1872    assert( t != o );
     1873    assert( t != NULL );
     1874    assert( o != NULL );
     1875
     1876    t->seederCount = o->seederCount;
     1877    t->leecherCount = o->leecherCount;
     1878    t->downloadCount = o->downloadCount;
     1879    t->downloaderCount = o->downloaderCount;
     1880    memcpy( t->key_param, o->key_param, sizeof( t->key_param ) );
     1881}
     1882
     1883static void
     1884tierCopyAttributes( tr_tier * t, const tr_tier * o )
     1885{
     1886    int i, n;
     1887    tr_tier bak;
     1888
     1889    assert( t != NULL );
     1890    assert( o != NULL );
     1891    assert( t != o );
     1892
     1893    bak = *t;
     1894    *t = *o;
     1895    t->tor = bak.tor;
     1896    t->trackers = bak.trackers;
     1897    t->announceEvents = bak.announceEvents;
     1898    t->currentTracker = bak.currentTracker;
     1899    t->currentTrackerIndex = bak.currentTrackerIndex;
     1900
     1901    tr_ptrArrayClear( &t->announceEvents );
     1902    for( i=0, n=tr_ptrArraySize(&o->announceEvents); i<n; ++i )
     1903        tr_ptrArrayAppend( &t->announceEvents, tr_ptrArrayNth((tr_ptrArray*)&o->announceEvents,i) );
     1904}
     1905
     1906void
     1907tr_announcerResetTorrent( tr_announcer * announcer, tr_torrent * tor )
     1908{
     1909    tr_ptrArray oldTiers = TR_PTR_ARRAY_INIT;
     1910
     1911    /* if we had tiers already, make a backup of them */
     1912    if( tor->tiers != NULL )
     1913    {
     1914        oldTiers = tor->tiers->tiers;
     1915        tor->tiers->tiers = TR_PTR_ARRAY_INIT;
     1916    }
     1917
     1918    /* create the new tier/tracker structs */
     1919    addTorrentToTier( announcer, tor->tiers, tor );
     1920
     1921    /* if we had tiers already, merge their state into the new structs */
     1922    if( !tr_ptrArrayEmpty( &oldTiers ) )
     1923    {
     1924        int i, in;
     1925        for( i=0, in=tr_ptrArraySize(&oldTiers); i<in; ++i )
     1926        {
     1927            int j, jn;
     1928            const tr_tier * o = tr_ptrArrayNth( &oldTiers, i );
     1929
     1930            if( o->currentTracker == NULL )
     1931                continue;
     1932
     1933            for( j=0, jn=tr_ptrArraySize(&tor->tiers->tiers); j<jn; ++j )
     1934            {
     1935                int k, kn;
     1936                tr_tier * t = tr_ptrArrayNth(&tor->tiers->tiers,j);
     1937
     1938                for( k=0, kn=tr_ptrArraySize(&t->trackers); k<kn; ++k )
     1939                {
     1940                    tr_tracker_item * item = tr_ptrArrayNth(&t->trackers,k);
     1941                    if( strcmp( o->currentTracker->announce, item->announce ) )
     1942                        continue;
     1943                    tierCopyAttributes( t, o );
     1944                    t->currentTracker = item;
     1945                    t->currentTrackerIndex = k;
     1946                    t->wasCopied = TRUE;
     1947                    trackerItemCopyAttributes( item, o->currentTracker );
     1948                    dbgmsg( t, "attributes copied to tier %d, tracker %d"
     1949                                               "from tier %d, tracker %d",
     1950                            i, o->currentTrackerIndex, j, k );
     1951
     1952                }
     1953            }
     1954        }
     1955    }
     1956
     1957    /* kickstart any tiers that didn't get started */
     1958    if( tor->isRunning )
     1959    {
     1960        int i, n;
     1961        const time_t now = tr_time( );
     1962        tr_tier ** tiers = (tr_tier**) tr_ptrArrayPeek( &tor->tiers->tiers, &n );
     1963        for( i=0; i<n; ++i ) {
     1964            tr_tier * tier = tiers[i];
     1965            if( !tier->wasCopied )
     1966                tierAddAnnounce( tier, STARTED, now );
     1967        }
     1968    }
     1969
     1970    /* cleanup */
     1971    tr_ptrArrayDestruct( &oldTiers, tierFree );
     1972}
Note: See TracChangeset for help on using the changeset viewer.