1 /* This software was written by Dirk Engling <erdgeist@erdgeist.org>
2 It is considered beerware. Prost. Skol. Cheers or whatever.
15 #include "trackerlogic.h"
17 #include "ot_vector.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
)
31 OT_PEERTIME( peers
, peer_size
) = timediff
;
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
;
44 if( OT_PEERFLAG_D( peers
, peer_size
) & PEER_FLAG_SEEDING
)
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 */
60 /* Torrent has idled out */
61 if( timedout
> OT_TORRENT_TIMEOUT
)
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
;
81 vector_fixup_peers( peer_vector
, peer_size
);
83 /* Skip to next bucket, a vector containing peers */
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
;
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
;
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
113 static void * clean_worker( void * args
) {
116 int bucket
= OT_BUCKET_COUNT
;
118 ot_vector
*torrents_list
= mutex_bucket_lock( bucket
);
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
;
130 mutex_bucket_unlock( bucket
, delta_torrentcount
);
131 if( !g_opentracker_running
)
133 usleep( OT_CLEAN_SLEEP
);
136 #ifdef WANT_ACCESSLIST
137 accesslist_cleanup();
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";