From 334c6e4bbb97a4c0656e1b07c3e6a565f68eae2b Mon Sep 17 00:00:00 2001 From: erdgeist <> Date: Fri, 28 Nov 2008 22:21:10 +0000 Subject: The BIG refactoring [tm]. Too many changes to count them. If it doesn't suite you, revert to last version. --- ot_clean.c | 148 +++++++++++++++++++++++++++++-------------------------------- 1 file changed, 71 insertions(+), 77 deletions(-) (limited to 'ot_clean.c') diff --git a/ot_clean.c b/ot_clean.c index 4f18433..e4d8ca2 100644 --- a/ot_clean.c +++ b/ot_clean.c @@ -7,29 +7,53 @@ #include #include #include -#include #include +#include /* Libowfat */ -#include "byte.h" #include "io.h" /* Opentracker */ #include "trackerlogic.h" #include "ot_mutex.h" +#include "ot_vector.h" +#include "ot_clean.h" + +/* Returns amount of removed peers */ +static ssize_t clean_single_bucket( ot_peer *peers, size_t peer_count, time_t timedout, int *removed_seeders ) { + ot_peer *last_peer = peers + peer_count, *insert_point; + time_t timediff; + + /* Two scan modes: unless there is one peer removed, just increase ot_peertime */ + while( peers < last_peer ) { + if( ( timediff = timedout + OT_PEERTIME( peers ) ) >= OT_PEER_TIMEOUT ) + break; + OT_PEERTIME( peers++ ) = timediff; + } + + /* If we at least remove one peer, we have to copy */ + insert_point = peers; + while( peers < last_peer ) + if( ( timediff = timedout + OT_PEERTIME( peers ) ) < OT_PEER_TIMEOUT ) { + OT_PEERTIME( peers ) = timediff; + *(uint64_t*)(insert_point++) = *(uint64_t*)(peers++); + } else + if( OT_FLAG( peers++ ) & PEER_FLAG_SEEDING ) + (*removed_seeders)++; + + return peers - insert_point; +} /* Clean a single torrent return 1 if torrent timed out */ int clean_single_torrent( ot_torrent *torrent ) { ot_peerlist *peer_list = torrent->peer_list; - size_t peers_count = 0, seeds_count; - time_t timedout = (int)( NOW - peer_list->base ); - int i; -#ifdef WANT_SYNC_BATCH - char *new_peers; -#endif + ot_vector *bucket_list = &peer_list->peers; + time_t timedout = (time_t)( g_now_minutes - peer_list->base ); + int num_buckets = 1, removed_seeders = 0; + /* No need to clean empty torrent */ if( !timedout ) return 0; @@ -38,97 +62,67 @@ int clean_single_torrent( ot_torrent *torrent ) { return 1; /* Nothing to be cleaned here? Test if torrent is worth keeping */ - if( timedout > OT_POOLS_COUNT ) { + if( timedout > OT_PEER_TIMEOUT ) { if( !peer_list->peer_count ) return peer_list->down_count ? 0 : 1; - timedout = OT_POOLS_COUNT; + timedout = OT_PEER_TIMEOUT; } - /* Release vectors that have timed out */ - for( i = OT_POOLS_COUNT - timedout; i < OT_POOLS_COUNT; ++i ) - free( peer_list->peers[i].data); - - /* Shift vectors back by the amount of pools that were shifted out */ - memmove( peer_list->peers + timedout, peer_list->peers, sizeof( ot_vector ) * ( OT_POOLS_COUNT - timedout ) ); - byte_zero( peer_list->peers, sizeof( ot_vector ) * timedout ); - - /* Shift back seed counts as well */ - memmove( peer_list->seed_counts + timedout, peer_list->seed_counts, sizeof( size_t ) * ( OT_POOLS_COUNT - timedout ) ); - byte_zero( peer_list->seed_counts, sizeof( size_t ) * timedout ); - -#ifdef WANT_SYNC_BATCH - /* Save the block modified within last OT_POOLS_TIMEOUT */ - if( peer_list->peers[1].size && - ( new_peers = realloc( peer_list->changeset.data, sizeof( ot_peer ) * peer_list->peers[1].size ) ) ) - { - memmove( new_peers, peer_list->peers[1].data, peer_list->peers[1].size ); - peer_list->changeset.data = new_peers; - peer_list->changeset.size = sizeof( ot_peer ) * peer_list->peers[1].size; - } else { - free( peer_list->changeset.data ); - - memset( &peer_list->changeset, 0, sizeof( ot_vector ) ); + if( OT_PEERLIST_HASBUCKETS( peer_list ) ) { + num_buckets = bucket_list->size; + bucket_list = (ot_vector *)bucket_list->data; } -#endif - peers_count = seeds_count = 0; - for( i = 0; i < OT_POOLS_COUNT; ++i ) { - peers_count += peer_list->peers[i].size; - seeds_count += peer_list->seed_counts[i]; + while( num_buckets-- ) { + size_t removed_peers = clean_single_bucket( bucket_list->data, bucket_list->size, timedout, &removed_seeders ); + peer_list->peer_count -= removed_peers; + bucket_list->size -= removed_peers; + if( bucket_list->size < removed_peers ) + vector_fixup_peers( bucket_list ); + ++bucket_list; } - peer_list->seed_count = seeds_count; - peer_list->peer_count = peers_count; - if( peers_count ) - peer_list->base = NOW; + peer_list->seed_count -= removed_seeders; + + /* See, if we need to convert a torrent from simple vector to bucket list */ + if( ( peer_list->peer_count > OT_PEER_BUCKET_MINCOUNT ) || OT_PEERLIST_HASBUCKETS(peer_list) ) + vector_redistribute_buckets( peer_list ); + + if( peer_list->peer_count ) + peer_list->base = g_now_minutes; else { /* When we got here, the last time that torrent - has been touched is OT_POOLS_COUNT units before */ - peer_list->base = NOW - OT_POOLS_COUNT; + has been touched is OT_PEER_TIMEOUT Minutes before */ + peer_list->base = g_now_minutes - OT_PEER_TIMEOUT; } return 0; -} - -static void clean_make() { - int bucket; - - for( bucket = OT_BUCKET_COUNT - 1; bucket >= 0; --bucket ) { - ot_vector *torrents_list = mutex_bucket_lock( bucket ); - size_t toffs; - for( toffs=0; toffssize; ++toffs ) { - ot_torrent *torrent = ((ot_torrent*)(torrents_list->data)) + toffs; - if( clean_single_torrent( torrent ) ) { - vector_remove_torrent( torrents_list, torrent ); - --toffs; continue; - } - } - mutex_bucket_unlock( bucket ); - - /* We want the cleanup to be spread about 2 Minutes to reduce load spikes - during cleanup. Sleeping around two minutes was chosen to allow enough - time for the actual work and fluctuations in timer. */ - usleep( ( 2 * 60 * 1000000 ) / OT_BUCKET_COUNT ); - } } /* Clean up all peers in current bucket, remove timedout pools and - torrents */ + torrents */ static void * clean_worker( void * args ) { - args = args; + args=args; while( 1 ) { - ot_tasktype tasktype = TASK_CLEAN; - ot_taskid taskid = mutex_workqueue_poptask( &tasktype ); - clean_make( ); - mutex_workqueue_pushsuccess( taskid ); + int bucket = OT_BUCKET_COUNT; + while( bucket-- ) { + ot_vector *torrents_list = mutex_bucket_lock( bucket ); + size_t toffs; + + for( toffs=0; toffssize; ++toffs ) { + ot_torrent *torrent = ((ot_torrent*)(torrents_list->data)) + toffs; + if( clean_single_torrent( torrent ) ) { + vector_remove_torrent( torrents_list, torrent ); + --toffs; continue; + } + } + mutex_bucket_unlock( bucket ); + usleep( OT_CLEAN_SLEEP ); + } } return NULL; } -void clean_all_torrents( ) { - mutex_workqueue_pushtask( 0, TASK_CLEAN ); -} - static pthread_t thread_id; void clean_init( void ) { pthread_create( &thread_id, NULL, clean_worker, NULL ); -- cgit v1.2.3