Re: How to check if the client dropped the connection

2009-09-29 Thread André Warnier

aaime74 wrote:
...
Hi.
Kind of restarting from the beginning, I think that the first question 
to ask is whether whatever method which actually does the rendering of 
the maps, and which is heavy in terms of resources, is capable of 
being interrupted cleanly in the middle.  Is it capable itself of 
checking regularly if it should continue doing the work ? Or else, if 
you shoot it down does it mop up after itself, or does it leave stuff 
to clean up all over the place ?


From an overall design point of view, it seem to me that you have two 
very different types of processes going on : the first type is the 
management of the HTTP requests, connections, protocol, etc.., which is 
something that should be efficient, light-weight and quick, should 
detect (whenever possible) that the client has broken the connection and 
so on.  That part should also serve the response to the client, when the 
full response is ready as a static object on disk e.g.
The second part is the generation of that content, which by it's nature 
is slow and heavy, but has a very simple interface (create this 
content; stop right now; ..).


Personally, I would tend to try to separate the two parts, and create a 
separate process to handle the content generation, a bit like a database 
back-end.  It seems to me that it would then be easier to wrap this 
process in a simple management wrapper which can interrupt the content 
generation when receiving some signal from the first part, and cleanup 
properly, without tying up resources useful to the HTTP part in the 
meantime.
Such a separation may also simplify aspects such as caching of 
previously generated content, or load-balancing several content generators.


Maybe you should have a look at Apache MINA for the content-generation 
side ? (http://mina.apache.org/)


The (whenever possible) above refers to the fact that a number of 
things outside of your control can come in the way of such detection : 
proxies, firewalls and the like.  If the ultimate client breaks the 
connection, it is not guaranteed that Tomcat itself would notice this 
right away.


-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



Re: How to check if the client dropped the connection

2009-09-29 Thread aaime74



awarnier wrote:
 
 aaime74 wrote:
 ...
 Hi.
 Kind of restarting from the beginning, I think that the first question 
 to ask is whether whatever method which actually does the rendering of 
 the maps, and which is heavy in terms of resources, is capable of 
 being interrupted cleanly in the middle.  Is it capable itself of 
 checking regularly if it should continue doing the work ? Or else, if 
 you shoot it down does it mop up after itself, or does it leave stuff 
 to clean up all over the place ?
 

I can cleanly stop the rendering process in almost any point of it.
The issue is not stopping it, it's detecting the client connection 
was dropped.

No matter what solution is adopted, one still depends on the ability
to detect the client has dropped the connection, something that no
one so far described how to check (I'm starting to wonder if there
is a way at all).


awarnier wrote:
 
 The (whenever possible) above refers to the fact that a number of 
 things outside of your control can come in the way of such detection : 
 proxies, firewalls and the like.  If the ultimate client breaks the 
 connection, it is not guaranteed that Tomcat itself would notice this 
 right away.
 

Ok, but let's say Tomcat is capable of that. How does one check from
within the servlet that the connection has been dropped without writing
out anything? What I've tried so far is trying to block on the input stream
provided by the Http request and hoping it would throw an exception if
the client drop the conntection, but that does not work, the input
stream just return -1 to any read operation no matter if the client
is still connected or not.

Cheers
Andrea
-- 
View this message in context: 
http://www.nabble.com/How-to-check-if-the-client-dropped-the-connection-tp25641481p25658980.html
Sent from the Tomcat - User mailing list archive at Nabble.com.


-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



Re: How to check if the client dropped the connection

2009-09-29 Thread aaime74


Markus Meyer wrote:
 
 I'm not saying you should store the whole map all at once. My approach 
 was to dynamically cache requests that the client may want to make in 
 advance. An easy example would be if a client makes a request for the 
 city center, you create the map for the city center plus the suburbs 
 around it and store it somewhere, then return the city center. If the 
 user then moves around a bit to see the suburbs, you already have the 
 whole map cached and just need to return it, no need to do any further 
 calculation.
 

Sorry, I've lost you there. How is drawing a bigger image going to solve
the problem, which in the end is both a CPU waste but also an OOM
due to too many images being generated at the same time because
of the user zooming in and out fast (most of them are actually not
wanted anymore by the client which in the meantime will drop the
connection).

If anything your suggestion seems to make the client wait longer and
the server OOM faster.


Markus Meyer wrote:
 
 If you then also compress the image on the fly while you are reading it 
 from disk (or from some memory cache), you will start writing to the 
 output stream very soon (also detecting the dropped connection very 
 soon) and the servlet will not need much RAM. Of course this does not 
 work if you just use Java's built-in PNG encoder.
 
 Obviously, caching always comes with the price that you will have the 
 occassional cache miss :-) That is, this does not work for every request 
 but may decrease load and RAM usage a lot for typical use cases.
 

WMS and tile systems are related, but they don't work the same way,
I cited tiling because it's the thing people know the most given the
Google maps popularity.

A desktop WMS client won't use any pre-defined tile structure, each
request will be different in terms of layer requested, zoom level, 
and area. The potential for caching is very, very low.

