[Geoserver-devel] Incorporating jtilecache

Hi,

I am looking to integrate Chris Whitney's JTileCache ( http://whitney.textdriven.com/blog/2007/07/03/jtilecache-proxy-edition/ ) into Geoserver.

Currently it is a separate servlet that communicates with Geoserver through HTTP using the regular WMS interface. It would be nice to bring it closer to Geoserver, so that it knows more about what layers are available, what needs to be purged and so on.

My first attempt was to create a new community module with the code and create a route for /geoserver/tilecache . But I wasn't able to find an elegant way to make WMS requests, because invoking DefaultWebMapService appears to require a getMapRequest, which in turn requires the actual URL. After the dispatcher I can only seem to get my hands on a org.restlet.Request, which is tricky to turn back into an URL.

A compromise I am leaning towards is to skip the dispatcher and keep jtilecache separate, but pass WMS information in through applicationContext. I am not sure whether requests for fresh tiles would still be HTTP requests, or whether I could use the WMS functions directly.

Do people have other suggestions on how to do this?
-Arne

Arne Kepp ha scritto:

Hi,

I am looking to integrate Chris Whitney's JTileCache ( http://whitney.textdriven.com/blog/2007/07/03/jtilecache-proxy-edition/ ) into Geoserver.

Currently it is a separate servlet that communicates with Geoserver through HTTP using the regular WMS interface. It would be nice to bring it closer to Geoserver, so that it knows more about what layers are available, what needs to be purged and so on.

My first attempt was to create a new community module with the code and create a route for /geoserver/tilecache . But I wasn't able to find an elegant way to make WMS requests, because invoking DefaultWebMapService appears to require a getMapRequest, which in turn requires the actual URL. After the dispatcher I can only seem to get my hands on a org.restlet.Request, which is tricky to turn back into an URL.

A compromise I am leaning towards is to skip the dispatcher and keep jtilecache separate, but pass WMS information in through applicationContext. I am not sure whether requests for fresh tiles would still be HTTP requests, or whether I could use the WMS functions directly.

Hard to help you out since I never tried to use JTileCache. Just as starters, which protocol does it use? WMS? or TMS?
The best I think would be to create a new service for jtilecache and
have it use the WMS objects directly. Unfortunately the process
to create a new service is totally undocumented (http://jira.codehaus.org/browse/GEOS-940), I had to do
"monkey see, monkey do" myself for the WCS 1.1.1 implementation I'm
working on. I can try to help you, but mail is not exactly the
easiest medium... it would be better to have that docs in the wiki, sigh...

Cheers
Andrea

      When I wrote JTileCache, it was only designed to be used with WMS. I didn't / still don't know enough about the Geoserver code to figure out how to fit a cache directly into the code path.

      JTileCache essentially works off of "WMSParameters" information. As the name implies, these objects contain all of the WMS request information (BBOX, width, height, etc). Normally, these parameters are taken from the WMS request GET parameters.

      If the module can get all of that information directly from Geoserver (i.e. it is capable of constructing a WMSParameters object with all of the information), then there is no need for dealing with URLs. Simply call JTileCache.setToCache( WMSParameters, ImageTile) or getFromCache(WMSParameters).

Let me know if you have any questions, and I'll try to help out as much as possible.

-- Chris Whitney

On Nov 27, 2007, at 10:32 AM, Andrea Aime wrote:

Arne Kepp ha scritto:

Hi,

I am looking to integrate Chris Whitney's JTileCache (
http://whitney.textdriven.com/blog/2007/07/03/jtilecache-proxy-edition/
) into Geoserver.

Currently it is a separate servlet that communicates with Geoserver
through HTTP using the regular WMS interface. It would be nice to bring
it closer to Geoserver, so that it knows more about what layers are
available, what needs to be purged and so on.

My first attempt was to create a new community module with the code and
create a route for /geoserver/tilecache . But I wasn't able to find an
elegant way to make WMS requests, because invoking DefaultWebMapService
appears to require a getMapRequest, which in turn requires the actual
URL. After the dispatcher I can only seem to get my hands on a
org.restlet.Request, which is tricky to turn back into an URL.

A compromise I am leaning towards is to skip the dispatcher and keep
jtilecache separate, but pass WMS information in through
applicationContext. I am not sure whether requests for fresh tiles would
still be HTTP requests, or whether I could use the WMS functions directly.

Hard to help you out since I never tried to use JTileCache. Just as
starters, which protocol does it use? WMS? or TMS?
The best I think would be to create a new service for jtilecache and
have it use the WMS objects directly. Unfortunately the process
to create a new service is totally undocumented
(http://jira.codehaus.org/browse/GEOS-940), I had to do
"monkey see, monkey do" myself for the WCS 1.1.1 implementation I'm
working on. I can try to help you, but mail is not exactly the
easiest medium... it would be better to have that docs in the wiki, sigh...

Cheers
Andrea

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Geoserver-devel mailing list
Geoserver-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/geoserver-devel

I think communicating to GeoServer with the http using the regular WMS interface is the way to go. I don't think we want it too closely tied to GeoServer, and there's practically no performance win.

I'm not sure that in the long run we really want to get much information directly through the applicationContext. Like ideally we would communicate most of the information through WMS and perhaps REST interfaces. We want people to be able to easily deploy jtilecache on its own dedicated server, but also to be able to ship with it. But they should be able to have jtilecache and just point it at a GeoServer instance and vice versa, and have them communicate properly.

So first step would be to just get all the layers from the application context and cache them all by default (when wms is accessed through the jtilecache endpoint). Later that could maybe be done through a capabilities document.

After that we'd want to be able to configure layers on and off, and perhaps set some params. This should probably be done by getting a hold of the geoserver 'data directory', and writing to a folder there. I don't know that we've got a good coherent story on how to do that, but there are some other modules that do so.

After that you'd want to put a REST API on JTileCache to set those configurations. And then we could add hooks to the GeoServer UI, or perhaps directly through an openlayers application. GeoServer would assume a local jtilecache, but could then also be configured to point at one or more remote ones as well, to control their settings.

And then in to the future we'd add control of the cache, expiry and seeding and the like, through a REST API as well, that we would then hook up to GeoServer's transaction code.

Does that make sense? Basically what I'm saying is most all communication should go through REST and WMS, so we can distribute it easily. It should just be able to ship as a jar with geoserver, and persist its settings to the data_dir.

Chris

Arne Kepp wrote:

Hi,

I am looking to integrate Chris Whitney's JTileCache ( http://whitney.textdriven.com/blog/2007/07/03/jtilecache-proxy-edition/ ) into Geoserver.

Currently it is a separate servlet that communicates with Geoserver through HTTP using the regular WMS interface. It would be nice to bring it closer to Geoserver, so that it knows more about what layers are available, what needs to be purged and so on.

My first attempt was to create a new community module with the code and create a route for /geoserver/tilecache . But I wasn't able to find an elegant way to make WMS requests, because invoking DefaultWebMapService appears to require a getMapRequest, which in turn requires the actual URL. After the dispatcher I can only seem to get my hands on a org.restlet.Request, which is tricky to turn back into an URL.

A compromise I am leaning towards is to skip the dispatcher and keep jtilecache separate, but pass WMS information in through applicationContext. I am not sure whether requests for fresh tiles would still be HTTP requests, or whether I could use the WMS functions directly.

Do people have other suggestions on how to do this?
-Arne

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Geoserver-devel mailing list
Geoserver-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/geoserver-devel

!DSPAM:4005,474c5f4b152807180515871!

Also, note that geoserver has support for setting the industry-standard
cache-control headers. I strongly suggest that JTileCache be programmed
to support those parameters. Those cache-control headers are in-place
for a reason (even if that reason is squid right now!)

--saul

On Tue, 2007-11-27 at 18:30 -0500, Chris Holmes wrote:

I think communicating to GeoServer with the http using the regular WMS
interface is the way to go. I don't think we want it too closely tied
to GeoServer, and there's practically no performance win.

I'm not sure that in the long run we really want to get much information
directly through the applicationContext. Like ideally we would
communicate most of the information through WMS and perhaps REST
interfaces. We want people to be able to easily deploy jtilecache on
its own dedicated server, but also to be able to ship with it. But they
should be able to have jtilecache and just point it at a GeoServer
instance and vice versa, and have them communicate properly.

So first step would be to just get all the layers from the application
context and cache them all by default (when wms is accessed through the
jtilecache endpoint). Later that could maybe be done through a
capabilities document.

After that we'd want to be able to configure layers on and off, and
perhaps set some params. This should probably be done by getting a hold
of the geoserver 'data directory', and writing to a folder there. I
don't know that we've got a good coherent story on how to do that, but
there are some other modules that do so.

After that you'd want to put a REST API on JTileCache to set those
configurations. And then we could add hooks to the GeoServer UI, or
perhaps directly through an openlayers application. GeoServer would
assume a local jtilecache, but could then also be configured to point at
one or more remote ones as well, to control their settings.

And then in to the future we'd add control of the cache, expiry and
seeding and the like, through a REST API as well, that we would then
hook up to GeoServer's transaction code.

Does that make sense? Basically what I'm saying is most all
communication should go through REST and WMS, so we can distribute it
easily. It should just be able to ship as a jar with geoserver, and
persist its settings to the data_dir.

Chris

Arne Kepp wrote:
> Hi,
>
> I am looking to integrate Chris Whitney's JTileCache (
> http://whitney.textdriven.com/blog/2007/07/03/jtilecache-proxy-edition/
> ) into Geoserver.
>
> Currently it is a separate servlet that communicates with Geoserver
> through HTTP using the regular WMS interface. It would be nice to bring
> it closer to Geoserver, so that it knows more about what layers are
> available, what needs to be purged and so on.
>
> My first attempt was to create a new community module with the code and
> create a route for /geoserver/tilecache . But I wasn't able to find an
> elegant way to make WMS requests, because invoking DefaultWebMapService
> appears to require a getMapRequest, which in turn requires the actual
> URL. After the dispatcher I can only seem to get my hands on a
> org.restlet.Request, which is tricky to turn back into an URL.
>
> A compromise I am leaning towards is to skip the dispatcher and keep
> jtilecache separate, but pass WMS information in through
> applicationContext. I am not sure whether requests for fresh tiles would
> still be HTTP requests, or whether I could use the WMS functions directly.
>
> Do people have other suggestions on how to do this?
> -Arne
>
> -------------------------------------------------------------------------
> This SF.net email is sponsored by: Microsoft
> Defy all challenges. Microsoft(R) Visual Studio 2005.
> http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
> _______________________________________________
> Geoserver-devel mailing list
> Geoserver-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/geoserver-devel
>
> !DSPAM:4005,474c5f4b152807180515871!
>
-------------------------------------------------------------------------
SF.Net email is sponsored by: The Future of Linux Business White Paper
from Novell. From the desktop to the data center, Linux is going
mainstream. Let it simplify your IT future.
http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4
_______________________________________________ Geoserver-devel mailing list Geoserver-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/geoserver-devel

