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