MemorySegment view of data in an
IndexInput and passing it to a caller-supplied action. The
segment may come from a MemorySegmentAccessInput (mmap),
a direct ByteBuffer view (e.g. blob-cache), or a
heap copy as a last resort.
All resource management (ref-counting, buffer release) is handled internally — callers never see a closeable resource.
-
Method Summary
Modifier and TypeMethodDescriptionstatic booleancanUseSegmentSlices(org.apache.lucene.store.IndexInput input) ReturnstrueifMemorySegmentslices can be obtained from the specifiedIndexInput.static voidcheckInputType(org.apache.lucene.store.IndexInput in) Checks that aFilterIndexInputwrapper also implementsMemorySegmentAccessInputorDirectAccessInput, so that zero-copy access is preserved through the wrapper chain.static <R> RwithSlice(org.apache.lucene.store.IndexInput in, long length, IntFunction<byte[]> scratchSupplier, CheckedFunction<MemorySegment, R, IOException> action) Obtains a memory segment for the nextlengthbytes of the index input, passes it toaction, and returns the result.static booleanwithSliceAddresses(org.apache.lucene.store.IndexInput in, long[] offsets, int length, int count, IntFunction<MemorySegment> addressesBufferSupplier, CheckedConsumer<MemorySegment, IOException> action) Resolvescountfile ranges to native memory addresses and passes the address array to the action.
-
Method Details
-
canUseSegmentSlices
public static boolean canUseSegmentSlices(org.apache.lucene.store.IndexInput input) ReturnstrueifMemorySegmentslices can be obtained from the specifiedIndexInput. -
withSlice
public static <R> R withSlice(org.apache.lucene.store.IndexInput in, long length, IntFunction<byte[]> scratchSupplier, CheckedFunction<MemorySegment, R, throws IOExceptionIOException> action) Obtains a memory segment for the nextlengthbytes of the index input, passes it toaction, and returns the result. The position of the index input is advanced bylength.This method first tries to obtain a slice via
MemorySegmentAccessInput.segmentSliceOrNull(long, long). If that returnsnull, it tries a directByteBufferview viaDirectAccessInput. As a last resort it copies the data onto the heap using a byte array obtained fromscratchSupplier.The memory segment passed to
actionis valid only for the duration of the call. Callers must not retain references to it.- Parameters:
in- the index input positioned at the data to readlength- the number of bytes to readscratchSupplier- supplies a byte array of at least the requested length, used only on the heap-copy fallback pathaction- the function to apply to the memory segment- Returns:
- the result of applying
action - Throws:
IOException
-
withSliceAddresses
public static boolean withSliceAddresses(org.apache.lucene.store.IndexInput in, long[] offsets, int length, int count, IntFunction<MemorySegment> addressesBufferSupplier, CheckedConsumer<MemorySegment, IOException> action) throws IOExceptionResolvescountfile ranges to native memory addresses and passes the address array to the action. TriesMemorySegmentAccessInputfirst (contiguous segment, pointer arithmetic), thenDirectAccessInput(withByteBufferSlices). Returnsfalsewithout invoking the action if neither path is available - there is no heap fallback since native addresses are required.Memory safety: The addresses in the
addrsarray are raw native pointers extracted viaMemorySegment.address(). The native code that consumes them (e.g. a bulk-gather FFI downcall) will dereference these pointers directly - there is no scope or bounds check at that point. The backing memory must therefore remain valid for the entire duration of theaction.With the current callers, the backing memory is independently kept alive: on the MSAI path, the arena is owned by the
IndexInputwhich the caller holds as a field; on the DAI path, cache regions are ref-counted byDirectAccessInput.withByteBufferSlices(long[], int, int, org.elasticsearch.core.CheckedConsumer<java.nio.ByteBuffer[], java.io.IOException>)for the duration of the callback. However, that safety relies on implementation details ofMMapDirectoryandSharedBlobCacheService. The JIT is also permitted to discard local references after their last use (JLS 12.6.1), which could in theory allow the segment or buffer objects to be collected while the native call is in flight. TheReference.reachabilityFence(java.lang.Object)calls below are therefore added as low-cost defensive insurance: they make the lifetime contract explicit and protect against future changes to either the callers or the backing-memory implementations.- Parameters:
in- the index inputoffsets- file byte offsets for each range (caller-owned, not modified)length- byte length of each range (same for all)count- number of ranges to resolveaddressesBufferSupplier- called withcount; must return a writableMemorySegmentwith room for at leastcountpointer-width entries. The segment may be larger and may be reused across calls; only entries[0, count)are written by this method.action- invoked with the same segment returned by the supplier; only the firstcountaddress slots contain valid data, and those addresses are valid only for the duration of the call.- Returns:
trueif addresses were resolved and the action was invoked- Throws:
IOException
-
checkInputType
public static void checkInputType(org.apache.lucene.store.IndexInput in) Checks that aFilterIndexInputwrapper also implementsMemorySegmentAccessInputorDirectAccessInput, so that zero-copy access is preserved through the wrapper chain.
-