MCPcopy Create free account
hub / github.com/apple/foundationdb / findKey

Function findKey

fdbserver/StorageCache.actor.cpp:626–702  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

624}
625
626Key findKey(StorageCacheData* data, KeySelectorRef sel, Version version, KeyRange range, int* pOffset)
627// Attempts to find the key indicated by sel in the data at version, within range.
628// Precondition: selectorInRange(sel, range)
629// If it is found, offset is set to 0 and a key is returned which falls inside range.
630// If the search would depend on any key outside range OR if the key selector offset is too large (range read returns
631// too many bytes), it returns either
632// a negative offset and a key in [range.begin, sel.getKey()], indicating the key is (the first key <= returned key) +
633// offset, or a positive offset and a key in (sel.getKey(), range.end], indicating the key is (the first key >=
634// returned key) + offset-1
635// The range passed in to this function should specify a cacheRange. If range.begin is repeatedly not the beginning of
636// a cacheRange, then it is possible to get stuck looping here
637{
638 ASSERT(version != latestVersion);
639 ASSERT(selectorInRange(sel, range) && version >= data->oldestVersion.get());
640
641 // Count forward or backward distance items, skipping the first one if it == key and skipEqualKey
642 bool forward = sel.offset > 0; // If forward, result >= sel.getKey(); else result <= sel.getKey()
643 int sign = forward ? +1 : -1;
644 bool skipEqualKey = sel.orEqual == forward;
645 int distance = forward ? sel.offset : 1 - sel.offset;
646
647 // Don't limit the number of bytes if this is a trivial key selector (there will be at most two items returned from
648 // the read range in this case)
649 int maxBytes;
650 if (sel.offset <= 1 && sel.offset >= 0)
651 maxBytes = std::numeric_limits<int>::max();
652 else
653 maxBytes = BUGGIFY ? SERVER_KNOBS->BUGGIFY_LIMIT_BYTES : SERVER_KNOBS->STORAGE_LIMIT_BYTES;
654
655 GetKeyValuesReply rep =
656 readRange(data,
657 version,
658 forward ? KeyRangeRef(sel.getKey(), range.end) : KeyRangeRef(range.begin, keyAfter(sel.getKey())),
659 (distance + skipEqualKey) * sign,
660 &maxBytes);
661 bool more = rep.more && rep.data.size() != distance + skipEqualKey;
662
663 // If we get only one result in the reverse direction as a result of the data being too large, we could get stuck in
664 // a loop
665 if (more && !forward && rep.data.size() == 1) {
666 CODE_PROBE(true, "Reverse key selector returned only one result in range read");
667 maxBytes = std::numeric_limits<int>::max();
668 GetKeyValuesReply rep2 =
669 readRange(data, version, KeyRangeRef(range.begin, keyAfter(sel.getKey())), -2, &maxBytes);
670 rep = rep2;
671 more = rep.more && rep.data.size() != distance + skipEqualKey;
672 ASSERT(rep.data.size() == 2 || !more);
673 }
674
675 int index = distance - 1;
676 if (skipEqualKey && rep.data.size() && rep.data[0].key == sel.getKey())
677 ++index;
678
679 if (index < rep.data.size()) {
680 *pOffset = 0;
681 return rep.data[index].key;
682 } else {
683 // FIXME: If range.begin=="" && !forward, return success?

Callers 6

Future<Void> getKeyFunction · 0.85
Future<Void> getKeyQFunction · 0.85

Calls 8

selectorInRangeFunction · 0.85
readRangeFunction · 0.85
getMethod · 0.65
getKeyMethod · 0.65
KeyRangeRefClass · 0.50
keyAfterFunction · 0.50
sizeMethod · 0.45
backMethod · 0.45

Tested by

no test coverage detected