diff --git a/src/box/index.m b/src/box/index.m index ca67def06477c481d5127e5a2bb62815f7d4e0b6..6e7f1fdaf4992958d3e47413d816aa106ef5bad1 100644 --- a/src/box/index.m +++ b/src/box/index.m @@ -46,19 +46,6 @@ static struct index_traits hash_index_traits = { const char *field_data_type_strs[] = {"NUM", "NUM64", "STR", "\0"}; const char *index_type_strs[] = { "HASH", "TREE", "\0" }; -static struct tuple * -iterator_next_equal(struct iterator *it __attribute__((unused))) -{ - return NULL; -} - -static struct tuple * -iterator_first_equal(struct iterator *it) -{ - it->next_equal = iterator_next_equal; - return it->next(it); -} - static void check_key_parts(struct key_def *key_def, int part_count, bool partial_key_allowed) @@ -261,25 +248,38 @@ check_key_parts(struct key_def *key_def, /* }}} */ -/* {{{ HashIndex -- base class for all hashes. ********************/ +/* {{{ HashIndex Iterators ****************************************/ -struct hash_iterator { +struct hash_i32_iterator { struct iterator base; /* Must be the first member. */ struct mh_i32ptr_t *hash; mh_int_t h_pos; }; -static struct hash_iterator * -hash_iterator(struct iterator *it) +struct hash_i64_iterator { + struct iterator base; + struct mh_i64ptr_t *hash; + mh_int_t h_pos; +}; + +struct hash_lstr_iterator { + struct iterator base; + struct mh_lstrptr_t *hash; + mh_int_t h_pos; +}; + +void +hash_iterator_free(struct iterator *iterator) { - return (struct hash_iterator *) it; + assert(iterator->free == hash_iterator_free); + free(iterator); } struct tuple * -hash_iterator_next(struct iterator *iterator) +hash_iterator_i32_ge(struct iterator *ptr) { - assert(iterator->next == hash_iterator_next); - struct hash_iterator *it = hash_iterator(iterator); + assert(ptr->free == hash_iterator_free); + struct hash_i32_iterator *it = (struct hash_i32_iterator *) ptr; while (it->h_pos < mh_end(it->hash)) { if (mh_exist(it->hash, it->h_pos)) @@ -289,13 +289,64 @@ hash_iterator_next(struct iterator *iterator) return NULL; } -void -hash_iterator_free(struct iterator *iterator) +struct tuple * +hash_iterator_i64_ge(struct iterator *ptr) { - assert(iterator->next == hash_iterator_next); - free(iterator); + assert(ptr->free == hash_iterator_free); + struct hash_i64_iterator *it = (struct hash_i64_iterator *) ptr; + + while (it->h_pos < mh_end(it->hash)) { + if (mh_exist(it->hash, it->h_pos)) + return mh_value(it->hash, it->h_pos++); + it->h_pos++; + } + return NULL; +} + +struct tuple * +hash_iterator_lstr_ge(struct iterator *ptr) +{ + assert(ptr->free == hash_iterator_free); + struct hash_lstr_iterator *it = (struct hash_lstr_iterator *) ptr; + + while (it->h_pos < mh_end(it->hash)) { + if (mh_exist(it->hash, it->h_pos)) + return mh_value(it->hash, it->h_pos++); + it->h_pos++; + } + return NULL; +} + +static struct tuple * +hash_iterator_eq_next(struct iterator *it __attribute__((unused))) +{ + return NULL; +} + +static struct tuple * +hash_iterator_i32_eq(struct iterator *it) +{ + it->next_equal = hash_iterator_eq_next; + return hash_iterator_i32_ge(it); +} + +static struct tuple * +hash_iterator_i64_eq(struct iterator *it) +{ + it->next_equal = hash_iterator_eq_next; + return hash_iterator_i64_ge(it); +} + +static struct tuple * +hash_iterator_lstr_eq(struct iterator *it) +{ + it->next_equal = hash_iterator_eq_next; + return hash_iterator_lstr_ge(it); } +/* }}} */ + +/* {{{ HashIndex -- base class for all hashes. ********************/ @implementation HashIndex @@ -370,17 +421,6 @@ hash_iterator_free(struct iterator *iterator) return [self findUnsafe :field :1]; } -- (struct iterator *) allocIterator -{ - struct hash_iterator *it = malloc(sizeof(struct hash_iterator)); - if (it) { - memset(it, 0, sizeof(struct hash_iterator)); - it->base.next = hash_iterator_next; - it->base.free = hash_iterator_free; - } - return (struct iterator *) it; -} - @end /* }}} */ @@ -479,10 +519,21 @@ int32_key_to_value(void *key) #endif } +- (struct iterator *) allocIterator +{ + struct hash_i32_iterator *it = malloc(sizeof(struct hash_i32_iterator)); + if (it) { + memset(it, 0, sizeof(*it)); + it->base.next = hash_iterator_i32_ge; + it->base.free = hash_iterator_free; + } + return (struct iterator *) it; +} + - (void) initIterator: (struct iterator *) iterator :(enum iterator_type) type { - assert(iterator->next == hash_iterator_next); - struct hash_iterator *it = hash_iterator(iterator); + assert(iterator->next == hash_iterator_i32_ge); + struct hash_i32_iterator *it = (struct hash_i32_iterator *) iterator; if (type == ITER_REVERSE) tnt_raise(IllegalParams, :"hash iterator is forward only"); @@ -499,11 +550,11 @@ int32_key_to_value(void *key) if (type == ITER_REVERSE) tnt_raise(IllegalParams, :"hash iterator is forward only"); - assert(iterator->next == hash_iterator_next); - struct hash_iterator *it = hash_iterator(iterator); + assert(iterator->next == hash_iterator_i32_ge); + struct hash_i32_iterator *it = (struct hash_i32_iterator *) iterator; u32 num = int32_key_to_value(key); - it->base.next_equal = iterator_first_equal; + it->base.next_equal = hash_iterator_i32_eq; it->h_pos = mh_i32ptr_get(int_hash, num); it->hash = int_hash; } @@ -602,17 +653,28 @@ int64_key_to_value(void *key) #endif } +- (struct iterator *) allocIterator +{ + struct hash_i64_iterator *it = malloc(sizeof(struct hash_i64_iterator)); + if (it) { + memset(it, 0, sizeof(*it)); + it->base.next = hash_iterator_i64_ge; + it->base.free = hash_iterator_free; + } + return (struct iterator *) it; +} + - (void) initIterator: (struct iterator *) iterator :(enum iterator_type) type { - assert(iterator->next == hash_iterator_next); - struct hash_iterator *it = hash_iterator(iterator); + assert(iterator->next == hash_iterator_i64_ge); + struct hash_i64_iterator *it = (struct hash_i64_iterator *) iterator; if (type == ITER_REVERSE) tnt_raise(IllegalParams, :"hash iterator is forward only"); it->base.next_equal = 0; /* Should not be used if not positioned. */ it->h_pos = mh_begin(int64_hash); - it->hash = (struct mh_i32ptr_t *) int64_hash; + it->hash = int64_hash; } - (void) initIteratorUnsafe: (struct iterator *) iterator :(enum iterator_type) type @@ -622,14 +684,14 @@ int64_key_to_value(void *key) if (type == ITER_REVERSE) tnt_raise(IllegalParams, :"hash iterator is forward only"); - assert(iterator->next == hash_iterator_next); - struct hash_iterator *it = hash_iterator(iterator); + assert(iterator->next == hash_iterator_i64_ge); + struct hash_i64_iterator *it = (struct hash_i64_iterator *) iterator; u64 num = int64_key_to_value(key); - it->base.next_equal = iterator_first_equal; + it->base.next_equal = hash_iterator_i64_eq; it->h_pos = mh_i64ptr_get(int64_hash, num); - it->hash = (struct mh_i32ptr_t *) int64_hash; + it->hash = int64_hash; } @end @@ -720,17 +782,29 @@ int64_key_to_value(void *key) #endif } +- (struct iterator *) allocIterator +{ + struct hash_lstr_iterator *it = malloc(sizeof(struct hash_lstr_iterator)); + if (it) { + memset(it, 0, sizeof(*it)); + it->base.next = hash_iterator_lstr_ge; + it->base.free = hash_iterator_free; + } + return (struct iterator *) it; +} + + - (void) initIterator: (struct iterator *) iterator :(enum iterator_type) type { - assert(iterator->next == hash_iterator_next); - struct hash_iterator *it = hash_iterator(iterator); + assert(iterator->next == hash_iterator_lstr_ge); + struct hash_lstr_iterator *it = (struct hash_lstr_iterator *) iterator; if (type == ITER_REVERSE) tnt_raise(IllegalParams, :"hash iterator is forward only"); it->base.next_equal = 0; /* Should not be used if not positioned. */ it->h_pos = mh_begin(str_hash); - it->hash = (struct mh_i32ptr_t *) str_hash; + it->hash = str_hash; } - (void) initIteratorUnsafe: (struct iterator *) iterator @@ -741,12 +815,12 @@ int64_key_to_value(void *key) if (type == ITER_REVERSE) tnt_raise(IllegalParams, :"hash iterator is forward only"); - assert(iterator->next == hash_iterator_next); - struct hash_iterator *it = hash_iterator(iterator); + assert(iterator->next == hash_iterator_lstr_ge); + struct hash_lstr_iterator *it = (struct hash_lstr_iterator *) iterator; - it->base.next_equal = iterator_first_equal; + it->base.next_equal = hash_iterator_lstr_eq; it->h_pos = mh_lstrptr_get(str_hash, key); - it->hash = (struct mh_i32ptr_t *) str_hash; + it->hash = str_hash; } @end