Make chunked transfers use gzip also
[opentracker.git] / ot_clean.c
blob739e7850786194ef321ecc5ad2b1d8378a58adc2
1 /* This software was written by Dirk Engling <erdgeist@erdgeist.org>
2 It is considered beerware. Prost. Skol. Cheers or whatever.
4 $id$ */
6 /* System */
7 #include <pthread.h>
8 #include <unistd.h>
9 #include <string.h>
11 /* Libowfat */
12 #include "io.h"
14 /* Opentracker */
15 #include "trackerlogic.h"
16 #include "ot_mutex.h"
17 #include "ot_vector.h"
18 #include "ot_clean.h"
19 #include "ot_stats.h"
20 #include "ot_accesslist.h"
22 /* Returns amount of removed peers */
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 * peer_size, *insert_point;
26 /* Two scan modes: unless there is one peer removed, just increase ot_peertime */
27 while( peers < last_peer ) {
28 time_t timediff = timedout + OT_PEERTIME( peers, peer_size );
29 if( timediff >= OT_PEER_TIMEOUT )
30 break;
31 OT_PEERTIME( peers, peer_size ) = timediff;
32 peers += peer_size;
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 );
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
44 if( OT_PEERFLAG_D( peers, peer_size ) & PEER_FLAG_SEEDING )
45 (*removed_seeders)++;
48 return (peers - insert_point) / peer_size;
51 int clean_single_peer_list( ot_peerlist *peer_list, size_t peer_size ) {
52 ot_vector *peer_vector = &peer_list->peers;
53 time_t timedout = (time_t)( g_now_minutes - peer_list->base );
54 int num_buckets = 1, removed_seeders = 0;
56 /* No need to clean empty torrent */
57 if( !timedout )
58 return 0;
60 /* Torrent has idled out */
61 if( timedout > OT_TORRENT_TIMEOUT )
62 return 1;
64 /* Nothing to be cleaned here? Test if torrent is worth keeping */
65 if( timedout > OT_PEER_TIMEOUT ) {
66 if( !peer_list->peer_count )
67 return peer_list->down_count ? 0 : 1;
68 timedout = OT_PEER_TIMEOUT;
71 if( OT_PEERLIST_HASBUCKETS( peer_list ) ) {
72 num_buckets = peer_vector->size;
73 peer_vector = (ot_vector *)peer_vector->data;
76 while( num_buckets-- ) {
77 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;
79 peer_vector->size -= removed_peers;
80 if( removed_peers )
81 vector_fixup_peers( peer_vector, peer_size );
83 /* Skip to next bucket, a vector containing peers */
84 ++peer_vector;
87 peer_list->seed_count -= removed_seeders;
89 /* See if we need to convert a torrent from simple vector to bucket list */
90 if( ( peer_list->peer_count > OT_PEER_BUCKET_MINCOUNT ) || OT_PEERLIST_HASBUCKETS(peer_list) )
91 vector_redistribute_buckets( peer_list, peer_size );
93 if( peer_list->peer_count )
94 peer_list->base = g_now_minutes;
95 else {
96 /* When we got here, the last time that torrent
97 has been touched is OT_PEER_TIMEOUT Minutes before */
98 peer_list->base = g_now_minutes - OT_PEER_TIMEOUT;
100 return 0;
103 /* Clean a single torrent
104 return 1 if torrent timed out
106 int clean_single_torrent( ot_torrent *torrent ) {
107 return clean_single_peer_list( torrent->peer_list6, OT_PEER_SIZE6) *
108 clean_single_peer_list( torrent->peer_list4, OT_PEER_SIZE4);
111 /* Clean up all peers in current bucket, remove timedout pools and
112 torrents */
113 static void * clean_worker( void * args ) {
114 (void) args;
115 while( 1 ) {
116 int bucket = OT_BUCKET_COUNT;
117 while( bucket-- ) {
118 ot_vector *torrents_list = mutex_bucket_lock( bucket );
119 size_t toffs;
120 int delta_torrentcount = 0;
122 for( toffs=0; toffs<torrents_list->size; ++toffs ) {
123 ot_torrent *torrent = ((ot_torrent*)(torrents_list->data)) + toffs;
124 if( clean_single_torrent( torrent ) ) {
125 vector_remove_torrent( torrents_list, torrent );
126 --delta_torrentcount;
127 --toffs;
130 mutex_bucket_unlock( bucket, delta_torrentcount );
131 if( !g_opentracker_running )
132 return NULL;
133 usleep( OT_CLEAN_SLEEP );
135 stats_cleanup();
136 #ifdef WANT_ACCESSLIST
137 accesslist_cleanup();
138 #endif
140 return NULL;
143 static pthread_t thread_id;
144 void clean_init( void ) {
145 pthread_create( &thread_id, NULL, clean_worker, NULL );
148 void clean_deinit( void ) {
149 pthread_cancel( thread_id );
152 const char *g_version_clean_c = "$Source$: $Revision$\n";