Skip to content

Conversation

sbordet
Copy link
Contributor

@sbordet sbordet commented Sep 29, 2025

No description provided.

Signed-off-by: Simone Bordet <[email protected]>
Implemented `Response.write(Response, boolean, Content.Source, Callback)`.

Signed-off-by: Simone Bordet <[email protected]>
Implemented `Sink.write(Response, boolean, Content.Source, Callback)`.
Now the API is just the `Sink.write()` above, and most of the rest is
hidden.

Updated IOResources to use the new method above, so normal file serving
should be able to leverage zero-copy.

Signed-off-by: Simone Bordet <[email protected]>
Signed-off-by: Simone Bordet <[email protected]>
Signed-off-by: Simone Bordet <[email protected]>
Copy link
Contributor

@gregw gregw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm hating this less

Comment on lines +211 to +216
interface Aware
{
Source getContentSource();

void setContentSource(Source source);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #13656 as an alternate way to tunnel a Source through a ByteBuffer only API.
Although I'm hating the current iteration of Aware less than I did originally

{
if (sink instanceof Content.Source.Aware aware)
return aware;
if (sink instanceof Wrapper wrapper)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if the sink is wrapped then we should not bypass it with transferTo
Perhaps we need an AwareWrapper, that would allow itself to be bypassed?

{
// Optimization to enable zero-copy.
aware.setContentSource(source);
sink.write(last, TRANSFER, callback);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel that we should allow some failures on the callback here to fall through to a normal copy. I.e. if something in the implementation is Aware but cannot do a transferTo (perhaps because it would be non optimal) then it can fail this write with a TransferToFailed exception, which would then just do the normal copy below.

Content.Source.Aware aware = findContentSourceAware(sink);
if (aware != null)
{
// Optimization to enable zero-copy.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Explain in the comment how the optimization still uses the sink.write path, so that commit logic etc. can be triggered. Specifically, we do not do aware.transfer(source, callback) because we might need to commit the response.

return;
}

// TODO: check that we don't have both a ByteBuffer and a Content.Source.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should also check content==TRANSFER, because if some sink wrapper inserted different content, then the presence of the source will need to be ignored

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: No status
Development

Successfully merging this pull request may close these issues.

Provide support for sending Content.Source via sendfile / FileChannel.transferTo
2 participants