Skip to content

Commit c57878c

Browse files
committed
Address PR comments
Signed-off-by: Uri Yagelnik <[email protected]>
1 parent 6df1a9a commit c57878c

File tree

3 files changed

+52
-11
lines changed

3 files changed

+52
-11
lines changed

src/hashtable.c

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
*/
4747
#include "hashtable.h"
4848
#include "serverassert.h"
49+
#include "server.h"
4950
#include "zmalloc.h"
5051
#include "mt19937-64.h"
5152
#include "monotonic.h"
@@ -148,8 +149,6 @@ void hashtableSetResizePolicy(hashtableResizePolicy policy) {
148149
#define ENTRIES_PER_BUCKET 7
149150
#define BUCKET_BITS_TYPE uint8_t
150151
#define BITS_NEEDED_TO_STORE_POS_WITHIN_BUCKET 3
151-
/* Iterator table value indicating iteration is complete */
152-
#define HASHTABLE_ITER_END_TABLE 2
153152

154153
/* Selecting the number of buckets.
155154
*
@@ -1936,6 +1935,11 @@ size_t hashtableScanDefrag(hashtable *ht, size_t cursor, hashtableScanFunction f
19361935

19371936
/* --- Iterator --- */
19381937

1938+
#define HASHTABLE_ITER_UNINITIALIZED -1
1939+
#define HASHTABLE_ITER_PRIMARY_TABLE 0
1940+
#define HASHTABLE_ITER_REHASH_TABLE 1
1941+
#define HASHTABLE_ITER_FINISHED 2
1942+
19391943
/* Initialize an iterator for a hashtable.
19401944
*
19411945
* The 'flags' argument can be used to tweak the behaviour. It's a bitwise-or
@@ -1978,11 +1982,12 @@ size_t hashtableScanDefrag(hashtable *ht, size_t cursor, hashtableScanFunction f
19781982
* Call hashtableNext to fetch each entry. You must call hashtableResetIterator
19791983
* when you are done with the iterator.
19801984
*/
1985+
19811986
void hashtableInitIterator(hashtableIterator *iterator, hashtable *ht, uint8_t flags) {
19821987
iter *iter;
19831988
iter = iteratorFromOpaque(iterator);
19841989
iter->hashtable = ht;
1985-
iter->table = 0;
1990+
iter->table = HASHTABLE_ITER_PRIMARY_TABLE;
19861991
iter->index = -1;
19871992
iter->flags = flags;
19881993
}
@@ -1997,7 +2002,7 @@ void hashtableReinitIterator(hashtableIterator *iterator, hashtable *ht) {
19972002
/* Resets a stack-allocated iterator. */
19982003
void hashtableResetIterator(hashtableIterator *iterator) {
19992004
iter *iter = iteratorFromOpaque(iterator);
2000-
if (!(iter->index == -1 && iter->table == 0)) {
2005+
if (!(iter->index == -1 && iter->table == HASHTABLE_ITER_PRIMARY_TABLE)) {
20012006
if (isSafe(iter)) {
20022007
hashtableResumeRehashing(iter->hashtable);
20032008
assert(iter->hashtable->pause_rehash >= 0);
@@ -2028,13 +2033,19 @@ void hashtableReleaseIterator(hashtableIterator *iterator) {
20282033
bool hashtableNext(hashtableIterator *iterator, void **elemptr) {
20292034
iter *iter = iteratorFromOpaque(iterator);
20302035

2031-
assert(iter->table <= HASHTABLE_ITER_END_TABLE);
2032-
if (iter->table == HASHTABLE_ITER_END_TABLE) {
2036+
if (iter->table == HASHTABLE_ITER_FINISHED) {
20332037
return false;
20342038
}
20352039

2040+
/* Check for unexpected iterator states that indicate bugs */
2041+
debugServerAssert(iter->table < HASHTABLE_ITER_FINISHED &&
2042+
(iter->table != HASHTABLE_ITER_REHASH_TABLE || hashtableIsRehashing(iter->hashtable)) &&
2043+
(iter->index < 0 || !iter->hashtable->tables[iter->table] ||
2044+
(size_t)iter->index < numBuckets(iter->hashtable->bucket_exp[iter->table])));
2045+
2046+
20362047
while (1) {
2037-
if (iter->index == -1 && iter->table == 0) {
2048+
if (iter->index == -1 && iter->table == HASHTABLE_ITER_PRIMARY_TABLE) {
20382049
/* It's the first call to next. */
20392050
if (isSafe(iter)) {
20402051
hashtablePauseRehashing(iter->hashtable);
@@ -2079,9 +2090,9 @@ bool hashtableNext(hashtableIterator *iterator, void **elemptr) {
20792090
iter->pos_in_bucket = 0;
20802091
iter->index++;
20812092
if ((size_t)iter->index >= numBuckets(iter->hashtable->bucket_exp[iter->table])) {
2082-
if (hashtableIsRehashing(iter->hashtable) && iter->table == 0) {
2093+
if (hashtableIsRehashing(iter->hashtable) && iter->table == HASHTABLE_ITER_PRIMARY_TABLE) {
20832094
iter->index = 0;
2084-
iter->table++;
2095+
iter->table = HASHTABLE_ITER_REHASH_TABLE;
20852096
} else {
20862097
/* Done. */
20872098
break;
@@ -2110,7 +2121,7 @@ bool hashtableNext(hashtableIterator *iterator, void **elemptr) {
21102121
}
21112122
return true;
21122123
}
2113-
iter->table = HASHTABLE_ITER_END_TABLE;
2124+
iter->table = HASHTABLE_ITER_FINISHED;
21142125
return false;
21152126
}
21162127

src/unit/test_files.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ int test_compact_bucket_chain(int argc, char **argv, int flags);
4141
int test_random_entry(int argc, char **argv, int flags);
4242
int test_random_entry_with_long_chain(int argc, char **argv, int flags);
4343
int test_random_entry_sparse_table(int argc, char **argv, int flags);
44+
int test_iterator_bounds_check(int argc, char **argv, int flags);
4445
int test_intsetValueEncodings(int argc, char **argv, int flags);
4546
int test_intsetBasicAdding(int argc, char **argv, int flags);
4647
int test_intsetLargeNumberRandomAdd(int argc, char **argv, int flags);
@@ -258,7 +259,7 @@ unitTest __test_crc64combine_c[] = {{"test_crc64combine", test_crc64combine}, {N
258259
unitTest __test_dict_c[] = {{"test_dictCreate", test_dictCreate}, {"test_dictAdd16Keys", test_dictAdd16Keys}, {"test_dictDisableResize", test_dictDisableResize}, {"test_dictAddOneKeyTriggerResize", test_dictAddOneKeyTriggerResize}, {"test_dictDeleteKeys", test_dictDeleteKeys}, {"test_dictDeleteOneKeyTriggerResize", test_dictDeleteOneKeyTriggerResize}, {"test_dictEmptyDirAdd128Keys", test_dictEmptyDirAdd128Keys}, {"test_dictDisableResizeReduceTo3", test_dictDisableResizeReduceTo3}, {"test_dictDeleteOneKeyTriggerResizeAgain", test_dictDeleteOneKeyTriggerResizeAgain}, {"test_dictBenchmark", test_dictBenchmark}, {NULL, NULL}};
259260
unitTest __test_endianconv_c[] = {{"test_endianconv", test_endianconv}, {NULL, NULL}};
260261
unitTest __test_entry_c[] = {{"test_entryCreate", test_entryCreate}, {"test_entryUpdate", test_entryUpdate}, {"test_entryHasexpiry_entrySetExpiry", test_entryHasexpiry_entrySetExpiry}, {"test_entryIsExpired", test_entryIsExpired}, {"test_entryMemUsage_entrySetExpiry_entrySetValue", test_entryMemUsage_entrySetExpiry_entrySetValue}, {NULL, NULL}};
261-
unitTest __test_hashtable_c[] = {{"test_cursor", test_cursor}, {"test_set_hash_function_seed", test_set_hash_function_seed}, {"test_add_find_delete", test_add_find_delete}, {"test_add_find_delete_avoid_resize", test_add_find_delete_avoid_resize}, {"test_instant_rehashing", test_instant_rehashing}, {"test_bucket_chain_length", test_bucket_chain_length}, {"test_two_phase_insert_and_pop", test_two_phase_insert_and_pop}, {"test_replace_reallocated_entry", test_replace_reallocated_entry}, {"test_incremental_find", test_incremental_find}, {"test_scan", test_scan}, {"test_iterator", test_iterator}, {"test_safe_iterator", test_safe_iterator}, {"test_compact_bucket_chain", test_compact_bucket_chain}, {"test_random_entry", test_random_entry}, {"test_random_entry_with_long_chain", test_random_entry_with_long_chain}, {"test_random_entry_sparse_table", test_random_entry_sparse_table}, {NULL, NULL}};
262+
unitTest __test_hashtable_c[] = {{"test_cursor", test_cursor}, {"test_set_hash_function_seed", test_set_hash_function_seed}, {"test_add_find_delete", test_add_find_delete}, {"test_add_find_delete_avoid_resize", test_add_find_delete_avoid_resize}, {"test_instant_rehashing", test_instant_rehashing}, {"test_bucket_chain_length", test_bucket_chain_length}, {"test_two_phase_insert_and_pop", test_two_phase_insert_and_pop}, {"test_replace_reallocated_entry", test_replace_reallocated_entry}, {"test_incremental_find", test_incremental_find}, {"test_scan", test_scan}, {"test_iterator", test_iterator}, {"test_safe_iterator", test_safe_iterator}, {"test_compact_bucket_chain", test_compact_bucket_chain}, {"test_random_entry", test_random_entry}, {"test_random_entry_with_long_chain", test_random_entry_with_long_chain}, {"test_random_entry_sparse_table", test_random_entry_sparse_table}, {"test_iterator_bounds_check", test_iterator_bounds_check}, {NULL, NULL}};
262263
unitTest __test_intset_c[] = {{"test_intsetValueEncodings", test_intsetValueEncodings}, {"test_intsetBasicAdding", test_intsetBasicAdding}, {"test_intsetLargeNumberRandomAdd", test_intsetLargeNumberRandomAdd}, {"test_intsetUpgradeFromint16Toint32", test_intsetUpgradeFromint16Toint32}, {"test_intsetUpgradeFromint16Toint64", test_intsetUpgradeFromint16Toint64}, {"test_intsetUpgradeFromint32Toint64", test_intsetUpgradeFromint32Toint64}, {"test_intsetStressLookups", test_intsetStressLookups}, {"test_intsetStressAddDelete", test_intsetStressAddDelete}, {NULL, NULL}};
263264
unitTest __test_kvstore_c[] = {{"test_kvstoreAdd16Keys", test_kvstoreAdd16Keys}, {"test_kvstoreIteratorRemoveAllKeysNoDeleteEmptyHashtable", test_kvstoreIteratorRemoveAllKeysNoDeleteEmptyHashtable}, {"test_kvstoreIteratorRemoveAllKeysDeleteEmptyHashtable", test_kvstoreIteratorRemoveAllKeysDeleteEmptyHashtable}, {"test_kvstoreHashtableIteratorRemoveAllKeysNoDeleteEmptyHashtable", test_kvstoreHashtableIteratorRemoveAllKeysNoDeleteEmptyHashtable}, {"test_kvstoreHashtableIteratorRemoveAllKeysDeleteEmptyHashtable", test_kvstoreHashtableIteratorRemoveAllKeysDeleteEmptyHashtable}, {"test_kvstoreHashtableExpand", test_kvstoreHashtableExpand}, {NULL, NULL}};
264265
unitTest __test_listpack_c[] = {{"test_listpackCreateIntList", test_listpackCreateIntList}, {"test_listpackCreateList", test_listpackCreateList}, {"test_listpackLpPrepend", test_listpackLpPrepend}, {"test_listpackLpPrependInteger", test_listpackLpPrependInteger}, {"test_listpackGetELementAtIndex", test_listpackGetELementAtIndex}, {"test_listpackPop", test_listpackPop}, {"test_listpackGetELementAtIndex2", test_listpackGetELementAtIndex2}, {"test_listpackIterate0toEnd", test_listpackIterate0toEnd}, {"test_listpackIterate1toEnd", test_listpackIterate1toEnd}, {"test_listpackIterate2toEnd", test_listpackIterate2toEnd}, {"test_listpackIterateBackToFront", test_listpackIterateBackToFront}, {"test_listpackIterateBackToFrontWithDelete", test_listpackIterateBackToFrontWithDelete}, {"test_listpackDeleteWhenNumIsMinusOne", test_listpackDeleteWhenNumIsMinusOne}, {"test_listpackDeleteWithNegativeIndex", test_listpackDeleteWithNegativeIndex}, {"test_listpackDeleteInclusiveRange0_0", test_listpackDeleteInclusiveRange0_0}, {"test_listpackDeleteInclusiveRange0_1", test_listpackDeleteInclusiveRange0_1}, {"test_listpackDeleteInclusiveRange1_2", test_listpackDeleteInclusiveRange1_2}, {"test_listpackDeleteWitStartIndexOutOfRange", test_listpackDeleteWitStartIndexOutOfRange}, {"test_listpackDeleteWitNumOverflow", test_listpackDeleteWitNumOverflow}, {"test_listpackBatchDelete", test_listpackBatchDelete}, {"test_listpackDeleteFooWhileIterating", test_listpackDeleteFooWhileIterating}, {"test_listpackReplaceWithSameSize", test_listpackReplaceWithSameSize}, {"test_listpackReplaceWithDifferentSize", test_listpackReplaceWithDifferentSize}, {"test_listpackRegressionGt255Bytes", test_listpackRegressionGt255Bytes}, {"test_listpackCreateLongListAndCheckIndices", test_listpackCreateLongListAndCheckIndices}, {"test_listpackCompareStrsWithLpEntries", test_listpackCompareStrsWithLpEntries}, {"test_listpackLpMergeEmptyLps", test_listpackLpMergeEmptyLps}, {"test_listpackLpMergeLp1Larger", test_listpackLpMergeLp1Larger}, {"test_listpackLpMergeLp2Larger", test_listpackLpMergeLp2Larger}, {"test_listpackLpNextRandom", test_listpackLpNextRandom}, {"test_listpackLpNextRandomCC", test_listpackLpNextRandomCC}, {"test_listpackRandomPairWithOneElement", test_listpackRandomPairWithOneElement}, {"test_listpackRandomPairWithManyElements", test_listpackRandomPairWithManyElements}, {"test_listpackRandomPairsWithOneElement", test_listpackRandomPairsWithOneElement}, {"test_listpackRandomPairsWithManyElements", test_listpackRandomPairsWithManyElements}, {"test_listpackRandomPairsUniqueWithOneElement", test_listpackRandomPairsUniqueWithOneElement}, {"test_listpackRandomPairsUniqueWithManyElements", test_listpackRandomPairsUniqueWithManyElements}, {"test_listpackPushVariousEncodings", test_listpackPushVariousEncodings}, {"test_listpackLpFind", test_listpackLpFind}, {"test_listpackLpValidateIntegrity", test_listpackLpValidateIntegrity}, {"test_listpackNumberOfElementsExceedsLP_HDR_NUMELE_UNKNOWN", test_listpackNumberOfElementsExceedsLP_HDR_NUMELE_UNKNOWN}, {"test_listpackStressWithRandom", test_listpackStressWithRandom}, {"test_listpackSTressWithVariableSize", test_listpackSTressWithVariableSize}, {"test_listpackBenchmarkInit", test_listpackBenchmarkInit}, {"test_listpackBenchmarkLpAppend", test_listpackBenchmarkLpAppend}, {"test_listpackBenchmarkLpFindString", test_listpackBenchmarkLpFindString}, {"test_listpackBenchmarkLpFindNumber", test_listpackBenchmarkLpFindNumber}, {"test_listpackBenchmarkLpSeek", test_listpackBenchmarkLpSeek}, {"test_listpackBenchmarkLpValidateIntegrity", test_listpackBenchmarkLpValidateIntegrity}, {"test_listpackBenchmarkLpCompareWithString", test_listpackBenchmarkLpCompareWithString}, {"test_listpackBenchmarkLpCompareWithNumber", test_listpackBenchmarkLpCompareWithNumber}, {"test_listpackBenchmarkFree", test_listpackBenchmarkFree}, {NULL, NULL}};

src/unit/test_hashtable.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -945,3 +945,32 @@ int test_random_entry_sparse_table(int argc, char **argv, int flags) {
945945
zfree(values);
946946
return 0;
947947
}
948+
949+
int test_iterator_bounds_check(int argc, char **argv, int flags) {
950+
UNUSED(argc);
951+
UNUSED(argv);
952+
UNUSED(flags);
953+
954+
hashtableType type = {0};
955+
hashtable *ht = hashtableCreate(&type);
956+
957+
for (size_t j = 0; j < 100; j++) {
958+
TEST_ASSERT(hashtableAdd(ht, (void *)j));
959+
}
960+
961+
hashtableIterator iter;
962+
void *entry;
963+
hashtableInitIterator(&iter, ht, 0);
964+
965+
size_t count = 0;
966+
while (hashtableNext(&iter, &entry)) count++;
967+
TEST_ASSERT(count == 100);
968+
969+
/* Calling next again should return false */
970+
TEST_ASSERT(!hashtableNext(&iter, &entry));
971+
TEST_ASSERT(!hashtableNext(&iter, &entry));
972+
973+
hashtableResetIterator(&iter);
974+
hashtableRelease(ht);
975+
return 0;
976+
}

0 commit comments

Comments
 (0)