<div dir="ltr"><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Jun 16, 2020 at 11:18 PM Stuart Douglas &lt;<a href="mailto:sdouglas@redhat.com">sdouglas@redhat.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="auto"><div><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, 17 Jun 2020, 6:07 am Nate, &lt;<a href="mailto:nate@n4te.com" target="_blank">nate@n4te.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">I dispatch to a worker thread, then read from the file using FileInputStream and write to exchange.getOutputStream(). However, I noticed that this writes all the bytes immediately.  Digging into why, 
exchange.getOutputStream() uses UndertowOutputStream which appears to buffer all the data given to it. 
Not only does this seem inefficient to copy 100MB for every request, it means I don&#39;t know when the transfer completes so I can&#39;t track concurrent downloads.</div></blockquote></div></div><div dir="auto"><br>I don&#39;t understand exactly what you are doing here, can you share a code snippet?<span class="gmail_default" style="font-size:small"> </span>The stream will always write everything that is given to it, but it won&#39;t allocate 100M of buffers. If you have loaded the whole file into memory then it is your code that has buffered the full 100M.</div></div></blockquote><div><div style="font-size:small" class="gmail_default"></div><br></div><div><div style="font-size:small" class="gmail_default">I was reading one byte[] from the InputStream and writing it before reading the next. I&#39;ve now stepped through UndertowOutputStream and I see it copies to a ByteBuffer, then writes that. So I apologize -- I misspoke, it doesn&#39;t buffer the whole 100MB. The behavior I am seeing still has me spooked though.<br></div><div style="font-size:small" class="gmail_default"><br></div><div style="font-size:small" class="gmail_default">I have now switched to <span class="gmail_default" style="font-size:small"></span>transferBlocking, like this:</div><div style="font-size:small" class="gmail_default">
<div>
<div><div></div><div>var rateLimit = RateLimit.obtain(ip); // Throws if the IP has too many concurrent downloads.<br>try (var input = new FileInputStream(file)) {<br>        
            

Channels.<span class="gmail_default" style="font-size:small"></span>transferBlocking(exchange.getResponseChannel(), input.getChannel(), position, length);<br>
<div style="font-size:small" class="gmail_default"><div><div><div>
            



exchange.endExchange();</div></div></div>

</div>

} finally {<br>            rateLimit.release(ip);<br>}</div><div></div></div></div></div><br></div><div><div style="font-size:small" class="gmail_default">My concern is that 
<span class="gmail_default" style="font-size:small"></span>transferBlocking returns very quickly. For example, I run curl 3 times simultaneously to download the file at 10 bytes/sec. For each request, all the code above completes right away, even though the 3 curl instances are still downloading and won&#39;t finish for ~150 hours.<br></div></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="auto"><div dir="auto">The stream approach you mention at the start will do it. Just be aware that your systems socket buffer will also come into play here too, initially undertow will be able to write a bit without blocking until the buffer fills up.</div></div></blockquote><div><br></div><div style="font-size:small" class="gmail_default">Could the system&#39;s socket buffer be responsible for the behavior I see? If so, maybe it is working correctly and I see the request code complete quickly because I don&#39;t have much load on the server?<br></div><div style="font-size:small" class="gmail_default"><br></div><div style="font-size:small" class="gmail_default"></div><div style="font-size:small" class="gmail_default">It&#39;s a little unfortunate to read (and buffer at the system level) the whole file when the request may be abandoned. In fact, the reason I want to limit concurrent downloads by IP is that many people in China use downloader software because of their government firewall. That software hits my server every few seconds for hundreds or even thousands of times. It would be nice to avoid doing too much work prematurely, though 
limiting concurrent downloads by IP should also solve the problem.<br></div><div style="font-size:small" class="gmail_default"><br></div><div style="font-size:small" class="gmail_default">

Is there a way I can know when the client has received all the data, even if it is buffered at the system level?</div><div style="font-size:small" class="gmail_default"></div></div><div class="gmail_quote"><br></div><div class="gmail_quote"><div style="font-size:small" class="gmail_default">Thanks!</div><div style="font-size:small" class="gmail_default">-Nate<br></div></div></div>