exo-jcr SVN: r4425 - jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr.
by do-not-reply@jboss.org
Author: tolusha
Date: 2011-05-25 02:24:01 -0400 (Wed, 25 May 2011)
New Revision: 4425
Modified:
jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/performance-tuning-guide.xml
Log:
EXOJCR-1187: Increase memory consuming of JCR, OutOfMemoryError: PermGen space
Modified: jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/performance-tuning-guide.xml
===================================================================
--- jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/performance-tuning-guide.xml 2011-05-24 11:00:53 UTC (rev 4424)
+++ jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/performance-tuning-guide.xml 2011-05-25 06:24:01 UTC (rev 4425)
@@ -1,323 +1,334 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
-"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="JCR.PerformanceTuningGuide">
- <?dbhtml filename="ch-jcr-performance-tuning.html"?>
-
- <title>JCR Performance Tuning Guide</title>
-
- <section>
- <title>Introduction</title>
-
- <para>This guide will show you possible ways of improving JCR
- performance.</para>
-
- <para>It is intended to GateIn Administrators and those who wants to use
- JCR features.</para>
- </section>
-
- <section>
- <title>JCR Performance and Scalability</title>
-
- <section>
- <title>Cluster configuration</title>
-
- <para><citetitle>EC2 network</citetitle>: 1Gbit</para>
-
- <para><citetitle>Servers hardware</citetitle>:<simplelist>
- <member>7.5 GB memory</member>
-
- <member>4 EC2 Compute Units (2 virtual cores with 2 EC2 Compute
- Units each)</member>
-
- <member>850 GB instance storage (2×420 GB plus 10 GB root
- partition)</member>
-
- <member>64-bit platform</member>
-
- <member>I/O Performance: High</member>
-
- <member>API name: m1.large</member>
- </simplelist></para>
-
- <note>
- <para>NFS and statistics (cacti snmp) server were located on one
- physical server.</para>
- </note>
-
- <para><citetitle>JBoss AS configuration</citetitle></para>
-
- <para><code>JAVA_OPTS: -Dprogram.name=run.sh -server -Xms4g -Xmx4g
- -XX:MaxPermSize=512m -Dorg.jboss.resolver.warning=true
- -Dsun.rmi.dgc.client.gcInterval=3600000
- -Dsun.rmi.dgc.server.gcInterval=3600000 -XX:+UseParallelGC
- -Djava.net.preferIPv4Stack=true</code></para>
- </section>
-
- <section>
- <title>JCR Clustered Performance</title>
-
- <para>Benchmark test using webdav (Complex read/write load test
- (benchmark)) with 20K same file. To obtain per-operation results we have
- used custom output from the testscase threads to CSV file.</para>
-
- <para><citetitle>Read operation</citetitle>:<simplelist>
- <member>Warm-up iterations: 100</member>
-
- <member>Run iterations: 2000</member>
-
- <member>Background writing threads: 25</member>
-
- <member>Reading threads: 225</member>
- </simplelist></para>
-
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/perf_EC2_results.jpg" />
- </imageobject>
- </mediaobject>
-
- <table>
- <title></title>
-
- <tgroup cols="4">
- <thead>
- <row>
- <entry>Nodes count</entry>
-
- <entry>tps</entry>
-
- <entry> Responses >2s</entry>
-
- <entry>Responses >4s</entry>
- </row>
- </thead>
-
- <tbody>
- <row>
- <entry>1</entry>
-
- <entry>523</entry>
-
- <entry>6.87%</entry>
-
- <entry>1.27% </entry>
- </row>
-
- <row>
- <entry>2</entry>
-
- <entry>1754</entry>
-
- <entry>0.64% </entry>
-
- <entry>0.08% </entry>
- </row>
-
- <row>
- <entry>3</entry>
-
- <entry>2388</entry>
-
- <entry>0.49% </entry>
-
- <entry>0.09% </entry>
- </row>
-
- <row>
- <entry>4</entry>
-
- <entry>2706</entry>
-
- <entry>0.46% </entry>
-
- <entry> 0.1% </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <para><citetitle>Read operaion with more threads</citetitle>:</para>
-
- <simplelist>
- <member>Warm-up iterations: 100</member>
-
- <member>Run iterations: 2000</member>
-
- <member>Background writing threads: 50</member>
-
- <member>Reading threads: 450</member>
- </simplelist>
-
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/perf_EC2_results_2.jpg" />
- </imageobject>
- </mediaobject>
-
- <table>
- <title></title>
-
- <tgroup cols="4">
- <thead>
- <row>
- <entry>Nodes count</entry>
-
- <entry>tps</entry>
-
- <entry>Responses >2s</entry>
-
- <entry>Responses >4s</entry>
- </row>
- </thead>
-
- <tbody>
- <row>
- <entry>1</entry>
-
- <entry>116</entry>
-
- <entry>?</entry>
-
- <entry>?</entry>
- </row>
-
- <row>
- <entry>2</entry>
-
- <entry>1558</entry>
-
- <entry>6.1%</entry>
-
- <entry>0.6%</entry>
- </row>
-
- <row>
- <entry>3</entry>
-
- <entry>2242</entry>
-
- <entry>3.1%</entry>
-
- <entry>0.38%</entry>
- </row>
-
- <row>
- <entry>4</entry>
-
- <entry>2756 </entry>
-
- <entry>2.2%</entry>
-
- <entry>0.41%</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </section>
- </section>
-
- <section>
- <title>Performance Tuning Guide</title>
-
- <section>
- <title>JBoss AS Tuning</title>
-
- <para>You can use <parameter>maxThreads</parameter> parameter to
- increase maximum amount of threads that can be launched in AS instance.
- This can improve performance if you need a high level of concurrency.
- also you can use <code>-XX:+UseParallelGC</code> java directory to use
- paralel garbage collector.</para>
-
- <tip>
- <para>Beware of setting <parameter>maxThreads</parameter> too big,
- this can cause <exceptionname>OutOfMemoryError</exceptionname>. We've
- got it with <code>maxThreads=1250</code> on such machine:</para>
-
- <simplelist>
- <member>7.5 GB memory</member>
-
- <member>4 EC2 Compute Units (2 virtual cores with 2 EC2 Compute
- Units each)</member>
-
- <member>850 GB instance storage (2×420 GB plus 10 GB root
- partition)</member>
-
- <member>64-bit platform</member>
-
- <member>I/O Performance: High</member>
-
- <member>API name: m1.large</member>
-
- <member>java -Xmx 4g</member>
- </simplelist>
- </tip>
- </section>
-
- <section>
- <title>JCR Cache Tuning</title>
-
- <para><citetitle>Cache size</citetitle></para>
-
- <para>JCR-cluster implementation is built using JBoss Cache as
- distributed, replicated cache. But there is one particularity related to
- remove action in it. Speed of this operation depends on the actual size
- of cache. As many nodes are currently in cache as much time is needed to
- remove one particular node (subtree) from it.</para>
-
- <para><citetitle>Eviction</citetitle></para>
-
- <para>Manipulations with eviction <parameter>wakeUpInterval</parameter>
- value doestn't affect on performance. Performance results with values
- from 500 up to 3000 are approximately equal.</para>
-
- <para><citetitle>Transaction Timeout</citetitle></para>
-
- <para>Using short timeout for long transactions such as Export/Import,
- removing huge subtree defined timeout may cause
- <exceptionname>TransactionTimeoutException</exceptionname>. [TODO] put
- recomended timeout value</para>
- </section>
-
- <section>
- <title>Clustering</title>
-
- <para>For performance it is better to have loadbalacer, DB server and
- shared NFS on different computers. If in some reasons you see that one
- node gets more load than others you can decrease this load using load
- value in load balancer.</para>
-
- <para><citetitle>JGroups configuration</citetitle></para>
-
- <para>It's recommended to use "multiplexer stack" feature present in
- JGroups. It is set by default in eXo JCR and offers higher performance
- in cluster, using less network connections also. If there are two or
- more clusters in your network, please check that they use different
- ports and different cluster names.</para>
-
- <para><citetitle>Write performance in cluster</citetitle></para>
-
- <para>Exo JCR implementation uses Lucene indexing engine to provide
- search capabilities. But Lucene brings some limitations for write
- operations: it can perform indexing only in one thread. Thats why write
- performance in cluster is not higher than in singleton environment. Data
- is indexed on coordinator node, so increasing write-load on cluster may
- lead to ReplicationTimeout exception. It occurs because writing threads
- queue in the indexer and under high load timeout for replication to
- coordinator will be exceeded.</para>
-
- <para>Taking in consideration this fact, it is recommended to exceed
- <parameter>replTimeout</parameter> value in cache configurations in case
- of high write-load.</para>
-
- <para><citetitle>Replication timeout</citetitle></para>
-
- <para>Some operations may take too much time. So if you get
- <exceptionname>ReplicationTimeoutException</exceptionname> try
- increasing replication timeout:<programlisting> <clustering mode="replication" clusterName="${jbosscache-cluster-name}">
- ...
- <sync replTimeout="60000" />
- </clustering></programlisting>value is set in miliseconds.</para>
- </section>
- </section>
-</chapter>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter id="JCR.PerformanceTuningGuide">
+ <?dbhtml filename="ch-jcr-performance-tuning.html"?>
+
+ <title>JCR Performance Tuning Guide</title>
+
+ <section>
+ <title>Introduction</title>
+
+ <para>This guide will show you possible ways of improving JCR
+ performance.</para>
+
+ <para>It is intended to GateIn Administrators and those who wants to use
+ JCR features.</para>
+ </section>
+
+ <section>
+ <title>JCR Performance and Scalability</title>
+
+ <section>
+ <title>Cluster configuration</title>
+
+ <para><citetitle>EC2 network</citetitle>: 1Gbit</para>
+
+ <para><citetitle>Servers hardware</citetitle>:<simplelist>
+ <member>7.5 GB memory</member>
+
+ <member>4 EC2 Compute Units (2 virtual cores with 2 EC2 Compute
+ Units each)</member>
+
+ <member>850 GB instance storage (2×420 GB plus 10 GB root
+ partition)</member>
+
+ <member>64-bit platform</member>
+
+ <member>I/O Performance: High</member>
+
+ <member>API name: m1.large</member>
+ </simplelist></para>
+
+ <note>
+ <para>NFS and statistics (cacti snmp) server were located on one
+ physical server.</para>
+ </note>
+
+ <para><citetitle>JBoss AS configuration</citetitle></para>
+
+ <para><code>JAVA_OPTS: -Dprogram.name=run.sh -server -Xms4g -Xmx4g
+ -XX:MaxPermSize=512m -Dorg.jboss.resolver.warning=true
+ -Dsun.rmi.dgc.client.gcInterval=3600000
+ -Dsun.rmi.dgc.server.gcInterval=3600000 -XX:+UseParallelGC
+ -Djava.net.preferIPv4Stack=true</code></para>
+ </section>
+
+ <section>
+ <title>JCR Clustered Performance</title>
+
+ <para>Benchmark test using webdav (Complex read/write load test
+ (benchmark)) with 20K same file. To obtain per-operation results we have
+ used custom output from the testscase threads to CSV file.</para>
+
+ <para><citetitle>Read operation</citetitle>:<simplelist>
+ <member>Warm-up iterations: 100</member>
+
+ <member>Run iterations: 2000</member>
+
+ <member>Background writing threads: 25</member>
+
+ <member>Reading threads: 225</member>
+ </simplelist></para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/perf_EC2_results.jpg" />
+ </imageobject>
+ </mediaobject>
+
+ <table>
+ <title></title>
+
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Nodes count</entry>
+
+ <entry>tps</entry>
+
+ <entry>Responses >2s</entry>
+
+ <entry>Responses >4s</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry>1</entry>
+
+ <entry>523</entry>
+
+ <entry>6.87%</entry>
+
+ <entry>1.27%</entry>
+ </row>
+
+ <row>
+ <entry>2</entry>
+
+ <entry>1754</entry>
+
+ <entry>0.64%</entry>
+
+ <entry>0.08%</entry>
+ </row>
+
+ <row>
+ <entry>3</entry>
+
+ <entry>2388</entry>
+
+ <entry>0.49%</entry>
+
+ <entry>0.09%</entry>
+ </row>
+
+ <row>
+ <entry>4</entry>
+
+ <entry>2706</entry>
+
+ <entry>0.46%</entry>
+
+ <entry>0.1%</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para><citetitle>Read operaion with more threads</citetitle>:</para>
+
+ <simplelist>
+ <member>Warm-up iterations: 100</member>
+
+ <member>Run iterations: 2000</member>
+
+ <member>Background writing threads: 50</member>
+
+ <member>Reading threads: 450</member>
+ </simplelist>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/perf_EC2_results_2.jpg" />
+ </imageobject>
+ </mediaobject>
+
+ <table>
+ <title></title>
+
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Nodes count</entry>
+
+ <entry>tps</entry>
+
+ <entry>Responses >2s</entry>
+
+ <entry>Responses >4s</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry>1</entry>
+
+ <entry>116</entry>
+
+ <entry>?</entry>
+
+ <entry>?</entry>
+ </row>
+
+ <row>
+ <entry>2</entry>
+
+ <entry>1558</entry>
+
+ <entry>6.1%</entry>
+
+ <entry>0.6%</entry>
+ </row>
+
+ <row>
+ <entry>3</entry>
+
+ <entry>2242</entry>
+
+ <entry>3.1%</entry>
+
+ <entry>0.38%</entry>
+ </row>
+
+ <row>
+ <entry>4</entry>
+
+ <entry>2756</entry>
+
+ <entry>2.2%</entry>
+
+ <entry>0.41%</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ </section>
+
+ <section>
+ <title>Performance Tuning Guide</title>
+
+ <section>
+ <title>JBoss AS Tuning</title>
+
+ <para>You can use <parameter>maxThreads</parameter> parameter to
+ increase maximum amount of threads that can be launched in AS instance.
+ This can improve performance if you need a high level of concurrency.
+ also you can use <code>-XX:+UseParallelGC</code> java directory to use
+ paralel garbage collector.</para>
+
+ <tip>
+ <para>Beware of setting <parameter>maxThreads</parameter> too big,
+ this can cause <exceptionname>OutOfMemoryError</exceptionname>. We've
+ got it with <code>maxThreads=1250</code> on such machine:</para>
+
+ <simplelist>
+ <member>7.5 GB memory</member>
+
+ <member>4 EC2 Compute Units (2 virtual cores with 2 EC2 Compute
+ Units each)</member>
+
+ <member>850 GB instance storage (2×420 GB plus 10 GB root
+ partition)</member>
+
+ <member>64-bit platform</member>
+
+ <member>I/O Performance: High</member>
+
+ <member>API name: m1.large</member>
+
+ <member>java -Xmx 4g</member>
+ </simplelist>
+ </tip>
+ </section>
+
+ <section>
+ <title>JCR Cache Tuning</title>
+
+ <para><citetitle>Cache size</citetitle></para>
+
+ <para>JCR-cluster implementation is built using JBoss Cache as
+ distributed, replicated cache. But there is one particularity related to
+ remove action in it. Speed of this operation depends on the actual size
+ of cache. As many nodes are currently in cache as much time is needed to
+ remove one particular node (subtree) from it.</para>
+
+ <para><citetitle>Eviction</citetitle></para>
+
+ <para>Manipulations with eviction <parameter>wakeUpInterval</parameter>
+ value doestn't affect on performance. Performance results with values
+ from 500 up to 3000 are approximately equal.</para>
+
+ <para><citetitle>Transaction Timeout</citetitle></para>
+
+ <para>Using short timeout for long transactions such as Export/Import,
+ removing huge subtree defined timeout may cause
+ <exceptionname>TransactionTimeoutException</exceptionname>. [TODO] put
+ recomended timeout value</para>
+ </section>
+
+ <section>
+ <title>Clustering</title>
+
+ <para>For performance it is better to have loadbalacer, DB server and
+ shared NFS on different computers. If in some reasons you see that one
+ node gets more load than others you can decrease this load using load
+ value in load balancer.</para>
+
+ <para><citetitle>JGroups configuration</citetitle></para>
+
+ <para>It's recommended to use "multiplexer stack" feature present in
+ JGroups. It is set by default in eXo JCR and offers higher performance
+ in cluster, using less network connections also. If there are two or
+ more clusters in your network, please check that they use different
+ ports and different cluster names.</para>
+
+ <para><citetitle>Write performance in cluster</citetitle></para>
+
+ <para>Exo JCR implementation uses Lucene indexing engine to provide
+ search capabilities. But Lucene brings some limitations for write
+ operations: it can perform indexing only in one thread. Thats why write
+ performance in cluster is not higher than in singleton environment. Data
+ is indexed on coordinator node, so increasing write-load on cluster may
+ lead to ReplicationTimeout exception. It occurs because writing threads
+ queue in the indexer and under high load timeout for replication to
+ coordinator will be exceeded.</para>
+
+ <para>Taking in consideration this fact, it is recommended to exceed
+ <parameter>replTimeout</parameter> value in cache configurations in case
+ of high write-load.</para>
+
+ <para><citetitle>Replication timeout</citetitle></para>
+
+ <para>Some operations may take too much time. So if you get
+ <exceptionname>ReplicationTimeoutException</exceptionname> try
+ increasing replication timeout:<programlisting> <clustering mode="replication" clusterName="${jbosscache-cluster-name}">
+ ...
+ <sync replTimeout="60000" />
+ </clustering></programlisting>value is set in miliseconds.</para>
+ </section>
+
+ <section>
+ <title>JVM parameters</title>
+
+ <para><citetitle>PermGen space size</citetitle></para>
+
+ <para>if it is used ISPN, needs to increase the PermGen size to 256M due
+ to the latest versions of JGroups that are required for ISPN. In case is
+ it is used JBC can keep on using JGroups 2.6.13.GA thus doesn't need to
+ increase the PermGen size.</para>
+ </section>
+ </section>
+</chapter>
13 years
exo-jcr SVN: r4424 - in jcr/branches/1.12.x: patch/1.12.8-GA and 2 other directories.
by do-not-reply@jboss.org
Author: paristote
Date: 2011-05-24 07:00:53 -0400 (Tue, 24 May 2011)
New Revision: 4424
Added:
jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1572/
jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1572/readme.txt
Removed:
jcr/branches/1.12.x/patch/1.12.8-GA/JCR-1572/
Modified:
jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/MultiIndex.java
Log:
JCR-1572
What is the problem to fix?
* Tested EPP 5.0.1 with 19 000 users created thanks to crash and its advanced command addusers that you can found here https://github.com/exoplatform/gatein-stuff. The table JCR_SITEM contains 4,3 Millions of rows and JCR_SVALUE contains 3,2 Millions of rows, in this case if I try to re-index my content that contains 1 216 000 nodes, the re-indexing takes 3 h 40 minutes on my laptop which is a dual core. The idea of my patch proposal is to propose a multi-threaded re-indexing mechanism in order to take advantage of multi-cores which is commonly used now, thanks to this patch the re-indexing takes 2 h 20 minutes on my laptop knowing that the main bottelneck is the db.
Please check the patch and if it is ok ask the QA to load a big table and re-index it with and without the patch to see the gain in their environment.
How is the problem fixed?
* involve several threads in jcr indexing operation
Modified: jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/MultiIndex.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/MultiIndex.java 2011-05-24 10:44:25 UTC (rev 4423)
+++ jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/MultiIndex.java 2011-05-24 11:00:53 UTC (rev 4424)
@@ -43,9 +43,16 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Queue;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicReference;
import javax.jcr.ItemNotFoundException;
import javax.jcr.RepositoryException;
@@ -214,6 +221,11 @@
private boolean reindexing = false;
/**
+ * Flag indicating whether the index is stopped.
+ */
+ private volatile boolean stopped;
+
+ /**
* The index format version of this multi index.
*/
private final IndexFormatVersion version;
@@ -314,6 +326,14 @@
setReadWrite();
}
this.indexNames.setMultiIndex(this);
+ // Add a hook that will stop the threads if they are still running
+ Runtime.getRuntime().addShutdownHook(new Thread()
+ {
+ public void run()
+ {
+ stopped = true;
+ }
+ });
}
/**
@@ -374,11 +394,10 @@
reindexing = true;
try
{
- long count = 0;
// traverse and index workspace
executeAndLog(new Start(Action.INTERNAL_TRANSACTION));
// NodeData rootState = (NodeData) stateMgr.getItemData(rootId);
- count = createIndex(indexingTree.getIndexingRoot(), stateMgr, count);
+ long count = createIndex(indexingTree.getIndexingRoot(), stateMgr);
executeAndLog(new Commit(getTransactionId()));
log.info("Created initial index for {} nodes", new Long(count));
releaseMultiReader();
@@ -958,6 +977,7 @@
}
}
}
+ this.stopped = true;
}
/**
@@ -1304,44 +1324,118 @@
* @throws RepositoryException
* if any other error occurs
*/
- private long createIndex(NodeData node, ItemDataConsumer stateMgr, long count) throws IOException,
+ private long createIndex(NodeData node, ItemDataConsumer stateMgr) throws IOException,
RepositoryException
{
+ MultithreadedIndexing indexing = new MultithreadedIndexing(node, stateMgr);
+ return indexing.launch(false);
+ }
+
+ /**
+ * Recursively creates an index starting with the NodeState
+ * <code>node</code>.
+ *
+ * @pamam tasks
+ * the queue of existing indexing tasks
+ * @param node
+ * the current NodeState.
+ * @param stateMgr
+ * the shared item state manager.
+ * @param count
+ * the number of nodes already indexed.
+ * @throws IOException
+ * if an error occurs while writing to the index.
+ * @throws ItemStateException
+ * if an node state cannot be found.
+ * @throws RepositoryException
+ * if any other error occurs
+ * @throws InterruptedException
+ * if the task has been interrupted
+ */
+ private void createIndex(final Queue<Callable<Void>> tasks, final NodeData node, final ItemDataConsumer stateMgr, final AtomicLong count) throws IOException,
+ RepositoryException, InterruptedException
+ {
+ if (stopped)
+ {
+ throw new InterruptedException();
+ }
// NodeId id = node.getNodeId();
if (indexingTree.isExcluded(node))
{
- return count;
+ return;
}
- executeAndLog(new AddNode(getTransactionId(), node.getIdentifier()));
- if (++count % 100 == 0)
+ executeAndLog(new AddNode(getTransactionId(), node.getIdentifier(), true));
+ if (count.incrementAndGet() % 1000 == 0)
{
-
- log.info("indexing... {} ({})", node.getQPath().getAsString(), new Long(count));
+ log.info("indexing... {} ({})", node.getQPath().getAsString(), new Long(count.get()));
}
- if (count % 10 == 0)
+ synchronized (this)
{
- checkIndexingQueue(true);
+ if (count.get() % 10 == 0)
+ {
+ checkIndexingQueue(true);
+ }
+ checkVolatileCommit();
}
- checkVolatileCommit();
List<NodeData> children = stateMgr.getChildNodesData(node);
- for (NodeData nodeData : children)
+ for (final NodeData nodeData : children)
{
-
- NodeData childState = (NodeData)stateMgr.getItemData(nodeData.getIdentifier());
- if (childState == null)
+ Callable<Void> task = new Callable<Void>()
{
- handler.getOnWorkspaceInconsistencyHandler().handleMissingChildNode(
- new ItemNotFoundException("Child not found "), handler, nodeData.getQPath(), node, nodeData);
- }
+ public Void call() throws Exception
+ {
+ createIndex(tasks, node, stateMgr, count, nodeData);
+ return null;
+ }
- if (nodeData != null)
+ };
+ if (!tasks.offer(task))
{
- count = createIndex(nodeData, stateMgr, count);
+ // All threads have tasks to do so we do it ourself
+ createIndex(tasks, node, stateMgr, count, nodeData);
}
}
+ }
+
+ /**
+ * Recursively creates an index starting with the NodeState
+ * <code>node</code>.
+ *
+ * @pamam tasks
+ * the queue of existing indexing tasks
+ * @param node
+ * the current NodeState.
+ * @param stateMgr
+ * the shared item state manager.
+ * @param count
+ * the number of nodes already indexed.
+ * @param nodeData
+ * the node data to index.
+ * @throws IOException
+ * if an error occurs while writing to the index.
+ * @throws ItemStateException
+ * if an node state cannot be found.
+ * @throws RepositoryException
+ * if any other error occurs
+ * @throws InterruptedException
+ * if the task has been interrupted
+ */
+ private void createIndex(final Queue<Callable<Void>> tasks, final NodeData node,
+ final ItemDataConsumer stateMgr, final AtomicLong count, final NodeData nodeData)
+ throws RepositoryException, IOException, InterruptedException
+ {
+ NodeData childState = (NodeData)stateMgr.getItemData(nodeData.getIdentifier());
+ if (childState == null)
+ {
+ handler.getOnWorkspaceInconsistencyHandler().handleMissingChildNode(
+ new ItemNotFoundException("Child not found "), handler, nodeData.getQPath(), node, nodeData);
+ }
- return count;
+ if (nodeData != null)
+ {
+ createIndex(tasks, nodeData, stateMgr, count);
+ }
}
/**
@@ -1857,6 +1951,8 @@
*/
private Document doc;
+ private boolean synch;
+
/**
* Creates a new AddNode action.
*
@@ -1867,8 +1963,22 @@
*/
AddNode(long transactionId, String uuid)
{
+ this(transactionId, uuid, false);
+ }
+
+ /**
+ * Creates a new AddNode action.
+ *
+ * @param transactionId
+ * the id of the transaction that executes this action.
+ * @param uuid
+ * the uuid of the node to add.
+ */
+ AddNode(long transactionId, String uuid, boolean synch)
+ {
super(transactionId, Action.TYPE_ADD_NODE);
this.uuid = uuid;
+ this.synch = synch;
}
/**
@@ -1928,7 +2038,17 @@
}
if (doc != null)
{
- index.volatileIndex.addDocuments(new Document[]{doc});
+ if (synch)
+ {
+ synchronized (index)
+ {
+ index.volatileIndex.addDocuments(new Document[]{doc});
+ }
+ }
+ else
+ {
+ index.volatileIndex.addDocuments(new Document[]{doc});
+ }
}
}
@@ -2540,7 +2660,206 @@
}
}
}
+
+ /**
+ * This class is used to index a node and its descendants nodes with several threads
+ */
+ private class MultithreadedIndexing
+ {
+ /**
+ * This instance of {@link AtomicReference} will contain the exception meet if any exception has occurred
+ */
+ private final AtomicReference<Exception> exception = new AtomicReference<Exception>();
+
+ /**
+ * The total amount of threads used for the indexing
+ */
+ private final int nThreads = Runtime.getRuntime().availableProcessors();
+
+ /**
+ * The {@link CountDownLatch} used to notify that the indexing is over
+ */
+ private final CountDownLatch endSignal = new CountDownLatch(nThreads);
+
+ /**
+ * The total amount of threads currently working
+ */
+ private final AtomicInteger runningThreads = new AtomicInteger();
+
+ /**
+ * The total amount of nodes already indexed
+ */
+ private final AtomicLong count = new AtomicLong();
+
+ /**
+ * The list of indexing tasks left to do
+ */
+ private final Queue<Callable<Void>> tasks = new LinkedBlockingQueue<Callable<Void>>(nThreads)
+ {
+ private static final long serialVersionUID = 1L;
+ @Override
+ public Callable<Void> poll()
+ {
+ Callable<Void> task;
+ synchronized (runningThreads)
+ {
+ if ((task = super.poll()) != null)
+ {
+ runningThreads.incrementAndGet();
+ }
+ }
+ return task;
+ }
+
+ @Override
+ public boolean offer(Callable<Void> o)
+ {
+ if (super.offer(o))
+ {
+ synchronized (runningThreads)
+ {
+ runningThreads.notifyAll();
+ }
+ return true;
+ }
+ return false;
+ }
+ };
+
+ /**
+ * The task that all the indexing threads have to execute
+ */
+ private final Runnable indexingTask = new Runnable()
+ {
+ public void run()
+ {
+ while (exception.get() == null)
+ {
+ Callable<Void> task;
+ while (exception.get() == null && (task = tasks.poll()) != null)
+ {
+ try
+ {
+ task.call();
+ }
+ catch (InterruptedException e)
+ {
+ Thread.currentThread().interrupt();
+ }
+ catch (Exception e)
+ {
+ exception.set(e);
+ }
+ finally
+ {
+ synchronized (runningThreads)
+ {
+ runningThreads.decrementAndGet();
+ runningThreads.notifyAll();
+ }
+ }
+ }
+ synchronized (runningThreads)
+ {
+ if (exception.get() == null && (runningThreads.get() > 0))
+ {
+ try
+ {
+ runningThreads.wait();
+ }
+ catch (InterruptedException e)
+ {
+ Thread.currentThread().interrupt();
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ endSignal.countDown();
+ }
+ };
+
+ /**
+ * Default constructor
+ * @param node
+ * the current NodeState.
+ * @param stateMgr
+ * the shared item state manager.
+ */
+ public MultithreadedIndexing(final NodeData node, final ItemDataConsumer stateMgr)
+ {
+ tasks.offer(new Callable<Void>()
+ {
+ public Void call() throws Exception
+ {
+ createIndex(tasks, node, stateMgr, count);
+ return null;
+ }
+ });
+ }
+
+ /**
+ * Launches the indexing
+ * @param asynchronous indicates whether or not the current thread needs to wait until the
+ * end of the indexing
+ * @return the total amount of nodes that have been indexed. <code>-1</code> in case of an
+ * asynchronous indexing
+ * @throws IOException
+ * if an error occurs while writing to the index.
+ * @throws ItemStateException
+ * if an node state cannot be found.
+ * @throws RepositoryException
+ * if any other error occurs
+ */
+ public long launch(boolean asynchronous) throws IOException, RepositoryException
+ {
+ startThreads();
+ if (!asynchronous)
+ {
+ try
+ {
+ endSignal.await();
+ if (exception.get() != null)
+ {
+ if (exception.get() instanceof IOException)
+ {
+ throw (IOException)exception.get();
+ }
+ else if (exception.get() instanceof RepositoryException)
+ {
+ throw (RepositoryException)exception.get();
+ }
+ else
+ {
+ throw new RuntimeException("Error while indexing", exception.get());
+ }
+ }
+ return count.get();
+ }
+ catch (InterruptedException e)
+ {
+ Thread.currentThread().interrupt();
+ }
+ }
+ return -1L;
+ }
+
+ /**
+ * Starts all the indexing threads
+ */
+ private void startThreads()
+ {
+ for (int i=0; i < nThreads; i++)
+ {
+ (new Thread(indexingTask, "Indexing Thread #" + (i + 1))).start();
+ }
+ }
+ }
+
/**
* @see org.exoplatform.services.jcr.impl.core.query.lucene.IndexUpdateMonitorListener#onUpdateInProgressChange(boolean)
*/
Added: jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1572/readme.txt
===================================================================
--- jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1572/readme.txt (rev 0)
+++ jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1572/readme.txt 2011-05-24 11:00:53 UTC (rev 4424)
@@ -0,0 +1,65 @@
+Summary
+
+ Status: Improve the re-indexing mechanism to take advantage of multi-cores
+ CCP Issue: N/A, Product Jira Issue: JCR-1572.
+ Complexity: Medium
+
+The Proposal
+Problem description
+
+What is the problem to fix?
+Tested EPP 5.0.1 with 19 000 users created thanks to crash and its advanced command addusers that you can found here https://github.com/exoplatform/gatein-stuff. The table JCR_SITEM contains 4,3 Millions of rows and JCR_SVALUE contains 3,2 Millions of rows, in this case if I try to re-index my content that contains 1 216 000 nodes, the re-indexing takes 3 h 40 minutes on my laptop which is a dual core. The idea of my patch proposal is to propose a multi-threaded re-indexing mechanism in order to take advantage of multi-cores which is commonly used now, thanks to this patch the re-indexing takes 2 h 20 minutes on my laptop knowing that the main bottelneck is the db.
+
+Please check the patch and if it is ok ask the QA to load a big table and re-index it with and without the patch to see the gain in their environment.
+Fix description
+
+How is the problem fixed?
+
+* involve several threads in jcr indexing operation* *
+
+Patch information:
+Patch files: JCR-1572.patch
+
+Tests to perform
+
+Reproduction test
+* No
+
+Tests performed at DevLevel
+* functional testing in JCR project
+
+Tests performed at QA/Support Level
+*
+
+Documentation changes
+
+Documentation changes:
+* No
+
+Configuration changes
+
+Configuration changes:
+* No
+
+Will previous configuration continue to work?
+* Yes
+
+Risks and impacts
+
+Can this bug fix have any side effects on current client projects?
+ No
+
+Is there a performance risk/cost?
+* No
+
+Validation (PM/Support/QA)
+
+PM Comment
+* PL review: patch validated
+
+Support Comment
+* Support review: patch validated
+
+QA Feedbacks
+*
+
13 years
exo-jcr SVN: r4423 - in jcr/branches/1.12.x: patch/1.12.8-GA and 2 other directories.
by do-not-reply@jboss.org
Author: paristote
Date: 2011-05-24 06:44:25 -0400 (Tue, 24 May 2011)
New Revision: 4423
Added:
jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1577/
jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1577/readme.txt
Removed:
jcr/branches/1.12.x/patch/1.12.8-GA/JCR-1577/
Modified:
jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/DefaultChangesFilter.java
Log:
JCR-1577
Check in DefaultChangesFilter if we use the right ids in case of a IOException while updating the index of the parentSearchManager
How is the problem fixed?
Fixed by passing correct lists of added and removed nodes on Exception to queryHandler.logErrorChanges(List, List);
Modified: jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/DefaultChangesFilter.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/DefaultChangesFilter.java 2011-05-24 10:24:41 UTC (rev 4422)
+++ jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/DefaultChangesFilter.java 2011-05-24 10:44:25 UTC (rev 4423)
@@ -117,7 +117,7 @@
log.error("Error indexing changes " + e, e);
try
{
- parentHandler.logErrorChanges(removedNodes, addedNodes);
+ parentHandler.logErrorChanges(parentRemovedNodes, parentAddedNodes);
}
catch (IOException ioe)
{
Added: jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1577/readme.txt
===================================================================
--- jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1577/readme.txt (rev 0)
+++ jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1577/readme.txt 2011-05-24 10:44:25 UTC (rev 4423)
@@ -0,0 +1,106 @@
+Summary
+
+ Status: Check in DefaultChangesFilter if we use the right ids in case of a IOException while updating the index of the parentSearchManager
+ CCP Issue: N/A, Product Jira Issue: JCR-1577.
+ Complexity: N/A
+
+The Proposal
+Problem description
+
+What is the problem to fix?
+In the method DefaultChangesFilter.doUpdateIndex(Set<String> removedNodes, Set<String> addedNodes, Set<String> parentRemovedNodes,
+Set<String> parentAddedNodes), I see
+try
+ {
+ parentSearchManager.updateIndex(parentRemovedNodes, parentAddedNodes);
+ }
+ catch (RepositoryException e)
+ {
+ log.error("Error indexing changes " + e, e);
+ }
+ catch (IOException e)
+ {
+ log.error("Error indexing changes " + e, e);
+ try
+ {
+ parentHandler.logErrorChanges(removedNodes, addedNodes);
+ }
+ catch (IOException ioe)
+ {
+ log.warn("Exception occure when errorLog writed. Error log is not complete. " + ioe, ioe);
+ }
+ }
+
+shouldn't it be:
+try
+ {
+ parentSearchManager.updateIndex(parentRemovedNodes, parentAddedNodes);
+ }
+ catch (RepositoryException e)
+ {
+ log.error("Error indexing changes " + e, e);
+ }
+ catch (IOException e)
+ {
+ log.error("Error indexing changes " + e, e);
+ try
+ {
+ parentHandler.logErrorChanges(parentRemovedNodes, parentAddedNodes);
+ }
+ catch (IOException ioe)
+ {
+ log.warn("Exception occure when errorLog writed. Error log is not complete. " + ioe, ioe);
+ }
+ }
+Fix description
+
+How is the problem fixed?
+
+ Fixed by passing correct lists of added and removed nodes on Exception to queryHandler.logErrorChanges(List, List);
+
+Patch information: JCR-1577.patch
+
+Tests to perform
+
+Reproduction test
+ none;
+
+Tests performed at DevLevel
+
+ Full set of eXo and TCK test with manual tests in cluster;
+
+Tests performed at QA/Support Level
+*
+
+Documentation changes
+
+Documentation changes:
+ none;
+
+Configuration changes
+
+Configuration changes:
+ none;
+
+Will previous configuration continue to work?
+ yes;
+
+Risks and impacts
+
+Can this bug fix have any side effects on current client projects?
+ none;
+
+Is there a performance risk/cost?
+ no;
+
+Validation (PM/Support/QA)
+
+PM Comment
+* PL review: patch validated
+
+Support Comment
+* Support review: patch validated
+
+QA Feedbacks
+*
+
13 years
exo-jcr SVN: r4422 - in jcr/branches/1.12.x: exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core and 13 other directories.
by do-not-reply@jboss.org
Author: paristote
Date: 2011-05-24 06:24:41 -0400 (Tue, 24 May 2011)
New Revision: 4422
Added:
jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1611/readme.txt
Modified:
jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/dataflow/ItemDataConsumer.java
jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/NodeImpl.java
jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionDataManager.java
jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/DefaultItemDataCopyVisitor.java
jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/ACLInheritanceSupportedWorkspaceDataManager.java
jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/WorkspacePersistentDataManager.java
jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/LocalWorkspaceStorageDataManagerProxy.java
jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/SessionChangesLog.java
jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/TransactionableDataManager.java
jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/inmemory/InmemoryStorageConnection.java
jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/DBConstants.java
jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCStorageConnection.java
jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/HSQLDBMultiDbJDBCConnection.java
jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/HSQLDBSingleDbJDBCConnection.java
jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/MultiDbJDBCConnection.java
jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/SingleDbJDBCConnection.java
jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/HSQLDBMultiDbJDBCConnection.java
jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/HSQLDBSingleDbJDBCConnection.java
jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/MultiDbJDBCConnection.java
jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/SingleDbJDBCConnection.java
jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/statistics/StatisticsJDBCStorageConnection.java
jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/storage/WorkspaceStorageConnection.java
jcr/branches/1.12.x/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/core/TestNodeOrder.java
jcr/branches/1.12.x/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/TestCacheableWorkspaceDataManager.java
jcr/branches/1.12.x/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/TestJBossCacheWorkspaceStorageCacheInClusterMode.java
Log:
JCR-1611
What is the problem to fix?
We need to backport the fix of the jira EXOJCR-1234 to JCR 1.12.x.
How is the problem fixed?
Change the calculation way of last order number during node adding. The new order number will be as real last order number plus 1.
In previous impl it was as children nodes count plus 1.
Modified: jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/dataflow/ItemDataConsumer.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/dataflow/ItemDataConsumer.java 2011-05-24 10:07:21 UTC (rev 4421)
+++ jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/dataflow/ItemDataConsumer.java 2011-05-24 10:24:41 UTC (rev 4422)
@@ -91,6 +91,15 @@
* @return int, child nodes count
*/
int getChildNodesCount(NodeData parent) throws RepositoryException;
+
+ /**
+ * Get order number of parent's last child node.
+ *
+ * @param parent node
+ * @return int Returns last child nodes order number or -1 if there is no subnodes.
+ * @throws RepositoryException
+ */
+ int getLastOrderNumber(NodeData parent) throws RepositoryException;
/**
* Get child Properties of the parent node.
Modified: jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/NodeImpl.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/NodeImpl.java 2011-05-24 10:07:21 UTC (rev 4421)
+++ jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/NodeImpl.java 2011-05-24 10:24:41 UTC (rev 4422)
@@ -2829,7 +2829,7 @@
private int getNextChildOrderNum() throws RepositoryException
{
- return dataManager.getChildNodesCount(nodeData());
+ return dataManager.getLastOrderNumber(nodeData()) + 1;
}
/**
Modified: jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionDataManager.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionDataManager.java 2011-05-24 10:07:21 UTC (rev 4421)
+++ jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionDataManager.java 2011-05-24 10:24:41 UTC (rev 4422)
@@ -843,6 +843,17 @@
/**
* {@inheritDoc}
*/
+ public int getLastOrderNumber(NodeData parent) throws RepositoryException
+ {
+ int lastOrderNumber = changesLog.getLastChildOrderNumber(parent.getIdentifier());
+ int lastPersistedNodeOrderNumber = transactionableManager.getLastOrderNumber(parent);
+
+ return Math.max(lastPersistedNodeOrderNumber, lastOrderNumber);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public int getChildNodesCount(NodeData parent) throws RepositoryException
{
int childsCount =
Modified: jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/DefaultItemDataCopyVisitor.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/DefaultItemDataCopyVisitor.java 2011-05-24 10:07:21 UTC (rev 4421)
+++ jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/DefaultItemDataCopyVisitor.java 2011-05-24 10:24:41 UTC (rev 4422)
@@ -154,7 +154,8 @@
// If ordering is supported by the node type of the parent node of the new
// location, then the newly moved node is appended to the end of the child node list.
int orderNum = 0;
- if (ntManager.isOrderableChildNodesSupported(parent.getPrimaryTypeName(), parent.getMixinTypeNames()))
+ if (level == 0
+ && ntManager.isOrderableChildNodesSupported(parent.getPrimaryTypeName(), parent.getMixinTypeNames()))
{
orderNum = calculateNewNodeOrderNumber();
}
@@ -264,7 +265,7 @@
protected int calculateNewNodeOrderNumber() throws RepositoryException
{
- return dataManager.getChildNodesCount(curParent());
+ return dataManager.getLastOrderNumber(curParent()) + 1;
}
protected QPath calculateNewNodePath(NodeData node, int level) throws RepositoryException
Modified: jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/ACLInheritanceSupportedWorkspaceDataManager.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/ACLInheritanceSupportedWorkspaceDataManager.java 2011-05-24 10:07:21 UTC (rev 4421)
+++ jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/ACLInheritanceSupportedWorkspaceDataManager.java 2011-05-24 10:24:41 UTC (rev 4422)
@@ -158,6 +158,14 @@
/**
* {@inheritDoc}
*/
+ public int getLastOrderNumber(final NodeData parent) throws RepositoryException
+ {
+ return persistentManager.getLastOrderNumber(parent);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public int getChildNodesCount(final NodeData parent) throws RepositoryException
{
return persistentManager.getChildNodesCount(parent);
Modified: jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/WorkspacePersistentDataManager.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/WorkspacePersistentDataManager.java 2011-05-24 10:07:21 UTC (rev 4421)
+++ jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/WorkspacePersistentDataManager.java 2011-05-24 10:24:41 UTC (rev 4422)
@@ -473,10 +473,27 @@
con.close();
}
}
-
+
/**
* {@inheritDoc}
*/
+ @Override
+ public int getLastOrderNumber(final NodeData nodeData) throws RepositoryException
+ {
+ final WorkspaceStorageConnection con = dataContainer.openConnection();
+ try
+ {
+ return con.getLastOrderNumber(nodeData);
+ }
+ finally
+ {
+ con.close();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public int getChildNodesCount(NodeData parent) throws RepositoryException
{
final WorkspaceStorageConnection con = dataContainer.openConnection();
Modified: jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/LocalWorkspaceStorageDataManagerProxy.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/LocalWorkspaceStorageDataManagerProxy.java 2011-05-24 10:07:21 UTC (rev 4421)
+++ jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/LocalWorkspaceStorageDataManagerProxy.java 2011-05-24 10:24:41 UTC (rev 4422)
@@ -135,6 +135,14 @@
/**
* {@inheritDoc}
*/
+ public int getLastOrderNumber(final NodeData parent) throws RepositoryException
+ {
+ return storageDataManager.getLastOrderNumber(parent);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public int getChildNodesCount(final NodeData parent) throws RepositoryException
{
return storageDataManager.getChildNodesCount(parent);
Modified: jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/SessionChangesLog.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/SessionChangesLog.java 2011-05-24 10:07:21 UTC (rev 4421)
+++ jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/SessionChangesLog.java 2011-05-24 10:24:41 UTC (rev 4422)
@@ -62,11 +62,24 @@
new HashMap<String, Map<String, ItemState>>();
/**
- * Stores persisted child nodes count.
+ * Stores info for persisted child nodes by parent identifier.
+ * <br>Index in array points to:
+ * <br>0 - child nodes count
+ * <br>1 - last child order number
*/
- protected Map<String, int[]> childNodesCount = new HashMap<String, int[]>();
+ protected Map<String, int[]> childNodesInfo = new HashMap<String, int[]>();
/**
+ * Index in <code>childNodesInfo<code> value array to store child nodes count.
+ */
+ protected final int CHILD_NODES_COUNT_INDEX = 0;
+
+ /**
+ * Index in <code>childNodesInfo<code> value array to store last child order number.
+ */
+ protected final int CHILD_NODES_LAST_ORDER_NUMBER_INDEX = 1;
+
+ /**
* Create empty ChangesLog.
*
* @param sessionId
@@ -129,7 +142,7 @@
index.clear();
lastChildNodeStates.clear();
lastChildPropertyStates.clear();
- childNodesCount.clear();
+ childNodesInfo.clear();
}
/**
@@ -153,21 +166,25 @@
index.remove(item.getData().getQPath());
index.remove(new ParentIDQPathBasedKey(item));
index.remove(new IDStateBasedKey(item.getData().getIdentifier(), item.getState()));
- childNodesCount.remove(item.getData().getIdentifier());
+ childNodesInfo.remove(item.getData().getIdentifier());
lastChildNodeStates.remove(item.getData().getIdentifier());
lastChildPropertyStates.remove(item.getData().getIdentifier());
if (item.isNode() && item.isPersisted())
{
- int childCount[] = childNodesCount.get(item.getData().getParentIdentifier());
- if (childCount != null)
+ int childInfo[] = childNodesInfo.get(item.getData().getParentIdentifier());
+ if (childInfo != null)
{
if (item.isDeleted())
- ++childCount[0];
+ {
+ ++childInfo[CHILD_NODES_COUNT_INDEX];
+ }
else if (item.isAdded())
- --childCount[0];
+ {
+ --childInfo[CHILD_NODES_COUNT_INDEX];
+ }
- childNodesCount.put(item.getData().getParentIdentifier(), childCount);
+ childNodesInfo.put(item.getData().getParentIdentifier(), childInfo);
}
}
@@ -412,10 +429,17 @@
public int getChildNodesCount(String rootIdentifier)
{
- int[] childCount = childNodesCount.get(rootIdentifier);
- return childCount == null ? 0 : childCount[0];
+ int[] childInfo = childNodesInfo.get(rootIdentifier);
+ return childInfo == null ? 0 : childInfo[CHILD_NODES_COUNT_INDEX];
}
+ public int getLastChildOrderNumber(String rootIdentifier)
+ {
+
+ int[] childInfo = childNodesInfo.get(rootIdentifier);
+ return childInfo == null ? -1 : childInfo[CHILD_NODES_LAST_ORDER_NUMBER_INDEX];
+ }
+
/**
* Collect last in ChangesLog order item child changes.
*
@@ -663,16 +687,22 @@
if (item.isNode() && item.isPersisted())
{
- int[] childCount = childNodesCount.get(item.getData().getParentIdentifier());
- if (childCount == null)
- childCount = new int[1];
+ int[] childInfo = childNodesInfo.get(item.getData().getParentIdentifier());
+ if (childInfo == null)
+ {
+ childInfo = new int[2];
+ }
if (item.isDeleted())
- --childCount[0];
+ {
+ --childInfo[CHILD_NODES_COUNT_INDEX];
+ }
else if (item.isAdded())
- ++childCount[0];
-
- childNodesCount.put(item.getData().getParentIdentifier(), childCount);
+ {
+ ++childInfo[CHILD_NODES_COUNT_INDEX];
+ childInfo[CHILD_NODES_LAST_ORDER_NUMBER_INDEX] = ((NodeData)item.getData()).getOrderNumber();
+ }
+ childNodesInfo.put(item.getData().getParentIdentifier(), childInfo);
}
}
Modified: jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/TransactionableDataManager.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/TransactionableDataManager.java 2011-05-24 10:07:21 UTC (rev 4421)
+++ jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/TransactionableDataManager.java 2011-05-24 10:24:41 UTC (rev 4422)
@@ -114,6 +114,37 @@
/**
* {@inheritDoc}
*/
+ public int getLastOrderNumber(final NodeData parent) throws RepositoryException
+ {
+ if (txStarted())
+ {
+ int txLastOrderNumber = -1;
+ for (ItemState change : transactionLog.getAllStates())
+ {
+ if (change.isNode() && change.isPersisted() && change.isAdded()
+ && change.getData().getParentIdentifier().equals(parent.getIdentifier()))
+ {
+ int orderNumber = ((NodeData)change.getData()).getOrderNumber();
+ if (orderNumber > txLastOrderNumber)
+ {
+ txLastOrderNumber = orderNumber;
+ }
+ }
+ }
+
+ int lastOrderNumber = storageDataManager.getLastOrderNumber(parent);
+
+ return Math.max(lastOrderNumber, txLastOrderNumber);
+ }
+ else
+ {
+ return storageDataManager.getLastOrderNumber(parent);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public int getChildNodesCount(final NodeData parent) throws RepositoryException
{
if (txStarted())
Modified: jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/inmemory/InmemoryStorageConnection.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/inmemory/InmemoryStorageConnection.java 2011-05-24 10:07:21 UTC (rev 4421)
+++ jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/inmemory/InmemoryStorageConnection.java 2011-05-24 10:24:41 UTC (rev 4422)
@@ -126,6 +126,11 @@
return null;
}
+ public int getLastOrderNumber(NodeData nodeData) throws RepositoryException
+ {
+ return -1;
+ }
+
public int getChildNodesCount(NodeData nodeData) throws RepositoryException
{
return 0;
Modified: jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/DBConstants.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/DBConstants.java 2011-05-24 10:07:21 UTC (rev 4421)
+++ jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/DBConstants.java 2011-05-24 10:24:41 UTC (rev 4422)
@@ -128,8 +128,13 @@
* FIND_NODES_BY_PARENTID.
*/
protected String FIND_NODES_BY_PARENTID;
-
+
/**
+ * FIND_LAST_ORDER_NUMBER_BY_PARENTID.
+ */
+ protected String FIND_LAST_ORDER_NUMBER_BY_PARENTID;
+
+ /**
* FIND_NODES_COUNT_BY_PARENTID.
*/
protected String FIND_NODES_COUNT_BY_PARENTID;
Modified: jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCStorageConnection.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCStorageConnection.java 2011-05-24 10:07:21 UTC (rev 4421)
+++ jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCStorageConnection.java 2011-05-24 10:24:41 UTC (rev 4422)
@@ -151,6 +151,8 @@
protected PreparedStatement findNodesByParentId;
+ protected PreparedStatement findLastOrderNumberByParentId;
+
protected PreparedStatement findNodesCountByParentId;
protected PreparedStatement findPropertiesByParentId;
@@ -459,6 +461,11 @@
findNodesByParentId.close();
}
+ if (findLastOrderNumberByParentId != null)
+ {
+ findLastOrderNumberByParentId.close();
+ }
+
if (findNodesCountByParentId != null)
{
findNodesCountByParentId.close();
@@ -921,6 +928,44 @@
/**
* {@inheritDoc}
*/
+ public int getLastOrderNumber(NodeData parent) throws RepositoryException
+ {
+ checkIfOpened();
+ try
+ {
+ ResultSet count = findLastOrderNumberByParentIdentifier(getInternalId(parent.getIdentifier()));
+ try
+ {
+ if (count.next() && count.getInt(1) > 0)
+ {
+ return count.getInt(2);
+ }
+ else
+ {
+ return -1;
+ }
+ }
+ finally
+ {
+ try
+ {
+ count.close();
+ }
+ catch (SQLException e)
+ {
+ LOG.error("Can't close the ResultSet: " + e);
+ }
+ }
+ }
+ catch (SQLException e)
+ {
+ throw new RepositoryException(e);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public int getChildNodesCount(NodeData parent) throws RepositoryException
{
checkIfOpened();
@@ -2454,6 +2499,8 @@
protected abstract ResultSet findChildNodesByParentIdentifier(String parentIdentifier) throws SQLException;
+ protected abstract ResultSet findLastOrderNumberByParentIdentifier(String parentIdentifier) throws SQLException;
+
protected abstract ResultSet findChildNodesCountByParentIdentifier(String parentIdentifier) throws SQLException;
protected abstract ResultSet findChildPropertiesByParentIdentifier(String parentIdentifier) throws SQLException;
Modified: jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/HSQLDBMultiDbJDBCConnection.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/HSQLDBMultiDbJDBCConnection.java 2011-05-24 10:07:21 UTC (rev 4421)
+++ jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/HSQLDBMultiDbJDBCConnection.java 2011-05-24 10:24:41 UTC (rev 4422)
@@ -74,6 +74,8 @@
"select V.DATA" + " from JCR_MITEM I, JCR_MVALUE V"
+ " where I.PARENT_ID=? and I.I_CLASS=2 and I.NAME=? and I.ID=V.PROPERTY_ID order by V.ORDER_NUM";
FIND_NODES_BY_PARENTID = "select * from JCR_MITEM" + " where PARENT_ID=? and I_CLASS=1" + " order by N_ORDER_NUM";
+ FIND_LAST_ORDER_NUMBER_BY_PARENTID =
+ "select count(*), max(N_ORDER_NUM) from JCR_MITEM where PARENT_ID=? and I_CLASS=1";
FIND_NODES_COUNT_BY_PARENTID = "select count(ID) from JCR_MITEM" + " where PARENT_ID=? and I_CLASS=1";
FIND_PROPERTIES_BY_PARENTID = "select * from JCR_MITEM" + " where PARENT_ID=? and I_CLASS=2" + " order by ID";
}
Modified: jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/HSQLDBSingleDbJDBCConnection.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/HSQLDBSingleDbJDBCConnection.java 2011-05-24 10:07:21 UTC (rev 4421)
+++ jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/HSQLDBSingleDbJDBCConnection.java 2011-05-24 10:24:41 UTC (rev 4422)
@@ -81,6 +81,8 @@
+ " where I.PARENT_ID=? and I.I_CLASS=2 and I.CONTAINER_NAME=? and I.NAME=? and I.ID=V.PROPERTY_ID order by V.ORDER_NUM";
FIND_NODES_BY_PARENTID =
"select * from JCR_SITEM" + " where PARENT_ID=? and I_CLASS=1 and CONTAINER_NAME=?" + " order by N_ORDER_NUM";
+ FIND_LAST_ORDER_NUMBER_BY_PARENTID =
+ "select count(*), max(N_ORDER_NUM) from JCR_SITEM where PARENT_ID=? and I_CLASS=1 and CONTAINER_NAME=?";
FIND_NODES_COUNT_BY_PARENTID =
"select count(ID) from JCR_SITEM" + " where PARENT_ID=? and I_CLASS=1 and CONTAINER_NAME=?";
FIND_PROPERTIES_BY_PARENTID =
@@ -142,6 +144,23 @@
* {@inheritDoc}
*/
@Override
+ protected ResultSet findLastOrderNumberByParentIdentifier(String parentIdentifier) throws SQLException
+ {
+ if (findLastOrderNumberByParentId == null)
+ findLastOrderNumberByParentId = dbConnection.prepareStatement(FIND_LAST_ORDER_NUMBER_BY_PARENTID);
+ else
+ findLastOrderNumberByParentId.clearParameters();
+
+ findLastOrderNumberByParentId.setString(1, parentIdentifier);
+ findLastOrderNumberByParentId.setString(2, containerName);
+
+ return findLastOrderNumberByParentId.executeQuery();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
protected ResultSet findChildNodesCountByParentIdentifier(String parentCid) throws SQLException
{
if (findNodesCountByParentId == null)
Modified: jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/MultiDbJDBCConnection.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/MultiDbJDBCConnection.java 2011-05-24 10:07:21 UTC (rev 4421)
+++ jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/MultiDbJDBCConnection.java 2011-05-24 10:24:41 UTC (rev 4422)
@@ -127,6 +127,9 @@
FIND_NODES_BY_PARENTID = "select * from JCR_MITEM" + " where I_CLASS=1 and PARENT_ID=?" + " order by N_ORDER_NUM";
+ FIND_LAST_ORDER_NUMBER_BY_PARENTID =
+ "select count(*), max(N_ORDER_NUM) from JCR_MITEM where I_CLASS=1 and PARENT_ID=?";
+
FIND_NODES_COUNT_BY_PARENTID = "select count(ID) from JCR_MITEM" + " where I_CLASS=1 and PARENT_ID=?";
FIND_PROPERTIES_BY_PARENTID = "select * from JCR_MITEM" + " where I_CLASS=2 and PARENT_ID=?" + " order by ID";
@@ -371,6 +374,21 @@
* {@inheritDoc}
*/
@Override
+ protected ResultSet findLastOrderNumberByParentIdentifier(String parentIdentifier) throws SQLException
+ {
+ if (findLastOrderNumberByParentId == null)
+ findLastOrderNumberByParentId = dbConnection.prepareStatement(FIND_LAST_ORDER_NUMBER_BY_PARENTID);
+ else
+ findLastOrderNumberByParentId.clearParameters();
+
+ findLastOrderNumberByParentId.setString(1, parentIdentifier);
+ return findLastOrderNumberByParentId.executeQuery();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
protected ResultSet findChildNodesCountByParentIdentifier(String parentIdentifier) throws SQLException
{
if (findNodesCountByParentId == null)
Modified: jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/SingleDbJDBCConnection.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/SingleDbJDBCConnection.java 2011-05-24 10:07:21 UTC (rev 4421)
+++ jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/SingleDbJDBCConnection.java 2011-05-24 10:24:41 UTC (rev 4422)
@@ -133,6 +133,9 @@
FIND_NODES_BY_PARENTID =
"select * from JCR_SITEM" + " where I_CLASS=1 and CONTAINER_NAME=? and PARENT_ID=?" + " order by N_ORDER_NUM";
+ FIND_LAST_ORDER_NUMBER_BY_PARENTID =
+ "select count(*), max(N_ORDER_NUM) from JCR_SITEM where I_CLASS=1 and CONTAINER_NAME=? and PARENT_ID=?";
+
FIND_NODES_COUNT_BY_PARENTID =
"select count(ID) from JCR_SITEM" + " where I_CLASS=1 and CONTAINER_NAME=? and PARENT_ID=?";
@@ -282,6 +285,22 @@
* {@inheritDoc}
*/
@Override
+ protected ResultSet findLastOrderNumberByParentIdentifier(String parentIdentifier) throws SQLException
+ {
+ if (findLastOrderNumberByParentId == null)
+ findLastOrderNumberByParentId = dbConnection.prepareStatement(FIND_LAST_ORDER_NUMBER_BY_PARENTID);
+ else
+ findLastOrderNumberByParentId.clearParameters();
+
+ findLastOrderNumberByParentId.setString(1, containerName);
+ findLastOrderNumberByParentId.setString(2, parentIdentifier);
+ return findLastOrderNumberByParentId.executeQuery();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
protected ResultSet findChildNodesCountByParentIdentifier(String parentCid) throws SQLException
{
if (findNodesCountByParentId == null)
Modified: jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/HSQLDBMultiDbJDBCConnection.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/HSQLDBMultiDbJDBCConnection.java 2011-05-24 10:07:21 UTC (rev 4421)
+++ jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/HSQLDBMultiDbJDBCConnection.java 2011-05-24 10:24:41 UTC (rev 4422)
@@ -78,6 +78,10 @@
"select V.DATA" + " from JCR_MITEM I, JCR_MVALUE V"
+ " where I.PARENT_ID=? and I.I_CLASS=2 and I.NAME=? and I.ID=V.PROPERTY_ID order by V.ORDER_NUM";
FIND_NODES_BY_PARENTID = "select * from JCR_MITEM" + " where PARENT_ID=? and I_CLASS=1" + " order by N_ORDER_NUM";
+
+ FIND_LAST_ORDER_NUMBER_BY_PARENTID =
+ "select count(*), max(N_ORDER_NUM) from JCR_MITEM where PARENT_ID=? and I_CLASS=1";
+
FIND_NODES_COUNT_BY_PARENTID = "select count(ID) from JCR_MITEM" + " where PARENT_ID=? and I_CLASS=1";
FIND_PROPERTIES_BY_PARENTID = "select * from JCR_MITEM" + " where PARENT_ID=? and I_CLASS=2" + " order by ID";
FIND_NODES_BY_PARENTID_CQ =
Modified: jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/HSQLDBSingleDbJDBCConnection.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/HSQLDBSingleDbJDBCConnection.java 2011-05-24 10:07:21 UTC (rev 4421)
+++ jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/HSQLDBSingleDbJDBCConnection.java 2011-05-24 10:24:41 UTC (rev 4422)
@@ -85,6 +85,10 @@
+ " where I.PARENT_ID=? and I.I_CLASS=2 and I.CONTAINER_NAME=? and I.NAME=? and I.ID=V.PROPERTY_ID order by V.ORDER_NUM";
FIND_NODES_BY_PARENTID =
"select * from JCR_SITEM" + " where PARENT_ID=? and I_CLASS=1 and CONTAINER_NAME=?" + " order by N_ORDER_NUM";
+
+ FIND_LAST_ORDER_NUMBER_BY_PARENTID =
+ "select count(*), max(N_ORDER_NUM) from JCR_SITEM where PARENT_ID=? and I_CLASS=1 and CONTAINER_NAME=?";
+
FIND_NODES_COUNT_BY_PARENTID =
"select count(ID) from JCR_SITEM" + " where PARENT_ID=? and I_CLASS=1 and CONTAINER_NAME=?";
FIND_PROPERTIES_BY_PARENTID =
@@ -165,6 +169,23 @@
* {@inheritDoc}
*/
@Override
+ protected ResultSet findLastOrderNumberByParentIdentifier(String parentIdentifier) throws SQLException
+ {
+ if (findLastOrderNumberByParentId == null)
+ findLastOrderNumberByParentId = dbConnection.prepareStatement(FIND_LAST_ORDER_NUMBER_BY_PARENTID);
+ else
+ findLastOrderNumberByParentId.clearParameters();
+
+ findLastOrderNumberByParentId.setString(1, parentIdentifier);
+ findLastOrderNumberByParentId.setString(2, containerName);
+
+ return findLastOrderNumberByParentId.executeQuery();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
protected ResultSet findChildNodesCountByParentIdentifier(String parentCid) throws SQLException
{
if (findNodesCountByParentId == null)
Modified: jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/MultiDbJDBCConnection.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/MultiDbJDBCConnection.java 2011-05-24 10:07:21 UTC (rev 4421)
+++ jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/MultiDbJDBCConnection.java 2011-05-24 10:24:41 UTC (rev 4422)
@@ -151,6 +151,9 @@
+ " from JCR_MITEM I, (SELECT ID, PARENT_ID from JCR_MITEM where ID=?) J"
+ " where I.ID = J.ID or I.ID = J.PARENT_ID";
+ FIND_LAST_ORDER_NUMBER_BY_PARENTID =
+ "select count(*), max(N_ORDER_NUM) from JCR_MITEM where I_CLASS=1 and PARENT_ID=?";
+
FIND_NODES_COUNT_BY_PARENTID = "select count(ID) from JCR_MITEM" + " where I_CLASS=1 and PARENT_ID=?";
FIND_PROPERTIES_BY_PARENTID = "select * from JCR_MITEM" + " where I_CLASS=2 and PARENT_ID=?" + " order by NAME";
@@ -413,6 +416,21 @@
* {@inheritDoc}
*/
@Override
+ protected ResultSet findLastOrderNumberByParentIdentifier(String parentIdentifier) throws SQLException
+ {
+ if (findLastOrderNumberByParentId == null)
+ findLastOrderNumberByParentId = dbConnection.prepareStatement(FIND_LAST_ORDER_NUMBER_BY_PARENTID);
+ else
+ findLastOrderNumberByParentId.clearParameters();
+
+ findLastOrderNumberByParentId.setString(1, parentIdentifier);
+ return findLastOrderNumberByParentId.executeQuery();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
protected ResultSet findChildNodesCountByParentIdentifier(String parentIdentifier) throws SQLException
{
if (findNodesCountByParentId == null)
Modified: jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/SingleDbJDBCConnection.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/SingleDbJDBCConnection.java 2011-05-24 10:07:21 UTC (rev 4421)
+++ jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/SingleDbJDBCConnection.java 2011-05-24 10:24:41 UTC (rev 4422)
@@ -157,6 +157,9 @@
+ " from JCR_SITEM I, (SELECT ID, PARENT_ID from JCR_SITEM where ID=?) J"
+ " where I.ID = J.ID or I.ID = J.PARENT_ID";
+ FIND_LAST_ORDER_NUMBER_BY_PARENTID =
+ "select count(*), max(N_ORDER_NUM) from JCR_SITEM where I_CLASS=1 and CONTAINER_NAME=? and PARENT_ID=?";
+
FIND_NODES_COUNT_BY_PARENTID =
"select count(ID) from JCR_SITEM" + " where I_CLASS=1 and CONTAINER_NAME=? and PARENT_ID=?";
@@ -308,6 +311,22 @@
* {@inheritDoc}
*/
@Override
+ protected ResultSet findLastOrderNumberByParentIdentifier(String parentIdentifier) throws SQLException
+ {
+ if (findLastOrderNumberByParentId == null)
+ findLastOrderNumberByParentId = dbConnection.prepareStatement(FIND_LAST_ORDER_NUMBER_BY_PARENTID);
+ else
+ findLastOrderNumberByParentId.clearParameters();
+
+ findLastOrderNumberByParentId.setString(1, containerName);
+ findLastOrderNumberByParentId.setString(2, parentIdentifier);
+ return findLastOrderNumberByParentId.executeQuery();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
protected ResultSet findChildNodesCountByParentIdentifier(String parentCid) throws SQLException
{
if (findNodesCountByParentId == null)
Modified: jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/statistics/StatisticsJDBCStorageConnection.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/statistics/StatisticsJDBCStorageConnection.java 2011-05-24 10:07:21 UTC (rev 4421)
+++ jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/statistics/StatisticsJDBCStorageConnection.java 2011-05-24 10:24:41 UTC (rev 4422)
@@ -117,6 +117,12 @@
* <code>getChildNodesCount(NodeData parent)</code>
*/
private static final String GET_CHILD_NODES_COUNT_DESCR = "getChildNodesCount";
+
+ /**
+ * The description of the statistics corresponding to the method
+ * <code>getLastOrderNumber(NodeData parent)</code>
+ */
+ private static final String GET_LAST_ORDER_NUMBER_DESCR = "getLastOrderNumber";
/**
* The description of the statistics corresponding to the method
@@ -171,6 +177,8 @@
GET_ITEM_DATA_BY_NODE_DATA_NQ_PATH_ENTRY_DESCR));
ALL_STATISTICS.put(GET_CHILD_NODES_DATA_DESCR, new Statistics(GLOBAL_STATISTICS, GET_CHILD_NODES_DATA_DESCR));
ALL_STATISTICS.put(GET_CHILD_NODES_COUNT_DESCR, new Statistics(GLOBAL_STATISTICS, GET_CHILD_NODES_COUNT_DESCR));
+ ALL_STATISTICS.put(GET_LAST_ORDER_NUMBER_DESCR, new Statistics(GLOBAL_STATISTICS, GET_LAST_ORDER_NUMBER_DESCR));
+
ALL_STATISTICS.put(GET_CHILD_PROPERTIES_DATA_DESCR, new Statistics(GLOBAL_STATISTICS,
GET_CHILD_PROPERTIES_DATA_DESCR));
ALL_STATISTICS.put(LIST_CHILD_PROPERTIES_DATA_DESCR, new Statistics(GLOBAL_STATISTICS,
@@ -227,7 +235,7 @@
}
/**
- * @see org.exoplatform.services.jcr.storage.WorkspaceStorageConnection#add(org.exoplatform.services.jcr.datamodel.NodeData)
+ * {@inheritDoc}
*/
public void add(NodeData data) throws RepositoryException, UnsupportedOperationException, InvalidItemStateException,
IllegalStateException
@@ -245,7 +253,7 @@
}
/**
- * @see org.exoplatform.services.jcr.storage.WorkspaceStorageConnection#add(org.exoplatform.services.jcr.datamodel.PropertyData)
+ * {@inheritDoc}
*/
public void add(PropertyData data) throws RepositoryException, UnsupportedOperationException,
InvalidItemStateException, IllegalStateException
@@ -263,7 +271,7 @@
}
/**
- * @see org.exoplatform.services.jcr.storage.WorkspaceStorageConnection#close()
+ * {@inheritDoc}
*/
public void close() throws IllegalStateException, RepositoryException
{
@@ -280,7 +288,7 @@
}
/**
- * @see org.exoplatform.services.jcr.storage.WorkspaceStorageConnection#commit()
+ * {@inheritDoc}
*/
public void commit() throws IllegalStateException, RepositoryException
{
@@ -297,7 +305,7 @@
}
/**
- * @see org.exoplatform.services.jcr.storage.WorkspaceStorageConnection#delete(org.exoplatform.services.jcr.datamodel.NodeData)
+ * {@inheritDoc}
*/
public void delete(NodeData data) throws RepositoryException, UnsupportedOperationException,
InvalidItemStateException, IllegalStateException
@@ -315,7 +323,7 @@
}
/**
- * @see org.exoplatform.services.jcr.storage.WorkspaceStorageConnection#delete(org.exoplatform.services.jcr.datamodel.PropertyData)
+ * {@inheritDoc}
*/
public void delete(PropertyData data) throws RepositoryException, UnsupportedOperationException,
InvalidItemStateException, IllegalStateException
@@ -333,8 +341,25 @@
}
/**
- * @see org.exoplatform.services.jcr.storage.WorkspaceStorageConnection#getChildNodesCount(org.exoplatform.services.jcr.datamodel.NodeData)
+ * {@inheritDoc}
*/
+ public int getLastOrderNumber(NodeData parent) throws RepositoryException
+ {
+ Statistics s = ALL_STATISTICS.get(GET_LAST_ORDER_NUMBER_DESCR);
+ try
+ {
+ s.begin();
+ return wcs.getLastOrderNumber(parent);
+ }
+ finally
+ {
+ s.end();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public int getChildNodesCount(NodeData parent) throws RepositoryException
{
Statistics s = ALL_STATISTICS.get(GET_CHILD_NODES_COUNT_DESCR);
@@ -350,7 +375,7 @@
}
/**
- * @see org.exoplatform.services.jcr.storage.WorkspaceStorageConnection#getChildNodesData(org.exoplatform.services.jcr.datamodel.NodeData)
+ * {@inheritDoc}
*/
public List<NodeData> getChildNodesData(NodeData parent) throws RepositoryException, IllegalStateException
{
@@ -367,7 +392,7 @@
}
/**
- * @see org.exoplatform.services.jcr.storage.WorkspaceStorageConnection#getChildPropertiesData(org.exoplatform.services.jcr.datamodel.NodeData)
+ * {@inheritDoc}
*/
public List<PropertyData> getChildPropertiesData(NodeData parent) throws RepositoryException, IllegalStateException
{
@@ -410,7 +435,7 @@
}
/**
- * @see org.exoplatform.services.jcr.storage.WorkspaceStorageConnection#getItemData(java.lang.String)
+ * {@inheritDoc}
*/
public ItemData getItemData(String identifier) throws RepositoryException, IllegalStateException
{
@@ -427,7 +452,7 @@
}
/**
- * @see org.exoplatform.services.jcr.storage.WorkspaceStorageConnection#getReferencesData(java.lang.String)
+ * {@inheritDoc}
*/
public List<PropertyData> getReferencesData(String nodeIdentifier) throws RepositoryException,
IllegalStateException, UnsupportedOperationException
@@ -445,7 +470,7 @@
}
/**
- * @see org.exoplatform.services.jcr.storage.WorkspaceStorageConnection#isOpened()
+ * {@inheritDoc}
*/
public boolean isOpened()
{
@@ -462,7 +487,7 @@
}
/**
- * @see org.exoplatform.services.jcr.storage.WorkspaceStorageConnection#listChildPropertiesData(org.exoplatform.services.jcr.datamodel.NodeData)
+ * {@inheritDoc}
*/
public List<PropertyData> listChildPropertiesData(NodeData parent) throws RepositoryException, IllegalStateException
{
@@ -479,7 +504,7 @@
}
/**
- * @see org.exoplatform.services.jcr.storage.WorkspaceStorageConnection#rename(org.exoplatform.services.jcr.datamodel.NodeData)
+ * {@inheritDoc}
*/
public void rename(NodeData data) throws RepositoryException, UnsupportedOperationException,
InvalidItemStateException, IllegalStateException
@@ -497,7 +522,7 @@
}
/**
- * @see org.exoplatform.services.jcr.storage.WorkspaceStorageConnection#rollback()
+ * {@inheritDoc}
*/
public void rollback() throws IllegalStateException, RepositoryException
{
@@ -514,7 +539,7 @@
}
/**
- * @see org.exoplatform.services.jcr.storage.WorkspaceStorageConnection#update(org.exoplatform.services.jcr.datamodel.NodeData)
+ * {@inheritDoc}
*/
public void update(NodeData data) throws RepositoryException, UnsupportedOperationException,
InvalidItemStateException, IllegalStateException
@@ -532,7 +557,7 @@
}
/**
- * @see org.exoplatform.services.jcr.storage.WorkspaceStorageConnection#update(org.exoplatform.services.jcr.datamodel.PropertyData)
+ * {@inheritDoc}
*/
public void update(PropertyData data) throws RepositoryException, UnsupportedOperationException,
InvalidItemStateException, IllegalStateException
Modified: jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/storage/WorkspaceStorageConnection.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/storage/WorkspaceStorageConnection.java 2011-05-24 10:07:21 UTC (rev 4421)
+++ jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/storage/WorkspaceStorageConnection.java 2011-05-24 10:24:41 UTC (rev 4422)
@@ -126,6 +126,15 @@
int getChildNodesCount(NodeData parent) throws RepositoryException;
/**
+ * Reads order number of last <code>parent<code/> child nodes.
+ *
+ * @param parent NodeData
+ * @return long, order number of last parent's child node.
+ * @throws RepositoryException if error occurs
+ */
+ int getLastOrderNumber(NodeData parent) throws RepositoryException;
+
+ /**
* Reads <code>List</code> of <code>PropertyData</code> from the storage using item's parent
* location.
*
Modified: jcr/branches/1.12.x/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/core/TestNodeOrder.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/core/TestNodeOrder.java 2011-05-24 10:07:21 UTC (rev 4421)
+++ jcr/branches/1.12.x/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/core/TestNodeOrder.java 2011-05-24 10:24:41 UTC (rev 4422)
@@ -36,14 +36,14 @@
*/
package org.exoplatform.services.jcr.impl.core;
+import org.exoplatform.services.jcr.JcrImplBaseTest;
+import org.exoplatform.services.jcr.datamodel.NodeData;
+
import javax.jcr.ItemExistsException;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.Session;
-import org.exoplatform.services.jcr.JcrImplBaseTest;
-import org.exoplatform.services.jcr.datamodel.NodeData;
-
/**
* Created by The eXo Platform SAS.
*
@@ -227,7 +227,7 @@
assertEquals(order++, orderNumb);
}
}
-
+
public void testOrderWithRefreshKeep() throws Exception
{
Node testNode = root.addNode("testNode");
@@ -268,4 +268,41 @@
}
}
+ public void testRemoveOrder() throws Exception
+ {
+ Node list = session.getRootNode().addNode("list");
+ assertTrue(list.getPrimaryNodeType().hasOrderableChildNodes());
+ list.addNode("foo", "nt:unstructured");
+ list.addNode("bar", "nt:unstructured");
+ list.addNode("juu", "nt:unstructured");
+ session.save();
+
+ list = session.getRootNode().getNode("list");
+ list.getNode("bar").remove();
+ session.save();
+
+ list = session.getRootNode().getNode("list");
+ list.addNode("daa", "nt:unstructured");
+ session.save();
+
+ //check order numbers
+ NodeImpl foo = (NodeImpl)list.getNode("foo");
+ assertEquals(0, ((NodeData)foo.getData()).getOrderNumber());
+ NodeImpl juu = (NodeImpl)list.getNode("juu");
+ assertEquals(2, ((NodeData)juu.getData()).getOrderNumber());
+ NodeImpl daa = (NodeImpl)list.getNode("daa");
+ assertEquals(3, ((NodeData)daa.getData()).getOrderNumber());
+
+ // list.orderBefore("daa", null);
+ NodeIterator it = list.getNodes();
+ foo = (NodeImpl)it.nextNode();
+ assertEquals("foo", foo.getName());
+ juu = (NodeImpl)it.nextNode();
+ assertEquals("juu", juu.getName());
+ daa = (NodeImpl)it.nextNode();
+ assertEquals("daa", daa.getName());
+ assertFalse(it.hasNext());
+ session.save();
+ }
+
}
Modified: jcr/branches/1.12.x/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/TestCacheableWorkspaceDataManager.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/TestCacheableWorkspaceDataManager.java 2011-05-24 10:07:21 UTC (rev 4421)
+++ jcr/branches/1.12.x/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/TestCacheableWorkspaceDataManager.java 2011-05-24 10:24:41 UTC (rev 4422)
@@ -526,6 +526,12 @@
{
}
+ @Override
+ public int getLastOrderNumber(NodeData parent) throws RepositoryException
+ {
+ return -1;
+ }
+
};
private static class MyWorkspaceDataContainer extends WorkspaceDataContainerBase
Modified: jcr/branches/1.12.x/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/TestJBossCacheWorkspaceStorageCacheInClusterMode.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/TestJBossCacheWorkspaceStorageCacheInClusterMode.java 2011-05-24 10:07:21 UTC (rev 4421)
+++ jcr/branches/1.12.x/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/TestJBossCacheWorkspaceStorageCacheInClusterMode.java 2011-05-24 10:24:41 UTC (rev 4422)
@@ -96,6 +96,7 @@
// Test getChildNodesData
Action readAction = new Action(cwdmNode2)
{
+ @Override
public void execute(NodeData parentNode) throws Exception
{
cwdm.getChildNodesData(parentNode);
@@ -103,6 +104,7 @@
};
Action writeAction = new Action(cwdmNode1)
{
+ @Override
public void execute(NodeData parentNode) throws Exception
{
PlainChangesLog chlog = new PlainChangesLogImpl();
@@ -127,6 +129,7 @@
// Test getChildPropertiesData
readAction = new Action(cwdmNode2)
{
+ @Override
public void execute(NodeData parentNode) throws Exception
{
cwdm.getChildPropertiesData(parentNode);
@@ -134,6 +137,7 @@
};
writeAction = new Action(cwdmNode1)
{
+ @Override
public void execute(NodeData parentNode) throws Exception
{
PlainChangesLog chlog = new PlainChangesLogImpl();
@@ -161,6 +165,7 @@
// Test getReferencesData
readAction = new Action(cwdmNode2)
{
+ @Override
public void execute(NodeData parentNode) throws Exception
{
cwdm.getReferencesData(parentNode.getIdentifier(), false);
@@ -168,6 +173,7 @@
};
writeAction = new Action(cwdmNode1)
{
+ @Override
public void execute(NodeData parentNode) throws Exception
{
PlainChangesLog chlog = new PlainChangesLogImpl();
@@ -196,6 +202,7 @@
// Test getItemData by Id
readAction = new Action(cwdmNode2)
{
+ @Override
public void execute(NodeData parentNode) throws Exception
{
cwdm.getItemData(parentNode.getIdentifier());
@@ -203,6 +210,7 @@
};
writeAction = new Action(cwdmNode1)
{
+ @Override
public void execute(NodeData parentNode) throws Exception
{
PlainChangesLog chlog = new PlainChangesLogImpl();
@@ -231,6 +239,7 @@
final QPathEntry qpe = new QPathEntry(null, "my-property", 1);
readAction = new Action(cwdmNode2)
{
+ @Override
public void execute(NodeData parentNode) throws Exception
{
cwdm.getItemData(parentNode, qpe, ItemType.PROPERTY);
@@ -238,6 +247,7 @@
};
writeAction = new Action(cwdmNode1)
{
+ @Override
public void execute(NodeData parentNode) throws Exception
{
PlainChangesLog chlog = new PlainChangesLogImpl();
@@ -308,6 +318,7 @@
final CountDownLatch doneSignal = new CountDownLatch(2);
Thread writer = new Thread()
{
+ @Override
public void run()
{
try
@@ -331,6 +342,7 @@
writer.start();
Thread reader = new Thread()
{
+ @Override
public void run()
{
try
@@ -593,6 +605,11 @@
InvalidItemStateException, IllegalStateException
{
}
+
+ public int getLastOrderNumber(NodeData parent) throws RepositoryException
+ {
+ return -1;
+ }
};
private static class MyWorkspaceDataContainer extends WorkspaceDataContainerBase
Added: jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1611/readme.txt
===================================================================
--- jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1611/readme.txt (rev 0)
+++ jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1611/readme.txt 2011-05-24 10:24:41 UTC (rev 4422)
@@ -0,0 +1,63 @@
+Summary
+
+ Status: Create testing repositories for version 1.12.x
+ CCP Issue: JCR-1234, Product Jira Issue: JCR-1611.
+ Complexity: Low
+
+The Proposal
+Problem description
+
+What is the problem to fix?
+We need to backport the fix of the jira EXOJCR-1234 to JCR 1.12.x.
+Fix description
+
+How is the problem fixed?
+
+ Change the calculation way of last order number during node adding. The new order number will be as real last order number plus 1. In previous impl it was as children nodes count plus 1.
+
+Patch information: JCR-1611.patch
+
+Tests to perform
+
+Reproduction test
+
+* TestNodeOrder.java* *
+
+Tests performed at DevLevel
+ * functional testing in jcr core project
+
+Tests performed at QA/Support Level
+*
+
+Documentation changes
+
+Documentation changes:
+ * no
+
+Configuration changes
+
+Configuration changes:
+ * No
+
+Will previous configuration continue to work?
+ * Yes
+
+Risks and impacts
+
+Can this bug fix have any side effects on current client projects?
+
+ No
+
+Is there a performance risk/cost?
+ * Workspace.copy() method could be a bit slower. See tests results http://tests.exoplatform.org/JCR/1.12.9-GA/rev.4331_testukr_230/daily-per...
+Validation (PM/Support/QA)
+
+PM Comment
+* PL review: Patch validated
+
+Support Comment
+* Support review: Patch validated
+
+QA Feedbacks
+*
+
13 years
exo-jcr SVN: r4421 - in jcr/branches/1.12.x: exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr and 2 other directories.
by do-not-reply@jboss.org
Author: paristote
Date: 2011-05-24 06:07:21 -0400 (Tue, 24 May 2011)
New Revision: 4421
Added:
jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1618/readme.txt
Modified:
jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainer.java
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/configuration/jdbc-data-container-config.xml
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/data-container.xml
Log:
JCR-1618
What is the problem to fix?
This issue is only reproduced with Mysql engine type InnoDB(not reproduced with MySQL MyIsam)
when we try to create a new nodetype with same name sibling we get an exception.
How is the problem fixed?
Check-sns-new-connection is set to false by default
Modified: jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainer.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainer.java 2011-05-24 09:43:47 UTC (rev 4420)
+++ jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainer.java 2011-05-24 10:07:21 UTC (rev 4421)
@@ -370,7 +370,7 @@
}
catch (RepositoryConfigurationException e)
{
- this.checkSNSNewConnection = DBConstants.DB_DIALECT_SYBASE.equals(this.dbDialect) ? false : true;
+ this.checkSNSNewConnection = false;
}
// ------------- Values swap config ------------------
@@ -836,6 +836,22 @@
*/
public void start()
{
+ // if isolation level lesser then TRANSACTION_READ_COMMITTED, print a warning
+ try
+ {
+ if (getConnectionFactory().getJdbcConnection().getTransactionIsolation() < Connection.TRANSACTION_READ_COMMITTED)
+ {
+ LOG.warn("Wrong default isolation level, please set the default isolation level to READ_COMMITTED or higher. Other default isolation levels are not supported");
+ }
+ }
+ catch (SQLException e)
+ {
+ LOG.error("Error checking isolation level configuration.", e);
+ }
+ catch (RepositoryException e)
+ {
+ LOG.error("Error checking isolation level configuration.", e);
+ }
}
/**
Modified: jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/configuration/jdbc-data-container-config.xml
===================================================================
--- jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/configuration/jdbc-data-container-config.xml 2011-05-24 09:43:47 UTC (rev 4420)
+++ jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/configuration/jdbc-data-container-config.xml 2011-05-24 10:07:21 UTC (rev 4421)
@@ -56,6 +56,13 @@
</listitem>
</itemizedlist></para>
+ <note>
+ <para>Please note, that JCR requires at least READ_COMMITED isolation
+ level and other RDBMS configurations can cause some side-effects and
+ issues. So, please, make sure proper isolation level is configured on
+ database server side.</para>
+ </note>
+
<para>Each database software supports ANSI SQL standards but also has its
own specifics. So, each database has its own configuration in eXo JCR as a
database dialect parameter. If you need a more detailed configuration of
Modified: jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/data-container.xml
===================================================================
--- jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/data-container.xml 2011-05-24 09:43:47 UTC (rev 4420)
+++ jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/data-container.xml 2011-05-24 10:07:21 UTC (rev 4421)
@@ -96,18 +96,6 @@
<programlisting>boolean isCheckSNSNewConnection();
</programlisting>
- <important>
- <title>New connection for SNS</title>
-
- <para>It is neccessary to check the name of nodes when they have the
- same names. Usually, new Workspace Storage Connection is used for this
- purpose. The improvement came from JDBC Workspace Data Container,
- which shows a better performance on Oracle RDBMS when using new
- connection for checking SNS existence. But later, this causes to
- deadlocks on Sybase RDBMS, so this feature is made as an optional and
- configurable one.</para>
- </important>
-
<para>Container initialization is only based on a configuration. After
the container has been created, it's not possible to change parameters.
Configuration consists of implementation class and set of properties and
Added: jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1618/readme.txt
===================================================================
--- jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1618/readme.txt (rev 0)
+++ jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1618/readme.txt 2011-05-24 10:07:21 UTC (rev 4421)
@@ -0,0 +1,106 @@
+Summary
+
+ Status: javax.jcr.InvalidItemStateException: Node can't be saved No same-name sibling exists with index 2
+ CCP Issue: CCP-928, Product Jira Issue: JCR-1618.
+ Complexity: Low
+
+The Proposal
+Problem description
+
+What is the problem to fix?
+This issue is only reproduced with Mysql engine type InnoDB(not reproduced with MySQL MyIsam)
+
+when we try to create a new nodetype with same name sibling we get this exception :
+12:54:42,125 ERROR [STDERR] javax.jcr.InvalidItemStateException: Node can't be saved []:1[]test2000:3. No same-name sibling exists with index 2.
+12:54:42,125 ERROR [STDERR] at org.exoplatform.services.jcr.impl.dataflow.persistent.WorkspacePersistentDataManager.checkPersistedSNS(WorkspacePersistentDataManager.java:586)
+12:54:42,125 ERROR [STDERR] at org.exoplatform.services.jcr.impl.dataflow.persistent.WorkspacePersistentDataManager.checkSameNameSibling(WorkspacePersistentDataManager.java:558)
+12:54:42,125 ERROR [STDERR] at org.exoplatform.services.jcr.impl.dataflow.persistent.WorkspacePersistentDataManager.doAdd(WorkspacePersistentDataManager.java:655)
+12:54:42,125 ERROR [STDERR] at org.exoplatform.services.jcr.impl.dataflow.persistent.WorkspacePersistentDataManager$ChangesLogPersister.save(WorkspacePersistentDataManager.java:387)
+12:54:42,125 ERROR [STDERR] at org.exoplatform.services.jcr.impl.dataflow.persistent.WorkspacePersistentDataManager.save(WorkspacePersistentDataManager.java:165)
+12:54:42,125 ERROR [STDERR] at org.exoplatform.services.jcr.impl.dataflow.persistent.CacheableWorkspaceDataManager.access$101(CacheableWorkspaceDataManager.java:54)
+12:54:42,125 ERROR [STDERR] at org.exoplatform.services.jcr.impl.dataflow.persistent.CacheableWorkspaceDataManager$SaveInTransaction.action(CacheableWorkspaceDataManager.java:262)
+12:54:42,125 ERROR [STDERR] at org.exoplatform.services.jcr.impl.dataflow.persistent.TxIsolatedOperation.txAction(TxIsolatedOperation.java:92)
+12:54:42,125 ERROR [STDERR] at org.exoplatform.services.jcr.impl.dataflow.persistent.CacheableWorkspaceDataManager$SaveInTransaction.txAction(CacheableWorkspaceDataManager.java:268)
+12:54:42,125 ERROR [STDERR] at org.exoplatform.services.jcr.impl.dataflow.persistent.TxIsolatedOperation.perform(TxIsolatedOperation.java:210)
+12:54:42,125 ERROR [STDERR] at org.exoplatform.services.jcr.impl.dataflow.persistent.CacheableWorkspaceDataManager.save(CacheableWorkspaceDataManager.java:526)
+12:54:42,125 ERROR [STDERR] at org.exoplatform.services.jcr.impl.dataflow.persistent.ACLInheritanceSupportedWorkspaceDataManager.save(ACLInheritanceSupportedWorkspaceDataManager.java:225)
+12:54:42,125 ERROR [STDERR] at org.exoplatform.services.jcr.impl.dataflow.persistent.VersionableWorkspaceDataManager.save(VersionableWorkspaceDataManager.java:244)
+12:54:42,125 ERROR [STDERR] at org.exoplatform.services.jcr.impl.dataflow.session.TransactionableDataManager.save(TransactionableDataManager.java:366)
+12:54:42,125 ERROR [STDERR] at org.exoplatform.services.jcr.impl.core.SessionDataManager.commit(SessionDataManager.java:1389)
+12:54:42,125 ERROR [STDERR] at org.exoplatform.services.jcr.impl.core.ItemImpl.save(ItemImpl.java:684)
+12:54:42,125 ERROR [STDERR] at org.exoplatform.services.jcr.impl.core.SessionImpl.save(SessionImpl.java:935)
+12:54:42,125 ERROR [STDERR] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+12:54:42,125 ERROR [STDERR] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
+12:54:42,125 ERROR [STDERR] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
+12:54:42,125 ERROR [STDERR] at java.lang.reflect.Method.invoke(Method.java:597)
+
+How to reproduce :
+you can find in attachment a sample usecase you need just to deploy the bsh script under your jboss home and you will get this exception
+
+we create in this case a node "test" then we save the session and if we try to create a new node with the same name we get InvalidItemState Exception :
+print("create first Node");
+ sess = getSessionFromExoAPI();
+ print(sess);
+ sess.getRootNode().addNode("test");
+ sess.save();
+ print("create second Node");
+ print("Initializing");
+ sess = getSessionFromExoAPI();
+ print(sess);
+ print("create second Node with the same name");
+ sess.getRootNode().addNode("test");
+ sess.save();
+Fix description
+
+How is the problem fixed?
+
+Check-sns-new-connection is set to false by default
+
+Patch information:
+JCR-1618.patch
+
+Tests to perform
+
+Reproduction test
+
+ No
+
+Tests performed at DevLevel
+
+ functional tests in jcr-core project. Manual testing wih JBoss bundle.
+
+Tests performed at QA/Support Level
+*
+
+Documentation changes
+
+Documentation changes:
+ No
+
+Configuration changes
+
+Configuration changes:
+ No
+
+Will previous configuration continue to work?
+ Yes
+
+Risks and impacts
+
+Can this bug fix have any side effects on current client projects?
+ No
+
+Is there a performance risk/cost?
+ No
+
+Validation (PM/Support/QA)
+
+PM Comment
+* PL review: Patch validated
+
+Support Comment
+* Support review: Patch validated
+
+QA Feedbacks
+*
+
13 years
exo-jcr SVN: r4420 - in jcr/branches/1.12.x: exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/command and 3 other directories.
by do-not-reply@jboss.org
Author: paristote
Date: 2011-05-24 05:43:47 -0400 (Tue, 24 May 2011)
New Revision: 4420
Added:
jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1597/readme.txt
Modified:
jcr/branches/1.12.x/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/WebDavServiceImpl.java
jcr/branches/1.12.x/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/command/LockCommand.java
jcr/branches/1.12.x/exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/command/TestLock.java
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/protocols/webdav.xml
Log:
JCR-1597
What is the problem to fix?
There are some problems when using webdav on Windows 7. We can't open a document (MS Office 2010) or the document is opened as read only (Open Office)
How is the problem fixed?
Lock tokens parsing fixed, to parse tokens not surrounded by '<' and '>' characters. To open documents via basic authentication on Windows 7 with MS Office 2010 we also need to edit registry.
Modified: jcr/branches/1.12.x/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/WebDavServiceImpl.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/WebDavServiceImpl.java 2011-05-24 06:48:30 UTC (rev 4419)
+++ jcr/branches/1.12.x/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/WebDavServiceImpl.java 2011-05-24 09:43:47 UTC (rev 4420)
@@ -1311,7 +1311,10 @@
if (lockTokenHeader != null)
{
- lockTokenHeader = lockTokenHeader.substring(1, lockTokenHeader.length() - 1);
+ if (lockTokenHeader.startsWith("<"))
+ {
+ lockTokenHeader = lockTokenHeader.substring(1, lockTokenHeader.length() - 1);
+ }
if (lockTokenHeader.contains(WebDavConst.Lock.OPAQUE_LOCK_TOKEN))
{
Modified: jcr/branches/1.12.x/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/command/LockCommand.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/command/LockCommand.java 2011-05-24 06:48:30 UTC (rev 4419)
+++ jcr/branches/1.12.x/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/command/LockCommand.java 2011-05-24 09:43:47 UTC (rev 4420)
@@ -26,6 +26,7 @@
import org.exoplatform.services.jcr.webdav.command.lock.LockRequestEntity;
import org.exoplatform.services.jcr.webdav.lock.NullResourceLocksHolder;
import org.exoplatform.services.jcr.webdav.resource.GenericResource;
+import org.exoplatform.services.jcr.webdav.util.PropertyConstants;
import org.exoplatform.services.jcr.webdav.xml.PropertyWriteUtil;
import org.exoplatform.services.jcr.webdav.xml.WebDavNamespaceContext;
import org.exoplatform.services.log.ExoLogger;
@@ -42,6 +43,7 @@
import javax.jcr.lock.LockException;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.StreamingOutput;
+import javax.xml.namespace.QName;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamWriter;
@@ -89,6 +91,7 @@
public Response lock(Session session, String path, HierarchicalProperty body, Depth depth, String timeout)
{
+ boolean bodyIsEmpty = (body == null);
String lockToken;
try
{
@@ -106,7 +109,21 @@
}
}
- Lock lock = node.lock((depth.getIntValue() != 1), false);
+ Lock lock;
+ if (bodyIsEmpty)
+ {
+ lock = node.getLock();
+ lock.refresh();
+
+ body = new HierarchicalProperty(new QName("DAV", "activelock", "D"));
+ HierarchicalProperty owner = new HierarchicalProperty(PropertyConstants.OWNER);
+ HierarchicalProperty href = new HierarchicalProperty(new QName("D", "href"), lock.getLockOwner());
+ body.addChild(owner).addChild(href);
+ }
+ else
+ {
+ lock = node.lock((depth.getIntValue() != 1), false);
+ }
lockToken = lock.getLockToken();
}
catch (PathNotFoundException pexc)
@@ -118,8 +135,17 @@
lockToken = WebDavConst.Lock.OPAQUE_LOCK_TOKEN + ":" + lockToken;
- return Response.ok(body(nsContext, requestEntity, depth, lockToken, requestEntity.getOwner(), timeout),
- "text/xml").header("Lock-Token", "<" + lockToken + ">").build();
+ if (bodyIsEmpty)
+ {
+ return Response.ok(body(nsContext, requestEntity, depth, lockToken, requestEntity.getOwner(), timeout),
+ "text/xml").build();
+ }
+ else
+ {
+ return Response
+ .ok(body(nsContext, requestEntity, depth, lockToken, requestEntity.getOwner(), timeout), "text/xml")
+ .header("Lock-Token", "<" + lockToken + ">").build();
+ }
// TODO 412 Precondition Failed ?
}
Modified: jcr/branches/1.12.x/exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/command/TestLock.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/command/TestLock.java 2011-05-24 06:48:30 UTC (rev 4419)
+++ jcr/branches/1.12.x/exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/command/TestLock.java 2011-05-24 09:43:47 UTC (rev 4420)
@@ -21,14 +21,18 @@
import org.exoplatform.common.http.HTTPStatus;
import org.exoplatform.services.jcr.webdav.BaseStandaloneTest;
import org.exoplatform.services.jcr.webdav.WebDavConstants.WebDAVMethods;
+import org.exoplatform.services.jcr.webdav.command.LockCommand.LockResultResponseEntity;
import org.exoplatform.services.jcr.webdav.util.TextUtil;
import org.exoplatform.services.jcr.webdav.utils.TestUtils;
+import org.exoplatform.services.rest.ExtHttpHeaders;
import org.exoplatform.services.rest.impl.ContainerResponse;
import org.exoplatform.services.rest.impl.MultivaluedMapImpl;
import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.InputStream;
+import javax.jcr.Node;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
@@ -46,6 +50,10 @@
private String path = TestUtils.getFileName();
private String fileContent = TestUtils.getFileContent();
+
+ private String lockRequestBody = "<D:lockinfo xmlns:D='DAV:'>" + "<D:lockscope>" + "<D:exclusive/>"
+ + "</D:lockscope>" + "<D:locktype>" + "<D:write/>" + "</D:locktype>" + "<D:owner>" + "<D:href>testOwner</D:href>"
+ + "</D:owner>" + "</D:lockinfo>";
@Override
public void setUp() throws Exception
@@ -55,17 +63,134 @@
TestUtils.addContent(session, path, inputStream, defaultFileNodeType, "");
}
+ /**
+ * Testing Lock method. Firstly lock existing node via webdav LOCK method and check for correct response status.
+ * Secondly check if the node is locked indeed via webdav DELETE method (no delete or any other operation cannot
+ * be performed with locked node). The response status must be LOCKED.
+ * @throws Exception
+ */
public void testLock() throws Exception
{
MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
- headers.add("Content-Type", MediaType.TEXT_PLAIN);
- ContainerResponse containerResponse = service(WebDAVMethods.LOCK, getPathWS() + path, "", headers, null);
+ headers.add(ExtHttpHeaders.CONTENTTYPE, MediaType.TEXT_PLAIN);
+ ContainerResponse containerResponse =
+ service(WebDAVMethods.LOCK, getPathWS() + path, "", headers, lockRequestBody.getBytes());
+ MultivaluedMap<String, Object> lockResponseHeaders = containerResponse.getHttpHeaders();
+
assertEquals(HTTPStatus.OK, containerResponse.getStatus());
+
+ // some manipulation to serialize response entity
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ LockResultResponseEntity entity = (LockResultResponseEntity)containerResponse.getEntity();
+ entity.write(outputStream);
+
+ System.out.println("\n=Lock method response body (add lock)=====");
+ System.out.println("==========================================");
+ System.out.println(outputStream.toString());
+ System.out.println("==========================================\n");
+
containerResponse = service("DELETE", getPathWS() + path, "", null, null);
+
assertEquals(HTTPStatus.LOCKED, containerResponse.getStatus());
assertTrue(session.getRootNode().getNode(TextUtil.relativizePath(path)).isLocked());
+
+ // here we're unlocking a node, to use it in other tests
+ // firstly get lock-token from response entity
+ String lockToken = outputStream.toString();
+ lockToken = lockToken.substring(lockToken.indexOf(">opaquelocktoken:"));
+ lockToken = lockToken.substring(lockToken.indexOf(":") + 1, lockToken.indexOf("<"));
+
+ // secondly add lock-token to current session and unlock the node
+ session.addLockToken(lockToken);
+ ((Node)session.getItem(path)).unlock();
}
+ /**
+ * Testing lock refreshing. Firstly we lock the node. Secondly we refresh the lock
+ * via webdav LOCK method with no body. In both cases OK webdav status must be returned.
+ * @throws Exception
+ */
+ public void testLockRefresh() throws Exception
+ {
+ MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
+ headers.add("Content-Type", MediaType.TEXT_PLAIN);
+ ContainerResponse containerResponse =
+ service(WebDAVMethods.LOCK, getPathWS() + path, "", headers, lockRequestBody.getBytes());
+ MultivaluedMap<String, Object> lockResponseHeaders = containerResponse.getHttpHeaders();
+
+ assertEquals(HTTPStatus.OK, containerResponse.getStatus());
+
+ // get lock-token from response body
+ // some manipulation to serialize response entity
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ LockResultResponseEntity entity = (LockResultResponseEntity)containerResponse.getEntity();
+ entity.write(outputStream);
+
+ String lockToken = outputStream.toString();
+ lockToken = lockToken.substring(lockToken.indexOf(">opaquelocktoken:"));
+ lockToken = lockToken.substring(lockToken.indexOf(":") + 1, lockToken.indexOf("<"));
+
+ //prepare to send lock refresh request
+ headers = new MultivaluedMapImpl();
+ headers.add(ExtHttpHeaders.CONTENTTYPE, MediaType.TEXT_PLAIN);
+ headers.add(ExtHttpHeaders.LOCKTOKEN, lockToken);
+
+ containerResponse = service(WebDAVMethods.LOCK, getPathWS() + path, "", headers, null);
+
+ assertEquals(HTTPStatus.OK, containerResponse.getStatus());
+
+ // some manipulation to serialize response entity
+ outputStream = new ByteArrayOutputStream();
+ entity = (LockResultResponseEntity)containerResponse.getEntity();
+ entity.write(outputStream);
+
+ System.out.println("\n=Lock method response body (refresh lock)=");
+ System.out.println("==========================================");
+ System.out.println(outputStream.toString());
+ System.out.println("==========================================\n");
+
+ // add lock-token to current session and unlock the node
+ session.addLockToken(lockToken);
+ ((Node)session.getItem(path)).unlock();
+
+ }
+
+ /**
+ * Testing trying to lock already locked node. Firstly we lock the node. Secondly we send webdav LOCK
+ * request with request body (because in case the body is empty the LOCK request should refresh already
+ * existing lock) to try to lock previously locked node. LOCKED webdav status must be returned.
+ * @throws Exception
+ */
+ public void testAlreadyLocked() throws Exception
+ {
+ MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
+ headers.add(ExtHttpHeaders.CONTENTTYPE, MediaType.TEXT_PLAIN);
+ ContainerResponse containerResponse =
+ service(WebDAVMethods.LOCK, getPathWS() + path, "", headers, lockRequestBody.getBytes());
+
+ assertEquals(HTTPStatus.OK, containerResponse.getStatus());
+
+ // some manipulation to serialize response entity
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ LockResultResponseEntity entity = (LockResultResponseEntity)containerResponse.getEntity();
+ entity.write(outputStream);
+
+ String lockToken = outputStream.toString();
+ lockToken = lockToken.substring(lockToken.indexOf(">opaquelocktoken:"));
+ lockToken = lockToken.substring(lockToken.indexOf(":") + 1, lockToken.indexOf("<"));
+
+ // prepare to send lock request
+ headers = new MultivaluedMapImpl();
+ headers.add(ExtHttpHeaders.CONTENTTYPE, MediaType.TEXT_PLAIN);
+ containerResponse = service(WebDAVMethods.LOCK, getPathWS() + path, "", headers, lockRequestBody.getBytes());
+
+ assertEquals(HTTPStatus.LOCKED, containerResponse.getStatus());
+
+ // add lock-token to current session and unlock the node
+ session.addLockToken(lockToken);
+ ((Node)session.getItem(path)).unlock();
+ }
+
@Override
protected String getRepositoryName()
{
Modified: jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/protocols/webdav.xml
===================================================================
--- jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/protocols/webdav.xml 2011-05-24 06:48:30 UTC (rev 4419)
+++ jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/protocols/webdav.xml 2011-05-24 09:43:47 UTC (rev 4420)
@@ -303,5 +303,43 @@
</listitem>
</orderedlist>
</section>
+ <section>
+ <title>Microsoft Office 2010</title>
+ <para>If you have Microsoft Office 2010 applications or Microsoft Office 2007 applications installed on a client computer. From that client computer, you try to access an Office file that is stored on a web server that is configured for Basic authentication. The connection between your computer and the web server does not use Secure Sockets Layer (SSL). When you try to open or to download the file, you experience the following symptoms:
+ <itemizedlist>
+ <listitem>
+ <para>The Office file does not open or download.</para>
+ </listitem>
+ <listitem>
+ <para>You do not receive a Basic authentication password prompt when you try to open or to download the file.</para>
+ </listitem>
+ <listitem>
+ <para>You do not receive an error message when you try to open the file. The associated Office application starts. However, the selected file does not open.</para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>To enable Basic authentication on the client computer, follow these steps:</para>
+ <orderedlist>
+ <listitem>
+ <para>Click Start, type regedit in the Start Search box, and then press Enter.</para>
+ </listitem>
+ <listitem>
+ <para>Locate and then click the following registry subkey: </para>
+ <para>HKEY_CURRENT_USER\Software\Microsoft\Office\14.0\Common\Internet</para>
+ </listitem>
+ <listitem>
+ <para>On the Edit menu, point to New, and then click DWORD Value.</para>
+ </listitem>
+ <listitem>
+ <para>Type BasicAuthLevel, and then press Enter.</para>
+ </listitem>
+ <listitem>
+ <para>Right-click BasicAuthLevel, and then click Modify.</para>
+ </listitem>
+ <listitem>
+ <para>In the Value data box, type 2, and then click OK.</para>
+ </listitem>
+ </orderedlist>
+ </section>
</section>
</chapter>
Added: jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1597/readme.txt
===================================================================
--- jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1597/readme.txt (rev 0)
+++ jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1597/readme.txt 2011-05-24 09:43:47 UTC (rev 4420)
@@ -0,0 +1,70 @@
+Summary
+
+ Status: Problem of webdav on windows 7
+ CCP Issue: CCP-823, Product Jira Issue: JCR-1597.
+ Complexity: Low
+
+The Proposal
+Problem description
+
+What is the problem to fix?
+There are some problems when using webdav on Windows 7. We can't open a document (MS Office 2010) or the document is opened as read only (Open Office)
+Fix description
+
+How is the problem fixed?
+
+ Lock tokens parsing fixed, to parse tokens not surrounded by '<' and '>' characters. To open documents via basic authentication on Windows 7 with MS Office 2010 we also need to edit registry.
+
+Patch information:
+Patch files: JCR-1597.patch
+
+Tests to perform
+
+Reproduction test
+* Steps to reproduce:
+1. Create a webdav drive on windows 7 by using this command net use o: "http://localhost:80/rest/private/jcr/repository/collaboration/" and those param must be verified:
+
+ "web client" service must be turn on
+ HKLM/system/currentversion/services/webclient/parameters/UseBasicAuth=2
+ the port of the jboss has to be 80 for http and 443 for https, not 8080 and 8443
+ 2. Open the document
+
+Tests performed at DevLevel
+
+ Created WebDAV drive on Windows 7. Tested opening and saving documents with MS Office 2010 and OpenOffice.org 3.3.2.
+
+Tests performed at QA/Support Level
+*
+
+Documentation changes
+
+Documentation changes:
+ Added description how to edit a registry to enable MS Office 2010 opening WebDAV documents using basic authentication over non-ssl connection.
+
+Configuration changes
+
+Configuration changes:
+ None
+
+Will previous configuration continue to work?
+ Yes
+
+Risks and impacts
+
+Can this bug fix have any side effects on current client projects?
+ No
+
+Is there a performance risk/cost?
+ No
+
+Validation (PM/Support/QA)
+
+PM Comment
+* PL review: Patch validated
+
+Support Comment
+* Support review: Patch validated
+
+QA Feedbacks
+*
+
13 years
exo-jcr SVN: r4419 - in jcr/trunk: exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/version and 1 other directories.
by do-not-reply@jboss.org
Author: tolusha
Date: 2011-05-24 02:48:30 -0400 (Tue, 24 May 2011)
New Revision: 4419
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/datamodel/InternalQName.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/version/VersionHistoryDataHelper.java
jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/script/groovy/JcrGroovyResourceLoader.java
Log:
EXOJCR-1187: avoid using intern calls
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/datamodel/InternalQName.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/datamodel/InternalQName.java 2011-05-24 06:47:34 UTC (rev 4418)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/datamodel/InternalQName.java 2011-05-24 06:48:30 UTC (rev 4419)
@@ -40,7 +40,7 @@
*/
public InternalQName(String namespace, String name)
{
- super(safeIntern(namespace), safeIntern(name));
+ super(safeIntern(namespace), name);
}
private static String safeIntern(String s)
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/version/VersionHistoryDataHelper.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/version/VersionHistoryDataHelper.java 2011-05-24 06:47:34 UTC (rev 4418)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/version/VersionHistoryDataHelper.java 2011-05-24 06:48:30 UTC (rev 4419)
@@ -123,8 +123,8 @@
TransientNodeData vh = init(versionable, changes);
// TransientItemData
- this.parentIdentifier = vh.getParentIdentifier().intern();
- this.identifier = vh.getIdentifier().intern();
+ this.parentIdentifier = vh.getParentIdentifier();
+ this.identifier = vh.getIdentifier();
this.qpath = vh.getQPath();
this.persistedVersion = vh.getPersistedVersion();
Modified: jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/script/groovy/JcrGroovyResourceLoader.java
===================================================================
--- jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/script/groovy/JcrGroovyResourceLoader.java 2011-05-24 06:47:34 UTC (rev 4418)
+++ jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/script/groovy/JcrGroovyResourceLoader.java 2011-05-24 06:48:30 UTC (rev 4419)
@@ -79,30 +79,18 @@
{
if (LOG.isDebugEnabled())
LOG.debug("Process file: " + filename);
- URL resource = null;
- filename = filename.intern();
- synchronized (filename)
- {
- resource = resources.get(filename);
- boolean inCache = resource != null;
- if (inCache && !checkResource(resource))
- resource = null;
- for (int i = 0; i < roots.length && resource == null; i++)
- {
- // In JCR URL path represented by fragment jcr://repository/workspace#/path
- URL tmp =
- ("jcr".equals(roots[i].getProtocol())) ? new URL(roots[i], "#" + roots[i].getRef() + filename)
- : new URL(roots[i], filename);
- if (checkResource(tmp))
- resource = tmp;
- }
- if (resource != null)
- resources.put(filename, resource);
- else if (inCache)
- resources.remove(filename);
- }
- return resource;
+ return super.getResource(filename);
}
+
+ /**
+ * @see org.exoplatform.services.rest.ext.groovy.DefaultGroovyResourceLoader#createURL(java.net.URL,java.lang.String)
+ */
+ @Override
+ protected URL createURL(URL root, String filename) throws MalformedURLException
+ {
+ return ("jcr".equals(root.getProtocol())) ? new URL(root, "#" + root.getRef() + filename)
+ : new URL(root, filename);
+ }
/**
* @see org.exoplatform.services.rest.ext.groovy.DefaultGroovyResourceLoader#checkResource(java.net.URL)
13 years
exo-jcr SVN: r4418 - ws/trunk/exo.ws.rest.ext/src/main/java/org/exoplatform/services/rest/ext/groovy.
by do-not-reply@jboss.org
Author: tolusha
Date: 2011-05-24 02:47:34 -0400 (Tue, 24 May 2011)
New Revision: 4418
Modified:
ws/trunk/exo.ws.rest.ext/src/main/java/org/exoplatform/services/rest/ext/groovy/DefaultGroovyResourceLoader.java
Log:
EXOJCR-1187: avoid using intern calls
Modified: ws/trunk/exo.ws.rest.ext/src/main/java/org/exoplatform/services/rest/ext/groovy/DefaultGroovyResourceLoader.java
===================================================================
--- ws/trunk/exo.ws.rest.ext/src/main/java/org/exoplatform/services/rest/ext/groovy/DefaultGroovyResourceLoader.java 2011-05-24 06:33:05 UTC (rev 4417)
+++ ws/trunk/exo.ws.rest.ext/src/main/java/org/exoplatform/services/rest/ext/groovy/DefaultGroovyResourceLoader.java 2011-05-24 06:47:34 UTC (rev 4418)
@@ -31,6 +31,13 @@
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.FutureTask;
/**
* @author <a href="mailto:andrew00x@gmail.com">Andrey Parfonov</a>
@@ -41,6 +48,8 @@
{
private static final String DEFAULT_SOURCE_FILE_EXTENSION = ".groovy";
+ public final ConcurrentMap<String, Future<URL>> findResourceURLTasks = new ConcurrentHashMap<String, Future<URL>>();
+
// TODO need configurable ?
private int maxEntries = 512;
@@ -100,30 +109,80 @@
return resource;
}
- protected URL getResource(String filename) throws MalformedURLException
+ protected URL getResource(final String filename) throws MalformedURLException
{
- URL resource = null;
- filename = filename.intern();
- synchronized (filename)
+ // First we check the cache outside the synchronized block
+ URL resource = resources.get(filename);
+ if (resource != null && checkResource(resource))
{
- resource = resources.get(filename);
- boolean inCache = resource != null;
- if (inCache && !checkResource(resource))
- resource = null; // Resource in cache is unreachable.
- for (int i = 0; i < roots.length && resource == null; i++)
+ // The resource could be found in the cache and is reachable
+ return resource;
+ }
+ // The resource cannot be found or is unreachable
+ // Check if a corresponding findResourceURL task exists
+ Future<URL> findResourceURLTask = findResourceURLTasks.get(filename);
+ if (findResourceURLTask == null)
+ {
+ // The task doesn't exist so we create it
+ FutureTask<URL> f = new FutureTask<URL>(new Callable<URL>()
{
- URL tmp = new URL(roots[i], filename);
- if (checkResource(tmp))
- resource = tmp;
+ public URL call() throws Exception
+ {
+ return findResourceURL(filename);
+ }
+ });
+ // We add the new task to the existing tasks
+ findResourceURLTask = findResourceURLTasks.putIfAbsent(filename, f);
+ if (findResourceURLTask == null)
+ {
+ // The task has not be registered so we launch it
+ findResourceURLTask = f;
+ f.run();
}
- if (resource != null)
- resources.put(filename, resource);
- else if (inCache)
- resources.remove(filename);
}
+ try
+ {
+ return findResourceURLTask.get();
+ }
+ catch (CancellationException e)
+ {
+ findResourceURLTasks.remove(filename, findResourceURLTask);
+ }
+ catch (ExecutionException e)
+ {
+ throw (MalformedURLException)e.getCause();
+ }
+ catch (InterruptedException e)
+ {
+ Thread.currentThread().interrupt();
+ }
+ return null;
+ }
+
+ protected URL findResourceURL(String filename) throws MalformedURLException
+ {
+ URL resource = resources.get(filename);
+ boolean inCache = resource != null;
+ if (inCache && !checkResource(resource))
+ resource = null; // Resource in cache is unreachable.
+ for (int i = 0; i < roots.length && resource == null; i++)
+ {
+ URL tmp = createURL(roots[i], filename);
+ if (checkResource(tmp))
+ resource = tmp;
+ }
+ if (resource != null)
+ resources.put(filename, resource);
+ else if (inCache)
+ resources.remove(filename);
return resource;
}
-
+
+ protected URL createURL(URL root, String filename) throws MalformedURLException
+ {
+ return new URL(root, filename);
+ }
+
protected String getSourceFileExtension()
{
return DEFAULT_SOURCE_FILE_EXTENSION;
13 years
exo-jcr SVN: r4417 - jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/kernel.
by do-not-reply@jboss.org
Author: tolusha
Date: 2011-05-24 02:33:05 -0400 (Tue, 24 May 2011)
New Revision: 4417
Modified:
jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/kernel/transaction-service.xml
Log:
EXOJCR-1329: Allow to use TransactionsEssentials as TransactionManager
Modified: jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/kernel/transaction-service.xml
===================================================================
--- jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/kernel/transaction-service.xml 2011-05-24 06:32:39 UTC (rev 4416)
+++ jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/kernel/transaction-service.xml 2011-05-24 06:33:05 UTC (rev 4417)
@@ -72,7 +72,7 @@
<section>
<title>JOTM in standalone mode</title>
- <para>To use JOTM as TransactionManager in standalone mode simply add
+ <para>To use JOTM as TransactionManager in standalone mode, simply add
the following component configuration:</para>
<programlisting> <component>
@@ -225,5 +225,24 @@
</init-params-->
</component></programlisting>
</section>
+
+ <section>
+ <title>TransactionsEssentials in standalone mode</title>
+
+ <para>To use TransactionsEssentials as TransactionManager in standalone
+ mode, simply add the following component configuration:</para>
+
+ <programlisting> <component>
+ <key>org.exoplatform.services.transaction.TransactionService</key>
+ <type>org.exoplatform.services.transaction.impl.atomikos.TransactionsEssentialsTransactionService</type>
+ <!-- Uncomment the lines below if you want to set default transaction timeout that is expressed in seconds -->
+ <!--init-params>
+ <value-param>
+ <name>timeout</name>
+ <value>60</value>
+ </value-param>
+ </init-params-->
+ </component></programlisting>
+ </section>
</section>
</chapter>
13 years
exo-jcr SVN: r4416 - in kernel/trunk: exo.kernel.component.common and 2 other directories.
by do-not-reply@jboss.org
Author: tolusha
Date: 2011-05-24 02:32:39 -0400 (Tue, 24 May 2011)
New Revision: 4416
Added:
kernel/trunk/exo.kernel.component.common/src/main/java/org/exoplatform/services/transaction/impl/atomikos/
kernel/trunk/exo.kernel.component.common/src/main/java/org/exoplatform/services/transaction/impl/atomikos/TransactionsEssentialsTransactionService.java
Modified:
kernel/trunk/exo.kernel.component.common/pom.xml
kernel/trunk/pom.xml
Log:
EXOJCR-1329: Allow to use TransactionsEssentials as TransactionManager
Modified: kernel/trunk/exo.kernel.component.common/pom.xml
===================================================================
--- kernel/trunk/exo.kernel.component.common/pom.xml 2011-05-24 04:33:12 UTC (rev 4415)
+++ kernel/trunk/exo.kernel.component.common/pom.xml 2011-05-24 06:32:39 UTC (rev 4416)
@@ -101,6 +101,11 @@
<groupId>org.jgroups</groupId>
<artifactId>jgroups</artifactId>
</dependency>
+ <dependency>
+ <groupId>com.atomikos</groupId>
+ <artifactId>transactions-jta</artifactId>
+ <scope>provided</scope>
+ </dependency>
</dependencies>
<build>
<plugins>
Added: kernel/trunk/exo.kernel.component.common/src/main/java/org/exoplatform/services/transaction/impl/atomikos/TransactionsEssentialsTransactionService.java
===================================================================
--- kernel/trunk/exo.kernel.component.common/src/main/java/org/exoplatform/services/transaction/impl/atomikos/TransactionsEssentialsTransactionService.java (rev 0)
+++ kernel/trunk/exo.kernel.component.common/src/main/java/org/exoplatform/services/transaction/impl/atomikos/TransactionsEssentialsTransactionService.java 2011-05-24 06:32:39 UTC (rev 4416)
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2011 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.exoplatform.services.transaction.impl.atomikos;
+
+import com.atomikos.icatch.jta.UserTransactionManager;
+
+import org.exoplatform.services.transaction.TransactionService;
+import org.exoplatform.services.transaction.impl.AbstractTransactionService;
+import org.picocontainer.Startable;
+
+import javax.transaction.TransactionManager;
+import javax.transaction.UserTransaction;
+
+/**
+ * An implementation of a {@link TransactionService} for TransactionsEssentials from Atomikos
+ * to be used in standalone mode
+ *
+ * @author <a href="mailto:nfilotto@exoplatform.com">Nicolas Filotto</a>
+ * @version $Id$
+ *
+ */
+public class TransactionsEssentialsTransactionService extends AbstractTransactionService implements Startable
+{
+
+ /**
+ * @see org.exoplatform.services.transaction.impl.AbstractTransactionService#findTransactionManager()
+ */
+ @Override
+ protected TransactionManager findTransactionManager() throws Exception
+ {
+ UserTransactionManager tm = new UserTransactionManager();
+ tm.init();
+ return tm;
+ }
+
+ /**
+ * @see org.exoplatform.services.transaction.impl.AbstractTransactionService#findUserTransaction()
+ */
+ @Override
+ protected UserTransaction findUserTransaction() throws Exception
+ {
+ return (UserTransaction)getTransactionManager();
+ }
+
+ /**
+ * @see org.picocontainer.Startable#start()
+ */
+ public void start()
+ {
+ }
+
+ /**
+ * @see org.picocontainer.Startable#stop()
+ */
+ public void stop()
+ {
+ if (isTMInitialized())
+ {
+ TransactionManager tm = getTransactionManager();
+ if (tm instanceof UserTransactionManager)
+ {
+ UserTransactionManager utm = (UserTransactionManager)tm;
+ utm.close();
+ }
+ }
+ }
+}
Modified: kernel/trunk/pom.xml
===================================================================
--- kernel/trunk/pom.xml 2011-05-24 04:33:12 UTC (rev 4415)
+++ kernel/trunk/pom.xml 2011-05-24 06:32:39 UTC (rev 4416)
@@ -213,6 +213,11 @@
<artifactId>jotm-core</artifactId>
<version>2.1.9</version>
</dependency>
+ <dependency>
+ <groupId>com.atomikos</groupId>
+ <artifactId>transactions-jta</artifactId>
+ <version>3.7.0</version>
+ </dependency>
</dependencies>
</dependencyManagement>
13 years