Caching with timed expiry

S

Sebastian

Hello there,

does anyone of a cache / map implementation in which entries
expire after a fixed time? By which I mean that after a cnfigurable
delay after an enzry has been caches,it is automatically removed
from the cache and some clean-up action (perhaps event-triggred)
can be taken.

My scenario is this: A GUI client searches an LDAP server using
the virtual list view control. The server requires all requests
to be made over the same connection. So my middleware component
will need to check out that connection from a pool and cache it,
using the ASN1 cookie sent by the client as a key.

Trouble is, if the client never signals that it won't request
another page (e. g. because it crashes), I need to auto-release
the LDAP server connection to the connection pool to prevent leakage.
I thought that a ready-made cache with timed expiry would come in handy.
If there is no such beast, any ideas for possible approaches?

-- Sebastian
 
J

Jim Janney

Sebastian said:
Hello there,

does anyone of a cache / map implementation in which entries
expire after a fixed time? By which I mean that after a cnfigurable
delay after an enzry has been caches,it is automatically removed
from the cache and some clean-up action (perhaps event-triggred)
can be taken.

My scenario is this: A GUI client searches an LDAP server using
the virtual list view control. The server requires all requests
to be made over the same connection. So my middleware component
will need to check out that connection from a pool and cache it,
using the ASN1 cookie sent by the client as a key.

Trouble is, if the client never signals that it won't request
another page (e. g. because it crashes), I need to auto-release
the LDAP server connection to the connection pool to prevent leakage.
I thought that a ready-made cache with timed expiry would come in handy.
If there is no such beast, any ideas for possible approaches?

-- Sebastian

Look at subclassing java.util.LinkedHashMap and overriding the
removeEldestEntry method to check an expiration time. The removal time
will not be precise (since it's triggered when something else is looked
up) but it may be good enough.
 
R

Roedy Green

Hello there,

does anyone of a cache / map implementation in which entries
expire after a fixed time? By which I mean that after a cnfigurable
delay after an enzry has been caches,it is automatically removed
from the cache and some clean-up action (perhaps event-triggred)
can be taken.

My scenario is this: A GUI client searches an LDAP server using
the virtual list view control. The server requires all requests
to be made over the same connection. So my middleware component
will need to check out that connection from a pool and cache it,
using the ASN1 cookie sent by the client as a key.

Trouble is, if the client never signals that it won't request
another page (e. g. because it crashes), I need to auto-release
the LDAP server connection to the connection pool to prevent leakage.
I thought that a ready-made cache with timed expiry would come in handy.
If there is no such beast, any ideas for possible approaches?

-- Sebastian

You might want to look into weak links.
http://mindprod.com/jgloss/weak.html


See
--
Roedy Green Canadian Mind Products
http://mindprod.com
Programmers love to create simplified replacements for HTML.
They forget that the simplest language is the one you
already know. They also forget that their simple little
markup language will bit by bit become even more convoluted
and complicated than HTML because of the unplanned way it grows.
..
 
S

Silvio Bierman

Look at subclassing java.util.LinkedHashMap and overriding the
removeEldestEntry method to check an expiration time. The removal time
will not be precise (since it's triggered when something else is looked
up) but it may be good enough.

Actually this is not going to work since removeEldestEntry is only
called when calling put on the map and even then it is only called once
for each put, disallowing dropping multiple expired entries at once.
I kicked LinkedHashMap around a couple of times to try and get this
working properly but gave up on it.

The simplest self-built solution is wrapping key/element pairs in
wrapper objects that also implements a doubly-linked list to represent
the queue and coupling that with a plain HashMap that maps key values to
the corresponding wrapper.
I have done this to create caches that makes elements expire if they
have been in the cache for too long or have not been retrieved for too
long. Naturally this can be done either implicitly at lookup time or
explicitly with some purgeExpiredEntries method that could be called
periodically even when not querying the cache.

There probably also are existing cache libraries that will do this for
you if you don't mind the dependency.

Silvio
 
J

Jim Janney

Silvio Bierman said:
Actually this is not going to work since removeEldestEntry is only
called when calling put on the map and even then it is only called
once for each put, disallowing dropping multiple expired entries at
once.
I kicked LinkedHashMap around a couple of times to try and get this
working properly but gave up on it.

Hmm, yes. An access-ordered LinkedHashMap may stop growing, but it will
never shrink unless you explicitly remove entries. I suppose you could
repeatedly add a bogus entry and then remove it again? Still not the
cleanest approach.
The simplest self-built solution is wrapping key/element pairs in
wrapper objects that also implements a doubly-linked list to represent
the queue and coupling that with a plain HashMap that maps key values
to the corresponding wrapper.
I have done this to create caches that makes elements expire if they
have been in the cache for too long or have not been retrieved for too
long. Naturally this can be done either implicitly at lookup time or
explicitly with some purgeExpiredEntries method that could be called
periodically even when not querying the cache.

There probably also are existing cache libraries that will do this for
you if you don't mind the dependency.

A separate priority queue kept in parallel with the map?
 
A

Arved Sandstrom

Actually this is not going to work since removeEldestEntry is only
called when calling put on the map and even then it is only called once
for each put, disallowing dropping multiple expired entries at once.
I kicked LinkedHashMap around a couple of times to try and get this
working properly but gave up on it.

The simplest self-built solution is wrapping key/element pairs in
wrapper objects that also implements a doubly-linked list to represent
the queue and coupling that with a plain HashMap that maps key values to
the corresponding wrapper.
I have done this to create caches that makes elements expire if they
have been in the cache for too long or have not been retrieved for too
long. Naturally this can be done either implicitly at lookup time or
explicitly with some purgeExpiredEntries method that could be called
periodically even when not querying the cache.
There probably also are existing cache libraries that will do this for
you if you don't mind the dependency.

Google Guava with its CacheBuilder, or ehcache, for example.

AHS
 
S

Silvio Bierman

A separate priority queue kept in parallel with the map?

Yep, that is what I meant. If you wrap both in the cache object they are
easy to keep synchronized.

I suggested implementing the priority queue manually and put queue nodes
as values in the HashMap to prevent O(n) operations on the queue(s).

For the situation where I needed to handle both cache presence timeouts
AND cache lookup timeouts it looked something like:

public class MyCache<K,V>
{
private class Node
{
K key;
V value;
Node previousAddition;
Node nextAddition;
long additionTime;
Node previousAccess;
Node nextAccess;
long accessTime;
}

private HashMap<K,Node> lookup = new HashMap<K,Node>();

private Node accessHead;
private Node accessTail;
private Node additionHead;
private Node additionTail;

//...
}

Only an approximation from the top of my mind, the actual code is Scala.
The operations are trivial to implement.
 
S

Sebastian

Thank you everyone for your help. Google Guava does
indeed do all I need:

Cache<ASN1Octet, LDAPConnection> connectionCache =
CacheBuilder.newBuilder()
.expireAfterAccess(2, TimeUnit.MINUTES)
.removalListener(MY_LISTENER)
.build();

-- Sebastian
 
R

Robert Klemme

You might want to look into weak links.
http://mindprod.com/jgloss/weak.html

That does not give you control of the timing. In theory a SoftReference
might be better because GC is more reluctant to clear it. But it's not
entirely clear whether they actually behave differently in practice and
you still do not get control of timing.

Kind regards

robert
 
A

Arne Vajhøj

You might want to look into weak links.

Why?

They do not provide the functionality requested.

Is "in which entries expire after a fixed time" a
difficult requirements to understand?

Arne
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,024
Latest member
ARDU_PROgrammER

Latest Threads

Top