示例#1
0
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;
}