diff options
| author | erdgeist <> | 2007-11-06 11:58:32 +0000 |
|---|---|---|
| committer | erdgeist <> | 2007-11-06 11:58:32 +0000 |
| commit | 8900cc0dd980cb08a0af957a1d0dd849bf3c2ac6 (patch) | |
| tree | 70aeed1dbaceea343e6ebd000d46df025bae21fc /ot_vector.c | |
| parent | 5749f1d8fe80cbb84d66a265bcf9bafe159985ab (diff) | |
No one can get access to buckets now without locking them. Also split up the trackerlogic.c-monster in functional sub-units. HEADS UP: this code is untested and not considered stable.
Diffstat (limited to 'ot_vector.c')
| -rw-r--r-- | ot_vector.c | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/ot_vector.c b/ot_vector.c new file mode 100644 index 0000000..aa71279 --- /dev/null +++ b/ot_vector.c | |||
| @@ -0,0 +1,110 @@ | |||
| 1 | /* This software was written by Dirk Engling <erdgeist@erdgeist.org> | ||
| 2 | It is considered beerware. Prost. Skol. Cheers or whatever. */ | ||
| 3 | |||
| 4 | /* System */ | ||
| 5 | #include <stdlib.h> | ||
| 6 | #include <string.h> | ||
| 7 | |||
| 8 | /* Opentracker */ | ||
| 9 | #include "trackerlogic.h" | ||
| 10 | #include "ot_vector.h" | ||
| 11 | |||
| 12 | /* This function gives us a binary search that returns a pointer, even if | ||
| 13 | no exact match is found. In that case it sets exactmatch 0 and gives | ||
| 14 | calling functions the chance to insert data | ||
| 15 | */ | ||
| 16 | void *binary_search( const void * const key, const void * base, const size_t member_count, const size_t member_size, | ||
| 17 | size_t compare_size, int *exactmatch ) { | ||
| 18 | size_t mc = member_count; | ||
| 19 | ot_byte *lookat = ((ot_byte*)base) + member_size * (member_count >> 1); | ||
| 20 | *exactmatch = 1; | ||
| 21 | |||
| 22 | while( mc ) { | ||
| 23 | int cmp = memcmp( lookat, key, compare_size); | ||
| 24 | if (cmp == 0) return (void *)lookat; | ||
| 25 | if (cmp < 0) { | ||
| 26 | base = (void*)(lookat + member_size); | ||
| 27 | --mc; | ||
| 28 | } | ||
| 29 | mc >>= 1; | ||
| 30 | lookat = ((ot_byte*)base) + member_size * (mc >> 1); | ||
| 31 | } | ||
| 32 | *exactmatch = 0; | ||
| 33 | return (void*)lookat; | ||
| 34 | } | ||
| 35 | |||
| 36 | /* This is the generic insert operation for our vector type. | ||
| 37 | It tries to locate the object at "key" with size "member_size" by comparing its first "compare_size" bytes with | ||
| 38 | those of objects in vector. Our special "binary_search" function does that and either returns the match or a | ||
| 39 | pointer to where the object is to be inserted. vector_find_or_insert makes space for the object and copies it, | ||
| 40 | if it wasn't found in vector. Caller needs to check the passed "exactmatch" variable to see, whether an insert | ||
| 41 | took place. If resizing the vector failed, NULL is returned, else the pointer to the object in vector. | ||
| 42 | */ | ||
| 43 | void *vector_find_or_insert( ot_vector *vector, void *key, size_t member_size, size_t compare_size, int *exactmatch ) { | ||
| 44 | ot_byte *match = binary_search( key, vector->data, vector->size, member_size, compare_size, exactmatch ); | ||
| 45 | |||
| 46 | if( *exactmatch ) return match; | ||
| 47 | |||
| 48 | if( vector->size + 1 >= vector->space ) { | ||
| 49 | size_t new_space = vector->space ? OT_VECTOR_GROW_RATIO * vector->space : OT_VECTOR_MIN_MEMBERS; | ||
| 50 | ot_byte *new_data = realloc( vector->data, new_space * member_size ); | ||
| 51 | if( !new_data ) return NULL; | ||
| 52 | |||
| 53 | /* Adjust pointer if it moved by realloc */ | ||
| 54 | match = new_data + (match - (ot_byte*)vector->data); | ||
| 55 | |||
| 56 | vector->data = new_data; | ||
| 57 | vector->space = new_space; | ||
| 58 | } | ||
| 59 | memmove( match + member_size, match, ((ot_byte*)vector->data) + member_size * vector->size - match ); | ||
| 60 | vector->size++; | ||
| 61 | return match; | ||
| 62 | } | ||
| 63 | |||
| 64 | /* This is the non-generic delete from vector-operation specialized for peers in pools. | ||
| 65 | Set hysteresis == 0 if you expect the vector not to ever grow again. | ||
| 66 | It returns 0 if no peer was found (and thus not removed) | ||
| 67 | 1 if a non-seeding peer was removed | ||
| 68 | 2 if a seeding peer was removed | ||
| 69 | */ | ||
| 70 | int vector_remove_peer( ot_vector *vector, ot_peer *peer, int hysteresis ) { | ||
| 71 | int exactmatch; | ||
| 72 | size_t shrink_thresh = hysteresis ? OT_VECTOR_SHRINK_THRESH : OT_VECTOR_SHRINK_RATIO; | ||
| 73 | ot_peer *end = ((ot_peer*)vector->data) + vector->size; | ||
| 74 | ot_peer *match; | ||
| 75 | |||
| 76 | if( !vector->size ) return 0; | ||
| 77 | match = binary_search( peer, vector->data, vector->size, sizeof( ot_peer ), OT_PEER_COMPARE_SIZE, &exactmatch ); | ||
| 78 | |||
| 79 | if( !exactmatch ) return 0; | ||
| 80 | exactmatch = ( OT_FLAG( match ) & PEER_FLAG_SEEDING ) ? 2 : 1; | ||
| 81 | memmove( match, match + 1, sizeof(ot_peer) * ( end - match - 1 ) ); | ||
| 82 | if( ( --vector->size * shrink_thresh < vector->space ) && ( vector->space > OT_VECTOR_MIN_MEMBERS ) ) { | ||
| 83 | vector->space /= OT_VECTOR_SHRINK_RATIO; | ||
| 84 | vector->data = realloc( vector->data, vector->space * sizeof( ot_peer ) ); | ||
| 85 | } | ||
| 86 | if( !vector->size ) { | ||
| 87 | /* for peer pools its safe to let them go, | ||
| 88 | in 999 of 1000 this happens in older pools, that won't ever grow again */ | ||
| 89 | free( vector->data ); | ||
| 90 | vector->data = NULL; | ||
| 91 | vector->space = 0; | ||
| 92 | } | ||
| 93 | return exactmatch; | ||
| 94 | } | ||
| 95 | |||
| 96 | void vector_remove_torrent( ot_vector *vector, ot_torrent *match ) { | ||
| 97 | ot_torrent *end = ((ot_torrent*)vector->data) + vector->size; | ||
| 98 | |||
| 99 | if( !vector->size ) return; | ||
| 100 | |||
| 101 | /* If this is being called after a unsuccessful malloc() for peer_list | ||
| 102 | in add_peer_to_torrent, match->peer_list actually might be NULL */ | ||
| 103 | if( match->peer_list) free_peerlist( match->peer_list ); | ||
| 104 | |||
| 105 | memmove( match, match + 1, sizeof(ot_torrent) * ( end - match - 1 ) ); | ||
| 106 | if( ( --vector->size * OT_VECTOR_SHRINK_THRESH < vector->space ) && ( vector->space > OT_VECTOR_MIN_MEMBERS ) ) { | ||
| 107 | vector->space /= OT_VECTOR_SHRINK_RATIO; | ||
| 108 | vector->data = realloc( vector->data, vector->space * sizeof( ot_torrent ) ); | ||
| 109 | } | ||
| 110 | } | ||
