diff options
Diffstat (limited to 'ot_clean.c')
| -rw-r--r-- | ot_clean.c | 135 |
1 files changed, 68 insertions, 67 deletions
| @@ -5,90 +5,91 @@ | |||
| 5 | 5 | ||
| 6 | /* System */ | 6 | /* System */ |
| 7 | #include <pthread.h> | 7 | #include <pthread.h> |
| 8 | #include <unistd.h> | ||
| 9 | #include <string.h> | 8 | #include <string.h> |
| 9 | #include <unistd.h> | ||
| 10 | 10 | ||
| 11 | /* Libowfat */ | 11 | /* Libowfat */ |
| 12 | #include "io.h" | 12 | #include "io.h" |
| 13 | 13 | ||
| 14 | /* Opentracker */ | 14 | /* Opentracker */ |
| 15 | #include "trackerlogic.h" | 15 | #include "ot_accesslist.h" |
| 16 | #include "ot_mutex.h" | ||
| 17 | #include "ot_vector.h" | ||
| 18 | #include "ot_clean.h" | 16 | #include "ot_clean.h" |
| 17 | #include "ot_mutex.h" | ||
| 19 | #include "ot_stats.h" | 18 | #include "ot_stats.h" |
| 20 | #include "ot_accesslist.h" | 19 | #include "ot_vector.h" |
| 20 | #include "trackerlogic.h" | ||
| 21 | 21 | ||
| 22 | /* Returns amount of removed peers */ | 22 | /* Returns amount of removed peers */ |
| 23 | static ssize_t clean_single_bucket( ot_peer *peers, size_t peer_count, time_t timedout, int *removed_seeders ) { | 23 | static ssize_t clean_single_bucket(ot_peer *peers, size_t peer_count, size_t peer_size, time_t timedout, int *removed_seeders) { |
| 24 | ot_peer *last_peer = peers + peer_count, *insert_point; | 24 | ot_peer *last_peer = peers + peer_count * peer_size, *insert_point; |
| 25 | time_t timediff; | ||
| 26 | 25 | ||
| 27 | /* Two scan modes: unless there is one peer removed, just increase ot_peertime */ | 26 | /* Two scan modes: unless there is one peer removed, just increase ot_peertime */ |
| 28 | while( peers < last_peer ) { | 27 | while (peers < last_peer) { |
| 29 | if( ( timediff = timedout + OT_PEERTIME( peers ) ) >= OT_PEER_TIMEOUT ) | 28 | time_t timediff = timedout + OT_PEERTIME(peers, peer_size); |
| 29 | if (timediff >= OT_PEER_TIMEOUT) | ||
| 30 | break; | 30 | break; |
| 31 | OT_PEERTIME( peers++ ) = timediff; | 31 | OT_PEERTIME(peers, peer_size) = timediff; |
| 32 | peers += peer_size; | ||
| 33 | } | ||
| 34 | |||
| 35 | /* If we at least remove one peer, we have to copy */ | ||
| 36 | for (insert_point = peers; peers < last_peer; peers += peer_size) { | ||
| 37 | time_t timediff = timedout + OT_PEERTIME(peers, peer_size); | ||
| 38 | |||
| 39 | if (timediff < OT_PEER_TIMEOUT) { | ||
| 40 | OT_PEERTIME(peers, peer_size) = timediff; | ||
| 41 | memcpy(insert_point, peers, peer_size); | ||
| 42 | insert_point += peer_size; | ||
| 43 | } else if (OT_PEERFLAG_D(peers, peer_size) & PEER_FLAG_SEEDING) | ||
| 44 | (*removed_seeders)++; | ||
| 32 | } | 45 | } |
| 33 | 46 | ||
| 34 | /* If we at least remove one peer, we have to copy */ | 47 | return (peers - insert_point) / peer_size; |
| 35 | insert_point = peers; | ||
| 36 | while( peers < last_peer ) | ||
| 37 | if( ( timediff = timedout + OT_PEERTIME( peers ) ) < OT_PEER_TIMEOUT ) { | ||
| 38 | OT_PEERTIME( peers ) = timediff; | ||
| 39 | memcpy( insert_point++, peers++, sizeof(ot_peer)); | ||
| 40 | } else | ||
| 41 | if( OT_PEERFLAG( peers++ ) & PEER_FLAG_SEEDING ) | ||
| 42 | (*removed_seeders)++; | ||
| 43 | |||
| 44 | return peers - insert_point; | ||
| 45 | } | 48 | } |
| 46 | 49 | ||
| 47 | /* Clean a single torrent | 50 | int clean_single_peer_list(ot_peerlist *peer_list, size_t peer_size) { |
| 48 | return 1 if torrent timed out | 51 | ot_vector *peer_vector = &peer_list->peers; |
| 49 | */ | 52 | time_t timedout = (time_t)(g_now_minutes - peer_list->base); |
| 50 | int clean_single_torrent( ot_torrent *torrent ) { | 53 | int num_buckets = 1, removed_seeders = 0; |
| 51 | ot_peerlist *peer_list = torrent->peer_list; | ||
| 52 | ot_vector *bucket_list = &peer_list->peers; | ||
| 53 | time_t timedout = (time_t)( g_now_minutes - peer_list->base ); | ||
| 54 | int num_buckets = 1, removed_seeders = 0; | ||
| 55 | 54 | ||
| 56 | /* No need to clean empty torrent */ | 55 | /* No need to clean empty torrent */ |
| 57 | if( !timedout ) | 56 | if (!timedout) |
| 58 | return 0; | 57 | return 0; |
| 59 | 58 | ||
| 60 | /* Torrent has idled out */ | 59 | /* Torrent has idled out */ |
| 61 | if( timedout > OT_TORRENT_TIMEOUT ) | 60 | if (timedout > OT_TORRENT_TIMEOUT) |
| 62 | return 1; | 61 | return 1; |
| 63 | 62 | ||
| 64 | /* Nothing to be cleaned here? Test if torrent is worth keeping */ | 63 | /* Nothing to be cleaned here? Test if torrent is worth keeping */ |
| 65 | if( timedout > OT_PEER_TIMEOUT ) { | 64 | if (timedout > OT_PEER_TIMEOUT) { |
| 66 | if( !peer_list->peer_count ) | 65 | if (!peer_list->peer_count) |
| 67 | return peer_list->down_count ? 0 : 1; | 66 | return peer_list->down_count ? 0 : 1; |
| 68 | timedout = OT_PEER_TIMEOUT; | 67 | timedout = OT_PEER_TIMEOUT; |
| 69 | } | 68 | } |
| 70 | 69 | ||
| 71 | if( OT_PEERLIST_HASBUCKETS( peer_list ) ) { | 70 | if (OT_PEERLIST_HASBUCKETS(peer_list)) { |
| 72 | num_buckets = bucket_list->size; | 71 | num_buckets = peer_vector->size; |
| 73 | bucket_list = (ot_vector *)bucket_list->data; | 72 | peer_vector = (ot_vector *)peer_vector->data; |
| 74 | } | 73 | } |
| 75 | 74 | ||
| 76 | while( num_buckets-- ) { | 75 | while (num_buckets--) { |
| 77 | size_t removed_peers = clean_single_bucket( bucket_list->data, bucket_list->size, timedout, &removed_seeders ); | 76 | size_t removed_peers = clean_single_bucket(peer_vector->data, peer_vector->size, peer_size, timedout, &removed_seeders); |
| 78 | peer_list->peer_count -= removed_peers; | 77 | peer_list->peer_count -= removed_peers; |
| 79 | bucket_list->size -= removed_peers; | 78 | peer_vector->size -= removed_peers; |
| 80 | if( bucket_list->size < removed_peers ) | 79 | if (removed_peers) |
| 81 | vector_fixup_peers( bucket_list ); | 80 | vector_fixup_peers(peer_vector, peer_size); |
| 82 | ++bucket_list; | 81 | |
| 82 | /* Skip to next bucket, a vector containing peers */ | ||
| 83 | ++peer_vector; | ||
| 83 | } | 84 | } |
| 84 | 85 | ||
| 85 | peer_list->seed_count -= removed_seeders; | 86 | peer_list->seed_count -= removed_seeders; |
| 86 | 87 | ||
| 87 | /* See, if we need to convert a torrent from simple vector to bucket list */ | 88 | /* See if we need to convert a torrent from simple vector to bucket list */ |
| 88 | if( ( peer_list->peer_count > OT_PEER_BUCKET_MINCOUNT ) || OT_PEERLIST_HASBUCKETS(peer_list) ) | 89 | if ((peer_list->peer_count > OT_PEER_BUCKET_MINCOUNT) || OT_PEERLIST_HASBUCKETS(peer_list)) |
| 89 | vector_redistribute_buckets( peer_list ); | 90 | vector_redistribute_buckets(peer_list, peer_size); |
| 90 | 91 | ||
| 91 | if( peer_list->peer_count ) | 92 | if (peer_list->peer_count) |
| 92 | peer_list->base = g_now_minutes; | 93 | peer_list->base = g_now_minutes; |
| 93 | else { | 94 | else { |
| 94 | /* When we got here, the last time that torrent | 95 | /* When we got here, the last time that torrent |
| @@ -96,32 +97,38 @@ int clean_single_torrent( ot_torrent *torrent ) { | |||
| 96 | peer_list->base = g_now_minutes - OT_PEER_TIMEOUT; | 97 | peer_list->base = g_now_minutes - OT_PEER_TIMEOUT; |
| 97 | } | 98 | } |
| 98 | return 0; | 99 | return 0; |
| 100 | } | ||
| 99 | 101 | ||
| 102 | /* Clean a single torrent | ||
| 103 | return 1 if torrent timed out | ||
| 104 | */ | ||
| 105 | int clean_single_torrent(ot_torrent *torrent) { | ||
| 106 | return clean_single_peer_list(torrent->peer_list6, OT_PEER_SIZE6) * clean_single_peer_list(torrent->peer_list4, OT_PEER_SIZE4); | ||
| 100 | } | 107 | } |
| 101 | 108 | ||
| 102 | /* Clean up all peers in current bucket, remove timedout pools and | 109 | /* Clean up all peers in current bucket, remove timedout pools and |
| 103 | torrents */ | 110 | torrents */ |
| 104 | static void * clean_worker( void * args ) { | 111 | static void *clean_worker(void *args) { |
| 105 | (void) args; | 112 | (void)args; |
| 106 | while( 1 ) { | 113 | while (1) { |
| 107 | int bucket = OT_BUCKET_COUNT; | 114 | int bucket = OT_BUCKET_COUNT; |
| 108 | while( bucket-- ) { | 115 | while (bucket--) { |
| 109 | ot_vector *torrents_list = mutex_bucket_lock( bucket ); | 116 | ot_vector *torrents_list = mutex_bucket_lock(bucket); |
| 110 | size_t toffs; | 117 | size_t toffs; |
| 111 | int delta_torrentcount = 0; | 118 | int delta_torrentcount = 0; |
| 112 | 119 | ||
| 113 | for( toffs=0; toffs<torrents_list->size; ++toffs ) { | 120 | for (toffs = 0; toffs < torrents_list->size; ++toffs) { |
| 114 | ot_torrent *torrent = ((ot_torrent*)(torrents_list->data)) + toffs; | 121 | ot_torrent *torrent = ((ot_torrent *)(torrents_list->data)) + toffs; |
| 115 | if( clean_single_torrent( torrent ) ) { | 122 | if (clean_single_torrent(torrent)) { |
| 116 | vector_remove_torrent( torrents_list, torrent ); | 123 | vector_remove_torrent(torrents_list, torrent); |
| 117 | --delta_torrentcount; | 124 | --delta_torrentcount; |
| 118 | --toffs; | 125 | --toffs; |
| 119 | } | 126 | } |
| 120 | } | 127 | } |
| 121 | mutex_bucket_unlock( bucket, delta_torrentcount ); | 128 | mutex_bucket_unlock(bucket, delta_torrentcount); |
| 122 | if( !g_opentracker_running ) | 129 | if (!g_opentracker_running) |
| 123 | return NULL; | 130 | return NULL; |
| 124 | usleep( OT_CLEAN_SLEEP ); | 131 | usleep(OT_CLEAN_SLEEP); |
| 125 | } | 132 | } |
| 126 | stats_cleanup(); | 133 | stats_cleanup(); |
| 127 | #ifdef WANT_ACCESSLIST | 134 | #ifdef WANT_ACCESSLIST |
| @@ -132,12 +139,6 @@ static void * clean_worker( void * args ) { | |||
| 132 | } | 139 | } |
| 133 | 140 | ||
| 134 | static pthread_t thread_id; | 141 | static pthread_t thread_id; |
| 135 | void clean_init( void ) { | 142 | void clean_init(void) { pthread_create(&thread_id, NULL, clean_worker, NULL); } |
| 136 | pthread_create( &thread_id, NULL, clean_worker, NULL ); | ||
| 137 | } | ||
| 138 | |||
| 139 | void clean_deinit( void ) { | ||
| 140 | pthread_cancel( thread_id ); | ||
| 141 | } | ||
| 142 | 143 | ||
| 143 | const char *g_version_clean_c = "$Source$: $Revision$\n"; | 144 | void clean_deinit(void) { pthread_cancel(thread_id); } |