The tile system are on the other side setup to make caching possible
and efficient by imposing structure on the requests, but what I'm dealing
with here is pure WMS.

What I'm talking about here are the industry standard solutions for
WMS map rendering. We can discuss this at lenght and we could come
out with some interesting new way that was not tried before in the
field. But in the meatime I would really appreciate if anybody could
answer my first question: how does one detect the client connection
has been dropped? Is there any way? Does anybody know?


Markus Meyer wrote:
 
 In your OP you write: Unfortunately in the meantime the older requests 
 are still running, drawing a map takes time and a lot of memory, for 
 example the above request, which is a small one btw, allocates a 
 BufferedImage of 700KB. This indicates that you (1) seem to not use any 
 caching (drawing a map takes time - with caching the map would already 
 have been drawn) and (2) you use BufferedImage which of course does not 
 allow you to PNG-encode on the fly. Both problems would be solved with 
 the above suggestion.
 

The rendering subsystem actually takes a Graphics2D. If you can suggest
ways to draw lines, points and polygons on a raster image that is not
memory bound (like a buffered image) and has no sewing effects 
(like tiles, that do break labelling, long story, don't get me started on
this) 
I'm all ears.

Cheers
Andrea
-- 
View this message in context: 
http://www.nabble.com/How-to-check-if-the-client-dropped-the-connection-tp25641481p25659184.html
Sent from the Tomcat - User mailing list archive at Nabble.com.


-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



Re: How to check if the client dropped the connection

2009-09-29 Thread Pid

On 29/09/2009 09:15, André Warnier wrote:

aaime74 wrote:
...
Hi.
Kind of restarting from the beginning, I think that the first question
to ask is whether whatever method which actually does the rendering of
the maps, and which is heavy in terms of resources, is capable of
being interrupted cleanly in the middle. Is it capable itself of
checking regularly if it should continue doing the work ? Or else, if
you shoot it down does it mop up after itself, or does it leave stuff
to clean up all over the place ?

 From an overall design point of view, it seem to me that you have two
very different types of processes going on : the first type is the
management of the HTTP requests, connections, protocol, etc.., which is
something that should be efficient, light-weight and quick, should
detect (whenever possible) that the client has broken the connection and
so on. That part should also serve the response to the client, when the
full response is ready as a static object on disk e.g.


Andre's approach is correct IMHO, it's a caching problem: decouple the 
generation bit from the delivery bit and ensure that the data you need 
to serve is always available at short notice, so the consequences of an 
interruption aren't so big.




The second part is the generation of that content, which by it's nature
is slow and heavy, but has a very simple interface (create this
content; stop right now; ..).


Consider pre-fetching the next possible grid squares into the cache - 
you may also consider tuning your caching algorithm to determine the 
rate  direction of travel (of a given client) across the map, so you 
can avoid pre-fetching unnecessary units.


I'd be thinking of a queue of requests and a multi-threaded 
(multi-server?) pool to service it.



Slightly more leftfield: if you're effectively serving static images off 
a disk, you could consider directing (via a forward) requests straight 
to a public image directory and use APR/sendfile to serve them 
statically - which would be very fast, delivery-wise, and would 
eliminate the need for you to handle interruptions in your own code.  (I 
think.)



Lastly, if it's a heavy-weight process then at some point, when demand 
rises, you'll need a server(s) with lots of power and probably a big 
chunk of RAM.  Don't try and design around this.



p



Personally, I would tend to try to separate the two parts, and create a
separate process to handle the content generation, a bit like a database
back-end. It seems to me that it would then be easier to wrap this
process in a simple management wrapper which can interrupt the content
generation when receiving some signal from the first part, and cleanup
properly, without tying up resources useful to the HTTP part in the
meantime.
Such a separation may also simplify aspects such as caching of
previously generated content, or load-balancing several content generators.

