DbStatus artNextKey(DbCursor *dbCursor, DbMap *map) { ArtCursor *cursor = (ArtCursor *)((char *)dbCursor + dbCursor->xtra); bool binaryFlds = map->arenaDef->params[IdxKeyFlds].boolVal; int slot, len; switch (dbCursor->state) { case CursorLeftEof: case CursorNone: artLeftKey(dbCursor, map); break; case CursorRightEof: return DB_CURSOR_eof; default: break; } while (cursor->depth < MAX_cursor) { CursorStack* stack = &cursor->stack[cursor->depth - 1]; dbCursor->keyLen = stack->off; cursor->lastFld = stack->lastFld; switch (stack->slot->type < SpanNode ? stack->slot->type : SpanNode) { case UnusedSlot: { break; } case FldEnd: { // this case only occurs with binaryFlds is true ARTFldEnd* fldEndNode = getObj(map, *stack->slot); // end this field and begin next one if (stack->ch < 0) { int fldLen = dbCursor->keyLen - cursor->lastFld - 2; cursor->key[cursor->lastFld] = fldLen >> 8; cursor->key[cursor->lastFld + 1] = fldLen; cursor->lastFld = dbCursor->keyLen; dbCursor->keyLen += 2; cursor->stack[cursor->depth].slot->bits = fldEndNode->nextFld->bits; cursor->stack[cursor->depth].addr = fldEndNode->nextFld; cursor->stack[cursor->depth].ch = -1; cursor->stack[cursor->depth].lastFld = cursor->lastFld; cursor->stack[cursor->depth++].off = dbCursor->keyLen; stack->ch = 0; continue; } // continue processing the current field bytes if (stack->ch > 255) break; cursor->stack[cursor->depth].slot->bits = fldEndNode->sameFld->bits; cursor->stack[cursor->depth].addr = fldEndNode->sameFld; cursor->stack[cursor->depth].off = dbCursor->keyLen; cursor->stack[cursor->depth].lastFld = cursor->lastFld; cursor->stack[cursor->depth++].ch = -1; stack->ch = 256; continue; } case KeyUniq: { if (stack->ch < 0) { ARTKeyUniq* keyUniqNode = getObj(map, *stack->slot); cursor->stack[cursor->depth].slot->bits = keyUniqNode->dups->bits; cursor->stack[cursor->depth].addr = keyUniqNode->dups; cursor->stack[cursor->depth].ch = -1; cursor->stack[cursor->depth].lastFld = cursor->lastFld; cursor->stack[cursor->depth++].off = dbCursor->keyLen; stack->ch = 0; continue; } if (stack->ch == 0) { ARTKeyUniq* keyUniqNode = getObj(map, *stack->slot); cursor->stack[cursor->depth].slot->bits = keyUniqNode->next->bits; cursor->stack[cursor->depth].addr = keyUniqNode->next; cursor->stack[cursor->depth].ch = -1; cursor->stack[cursor->depth].lastFld = cursor->lastFld; cursor->stack[cursor->depth++].off = dbCursor->keyLen; stack->ch = 256; continue; } break; } case KeyEnd: { if (stack->ch < 0) { if (binaryFlds) { int fldLen = dbCursor->keyLen - cursor->lastFld - 2; cursor->key[cursor->lastFld] = fldLen >> 8; cursor->key[cursor->lastFld + 1] = fldLen; cursor->lastFld = dbCursor->keyLen; } if (stack->slot->addr) { // was there a continuation? ARTKeyEnd* keyEndNode = getObj(map, *stack->slot); cursor->stack[cursor->depth].slot->bits = keyEndNode->next->bits; cursor->stack[cursor->depth].addr = keyEndNode->next; cursor->stack[cursor->depth].ch = -1; cursor->stack[cursor->depth].lastFld = cursor->lastFld; cursor->stack[cursor->depth++].off = dbCursor->keyLen; stack->ch = 0; continue; } dbCursor->state = CursorPosAt; stack->ch = 0; return DB_OK; } break; } case SpanNode: { ARTSpan* spanNode = getObj(map, *stack->slot); len = stack->slot->nbyte + 1; // continue into our next slot if (stack->ch < 0) { memcpy(cursor->key + dbCursor->keyLen, spanNode->bytes, len); dbCursor->keyLen += len; cursor->stack[cursor->depth].slot->bits = spanNode->next->bits; cursor->stack[cursor->depth].addr = spanNode->next; cursor->stack[cursor->depth].ch = -1; cursor->stack[cursor->depth].lastFld = cursor->lastFld; cursor->stack[cursor->depth++].off = dbCursor->keyLen; stack->ch = 0; continue; } break; } case Array4: { ARTNode4* radix4Node = getObj(map, *stack->slot); slot = slot4x14(stack->ch, 4, radix4Node->alloc, radix4Node->keys); if (slot >= 4) break; stack->ch = radix4Node->keys[slot]; cursor->key[dbCursor->keyLen++] = radix4Node->keys[slot]; cursor->stack[cursor->depth].slot->bits = radix4Node->radix[slot].bits; cursor->stack[cursor->depth].addr = &radix4Node->radix[slot]; cursor->stack[cursor->depth].off = dbCursor->keyLen; cursor->stack[cursor->depth].lastFld = cursor->lastFld; cursor->stack[cursor->depth++].ch = -1; continue; } case Array14: { ARTNode14* radix14Node = getObj(map, *stack->slot); slot = slot4x14(stack->ch, 14, radix14Node->alloc, radix14Node->keys); if (slot >= 14) break; stack->ch = radix14Node->keys[slot]; cursor->key[dbCursor->keyLen++] = radix14Node->keys[slot]; cursor->stack[cursor->depth].slot->bits = radix14Node->radix[slot].bits; cursor->stack[cursor->depth].addr = &radix14Node->radix[slot]; cursor->stack[cursor->depth].ch = -1; cursor->stack[cursor->depth].lastFld = cursor->lastFld; cursor->stack[cursor->depth++].off = dbCursor->keyLen; continue; } case Array64: { ARTNode64* radix64Node = getObj(map, *stack->slot); stack->ch = slot64(stack->ch, radix64Node->alloc, radix64Node->keys); if (stack->ch == 256) break; cursor->key[dbCursor->keyLen++] = (uint8_t)stack->ch; cursor->stack[cursor->depth].slot->bits = radix64Node->radix[radix64Node->keys[stack->ch]].bits; cursor->stack[cursor->depth].addr = &radix64Node->radix[radix64Node->keys[stack->ch]]; cursor->stack[cursor->depth].ch = -1; cursor->stack[cursor->depth].lastFld = cursor->lastFld; cursor->stack[cursor->depth++].off = dbCursor->keyLen; continue; } case Array256: { ARTNode256* radix256Node = getObj(map, *stack->slot); while (stack->ch < 256) { uint32_t idx = ++stack->ch; if (idx < 256 && radix256Node->radix[idx].type) break; } if (stack->ch == 256) break; cursor->key[dbCursor->keyLen++] = (uint8_t)stack->ch; cursor->stack[cursor->depth].slot->bits = radix256Node->radix[stack->ch].bits; cursor->stack[cursor->depth].addr = &radix256Node->radix[stack->ch]; cursor->stack[cursor->depth].ch = -1; cursor->stack[cursor->depth].lastFld = cursor->lastFld; cursor->stack[cursor->depth++].off = dbCursor->keyLen; continue; } } // end switch if (--cursor->depth) { stack = &cursor->stack[cursor->depth]; dbCursor->keyLen = stack->off; continue; } break; } // end while
DbAddr *artFindNxtFld( DbMap *index, ArtCursor *cursor, DbAddr *slot, uint8_t *key, uint32_t keylen) { uint32_t startSize = cursor->keySize; uint32_t startDepth = cursor->depth; uint32_t idx, offset = 0, spanMax; bool restart = true; bool pass = false; CursorStack* stack; DbAddr newSlot[1]; cursor->atLeftEOF = false; do { restart = false; cursor->keySize = startSize; cursor->depth = startDepth; // if we are waiting on a dead bit to clear if (pass) art_yield(); else pass = true; // loop through all the key bytes stack = cursor->stack + cursor->depth; while (offset < keylen) { if (slot->dead) { restart = true; break; } stack = &cursor->stack[cursor->depth++]; stack->slot->bits = slot->bits; stack->addr = slot; stack->off = cursor->keySize; stack->ch = -1; newSlot->bits = slot->bits; spanMax = SPANLEN(slot->type); switch (slot->type < SpanNode ? slot->type : SpanNode) { case FldEnd: case Suffix: { ARTEnd *endNode = getObj(index, *slot); slot = endNode->pass; stack->ch = 256; continue; } case KeyEnd: { break; } case SpanNode: { ARTSpan* spanNode = getObj(index, *slot); uint32_t amt = keylen - offset; int diff; spanMax += stack->slot->nbyte + 1; if (amt > spanMax) amt = spanMax; diff = memcmp(key + offset, spanNode->bytes, amt); // is span size > key size? if (spanMax > amt) { if (diff <= 0) stack->ch = -1; else stack->ch = 256; break; } // does key end in the middle of the span? // if so, is the key larger or smaller? if (diff) { stack->ch = diff < 0 ? -1 : 256; break; } // copy key bytes and continue to the next slot memcpy(cursor->key + cursor->keySize, spanNode->bytes, spanMax); cursor->keySize += spanMax; slot = spanNode->next; offset += spanMax; stack->ch = 0; continue; } case Array4: { ARTNode4 *node = getObj(index, *slot); // simple loop comparing bytes for (idx = 0; idx < 4; idx++) { if (node->alloc & (1 << idx)) if (key[offset] == node->keys[idx]) break; } if (idx < 4) { slot = node->radix + idx; // slot points to child node cursor->key[cursor->keySize++] = node->keys[idx]; stack->ch = node->keys[idx]; offset++; // update key byte offset continue; } // key byte not found idx = slot4x14(stack->ch, 4, node->alloc, node->keys); if (idx < 4) stack->ch = node->keys[idx]; else stack->ch = 256; break; } case Array14: { ARTNode14 *node = getObj(index, *slot); // simple loop comparing bytes for (idx = 0; idx < 14; idx++) { if (node->alloc & (1 << idx)) if (key[offset] == node->keys[idx]) break; } if (idx < 14) { slot = node->radix + idx; // slot points to child node cursor->key[cursor->keySize++] = node->keys[idx]; stack->ch = node->keys[idx]; offset++; // update key byte offset continue; } // key byte not found idx = slot4x14(stack->ch, 14, node->alloc, node->keys); if (idx < 14) stack->ch = node->keys[idx]; else stack->ch = 256; break; } case Array64: { ARTNode64* node = getObj(index, *slot); idx = node->keys[key[offset]]; if (idx < 0xff && (node->alloc & (1ULL << idx))) { slot = node->radix + idx; // slot points to child node cursor->key[cursor->keySize++] = key[offset]; stack->ch = key[offset]; offset++; // update key offset continue; } // key byte not found idx = slot64(stack->ch, node->alloc, node->keys); if (idx < 256) stack->ch = idx; else stack->ch = 256; break; } case Array256: { ARTNode256* node = getObj(index, *slot); idx = key[offset]; if (node->alloc[idx / 64] & (1ULL << (idx % 64))) { cursor->key[cursor->keySize++] = idx; slot = node->radix + idx; // slot points to child node stack->ch = idx; offset++; // update key byte offset continue; } // key byte not found while (stack->ch < 256) { idx = ++stack->ch; if (idx < 256 && node->alloc[idx / 64] & (1ULL << (idx % 64))) break; } break; } case UnusedSlot: { cursor->depth--; if (!cursor->depth) cursor->atRightEOF = true; break; } default: { // unreachable } } // end switch return slot; } // end while (offset < keylen) } while (restart); return slot; }