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)
|
if (state == TRANSIENT)
|
||||||
return; // no need to lock transient node
|
return; // no need to lock transient node
|
||||||
Transactor current = (Transactor) Thread.currentThread ();
|
Transactor current = (Transactor) Thread.currentThread ();
|
||||||
|
|
||||||
if (!current.isActive ())
|
if (!current.isActive ())
|
||||||
throw new helma.framework.TimeoutException ();
|
throw new helma.framework.TimeoutException ();
|
||||||
if (state == INVALID) {
|
if (state == INVALID) {
|
||||||
|
@ -336,10 +337,12 @@ public class Node implements INode, Serializable {
|
||||||
Thread.dumpStack ();
|
Thread.dumpStack ();
|
||||||
throw new ConcurrencyException ("Node "+this+" was invalidated by another thread.");
|
throw new ConcurrencyException ("Node "+this+" was invalidated by another thread.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lock != null && lock != current && lock.isAlive () && lock.isActive ()) {
|
if (lock != null && lock != current && lock.isAlive () && lock.isActive ()) {
|
||||||
nmgr.logEvent ("Concurrency conflict for "+this+", lock held by "+lock);
|
nmgr.logEvent ("Concurrency conflict for "+this+", lock held by "+lock);
|
||||||
throw new ConcurrencyException ("Tried to modify "+this+" from two threads at the same time.");
|
throw new ConcurrencyException ("Tried to modify "+this+" from two threads at the same time.");
|
||||||
}
|
}
|
||||||
|
|
||||||
current.visitNode (this);
|
current.visitNode (this);
|
||||||
lock = current;
|
lock = current;
|
||||||
}
|
}
|
||||||
|
@ -602,6 +605,9 @@ public class Node implements INode, Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get parent, retrieving it if necessary.
|
||||||
|
*/
|
||||||
public INode getParent () {
|
public INode getParent () {
|
||||||
|
|
||||||
// check what's specified in the type.properties for this node.
|
// check what's specified in the type.properties for this node.
|
||||||
|
@ -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
|
* 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
|
// 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
|
// to the next option described in the type.properties _parent info
|
||||||
INode parent = n.getParent ();
|
INode parent = n.getParent ();
|
||||||
|
|
||||||
releaseNode (n);
|
releaseNode (n);
|
||||||
|
|
||||||
if (parent == this) {
|
if (parent == this) {
|
||||||
|
|
|
@ -165,7 +165,7 @@ public final class NodeManager {
|
||||||
if (node != null) {
|
if (node != null) {
|
||||||
synchronized (cache) {
|
synchronized (cache) {
|
||||||
Node oldnode = (Node) cache.put (node.getKey (), node);
|
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);
|
cache.put (node.getKey (), oldnode);
|
||||||
node = oldnode;
|
node = oldnode;
|
||||||
}
|
}
|
||||||
|
@ -254,6 +254,7 @@ public final class NodeManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (node == nullNode) {
|
} else if (node == nullNode) {
|
||||||
|
// the nullNode caches a null value, i.e. an object that doesn't exist
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
// update primary key in cache to keep it from being flushed, see above
|
// 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
|
// update may cause changes in the node's parent subnode array
|
||||||
if (node.isAnonymous()) {
|
if (node.isAnonymous()) {
|
||||||
Node parent = (Node) node.getParent ();
|
Node parent = node.getCachedParent ();
|
||||||
if (parent != null)
|
if (parent != null)
|
||||||
parent.lastSubnodeChange = System.currentTimeMillis ();
|
parent.lastSubnodeChange = System.currentTimeMillis ();
|
||||||
}
|
}
|
||||||
|
@ -591,7 +592,14 @@ public final class NodeManager {
|
||||||
qds.fetchRecords ();
|
qds.fetchRecords ();
|
||||||
for (int i=0; i<qds.size (); i++) {
|
for (int i=0; i<qds.size (); i++) {
|
||||||
Record rec = qds.getRecord (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 {
|
} finally {
|
||||||
|
|
|
@ -129,7 +129,6 @@ public class Transactor extends Thread {
|
||||||
|
|
||||||
for (Iterator i=nodes.values().iterator(); i.hasNext (); ) {
|
for (Iterator i=nodes.values().iterator(); i.hasNext (); ) {
|
||||||
Node node = (Node) i.next ();
|
Node node = (Node) i.next ();
|
||||||
|
|
||||||
// update nodes in db
|
// update nodes in db
|
||||||
int nstate = node.getState ();
|
int nstate = node.getState ();
|
||||||
if (nstate == Node.NEW) {
|
if (nstate == Node.NEW) {
|
||||||
|
@ -137,12 +136,12 @@ public class Transactor extends Thread {
|
||||||
nmgr.insertNode (nmgr.db, txn, node);
|
nmgr.insertNode (nmgr.db, txn, node);
|
||||||
node.setState (Node.CLEAN);
|
node.setState (Node.CLEAN);
|
||||||
ins++;
|
ins++;
|
||||||
nmgr.app.logEvent ("inserted: Node "+node.getName ()+"/"+node.getID ());
|
nmgr.app.logEvent ("inserted: Node "+node.getPrototype ()+"/"+node.getID ());
|
||||||
} else if (nstate == Node.MODIFIED) {
|
} else if (nstate == Node.MODIFIED) {
|
||||||
nmgr.updateNode (nmgr.db, txn, node);
|
nmgr.updateNode (nmgr.db, txn, node);
|
||||||
node.setState (Node.CLEAN);
|
node.setState (Node.CLEAN);
|
||||||
upd++;
|
upd++;
|
||||||
nmgr.app.logEvent ("updated: Node "+node.getName ()+"/"+node.getID ());
|
nmgr.app.logEvent ("updated: Node "+node.getPrototype ()+"/"+node.getID ());
|
||||||
} else if (nstate == Node.DELETED) {
|
} else if (nstate == Node.DELETED) {
|
||||||
// nmgr.app.logEvent ("deleted: "+node.getFullName ()+" ("+node.getName ()+")");
|
// nmgr.app.logEvent ("deleted: "+node.getFullName ()+" ("+node.getName ()+")");
|
||||||
nmgr.deleteNode (nmgr.db, txn, node);
|
nmgr.deleteNode (nmgr.db, txn, node);
|
||||||
|
|
Loading…
Add table
Reference in a new issue