private EntitiesOfTypeIterator( @NotNull final EntitiesOfTypeRangeIterable iterable, @NotNull final Cursor index) { super(iterable); setCursor(index); final ByteIterable key = LongBinding.longToCompressedEntry(min); checkHasNext(getCursor().getSearchKeyRange(key) != null); }
@Override @Nullable public EntityId nextIdImpl() { if (hasNextImpl()) { explain(getType()); final Cursor cursor = getCursor(); final long localId = LongBinding.compressedEntryToLong(cursor.getKey()); final EntityId result = new PersistentEntityId(entityTypeId, localId); checkHasNext(cursor.getNext()); return result; } return null; }
@Override protected long countImpl(@NotNull final PersistentStoreTransaction txn) { final Cursor cursor = openCursor(txn); if (cursor == null) { return 0; } try { final ByteIterable key = LongBinding.longToCompressedEntry(min); long result = 0; boolean success = cursor.getSearchKeyRange(key) != null; while (success) { if (max > LongBinding.compressedEntryToLong(cursor.getKey())) { break; } result++; success = cursor.getNextNoDup(); } return result; } finally { cursor.close(); } }
public static int binarySearch( @NotNull final IByteIterableComparator comparator, final ByteIterable key, int low, int high, final int bytesPerLong, Log log, long startAddress) { final LogCache cache = log.cache; final int pageSize = log.getCachePageSize(); final int mask = pageSize - 1; // page size is always a power of 2 long leftAddress = -1L; byte[] leftPage = null; long rightAddress = -1L; byte[] rightPage = null; final BinarySearchIterator it = new BinarySearchIterator(pageSize); while (low <= high) { final int mid = (low + high + 1) >>> 1; final long midAddress = startAddress + (mid * bytesPerLong); it.offset = ((int) midAddress) & mask; it.address = midAddress - it.offset; boolean loaded = false; if (it.address == leftAddress) { it.page = leftPage; } else if (it.address == rightAddress) { it.page = rightPage; } else { it.page = cache.getPage(log, it.address).getBytesUnsafe(); loaded = true; } final int cmp; final long address; final byte[] page; if (pageSize - it.offset < bytesPerLong) { final long nextAddress = (address = it.address) + pageSize; if (rightAddress == nextAddress) { it.nextPage = rightPage; } else { it.nextPage = cache.getPage(log, nextAddress).getBytesUnsafe(); loaded = true; } page = it.page; cmp = comparator.compare(LongBinding.entryToUnsignedLong(it.asCompound(), bytesPerLong), key); } else { cmp = comparator.compare(LongBinding.entryToUnsignedLong(it, bytesPerLong), key); page = it.page; address = it.address; } if (cmp < 0) { // left < right low = mid + 1; if (loaded) { leftAddress = it.address; leftPage = it.page; } } else if (cmp > 0) { // left > right high = mid - 1; if (loaded) { rightAddress = address; rightPage = page; } } else { return mid; // key found } } return -(low + 1); // key not found. }
private void checkHasNext(final boolean success) { hasNext = success && max >= LongBinding.compressedEntryToLong(getCursor().getKey()); }
@Override public long nextLong(final int length) { final long result = LongBinding.entryToUnsignedLong(page, offset, length); offset += length; return result; }