Maybe you should have a look at Apache MINA for the content-generation
side ? (http://mina.apache.org/)

The (whenever possible) above refers to the fact that a number of
things outside of your control can come in the way of such detection :
proxies, firewalls and the like. If the ultimate client breaks the
connection, it is not guaranteed that Tomcat itself would notice this
right away.

-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org




-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



Re: How to check if the client dropped the connection

2009-09-29 Thread Pid

On 29/09/2009 09:34, aaime74 wrote:




awarnier wrote:


aaime74 wrote:
...
Hi.
Kind of restarting from the beginning, I think that the first question
to ask is whether whatever method which actually does the rendering of
the maps, and which is heavy in terms of resources, is capable of
being interrupted cleanly in the middle.  Is it capable itself of
checking regularly if it should continue doing the work ? Or else, if
you shoot it down does it mop up after itself, or does it leave stuff
to clean up all over the place ?



I can cleanly stop the rendering process in almost any point of it.
The issue is not stopping it, it's detecting the client connection
was dropped.

No matter what solution is adopted, one still depends on the ability
to detect the client has dropped the connection, something that no
one so far described how to check (I'm starting to wonder if there
is a way at all).


awarnier wrote:


The (whenever possible) above refers to the fact that a number of
things outside of your control can come in the way of such detection :
proxies, firewalls and the like.  If the ultimate client breaks the
connection, it is not guaranteed that Tomcat itself would notice this
right away.



Ok, but let's say Tomcat is capable of that. How does one check from
within the servlet that the connection has been dropped without writing
out anything? What I've tried so far is trying to block on the input stream
provided by the Http request and hoping it would throw an exception if
the client drop the conntection, but that does not work, the input
stream just return -1 to any read operation no matter if the client
is still connected or not.


If you've processed request parameters, the inputstream is empty because 
it's already been consumed.


As previously stated, you'd have to try and write something (a header?) 
to the outputstream to find out if it's available or not.


  hres.addHeader(X-Streamcheck-01, OK!);

  ... do some work ...

  hres.addHeader(X-Streamcheck-02, OK!);


p




Cheers
Andrea



-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



Re: How to check if the client dropped the connection

2009-09-29 Thread Pid

On 29/09/2009 09:47, aaime74 wrote:



Markus Meyer wrote:


I'm not saying you should store the whole map all at once. My approach
was to dynamically cache requests that the client may want to make in
advance. An easy example would be if a client makes a request for the
city center, you create the map for the city center plus the suburbs
around it and store it somewhere, then return the city center. If the
user then moves around a bit to see the suburbs, you already have the
whole map cached and just need to return it, no need to do any further
calculation.



Sorry, I've lost you there. How is drawing a bigger image going to solve
the problem, which in the end is both a CPU waste but also an OOM
due to too many images being generated at the same time because
of the user zooming in and out fast (most of them are actually not
wanted anymore by the client which in the meantime will drop the
connection).


... because for future requests, the data already exists and the work is 
already done.  The consequences of a dropped connection are therefore 
reduced because you're not doing the work for every single request, and 
any work you are doing isn't completely wasted.



Take for example the situation where a user zooms in one direction, 
changes their mind  goes back (say to check a point of origin), then 
*again* reverses direction to proceed as before.


If you've cached the responses to the first motion then you don't need 
to do the work again when the third motion occurs - and the work done 
the first time isn't wasted.



Queuing the requests for generating images would allow you to limit how 
much work was being done and reduce the chances of an OOM.




It might simply be that you can't achieve what you want without lots of 
RAM and more processing power than you currently have.


You may find that you must either queue the generator requests to manage 
the load on the server - at the price of making clients wait for data, 
or you that you must add more processing power  RAM.


(It sounds like your current setup can't cope with a single users' peak 
load.)



Caching stuff mitigates some of the problems you have but it won't solve 
the overall problem (which is not that connections are dropped - it's 
that the work done is both wasted and too much for the server to handle).



p




If anything your suggestion seems to make the client wait longer and
the server OOM faster.






Markus Meyer wrote:


If you then also compress the image on the fly while you are reading it
from disk (or from some memory cache), you will start writing to the
output stream very soon (also detecting the dropped connection very
soon) and the servlet will not need much RAM. Of course this does not
work if you just use Java's built-in PNG encoder.

Obviously, caching always comes with the price that you will have the
occassional cache miss :-) That is, this does not work for every request
but may decrease load and RAM usage a lot for typical use cases.



WMS and tile systems are related, but they don't work the same way,
I cited tiling because it's the thing people know the most given the
Google maps popularity.

A desktop WMS client won't use any pre-defined tile structure, each
request will be different in terms of layer requested, zoom level,
and area. The potential for caching is very, very low.

The tile system are on the other side setup to make caching possible
and efficient by imposing structure on the requests, but what I'm dealing
with here is pure WMS.

What I'm talking about here are the industry standard solutions for
WMS map rendering. We can discuss this at lenght and we could come
out with some interesting new way that was not tried before in the
field. But in the meatime I would really appreciate if anybody could
answer my first question: how does one detect the client connection
has been dropped? Is there any way? Does anybody know?


Markus Meyer wrote:


In your OP you write: Unfortunately in the meantime the older requests
are still running, drawing a map takes time and a lot of memory, for
example the above request, which is a small one btw, allocates a
BufferedImage of 700KB. This indicates that you (1) seem to not use any
caching (drawing a map takes time - with caching the map would already
have been drawn) and (2) you use BufferedImage which of course does not
allow you to PNG-encode on the fly. Both problems would be solved with
the above suggestion.



The rendering subsystem actually takes a Graphics2D. If you can suggest
ways to draw lines, points and polygons on a raster image that is not
memory bound (like a buffered image) and has no sewing effects
(like tiles, that do break labelling, long story, don't get me started on
this)
I'm all ears.

Cheers
Andrea



-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



Re: How to check if the client dropped the connection

2009-09-29 Thread Peter Crowther
2009/9/29 aaime74 andrea.a...@gmail.com

 But in the meatime I would really appreciate if anybody could
 answer my first question: how does one detect the client connection
 has been dropped? Is there any way? Does anybody know?


