diff options
Diffstat (limited to 'src/ot_clean.c')
| -rw-r--r-- | src/ot_clean.c | 64 |
1 files changed, 35 insertions, 29 deletions
diff --git a/src/ot_clean.c b/src/ot_clean.c index 9e2186f..130bd2a 100644 --- a/src/ot_clean.c +++ b/src/ot_clean.c | |||
| @@ -51,51 +51,48 @@ static ssize_t clean_single_bucket(ot_peer *peers, size_t peer_count, size_t pee | |||
| 51 | return (peers - insert_point) / peer_size; | 51 | return (peers - insert_point) / peer_size; |
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | /* Age one family's peers by timedout minutes. Frees the list and clears the | 54 | /* Age one family's peers by timedout minutes. Releases and zeroes the vector |
| 55 | slot once its last peer is gone, so an absent family costs nothing. */ | 55 | once its last peer is gone, so an empty family costs nothing. */ |
| 56 | static void clean_peer_list_family(ot_peerlist **slot, size_t peer_size, ot_time timedout) { | 56 | static void clean_family_vector(ot_vector *peer_vector, size_t peer_size, ot_time timedout, size_t *removed_seeders) { |
| 57 | ot_peerlist *peer_list = *slot; | 57 | ot_vector *bucket = peer_vector; |
| 58 | ot_vector *peer_vector; | 58 | size_t num_buckets = 1, peer_count; |
| 59 | size_t num_buckets = 1, removed_seeders = 0; | ||
| 60 | 59 | ||
| 61 | if (!peer_list) | 60 | if (OT_VECTOR_HASBUCKETS(peer_vector)) { |
| 62 | return; | ||
| 63 | |||
| 64 | peer_vector = &peer_list->peers; | ||
| 65 | if (OT_PEERLIST_HASBUCKETS(peer_list)) { | ||
| 66 | num_buckets = peer_vector->size; | 61 | num_buckets = peer_vector->size; |
| 67 | peer_vector = (ot_vector *)peer_vector->data; | 62 | bucket = (ot_vector *)peer_vector->data; |
| 68 | } | 63 | } |
| 69 | 64 | ||
| 70 | while (num_buckets--) { | 65 | while (num_buckets--) { |
| 71 | size_t removed_peers = clean_single_bucket(peer_vector->data, peer_vector->size, peer_size, timedout, &removed_seeders); | 66 | size_t removed_peers = clean_single_bucket(bucket->data, bucket->size, peer_size, timedout, removed_seeders); |
| 72 | peer_list->peer_count -= removed_peers; | 67 | bucket->size -= removed_peers; |
| 73 | peer_vector->size -= removed_peers; | ||
| 74 | if (removed_peers) | 68 | if (removed_peers) |
| 75 | vector_fixup_peers(peer_vector, peer_size); | 69 | vector_fixup_peers(bucket, peer_size); |
| 76 | 70 | ||
| 77 | /* Skip to next bucket, a vector containing peers */ | 71 | /* Skip to next bucket, a vector containing peers */ |
| 78 | ++peer_vector; | 72 | ++bucket; |
| 79 | } | 73 | } |
| 80 | 74 | ||
| 81 | peer_list->seed_count -= removed_seeders; | 75 | peer_count = vector_peer_count(peer_vector); |
| 82 | 76 | ||
| 83 | if (!peer_list->peer_count) { | 77 | /* Run dry: release the family (a collapsed bucket list or a plain vector) */ |
| 84 | free_peerlist(peer_list); | 78 | if (!peer_count) { |
| 85 | *slot = NULL; | 79 | free_peer_vector(peer_vector); |
| 80 | memset(peer_vector, 0, sizeof(*peer_vector)); | ||
| 86 | return; | 81 | return; |
| 87 | } | 82 | } |
| 88 | 83 | ||
| 89 | /* See if we need to convert the list from simple vector to bucket list */ | 84 | /* See if we need to convert the vector from simple to bucket list or back */ |
| 90 | if ((peer_list->peer_count > OT_PEER_BUCKET_MINCOUNT) || OT_PEERLIST_HASBUCKETS(peer_list)) | 85 | if ((peer_count > OT_PEER_BUCKET_MINCOUNT) || OT_VECTOR_HASBUCKETS(peer_vector)) |
| 91 | vector_redistribute_buckets(peer_list, peer_size); | 86 | vector_redistribute_buckets(peer_vector, peer_size, peer_count); |
| 92 | } | 87 | } |
| 93 | 88 | ||
| 94 | /* Clean a single torrent | 89 | /* Clean a single torrent |
| 95 | return 1 if torrent timed out | 90 | return 1 if torrent timed out |
| 96 | */ | 91 | */ |
| 97 | int clean_single_torrent(ot_torrent *torrent) { | 92 | int clean_single_torrent(ot_torrent *torrent) { |
| 98 | ot_time timedout = time_since_minutes(torrent->base); | 93 | ot_time timedout = time_since_minutes(torrent->base); |
| 94 | ot_peerlist *peer_list = torrent->peer_list; | ||
| 95 | size_t removed_seeders = 0; | ||
| 99 | 96 | ||
| 100 | /* Touched since the last sweep: nothing to do */ | 97 | /* Touched since the last sweep: nothing to do */ |
| 101 | if (!timedout) | 98 | if (!timedout) |
| @@ -107,7 +104,7 @@ int clean_single_torrent(ot_torrent *torrent) { | |||
| 107 | 104 | ||
| 108 | /* Already empty and nothing arrived before the peer timeout: keep it only | 105 | /* Already empty and nothing arrived before the peer timeout: keep it only |
| 109 | while a down count is worth remembering */ | 106 | while a down count is worth remembering */ |
| 110 | if (timedout > OT_PEER_TIMEOUT && !torrent->peer_list6 && !torrent->peer_list4) | 107 | if (timedout > OT_PEER_TIMEOUT && !peer_list) |
| 111 | return (torrent->down_count && timedout <= g_empty_torrent_timeout) ? 0 : 1; | 108 | return (torrent->down_count && timedout <= g_empty_torrent_timeout) ? 0 : 1; |
| 112 | 109 | ||
| 113 | /* Peers past the peer timeout are gone regardless, which caps how far the | 110 | /* Peers past the peer timeout are gone regardless, which caps how far the |
| @@ -115,10 +112,19 @@ int clean_single_torrent(ot_torrent *torrent) { | |||
| 115 | if (timedout > OT_PEER_TIMEOUT) | 112 | if (timedout > OT_PEER_TIMEOUT) |
| 116 | timedout = OT_PEER_TIMEOUT; | 113 | timedout = OT_PEER_TIMEOUT; |
| 117 | 114 | ||
| 118 | clean_peer_list_family(&torrent->peer_list6, OT_PEER_SIZE6, timedout); | 115 | if (peer_list) { |
| 119 | clean_peer_list_family(&torrent->peer_list4, OT_PEER_SIZE4, timedout); | 116 | clean_family_vector(&peer_list->peers6, OT_PEER_SIZE6, timedout, &removed_seeders); |
| 117 | clean_family_vector(&peer_list->peers4, OT_PEER_SIZE4, timedout, &removed_seeders); | ||
| 118 | peer_list->seed_count -= removed_seeders; | ||
| 119 | |||
| 120 | /* Both families gone: drop the peerlist, the torrent keeps only its count */ | ||
| 121 | if (!vector_peer_count(&peer_list->peers6) && !vector_peer_count(&peer_list->peers4)) { | ||
| 122 | free_peerlist(peer_list); | ||
| 123 | torrent->peer_list = peer_list = NULL; | ||
| 124 | } | ||
| 125 | } | ||
| 120 | 126 | ||
| 121 | if (torrent->peer_list6 || torrent->peer_list4) | 127 | if (peer_list) |
| 122 | torrent->base = time_now_minutes(); /* still carrying peers */ | 128 | torrent->base = time_now_minutes(); /* still carrying peers */ |
| 123 | else { | 129 | else { |
| 124 | /* Fell empty: hold base a peer timeout back so a later idle sweep makes | 130 | /* Fell empty: hold base a peer timeout back so a later idle sweep makes |