Oh yeah, I forgot that section in my email. With the new REST config api we should be able to read the cacheEnabled and cache time params from GeoServer.

Getting it from CacheEnabled makes a lot of sense to me. I'm less certain about using the timing stuff, as part of the reason for doing this is so we can be much smarter about expiry times. We want to hook it up to transactions, so that the cache expires right when the data changes. If we pass through long cache-control header times then clients won't get updates. I was thinking that JTileCache would use conditional GET in http so that clients only need to fetch a new image when it gets updated.

Though I suppose if a server is really sure that it's not going to be updated than a long expiry time is better than doing a ping every 5 minutes.

Chris

Saul Farber wrote:

Also, note that geoserver has support for setting the industry-standard
cache-control headers. I strongly suggest that JTileCache be programmed
to support those parameters. Those cache-control headers are in-place
for a reason (even if that reason is squid right now!)

--saul

On Tue, 2007-11-27 at 18:30 -0500, Chris Holmes wrote:

I think communicating to GeoServer with the http using the regular WMS interface is the way to go. I don't think we want it too closely tied to GeoServer, and there's practically no performance win.

I'm not sure that in the long run we really want to get much information directly through the applicationContext. Like ideally we would communicate most of the information through WMS and perhaps REST interfaces. We want people to be able to easily deploy jtilecache on its own dedicated server, but also to be able to ship with it. But they should be able to have jtilecache and just point it at a GeoServer instance and vice versa, and have them communicate properly.

So first step would be to just get all the layers from the application context and cache them all by default (when wms is accessed through the jtilecache endpoint). Later that could maybe be done through a capabilities document.

After that we'd want to be able to configure layers on and off, and perhaps set some params. This should probably be done by getting a hold of the geoserver 'data directory', and writing to a folder there. I don't know that we've got a good coherent story on how to do that, but there are some other modules that do so.

After that you'd want to put a REST API on JTileCache to set those configurations. And then we could add hooks to the GeoServer UI, or perhaps directly through an openlayers application. GeoServer would assume a local jtilecache, but could then also be configured to point at one or more remote ones as well, to control their settings.

And then in to the future we'd add control of the cache, expiry and seeding and the like, through a REST API as well, that we would then hook up to GeoServer's transaction code.

Does that make sense? Basically what I'm saying is most all communication should go through REST and WMS, so we can distribute it easily. It should just be able to ship as a jar with geoserver, and persist its settings to the data_dir.

Chris

Arne Kepp wrote:

Hi,

I am looking to integrate Chris Whitney's JTileCache ( http://whitney.textdriven.com/blog/2007/07/03/jtilecache-proxy-edition/ ) into Geoserver.

Currently it is a separate servlet that communicates with Geoserver through HTTP using the regular WMS interface. It would be nice to bring it closer to Geoserver, so that it knows more about what layers are available, what needs to be purged and so on.

My first attempt was to create a new community module with the code and create a route for /geoserver/tilecache . But I wasn't able to find an elegant way to make WMS requests, because invoking DefaultWebMapService appears to require a getMapRequest, which in turn requires the actual URL. After the dispatcher I can only seem to get my hands on a org.restlet.Request, which is tricky to turn back into an URL.

A compromise I am leaning towards is to skip the dispatcher and keep jtilecache separate, but pass WMS information in through applicationContext. I am not sure whether requests for fresh tiles would still be HTTP requests, or whether I could use the WMS functions directly.

Do people have other suggestions on how to do this?
-Arne

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Geoserver-devel mailing list
Geoserver-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/geoserver-devel

-------------------------------------------------------------------------
SF.Net email is sponsored by: The Future of Linux Business White Paper
from Novell. From the desktop to the data center, Linux is going
mainstream. Let it simplify your IT future.
http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4
_______________________________________________ Geoserver-devel mailing list Geoserver-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/geoserver-devel

!DSPAM:4005,474cad5714141849620573!

As a side note, I followed the JTilecache project during the summer on behalf of a customer.
Its a nice piece of work, and I think that being able to run the cache with a nice config UI would be really nice.
Given the headaches that has been reported on building a config GUI in struts however, might be a different issue.

To the point, when doing code reading and test-running JTilecache, I found that its a decent architecture with pluggable aproach to most options.
However, I found the below listed areas that needs attention for hardcore production use. ("proxy edition" is a nice description :-)).
1. Cache key Strageies isnt implemented
2. The internal representation of a tile is basically a BufferedImage.
3. Race condition in fetches

I did performance test JTilecache and found response times in the 20-40ms area for one user.
Given my project's requirements (disk based cache, no meta tiling, and timeframe of deployment)
I choose to write up a minimalistic clone of JTilecache with:
1. A suitable cache key generation where cache key is a filesystem path
2. An internal representation of a tile that's simply a File object.
3. No use of JCS for caching, hardcoded file caching.
4. A simple que of fetcher threads that eliminates race conditions.

All this renders response times for cache hits in the 1-5 ms area.
I just load-tested this and it scales very well, tested with up to 500 concurrent reqs in tomcat.

So my architectural input to cache design would be:
0. Make cache implementation pluggable (already beautifully implemented in JTileCache)
1. Make cache key stragegy pluggable
2. Make cache population thread safe / race condition safe.
3. Make internal tile representation a reference to data, not the data itself (BufferedImage).

I'd be more than happy to contribute my code, maybe just as an inspiration when actually fixing threaded fetchers :slight_smile:

Cheers
Per-Olof

Chris Holmes skrev:

Oh yeah, I forgot that section in my email. With the new REST config api we should be able to read the cacheEnabled and cache time params from GeoServer.

Getting it from CacheEnabled makes a lot of sense to me. I'm less certain about using the timing stuff, as part of the reason for doing this is so we can be much smarter about expiry times. We want to hook it up to transactions, so that the cache expires right when the data changes. If we pass through long cache-control header times then clients won't get updates. I was thinking that JTileCache would use conditional GET in http so that clients only need to fetch a new image when it gets updated.