First off, I assume you're serving these straight out of Tomcat to the
client - there's no proxying or Apache httpd to complicate things.  I think
you already said that, but this thread's gone down so many twists that I've
mislaid the information - my apologies.

I don't believe that Tomcat provides any such detection mechanism out of
the box.  It certainly doesn't provide any termination mechanism -
terminating a CGI script is easy as you know the code's held inside a nice
neat bundle of a process, but aborting a Thread in Tomcat could leave a
horrible legacy behind as it's all in the same address space.  However, I
think detection would be relatively simple to add.

First off, let's assume that the OS's stack and Java's socket implementation
work well enough together that isClosed() and isOutputConnected() on the
socket actually give you meaningful information.  If that's the case, all
you need to do is to be able to get direct hold of the Socket that's writing
the bytes and call appropriate methods on that.  I would assume there's no
way of doing this through the API, as it completely breaks layering.

At this point, I'd be cracking open the Tomcat source and hacking in The
Simplest Change That Could Possibly Work, just to see whether it does!  In
my case, that would involve some disgusting non-production hackery like
putting a reference to the Socket onto thread-local storage once you know
which thread will be handling the request, and making absolutely sure I took
it out again as the request returned.  Absolutely not what you want to do in
a production system, but useful for a proof of concept.  It's then possible
to ask the Socket about its state directly in various places in the
rendering pipeline, and abort the render if it's no longer required.

I'd then do further work to refactor this so that there's some more
appropriate (but Tomcat-specific) API, rather than the hackery described
above.

This does mean that you'd end up with a custom Tomcat, and hence your own
code to maintain through upgrades.  I suspect it's sufficiently isolated
that such maintenance wouldn't be too big a problem, but you'd definitely be
compiling from source.  That's not a huge undertaking - I've done it on a
couple of past projects.

Happy to chat further if this looks like a useful approach.  If you don't
want to code it yourself, I suspect there are several people on-list with
the skills and experience to construct such an addition.

- Peter


Re: How to check if the client dropped the connection

2009-09-29 Thread Peter Crowther
2009/9/29 Pid p...@pidster.com

 ... because for future requests, the data already exists and the work is
 already done.  The consequences of a dropped connection are therefore
 reduced because you're not doing the work for every single request, and any
 work you are doing isn't completely wasted.


Pid, you're assuming some features of the application that may not be true,
namely that a sufficiently high proportion of the images are re-used for
this work to be useful.  If the cache hit rate is low, that assumption may
well be false.

You're also assuming that the resulting artifact is sufficiently lightweight
that it is appropriate to cache.  That, in turn, depends on the relative
cost of generating the image vs storing it.  On modern machines with very
fast processors, modest amounts of memory and dreadful bandwidth to disk*,
I'd not be willing to take either side of that bet without examining the
application's resource profile in considerable detail.

- Peter

* Amdahl's Rule of Thumb: A machine should be able to clear its memory in
one second and write it to disk in 10 seconds.  For a general-purpose
server, I think the rule still holds.


Re: How to check if the client dropped the connection

2009-09-29 Thread André Warnier

aaime74 wrote:
...


Ok, but let's say Tomcat is capable of that. How does one check from
within the servlet that the connection has been dropped without writing
out anything? 


I have been looking (starting at the HttpServletResponse object), trying 
to follow the trail to see if one at some point can get hold of some 
Connection object which would have some isConnected property. No 
luck so far, but I am really not a java expert.


What I've tried so far is trying to block on the input stream

provided by the Http request and hoping it would throw an exception if
the client drop the conntection, but that does not work, the input
stream just return -1 to any read operation no matter if the client
is still connected or not.


Yes, but that is because each TCP connection really consists of two 
separate parts or sides. For each actor (server and client), there is 
one part that is the incoming connection, and another separate part that 
is the outgoing connection (the sides being crossed-over in the middle 
for the server and the client).
Each actor can close its own incoming or outgoing connection, 
independently, without warning to the other part. (E.g., suppose it just 
crashes). When that happens, the other side of that connection is left 
dangling : basically, it does not known that the other side is gone, 
until it tries to send something on that connection, and the TCP stack 
(deep down in the bowels of the underlying OS) returns an error, which 
then filters back up all the way to your java OutputStream object.


In your case, what matters to you is the response output stream, not the 
input stream, which could have been (validly) closed by the client 
already, if it has no further use for it.




-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



Re: How to check if the client dropped the connection

2009-09-29 Thread Christopher Schultz
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

Andrea,

On 9/29/2009 4:34 AM, aaime74 wrote:
 I can cleanly stop the rendering process in almost any point of it.
 The issue is not stopping it, it's detecting the client connection 
 was dropped.
 
 No matter what solution is adopted, one still depends on the ability
 to detect the client has dropped the connection, something that no
 one so far described how to check (I'm starting to wonder if there
 is a way at all).

I would do something like this, adopting Jason's strategy:

private static final byte[] NOTHING = new byte[0];

