int my_sortcmp(const char *s, const char *t, uint len) { #ifdef USE_STRCOLL if (use_strcoll(default_charset_info)) return my_strnncoll(default_charset_info, (uchar *)s, len, (uchar *)t, len); else #endif { while (len--) { if (my_sort_order[(uchar) *s++] != my_sort_order[(uchar) *t++]) return ((int) my_sort_order[(uchar) s[-1]] - (int) my_sort_order[(uchar) t[-1]]); } return 0; } }
/* DESCRIPTION Search for hashnr/key/keylen in the list starting from 'head' and position the cursor. The list is ORDER BY hashnr, key RETURN 0 - not found 1 - found NOTE cursor is positioned in either case pins[0..2] are used, they are NOT removed on return */ static int lfind(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr, const uchar *key, uint keylen, CURSOR *cursor, LF_PINS *pins) { uint32 cur_hashnr; const uchar *cur_key; uint cur_keylen; intptr link; retry: cursor->prev= (intptr *)head; do { /* PTR() isn't necessary below, head is a dummy node */ cursor->curr= (LF_SLIST *)(*cursor->prev); _lf_pin(pins, 1, cursor->curr); } while (*cursor->prev != (intptr)cursor->curr && LF_BACKOFF); for (;;) { if (unlikely(!cursor->curr)) return 0; /* end of the list */ do { /* QQ: XXX or goto retry ? */ link= cursor->curr->link; cursor->next= PTR(link); _lf_pin(pins, 0, cursor->next); } while (link != cursor->curr->link && LF_BACKOFF); cur_hashnr= cursor->curr->hashnr; cur_key= cursor->curr->key; cur_keylen= cursor->curr->keylen; if (*cursor->prev != (intptr)cursor->curr) { (void)LF_BACKOFF; goto retry; } if (!DELETED(link)) { if (cur_hashnr >= hashnr) { int r= 1; if (cur_hashnr > hashnr || (r= my_strnncoll(cs, (uchar*) cur_key, cur_keylen, (uchar*) key, keylen)) >= 0) return !r; } cursor->prev= &(cursor->curr->link); _lf_pin(pins, 2, cursor->curr); } else { /* we found a deleted node - be nice, help the other thread and remove this deleted node */ if (my_atomic_casptr((void **) cursor->prev, (void **)(char*) &cursor->curr, cursor->next)) _lf_alloc_free(pins, cursor->curr); else { (void)LF_BACKOFF; goto retry; } } cursor->curr= cursor->next; _lf_pin(pins, 1, cursor->curr); } }
/** walk the list, searching for an element or invoking a callback Search for hashnr/key/keylen in the list starting from 'head' and position the cursor. The list is ORDER BY hashnr, key @param head start walking the list from this node @param cs charset for comparing keys, NULL if callback is used @param hashnr hash number to search for @param key key to search for OR data for the callback @param keylen length of the key to compare, 0 if callback is used @param cursor for returning the found element @param pins see lf_alloc-pin.c @param callback callback action, invoked for every element @note cursor is positioned in either case pins[0..2] are used, they are NOT removed on return callback might see some elements twice (because of retries) @return if find: 0 - not found 1 - found if callback: 0 - ok 1 - error (callbck returned 1) */ static int l_find(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr, const uchar *key, uint keylen, CURSOR *cursor, LF_PINS *pins, my_hash_walk_action callback) { uint32 cur_hashnr; const uchar *cur_key; uint cur_keylen; intptr link; DBUG_ASSERT(!cs || !callback); /* should not be set both */ DBUG_ASSERT(!keylen || !callback); /* should not be set both */ retry: cursor->prev= (intptr *)head; do { /* PTR() isn't necessary below, head is a dummy node */ cursor->curr= (LF_SLIST *)(*cursor->prev); lf_pin(pins, 1, cursor->curr); } while (*cursor->prev != (intptr)cursor->curr && LF_BACKOFF); for (;;) { if (unlikely(!cursor->curr)) return 0; /* end of the list */ cur_hashnr= cursor->curr->hashnr; cur_keylen= cursor->curr->keylen; cur_key= cursor->curr->key; do { link= cursor->curr->link; cursor->next= PTR(link); lf_pin(pins, 0, cursor->next); } while (link != cursor->curr->link && LF_BACKOFF); if (!DELETED(link)) { if (unlikely(callback)) { if (cur_hashnr & 1 && callback(cursor->curr + 1, (void*)key)) return 1; } else if (cur_hashnr >= hashnr) { int r= 1; if (cur_hashnr > hashnr || (r= my_strnncoll(cs, cur_key, cur_keylen, key, keylen)) >= 0) return !r; } cursor->prev= &(cursor->curr->link); if (!(cur_hashnr & 1)) /* dummy node */ head= (LF_SLIST **)cursor->prev; lf_pin(pins, 2, cursor->curr); } else { /* we found a deleted node - be nice, help the other thread and remove this deleted node */ if (my_atomic_casptr((void **) cursor->prev, (void **) &cursor->curr, cursor->next) && LF_BACKOFF) lf_alloc_free(pins, cursor->curr); else goto retry; } cursor->curr= cursor->next; lf_pin(pins, 1, cursor->curr); } }