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*/
7387static 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+
8199retry :
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+
465524static const uchar * dummy_key = (uchar * )"" ;
466525
467526/*
0 commit comments