public void doGet(...) { // or whatever

  OutputStream out = response.getOutputStream();

  // look into java.util.concurrent.Executor and friends if
  // you've never seen them... great stuff
  MapDrawingTask /* implements Callable */ task = new MapDrawingTask();

  FutureVoid task = executor.submit(task);

  while(!task.isDone()  !task.isCancelled()) {
try {
  Thread.currentThread().sleep(100); // or whatever timeout you want
}
catch (InterruptedException ie) {
  // Ignore
}

try {
  out.write(NOTHING);
  out.flush();
}
catch (ClientAbortException cae) {
  task.cancel(true); // allow interruptions

  // the break isn't strictly necessary
  break; // or even return if you want to get out quick
}
  }

  if(!task.isCancelled()) {
// dump output to response
  }
}


You may want to catch more exceptions than just ClientAbortException
there, you might need more error handling in general, and my
quick-and-dirty thread-and-task management will probably need some
improvement and cleanup, but you get the general idea: the HTTP thread
blocks waiting for either the map-drawing task to complete, or for the
client to hang up the phone.

Hope that helps,
- -chris
-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.9 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkrCJxUACgkQ9CaO5/Lv0PDnqwCgn/WyPTUGwn6yHihzeak+HACW
aOUAnR/EogE5wbVVKJUd8/aFLqXPVbYK
=jXyD
-END PGP SIGNATURE-

-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



Re: How to check if the client dropped the connection

2009-09-29 Thread Christopher Schultz
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

Markus,

On 9/28/2009 6:03 PM, Markus Meyer wrote:
 Martin Gainty schrieb:
 could you explain just a bit more what is a tile?
 
 If you have a very large image, say 1 million x 1 million pixels or
 something like that, it is more efficient to split the image into tiles,
 that is small images of, say, 256 x 256 pixels. If a certain portion of
 the big image is requested, you can then load these tiles individually
 from disk and put them together to form the portion of the image that
 was requested.

Oddly enough, this is much more efficient to do on the client side if,
say, javascript is available. Google appears to do this with their maps:
if you pan around your home on maps.google.com, you can see the
individual tiles loading and being rendered on the screen to create a
larger image. If you pan off the screen no loading has to occur until
you cross one of the tile boundaries that has already been sent.

It's like looking through a small window at a large painting: you are
only seeing a small portion of the painting (the sum total of all
previously-fetched tiles) because of the size of the window (the view
port on the screen).

The OP seems to be using tiles on the backend for convenience, but then
using complex server-side methods to assemble the /exact/ image that the
client requested. That requires things like image decoding followed by
lots of memory allocation, and then a heavy re-compression before
streaming the result back to the client.

If the client has some measure of power, the server can take advantage
of that by converting all complex requests into individual, simple
requests. A request for a single 1000x1000 image could be converted into
16 requests for 256x256 static tile images, then re-assembled on the
client. No image manipulation occurs on the server, which is a /huge/
win for your service.

Unfortunately, it requires something like javascript to be present on
the client. If your service cannot tolerate such a requirement, then you
need to make arrangements for those clients who /don't/ have javascript
available.

- -chris
-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.9 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkrCKdcACgkQ9CaO5/Lv0PCh3QCeIWWVAQ7+ynyC9IaxfAQJ6bb5
hzcAnAqgYsWDPbKki8Yjsn/Tiuvh4T+a
=BzDn
-END PGP SIGNATURE-

-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



How to check if the client dropped the connection

2009-09-28 Thread aaime74

Hi,
I'm working on the development of an open source application, GeoServer,
implementing the Web Map Service specification.
The specification allows a client to request maps using simple GET
requests like:

http://sigma.openplans.org:8080/geoserver/wms?WIDTH=431SRS=EPSG%3A4326LAYERS=tiger-nyHEIGHT=550STYLES=FORMAT=image%2FpngSERVICE=WMSVERSION=1.1.1REQUEST=GetMapEXCEPTIONS=application%2Fvnd.ogc.se_inimageBBOX=-74.01697805908182,40.69808217724622,-73.99567744140603,40.72526393994153

