[ 
https://issues.apache.org/jira/browse/JCR-1558?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12593295#action_12593295
 ] 

Sébastien Launay commented on JCR-1558:
---------------------------------------

A solution may be to share namespaces indexes between nodes in the database.

Therefore at startup the second node will be aware of the namespace of index 11
and can load root node bundle.

Moreover the indexes will be unique in the cluster (with sequence or 
AUTO_INCREMENT feature)
which is not the case i think for the current implementation 
(NamespaceRegistryImpl) where
two indexes for two namespace indexes may overlap if they are declared at the 
same time
in two different nodes.

But it is currently not possible to use another implementation of 
NamespaceRegistry
so adding DatabaseNamespaceRegistry will refactor some part of RepositoryImpl
and repository.xml...

Another solution is to write the namespace value in the bundle instead of the 
index but it's
less efficiency and still does not prevent collision on indexes and will break 
back-compatibility.

What do you think ?

I will be pleased to submit a patch for this issue whatever the solution you 
found the best is.

> Namespace not registered yet prevent BundleDbPersistenceManager to detect 
> already existing root node and leads to workspace initialization failure in a 
> cluster environment
> ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: JCR-1558
>                 URL: https://issues.apache.org/jira/browse/JCR-1558
>             Project: Jackrabbit
>          Issue Type: Bug
>          Components: clustering, jackrabbit-core
>    Affects Versions: core 1.4.3
>         Environment: Jackrabbit 1.4.2 / Jackrabbit core 1.4.3
> MySqlPersistenceManager in clustering with two nodes and MySQL 
> 5.0.45-Debian_1ubuntu3.3-log / InnoDB tables
>            Reporter: Sébastien Launay
>
> I have two nodes in my cluster.
> When the first node starts for the first time, it creates the root node and
> register a custom namespace (rev 1) and custom node types (rev 2).
> Then it adds a child using the namespace declared before.
> Everything works fine as long as i have only one node.
> But when the second node starts for the first time, it try first to check if 
> a root node already exists (SharedItemStateManager constructor) :
>   // create root node state if it doesn't yet exist
>   if (!hasNonVirtualItemState(rootNodeId)) {
>     createRootNodeState(rootNodeId, ntReg);
>   }
> But, the call to hasNonVirtualItemState(rootNodeId) will log an non fatal 
> error but return false:
> ERROR [BundleDbPersistenceManager] failed to read bundle: 
> cafebabe-cafe-babe-cafe-babecafebabe: java.lang.IllegalStateException: 
> URIIndex not valid? javax.jcr.NamespaceException: URI for index 11 not 
> registered.
> The reason is because MySqlPersistenceManager#loadBundle(NodeId id, boolean 
> checkBeforeLoading) will retrieve
> the root node and its first level children:
> BundleBinding#readBundle(DataInputStream in, NodeId id)
> ...
>  bundle.addChildNodeEntry(readQName(in), childId)  // will fails the second 
> time
> Indeed this child name uses the custom namespace (index 11) not registered
> because the ClusterNode which consumes journal records is not yet started.
> And so on it will create the root node and will fail because the root node 
> already exists:
> ERROR [BundleDbPersistenceManager] failed to write bundle: 
> deadbeef-cafe-babe-cafe-babecafebabe
> com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException: 
> Duplicate entry 'Þ­¾ïÊþº¾Êþº¾Êþº¾' for key 1
>       at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1011)
>       at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956)
>       at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3491)
>       at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3423)
>       at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1936)
>       at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2060)
>       at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2542)
>       at 
> com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1734)
>       at com.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:995)
>       at 
> org.apache.jackrabbit.core.persistence.bundle.util.ConnectionRecoveryManager.executeStmtInternal(ConnectionRecoveryManager.java:365)
>       at 
> org.apache.jackrabbit.core.persistence.bundle.util.ConnectionRecoveryManager.executeStmtInternal(ConnectionRecoveryManager.java:292)
>       at 
> org.apache.jackrabbit.core.persistence.bundle.util.ConnectionRecoveryManager.executeStmt(ConnectionRecoveryManager.java:257)
>       at 
> org.apache.jackrabbit.core.persistence.bundle.util.ConnectionRecoveryManager.executeStmt(ConnectionRecoveryManager.java:237)
>       at 
> org.apache.jackrabbit.core.persistence.bundle.BundleDbPersistenceManager.storeBundle(BundleDbPersistenceManager.java:1270)
>       at 
> org.apache.jackrabbit.core.persistence.bundle.AbstractBundlePersistenceManager.putBundle(AbstractBundlePersistenceManager.java:703)
>       at 
> org.apache.jackrabbit.core.persistence.bundle.AbstractBundlePersistenceManager.store(AbstractBundlePersistenceManager.java:643)
>       at 
> org.apache.jackrabbit.core.persistence.bundle.BundleDbPersistenceManager.store(BundleDbPersistenceManager.java:529)
>       at 
> org.apache.jackrabbit.core.state.SharedItemStateManager.createRootNodeState(SharedItemStateManager.java:1084)
>       at 
> org.apache.jackrabbit.core.state.SharedItemStateManager.<init>(SharedItemStateManager.java:194)
>       at 
> org.apache.jackrabbit.core.RepositoryImpl.createItemStateManager(RepositoryImpl.java:1201)
>       at 
> org.apache.jackrabbit.core.RepositoryImpl$WorkspaceInfo.doInitialize(RepositoryImpl.java:1753)
>       at 
> org.apache.jackrabbit.core.RepositoryImpl$WorkspaceInfo.initialize(RepositoryImpl.java:1724)
>       at 
> org.apache.jackrabbit.core.RepositoryImpl.initWorkspace(RepositoryImpl.java:576)
>       at 
> org.apache.jackrabbit.core.RepositoryImpl.initStartupWorkspaces(RepositoryImpl.java:415)
>       at 
> org.apache.jackrabbit.core.RepositoryImpl.<init>(RepositoryImpl.java:305)
>       at 
> org.apache.jackrabbit.core.RepositoryImpl.create(RepositoryImpl.java:557)
>       at 
> org.apache.jackrabbit.core.TransientRepository$2.getRepository(TransientRepository.java:245)
>       at 
> org.apache.jackrabbit.core.TransientRepository.startRepository(TransientRepository.java:265)
>       at 
> org.apache.jackrabbit.core.TransientRepository.login(TransientRepository.java:333)
>       at 
> org.apache.jackrabbit.core.TransientRepository.login(TransientRepository.java:363)

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to