Though I suppose if a server is really sure that it's not going to be updated than a long expiry time is better than doing a ping every 5 minutes.

Chris

Saul Farber wrote:

Also, note that geoserver has support for setting the industry-standard
cache-control headers. I strongly suggest that JTileCache be programmed
to support those parameters. Those cache-control headers are in-place
for a reason (even if that reason is squid right now!)

--saul

On Tue, 2007-11-27 at 18:30 -0500, Chris Holmes wrote:

I think communicating to GeoServer with the http using the regular WMS interface is the way to go. I don't think we want it too closely tied to GeoServer, and there's practically no performance win.

I'm not sure that in the long run we really want to get much information directly through the applicationContext. Like ideally we would communicate most of the information through WMS and perhaps REST interfaces. We want people to be able to easily deploy jtilecache on its own dedicated server, but also to be able to ship with it. But they should be able to have jtilecache and just point it at a GeoServer instance and vice versa, and have them communicate properly.

So first step would be to just get all the layers from the application context and cache them all by default (when wms is accessed through the jtilecache endpoint). Later that could maybe be done through a capabilities document.

After that we'd want to be able to configure layers on and off, and perhaps set some params. This should probably be done by getting a hold of the geoserver 'data directory', and writing to a folder there. I don't know that we've got a good coherent story on how to do that, but there are some other modules that do so.

After that you'd want to put a REST API on JTileCache to set those configurations. And then we could add hooks to the GeoServer UI, or perhaps directly through an openlayers application. GeoServer would assume a local jtilecache, but could then also be configured to point at one or more remote ones as well, to control their settings.

And then in to the future we'd add control of the cache, expiry and seeding and the like, through a REST API as well, that we would then hook up to GeoServer's transaction code.

Does that make sense? Basically what I'm saying is most all communication should go through REST and WMS, so we can distribute it easily. It should just be able to ship as a jar with geoserver, and persist its settings to the data_dir.

Chris

Arne Kepp wrote:

Hi,

I am looking to integrate Chris Whitney's JTileCache ( http://whitney.textdriven.com/blog/2007/07/03/jtilecache-proxy-edition/ ) into Geoserver.

Currently it is a separate servlet that communicates with Geoserver through HTTP using the regular WMS interface. It would be nice to bring it closer to Geoserver, so that it knows more about what layers are available, what needs to be purged and so on.

My first attempt was to create a new community module with the code and create a route for /geoserver/tilecache . But I wasn't able to find an elegant way to make WMS requests, because invoking DefaultWebMapService appears to require a getMapRequest, which in turn requires the actual URL. After the dispatcher I can only seem to get my hands on a org.restlet.Request, which is tricky to turn back into an URL.

A compromise I am leaning towards is to skip the dispatcher and keep jtilecache separate, but pass WMS information in through applicationContext. I am not sure whether requests for fresh tiles would still be HTTP requests, or whether I could use the WMS functions directly.

Do people have other suggestions on how to do this?
-Arne

-------------------------------------------------------------------------

This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Geoserver-devel mailing list
Geoserver-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/geoserver-devel

-------------------------------------------------------------------------

SF.Net email is sponsored by: The Future of Linux Business White Paper
from Novell. From the desktop to the data center, Linux is going
mainstream. Let it simplify your IT future.
http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4
_______________________________________________ Geoserver-devel mailing list Geoserver-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/geoserver-devel

!DSPAM:4005,474cad5714141849620573!

------------------------------------------------------------------------

-------------------------------------------------------------------------
SF.Net email is sponsored by: The Future of Linux Business White Paper
from Novell. From the desktop to the data center, Linux is going
mainstream. Let it simplify your IT future.
http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4
------------------------------------------------------------------------

_______________________________________________
Geoserver-devel mailing list
Geoserver-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/geoserver-devel
  

Per-Olof Norén ha scritto:
...

I did performance test JTilecache and found response times in the 20-40ms area for one user.
Given my project's requirements (disk based cache, no meta tiling, and timeframe of deployment)
I choose to write up a minimalistic clone of JTilecache with:
1. A suitable cache key generation where cache key is a filesystem path
2. An internal representation of a tile that's simply a File object.
3. No use of JCS for caching, hardcoded file caching.
4. A simple que of fetcher threads that eliminates race conditions.

All this renders response times for cache hits in the 1-5 ms area.
I just load-tested this and it scales very well, tested with up to 500 concurrent reqs in tomcat.

Hum, very interesting. Can you open a jira issue an attach your work to
it for everybody interested to see?
Cheers
Andrea

Thanks for the write-up.

3. Make internal tile representation a reference to data, not the data
itself (BufferedImage).

This is the next step. When I started the project, I imagined that the cache could transcode images (i.e accept png from the WMS and output jpeg). The goal was a little unrealistic for the scope of the project, and slowed the cache down. Based on profiling work I did, removing that "feature" (essentially what you suggested), should cause a considerable speed-up.

I agree that a nice configuration and cache viewer UI would be very beneficial.

Please contribute your code, I would be happy to look it over. If you would like, I can also setup a sandbox in the JTileCache repository for you to commit any patches or new code.

Thanks,
Chris Whitney

On Nov 27, 2007, at 11:30 PM, Per-Olof Norén wrote:

As a side note, I followed the JTilecache project during the summer on
behalf of a customer.
Its a nice piece of work, and I think that being able to run the cache
with a nice config UI would be really nice.
Given the headaches that has been reported on building a config GUI in
struts however, might be a different issue.

To the point, when doing code reading and test-running JTilecache, I
found that its a decent architecture with pluggable aproach to most options.
However, I found the below listed areas that needs attention for
hardcore production use. ("proxy edition" is a nice description :-)).
1. Cache key Strageies isnt implemented
2. The internal representation of a tile is basically a BufferedImage.
3. Race condition in fetches

I did performance test JTilecache and found response times in the
20-40ms area for one user.
Given my project's requirements (disk based cache, no meta tiling, and
timeframe of deployment)
I choose to write up a minimalistic clone of JTilecache with:
1. A suitable cache key generation where cache key is a filesystem path
2. An internal representation of a tile that's simply a File object.
3. No use of JCS for caching, hardcoded file caching.
4. A simple que of fetcher threads that eliminates race conditions.

All this renders response times for cache hits in the 1-5 ms area.
I just load-tested this and it scales very well, tested with up to 500
concurrent reqs in tomcat.

So my architectural input to cache design would be:
0. Make cache implementation pluggable (already beautifully implemented
in JTileCache)
1. Make cache key stragegy pluggable
2. Make cache population thread safe / race condition safe.
3. Make internal tile representation a reference to data, not the data
itself (BufferedImage).

I'd be more than happy to contribute my code, maybe just as an
inspiration when actually fixing threaded fetchers :slight_smile:

Cheers
Per-Olof

Chris Holmes skrev:

Oh yeah, I forgot that section in my email. With the new REST config
api we should be able to read the cacheEnabled and cache time params
from GeoServer.

Getting it from CacheEnabled makes a lot of sense to me. I'm less
certain about using the timing stuff, as part of the reason for doing
this is so we can be much smarter about expiry times. We want to hook
it up to transactions, so that the cache expires right when the data
changes. If we pass through long cache-control header times then
clients won't get updates. I was thinking that JTileCache would use
conditional GET in http so that clients only need to fetch a new image
when it gets updated.

Though I suppose if a server is really sure that it's not going to be
updated than a long expiry time is better than doing a ping every 5
minutes.

Chris

Saul Farber wrote:

Also, note that geoserver has support for setting the industry-standard
cache-control headers. I strongly suggest that JTileCache be programmed
to support those parameters. Those cache-control headers are in-place
for a reason (even if that reason is squid right now!)

--saul

On Tue, 2007-11-27 at 18:30 -0500, Chris Holmes wrote:

I think communicating to GeoServer with the http using the regular
WMS interface is the way to go. I don't think we want it too
closely tied to GeoServer, and there's practically no performance win.

I'm not sure that in the long run we really want to get much
information directly through the applicationContext. Like ideally
we would communicate most of the information through WMS and perhaps
REST interfaces. We want people to be able to easily deploy
jtilecache on its own dedicated server, but also to be able to ship
with it. But they should be able to have jtilecache and just point
it at a GeoServer instance and vice versa, and have them communicate
properly.

So first step would be to just get all the layers from the
application context and cache them all by default (when wms is
accessed through the jtilecache endpoint). Later that could maybe
be done through a capabilities document.

