[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openjdk-nio-dev
Subject:    =?utf-8?B?562U5aSNOiDnrZTlpI06IChmYykgRmlsZUNoYW5uZWwudHJhbnNmZXJGcm9t?= =?utf-8?B?L3RyYW5zZmVyRnJvb
From:       "lihuaming (A)" <lihuaming3 () huawei ! com>
Date:       2021-01-30 7:52:59
Message-ID: FF52E71F75D5A341BDD9AB1622091FA501211B9E () DGGEML523-MBX ! china ! huawei ! com
[Download RAW message or body]

[Attachment #2 (text/plain)]

Hi Alan,

Please check my comments below, I mark them with starting ###. (sorry to use the \
Outlook again, some emails were lost in thunderbird, don't know why.)

发件人: Alan Bateman [mailto:Alan.Bateman@oracle.com]
发送时间: 2021年1月30日 1:07
收件人: lihuaming (A) <lihuaming3@huawei.com>; nio-dev@openjdk.java.net
主题: Re: 答复: (fc) FileChannel.transferFrom/transferFromArbitraryChannel to \
return -1 at some error condition

On 29/01/2021 12:51, lihuaming (A) wrote:

Here is a simple demo, I don't use FileChannel.transferFrom directly, but I hope I \
can clarify the situation. When ServerHangHttp and Client are up for a while (please \
check the bottom), no matter Server close the socket explicitly or kill by "kill -9 \
xxx", the client side will print out "[client] read : -1" continuously. so, if we are \
using FileChannel.transferFrom which will call transferFromArbitraryChannel which \
will call ReadableByteChannel.read, ReadableByteChannel.read will return -1, but \
transferFromArbitraryChannel will return 0, so as FileChannel.transferFrom. Based on \
this return value, following while loop will be a infinite loop, and user don't want \
to call something like "call sth like srcSocketChannel.read(...)", please check the \
reason in comments below. while (srcSocketChannel.isOpen()) {
  long l = fileChannel.transferFrom(srcSocketChannel,...);
  // user could call sth like srcSocketChannel.read(...), and expect it return -1, \
and break the loop, but it will be unacceptable for some program, where they would \
like to very quick copy, so called "zero" copy through fileChannel.transferFrom, and \
they don't want to add an extra check like "srcSocketChannel.read(...)"  if (l == -1) \
{ // break out the while loop } }
At this situation, I think it's more friendly to have fileChannel.transferFrom \
returns -1. The Client in the reproducer has a bug in that it will call read with 0 \
remaining bytes once it has read 100 bytes in total. So I would expect it will \
eventually spin reading 0 rather than -1.

### Sorry, please ignore this bug, I do kill the server manually shortly after it's \
connected with client.

If the server does terminate and close the connection gracefully then the client will \
spin reading -1 but only if reads -1/EOF before 1000 bytes are read.

### Yes, as I kill the server manually, so client read will return -1.

For transferFrom reading from an arbitrary channel then it may read bytes before EOF, \
in which case it will write those bytes to the file and return the number of bytes \
written/transferred. If called again then it will read again and just 0 because there \
are no bytes transferred. I don't see how we can could change this API without \
breaking existing usages that keeping a running code.

### if the arbitrary channel was just closed by peer side, transferFrom will return 0 \
this time or next time, and there is no way for it knows that the underlying socket \
was closed, unless it calls channel.read. But for performance consideration, I think \
some framework/program would like to call FileChannel,transferFrom(channel, …) \
only, rather than followed by a read+write just in case of channel is closed by peer \
side; read+write can be optimized by only do it if transferFrom(channel, …) returns \
0, but it still has some extra cost, and code is not simple and straight. ### I don't \
think this is jdk bug and I do have concern about the compatibility too and explained \
to framework/program developers, but I can also understand their points, so want to \
see if there are some way to make it more friendly to framework/program developers in \
this situation. Hope I have made it clear ☺. If there is no other better solutions, \
I will let them know that it's better to modify their code.

Thanks Alan for discussion.

Hamlin



-Alan


[Attachment #3 (text/html)]

<html xmlns:v="urn:schemas-microsoft-com:vml" \
xmlns:o="urn:schemas-microsoft-com:office:office" \
xmlns:w="urn:schemas-microsoft-com:office:word" \
xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" \
xmlns="http://www.w3.org/TR/REC-html40"> <head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
	{font-family:Wingdings;
	panose-1:5 0 0 0 0 0 0 0 0 0;}
@font-face
	{font-family:宋体;
	panose-1:2 1 6 0 3 1 1 1 1 1;}
@font-face
	{font-family:宋体;
	panose-1:2 1 6 0 3 1 1 1 1 1;}
@font-face
	{font-family:Calibri;
	panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
	{font-family:"\@宋体";
	panose-1:2 1 6 0 3 1 1 1 1 1;}
@font-face
	{font-family:微软雅黑;
	panose-1:2 11 5 3 2 2 4 2 2 4;}
@font-face
	{font-family:"\@微软雅黑";
	panose-1:2 11 5 3 2 2 4 2 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
	{margin:0cm;
	margin-bottom:.0001pt;
	text-align:justify;
	text-justify:inter-ideograph;
	font-size:10.5pt;
	font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
	{mso-style-priority:99;
	color:#0563C1;
	text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
	{mso-style-priority:99;
	color:#954F72;
	text-decoration:underline;}
p
	{mso-style-priority:99;
	mso-margin-top-alt:auto;
	margin-right:0cm;
	mso-margin-bottom-alt:auto;
	margin-left:0cm;
	font-size:12.0pt;
	font-family:宋体;}
pre
	{mso-style-priority:99;
	mso-style-link:"HTML 预设 式 Char";
	margin:0cm;
	margin-bottom:.0001pt;
	font-size:12.0pt;
	font-family:宋体;}
span.HTMLChar
	{mso-style-name:"HTML 预设 式 Char";
	mso-style-priority:99;
	mso-style-link:"HTML 预设 式";
	font-family:宋体;}
span.EmailStyle20
	{mso-style-type:personal;
	font-family:"Calibri",sans-serif;
	color:windowtext;}
span.EmailStyle21
	{mso-style-type:personal;
	font-family:"Calibri",sans-serif;
	color:#1F497D;}
span.EmailStyle22
	{mso-style-type:personal-reply;
	font-family:"Calibri",sans-serif;
	color:#1F497D;}
.MsoChpDefault
	{mso-style-type:export-only;
	font-size:10.0pt;}
@page WordSection1
	{size:612.0pt 792.0pt;
	margin:72.0pt 90.0pt 72.0pt 90.0pt;}
div.WordSection1
	{page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="ZH-CN" link="#0563C1" vlink="#954F72">
<div class="WordSection1">
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">Hi \
Alan,<o:p></o:p></span></p> <p class="MsoNormal"><span lang="EN-US" \
style="color:#1F497D"><o:p>&nbsp;</o:p></span></p> <p class="MsoNormal"><span \
lang="EN-US" style="color:#1F497D">Please check my comments below, I mark them with \
starting ###. (sorry to use the Outlook again, some emails were lost in thunderbird, \
don't know why.)<o:p></o:p></span></p> <p class="MsoNormal"><span lang="EN-US" \
style="color:#1F497D"><o:p>&nbsp;</o:p></span></p> <div>
<div style="border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0cm 0cm 0cm">
<p class="MsoNormal" align="left" style="text-align:left"><b><span \
style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">发件人<span \
lang="EN-US">:</span></span></b><span lang="EN-US" \
style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif"> Alan \
Bateman [mailto:Alan.Bateman@oracle.com] <br>
</span><b><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">发送时间<span \
lang="EN-US">:</span></span></b><span lang="EN-US" \
style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif"> \
2021</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">年<span \
lang="EN-US">1</span>月<span lang="EN-US">30</span>日<span lang="EN-US">  1:07<br>
</span><b>收件人<span lang="EN-US">:</span></b><span lang="EN-US"> lihuaming (A) \
&lt;lihuaming3@huawei.com&gt;; nio-dev@openjdk.java.net<br> </span><b>主题<span \
lang="EN-US">:</span></b><span lang="EN-US"> Re: </span>答复<span lang="EN-US">: \
(fc) FileChannel.transferFrom/transferFromArbitraryChannel to return -1 at some error \
condition<o:p></o:p></span></span></p> </div>
</div>
<p class="MsoNormal" align="left" style="text-align:left"><span \
lang="EN-US"><o:p>&nbsp;</o:p></span></p> <p class="MsoNormal" align="left" \
style="text-align:left"><span lang="EN-US">On 29/01/2021 12:51, lihuaming (A) \
wrote:<br> <br>
</span><span lang="EN-US" style="font-size:12.0pt"><o:p></o:p></span></p>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<p class="MsoNormal" align="left" \
style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;text-align:left"> <span \
lang="EN-US" style="font-size:12.0pt;font-family:宋体">Here is a simple demo, I \
don't use FileChannel.transferFrom directly, but I hope I can clarify the \
situation.</span><span lang="EN-US"><o:p></o:p></span></p> <p class="MsoNormal" \
align="left" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;text-align:left">
 <span lang="EN-US" style="font-size:12.0pt;font-family:宋体">When ServerHangHttp \
and Client are up for a while (please check the bottom), no matter Server close the \
socket explicitly or kill by &quot;kill -9 xxx&quot;, the client side will print out \
&quot;[client] read : -1&quot;  continuously. so, if we are using \
FileChannel.transferFrom which will call transferFromArbitraryChannel which will call \
ReadableByteChannel.read, ReadableByteChannel.read will return -1, but \
transferFromArbitraryChannel will return 0, so as FileChannel.transferFrom.  Based on \
this return value, following while loop will be a infinite loop, and user don't want \
to call something like &quot;call sth like srcSocketChannel.read(...)&quot;, please \
check the reason in comments below.</span><span lang="EN-US"><o:p></o:p></span></p> \
<p class="MsoNormal" align="left" style="text-align:left"><span lang="EN-US" \
style="font-size:12.0pt;font-family:宋体;color:black">while \
(srcSocketChannel.isOpen()) {</span><span lang="EN-US"><o:p></o:p></span></p> <p \
class="MsoNormal" align="left" style="text-align:left"><span lang="EN-US" \
style="font-size:12.0pt;font-family:宋体;color:black">&nbsp; long l = \
fileChannel.transferFrom(srcSocketChannel,...);<br> &nbsp; // user could call sth \
like srcSocketChannel.read(...), and expect it return -1, and break the loop, but it \
will be unacceptable for some program, where they would like to very quick copy, so \
called &quot;zero&quot; copy through fileChannel.transferFrom, and they don't  want \
to add an extra check like &quot;srcSocketChannel.read(...)&quot;<br> &nbsp; if (l == \
-1) { // break out the while loop }</span><span lang="EN-US"><o:p></o:p></span></p> \
<p class="MsoNormal" align="left" style="text-align:left"><span lang="EN-US" \
style="font-size:12.0pt;font-family:宋体;color:black">}</span><span \
lang="EN-US"><o:p></o:p></span></p> <p class="MsoNormal" align="left" \
style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;text-align:left"> <span \
lang="EN-US" style="font-size:12.0pt;font-family:宋体">At this situation, I think \
it's more friendly to have fileChannel.transferFrom returns -1.</span><span \
lang="EN-US"><o:p></o:p></span></p> </blockquote>
<p class="MsoNormal" align="left" style="text-align:left"><span lang="EN-US" \
style="font-size:12.0pt;font-family:宋体">The Client in the reproducer has a bug in \
that it will call read with 0 remaining bytes once it has read 100 bytes in total. So \
I would expect  it will eventually spin reading 0 rather than -1. <span \
style="color:#1F497D"><o:p></o:p></span></span></p> <p class="MsoNormal" align="left" \
style="text-align:left"><span lang="EN-US" \
style="color:#1F497D"><o:p>&nbsp;</o:p></span></p> <p class="MsoNormal" align="left" \
style="text-align:left"><span lang="EN-US" style="color:#1F497D">### Sorry, please \
ignore this bug, I do kill the server manually shortly after it's connected with \
client.<o:p></o:p></span></p> <p class="MsoNormal" align="left" \
style="text-align:left"><span lang="EN-US" \
style="color:#1F497D"><o:p>&nbsp;</o:p></span></p> <p class="MsoNormal" align="left" \
style="text-align:left"><span lang="EN-US" \
style="font-size:12.0pt;font-family:宋体">If the server does terminate and close \
the connection gracefully then the client will spin reading -1 but only if reads \
-1/EOF before 1000 bytes  are read. <span \
style="color:#1F497D"><o:p></o:p></span></span></p> <p class="MsoNormal" align="left" \
style="text-align:left"><span lang="EN-US" \
style="color:#1F497D"><o:p>&nbsp;</o:p></span></p> <p class="MsoNormal" align="left" \
style="text-align:left"><span lang="EN-US" style="color:#1F497D">### Yes, as I kill \
the server manually, so client read will return -1.<o:p></o:p></span></p> <p \
class="MsoNormal" align="left" style="text-align:left"><span lang="EN-US" \
style="color:#1F497D"><o:p>&nbsp;</o:p></span></p> <p class="MsoNormal" align="left" \
style="text-align:left"><span lang="EN-US" \
style="font-size:12.0pt;font-family:宋体">For transferFrom reading from an \
arbitrary channel then it may read bytes before EOF, in which case it will write \
those bytes to the file and  return the number of bytes written/transferred. If \
called again then it will read again and just 0 because there are no bytes \
transferred. I don't see how we can could change this API without breaking existing \
usages that keeping a running code.<span \
style="color:#1F497D"><o:p></o:p></span></span></p> <p class="MsoNormal" align="left" \
style="text-align:left"><span lang="EN-US" \
style="color:#1F497D"><o:p>&nbsp;</o:p></span></p> <p class="MsoNormal" align="left" \
style="text-align:left"><span lang="EN-US" style="color:#1F497D">### if the arbitrary \
channel was just closed by peer side, transferFrom will return 0 this time or next \
time, and there is no way for it knows that the underlying  socket was closed, unless \
it calls channel.read. But for performance consideration, I think some \
framework/program would like to call FileChannel,transferFrom(channel, …) only, \
rather than followed by a read&#43;write just in case of channel is closed by peer  \
side; read&#43;write can be optimized by only do it if transferFrom(channel, …) \
returns 0, but it still has some extra cost, and code is not simple and \
straight.<o:p></o:p></span></p> <p class="MsoNormal" align="left" \
style="text-align:left"><span lang="EN-US" style="color:#1F497D">### I don't think \
this is jdk bug and I do have concern about the compatibility too and explained to \
framework/program developers, but I can also understand their  points, so want to see \
if there are some way to make it more friendly to framework/program developers in \
this situation. Hope I have made it clear </span><span lang="EN-US" \
style="font-family:Wingdings;color:#1F497D">J</span><span lang="EN-US" \
style="color:#1F497D">. If there is no other better solutions, I will let them know \
that it's better to modify their code. <o:p></o:p></span></p>
<p class="MsoNormal" align="left" style="text-align:left"><span lang="EN-US" \
style="color:#1F497D"><o:p>&nbsp;</o:p></span></p> <p class="MsoNormal" align="left" \
style="text-align:left"><span lang="EN-US" style="color:#1F497D">Thanks Alan for \
discussion.<o:p></o:p></span></p> <p class="MsoNormal" align="left" \
style="text-align:left"><span lang="EN-US" \
style="color:#1F497D"><o:p>&nbsp;</o:p></span></p> <p class="MsoNormal" align="left" \
style="text-align:left"><span lang="EN-US" \
style="color:#1F497D">Hamlin<o:p></o:p></span></p> <p class="MsoNormal" align="left" \
style="text-align:left"><span lang="EN-US" \
style="color:#1F497D"><o:p>&nbsp;</o:p></span></p> <p class="MsoNormal" align="left" \
style="text-align:left"><span lang="EN-US" \
style="font-size:12.0pt;font-family:宋体"><br> <br>
-Alan<o:p></o:p></span></p>
</div>
</body>
</html>



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic