db-ojb-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From oliver.m...@ppi.de
Subject repost, RE: how to implement a TwoLevelCache
Date Fri, 19 Sep 2003 15:11:32 GMT
Hello,

I am sorry again if I am pedantic. But since Armin
just refactored the cache interface, I simply would like
to remind you of my experiences with this two-level
cache and the cloning/proxying issues related to it.
(Please see below for what I wrote then.)

If we want to ship such a two-level cache, I can contribute
my work, but it would require further refactoring to make
it nice.

It is probably something we do not want to do before 
1.0.0 is final.

regards,
  Olli

> -----Original Message-----
> From: oliver.matz@ppi.de [mailto:oliver.matz@ppi.de]
> Sent: Tuesday, June 17, 2003 10:24 AM
> To: ojb-dev@db.apache.org
> Subject: how to implement a TwoLevelCache, was: RE: caching 
> enhancements
> 
> 
> Hello,
> 
> I would like to share some experiences with you.
> 
> > -----Original Message-----
> > 
> > Caching between client interfaces: locking and cloning
> > ------------------------------------------------------
> > 
> > Whenever a persistence manager would use an object that was 
> > seen before by a different persistence manager, this object 
> > could wear dirty data if simply the reference would be used. 
> > Check out this example:
> > 
> > 2002-12-24 08:34pm      PM1 starts a transaction
> > 2002-12-24 08:35pm      PM1 loads object "reindeer3" from the 
> > database, with
> >                         state "tired"
> > 2002-12-24 08:36pm      PM2 starts a transaction
> > 2002-12-24 08:37pm      PM2 searches for "reindeer3" and gets 
> > a reference to
> >                         the "reindeer2" used by PM1
> > 2002-12-24 08:38pm      PM1 feeds "reindeer3" and changes 
> > it's state to
> >                         "christmas ready"
> > 2002-12-24 08:39pm      PM2 sets the state for "reindeer3" to 
> > "sleeping" in
> >                         order to make sure it is ready for 
> 2002-12-25
> > 
> > You know what? If both PMs would commit now, both would 
> > update a "sleeping" state for the reindeer. To find a 
> > way out of this, at least three solutions are open to be 
> > implemented:
> > 
> > - Make sure PM2 gets a different copy of reindeer3 - by 
> >   CLONING the reindeer from the cache 
> > - Make sure PM2 gets a different copy of reindeer3 - by 
> >   materializing the reindeer again from the database
> > - Do not allow using reindeer3 multiple times :(
> 
> > [thma] I'm not a frient of this cloning business. I know the 
> > JDORI simply use different cache instances for all 
> > PersistenceManagers. Those caches are strictly separated and 
> > will be emptied at transaction end.
> > 
> > IMO that's all that is needed.
> > 
> > I know that TopLink got in serious trouble with their cloning 
> 
> Thomas, can you tell us more about these troubles?
> 
> > cache implementation. A lot of user complained. It's not that 
> > easy to implement. And I don't know if it is worth the effort.
> > Needs more discussion. [/thma]
> 
> O.K., I would like to continue that discussion.
> 
> I have tried to implement a class TwoLevelBrokerCache that 
> implements ObjectCache.  The idea is as follows:
> 
> The cache is supposed to work in an environment where all
> database clients are in the same VM.  There is one global cache
> that is always consistent with the data in the database.  
> Besides, there is one cache for each broker.
> 
> References to objects in the global cache are never passed to
> the application.  When objects enter or leave the global cache,
> they are cloned.  (In the original posting, there is a section 
> on how to do that cloning, but let us not worry about that.
> In my situtation, the persistence-capable classes provide a method
> cacheClone() that does the job).
> 
> When an object is inserted in the per-broker-cache, a clone of it
> is inserted into the global cache.
> 
> When the transactin terminates, the per-broker-cache gets cleared.
> 
> When an object is lookup up in the cache, we first look into the
> per-broker-cache and then, if that fails, in the global cache.
> 
> I bet the idea is so obvious that other users must have done
> this before?!
> 
> Here are my experiences:
> 
> (1) Inside PersistenceBrokerImpl.getDBObject(), the method 
>     ObjectCache.cache(oid, newObj) is called fairly early - 
>     namely before newObj's references and collections 
>     are initialized.  
>     (This is to be able to handle cyclic references.)
>     If we clone the object inside ObjectCache.cache(..), then
>     the clone has uninitialized references and collections.
> 
> (2) In order to cope with (1), I would like to initialize
>     those references and collections with suitable proxies.
>     However, I had to cut-and-paste and adapt that code from 
>     PersistenceBrokerImpl because it is hidden in private 
>     methods.
> 
> (3) When testing the implementation, I use two brokers in the 
>     same thread.  I encountered the PersistenceBrokerThreadMapping.
>     I had not known before that the concept of a Thread's current
>     broker is present in the PB API.  I needed to call 
>      PersistenceBrokerThreadMapping.setCurrentPersistenceBroker
>     in order to to mix up the two per-broker-caches when traversing
>     references.
> 
> It seems that the current API is not optimal for that two-level 
> cache strategy.  What do you think?  Has anyone tried something 
> similar?
> 
> I would expect that a clever caching strategy can give a high 
> perfomance gain, so almost any effort is worth it.

---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org


Mime
View raw message