You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by dp...@apache.org on 2007/05/25 10:41:55 UTC
svn commit: r541585 - in
/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core:
cluster/ClusterNode.java cluster/NodeTypeEventChannel.java
cluster/NodeTypeEventListener.java nodetype/NodeTypeRegistry.java
Author: dpfister
Date: Fri May 25 01:41:46 2007
New Revision: 541585
URL: http://svn.apache.org/viewvc?view=rev&rev=541585
Log:
JCR-699: Clustering: re-registration of nodetypes is not synchronized
Modified:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/ClusterNode.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NodeTypeEventChannel.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NodeTypeEventListener.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/ClusterNode.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/ClusterNode.java?view=diff&rev=541585&r1=541584&r2=541585
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/ClusterNode.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/ClusterNode.java Fri May 25 01:41:46 2007
@@ -94,6 +94,26 @@
private static final int STOPPED = 2;
/**
+ * Bit indicating this is a registration operation.
+ */
+ private static final int NTREG_REGISTER = 0;
+
+ /**
+ * Bit indicating this is a reregistration operation.
+ */
+ private static final int NTREG_REREGISTER = (1 << 30);
+
+ /**
+ * Bit indicating this is an unregistration operation.
+ */
+ private static final int NTREG_UNREGISTER = (1 << 31);
+
+ /**
+ * Mask used in node type registration operations.
+ */
+ private static final int NTREG_MASK = (NTREG_REREGISTER | NTREG_UNREGISTER);
+
+ /**
* Logger.
*/
private static Logger log = LoggerFactory.getLogger(ClusterNode.class);
@@ -405,7 +425,71 @@
try {
record = journal.getProducer(PRODUCER_ID).append();
record.writeString(null);
- write(record, ntDefs);
+ write(record, ntDefs, true);
+ record.writeChar('\0');
+ record.update();
+ setRevision(record.getRevision());
+ succeeded = true;
+ } catch (JournalException e) {
+ String msg = "Unable to create log entry: " + e.getMessage();
+ log.error(msg);
+ } catch (Throwable e) {
+ String msg = "Unexpected error while creating log entry.";
+ log.error(msg, e);
+ } finally {
+ if (!succeeded && record != null) {
+ record.cancelUpdate();
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void reregistered(NodeTypeDef ntDef) {
+ if (status != STARTED) {
+ log.info("not started: nodetype operation ignored.");
+ return;
+ }
+ Record record = null;
+ boolean succeeded = false;
+
+ try {
+ record = journal.getProducer(PRODUCER_ID).append();
+ record.writeString(null);
+ write(record, ntDef);
+ record.writeChar('\0');
+ record.update();
+ setRevision(record.getRevision());
+ succeeded = true;
+ } catch (JournalException e) {
+ String msg = "Unable to create log entry: " + e.getMessage();
+ log.error(msg);
+ } catch (Throwable e) {
+ String msg = "Unexpected error while creating log entry.";
+ log.error(msg, e);
+ } finally {
+ if (!succeeded && record != null) {
+ record.cancelUpdate();
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void unregistered(Collection qnames) {
+ if (status != STARTED) {
+ log.info("not started: nodetype operation ignored.");
+ return;
+ }
+ Record record = null;
+ boolean succeeded = false;
+
+ try {
+ record = journal.getProducer(PRODUCER_ID).append();
+ record.writeString(null);
+ write(record, qnames, false);
record.writeChar('\0');
record.update();
setRevision(record.getRevision());
@@ -781,16 +865,46 @@
/**
* Process one or more node type registrations.
*
- * @param ntDefs node type definition
+ * @param c collection of node type definitions, if this is a register
+ * operation; collection of <code>QName</code>s if this is
+ * an unregister operation
+ * @param register <code>true</code>, if this is a register operation;
+ * <code>false</code> otherwise
+ */
+ private void process(Collection c, boolean register) {
+ if (nodeTypeListener == null) {
+ String msg = "NodeType listener unavailable.";
+ log.error(msg);
+ return;
+ }
+ try {
+ if (register) {
+ nodeTypeListener.externalRegistered(c);
+ } else {
+ nodeTypeListener.externalUnregistered(c);
+ }
+ } catch (InvalidNodeTypeDefException e) {
+ String msg = "Unable to deliver node type operation: " + e.getMessage();
+ log.error(msg);
+ } catch (RepositoryException e) {
+ String msg = "Unable to deliver node type operation: " + e.getMessage();
+ log.error(msg);
+ }
+ }
+
+ /**
+ * Process a node type re-registration.
+ *
+ * @param ntDef node type definition
*/
- private void process(Collection ntDefs) {
+ private void process(NodeTypeDef ntDef) {
if (nodeTypeListener == null) {
String msg = "NodeType listener unavailable.";
log.error(msg);
return;
}
try {
- nodeTypeListener.externalRegistered(ntDefs);
+ nodeTypeListener.externalReregistered(ntDef);
} catch (InvalidNodeTypeDefException e) {
String msg = "Unable to deliver node type operation: " + e.getMessage();
log.error(msg);
@@ -918,11 +1032,30 @@
process(oldPrefix, newPrefix, uri);
} else if (c == 'T') {
int size = record.readInt();
- HashSet ntDefs = new HashSet();
- for (int i = 0; i < size; i++) {
- ntDefs.add(record.readNodeTypeDef());
+ int opcode = size & NTREG_MASK;
+ size &= ~NTREG_MASK;
+
+ switch (opcode) {
+ case NTREG_REGISTER:
+ HashSet ntDefs = new HashSet();
+ for (int i = 0; i < size; i++) {
+ ntDefs.add(record.readNodeTypeDef());
+ }
+ process(ntDefs, true);
+ break;
+ case NTREG_REREGISTER:
+ process(record.readNodeTypeDef());
+ break;
+ case NTREG_UNREGISTER:
+ HashSet ntNames = new HashSet();
+ for (int i = 0; i < size; i++) {
+ ntNames.add(record.readQName());
+ }
+ process(ntNames, false);
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown opcode: " + opcode);
}
- process(ntDefs);
} else {
throw new IllegalArgumentException("Unknown entry type: " + c);
}
@@ -1061,16 +1194,37 @@
write(record, nodeId, false, false, null);
}
- private static void write(Record record, Collection ntDefs)
+ private static void write(Record record, Collection c, boolean register)
throws JournalException {
record.writeChar('T');
- record.writeInt(ntDefs.size());
- Iterator iter = ntDefs.iterator();
+ int size = c.size();
+ if (!register) {
+ size |= NTREG_UNREGISTER;
+ }
+ record.writeInt(size);
+
+ Iterator iter = c.iterator();
while (iter.hasNext()) {
- record.writeNodeTypeDef((NodeTypeDef) iter.next());
+ if (register) {
+ record.writeNodeTypeDef((NodeTypeDef) iter.next());
+ } else {
+ record.writeQName((QName) iter.next());
+ }
}
+ }
+
+ private static void write(Record record, NodeTypeDef ntDef)
+ throws JournalException {
+
+ record.writeChar('T');
+
+ int size = 1;
+ size |= NTREG_REREGISTER;
+ record.writeInt(size);
+
+ record.writeNodeTypeDef(ntDef);
}
private static void write(Record record, PropertyOperation operation)
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NodeTypeEventChannel.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NodeTypeEventChannel.java?view=diff&rev=541585&r1=541584&r2=541585
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NodeTypeEventChannel.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NodeTypeEventChannel.java Fri May 25 01:41:46 2007
@@ -16,6 +16,8 @@
*/
package org.apache.jackrabbit.core.cluster;
+import org.apache.jackrabbit.core.nodetype.NodeTypeDef;
+
import java.util.Collection;
/**
@@ -29,6 +31,20 @@
* @param ntDefs collection of node type definitions
*/
public void registered(Collection ntDefs);
+
+ /**
+ * Called when a node types has been re-registered.
+ *
+ * @param ntDef node type definition
+ */
+ public void reregistered(NodeTypeDef ntDef);
+
+ /**
+ * Called when one or more node types have been unregistered.
+ *
+ * @param ntNames collection of node type qnames
+ */
+ public void unregistered(Collection ntNames);
/**
* Set listener that will receive information about incoming, external node type events.
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NodeTypeEventListener.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NodeTypeEventListener.java?view=diff&rev=541585&r1=541584&r2=541585
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NodeTypeEventListener.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NodeTypeEventListener.java Fri May 25 01:41:46 2007
@@ -17,8 +17,10 @@
package org.apache.jackrabbit.core.cluster;
import org.apache.jackrabbit.core.nodetype.InvalidNodeTypeDefException;
+import org.apache.jackrabbit.core.nodetype.NodeTypeDef;
import javax.jcr.RepositoryException;
+import javax.jcr.nodetype.NoSuchNodeTypeException;
import java.util.Collection;
/**
@@ -35,4 +37,25 @@
*/
public void externalRegistered(Collection ntDefs)
throws RepositoryException, InvalidNodeTypeDefException;
+
+ /**
+ * Called when a node type has been externally re-registered.
+ *
+ * @param ntDef node type definition
+ * @throws RepositoryException if an error occurs
+ * @throws NoSuchNodeTypeException if the node type had not yet been registered
+ * @throws InvalidNodeTypeDefException if the node type definition is invalid
+ */
+ public void externalReregistered(NodeTypeDef ntDef)
+ throws NoSuchNodeTypeException, InvalidNodeTypeDefException, RepositoryException;
+
+ /**
+ * Called when one or more node types have been externally unregistered.
+ *
+ * @param ntNames node type qnames
+ * @throws RepositoryException if an error occurs
+ * @throws NoSuchNodeTypeException if a node type is already unregistered
+ */
+ public void externalUnregistered(Collection ntNames)
+ throws RepositoryException, NoSuchNodeTypeException;
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java?view=diff&rev=541585&r1=541584&r2=541585
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java Fri May 25 01:41:46 2007
@@ -200,8 +200,23 @@
* @throws InvalidNodeTypeDefException if the given node type definition is invalid.
* @throws RepositoryException if a repository error occurs.
*/
- public synchronized void registerNodeTypes(Collection ntDefs)
+ public void registerNodeTypes(Collection ntDefs)
throws InvalidNodeTypeDefException, RepositoryException {
+
+ registerNodeTypes(ntDefs, false);
+ }
+
+ /**
+ * Internal implementation of {@link #registerNodeTypes(Collection)}
+ *
+ * @param ntDefs a collection of <code>NodeTypeDef<code> objects
+ * @param external whether this invocation should be considered external
+ * @throws InvalidNodeTypeDefException if the given node type definition is invalid.
+ * @throws RepositoryException if a repository error occurs.
+ */
+ private synchronized void registerNodeTypes(Collection ntDefs, boolean external)
+ throws InvalidNodeTypeDefException, RepositoryException {
+
// validate and register new node type definitions
internalRegister(ntDefs);
// persist new node type definitions
@@ -211,8 +226,8 @@
}
persistCustomNodeTypeDefs(customNTDefs);
- // inform cluster
- if (eventChannel != null) {
+ // inform cluster if this is not an external invocation
+ if (!external && eventChannel != null) {
eventChannel.registered(ntDefs);
}
@@ -237,8 +252,25 @@
* @throws RepositoryException if another error occurs
* @see #unregisterNodeType(QName)
*/
- public synchronized void unregisterNodeTypes(Collection ntNames)
+ public void unregisterNodeTypes(Collection ntNames)
throws NoSuchNodeTypeException, RepositoryException {
+
+ unregisterNodeTypes(ntNames, false);
+ }
+
+ /**
+ * Internal implementation of {@link #unregisterNodeTypes(Collection)}
+ *
+ * @param ntNames a collection of <code>QName</code> objects denoting the
+ * node types to be unregistered
+ * @param external whether this invocation should be considered external
+ * @throws NoSuchNodeTypeException if any of the specified names does not
+ * denote a registered node type.
+ * @throws RepositoryException if another error occurs
+ */
+ private synchronized void unregisterNodeTypes(Collection ntNames, boolean external)
+ throws NoSuchNodeTypeException, RepositoryException {
+
// do some preliminary checks
for (Iterator iter = ntNames.iterator(); iter.hasNext();) {
QName ntName = (QName) iter.next();
@@ -273,6 +305,11 @@
// all preconditions are met, node types can now safely be unregistered
internalUnregister(ntNames);
+ // inform cluster if this is not an external invocation
+ if (!external && eventChannel != null) {
+ eventChannel.unregistered(ntNames);
+ }
+
// persist removal of node type definitions & notify listeners
for (Iterator iter = ntNames.iterator(); iter.hasNext();) {
QName ntName = (QName) iter.next();
@@ -307,15 +344,39 @@
}
/**
- * @param ntd
- * @return
- * @throws NoSuchNodeTypeException
- * @throws InvalidNodeTypeDefException
- * @throws RepositoryException
+ * Reregister a node type.
+ * @param ntd node type definition
+ * @return the new effective node type
+ * @throws NoSuchNodeTypeException if <code>ntd</code> refers to an
+ * unknown node type
+ * @throws InvalidNodeTypeDefException if the node type definition
+ * is invalid
+ * @throws RepositoryException if another error occurs
*/
- public synchronized EffectiveNodeType reregisterNodeType(NodeTypeDef ntd)
+ public EffectiveNodeType reregisterNodeType(NodeTypeDef ntd)
throws NoSuchNodeTypeException, InvalidNodeTypeDefException,
RepositoryException {
+
+ return reregisterNodeType(ntd, false);
+ }
+
+ /**
+ * Internal implementation of {@link #reregisterNodeType(NodeTypeDef)}.
+ *
+ * @param ntd node type definition
+ * @param external whether this invocation should be considered external
+ * @return the new effective node type
+ * @throws NoSuchNodeTypeException if <code>ntd</code> refers to an
+ * unknown node type
+ * @throws InvalidNodeTypeDefException if the node type definition
+ * is invalid
+ * @throws RepositoryException if another error occurs
+ */
+ private synchronized EffectiveNodeType reregisterNodeType(NodeTypeDef ntd,
+ boolean external)
+ throws NoSuchNodeTypeException, InvalidNodeTypeDefException,
+ RepositoryException {
+
QName name = ntd.getName();
if (!registeredNTDefs.containsKey(name)) {
throw new NoSuchNodeTypeException(name.toString());
@@ -358,6 +419,11 @@
// persist node type definitions
persistCustomNodeTypeDefs(customNTDefs);
+ // inform cluster if this is not an external invocation
+ if (!external && eventChannel != null) {
+ eventChannel.reregistered(ntd);
+ }
+
// notify listeners
notifyReRegistered(name);
return entNew;
@@ -608,19 +674,26 @@
public void externalRegistered(Collection ntDefs)
throws RepositoryException, InvalidNodeTypeDefException {
- // validate and register new node type definitions
- internalRegister(ntDefs);
- // persist new node type definitions
- for (Iterator iter = ntDefs.iterator(); iter.hasNext();) {
- NodeTypeDef ntDef = (NodeTypeDef) iter.next();
- customNTDefs.add(ntDef);
- }
- persistCustomNodeTypeDefs(customNTDefs);
- // notify listeners
- for (Iterator iter = ntDefs.iterator(); iter.hasNext();) {
- NodeTypeDef ntDef = (NodeTypeDef) iter.next();
- notifyRegistered(ntDef.getName());
- }
+ registerNodeTypes(ntDefs, true);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void externalReregistered(NodeTypeDef ntDef)
+ throws NoSuchNodeTypeException, InvalidNodeTypeDefException,
+ RepositoryException {
+
+ reregisterNodeType(ntDef, true);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void externalUnregistered(Collection ntNames)
+ throws RepositoryException, NoSuchNodeTypeException {
+
+ unregisterNodeTypes(ntNames, true);
}
//---------------------------------------------------------< overridables >