I am using a custom CacheLoader to back a TreeCache with a filesystem-based
cache -- directories correspond to parent nodes, and files correspond to leaf
nodes.
There is a problem with how the CacheLoader is invoked to fetch the children.
Let's say my file cache has, and my TreeCache is initially empty:
/a
/a/1
/a/2
/a/3
If I call cache.getChildrenNames("/a"), I will correctly get the child names
(1, 2, and 3). However, if I first call cache.get("/a"), and then call
cache.getChildrenNames("/a"), I will get an empty set.
I traced it down to this section of CacheLoaderInterceptor:
| CacheLoaderInterceptor.java:80
| ...
| if(fqn != null && (!cache.exists(fqn) || cache.exists(fqn,
TreeCache.UNINITIALIZED))) {
| n=loadNode(fqn);
| if(load_attributes && n != null)
| loadAttributesFromCacheLoader(n);
| // n=loadNode(fqn, load_attributes);
| lock(fqn, Node.LOCK_TYPE_WRITE, false); // not recursive
| }
|
| // special case: node is loaded, but children nodes haven't: check
with CacheLoader if children nodes are
| // present and load if yes
| if(meth.equals(TreeCache.getChildrenNamesMethodLocal) && n != null
&& fqn != null) {
| Map children=n.getChildren();
| if(children == null) {
| Set children_names=null;
| try {
| children_names=loader.getChildrenNames(fqn);
| }
| ...
|
The logic in the last bit is that if the node's children haven't been loaded
yet, it will get their names from the CacheLoader, and then create
uninitialized nodes for each (so future calls to getChildrenNames work).
Unfortunately, part of that if() statement checks that n != null, and n only
gets set if it did not exist at all, or was uninitialized, in the first part.
Thus if the parent node has previously been loaded, n will never get set, and
the loader will not get called.
The simple solution is to add an else clause which fetches the already loaded
node if it exists. Unfortunately, this just adds a new problem. If I were to
first call cache.get("/a/1"), the node now has loaded children. Now if I call
cache.getChildrenNames("/a"), it will return me the set (1), which is not
consistent with my CacheLoader.
Two possible solutions I can see:
| * Always stub all of the children of a node whenever the first child is
loaded. This will guarantee that no matter what order calls are made to the
cache, getChildrenNames will return results consistant with the CacheLoader.
Unfortunately, this carries a (potentially large) performance hit, since it
requires enumerating all children of a node before fetching one child.
| * Use a separate flag to indicate whether all children have been
loaded/stubbed, or just some (or no) children have been loaded. An additional
attribute like TreeCache.UNINITIALIZED could be added, or Node could contain a
allChildrenLoaded flag.
|
View the original post :
http://www.jboss.org/index.html?module=bb&op=viewtopic&p=3872880#3872880
Reply to the post :
http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=3872880
-------------------------------------------------------
SF email is sponsored by - The IT Product Guide
Read honest & candid reviews on hundreds of IT Products from real users.
Discover which products truly live up to the hype. Start reading now.
http://ads.osdn.com/?ad_id=6595&alloc_id=14396&op=click
_______________________________________________
JBoss-user mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/jboss-user