Skip to content

Commit

Permalink
#12681 atomically retain the buffer with a check that it still is in …
Browse files Browse the repository at this point in the history
…the cache, otherwise delegate to the wrapped content

Signed-off-by: Ludovic Orban <[email protected]>
  • Loading branch information
lorban committed Jan 13, 2025
1 parent 14d7a68 commit 35d58fc
Showing 1 changed file with 24 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -354,19 +354,39 @@ public String getKey()
@Override
public void writeTo(Content.Sink sink, long offset, long length, Callback callback)
{
boolean retained = false;
try
{
_buffer.retain();
sink.write(true, BufferUtil.slice(_buffer.getByteBuffer(), (int)offset, (int)length), Callback.from(_buffer::release, callback));
retained = retain();
if (retained)
sink.write(true, BufferUtil.slice(_buffer.getByteBuffer(), Math.toIntExact(offset), Math.toIntExact(length)), Callback.from(this::release, callback));
else
getWrapped().writeTo(sink, offset, length, callback);
}
catch (Throwable x)
{
// BufferUtil.slice() may fail if offset and/or length are out of bounds.
_buffer.release();
// BufferUtil.slice() may fail if offset and/or length are out of bounds,
// Math.toIntExact may fail too if offset or length are > Integer.MAX_VALUE.
if (retained)
release();
callback.failed(x);
}
}

/**
* Atomically checks that this content still is in cache (so it hasn't been released yet and is still usable) and retain
* its internal buffer if it is.
* @return true if this content can be used and has been retained, false otherwise.
*/
private boolean retain()
{
return _cache.computeIfPresent(_cacheKey, (s, cachingHttpContent) ->
{
_buffer.retain();
return cachingHttpContent;
}) != null;
}

@Override
public void release()
{
Expand Down

0 comments on commit 35d58fc

Please sign in to comment.