After that we'd want to be able to configure layers on and off, and
perhaps set some params. This should probably be done by getting a
hold of the geoserver 'data directory', and writing to a folder
there. I don't know that we've got a good coherent story on how to
do that, but there are some other modules that do so.

After that you'd want to put a REST API on JTileCache to set those
configurations. And then we could add hooks to the GeoServer UI, or
perhaps directly through an openlayers application. GeoServer would
assume a local jtilecache, but could then also be configured to
point at one or more remote ones as well, to control their settings.

And then in to the future we'd add control of the cache, expiry and
seeding and the like, through a REST API as well, that we would then
hook up to GeoServer's transaction code.

Does that make sense? Basically what I'm saying is most all
communication should go through REST and WMS, so we can distribute
it easily. It should just be able to ship as a jar with geoserver,
and persist its settings to the data_dir.

Chris

Arne Kepp wrote:

Hi,

I am looking to integrate Chris Whitney's JTileCache (
http://whitney.textdriven.com/blog/2007/07/03/jtilecache-proxy-edition/
) into Geoserver.

Currently it is a separate servlet that communicates with Geoserver
through HTTP using the regular WMS interface. It would be nice to
bring it closer to Geoserver, so that it knows more about what
layers are available, what needs to be purged and so on.

My first attempt was to create a new community module with the code
and create a route for /geoserver/tilecache . But I wasn't able to
find an elegant way to make WMS requests, because invoking
DefaultWebMapService appears to require a getMapRequest, which in
turn requires the actual URL. After the dispatcher I can only seem
to get my hands on a org.restlet.Request, which is tricky to turn
back into an URL.

A compromise I am leaning towards is to skip the dispatcher and
keep jtilecache separate, but pass WMS information in through
applicationContext. I am not sure whether requests for fresh tiles
would still be HTTP requests, or whether I could use the WMS
functions directly.

Do people have other suggestions on how to do this?
-Arne

-------------------------------------------------------------------------

This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Geoserver-devel mailing list
Geoserver-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/geoserver-devel

-------------------------------------------------------------------------

SF.Net email is sponsored by: The Future of Linux Business White Paper
from Novell. From the desktop to the data center, Linux is going
mainstream. Let it simplify your IT future.
http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4
_______________________________________________ Geoserver-devel
mailing list Geoserver-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/geoserver-devel

!DSPAM:4005,474cad5714141849620573!

------------------------------------------------------------------------

-------------------------------------------------------------------------
SF.Net email is sponsored by: The Future of Linux Business White Paper
from Novell. From the desktop to the data center, Linux is going
mainstream. Let it simplify your IT future.
http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4
------------------------------------------------------------------------

_______________________________________________
Geoserver-devel mailing list
Geoserver-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/geoserver-devel

-------------------------------------------------------------------------
SF.Net email is sponsored by: The Future of Linux Business White Paper
from Novell. From the desktop to the data center, Linux is going
mainstream. Let it simplify your IT future.
http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4
_______________________________________________
Geoserver-devel mailing list
Geoserver-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/geoserver-devel

Chris Whitney ha scritto:

Thanks for the write-up.

3. Make internal tile representation a reference to data, not the data
itself (BufferedImage).

Hi Chris,
I guess to incorporate JTileCache in another program one would need:
* programmatic access to its configuration (or a pluggable configuration)
* programmatic access to the tile cache service (afaik you already have
   that)
* a pluggable way to actually draw the maps. In a separate jtilecache
   one would use a module that does wms calls, in an integrated one
   we can call the geoserver map drawing objects directly.

Opinions?
Also, what's your idea about the future of jtilecache? Should we
try to keep it a separate project that someone will mantain?
By copying jtilecache sources inside GeoServer we're effectively
forking it.

Cheers
Andrea

That would be very cool, can you put it up somewhere?

I agree with your ideas, we'll try to make that happen.

Thanks for the input :slight_smile:
-Arne

Per-Olof Norén wrote:

As a side note, I followed the JTilecache project during the summer on behalf of a customer.
Its a nice piece of work, and I think that being able to run the cache with a nice config UI would be really nice.
Given the headaches that has been reported on building a config GUI in struts however, might be a different issue.

To the point, when doing code reading and test-running JTilecache, I found that its a decent architecture with pluggable aproach to most options.
However, I found the below listed areas that needs attention for hardcore production use. ("proxy edition" is a nice description :-)).
1. Cache key Strageies isnt implemented
2. The internal representation of a tile is basically a BufferedImage.
3. Race condition in fetches

I did performance test JTilecache and found response times in the 20-40ms area for one user.
Given my project's requirements (disk based cache, no meta tiling, and timeframe of deployment)
I choose to write up a minimalistic clone of JTilecache with:
1. A suitable cache key generation where cache key is a filesystem path
2. An internal representation of a tile that's simply a File object.
3. No use of JCS for caching, hardcoded file caching.
4. A simple que of fetcher threads that eliminates race conditions.

All this renders response times for cache hits in the 1-5 ms area.
I just load-tested this and it scales very well, tested with up to 500 concurrent reqs in tomcat.

So my architectural input to cache design would be:
0. Make cache implementation pluggable (already beautifully implemented in JTileCache)
1. Make cache key stragegy pluggable
2. Make cache population thread safe / race condition safe.
3. Make internal tile representation a reference to data, not the data itself (BufferedImage).

I'd be more than happy to contribute my code, maybe just as an inspiration when actually fixing threaded fetchers :slight_smile:

Cheers
Per-Olof

Chris Holmes skrev:
  

Oh yeah, I forgot that section in my email. With the new REST config api we should be able to read the cacheEnabled and cache time params from GeoServer.

Getting it from CacheEnabled makes a lot of sense to me. I'm less certain about using the timing stuff, as part of the reason for doing this is so we can be much smarter about expiry times. We want to hook it up to transactions, so that the cache expires right when the data changes. If we pass through long cache-control header times then clients won't get updates. I was thinking that JTileCache would use conditional GET in http so that clients only need to fetch a new image when it gets updated.

Though I suppose if a server is really sure that it's not going to be updated than a long expiry time is better than doing a ping every 5 minutes.

Chris

Saul Farber wrote:
    

Also, note that geoserver has support for setting the industry-standard
cache-control headers. I strongly suggest that JTileCache be programmed
to support those parameters. Those cache-control headers are in-place
for a reason (even if that reason is squid right now!)

--saul

On Tue, 2007-11-27 at 18:30 -0500, Chris Holmes wrote:
      

I think communicating to GeoServer with the http using the regular WMS interface is the way to go. I don't think we want it too closely tied to GeoServer, and there's practically no performance win.

I'm not sure that in the long run we really want to get much information directly through the applicationContext. Like ideally we would communicate most of the information through WMS and perhaps REST interfaces. We want people to be able to easily deploy jtilecache on its own dedicated server, but also to be able to ship with it. But they should be able to have jtilecache and just point it at a GeoServer instance and vice versa, and have them communicate properly.

So first step would be to just get all the layers from the application context and cache them all by default (when wms is accessed through the jtilecache endpoint). Later that could maybe be done through a capabilities document.

After that we'd want to be able to configure layers on and off, and perhaps set some params. This should probably be done by getting a hold of the geoserver 'data directory', and writing to a folder there. I don't know that we've got a good coherent story on how to do that, but there are some other modules that do so.

After that you'd want to put a REST API on JTileCache to set those configurations. And then we could add hooks to the GeoServer UI, or perhaps directly through an openlayers application. GeoServer would assume a local jtilecache, but could then also be configured to point at one or more remote ones as well, to control their settings.

And then in to the future we'd add control of the cache, expiry and seeding and the like, through a REST API as well, that we would then hook up to GeoServer's transaction code.

Does that make sense? Basically what I'm saying is most all communication should go through REST and WMS, so we can distribute it easily. It should just be able to ship as a jar with geoserver, and persist its settings to the data_dir.

Chris

Arne Kepp wrote:
        

Hi,

I am looking to integrate Chris Whitney's JTileCache ( http://whitney.textdriven.com/blog/2007/07/03/jtilecache-proxy-edition/ ) into Geoserver.

Currently it is a separate servlet that communicates with Geoserver through HTTP using the regular WMS interface. It would be nice to bring it closer to Geoserver, so that it knows more about what layers are available, what needs to be purged and so on.

