Return a random entry from the hash table. Useful to * implement randomized algorithms */
| 991 | /* Return a random entry from the hash table. Useful to |
| 992 | * implement randomized algorithms */ |
| 993 | dictEntry *dictGetRandomKey(dict *d) |
| 994 | { |
| 995 | dictEntry *he, *orighe; |
| 996 | unsigned long h; |
| 997 | int listlen, listele; |
| 998 | |
| 999 | if (dictSize(d) == 0) return NULL; |
| 1000 | if (dictIsRehashing(d)) _dictRehashStep(d); |
| 1001 | if (dictIsRehashing(d)) { |
| 1002 | long rehashidx = d->rehashidx; |
| 1003 | auto async = d->asyncdata; |
| 1004 | while (async != nullptr) { |
| 1005 | rehashidx = std::min((long)async->rehashIdxBase, rehashidx); |
| 1006 | async = async->next; |
| 1007 | } |
| 1008 | do { |
| 1009 | /* We are sure there are no elements in indexes from 0 |
| 1010 | * to rehashidx-1 */ |
| 1011 | h = rehashidx + (randomULong() % (dictSlots(d) - rehashidx)); |
| 1012 | he = (h >= d->ht[0].size) ? d->ht[1].table[h - d->ht[0].size] : |
| 1013 | d->ht[0].table[h]; |
| 1014 | } while(he == NULL); |
| 1015 | } else { |
| 1016 | do { |
| 1017 | h = randomULong() & d->ht[0].sizemask; |
| 1018 | he = d->ht[0].table[h]; |
| 1019 | } while(he == NULL); |
| 1020 | } |
| 1021 | |
| 1022 | /* Now we found a non empty bucket, but it is a linked |
| 1023 | * list and we need to get a random element from the list. |
| 1024 | * The only sane way to do so is counting the elements and |
| 1025 | * select a random index. */ |
| 1026 | listlen = 0; |
| 1027 | orighe = he; |
| 1028 | while(he) { |
| 1029 | he = he->next; |
| 1030 | listlen++; |
| 1031 | } |
| 1032 | listele = random() % listlen; |
| 1033 | he = orighe; |
| 1034 | while(listele--) he = he->next; |
| 1035 | return he; |
| 1036 | } |
| 1037 | |
| 1038 | /* This function samples the dictionary to return a few keys from random |
| 1039 | * locations. |
no test coverage detected