and the client gets back a PNG with a map of the request area.
No asynchronism is allowed, the protocol is standardized
(http://portal.opengeospatial.org/files/?artifact_id=1058) and I have no
controls over the clients (there are tens of them around, both open source
and proprietary) which are free to make as many request as they like, in
whatever order the like.

By spec we're forced to use a plain request and response approach, but
we're experiencing a problem with clients making lots of request as the
user zooms/pans around: basically a request is made, but the user keeps
on moving, the client drops the older requests (closing the connection in
face of
the server) and makes others.
Unfortunately in the meantime the older requests are still running, drawing
a map takes
time and a lot of memory, for example the above request, which is a
small one btw, allocates a BufferedImage of 700KB. The memory is
consumed up until the image is encoded out to the stream, which is also
the moment we finally figure out the client dropped the connection
(since writing to the servlet output stream fails).

This is very sub-optimal. Servers like Apache with cgi do kill the cgi
process the moment the connection is dropped, significantly reducing the
server load both in terms of CPU and memory consumption.

Is there any way to check if the client connection is still open using
only the standard servlet API?
If not, is there any Tomcat specific approach that might work instead?

If there is no solution that can be applied at the general servlet
api level, do you know of any Tomcat specific approach one could use?
e.g., casting the HttpServletResponse to some Tomcat specific class
and get some connection information status there?

Cheers
Andrea 
-- 
View this message in context: 
http://www.nabble.com/How-to-check-if-the-client-dropped-the-connection-tp25641481p25641481.html
Sent from the Tomcat - User mailing list archive at Nabble.com.


-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



Re: How to check if the client dropped the connection

2009-09-28 Thread Jason Brittain
Hi Andrea.

When the client disconnects, and your servlet tries to write to the output
stream, Tomcat will throw a ClientAbortException (you may have already seen
this):

http://tomcat.apache.org/tomcat-6.0-doc/api/org/apache/catalina/connector/ClientAbortException.html

Tomcat appears to only throw this exception when you either write some bytes
to the output stream or when you flush the output stream, and the client
already closed its end of the connection.  It appears that you could
periodically try flushing the output stream and see if doing so throws this
exception. You can flush after writing any number of bytes, including zero
bytes.  The first time you call flush, it will send the HTTP response
headers to the client, so you would need to first set the headers before
flushing.  That sounds difficult for you to do because you're writing an
image, and one of the headers would be Content-Length, which you probably
don't know until your image is generated.

--
Jason Brittain


On Mon, Sep 28, 2009 at 12:21 AM, aaime74 andrea.a...@gmail.com wrote:


 Hi,
 I'm working on the development of an open source application, GeoServer,
 implementing the Web Map Service specification.
 The specification allows a client to request maps using simple GET
 requests like:


 http://sigma.openplans.org:8080/geoserver/wms?WIDTH=431SRS=EPSG%3A4326LAYERS=tiger-nyHEIGHT=550STYLES=FORMAT=image%2FpngSERVICE=WMSVERSION=1.1.1REQUEST=GetMapEXCEPTIONS=application%2Fvnd.ogc.se_inimageBBOX=-74.01697805908182,40.69808217724622,-73.99567744140603,40.72526393994153

 and the client gets back a PNG with a map of the request area.
 No asynchronism is allowed, the protocol is standardized
 (http://portal.opengeospatial.org/files/?artifact_id=1058) and I have no
 controls over the clients (there are tens of them around, both open source
 and proprietary) which are free to make as many request as they like, in
 whatever order the like.

 By spec we're forced to use a plain request and response approach, but
 we're experiencing a problem with clients making lots of request as the
 user zooms/pans around: basically a request is made, but the user keeps
 on moving, the client drops the older requests (closing the connection in
 face of
 the server) and makes others.
 Unfortunately in the meantime the older requests are still running, drawing
 a map takes
 time and a lot of memory, for example the above request, which is a
 small one btw, allocates a BufferedImage of 700KB. The memory is
 consumed up until the image is encoded out to the stream, which is also
 the moment we finally figure out the client dropped the connection
 (since writing to the servlet output stream fails).

 This is very sub-optimal. Servers like Apache with cgi do kill the cgi
 process the moment the connection is dropped, significantly reducing the
 server load both in terms of CPU and memory consumption.

 Is there any way to check if the client connection is still open using
 only the standard servlet API?
 If not, is there any Tomcat specific approach that might work instead?

 If there is no solution that can be applied at the general servlet
 api level, do you know of any Tomcat specific approach one could use?
 e.g., casting the HttpServletResponse to some Tomcat specific class
 and get some connection information status there?

 Cheers
 Andrea
 --
 View this message in context:
 http://www.nabble.com/How-to-check-if-the-client-dropped-the-connection-tp25641481p25641481.html
 Sent from the Tomcat - User mailing list archive at Nabble.com.


 -
 To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
 For additional commands, e-mail: users-h...@tomcat.apache.org




-- 
Jason Brittain


Re: How to check if the client dropped the connection

2009-09-28 Thread Markus Meyer

Jason Brittain schrieb:

The first time you call flush, it will send the HTTP response
headers to the client, so you would need to first set the headers before
flushing.  That sounds difficult for you to do because you're writing an
image, and one of the headers would be Content-Length, which you probably
don't know until your image is generated.


Actually, Content-Length is optional as per the HTTP-1.1 spec:

http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html

However, my take on the OP is that a better optimization strategy in 
this case would be to just cache a larger image on the server rather 
than generating every image on-demand. That is, when the user is moving 
around in the image, the server, on the first request, would calculate 
the image for a much larger portion of the map than requested and stores 
it on disk in temporary storage (or in some cache area in RAM, if 
feasible, after all RAM is cheap these days and 64-bit machines can have 
lots of RAM). Storage of the images would not be done all at once but in 
tiles. When then user then moves around in the client, the requests just 
reads the tiles of the created image from disk, puts them together and 
clips the borders, then compresses the image and sends it to the client. 
It is possible that PNG even has some support for compressing parts of 
an image so the tiles itself could be already stored in compressed 
format, but it's been a while since I read the PNG spec last time. The 
same could be done for zooming by storing images in a pyramidal 
structure, like it is done in pattern recognition. While the user is 
moving, a background thread associated with the client could try to 
anticipate where the user is likely to be moving to and calculate the 
given tiles in advance. Actually, this sounds like an interesting 
project for several Ph.D. theses...



Markus

-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



Re: How to check if the client dropped the connection

2009-09-28 Thread aaime74


jasonb wrote:
 
 Hi Andrea.
 
 When the client disconnects, and your servlet tries to write to the output
 stream, Tomcat will throw a ClientAbortException (you may have already
 seen
 this):
 
 http://tomcat.apache.org/tomcat-6.0-doc/api/org/apache/catalina/connector/ClientAbortException.html
 
 Tomcat appears to only throw this exception when you either write some
 bytes
 to the output stream or when you flush the output stream, and the client
 already closed its end of the connection.  It appears that you could
 periodically try flushing the output stream and see if doing so throws
 this
 exception. You can flush after writing any number of bytes, including zero
 bytes.  The first time you call flush, it will send the HTTP response
 headers to the client, so you would need to first set the headers before
 flushing.  That sounds difficult for you to do because you're writing an
 image, and one of the headers would be Content-Length, which you probably
 don't know until your image is generated.


We actually don't send the content length out, we used chunked transfer
instead (that is, stream out the result of the png compression as made by
JAI
Image I/O) but unfortunately we cannot do that either, as the protocols
mandates that any error occurring during rendering be returned as XML.

So I actually know the final content type only when the image is fully
rendered,
which is when I start writing out bytes anyways.

Cheers
Andrea

-- 
View this message in context: 
http://www.nabble.com/How-to-check-if-the-client-dropped-the-connection-tp25641481p25651470.html
Sent from the Tomcat - User mailing list archive at Nabble.com.


-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



Re: How to check if the client dropped the connection

2009-09-28 Thread aaime74



Markus Meyer wrote:
 
 Jason Brittain schrieb:
 The first time you call flush, it will send the HTTP response
 headers to the client, so you would need to first set the headers before
 flushing.  That sounds difficult for you to do because you're writing an
 image, and one of the headers would be Content-Length, which you probably
 don't know until your image is generated.
 
 Actually, Content-Length is optional as per the HTTP-1.1 spec:
 
 http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
 
 However, my take on the OP is that a better optimization strategy in 
 this case would be to just cache a larger image on the server rather 
 than generating every image on-demand. That is, when the user is moving 
 around in the image, the server, on the first request, would calculate 
 the image for a much larger portion of the map than requested and stores 
 it on disk in temporary storage (or in some cache area in RAM, if 
 feasible, after all RAM is cheap these days and 64-bit machines can have 
 lots of RAM). Storage of the images would not be done all at once but in 
 tiles. When then user then moves around in the client, the requests just 
 reads the tiles of the created image from disk, puts them together and 
 clips the borders, then compresses the image and sends it to the client. 
 It is possible that PNG even has some support for compressing parts of 
 an image so the tiles itself could be already stored in compressed 
 format, but it's been a while since I read the PNG spec last time. The 
 same could be done for zooming by storing images in a pyramidal 
 structure, like it is done in pattern recognition. While the user is 
 moving, a background thread associated with the client could try to 
 anticipate where the user is likely to be moving to and calculate the 
 given tiles in advance. Actually, this sounds like an interesting 
 project for several Ph.D. theses...
 

Well, something like that has actually been done already, it's called
tile caching, and works under the restrictive conditions that you
can force the client to make requests in predetermined sizes and tiles.
As for applying this to the general case, I invite you to have a look
at how big the raster surface is and how much space is required
to actually store on the disk a full map (only _one_ map, some GeoServer
installs do serve 500-1000 different layers) here:
http://geowebcache.org/trac/wiki/resources
(the site is describing the tile cache companion to GeoServer, called
GeoWebCache)

So, it is somewhat doable, but only for a few backgrond layers that
do not change that often (once a month may be ok if you don't need
to zoom in too much).

Cheers
Andrea

-- 
View this message in context: 
http://www.nabble.com/How-to-check-if-the-client-dropped-the-connection-tp25641481p25651562.html
Sent from the Tomcat - User mailing list archive at Nabble.com.


-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



Re: How to check if the client dropped the connection

2009-09-28 Thread Markus Meyer

aaime74 schrieb:

Well, something like that has actually been done already, it's called
tile caching, and works under the restrictive conditions that you
can force the client to make requests in predetermined sizes and tiles.
As for applying this to the general case, I invite you to have a look
at how big the raster surface is and how much space is required
to actually store on the disk a full map (only _one_ map, some GeoServer
installs do serve 500-1000 different layers) here:


I'm not saying you should store the whole map all at once. My approach 
was to dynamically cache requests that the client may want to make in 
advance. An easy example would be if a client makes a request for the 
city center, you create the map for the city center plus the suburbs 
around it and store it somewhere, then return the city center. If the 
user then moves around a bit to see the suburbs, you already have the 
whole map cached and just need to return it, no need to do any further 
calculation.


If you then also compress the image on the fly while you are reading it 
from disk (or from some memory cache), you will start writing to the 
output stream very soon (also detecting the dropped connection very 
soon) and the servlet will not need much RAM. Of course this does not 
work if you just use Java's built-in PNG encoder.


Obviously, caching always comes with the price that you will have the 
occassional cache miss :-) That is, this does not work for every request 
but may decrease load and RAM usage a lot for typical use cases.


In your OP you write: Unfortunately in the meantime the older requests 
are still running, drawing a map takes time and a lot of memory, for 
example the above request, which is a small one btw, allocates a 
BufferedImage of 700KB. This indicates that you (1) seem to not use any 
caching (drawing a map takes time - with caching the map would already 
have been drawn) and (2) you use BufferedImage which of course does not 
allow you to PNG-encode on the fly. Both problems would be solved with 
the above suggestion.



Markus

-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



RE: How to check if the client dropped the connection

2009-09-28 Thread Martin Gainty

could you explain just a bit more what is a tile?

Martin 
__ 
Verzicht und Vertraulichkeitanmerkung
 
Diese Nachricht ist vertraulich. Sollten Sie nicht der vorgesehene Empfaenger 
sein, so bitten wir hoeflich um eine Mitteilung. Jede unbefugte Weiterleitung 
oder Fertigung einer Kopie ist unzulaessig. Diese Nachricht dient lediglich dem 
Austausch von Informationen und entfaltet keine rechtliche Bindungswirkung. 
Aufgrund der leichten Manipulierbarkeit von E-Mails koennen wir keine Haftung 
fuer den Inhalt uebernehmen.






 Date: Mon, 28 Sep 2009 21:27:15 +0200
 From: me...@mesw.de
 To: users@tomcat.apache.org
 Subject: Re: How to check if the client dropped the connection
 
 Jason Brittain schrieb:
  The first time you call flush, it will send the HTTP response
  headers to the client, so you would need to first set the headers before
  flushing.  That sounds difficult for you to do because you're writing an
  image, and one of the headers would be Content-Length, which you probably
  don't know until your image is generated.
 
 Actually, Content-Length is optional as per the HTTP-1.1 spec:
 
 http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
 
 However, my take on the OP is that a better optimization strategy in 
 this case would be to just cache a larger image on the server rather 
 than generating every image on-demand. That is, when the user is moving 
 around in the image, the server, on the first request, would calculate 
 the image for a much larger portion of the map than requested and stores 
 it on disk in temporary storage (or in some cache area in RAM, if 
 feasible, after all RAM is cheap these days and 64-bit machines can have 
 lots of RAM). Storage of the images would not be done all at once but in 
 tiles. When then user then moves around in the client, the requests just 
 reads the tiles of the created image from disk, puts them together and 
 clips the borders, then compresses the image and sends it to the client. 
 It is possible that PNG even has some support for compressing parts of 
 an image so the tiles itself could be already stored in compressed 
 format, but it's been a while since I read the PNG spec last time. The 
 same could be done for zooming by storing images in a pyramidal 
 structure, like it is done in pattern recognition. While the user is 
 moving, a background thread associated with the client could try to 
 anticipate where the user is likely to be moving to and calculate the 
 given tiles in advance. Actually, this sounds like an interesting 
 project for several Ph.D. theses...
 
 
 Markus
 
 -
 To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
 For additional commands, e-mail: users-h...@tomcat.apache.org
 
  
_
Hotmail® has ever-growing storage! Don’t worry about storage limits.
http://windowslive.com/Tutorial/Hotmail/Storage?ocid=TXT_TAGLM_WL_HM_Tutorial_Storage_062009

[OT] Re: How to check if the client dropped the connection

2009-09-28 Thread André Warnier

Martin Gainty wrote:

could you explain just a bit more what is a tile?


http://en.wikipedia.org/wiki/Tile

It's the same idea, but for images.


-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



Re: How to check if the client dropped the connection

2009-09-28 Thread Markus Meyer

Martin Gainty schrieb:

could you explain just a bit more what is a tile?


If you have a very large image, say 1 million x 1 million pixels or 
something like that, it is more efficient to split the image into tiles, 
that is small images of, say, 256 x 256 pixels. If a certain portion of 
the big image is requested, you can then load these tiles individually 
from disk and put them together to form the portion of the image that 
was requested. Tiles which are inside the requested image portion can be 
used as is, tiles at the borders may not be contained fully in the 
requested image and must possibly be clipped.


How tiles are used can be seen e.g. in Google Maps: when you have a slow 
internet connection, while scrolling you can actually see that the map 
consists of rectangular tiles which are loaded on demand.


This is more or less the same concept as blocks when doing paging of 
virtual memory or pages when talking about processor caches. Even 
Audacity (audio editor) uses this concept to achieve fast editing of 
very large audio files.



Markus

-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org