private void getRowKeyAtOrBefore(final SortedMap<HStoreKey, byte []> map,
final byte [] row, final SortedMap<HStoreKey, Long> candidateKeys,
final Set<HStoreKey> deletes) {
// We want the earliest possible to start searching from. Start before
// the candidate key in case it turns out a delete came in later.
HStoreKey search_key = candidateKeys.isEmpty()?
new HStoreKey(row, this.regionInfo):
new HStoreKey(candidateKeys.firstKey().getRow(), this.regionInfo);
List<HStoreKey> victims = new ArrayList<HStoreKey>();
long now = System.currentTimeMillis();
// Get all the entries that come equal or after our search key
SortedMap<HStoreKey, byte []> tailMap = map.tailMap(search_key);
// if there are items in the tail map, there's either a direct match to
// the search key, or a range of values between the first candidate key
// and the ultimate search key (or the end of the cache)
if (!tailMap.isEmpty() &&
HStoreKey.compareTwoRowKeys(this.regionInfo,
tailMap.firstKey().getRow(), search_key.getRow()) <= 0) {
Iterator<HStoreKey> key_iterator = tailMap.keySet().iterator();
// Keep looking at cells as long as they are no greater than the
// ultimate search key and there's still records left in the map.
HStoreKey deletedOrExpiredRow = null;
for (HStoreKey found_key = null; key_iterator.hasNext() &&
(found_key == null ||
HStoreKey.compareTwoRowKeys(this.regionInfo,
found_key.getRow(), row) <= 0);) {
found_key = key_iterator.next();
if (HStoreKey.compareTwoRowKeys(this.regionInfo,
found_key.getRow(), row) <= 0) {
if (HLogEdit.isDeleted(tailMap.get(found_key))) {
HStore.handleDeleted(found_key, candidateKeys, deletes);
if (deletedOrExpiredRow == null) {
deletedOrExpiredRow = found_key;
}
} else {
if (HStore.notExpiredAndNotInDeletes(this.ttl,
found_key, now, deletes)) {
candidateKeys.put(stripTimestamp(found_key),
new Long(found_key.getTimestamp()));
} else {
if (deletedOrExpiredRow == null) {
deletedOrExpiredRow = new HStoreKey(found_key);
}
addVictim(victims, found_key);
}
}
}