@Override public GetResult get(byte[] key) throws IOException { ensureNotClosed(); Preconditions.checkArgument(key != null && key.length > 0, "Key is empty"); Preconditions.checkArgument(this.getAppendedSize() >= 1, "the map table is empty"); GetResult result = new GetResult(); // leverage bloom filter for guarded condition if (!this.bloomFilter.mightContain(key)) return result; IMapEntry mapEntry = this.binarySearch(key); if (mapEntry == null) return result; else { if (mapEntry.isCompressed()) { result.setValue(Snappy.uncompress(mapEntry.getValue())); } else { result.setValue(mapEntry.getValue()); } if (mapEntry.isDeleted()) { result.setDeleted(true); return result; } if (mapEntry.isExpired()) { result.setExpired(true); return result; } // hint for locality result.setLevel(this.getLevel()); result.setTimeToLive(mapEntry.getTimeToLive()); result.setCreatedTime(mapEntry.getCreatedTime()); return result; } }
// Search the key in the hashcode sorted array private IMapEntry binarySearch(byte[] key) throws IOException { int hashCode = Arrays.hashCode(key); int lo = 0; int slo = lo; int hi = this.getAppendedSize() - 1; int shi = hi; while (lo <= hi) { int mid = lo + (hi - lo) / 2; IMapEntry mapEntry = this.getMapEntry(mid); int midHashCode = mapEntry.getKeyHash(); if (hashCode < midHashCode) hi = mid - 1; else if (hashCode > midHashCode) lo = mid + 1; else { if (BytesUtil.compare(key, mapEntry.getKey()) == 0) { return mapEntry; } // find left int index = mid - 1; while (index >= slo) { mapEntry = this.getMapEntry(index); if (hashCode != mapEntry.getKeyHash()) break; if (BytesUtil.compare(key, mapEntry.getKey()) == 0) { return mapEntry; } index--; } // find right index = mid + 1; while (index <= shi) { mapEntry = this.getMapEntry(index); if (hashCode != mapEntry.getKeyHash()) break; if (BytesUtil.compare(key, mapEntry.getKey()) == 0) { return mapEntry; } index++; } return null; } } return null; }