fixed bug with null node caching and groupby nodes.
This commit is contained in:
parent
df78802f57
commit
c2a80bb151
3 changed files with 31 additions and 7 deletions
|
@ -329,6 +329,7 @@ public class Node implements INode, Serializable {
|
|||
if (state == TRANSIENT)
|
||||
return; // no need to lock transient node
|
||||
Transactor current = (Transactor) Thread.currentThread ();
|
||||
|
||||
if (!current.isActive ())
|
||||
throw new helma.framework.TimeoutException ();
|
||||
if (state == INVALID) {
|
||||
|
@ -336,10 +337,12 @@ public class Node implements INode, Serializable {
|
|||
Thread.dumpStack ();
|
||||
throw new ConcurrencyException ("Node "+this+" was invalidated by another thread.");
|
||||
}
|
||||
|
||||
if (lock != null && lock != current && lock.isAlive () && lock.isActive ()) {
|
||||
nmgr.logEvent ("Concurrency conflict for "+this+", lock held by "+lock);
|
||||
throw new ConcurrencyException ("Tried to modify "+this+" from two threads at the same time.");
|
||||
}
|
||||
|
||||
current.visitNode (this);
|
||||
lock = current;
|
||||
}
|
||||
|
@ -602,12 +605,15 @@ public class Node implements INode, Serializable {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get parent, retrieving it if necessary.
|
||||
*/
|
||||
public INode getParent () {
|
||||
|
||||
// check what's specified in the type.properties for this node.
|
||||
ParentInfo[] parentInfo = null;
|
||||
if (dbmap != null && dbmap.isRelational () &&
|
||||
(lastParentSet < dbmap.getLastTypeChange() || lastParentSet < lastmodified))
|
||||
(lastParentSet < dbmap.getLastTypeChange() || lastParentSet < lastmodified))
|
||||
parentInfo = dbmap.getParentInfo ();
|
||||
|
||||
// check if current parent candidate matches presciption, if not, try to get it
|
||||
|
@ -646,6 +652,16 @@ public class Node implements INode, Serializable {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get parent, using cached info if it exists.
|
||||
*/
|
||||
public Node getCachedParent () {
|
||||
if (parentID == null)
|
||||
return null;
|
||||
return nmgr.getNode (parentID, parentmap);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* INode-related
|
||||
*/
|
||||
|
@ -948,6 +964,7 @@ public class Node implements INode, Serializable {
|
|||
// need to query parent before releaseNode is called, since this may change the parent
|
||||
// to the next option described in the type.properties _parent info
|
||||
INode parent = n.getParent ();
|
||||
|
||||
releaseNode (n);
|
||||
|
||||
if (parent == this) {
|
||||
|
|
|
@ -165,7 +165,7 @@ public final class NodeManager {
|
|||
if (node != null) {
|
||||
synchronized (cache) {
|
||||
Node oldnode = (Node) cache.put (node.getKey (), node);
|
||||
if (oldnode != null && oldnode.getState () != Node.INVALID) {
|
||||
if (oldnode != null && oldnode.getState () != Node.INVALID && oldnode != nullNode) {
|
||||
cache.put (node.getKey (), oldnode);
|
||||
node = oldnode;
|
||||
}
|
||||
|
@ -254,6 +254,7 @@ public final class NodeManager {
|
|||
}
|
||||
}
|
||||
} else if (node == nullNode) {
|
||||
// the nullNode caches a null value, i.e. an object that doesn't exist
|
||||
return null;
|
||||
} else {
|
||||
// update primary key in cache to keep it from being flushed, see above
|
||||
|
@ -454,7 +455,7 @@ public final class NodeManager {
|
|||
}
|
||||
// update may cause changes in the node's parent subnode array
|
||||
if (node.isAnonymous()) {
|
||||
Node parent = (Node) node.getParent ();
|
||||
Node parent = node.getCachedParent ();
|
||||
if (parent != null)
|
||||
parent.lastSubnodeChange = System.currentTimeMillis ();
|
||||
}
|
||||
|
@ -591,7 +592,14 @@ public final class NodeManager {
|
|||
qds.fetchRecords ();
|
||||
for (int i=0; i<qds.size (); i++) {
|
||||
Record rec = qds.getRecord (i);
|
||||
retval.addElement (rec.getValue (1).asString ());
|
||||
String kstr = rec.getValue (1).asString ();
|
||||
retval.addElement (kstr);
|
||||
// if these are groupby nodes, evict nullNode keys
|
||||
if (rel.groupby != null) {
|
||||
Key key = new Key ((String) null, home.getKey ().getVirtualID (kstr));
|
||||
if (cache.get (key) == nullNode)
|
||||
evictKey (key);
|
||||
}
|
||||
}
|
||||
|
||||
} finally {
|
||||
|
|
|
@ -129,7 +129,6 @@ public class Transactor extends Thread {
|
|||
|
||||
for (Iterator i=nodes.values().iterator(); i.hasNext (); ) {
|
||||
Node node = (Node) i.next ();
|
||||
|
||||
// update nodes in db
|
||||
int nstate = node.getState ();
|
||||
if (nstate == Node.NEW) {
|
||||
|
@ -137,12 +136,12 @@ public class Transactor extends Thread {
|
|||
nmgr.insertNode (nmgr.db, txn, node);
|
||||
node.setState (Node.CLEAN);
|
||||
ins++;
|
||||
nmgr.app.logEvent ("inserted: Node "+node.getName ()+"/"+node.getID ());
|
||||
nmgr.app.logEvent ("inserted: Node "+node.getPrototype ()+"/"+node.getID ());
|
||||
} else if (nstate == Node.MODIFIED) {
|
||||
nmgr.updateNode (nmgr.db, txn, node);
|
||||
node.setState (Node.CLEAN);
|
||||
upd++;
|
||||
nmgr.app.logEvent ("updated: Node "+node.getName ()+"/"+node.getID ());
|
||||
nmgr.app.logEvent ("updated: Node "+node.getPrototype ()+"/"+node.getID ());
|
||||
} else if (nstate == Node.DELETED) {
|
||||
// nmgr.app.logEvent ("deleted: "+node.getFullName ()+" ("+node.getName ()+")");
|
||||
nmgr.deleteNode (nmgr.db, txn, node);
|
||||
|
|
Loading…
Add table
Reference in a new issue