You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ojb-dev@db.apache.org by ol...@ppi.de on 2003/09/19 17:11:32 UTC

repost, RE: how to implement a TwoLevelCache

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


Re: repost, RE: how to implement a TwoLevelCache

Posted by Stephan Merker <St...@cegedim.fr>.
Hallo,

I've implemented a TwoLevelCache that works for distributed transactions
(JTA). I'm using the OTM copy strategy for cloning objects when they are
copied from the global cache to a tx local cache. The implementation has a
dependency to Tyrex (an open source transaction manager) in order to access
the current transaction. This dependency could be removed by using sort of
an Tx provider plug-in, that can be implemented for different tx managers.

The cache was implemented against OJB CVS HEAD from 2003-07-14 (just before
RC4), so it still uses the old cache interfaces. It works well for OJB +
Tyrex + Oracle 9i. However, I've not tested proxies. Before using the cache,
you should set a suitable copy strategy (default is no-op).

I've attached the source. Maybe it is of some help.

Stephan


Re: repost, RE: how to implement a TwoLevelCache

Posted by Armin Waibel <ar...@code-au-lait.de>.
Hi,
----- Original Message -----
From: "João Luz" <Jo...@ist.utl.pt>
To: "OJB Developers List" <oj...@db.apache.org>
Sent: Friday, September 19, 2003 11:00 PM
Subject: RE: repost, RE: how to implement a TwoLevelCache


> Hello Armin,
>
> When I was reading your post I stopped here
>
> "On the other hand with current implementation and
> a global ObjectCache we have
> problems with dirty reads from cache, corrupt objects in
> cache after rollback ...."
>
> Could you explain a little more this problem or send me to a place
when I
> can read about this problem.
>
> I'm asking this because we're facing a problem similar to this, ie, in
some
> situations in production server we were getting objects from cache
> corrupted. We've solved the problem by clearing the cache every time
we
> rollback...
>

This is one possibility to avoid corrupted data in cache.
Or you can use ObjectCachePerBrokerImpl. This cache
was cleared on each PB.close() call and avoid dirty reads too,
but has a performance impact.

regards,
Armin

> Thanks in advance,
> João V.Luz
>
>
>
> -----Original Message-----
> From: Armin Waibel [mailto:armin@code-au-lait.de]
> Sent: sexta-feira, 19 de Setembro de 2003 18:57
> To: OJB Developers List
> Subject: Re: repost, RE: how to implement a TwoLevelCache
>
>
> Hi,
>
> think it would be great to have a two-level
> cache in the kernel api.
>
> > > 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.
> ....
> > > cache strategy.  What do you think?  Has anyone tried something
> > > similar?
>
> Some weeks ago I started to implement a ObjectCache
> in a similar way but I'm become stuck with the cloning
> stuff.
> Think the caching handling in OTM is also compareable with
> your proposal. All objects in OTM were cloned (using
> ObjectCopyStrategy interface implementations)
> except objects with write lock (hope I tell the truth).
>
> I agree Thomas that the cloning of objects is evil.
> E.g. say object A has a reference using proxy, the real object
> is materialized but the real object itself is not serializeable but
> has a clone/copy method ... ok, this can be solved use writeObject/
> readObject methods in IndirectionHandler or declare real subject
> as transient.
> Or object A has a collection of B objects. For A we use serialization
> as copy strategy but the B objects use another copy strategy ....
>
> On the other hand with current implementation and
> a global ObjectCache we have
> problems with dirty reads from cache, corrupt objects in
> cache after rollback ....
>
> So I don't know what's the smartest way to go.
>
> regards,
> Armin
>
> ----- Original Message -----
> From: <ol...@ppi.de>
> To: <oj...@db.apache.org>
> Sent: Friday, September 19, 2003 5:11 PM
> Subject: repost, RE: how to implement a TwoLevelCache
>
>
> > 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
> >
> >
> >
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
> For additional commands, e-mail: ojb-dev-help@db.apache.org
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
> For additional commands, e-mail: ojb-dev-help@db.apache.org
>
>
>



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


RE: repost, RE: how to implement a TwoLevelCache

Posted by João Luz <Jo...@ist.utl.pt>.
Hello Armin,

When I was reading your post I stopped here

"On the other hand with current implementation and
a global ObjectCache we have
problems with dirty reads from cache, corrupt objects in
cache after rollback ...."

Could you explain a little more this problem or send me to a place when I
can read about this problem.

I'm asking this because we're facing a problem similar to this, ie, in some
situations in production server we were getting objects from cache
corrupted. We've solved the problem by clearing the cache every time we
rollback...

Thanks in advance,
	João V.Luz



-----Original Message-----
From: Armin Waibel [mailto:armin@code-au-lait.de]
Sent: sexta-feira, 19 de Setembro de 2003 18:57
To: OJB Developers List
Subject: Re: repost, RE: how to implement a TwoLevelCache


Hi,

think it would be great to have a two-level
cache in the kernel api.

> > 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.
....
> > cache strategy.  What do you think?  Has anyone tried something
> > similar?

Some weeks ago I started to implement a ObjectCache
in a similar way but I'm become stuck with the cloning
stuff.
Think the caching handling in OTM is also compareable with
your proposal. All objects in OTM were cloned (using
ObjectCopyStrategy interface implementations)
except objects with write lock (hope I tell the truth).

I agree Thomas that the cloning of objects is evil.
E.g. say object A has a reference using proxy, the real object
is materialized but the real object itself is not serializeable but
has a clone/copy method ... ok, this can be solved use writeObject/
readObject methods in IndirectionHandler or declare real subject
as transient.
Or object A has a collection of B objects. For A we use serialization
as copy strategy but the B objects use another copy strategy ....

On the other hand with current implementation and
a global ObjectCache we have
problems with dirty reads from cache, corrupt objects in
cache after rollback ....

So I don't know what's the smartest way to go.

regards,
Armin

----- Original Message -----
From: <ol...@ppi.de>
To: <oj...@db.apache.org>
Sent: Friday, September 19, 2003 5:11 PM
Subject: repost, RE: how to implement a TwoLevelCache


> 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
>
>
>



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


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


Re: repost, RE: how to implement a TwoLevelCache

Posted by Armin Waibel <ar...@code-au-lait.de>.
Hi,

think it would be great to have a two-level
cache in the kernel api.

> > 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. 
....
> > cache strategy.  What do you think?  Has anyone tried something 
> > similar?

Some weeks ago I started to implement a ObjectCache
in a similar way but I'm become stuck with the cloning
stuff.
Think the caching handling in OTM is also compareable with
your proposal. All objects in OTM were cloned (using
ObjectCopyStrategy interface implementations)
except objects with write lock (hope I tell the truth).

I agree Thomas that the cloning of objects is evil.
E.g. say object A has a reference using proxy, the real object
is materialized but the real object itself is not serializeable but
has a clone/copy method ... ok, this can be solved use writeObject/
readObject methods in IndirectionHandler or declare real subject
as transient.
Or object A has a collection of B objects. For A we use serialization
as copy strategy but the B objects use another copy strategy ....

On the other hand with current implementation and
a global ObjectCache we have
problems with dirty reads from cache, corrupt objects in
cache after rollback ....

So I don't know what's the smartest way to go.

regards,
Armin

----- Original Message ----- 
From: <ol...@ppi.de>
To: <oj...@db.apache.org>
Sent: Friday, September 19, 2003 5:11 PM
Subject: repost, RE: how to implement a TwoLevelCache


> 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
> 
> 
> 



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