An open and free bittorrent tracker https://erdgeist.org/gitweb/opentracker
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

140 lines
4.0 KiB

  1. /* This software was written by Dirk Engling <erdgeist@erdgeist.org>
  2. It is considered beerware. Prost. Skol. Cheers or whatever.
  3. $id$ */
  4. /* System */
  5. #include <pthread.h>
  6. #include <unistd.h>
  7. #include <string.h>
  8. /* Libowfat */
  9. #include "io.h"
  10. /* Opentracker */
  11. #include "trackerlogic.h"
  12. #include "ot_mutex.h"
  13. #include "ot_vector.h"
  14. #include "ot_clean.h"
  15. #include "ot_stats.h"
  16. /* Returns amount of removed peers */
  17. static ssize_t clean_single_bucket( ot_peer *peers, size_t peer_count, time_t timedout, int *removed_seeders ) {
  18. ot_peer *last_peer = peers + peer_count, *insert_point;
  19. time_t timediff;
  20. /* Two scan modes: unless there is one peer removed, just increase ot_peertime */
  21. while( peers < last_peer ) {
  22. if( ( timediff = timedout + OT_PEERTIME( peers ) ) >= OT_PEER_TIMEOUT )
  23. break;
  24. OT_PEERTIME( peers++ ) = timediff;
  25. }
  26. /* If we at least remove one peer, we have to copy */
  27. insert_point = peers;
  28. while( peers < last_peer )
  29. if( ( timediff = timedout + OT_PEERTIME( peers ) ) < OT_PEER_TIMEOUT ) {
  30. OT_PEERTIME( peers ) = timediff;
  31. memcpy( insert_point++, peers++, sizeof(ot_peer));
  32. } else
  33. if( OT_PEERFLAG( peers++ ) & PEER_FLAG_SEEDING )
  34. (*removed_seeders)++;
  35. return peers - insert_point;
  36. }
  37. /* Clean a single torrent
  38. return 1 if torrent timed out
  39. */
  40. int clean_single_torrent( ot_torrent *torrent ) {
  41. ot_peerlist *peer_list = torrent->peer_list;
  42. ot_vector *bucket_list = &peer_list->peers;
  43. time_t timedout = (time_t)( g_now_minutes - peer_list->base );
  44. int num_buckets = 1, removed_seeders = 0;
  45. /* No need to clean empty torrent */
  46. if( !timedout )
  47. return 0;
  48. /* Torrent has idled out */
  49. if( timedout > OT_TORRENT_TIMEOUT )
  50. return 1;
  51. /* Nothing to be cleaned here? Test if torrent is worth keeping */
  52. if( timedout > OT_PEER_TIMEOUT ) {
  53. if( !peer_list->peer_count )
  54. return peer_list->down_count ? 0 : 1;
  55. timedout = OT_PEER_TIMEOUT;
  56. }
  57. if( OT_PEERLIST_HASBUCKETS( peer_list ) ) {
  58. num_buckets = bucket_list->size;
  59. bucket_list = (ot_vector *)bucket_list->data;
  60. }
  61. while( num_buckets-- ) {
  62. size_t removed_peers = clean_single_bucket( bucket_list->data, bucket_list->size, timedout, &removed_seeders );
  63. peer_list->peer_count -= removed_peers;
  64. bucket_list->size -= removed_peers;
  65. if( bucket_list->size < removed_peers )
  66. vector_fixup_peers( bucket_list );
  67. ++bucket_list;
  68. }
  69. peer_list->seed_count -= removed_seeders;
  70. /* See, if we need to convert a torrent from simple vector to bucket list */
  71. if( ( peer_list->peer_count > OT_PEER_BUCKET_MINCOUNT ) || OT_PEERLIST_HASBUCKETS(peer_list) )
  72. vector_redistribute_buckets( peer_list );
  73. if( peer_list->peer_count )
  74. peer_list->base = g_now_minutes;
  75. else {
  76. /* When we got here, the last time that torrent
  77. has been touched is OT_PEER_TIMEOUT Minutes before */
  78. peer_list->base = g_now_minutes - OT_PEER_TIMEOUT;
  79. }
  80. return 0;
  81. }
  82. /* Clean up all peers in current bucket, remove timedout pools and
  83. torrents */
  84. static void * clean_worker( void * args ) {
  85. (void) args;
  86. while( 1 ) {
  87. int bucket = OT_BUCKET_COUNT;
  88. while( bucket-- ) {
  89. ot_vector *torrents_list = mutex_bucket_lock( bucket );
  90. size_t toffs;
  91. int delta_torrentcount = 0;
  92. for( toffs=0; toffs<torrents_list->size; ++toffs ) {
  93. ot_torrent *torrent = ((ot_torrent*)(torrents_list->data)) + toffs;
  94. if( clean_single_torrent( torrent ) ) {
  95. vector_remove_torrent( torrents_list, torrent );
  96. --delta_torrentcount;
  97. --toffs;
  98. }
  99. }
  100. mutex_bucket_unlock( bucket, delta_torrentcount );
  101. if( !g_opentracker_running )
  102. return NULL;
  103. usleep( OT_CLEAN_SLEEP );
  104. }
  105. stats_cleanup();
  106. }
  107. return NULL;
  108. }
  109. static pthread_t thread_id;
  110. void clean_init( void ) {
  111. pthread_create( &thread_id, NULL, clean_worker, NULL );
  112. }
  113. void clean_deinit( void ) {
  114. pthread_cancel( thread_id );
  115. }
  116. const char *g_version_clean_c = "$Source: /home/cvsroot/opentracker/ot_clean.c,v $: $Revision: 1.22 $\n";