My first attempt was to create a new community module with the code and create a route for /geoserver/tilecache . But I wasn't able to find an elegant way to make WMS requests, because invoking DefaultWebMapService appears to require a getMapRequest, which in turn requires the actual URL. After the dispatcher I can only seem to get my hands on a org.restlet.Request, which is tricky to turn back into an URL.

A compromise I am leaning towards is to skip the dispatcher and keep jtilecache separate, but pass WMS information in through applicationContext. I am not sure whether requests for fresh tiles would still be HTTP requests, or whether I could use the WMS functions directly.

Do people have other suggestions on how to do this?
-Arne

-------------------------------------------------------------------------

This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Geoserver-devel mailing list
Geoserver-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/geoserver-devel

-------------------------------------------------------------------------

SF.Net email is sponsored by: The Future of Linux Business White Paper
from Novell. From the desktop to the data center, Linux is going
mainstream. Let it simplify your IT future.
http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4
_______________________________________________ Geoserver-devel mailing list Geoserver-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/geoserver-devel
        

------------------------------------------------------------------------

-------------------------------------------------------------------------
SF.Net email is sponsored by: The Future of Linux Business White Paper
from Novell. From the desktop to the data center, Linux is going
mainstream. Let it simplify your IT future.
http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4
------------------------------------------------------------------------

_______________________________________________
Geoserver-devel mailing list
Geoserver-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/geoserver-devel
  
-------------------------------------------------------------------------
SF.Net email is sponsored by: The Future of Linux Business White Paper
from Novell. From the desktop to the data center, Linux is going
mainstream. Let it simplify your IT future.
http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4
_______________________________________________
Geoserver-devel mailing list
Geoserver-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/geoserver-devel

!DSPAM:4038,474d196b138635219720167!

I agree with Chris Holmes' ideas about the future of the project. Mainly, it would keep the code from being too closely tied to Geoserver while allowing an open configuration and cache expiring interface, which is what Geoserver (or any other WMS) would need:

Chris Holmes:
After that you'd want to put a REST API on JTileCache to set those configurations. And then we could add hooks to the GeoServer UI, or perhaps directly through an openlayers application.
...
And then in to the future we'd add control of the cache, expiry and seeding and the like, through a REST API as well, that we would then hook up to GeoServer's transaction code.
...
Does that make sense? Basically what I'm saying is most all communication should go through REST and WMS, so we can distribute it easily. It should just be able to ship as a jar with geoserver, and persist its settings to the data_dir.

In response to you question about maintenance-- I'm fine with the source moving into Geoserver's repository if that is the consensus. Summer of Code intended the project to be a sub-project of Geoserver, so I would not see that move as a fork. Google Code hosting was easier for me to setup the project initially (rather than having to get commit access to Geoserver), however, it might not be the best place for the project to stay.

-- Chris Whitney

On Nov 28, 2007, at 6:14 AM, Andrea Aime wrote:

Chris Whitney ha scritto:

Thanks for the write-up.

3. Make internal tile representation a reference to data, not the data
itself (BufferedImage).

Hi Chris,
I guess to incorporate JTileCache in another program one would need:
* programmatic access to its configuration (or a pluggable configuration)
* programmatic access to the tile cache service (afaik you already have
that)
* a pluggable way to actually draw the maps. In a separate jtilecache
one would use a module that does wms calls, in an integrated one
we can call the geoserver map drawing objects directly.

Opinions?
Also, what's your idea about the future of jtilecache? Should we
try to keep it a separate project that someone will mantain?
By copying jtilecache sources inside GeoServer we're effectively
forking it.

Cheers
Andrea

Yes, the plan is to attach sources to a newly created geoserver jira feature request, as Andrea suggested.
I just need to check to see that there is no code ownership issue involved tomorrow and then its out there.
I realised when looking into the python TileCache that there is some serious "snap-to-resolutions-grid" going on there.
What i wrote is sort-of an experiment gone semi-production, lacking all this snap-to-grid functions and a proper architecture and error handling design.
I consider it performance-wise inspiration for a proper implementation :slight_smile:

Cheers,
Per-Olof

Arne Kepp skrev:

That would be very cool, can you put it up somewhere?

I agree with your ideas, we'll try to make that happen.

Thanks for the input :slight_smile:
-Arne

Per-Olof Norén wrote:

As a side note, I followed the JTilecache project during the summer on behalf of a customer.
Its a nice piece of work, and I think that being able to run the cache with a nice config UI would be really nice.
Given the headaches that has been reported on building a config GUI in struts however, might be a different issue.

To the point, when doing code reading and test-running JTilecache, I found that its a decent architecture with pluggable aproach to most options.
However, I found the below listed areas that needs attention for hardcore production use. ("proxy edition" is a nice description :-)).
1. Cache key Strageies isnt implemented
2. The internal representation of a tile is basically a BufferedImage.
3. Race condition in fetches

I did performance test JTilecache and found response times in the 20-40ms area for one user.
Given my project's requirements (disk based cache, no meta tiling, and timeframe of deployment)
I choose to write up a minimalistic clone of JTilecache with:
1. A suitable cache key generation where cache key is a filesystem path
2. An internal representation of a tile that's simply a File object.
3. No use of JCS for caching, hardcoded file caching.
4. A simple que of fetcher threads that eliminates race conditions.

All this renders response times for cache hits in the 1-5 ms area.
I just load-tested this and it scales very well, tested with up to 500 concurrent reqs in tomcat.

So my architectural input to cache design would be:
0. Make cache implementation pluggable (already beautifully implemented in JTileCache)
1. Make cache key stragegy pluggable
2. Make cache population thread safe / race condition safe.
3. Make internal tile representation a reference to data, not the data itself (BufferedImage).

I'd be more than happy to contribute my code, maybe just as an inspiration when actually fixing threaded fetchers :slight_smile:

Cheers
Per-Olof

Chris Holmes skrev:

Oh yeah, I forgot that section in my email. With the new REST config api we should be able to read the cacheEnabled and cache time params from GeoServer.

Getting it from CacheEnabled makes a lot of sense to me. I'm less certain about using the timing stuff, as part of the reason for doing this is so we can be much smarter about expiry times. We want to hook it up to transactions, so that the cache expires right when the data changes. If we pass through long cache-control header times then clients won't get updates. I was thinking that JTileCache would use conditional GET in http so that clients only need to fetch a new image when it gets updated.

Though I suppose if a server is really sure that it's not going to be updated than a long expiry time is better than doing a ping every 5 minutes.

Chris

Saul Farber wrote:
   

Also, note that geoserver has support for setting the industry-standard
cache-control headers. I strongly suggest that JTileCache be programmed
to support those parameters. Those cache-control headers are in-place
for a reason (even if that reason is squid right now!)

--saul

On Tue, 2007-11-27 at 18:30 -0500, Chris Holmes wrote:
     

I think communicating to GeoServer with the http using the regular WMS interface is the way to go. I don't think we want it too closely tied to GeoServer, and there's practically no performance win.

I'm not sure that in the long run we really want to get much information directly through the applicationContext. Like ideally we would communicate most of the information through WMS and perhaps REST interfaces. We want people to be able to easily deploy jtilecache on its own dedicated server, but also to be able to ship with it. But they should be able to have jtilecache and just point it at a GeoServer instance and vice versa, and have them communicate properly.

So first step would be to just get all the layers from the application context and cache them all by default (when wms is accessed through the jtilecache endpoint). Later that could maybe be done through a capabilities document.

After that we'd want to be able to configure layers on and off, and perhaps set some params. This should probably be done by getting a hold of the geoserver 'data directory', and writing to a folder there. I don't know that we've got a good coherent story on how to do that, but there are some other modules that do so.

After that you'd want to put a REST API on JTileCache to set those configurations. And then we could add hooks to the GeoServer UI, or perhaps directly through an openlayers application. GeoServer would assume a local jtilecache, but could then also be configured to point at one or more remote ones as well, to control their settings.

And then in to the future we'd add control of the cache, expiry and seeding and the like, through a REST API as well, that we would then hook up to GeoServer's transaction code.

Does that make sense? Basically what I'm saying is most all communication should go through REST and WMS, so we can distribute it easily. It should just be able to ship as a jar with geoserver, and persist its settings to the data_dir.

Chris

Arne Kepp wrote:
       

Hi,

I am looking to integrate Chris Whitney's JTileCache ( http://whitney.textdriven.com/blog/2007/07/03/jtilecache-proxy-edition/ ) into Geoserver.

Currently it is a separate servlet that communicates with Geoserver through HTTP using the regular WMS interface. It would be nice to bring it closer to Geoserver, so that it knows more about what layers are available, what needs to be purged and so on.

