1010import org .apache .logging .log4j .LogManager ;
1111import org .apache .logging .log4j .Logger ;
1212import org .apache .lucene .store .IOContext ;
13- import org .elasticsearch .blobcache .BlobCacheUtils ;
13+ import org .elasticsearch .blobcache .common . ByteBufferReference ;
1414import org .elasticsearch .blobcache .common .ByteRange ;
1515import org .elasticsearch .blobcache .shared .SharedBlobCacheService ;
1616import org .elasticsearch .blobcache .shared .SharedBytes ;
2121import org .elasticsearch .xpack .searchablesnapshots .store .IndexInputStats ;
2222import org .elasticsearch .xpack .searchablesnapshots .store .SearchableSnapshotDirectory ;
2323
24- import java .io .IOException ;
2524import java .io .InputStream ;
2625import java .nio .ByteBuffer ;
27- import java .util .concurrent .Semaphore ;
2826
2927public class FrozenIndexInput extends MetadataCachingIndexInput {
3028
@@ -104,13 +102,10 @@ protected long getDefaultRangeSize() {
104102 protected void readWithoutBlobCache (ByteBuffer b ) throws Exception {
105103 final long position = getAbsolutePosition ();
106104 final int length = b .remaining ();
107- final int originalByteBufPosition = b .position ();
108-
109105 // Semaphore that, when all permits are acquired, ensures that async callbacks (such as those used by readCacheFile) are not
110106 // accessing the byte buffer anymore that was passed to readWithoutBlobCache
111107 // In particular, it's important to acquire all permits before adapting the ByteBuffer's offset
112- final Semaphore luceneByteBufPermits = new Semaphore (Integer .MAX_VALUE );
113- boolean bufferWriteLocked = false ;
108+ final ByteBufferReference byteBufferReference = new ByteBufferReference (b );
114109 logger .trace ("readInternal: read [{}-{}] from [{}]" , position , position + length , this );
115110 try {
116111 final ByteRange startRangeToWrite = computeRange (position );
@@ -122,99 +117,50 @@ protected void readWithoutBlobCache(ByteBuffer b) throws Exception {
122117 : "[" + position + "-" + (position + length ) + "] vs " + rangeToWrite ;
123118 final ByteRange rangeToRead = ByteRange .of (position , position + length );
124119
125- final int bytesRead = cacheFile .populateAndRead (
126- rangeToWrite ,
127- rangeToRead ,
128- ( channel , pos , relativePos , len ) -> readCacheFile (
129- channel ,
120+ final int bytesRead = cacheFile .populateAndRead (rangeToWrite , rangeToRead , ( channel , pos , relativePos , len ) -> {
121+ logger . trace (
122+ "{}: reading logical {} channel {} pos {} length {} (details: {})" ,
123+ fileInfo . physicalName (),
124+ rangeToRead . start () ,
130125 pos ,
131126 relativePos ,
132- len ,
133- b ,
134- rangeToRead .start (),
135- luceneByteBufPermits
136- ),
137- (channel , channelPos , relativePos , len , progressUpdater ) -> {
138- final long startTimeNanos = stats .currentTimeNanos ();
139- try (InputStream input = openInputStreamFromBlobStore (rangeToWrite .start () + relativePos , len )) {
140- assert ThreadPool .assertCurrentThreadPool (SearchableSnapshots .CACHE_FETCH_ASYNC_THREAD_POOL_NAME );
141- logger .trace (
142- "{}: writing channel {} pos {} length {} (details: {})" ,
143- fileInfo .physicalName (),
144- channelPos ,
145- relativePos ,
146- len ,
147- cacheFile
148- );
149- SharedBytes .copyToCacheFileAligned (
150- channel ,
151- input ,
152- channelPos ,
153- relativePos ,
154- len ,
155- progressUpdater ,
156- writeBuffer .get ().clear (),
157- cacheFile
158- );
159- final long endTimeNanos = stats .currentTimeNanos ();
160- stats .addCachedBytesWritten (len , endTimeNanos - startTimeNanos );
161- }
162- },
163- SearchableSnapshots .CACHE_FETCH_ASYNC_THREAD_POOL_NAME
164- );
127+ length ,
128+ cacheFile
129+ );
130+ final int read = SharedBytes .readCacheFile (channel , pos , relativePos , len , byteBufferReference , cacheFile );
131+ stats .addCachedBytesRead (read );
132+ return read ;
133+ }, (channel , channelPos , relativePos , len , progressUpdater ) -> {
134+ final long startTimeNanos = stats .currentTimeNanos ();
135+ try (InputStream input = openInputStreamFromBlobStore (rangeToWrite .start () + relativePos , len )) {
136+ assert ThreadPool .assertCurrentThreadPool (SearchableSnapshots .CACHE_FETCH_ASYNC_THREAD_POOL_NAME );
137+ logger .trace (
138+ "{}: writing channel {} pos {} length {} (details: {})" ,
139+ fileInfo .physicalName (),
140+ channelPos ,
141+ relativePos ,
142+ len ,
143+ cacheFile
144+ );
145+ SharedBytes .copyToCacheFileAligned (
146+ channel ,
147+ input ,
148+ channelPos ,
149+ relativePos ,
150+ len ,
151+ progressUpdater ,
152+ writeBuffer .get ().clear (),
153+ cacheFile
154+ );
155+ final long endTimeNanos = stats .currentTimeNanos ();
156+ stats .addCachedBytesWritten (len , endTimeNanos - startTimeNanos );
157+ }
158+ }, SearchableSnapshots .CACHE_FETCH_ASYNC_THREAD_POOL_NAME );
165159 assert bytesRead == length : bytesRead + " vs " + length ;
166- assert luceneByteBufPermits .availablePermits () == Integer .MAX_VALUE ;
167-
168- luceneByteBufPermits .acquire (Integer .MAX_VALUE );
169- bufferWriteLocked = true ;
170- b .position (originalByteBufPosition + bytesRead ); // mark all bytes as accounted for
160+ byteBufferReference .finish (bytesRead );
171161 } finally {
172- if (bufferWriteLocked == false ) {
173- luceneByteBufPermits .acquire (Integer .MAX_VALUE );
174- }
175- }
176- }
177-
178- private int readCacheFile (
179- final SharedBytes .IO fc ,
180- long channelPos ,
181- long relativePos ,
182- long length ,
183- final ByteBuffer buffer ,
184- long logicalPos ,
185- Semaphore luceneByteBufPermits
186- ) throws IOException {
187- logger .trace (
188- "{}: reading cached {} logical {} channel {} pos {} length {} (details: {})" ,
189- fileInfo .physicalName (),
190- false ,
191- logicalPos ,
192- channelPos ,
193- relativePos ,
194- length ,
195- cacheFile
196- );
197- if (length == 0L ) {
198- return 0 ;
199- }
200- final int bytesRead ;
201- if (luceneByteBufPermits .tryAcquire ()) {
202- try {
203- // create slice that is positioned to read the given values
204- final ByteBuffer dup = buffer .slice (buffer .position () + Math .toIntExact (relativePos ), Math .toIntExact (length ));
205- bytesRead = fc .read (dup , channelPos );
206- if (bytesRead == -1 ) {
207- BlobCacheUtils .throwEOF (channelPos , dup .remaining (), this .cacheFile );
208- }
209- } finally {
210- luceneByteBufPermits .release ();
211- }
212- } else {
213- // return fake response
214- return Math .toIntExact (length );
162+ byteBufferReference .finish (0 );
215163 }
216- stats .addCachedBytesRead (bytesRead );
217- return bytesRead ;
218164 }
219165
220166 @ Override
0 commit comments