Changes to InvocationContext and TransactionEntry
by Manik Surtani
Both of these classes were, among other things, collecting information
on locks acquired for their respective scopes. Nothing wrong with
this, except that it was a bit haphazard in the manner in which it was
done. There was no consistent naming (getInvocationLocksAcquired() in
the invocation context and getLocks() in the TransactionEntry),
consistent return value guarantees (IC could return null, while TE
always returned a defensively copied list) or storage consistency (IC
used an ArrayList, TE used a LinkedHashSet). And finally, it was a
PITA in the code - I saw a lot of repeated code like:
if (ctx.getTransactionEntry() == null)
{
// get locks from ctx
}
else
{
// get locks from TE
}
So here is what I have done to clean things up.
1. Consistent method names. getLocks(), addLock(), addAllLocks(),
removeLock(), clearLocks().
2. Properly documented expected return types. E.g., getLocks()
returns a defensively copied, immutable list.
3. Documented automatic scope upgrading. E.g., *always* use the
methods on InvocationContext. If a transaction is in scope, the IC
will delegate the call to the TE. Much simpler for calling code.
4. Consistent storage. LinkedHashSets, see JBCACHE-874 if you care
why.
5. Weakly typed methods. locks are Objects, Lists returned are
untyped. Had to do this to support MVCC which uses Fqns as locks and
not NodeLocks. We can make things strongly typed again once we drop
OL/PL support.
Further to the above, I propose we rename TransactionEntry to
TransactionContext, to be consistent with InvocationContext. WDYT?
Cheers
--
Manik Surtani
Lead, JBoss Cache
manik(a)jboss.org
16 years, 5 months
OwnableReentrantLock
by Manik Surtani
In implementing MVCC, I found that the existing
ReadWriteWithUpgradeLock in JBoss Cache was hugely inefficient (lots
of unnecessary syncs) and overkill in the support for readers which I
did not need. Looking around for something a little more "standard",
I considered the j.u.c.locks.ReentrantLock, but found this useless as
well since I need lock owners to be either Threads (if no tx is
running) or a GlobalTransaction instance. Furthermore, due to
replication of events, lock owners should not be compared using
identity (==) but equals() instead (important in the case of
GlobalTransactions owning locks).
So I went about implementing my own lock. After a few attempts using
a concurrent queue and LockSupport.park(), and then fiddling with
o.j.c.locks.AbstractQueuedSynchronizer (and several brainstorming
sessions with Jason), I finally settled on an implementation that does
look good enough. Note that this is *not* a general-purpose lock and
is tied to JBoss Cache, to be able to identify whether the lock to be
acquired needs to be on a Thread or a GlobalTransaction.
Have a look at the OwnableReentrantLock [1]. Apart from containing
minimal syncs and an efficient queueing algorithm thanks to AQS, one
of the other upsells is that it implements Lock, a nice familiar
interface. One benefit here is that if the cache is configured not to
use transactions, we can fall back to a j.u.c.locks.ReentrantLock
instead.
Please have a look at the implementation, comments appreciated.
Cheers
Manik
[1] http://anonsvn.jboss.org/repos/jbosscache/core/trunk/src/main/java/org/jb...
--
Manik Surtani
Lead, JBoss Cache
manik(a)jboss.org
16 years, 5 months
JBoss Cache Searchable interfaces
by Manik Surtani
Hi guys - a few comments on the public interfaces of SearchableCache -
1) IMO, I think that the SearchableCache.createQuery() method should
*not* return a FullTextQuery, but instead a JBCS-specific CacheQuery
interface with a subset of the methods in FullTextQuery.
I think the only methods in FullTextQuery that are relevant and that
should be carried across to CacheQuery are:
* list()
* iterator();
* setFirstResult(int i);
* setMaxResults(int i);
* setFetchSize(int i);
* getResultSize();
* setSort();
I think all of the rest - such as filters, criteria and projections -
are irrelevant to a query on a cache. WDYT? Emmanuel?
2) Also, rather than implement FullTextQuery.scroll() to return a
ScrollableResults instance, I'd rather that iterator() returns an
instance of a new interface, QueryResultsIterator, which extends
j.u.ListIterator. This gives us the ability to scroll back and forth
over a result set, and we could add additional methods to jump to a
specific point in the result set and helpers such as isLast(),
isFirst(), isBeforeLast(), isAfterFirst(), first(), last(),
afterFirst(), beforeLast().
I think that any benefit of a scrollable result set window preventing
loading unnecessary objects from a DB are lost when your backing store
is a cache and the objects are in memory anyway. And besides, any
further optimisations can be in the iterator implementation, such as
just maintaining a list of CachedEntityIds (a composite of Fqn and
key) and fetching the objects from the cache lazily, as required.
Also, with the above, 2, we don't leak any Hibernate or Hibernate
Search interfaces into the user API which again IMO is a good thing.
Thoughts, comments?
Cheers
Manik
On 24 Jun 2008, at 11:47, Navin Surtani wrote:
>
>
> Begin forwarded message:
>
>> From: Emmanuel Bernard <emmanuel(a)hibernate.org>
>> Date: 24 June 2008 08:19:03 BST
>> To: Navin Surtani <navin(a)surtani.org>
>> Subject: Re: More hibernate questions
>>
>> Scroll is more important than iterate because it allows to read
>> objects s a window and get rid of them on a regular basis without
>> facing out of memory exception.
>> I think it's used more often than iterate
>>
>> On Jun 23, 2008, at 18:17, Navin Surtani wrote:
>>
>>> Hey again -
>>>
>>> I have a CacheQueryImpl class that extends the FullTextQuery
>>> interface and I am implementing the methods as similar as possible.
>>>
>>> A couple of problems occur when you are taking in and using
>>> certain Hibernate objects for example. A problem lies with the
>>> scroll() method. I think it is very similar to the iterate()
>>> method and does not need to be implemented in CacheQueryImpl. Do
>>> you know if Hibernate users generally use this method and find
>>> that they need it? If so then I will try and implement it
>>> otherwise then I will just make it throw an exception.
>>>
>>> Thanks again :)
>>> Navin.
>>
>
--
Manik Surtani
Lead, JBoss Cache
manik(a)jboss.org
16 years, 5 months
Releases on JBC
by Manik Surtani
Guys,
I've just cut 2.2.0.CR4 with a couple of the regressions Jason and
Brian spotted integrating POJO Cache and AS clustering respectively,
and corresponding unit tests have been added. 2.2.0.CR4 is in the
maven repo and will make it to SF in due course.
Also, I've just created the 2.2.X branch [1] on which all further
2.2.X work should happen (and be ported to trunk if needed). Trunk
will now be 3.0.0.
[1] https://svn.jboss.org/repos/jbosscache/core/branches/2.2.X
Cheers,
--
Manik Surtani
Lead, JBoss Cache
manik(a)jboss.org
16 years, 5 months
maven.test.skip prevents the test jar from being deployed
by Jason T. Greene
I noticed that CR2 and CR1 were missing the test jar (which prevents
POJO Cache tests from running). This usually happens when you use
-Dmaven.test.skip, since it skips the test-compile and test-jar goals.
Instead use
-Dmaven.test.skip.exec
The longterm fix is to switch back to a decent build tool (ant) :)
--
Jason T. Greene
JBoss, a division of Red Hat
16 years, 5 months
Storing k, v at root node of marshaled region and cache loaders.
by Galder Zamarreno
Hi all,
Yesterday while looking at a support case, I discovered an awkward
behavior when it came to root region based marshalling nodes and cache
loaders.
Let's say you have a cache configured with a cache loader and have a
region marshaled called starting at /me. I have created an MBean so that
I can register/unregister classloader and activate/deactivate the region
upon deployment/undeployment of the classes I wanna put under /me.
Now, let's say that I put a k,v in /me which will get stored in the
cache loader. If I know touch the deployment archive to force a
redeployment and check the contents of the cache, they're empty. If I
try to get the k I put under /me, it'll return nothing. Why?
Simple: The cache instance is configured to preload from root (/) but
when the region is activated, /me node is created. When the preloading
phase comes, a check is made to see whether the node needs to be loaded:
private boolean mustLoad(DataNode n, Object key)
{
if (log.isTraceEnabled())
{
log.trace("mustLoad called with key=" + key + " and datanode="
+ n);
}
return n == null ||
(n.containsKey(TreeCache.UNINITIALIZED) && (key == null
|| !n.containsKey(key)));
}
The problem is that nothing will be preloaded for at least the /me node,
because the node is not null, and it's not TreeCache.UNINITIALIZED. Any
child nodes under the region node do not have issues like this.
This is likely a bug: maybe when the region is activated, the node
should probably be created as TreeCache.UNINITIALIZED? I think this
would work).
It's true that you could say that putting data at the root node of the
region is not a good idea regardless, but I think deep down this is a bug.
Thoughts?
p.s. This is at least present in 1.4.x, need to check trunk. However,
wanted to gather some thoughts before I continue debugging/fixing it.
--
Galder Zamarreño
Sr. Software Maintenance Engineer
JBoss, a division of Red Hat
16 years, 5 months
Lets ditch docbook (long-term)
by Jason T. Greene
This week a community contributor sent me some a very tiny correction to
the POJO Cache documentation (the word you had an additional y, "yyou").
Updating the docs for such a simple fix is a royal pain in the ass, and
required me merging it to 3 different project branches, regenerating
documentation using maven (which failed btw, since maven is a pos, and I
had to update an already released tag), and finally committing the new
docs to the CMS SVN.
This process combined with the unfriendly docbook format basically
discourages the docs from being properly maintained.
IMO a good wiki, like mediawiki, is superior to docbook for community
documentation, since its easy to update, easy to use, and allows
external community members to contribute updates without getting code
svn access.
I think we should move our project docs to something like mediawiki, and
save docbook for situations when you actually want printed documentation
(like EAP).
--
Jason T. Greene
JBoss, a division of Red Hat
16 years, 5 months