My first attempt was to create a new community module with the code and create a route for /geoserver/tilecache . But I wasn't able to find an elegant way to make WMS requests, because invoking DefaultWebMapService appears to require a getMapRequest, which in turn requires the actual URL. After the dispatcher I can only seem to get my hands on a org.restlet.Request, which is tricky to turn back into an URL.

A compromise I am leaning towards is to skip the dispatcher and keep jtilecache separate, but pass WMS information in through applicationContext. I am not sure whether requests for fresh tiles would still be HTTP requests, or whether I could use the WMS functions directly.

Do people have other suggestions on how to do this?
-Arne

-------------------------------------------------------------------------

This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Geoserver-devel mailing list
Geoserver-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/geoserver-devel

-------------------------------------------------------------------------

SF.Net email is sponsored by: The Future of Linux Business White Paper
from Novell. From the desktop to the data center, Linux is going
mainstream. Let it simplify your IT future.
http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4
_______________________________________________ Geoserver-devel mailing list Geoserver-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/geoserver-devel
        

------------------------------------------------------------------------

-------------------------------------------------------------------------

SF.Net email is sponsored by: The Future of Linux Business White Paper
from Novell. From the desktop to the data center, Linux is going
mainstream. Let it simplify your IT future.
http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4
------------------------------------------------------------------------

_______________________________________________
Geoserver-devel mailing list
Geoserver-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/geoserver-devel
      
-------------------------------------------------------------------------

SF.Net email is sponsored by: The Future of Linux Business White Paper
from Novell. From the desktop to the data center, Linux is going
mainstream. Let it simplify your IT future.
http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4
_______________________________________________
Geoserver-devel mailing list
Geoserver-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/geoserver-devel

!DSPAM:4038,474d196b138635219720167!

Hi again,

I Just posted a JIRA ticket, as promised.
http://jira.codehaus.org/browse/GEOS-1564

If time allows, I'll make a stab at trying to incorporate the
basic ideas against JTileCache svn, which would allow for
a patch-set to be applied either in a sandbox (as Chris suggested) or trunk.

Is there a geoserver / JTileCache roadmap (apart from the SoC specs) in writing somewhere?

Cheers,
Per-Olof

Per-Olof Norén skrev:

Yes, the plan is to attach sources to a newly created geoserver jira feature request, as Andrea suggested.
I just need to check to see that there is no code ownership issue involved tomorrow and then its out there.
I realised when looking into the python TileCache that there is some serious "snap-to-resolutions-grid" going on there.
What i wrote is sort-of an experiment gone semi-production, lacking all this snap-to-grid functions and a proper architecture and error handling design.
I consider it performance-wise inspiration for a proper implementation :slight_smile:

Cheers,
Per-Olof

Arne Kepp skrev:
  

That would be very cool, can you put it up somewhere?

I agree with your ideas, we'll try to make that happen.

Thanks for the input :slight_smile:
-Arne

Per-Olof Norén wrote:
    

As a side note, I followed the JTilecache project during the summer on behalf of a customer.
Its a nice piece of work, and I think that being able to run the cache with a nice config UI would be really nice.
Given the headaches that has been reported on building a config GUI in struts however, might be a different issue.

To the point, when doing code reading and test-running JTilecache, I found that its a decent architecture with pluggable aproach to most options.
However, I found the below listed areas that needs attention for hardcore production use. ("proxy edition" is a nice description :-)).
1. Cache key Strageies isnt implemented
2. The internal representation of a tile is basically a BufferedImage.
3. Race condition in fetches

I did performance test JTilecache and found response times in the 20-40ms area for one user.
Given my project's requirements (disk based cache, no meta tiling, and timeframe of deployment)
I choose to write up a minimalistic clone of JTilecache with:
1. A suitable cache key generation where cache key is a filesystem path
2. An internal representation of a tile that's simply a File object.
3. No use of JCS for caching, hardcoded file caching.
4. A simple que of fetcher threads that eliminates race conditions.

All this renders response times for cache hits in the 1-5 ms area.
I just load-tested this and it scales very well, tested with up to 500 concurrent reqs in tomcat.

So my architectural input to cache design would be:
0. Make cache implementation pluggable (already beautifully implemented in JTileCache)
1. Make cache key stragegy pluggable
2. Make cache population thread safe / race condition safe.
3. Make internal tile representation a reference to data, not the data itself (BufferedImage).

I'd be more than happy to contribute my code, maybe just as an inspiration when actually fixing threaded fetchers :slight_smile:

Cheers
Per-Olof

Chris Holmes skrev:

Oh yeah, I forgot that section in my email. With the new REST config api we should be able to read the cacheEnabled and cache time params from GeoServer.

Getting it from CacheEnabled makes a lot of sense to me. I'm less certain about using the timing stuff, as part of the reason for doing this is so we can be much smarter about expiry times. We want to hook it up to transactions, so that the cache expires right when the data changes. If we pass through long cache-control header times then clients won't get updates. I was thinking that JTileCache would use conditional GET in http so that clients only need to fetch a new image when it gets updated.

Though I suppose if a server is really sure that it's not going to be updated than a long expiry time is better than doing a ping every 5 minutes.

Chris

Saul Farber wrote:
   

Also, note that geoserver has support for setting the industry-standard
cache-control headers. I strongly suggest that JTileCache be programmed
to support those parameters. Those cache-control headers are in-place
for a reason (even if that reason is squid right now!)

--saul

On Tue, 2007-11-27 at 18:30 -0500, Chris Holmes wrote:
     

I think communicating to GeoServer with the http using the regular WMS interface is the way to go. I don't think we want it too closely tied to GeoServer, and there's practically no performance win.

I'm not sure that in the long run we really want to get much information directly through the applicationContext. Like ideally we would communicate most of the information through WMS and perhaps REST interfaces. We want people to be able to easily deploy jtilecache on its own dedicated server, but also to be able to ship with it. But they should be able to have jtilecache and just point it at a GeoServer instance and vice versa, and have them communicate properly.

So first step would be to just get all the layers from the application context and cache them all by default (when wms is accessed through the jtilecache endpoint). Later that could maybe be done through a capabilities document.

After that we'd want to be able to configure layers on and off, and perhaps set some params. This should probably be done by getting a hold of the geoserver 'data directory', and writing to a folder there. I don't know that we've got a good coherent story on how to do that, but there are some other modules that do so.

After that you'd want to put a REST API on JTileCache to set those configurations. And then we could add hooks to the GeoServer UI, or perhaps directly through an openlayers application. GeoServer would assume a local jtilecache, but could then also be configured to point at one or more remote ones as well, to control their settings.

And then in to the future we'd add control of the cache, expiry and seeding and the like, through a REST API as well, that we would then hook up to GeoServer's transaction code.

Does that make sense? Basically what I'm saying is most all communication should go through REST and WMS, so we can distribute it easily. It should just be able to ship as a jar with geoserver, and persist its settings to the data_dir.

Chris

Arne Kepp wrote:
       

Hi,

I am looking to integrate Chris Whitney's JTileCache ( http://whitney.textdriven.com/blog/2007/07/03/jtilecache-proxy-edition/ ) into Geoserver.

Currently it is a separate servlet that communicates with Geoserver through HTTP using the regular WMS interface. It would be nice to bring it closer to Geoserver, so that it knows more about what layers are available, what needs to be purged and so on.

My first attempt was to create a new community module with the code and create a route for /geoserver/tilecache . But I wasn't able to find an elegant way to make WMS requests, because invoking DefaultWebMapService appears to require a getMapRequest, which in turn requires the actual URL. After the dispatcher I can only seem to get my hands on a org.restlet.Request, which is tricky to turn back into an URL.

A compromise I am leaning towards is to skip the dispatcher and keep jtilecache separate, but pass WMS information in through applicationContext. I am not sure whether requests for fresh tiles would still be HTTP requests, or whether I could use the WMS functions directly.

Do people have other suggestions on how to do this?
-Arne

----------------------------------------------

Thanks Per,

there's no real roadmap at this point, I will try to assemble a roadmap based the feedback from everyone in the RnD section of Geoservers wiki later today or Monday.

We also need to decide where the code should live, continue in Google's repository or maybe on SourceForge.

I have already made some changes (replaced ImageTile with RawTile and improved streaming when til was not cached). This brought the response time down to less than 2 ms (using the JCS backend). I'll check that in once we know where the code will live.

-Arne

Per-Olof Norén wrote:

