Skip to content

Commit 8883c54

Browse files
vuvovasvoj
authored andcommitted
lf_hash_iterate() function
1 parent 48430e4 commit 8883c54

File tree

3 files changed

+91
-17
lines changed

3 files changed

+91
-17
lines changed

include/lf.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,8 @@ void lf_hash_destroy(LF_HASH *hash);
232232
int lf_hash_insert(LF_HASH *hash, LF_PINS *pins, const void *data);
233233
void *lf_hash_search(LF_HASH *hash, LF_PINS *pins, const void *key, uint keylen);
234234
int lf_hash_delete(LF_HASH *hash, LF_PINS *pins, const void *key, uint keylen);
235+
int lf_hash_iterate(LF_HASH *hash, LF_PINS *pins,
236+
my_hash_walk_action action, void *argument);
235237
/*
236238
shortcut macros to access underlying pinbox functions from an LF_HASH
237239
see _lf_pinbox_get_pins() and _lf_pinbox_put_pins()

mysys/lf_hash.c

Lines changed: 71 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <my_global.h>
2525
#include <m_string.h>
2626
#include <my_sys.h>
27+
#include <mysys_err.h>
2728
#include <my_bit.h>
2829
#include <lf.h>
2930

@@ -57,27 +58,44 @@ typedef struct {
5758
#define PTR(V) (LF_SLIST *)((V) & (~(intptr)1))
5859
#define DELETED(V) ((V) & 1)
5960

60-
/*
61-
DESCRIPTION
61+
/** walk the list, searching for an element or invoking a callback
62+
6263
Search for hashnr/key/keylen in the list starting from 'head' and
6364
position the cursor. The list is ORDER BY hashnr, key
6465
65-
RETURN
66-
0 - not found
67-
1 - found
66+
@param head start walking the list from this node
67+
@param cs charset for comparing keys, NULL if callback is used
68+
@param hashnr hash number to search for
69+
@param key key to search for OR data for the callback
70+
@param keylen length of the key to compare, 0 if callback is used
71+
@param cursor for returning the found element
72+
@param pins see lf_alloc-pin.c
73+
@param callback callback action, invoked for every element
6874
69-
NOTE
75+
@note
7076
cursor is positioned in either case
7177
pins[0..2] are used, they are NOT removed on return
78+
callback might see some elements twice (because of retries)
79+
80+
@return
81+
if find: 0 - not found
82+
1 - found
83+
if callback:
84+
0 - ok
85+
1 - error (callbck returned 1)
7286
*/
7387
static int lfind(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr,
74-
const uchar *key, uint keylen, CURSOR *cursor, LF_PINS *pins)
88+
const uchar *key, uint keylen, CURSOR *cursor, LF_PINS *pins,
89+
my_hash_walk_action callback)
7590
{
7691
uint32 cur_hashnr;
7792
const uchar *cur_key;
7893
uint cur_keylen;
7994
intptr link;
8095

96+
DBUG_ASSERT(!cs || !callback); /* should not be set both */
97+
DBUG_ASSERT(!keylen || !callback); /* should not be set both */
98+
8199
retry:
82100
cursor->prev= (intptr *)head;
83101
do { /* PTR() isn't necessary below, head is a dummy node */
@@ -102,7 +120,12 @@ static int lfind(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr,
102120

103121
if (!DELETED(link))
104122
{
105-
if (cur_hashnr >= hashnr)
123+
if (unlikely(callback))
124+
{
125+
if (callback(cursor->curr + 1, (void*)key))
126+
return 1;
127+
}
128+
else if (cur_hashnr >= hashnr)
106129
{
107130
int r= 1;
108131
if (cur_hashnr > hashnr ||
@@ -153,7 +176,7 @@ static LF_SLIST *linsert(LF_SLIST * volatile *head, CHARSET_INFO *cs,
153176
for (;;)
154177
{
155178
if (lfind(head, cs, node->hashnr, node->key, node->keylen,
156-
&cursor, pins) &&
179+
&cursor, pins, 0) &&
157180
(flags & LF_HASH_UNIQUE))
158181
{
159182
res= 0; /* duplicate found */
@@ -204,7 +227,7 @@ static int ldelete(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr,
204227

205228
for (;;)
206229
{
207-
if (!lfind(head, cs, hashnr, key, keylen, &cursor, pins))
230+
if (!lfind(head, cs, hashnr, key, keylen, &cursor, pins, 0))
208231
{
209232
res= 1; /* not found */
210233
break;
@@ -228,7 +251,7 @@ static int ldelete(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr,
228251
(to ensure the number of "set DELETED flag" actions
229252
is equal to the number of "remove from the list" actions)
230253
*/
231-
lfind(head, cs, hashnr, key, keylen, &cursor, pins);
254+
lfind(head, cs, hashnr, key, keylen, &cursor, pins, 0);
232255
}
233256
res= 0;
234257
break;
@@ -259,7 +282,7 @@ static LF_SLIST *lsearch(LF_SLIST * volatile *head, CHARSET_INFO *cs,
259282
LF_PINS *pins)
260283
{
261284
CURSOR cursor;
262-
int res= lfind(head, cs, hashnr, key, keylen, &cursor, pins);
285+
int res= lfind(head, cs, hashnr, key, keylen, &cursor, pins, 0);
263286
if (res)
264287
_lf_pin(pins, 2, cursor.curr);
265288
else
@@ -462,6 +485,42 @@ void *lf_hash_search(LF_HASH *hash, LF_PINS *pins, const void *key, uint keylen)
462485
return found ? found+1 : 0;
463486
}
464487

488+
489+
/**
490+
Iterate over all elements in hash and call function with the element
491+
492+
@note
493+
If one of 'action' invocations returns 1 the iteration aborts.
494+
'action' might see some elements twice!
495+
496+
@retval 0 ok
497+
@retval 1 error (action returned 1)
498+
@retval EE_OUTOFMEMORY
499+
*/
500+
int lf_hash_iterate(LF_HASH *hash, LF_PINS *pins,
501+
my_hash_walk_action action, void *argument)
502+
{
503+
CURSOR cursor;
504+
uint bucket= 0;
505+
int res;
506+
LF_SLIST * volatile *el;
507+
508+
lf_rwlock_by_pins(pins);
509+
el= _lf_dynarray_lvalue(&hash->array, bucket);
510+
if (unlikely(!el))
511+
return EE_OUTOFMEMORY;
512+
if (*el == NULL && unlikely(initialize_bucket(hash, el, bucket, pins)))
513+
return EE_OUTOFMEMORY;
514+
515+
res= lfind(el, 0, 0, (uchar*)argument, 0, &cursor, pins, action);
516+
517+
_lf_unpin(pins, 2);
518+
_lf_unpin(pins, 1);
519+
_lf_unpin(pins, 0);
520+
lf_rwunlock_by_pins(pins);
521+
return res;
522+
}
523+
465524
static const uchar *dummy_key= (uchar*)"";
466525

467526
/*

unittest/mysys/lf-t.c

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,18 @@ pthread_handler_t test_lf_alloc(void *arg)
113113
return 0;
114114
}
115115

116+
my_bool do_sum(void *num, void *acc)
117+
{
118+
*(int *)acc += *(int *)num;
119+
return 0;
120+
}
121+
122+
116123
#define N_TLH 1000
117124
pthread_handler_t test_lf_hash(void *arg)
118125
{
119126
int m= (*(int *)arg)/(2*N_TLH);
120-
int32 x,y,z,sum= 0, ins= 0;
127+
int32 x,y,z,sum= 0, ins= 0, scans= 0;
121128
LF_PINS *pins;
122129

123130
if (with_my_thread_init)
@@ -138,6 +145,12 @@ pthread_handler_t test_lf_hash(void *arg)
138145
sum+= z;
139146
ins++;
140147
}
148+
else
149+
{
150+
int unused= 0;
151+
lf_hash_iterate(&lf_hash, pins, do_sum, &unused);
152+
scans++;
153+
}
141154
}
142155
for (i= 0; i < N_TLH; i++)
143156
{
@@ -154,9 +167,9 @@ pthread_handler_t test_lf_hash(void *arg)
154167

155168
if (--N == 0)
156169
{
157-
diag("%d mallocs, %d pins in stack, %d hash size, %d inserts",
170+
diag("%d mallocs, %d pins in stack, %d hash size, %d inserts, %d scans",
158171
lf_hash.alloc.mallocs, lf_hash.alloc.pinbox.pins_in_array,
159-
lf_hash.size, inserts);
172+
lf_hash.size, inserts, scans);
160173
bad|= lf_hash.count;
161174
}
162175
if (!--running_threads) pthread_cond_signal(&cond);
@@ -181,12 +194,12 @@ void do_tests()
181194
with_my_thread_init= 1;
182195
test_concurrently("lf_pinbox (with my_thread_init)", test_lf_pinbox, N= THREADS, CYCLES);
183196
test_concurrently("lf_alloc (with my_thread_init)", test_lf_alloc, N= THREADS, CYCLES);
184-
test_concurrently("lf_hash (with my_thread_init)", test_lf_hash, N= THREADS, CYCLES/10);
197+
test_concurrently("lf_hash (with my_thread_init)", test_lf_hash, N= THREADS, CYCLES);
185198

186199
with_my_thread_init= 0;
187200
test_concurrently("lf_pinbox (without my_thread_init)", test_lf_pinbox, N= THREADS, CYCLES);
188201
test_concurrently("lf_alloc (without my_thread_init)", test_lf_alloc, N= THREADS, CYCLES);
189-
test_concurrently("lf_hash (without my_thread_init)", test_lf_hash, N= THREADS, CYCLES/10);
202+
test_concurrently("lf_hash (without my_thread_init)", test_lf_hash, N= THREADS, CYCLES);
190203

191204
lf_hash_destroy(&lf_hash);
192205
lf_alloc_destroy(&lf_allocator);

0 commit comments

Comments
 (0)