Hi again,

I Just posted a JIRA ticket, as promised.
http://jira.codehaus.org/browse/GEOS-1564

If time allows, I'll make a stab at trying to incorporate the
basic ideas against JTileCache svn, which would allow for
a patch-set to be applied either in a sandbox (as Chris suggested) or trunk.

Is there a geoserver / JTileCache roadmap (apart from the SoC specs) in writing somewhere?

Cheers,
Per-Olof

Per-Olof Norén skrev:
  

Yes, the plan is to attach sources to a newly created geoserver jira feature request, as Andrea suggested.
I just need to check to see that there is no code ownership issue involved tomorrow and then its out there.
I realised when looking into the python TileCache that there is some serious "snap-to-resolutions-grid" going on there.
What i wrote is sort-of an experiment gone semi-production, lacking all this snap-to-grid functions and a proper architecture and error handling design.
I consider it performance-wise inspiration for a proper implementation :slight_smile:

Cheers,
Per-Olof

Arne Kepp skrev:
  

That would be very cool, can you put it up somewhere?

I agree with your ideas, we'll try to make that happen.

Thanks for the input :slight_smile:
-Arne

Per-Olof Norén wrote:
    

As a side note, I followed the JTilecache project during the summer on behalf of a customer.
Its a nice piece of work, and I think that being able to run the cache with a nice config UI would be really nice.
Given the headaches that has been reported on building a config GUI in struts however, might be a different issue.

To the point, when doing code reading and test-running JTilecache, I found that its a decent architecture with pluggable aproach to most options.
However, I found the below listed areas that needs attention for hardcore production use. ("proxy edition" is a nice description :-)).
1. Cache key Strageies isnt implemented
2. The internal representation of a tile is basically a BufferedImage.
3. Race condition in fetches

I did performance test JTilecache and found response times in the 20-40ms area for one user.
Given my project's requirements (disk based cache, no meta tiling, and timeframe of deployment)
I choose to write up a minimalistic clone of JTilecache with:
1. A suitable cache key generation where cache key is a filesystem path
2. An internal representation of a tile that's simply a File object.
3. No use of JCS for caching, hardcoded file caching.
4. A simple que of fetcher threads that eliminates race conditions.

All this renders response times for cache hits in the 1-5 ms area.
I just load-tested this and it scales very well, tested with up to 500 concurrent reqs in tomcat.

So my architectural input to cache design would be:
0. Make cache implementation pluggable (already beautifully implemented in JTileCache)
1. Make cache key stragegy pluggable
2. Make cache population thread safe / race condition safe.
3. Make internal tile representation a reference to data, not the data itself (BufferedImage).

I'd be more than happy to contribute my code, maybe just as an inspiration when actually fixing threaded fetchers :slight_smile:

Cheers
Per-Olof

Chris Holmes skrev:

Oh yeah, I forgot that section in my email. With the new REST config api we should be able to read the cacheEnabled and cache time params from GeoServer.

Getting it from CacheEnabled makes a lot of sense to me. I'm less certain about using the timing stuff, as part of the reason for doing this is so we can be much smarter about expiry times. We want to hook it up to transactions, so that the cache expires right when the data changes. If we pass through long cache-control header times then clients won't get updates. I was thinking that JTileCache would use conditional GET in http so that clients only need to fetch a new image when it gets updated.

Though I suppose if a server is really sure that it's not going to be updated than a long expiry time is better than doing a ping every 5 minutes.

Chris

Saul Farber wrote:
   

Also, note that geoserver has support for setting the industry-standard
cache-control headers. I strongly suggest that JTileCache be programmed
to support those parameters. Those cache-control headers are in-place
for a reason (even if that reason is squid right now!)

--saul

On Tue, 2007-11-27 at 18:30 -0500, Chris Holmes wrote:
     

I think communicating to GeoServer with the http using the regular WMS interface is the way to go. I don't think we want it too closely tied to GeoServer, and there's practically no performance win.

I'm not sure that in the long run we really want to get much information directly through the applicationContext. Like ideally we would communicate most of the information through WMS and perhaps REST interfaces. We want people to be able to easily deploy jtilecache on its own dedicated server, but also to be able to ship with it. But they should be able to have jtilecache and just point it at a GeoServer instance and vice versa, and have them communicate properly.

So first step would be to just get all the layers from the application context and cache them all by default (when wms is accessed through the jtilecache endpoint). Later that could maybe be done through a capabilities document.

After that we'd want to be able to configure layers on and off, and perhaps set some params. This should probably be done by getting a hold of the geoserver 'data directory', and writing to a folder there. I don't know that we've got a good coherent story on how to do that, but there are some other modules that do so.

After that you'd want to put a REST API on JTileCache to set those configurations. And then we could add hooks to the GeoServer UI, or perhaps directly through an openlayers application. GeoServer would assume a local jtilecache, but could then also be configured to point at one or more remote ones as well, to control their settings.

And then in to the future we'd add control of the cache, expiry and seeding and the like, through a REST API as well, that we would then hook up to GeoServer's transaction code.

Does that make sense? Basically what I'm saying is most all communication should go through REST and WMS, so we can distribute it easily. It should just be able to ship as a jar with geoserver, and persist its settings to the data_dir.

Chris

Arne Kepp wrote:
       

Hi,

I am looking to integrate Chris Whitney's JTileCache ( http://whitney.textdriven.com/blog/2007/07/03/jtilecache-proxy-edition/ ) into Geoserver.

Currently it is a separate servlet that communicates with Geoserver through HTTP using the regular WMS interface. It would be nice to bring it closer to Geoserver, so that it knows more about what layers are available, what needs to be purged and so on.

My first attempt was to create a new community module with the code and create a route for /geoserver/tilecache . But I wasn't able to find an elegant way to make WMS requests, because invoking DefaultWebMapService appears to require a getMapRequest, which in turn requires the actual URL. After the dispatcher I can only seem to get my hands on a org.restlet.Request, which is tricky to turn back into an URL.

A compromise I am leaning towards is to skip the dispatcher and keep jtilecache separate, but pass WMS information in through applicationContext. I am not sure whether requests for fresh tiles would still be HTTP requests, or whether I could use the WMS functions directly.

Do people have other suggestions on how to do this?
-Arne

----------------------------------------------
                
-------------------------------------------------------------------------
SF.Net email is sponsored by: The Future of Linux Business White Paper
from Novell. From the desktop to the data center, Linux is going
mainstream. Let it simplify your IT future.
http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4
_______________________________________________
Geoserver-devel mailing list
Geoserver-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/geoserver-devel

!DSPAM:4038,474fda5e192532090977483!

Nice
Arne Kepp skrev:

Thanks Per,

there's no real roadmap at this point, I will try to assemble a roadmap based the feedback from everyone in the RnD section of Geoservers wiki later today or Monday.

Nice, I'll have a look then.

We also need to decide where the code should live, continue in Google's repository or maybe on SourceForge.

I have already made some changes (replaced ImageTile with RawTile and improved streaming when til was not cached). This brought the response time down to less than 2 ms (using the JCS backend). I'll check that in once we know where the code will live.

Im currently looking at the python sources of TileCache for aligning / rounding the wms requested bbox to defined zoomlevels/resolutions.
This is probaly the one feature that makes tilecache different from eg squid. It seems that when using openlayers, the "origin tile" is not requested with the coordinates (tilesorgin-parameter) specified in the layer. This basically forces a resolutions check and request alignment to be done in the cache.

I did have a link to the archive of a conversation at OpenLayers-users list describing the phenomena, but somehow seem to have lost it.

Cheers,
Per-Olof

Per-Olof Norén wrote:

Im currently looking at the python sources of TileCache for aligning / rounding the wms requested bbox to defined zoomlevels/resolutions.
This is probaly the one feature that makes tilecache different from eg squid. It seems that when using openlayers, the "origin tile" is not requested with the coordinates (tilesorgin-parameter) specified in the layer. This basically forces a resolutions check and request alignment to be done in the cache.

I have also looked into this. The Python tilecache creates a grid of what the tile boundaries *should* be, and then returns whatever the closest matching tile is. That, combined with a warning if the adjustment exceeds 1% (arbitrary choice), seems like a pretty good strategy. I haven't considered projection issues, I'm not even sure there are any, given the way resolution is defined. See http://wiki.osgeo.org/index.php/WMS_Tiling_Client_Recommendation

-Arne

I have already made some changes (replaced ImageTile with RawTile and improved streaming when til was not cached). This brought the response time down to less than 2 ms (using the JCS backend). I'll check that in once we know where the code will live.

Im currently looking at the python sources of TileCache for aligning / rounding the wms requested bbox to defined zoomlevels/resolutions.
This is probaly the one feature that makes tilecache different from eg squid. It seems that when using openlayers, the "origin tile" is not requested with the coordinates (tilesorgin-parameter) specified in the layer. This basically forces a resolutions check and request alignment to be done in the cache.

What tilesorigin-parameter are you talking about?

Chris

TileCache uses a tile origin parameter to define the starting point of the grid. The WMS-C recommendation says " A WMS-C service would likely only deliver images for bounding boxes aligned to a given rectangular origin and grid, and only at particular scale levels.". I think the origin is defined as the bottom left corner, but I'm not sure on that. The main advantage to having an origin is that you can specify tiles by integer X, integer Y instead of dealing with BBOXes for each tile. It shouldn't be needed as long as requests always come in as BBOXes. (As an aside, my code has some parameter matching for tile origins, that should be removed since it has no practical need.)

Regarding the resolutions / tile "alignment"-- I think there are two sensible ways to handle this.
1. Try to find the closest tile that matches the requested box. TileCache takes this approach. In order to make this option viable, you either have to a client that does not allow the creation of arbitrary requests, or one that knows that it should snap the arbitrary request to a tile. (For example, if you do an arbitrary request on an OpenLayers Google Maps layer, it snaps the request to Google's tiles.)

or

2. Same as before: define a set of resolutions that requests must fall on. If no resolutions are specified, arbitrary requests are allowed. But, add a second option that controls whether errors (such as off-resolution requests) should be sent to the WMS. If true, the result from the WMS request is sent back to the user but not cached.
      So:
    resolutions off, proxying on: arbitrary requests cached (requires a cache that uses BBOXes, not grids) -- possible cache polluting by nefarious users but could be useful for internal sites

    resolutions off, proxying off: all requests result in errors since there are no resolutions

    resolutions on, proxying on: requests on a resolution grid are cached, arbitrary requests are proxied from the WMS but not cached. This also allows passing requests that a tilecache would not understand (such as for a different image format, a WFS request, etc), while still having the benefits of a cache for the on-grid requests

    resolutions on, proxying off: requests on the resolution grid are sent to the user, off-grid requests result in an error message.

My plan for JTileCache was to follow #2 (and JTileCache is sort-of implemented to follow that). I really didn't like the idea of snapping a request to a tile behind the scenes since that doesn't seem like truly "honoring" a request.

That, combined with a warning if the
adjustment exceeds 1% (arbitrary choice), seems like a pretty good
strategy. I haven't considered projection issues, I'm not even sure
there are any, given the way resolution is defined

As far as I understand, there shouldn't be any projection issues. Possibly useful side note-- in JTileCache, the request resolution (BBOX / image size) is defined as equal to a resolution constraint if both resolutions are pixel equivalent. In other words, for a given BBOX, there a range of possible floating-point resolutions that would cause no change in the resulting image size (due to rounding). If both the request resolution and the resolution constraint are in the same range, then the resolution is equal.

-- Chris Whitney

On Nov 30, 2007, at 8:30 AM, Chris Holmes wrote:

I have already made some changes (replaced ImageTile with RawTile and improved streaming when til was not cached). This brought the response time down to less than 2 ms (using the JCS backend). I'll check that in once we know where the code will live.

Im currently looking at the python sources of TileCache for aligning / rounding the wms requested bbox to defined zoomlevels/resolutions.
This is probaly the one feature that makes tilecache different from eg squid. It seems that when using openlayers, the "origin tile" is not requested with the coordinates (tilesorgin-parameter) specified in the layer. This basically forces a resolutions check and request alignment to be done in the cache.

What tilesorigin-parameter are you talking about?

Chris

<cholmes.vcf>-------------------------------------------------------------------------
SF.Net email is sponsored by: The Future of Linux Business White Paper
from Novell. From the desktop to the data center, Linux is going
mainstream. Let it simplify your IT future.
http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4

Hi see comment below.

Chris Whitney skrev:

TileCache uses a tile origin parameter to define the starting point of the grid. The WMS-C recommendation says " A WMS-C service would likely only deliver images for bounding boxes aligned to a given rectangular origin and grid, and only at particular scale levels.". I think the origin is defined as the bottom left corner, but I'm not sure on that. The main advantage to having an origin is that you can specify tiles by integer X, integer Y instead of dealing with BBOXes for each tile. It shouldn't be needed as long as requests always come in as BBOXes. (As an aside, my code has some parameter matching for tile origins, that should be removed since it has no practical need.)

Regarding the resolutions / tile "alignment"-- I think there are two sensible ways to handle this.
1. Try to find the closest tile that matches the requested box. TileCache takes this approach. In order to make this option viable, you either have to a client that does not allow the creation of arbitrary requests, or one that knows that it should snap the arbitrary request to a tile. (For example, if you do an arbitrary request on an OpenLayers Google Maps layer, it snaps the request to Google's tiles.)

or

2. Same as before: define a set of resolutions that requests must fall on. If no resolutions are specified, arbitrary requests are allowed. But, add a second option that controls whether errors (such as off-resolution requests) should be sent to the WMS. If true, the result from the WMS request is sent back to the user but not cached.
     So:
        resolutions off, proxying on: arbitrary requests cached (requires a cache that uses BBOXes, not grids) -- possible cache polluting by nefarious users but could be useful for internal sites

        resolutions off, proxying off: all requests result in errors since there are no resolutions

        resolutions on, proxying on: requests on a resolution grid are cached, arbitrary requests are proxied from the WMS but not cached. This also allows passing requests that a tilecache would not understand (such as for a different image format, a WFS request, etc), while still having the benefits of a cache for the on-grid requests

        resolutions on, proxying off: requests on the resolution grid are sent to the user, off-grid requests result in an error message.

My plan for JTileCache was to follow #2 (and JTileCache is sort-of implemented to follow that). I really didn't like the idea of snapping a request to a tile behind the scenes since that doesn't seem like truly "honoring" a request.

The thing is, right now it seems like our favourite client OpenLayers does not honor its configuration, and that is what makes TileCache do things it does.
An example:
The swedish grid RT90 (EPSG:2400) has a defined extent in the projected coordinate system as (1200000,6100000,1900000,7700000).
Then configure an openlayers tiled layer with above extents and a tilesorigin = 1200000,6100000 and a scales / resolutions array.
Using OpenLayers a setup like above, one would assume that at least one tile requested (on the largest resolution) would have the tiles-origin in the bbox.
Instead of bbox=1200000,6100000,x2,y2 its requested as 1199999.9999999,61000000,x2,y2
This artifact of internal calculation in OL is non-visible in the resulting tile, but it does require carful handling server-side.

This is on-grid, but the request is not aligned, if just looking at the bbox parameter without gentle massage on it.

I really like the suggested ability to configure the behaviour.

Cheers,
Per-Olof

That, combined with a warning if the
adjustment exceeds 1% (arbitrary choice), seems like a pretty good
strategy. I haven't considered projection issues, I'm not even sure
there are any, given the way resolution is defined

As far as I understand, there shouldn't be any projection issues. Possibly useful side note-- in JTileCache, the request resolution (BBOX / image size) is defined as equal to a resolution constraint if both resolutions are pixel equivalent. In other words, for a given BBOX, there a range of possible floating-point resolutions that would cause no change in the resulting image size (due to rounding). If both the request resolution and the resolution constraint are in the same range, then the resolution is equal.

-- Chris Whitney

On Nov 30, 2007, at 8:30 AM, Chris Holmes wrote:

I have already made some changes (replaced ImageTile with RawTile and improved streaming when til was not cached). This brought the response time down to less than 2 ms (using the JCS backend). I'll check that in once we know where the code will live.

Im currently looking at the python sources of TileCache for aligning / rounding the wms requested bbox to defined zoomlevels/resolutions.
This is probaly the one feature that makes tilecache different from eg squid. It seems that when using openlayers, the "origin tile" is not requested with the coordinates (tilesorgin-parameter) specified in the layer. This basically forces a resolutions check and request alignment to be done in the cache.

What tilesorigin-parameter are you talking about?

Chris

<cholmes.vcf>-------------------------------------------------------------------------

SF.Net email is sponsored by: The Future of Linux Business White Paper
from Novell. From the desktop to the data center, Linux is going
mainstream. Let it simplify your IT future.
http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4