[exo-jcr-commits] exo-jcr SVN: r5809 - in jcr/branches/1.15.x: exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent and 12 other directories.

do-not-reply at jboss.org do-not-reply at jboss.org
Tue Mar 6 03:54:15 EST 2012


Author: tolusha
Date: 2012-03-06 03:54:13 -0500 (Tue, 06 Mar 2012)
New Revision: 5809

Added:
   jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/JDBCConnectionFactory.java
Modified:
   jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/JDBCCacheLoader.java
   jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/CacheableWorkspaceDataManager.java
   jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/WorkspacePersistentDataManager.java
   jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCStorageConnection.java
   jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCStorageConnection.java.orig
   jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/statistics/StatisticsJDBCStorageConnection.java
   jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/value/ValueOperation.java
   jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/value/fs/FileIOChannel.java
   jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/value/fs/operations/CASableDeleteValues.java
   jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/value/fs/operations/CASableWriteValue.java
   jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/value/fs/operations/DeleteValues.java
   jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/value/fs/operations/ValueFileOperation.java
   jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/value/fs/operations/WriteValue.java
   jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/storage/WorkspaceStorageConnection.java
   jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/storage/value/ValueIOChannel.java
   jcr/branches/1.15.x/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/BaseStandaloneTest.java
   jcr/branches/1.15.x/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/TestCacheableWorkspaceDataManager.java
   jcr/branches/1.15.x/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/TestWorkspaceStorageCacheInClusterMode.java
   jcr/branches/1.15.x/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/cache/jbosscache/TestJBossCacheWorkspaceStorageCache.java
   jcr/branches/1.15.x/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/faq/jcr-faq.xml
   jcr/branches/1.15.x/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/cluster-config.xml
   jcr/branches/1.15.x/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/jbosscache-configuration-templates.xml
   jcr/branches/1.15.x/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/lock-manager-config.xml
   jcr/branches/1.15.x/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/query-handler-config.xml
Log:
EXOJCR-1763: avoided potential inconsistency related to replication timeout

Modified: jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/JDBCCacheLoader.java
===================================================================
--- jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/JDBCCacheLoader.java	2012-03-06 07:08:30 UTC (rev 5808)
+++ jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/JDBCCacheLoader.java	2012-03-06 08:54:13 UTC (rev 5809)
@@ -20,6 +20,7 @@
 
 import org.exoplatform.services.database.utils.JDBCUtils;
 import org.jboss.cache.config.CacheLoaderConfig;
+import org.jboss.cache.config.CacheLoaderConfig.IndividualCacheLoaderConfig;
 import org.jboss.cache.loader.AdjListJDBCCacheLoaderConfig;
 
 import java.sql.Connection;
@@ -27,7 +28,8 @@
 
 /**
  * This class is used to override the method AdjListJDBCCacheLoader#tableExists in order
- * to more easily ensure multi-schema support.
+ * to more easily ensure multi-schema support and the method AdjListJDBCCacheLoader#setConfig
+ * in order to be able to use a data source name even in case of non managed data sources.
  * 
  * @author <a href="mailto:nfilotto at exoplatform.com">Nicolas Filotto</a>
  * @version $Id$
@@ -41,7 +43,23 @@
    {
       return JDBCUtils.tableExists(tableName, con);
    }
+   @Override
+   public void setConfig(IndividualCacheLoaderConfig base)
+   {
+      super.setConfig(base);
+      AdjListJDBCCacheLoaderConfig config = processConfig(base);
 
+      if (config.getDatasourceName() == null)
+      {
+         return;
+      }
+      /* We create the JDBCConnectionFactory instance but the JNDI lookup is no done until
+the start method is called, since that's when its registered in its lifecycle */
+      cf = new JDBCConnectionFactory();
+      /* We set the configuration */
+      cf.setConfig(config);
+   }
+   
    /**
     * {@inheritDoc}
     */

Added: jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/JDBCConnectionFactory.java
===================================================================
--- jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/JDBCConnectionFactory.java	                        (rev 0)
+++ jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/JDBCConnectionFactory.java	2012-03-06 08:54:13 UTC (rev 5809)
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2012 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.jcr.impl.core.lock.jbosscache;
+
+import org.exoplatform.container.ExoContainer;
+import org.exoplatform.container.ExoContainerContext;
+import org.exoplatform.services.jdbc.DataSourceProvider;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+import org.jboss.cache.loader.AdjListJDBCCacheLoaderConfig;
+import org.jboss.cache.loader.ConnectionFactory;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.sql.DataSource;
+
+/**
+ * @author <a href="mailto:nicolas.filotto at exoplatform.com">Nicolas Filotto</a>
+ * @version $Id$
+ */
+public class JDBCConnectionFactory implements ConnectionFactory
+{
+
+   /**
+    * Logger
+    */
+   private static final Log LOG = ExoLogger.getLogger("exo.jcr.component.core.NonManagedConnectionFactory");
+
+   private static final boolean trace = LOG.isTraceEnabled();
+
+   static final ThreadLocal<Connection> connection = new ThreadLocal<Connection>();
+
+   private DataSource dataSource;
+
+   private String datasourceName;
+
+   public void setConfig(AdjListJDBCCacheLoaderConfig config)
+   {
+      datasourceName = config.getDatasourceName();
+   }
+
+   private DataSourceProvider getDataSourceProvider()
+   {
+      ExoContainer container = ExoContainerContext.getCurrentContainer();
+      if (container == null)
+      {
+         LOG.warn("The current container cannot be found which prevents to retrieve the DataSourceProvider");
+         return null;
+      }
+      DataSourceProvider dsProvider =
+         (DataSourceProvider)container.getComponentInstanceOfType(DataSourceProvider.class);
+      if (dsProvider == null)
+      {
+         LOG.warn("The DataSourceProvider cannot be found in the container " + container.getContext().getName()
+            + ", it will be considered as non managed ");
+      }
+      return dsProvider;
+   }
+
+   public void start() throws Exception
+   {
+      // A datasource will be registered in JNDI in the start portion of
+      // its lifecycle, so now that we are in start() we can look it up
+
+      DataSourceProvider dsProvider = getDataSourceProvider();
+      InitialContext ctx = null;
+      try
+      {
+         if (dsProvider == null)
+         {
+            ctx = new InitialContext();
+            dataSource = (DataSource)ctx.lookup(datasourceName);
+         }
+         else
+         {
+            dataSource = dsProvider.getDataSource(datasourceName);
+         }
+         if (trace)
+         {
+            LOG.trace("Datasource lookup for " + datasourceName + " succeded: " + dataSource);
+         }
+      }
+      catch (NamingException e)
+      {
+         reportAndRethrowError("Failed to lookup datasource " + datasourceName, e);
+      }
+      finally
+      {
+         if (ctx != null)
+         {
+            try
+            {
+               ctx.close();
+            }
+            catch (NamingException e)
+            {
+               LOG.warn("Failed to close naming context.", e);
+            }
+         }
+      }
+   }
+
+   public void prepare(Object tx)
+   {
+      Connection con = getConnection();
+      try
+      {
+         if (con.getAutoCommit())
+         {
+            con.setAutoCommit(false);
+         }
+      }
+      catch (Exception e)
+      {
+         reportAndRethrowError("Failed to set auto-commit", e);
+      }
+
+      /* Connection set in ThreadLocal, no reason to return. It was previously returned for legacy purpouses
+      and to trace log the connection opening in JDBCCacheLoader. */
+      connection.set(con);
+
+      if (trace)
+      {
+         LOG.trace("opened tx connection: tx=" + tx + ", con=" + con);
+      }
+
+   }
+
+   public Connection getConnection()
+   {
+      Connection con = connection.get();
+
+      if (con == null)
+      {
+         try
+         {
+            con = checkoutConnection();
+            //               connection.set(con);
+         }
+         catch (SQLException e)
+         {
+            reportAndRethrowError("Failed to get connection for datasource=" + datasourceName, e);
+         }
+      }
+
+      if (trace)
+      {
+         LOG.trace("using connection: " + con);
+      }
+
+      return con;
+   }
+
+   public Connection checkoutConnection() throws SQLException
+   {
+      return dataSource.getConnection();
+   }
+
+   public void commit(Object tx)
+   {
+      Connection con = connection.get();
+      if (con == null)
+      {
+         throw new IllegalStateException("Failed to commit: thread is not associated with the connection!");
+      }
+
+      try
+      {
+         con.commit();
+         if (trace)
+         {
+            LOG.trace("committed tx=" + tx + ", con=" + con);
+         }
+      }
+      catch (SQLException e)
+      {
+         reportAndRethrowError("Failed to commit", e);
+      }
+      finally
+      {
+         closeTxConnection(con);
+      }
+   }
+
+   public void rollback(Object tx)
+   {
+      Connection con = connection.get();
+
+      try
+      {
+         con.rollback();
+         if (trace)
+         {
+            LOG.trace("rolledback tx=" + tx + ", con=" + con);
+         }
+      }
+      catch (SQLException e)
+      {
+         reportAndRethrowError("Failed to rollback", e);
+      }
+      finally
+      {
+         closeTxConnection(con);
+      }
+   }
+
+   public void close(Connection con)
+   {
+      if (con != null && con != connection.get())
+      {
+         try
+         {
+            con.close();
+
+            if (trace)
+            {
+               LOG.trace("closed non tx connection: " + con);
+            }
+         }
+         catch (SQLException e)
+         {
+            LOG.warn("Failed to close connection " + con, e);
+         }
+      }
+   }
+
+   public void stop()
+   {
+   }
+
+   private void closeTxConnection(Connection con)
+   {
+      safeClose(con);
+      connection.set(null);
+   }
+
+   private void safeClose(Connection con)
+   {
+      if (con != null)
+      {
+         try
+         {
+            con.close();
+         }
+         catch (SQLException e)
+         {
+            LOG.warn("Failed to close connection", e);
+         }
+      }
+   }
+
+   private void reportAndRethrowError(String message, Exception cause) throws IllegalStateException
+   {
+      LOG.error(message, cause);
+      throw new IllegalStateException(message, cause);
+   }
+}

Modified: jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/CacheableWorkspaceDataManager.java
===================================================================
--- jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/CacheableWorkspaceDataManager.java	2012-03-06 07:08:30 UTC (rev 5808)
+++ jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/CacheableWorkspaceDataManager.java	2012-03-06 08:54:13 UTC (rev 5809)
@@ -128,8 +128,6 @@
 
    private volatile BloomFilter<String> filterOwner;
 
-   private TransactionManager transactionManager;
-
    /**
     * The service for executing commands on all nodes of cluster.
     */
@@ -397,7 +395,7 @@
       WorkspaceStorageCache cache, SystemDataContainerHolder systemDataContainerHolder,
       TransactionableResourceManager txResourceManager, TransactionService transactionService, RPCService rpcService)
    {
-      super(dataContainer, systemDataContainerHolder, txResourceManager);
+      super(dataContainer, systemDataContainerHolder, txResourceManager, transactionService.getTransactionManager());
 
       bfProbability =
          wsConfig.getContainer().getParameterDouble(WorkspaceDataContainer.ACL_BF_FALSE_PROPBABILITY,
@@ -422,8 +420,6 @@
       this.requestCache = new ConcurrentHashMap<Integer, DataRequest>();
       addItemPersistenceListener(new CacheItemsPersistenceListener());
 
-      transactionManager = transactionService.getTransactionManager();
-
       this.rpcService = rpcService;
       this.txResourceManager = txResourceManager;
       doInitRemoteCommands();
@@ -469,7 +465,7 @@
       WorkspaceStorageCache cache, SystemDataContainerHolder systemDataContainerHolder,
       TransactionableResourceManager txResourceManager, RPCService rpcService)
    {
-      super(dataContainer, systemDataContainerHolder, txResourceManager);
+      super(dataContainer, systemDataContainerHolder, txResourceManager, getTransactionManagerFromCache(cache));
 
       bfProbability =
          wsConfig.getContainer().getParameterDouble(WorkspaceDataContainer.ACL_BF_FALSE_PROPBABILITY,
@@ -493,18 +489,6 @@
 
       this.requestCache = new ConcurrentHashMap<Integer, DataRequest>();
       addItemPersistenceListener(new CacheItemsPersistenceListener());
-
-      try
-      {
-         transactionManager =
-            (TransactionManager)cache.getClass().getMethod("getTransactionManager", null).invoke(null, null);
-      }
-      catch (Exception e)
-      {
-         LOG.debug("Could not get the transaction manager from the cache", e);
-         transactionManager = null;
-      }
-
       this.rpcService = rpcService;
       this.txResourceManager = txResourceManager;
       doInitRemoteCommands();
@@ -550,6 +534,24 @@
    }
 
    /**
+    * Try to get the TransactionManager from the cache by calling by reflection
+    * getTransactionManager() on the cache instance, by default it will return null
+    */
+   private static TransactionManager getTransactionManagerFromCache(WorkspaceStorageCache cache)
+   {
+      try
+      {
+         return (TransactionManager)cache.getClass().getMethod("getTransactionManager", (Class<?>[])null)
+            .invoke(cache, (Object[])null);
+      }
+      catch (Exception e)
+      {
+         LOG.debug("Could not get the transaction manager from the cache", e);
+      }
+      return null;
+   }
+   
+   /**
     * Get Items Cache.
     * 
     * @return WorkspaceStorageCache

Modified: jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/WorkspacePersistentDataManager.java
===================================================================
--- jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/WorkspacePersistentDataManager.java	2012-03-06 07:08:30 UTC (rev 5808)
+++ jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/WorkspacePersistentDataManager.java	2012-03-06 08:54:13 UTC (rev 5809)
@@ -61,6 +61,9 @@
 
 import javax.jcr.InvalidItemStateException;
 import javax.jcr.RepositoryException;
+import javax.transaction.Status;
+import javax.transaction.Synchronization;
+import javax.transaction.TransactionManager;
 
 /**
  * Created by The eXo Platform SAS.<br>
@@ -102,7 +105,7 @@
    /**
     * Persistent level listeners filters.
     */
-   protected final List<ItemsPersistenceListenerFilter> liestenerFilters;
+   protected final List<ItemsPersistenceListenerFilter> listenerFilters;
 
    /**
     * Read-only status.
@@ -115,6 +118,10 @@
    private final TransactionableResourceManager txResourceManager;
 
    /**
+    * The transaction manager
+    */
+   protected final TransactionManager transactionManager;
+   /**
     * Changes log wrapper adds possibility to replace changes log.
     * Changes log contains transient data on save but listeners should be notifyed
     * with persisted data only.
@@ -177,7 +184,7 @@
    protected WorkspacePersistentDataManager(WorkspaceDataContainer dataContainer,
       SystemDataContainerHolder systemDataContainerHolder)
    {
-      this(dataContainer, systemDataContainerHolder, null);
+      this(dataContainer, systemDataContainerHolder, null, null);
    }
 
    /**
@@ -191,15 +198,16 @@
     *          the resource manager used to manage the whole tx
     */
    public WorkspacePersistentDataManager(WorkspaceDataContainer dataContainer,
-      SystemDataContainerHolder systemDataContainerHolder, TransactionableResourceManager txResourceManager)
+      SystemDataContainerHolder systemDataContainerHolder, TransactionableResourceManager txResourceManager, TransactionManager transactionManager)
    {
       this.dataContainer = dataContainer;
       this.systemDataContainer = systemDataContainerHolder.getContainer();
 
       this.listeners = new ArrayList<ItemsPersistenceListener>();
       this.mandatoryListeners = new ArrayList<MandatoryItemsPersistenceListener>();
-      this.liestenerFilters = new ArrayList<ItemsPersistenceListenerFilter>();
+      this.listenerFilters = new ArrayList<ItemsPersistenceListenerFilter>();
       this.txResourceManager = txResourceManager;
+      this.transactionManager = transactionManager;
    }
 
    /**
@@ -248,7 +256,7 @@
          }
          // replace log with persisted data only
          logWrapper.setLog(persistedLog);
-
+         persister.prepare();
          notifySaveItems(persistedLog, true);
          onCommit(persister, mode);
          failed = false;
@@ -262,7 +270,7 @@
          persister.clear();
          if (failed)
          {
-            onRollback(persister, mode);
+            persister.rollback();
          }
       }
    }
@@ -274,22 +282,13 @@
    {
       if (txResourceManager != null && txResourceManager.isGlobalTxActive())
       {
-         return ConnectionMode.PARTIALLY_MANAGED;
+         return ConnectionMode.GLOBAL_TX;
       }
-      return ConnectionMode.NORMAL;
-   }
-
-   /**
-    * @param persister
-    * @throws RepositoryException
-    */
-   private void onRollback(final ChangesLogPersister persister, ConnectionMode mode) throws RepositoryException
-   {
-      if (mode == ConnectionMode.NORMAL || mode == ConnectionMode.PARTIALLY_MANAGED)
+      else if (transactionManager != null)
       {
-         // The rollback is done normally
-         persister.rollback();
+         return ConnectionMode.WITH_TRANSACTION_MANAGER;
       }
+      return ConnectionMode.NORMAL;
    }
 
    /**
@@ -303,8 +302,58 @@
          // The commit is done normally
          persister.commit();
       }
-      else if (mode == ConnectionMode.PARTIALLY_MANAGED)
+      else if (mode == ConnectionMode.WITH_TRANSACTION_MANAGER)
       {
+         try
+         {
+            transactionManager.getTransaction().registerSynchronization(new Synchronization()
+            {
+
+               public void beforeCompletion()
+               {
+               }
+
+               public void afterCompletion(int status)
+               {
+                  switch (status)
+                  {
+                     case Status.STATUS_COMMITTED:
+                        try
+                        {
+                           persister.commit();
+                        }
+                        catch (Exception e)
+                        {
+                           throw new RuntimeException("Could not commit the transaction", e);
+                        }
+                        break;
+                     case Status.STATUS_UNKNOWN:
+                        LOG.warn("Status UNKNOWN received in afterCompletion method, some data could have been corrupted !!");
+                     case Status.STATUS_MARKED_ROLLBACK:
+                     case Status.STATUS_ROLLEDBACK:
+                        try
+                        {
+                           persister.rollback();
+                        }
+                        catch (Exception e)
+                        {
+                           LOG.error("Could not roll back the transaction", e);
+                        }
+                        break;
+
+                     default:
+                        throw new IllegalStateException("illegal status: " + status);
+                  }                  
+               }
+            });
+         }
+         catch (Exception e)
+         {
+            throw new RepositoryException("Cannot register the synchronization for a late commit", e);
+         }
+      }
+      else if (mode == ConnectionMode.GLOBAL_TX)
+      {
          // The commit or rollback will be done by callback once the tx will be completed since it could
          // fail later in the tx
          txResourceManager.addListener(new TransactionableResourceManagerListener()
@@ -328,7 +377,7 @@
    }
 
    private enum ConnectionMode {
-      NORMAL, PARTIALLY_MANAGED
+      NORMAL, WITH_TRANSACTION_MANAGER, GLOBAL_TX
    }
 
    class ChangesLogPersister
@@ -352,6 +401,18 @@
          }
       }
 
+      protected void prepare() throws IllegalStateException, RepositoryException
+      {
+         if (thisConnection != null && thisConnection.isOpened())
+         {
+            thisConnection.prepare();
+         }
+         if (systemConnection != null && !systemConnection.equals(thisConnection) && systemConnection.isOpened())
+         {
+            systemConnection.prepare();
+         }
+      }
+
       protected void clear()
       {
          // help to GC
@@ -961,7 +1022,7 @@
     */
    public void addItemPersistenceListenerFilter(ItemsPersistenceListenerFilter filter)
    {
-      this.liestenerFilters.add(filter);
+      this.listenerFilters.add(filter);
    }
 
    /**
@@ -969,7 +1030,7 @@
     */
    public void removeItemPersistenceListenerFilter(ItemsPersistenceListenerFilter filter)
    {
-      this.liestenerFilters.remove(filter);
+      this.listenerFilters.remove(filter);
    }
 
    /**
@@ -982,7 +1043,7 @@
     */
    protected boolean isListenerAccepted(ItemsPersistenceListener listener)
    {
-      for (ItemsPersistenceListenerFilter f : liestenerFilters)
+      for (ItemsPersistenceListenerFilter f : listenerFilters)
       {
          if (!f.accept(listener))
          {

Modified: jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCStorageConnection.java
===================================================================
--- jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCStorageConnection.java	2012-03-06 07:08:30 UTC (rev 5808)
+++ jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCStorageConnection.java	2012-03-06 08:54:13 UTC (rev 5809)
@@ -348,16 +348,38 @@
 
          if (!readOnly)
          {
-            dbConnection.rollback();
+            try
+            {
+               dbConnection.rollback();               
+            }
+            finally
+            {
+               // rollback from the end
+               IOException e = null;
+               for (int p = valueChanges.size() - 1; p >= 0; p--)
+               {
+                  try
+                  {
+                     valueChanges.get(p).rollback();
+                  }
+                  catch (IOException e1)
+                  {
+                     if (e == null)
+                     {
+                        e = e1;
+                     }
+                     else
+                     {
+                        LOG.error("Could not rollback value change", e1);
+                     }
+                  }
+               }               
+               if (e != null)
+               {
+                  throw e;
+               }
+            }
          }
-
-         dbConnection.close();
-
-         // rollback from the end
-         for (int p = valueChanges.size() - 1; p >= 0; p--)
-         {
-            valueChanges.get(p).rollback();
-         }
       }
       catch (SQLException e)
       {
@@ -370,6 +392,17 @@
       finally
       {
          valueChanges.clear();
+         try
+         {
+            dbConnection.close();
+         }
+         catch (SQLException e)
+         {
+            if (LOG.isWarnEnabled())
+            {
+               LOG.warn("Could not close the connection", e);
+            }
+         }         
       }
    }
 
@@ -580,6 +613,24 @@
          LOG.error("Can't close the statement: " + e.getMessage());
       }
    }
+   
+   /**
+    * {@inheritDoc}
+    */
+   public final void prepare() throws IllegalStateException, RepositoryException
+   {
+      try
+      {
+         for (ValueIOChannel vo : valueChanges)
+         {
+            vo.prepare();
+         }
+      }
+      catch (IOException e)
+      {
+         throw new RepositoryException(e);
+      }
+   }
 
    /**
     * {@inheritDoc}
@@ -591,33 +642,44 @@
       {
          closeStatements();
 
-         if (!this.readOnly)
+         if (!readOnly)
          {
+            try
+            {
+               for (ValueIOChannel vo : valueChanges)
+               {
+                  vo.twoPhaseCommit();
+               }
+            }
+            catch (IOException e)
+            {
+               throw new RepositoryException(e);
+            }
+            finally
+            {
+               valueChanges.clear();
+            }
             dbConnection.commit();
          }
-
-         dbConnection.close();
-
+      }
+      catch (SQLException e)
+      {
+         throw new RepositoryException(e);
+      }
+      finally
+      {
          try
          {
-            for (ValueIOChannel vo : valueChanges)
+            dbConnection.close();
+         }
+         catch (SQLException e)
+         {
+            if (LOG.isWarnEnabled())
             {
-               vo.commit();
+               LOG.warn("Could not close the connection", e);
             }
          }
-         catch (IOException e)
-         {
-            throw new RepositoryException(e);
-         }
-         finally
-         {
-            valueChanges.clear();
-         }
       }
-      catch (SQLException e)
-      {
-         throw new RepositoryException(e);
-      }
    }
 
    /**

Modified: jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCStorageConnection.java.orig
===================================================================
--- jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCStorageConnection.java.orig	2012-03-06 07:08:30 UTC (rev 5808)
+++ jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCStorageConnection.java.orig	2012-03-06 08:54:13 UTC (rev 5809)
@@ -167,7 +167,7 @@
 
    protected PreparedStatement findPropertiesByParentId;
 
-   protected PreparedStatement findLowestPropertyVersions;
+   protected PreparedStatement findMaxPropertyVersions;
 
    protected PreparedStatement insertItem;
 
@@ -485,9 +485,9 @@
             findPropertiesByParentId.close();
          }
 
-         if (findLowestPropertyVersions != null)
+         if (findMaxPropertyVersions != null)
          {
-            findLowestPropertyVersions.close();
+            findMaxPropertyVersions.close();
          }
 
          if (insertItem != null)
@@ -1006,6 +1006,44 @@
    /**
     * {@inheritDoc}
     */
+   public int getMaxPropertyVersion(PropertyData data) throws RepositoryException
+   {
+      checkIfOpened();
+      try
+      {
+         ResultSet count = findMaxPropertyVersion(data.getParentIdentifier(), data.getQPath().getName().getAsString(), data.getQPath().getIndex());
+         try
+         {
+            if (count.next())
+            {
+               return count.getInt(1);
+            }
+            else
+            {
+               return 0;
+            }
+         }
+         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();
@@ -2699,16 +2737,6 @@
       }
    };
 
-   protected ResultSet findLowestPropertyVersions() throws SQLException
-   {
-      if (findLowestPropertyVersions == null)
-      {
-         findLowestPropertyVersions = dbConnection.prepareStatement(FIND_LOWEST_PROPERTY_VERSIONS);
-      }
-
-      return findLowestPropertyVersions.executeQuery();
-   }
-
    protected abstract int addNodeRecord(NodeData data) throws SQLException;
 
    protected abstract int addPropertyRecord(PropertyData prop) throws SQLException;
@@ -2773,4 +2801,6 @@
 
    protected abstract ResultSet findValueByPropertyIdOrderNumber(String cid, int orderNumb) throws SQLException;
 
+   protected abstract ResultSet findMaxPropertyVersion(String parentId, String name, int index) throws SQLException;
+
 }

Modified: jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/statistics/StatisticsJDBCStorageConnection.java
===================================================================
--- jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/statistics/StatisticsJDBCStorageConnection.java	2012-03-06 07:08:30 UTC (rev 5808)
+++ jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/statistics/StatisticsJDBCStorageConnection.java	2012-03-06 08:54:13 UTC (rev 5809)
@@ -69,6 +69,12 @@
 
    /**
     * The description of the statistics corresponding to the method 
+    * <code>prepare()</code>
+    */
+   private static final String PREPARE_DESCR = "prepare";   
+
+   /**
+    * The description of the statistics corresponding to the method 
     * <code>rename(NodeData data)</code>
     */
    private static final String RENAME_NODE_DATA_DESCR = "renameNodeData";
@@ -237,6 +243,8 @@
       ALL_STATISTICS.put(RENAME_NODE_DATA_DESCR, new Statistics(GLOBAL_STATISTICS, RENAME_NODE_DATA_DESCR));
       // Rollback
       ALL_STATISTICS.put(ROLLBACK_DESCR, new Statistics(GLOBAL_STATISTICS, ROLLBACK_DESCR));
+      // Prepare
+      ALL_STATISTICS.put(PREPARE_DESCR, new Statistics(GLOBAL_STATISTICS, PREPARE_DESCR));
       // Others
       ALL_STATISTICS.put(IS_OPENED_DESCR, new Statistics(null, IS_OPENED_DESCR));
       ALL_STATISTICS.put(CLOSE_DESCR, new Statistics(null, CLOSE_DESCR));
@@ -625,6 +633,23 @@
    /**
     * {@inheritDoc}
     */
+   public void prepare() throws IllegalStateException, RepositoryException
+   {
+      Statistics s = ALL_STATISTICS.get(PREPARE_DESCR);
+      try
+      {
+         s.begin();
+         wcs.prepare();
+      }
+      finally
+      {
+         s.end();
+      }
+   }
+   
+   /**
+    * {@inheritDoc}
+    */
    public void rollback() throws IllegalStateException, RepositoryException
    {
       Statistics s = ALL_STATISTICS.get(ROLLBACK_DESCR);

Modified: jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/value/ValueOperation.java
===================================================================
--- jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/value/ValueOperation.java	2012-03-06 07:08:30 UTC (rev 5808)
+++ jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/value/ValueOperation.java	2012-03-06 08:54:13 UTC (rev 5809)
@@ -49,11 +49,26 @@
    void rollback() throws IOException;
 
    /**
-    * Commit Value content.
+    * Commit Value content (one phase).
     * 
     * @throws IOException
     *           if error occurs
     */
    void commit() throws IOException;
 
+   /**
+    * Prepare Value content.
+    * 
+    * @throws IOException
+    *           if error occurs
+    */
+   void prepare() throws IOException;
+   
+   /**
+    * Commit Value content (two phases).
+    * 
+    * @throws IOException
+    *           if error occurs
+    */
+   void twoPhaseCommit() throws IOException;
 }

Modified: jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/value/fs/FileIOChannel.java
===================================================================
--- jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/value/fs/FileIOChannel.java	2012-03-06 07:08:30 UTC (rev 5808)
+++ jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/value/fs/FileIOChannel.java	2012-03-06 08:54:13 UTC (rev 5809)
@@ -124,6 +124,15 @@
    /**
     * {@inheritDoc}
     */
+   public void prepare() throws IOException
+   {
+      for (ValueOperation vo : changes)
+         vo.prepare();
+   }
+   
+   /**
+    * {@inheritDoc}
+    */
    public void commit() throws IOException
    {
       try
@@ -140,6 +149,22 @@
    /**
     * {@inheritDoc}
     */
+   public void twoPhaseCommit() throws IOException
+   {
+      try
+      {
+         for (ValueOperation vo : changes)
+            vo.twoPhaseCommit();
+      }
+      finally
+      {
+         changes.clear();
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
    public void rollback() throws IOException
    {
       try

Modified: jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/value/fs/operations/CASableDeleteValues.java
===================================================================
--- jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/value/fs/operations/CASableDeleteValues.java	2012-03-06 07:08:30 UTC (rev 5808)
+++ jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/value/fs/operations/CASableDeleteValues.java	2012-03-06 08:54:13 UTC (rev 5809)
@@ -81,11 +81,11 @@
     * {@inheritDoc}
     */
    @Override
-   public void commit() throws IOException
+   public void prepare() throws IOException
    {
       try
       {
-         super.commit();
+         super.prepare();
       }
       finally
       {

Modified: jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/value/fs/operations/CASableWriteValue.java
===================================================================
--- jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/value/fs/operations/CASableWriteValue.java	2012-03-06 07:08:30 UTC (rev 5808)
+++ jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/value/fs/operations/CASableWriteValue.java	2012-03-06 08:54:13 UTC (rev 5809)
@@ -149,66 +149,71 @@
     * {@inheritDoc}
     */
    @Override
-   public void commit() throws IOException
+   public void prepare() throws IOException
    {
       if (fileLock != null)
+      {
+         // write VCAS record first
          try
          {
-            // write VCAS record first
-            try
+            vcas.addValue(propertyId, orderNumb, vcasHash);
+         }
+         catch (RecordAlreadyExistsException e)
+         {
+            if (tempFile != null && tempFile.exists() && !tempFile.delete())
             {
-               vcas.addValue(propertyId, orderNumb, vcasHash);
+                 LOG.warn("Can't delete CAS temp file. Added to file cleaner. " + tempFile.getAbsolutePath());
+                 cleaner.addFile(tempFile);
             }
-            catch (RecordAlreadyExistsException e)
-            {
-               if (tempFile != null && tempFile.exists() && !tempFile.delete())
-               {
-                  LOG.warn("Can't delete CAS temp file. Added to file cleaner. " + tempFile.getAbsolutePath());
-                  cleaner.addFile(tempFile);
-               }
-               throw new RecordAlreadyExistsException("Write error: " + e, e);
-            }
+            throw new RecordAlreadyExistsException("Write error: " + e, e);
+         }
 
-            if (!vcasFile.exists())
-            {
-               // it's new CAS Value, we have to move temp to vcas location
-               // use RENAME only, don't copy - as copy will means that destination already exists etc.
+         if (!vcasFile.exists())
+         {
+            // it's new CAS Value, we have to move temp to vcas location
+            // use RENAME only, don't copy - as copy will means that destination already exists etc.
 
-               // make sure parent dir exists
-               vcasFile.getParentFile().mkdirs();
-
-               // rename propetynamed file to hashnamed one
-               try
-               {
-                  DirectoryHelper.renameFile(tempFile, vcasFile);
-               }
-               catch (IOException e)
-               {
-                  throw new VCASException("File " + tempFile.getAbsolutePath() + " can't be renamed to VCAS-named "
-                     + vcasFile.getAbsolutePath(), e);
-               }
-            } // else - CASed Value already exists
-
-            if (!value.isByteArray() && value instanceof StreamPersistedValueData)
+            // make sure parent dir exists
+            vcasFile.getParentFile().mkdirs();
+            // rename propetynamed file to hashnamed one
+            try
             {
-               // set persisted file
-               ((StreamPersistedValueData)value).setPersistedFile(vcasFile);
+               DirectoryHelper.renameFile(tempFile, vcasFile);
             }
+            catch (IOException e)
+            {
+               throw new VCASException("File " + tempFile.getAbsolutePath() + " can't be renamed to VCAS-named "
+                  + vcasFile.getAbsolutePath(), e);
+            }
+         } // else - CASed Value already exists
 
-         }
-         finally
+         if (!value.isByteArray() && value instanceof StreamPersistedValueData)
          {
-            // remove temp file
-            tempFile.delete(); // should be ok without file cleaner
-
-            fileLock.unlock();
+            // set persisted file
+            ((StreamPersistedValueData)value).setPersistedFile(vcasFile);
          }
+      }
    }
 
    /**
     * {@inheritDoc}
     */
    @Override
+   public void twoPhaseCommit() throws IOException
+   {
+      if (fileLock != null)
+      {
+         // remove temp file
+         tempFile.delete(); // should be ok without file cleaner
+
+         fileLock.unlock();
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
    public void rollback() throws IOException
    {
       if (fileLock != null)

Modified: jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/value/fs/operations/DeleteValues.java
===================================================================
--- jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/value/fs/operations/DeleteValues.java	2012-03-06 07:08:30 UTC (rev 5808)
+++ jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/value/fs/operations/DeleteValues.java	2012-03-06 08:54:13 UTC (rev 5809)
@@ -19,10 +19,12 @@
 package org.exoplatform.services.jcr.impl.storage.value.fs.operations;
 
 import org.exoplatform.services.jcr.impl.storage.value.ValueDataResourceHolder;
+import org.exoplatform.services.jcr.impl.util.io.DirectoryHelper;
 import org.exoplatform.services.jcr.impl.util.io.FileCleaner;
 
 import java.io.File;
 import java.io.IOException;
+import java.util.concurrent.atomic.AtomicLong;
 
 /**
  * Created by The eXo Platform SAS.
@@ -35,6 +37,7 @@
  */
 public class DeleteValues extends ValueFileOperation
 {
+   private static final AtomicLong SEQUENCE = new AtomicLong();
 
    /**
     * Files to be deleted.
@@ -47,6 +50,11 @@
    private ValueFileLock[] locks;
 
    /**
+    * The backup files
+    */
+   protected File[] bckFiles;
+
+   /**
     * DeleteValues constructor.
     * 
     * @param files
@@ -83,24 +91,58 @@
    /**
     * {@inheritDoc}
     */
+   public void prepare() throws IOException
+   {
+      if (locks != null)
+      {
+         bckFiles = new File[files.length];
+         for (int i = 0,length = files.length; i < length; i++)
+         {
+            File file = files[i];
+            if (file.exists())
+            {
+               bckFiles[i] = new File(file.getAbsolutePath() + "." + System.currentTimeMillis() + "_" + SEQUENCE.incrementAndGet());
+               DirectoryHelper.renameFile(file, bckFiles[i]);
+            }           
+         }
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
    public void rollback() throws IOException
    {
       if (locks != null)
-         for (ValueFileLock fl : locks)
-            fl.unlock();
+         try
+         {
+            for (int i = 0,length = files.length; i < length; i++)
+            {
+               File f = bckFiles[i];
+               if (f != null)
+               {
+                  DirectoryHelper.renameFile(f, files[i]);
+               }
+            }
+         }
+         finally
+         {
+            for (ValueFileLock fl : locks)
+               fl.unlock();
+         }
    }
 
    /**
     * {@inheritDoc}
     */
-   public void commit() throws IOException
+   public void twoPhaseCommit() throws IOException
    {
       if (locks != null)
          try
          {
-            for (File f : files)
+            for (File f : bckFiles)
             {
-               if (!f.delete())
+               if (f != null && !f.delete())
                   // Possible place of error: FileNotFoundException when we delete/update existing
                   // Value and then add/update again.
                   // After the time the Cleaner will delete the file which is mapped to the Value.
@@ -110,9 +152,8 @@
          }
          finally
          {
-            if (locks != null)
-               for (ValueFileLock fl : locks)
-                  fl.unlock();
+            for (ValueFileLock fl : locks)
+               fl.unlock();
          }
    }
 }

Modified: jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/value/fs/operations/ValueFileOperation.java
===================================================================
--- jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/value/fs/operations/ValueFileOperation.java	2012-03-06 07:08:30 UTC (rev 5808)
+++ jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/value/fs/operations/ValueFileOperation.java	2012-03-06 08:54:13 UTC (rev 5809)
@@ -282,4 +282,19 @@
 
       performed = true;
    }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void commit() throws IOException
+   {
+      try
+      {
+         prepare();         
+      }
+      finally
+      {
+         twoPhaseCommit();         
+      }
+   }
 }

Modified: jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/value/fs/operations/WriteValue.java
===================================================================
--- jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/value/fs/operations/WriteValue.java	2012-03-06 07:08:30 UTC (rev 5808)
+++ jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/value/fs/operations/WriteValue.java	2012-03-06 08:54:13 UTC (rev 5809)
@@ -80,33 +80,46 @@
       fileLock.lock();
    }
 
-   /**
-    * {@inheritDoc}
-    */
-   public void rollback() throws IOException
+   public void prepare() throws IOException
    {
       if (fileLock != null)
-         fileLock.unlock();
+      {
+         // be sure the destination dir exists (case for Tree-style storage)
+         file.getParentFile().mkdirs();
+         // write value to the file
+         writeValue(file, value);
+      }
    }
 
    /**
     * {@inheritDoc}
     */
-   public void commit() throws IOException
+   public void rollback() throws IOException
    {
       if (fileLock != null)
+      {
          try
          {
-            // be sure the destination dir exists (case for Tree-style storage)
-            file.getParentFile().mkdirs();
-
-            // write value to the file
-            writeValue(file, value);
+            if (file.exists() && !file.delete())
+            {
+               cleaner.addFile(file);
+            }
          }
          finally
          {
             fileLock.unlock();
          }
+      }
    }
 
+   /**
+    * {@inheritDoc}
+    */
+   public void twoPhaseCommit() throws IOException
+   {
+      if (fileLock != null)
+      {
+         fileLock.unlock();
+      }
+   }
 }

Modified: jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/storage/WorkspaceStorageConnection.java
===================================================================
--- jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/storage/WorkspaceStorageConnection.java	2012-03-06 07:08:30 UTC (rev 5808)
+++ jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/storage/WorkspaceStorageConnection.java	2012-03-06 08:54:13 UTC (rev 5809)
@@ -41,7 +41,7 @@
  * should have "opened" state. The connection becomes "closed" (invalid for using) after calling
  * commit() or rollback() methods. In this case methods calling will cause an IllegalStateException
  * 
- * Connection object intended to be as "light" as possible i.e. connection creation SHOULD NOT be
+ * Connection object intends to be as "light" as possible i.e. connection creation SHOULD NOT be
  * expensive operation, so better NOT to open/close potentially EXPENSIVE resources using by
  * Connection (WorkspaceDataContainer should be responsible for that). The Connection IS NOT a
  * thread-safe object and normally SHOULD NOT be pooled/cached.
@@ -370,6 +370,16 @@
       IllegalStateException;
 
    /**
+    * Prepare the commit phase.
+    * 
+    * @throws IllegalStateException
+    *           if connection is already closed
+    * @throws RepositoryException
+    *           if some exception occurred
+    */
+   void prepare() throws IllegalStateException, RepositoryException;
+   
+   /**
     * Persist changes and closes connection. It can be database transaction commit for instance etc.
     * 
     * @throws IllegalStateException

Modified: jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/storage/value/ValueIOChannel.java
===================================================================
--- jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/storage/value/ValueIOChannel.java	2012-03-06 07:08:30 UTC (rev 5808)
+++ jcr/branches/1.15.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/storage/value/ValueIOChannel.java	2012-03-06 08:54:13 UTC (rev 5809)
@@ -102,14 +102,30 @@
    String getStorageId();
 
    /**
-    * Commit channel changes.
+    * Prepare channel changes.
     * 
     * @throws IOException
     *           if error occurs
     */
+   void prepare() throws IOException;
+   
+   /**
+    * Commit channel changes (one phase).
+    * 
+    * @throws IOException
+    *           if error occurs
+    */
    void commit() throws IOException;
 
    /**
+    * Commit channel changes (two phases).
+    * 
+    * @throws IOException
+    *           if error occurs
+    */
+   void twoPhaseCommit() throws IOException;
+
+   /**
     * Rollback channel changes.
     * 
     * @throws IOException

Modified: jcr/branches/1.15.x/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/BaseStandaloneTest.java
===================================================================
--- jcr/branches/1.15.x/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/BaseStandaloneTest.java	2012-03-06 07:08:30 UTC (rev 5808)
+++ jcr/branches/1.15.x/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/BaseStandaloneTest.java	2012-03-06 08:54:13 UTC (rev 5809)
@@ -747,6 +747,11 @@
          throw new UnsupportedOperationException();
       }
 
+      public void prepare() throws IllegalStateException, RepositoryException
+      {
+         throw new UnsupportedOperationException("TestWorkspaceStorageConnection: operation is unsupported.");
+      }
+
    }
 
 }

Modified: jcr/branches/1.15.x/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/TestCacheableWorkspaceDataManager.java
===================================================================
--- jcr/branches/1.15.x/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/TestCacheableWorkspaceDataManager.java	2012-03-06 07:08:30 UTC (rev 5808)
+++ jcr/branches/1.15.x/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/TestCacheableWorkspaceDataManager.java	2012-03-06 08:54:13 UTC (rev 5809)
@@ -473,6 +473,10 @@
       {
       }
 
+      public void prepare() throws IllegalStateException, RepositoryException
+      {
+      }
+
       public void delete(NodeData data) throws RepositoryException, UnsupportedOperationException,
          InvalidItemStateException, IllegalStateException
       {

Modified: jcr/branches/1.15.x/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/TestWorkspaceStorageCacheInClusterMode.java
===================================================================
--- jcr/branches/1.15.x/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/TestWorkspaceStorageCacheInClusterMode.java	2012-03-06 07:08:30 UTC (rev 5808)
+++ jcr/branches/1.15.x/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/TestWorkspaceStorageCacheInClusterMode.java	2012-03-06 08:54:13 UTC (rev 5809)
@@ -651,6 +651,10 @@
       {
       }
 
+      public void prepare() throws IllegalStateException, RepositoryException
+      {
+      }
+
       public void commit() throws IllegalStateException, RepositoryException
       {
          if (wait.get() != null && wait.get())

Modified: jcr/branches/1.15.x/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/cache/jbosscache/TestJBossCacheWorkspaceStorageCache.java
===================================================================
--- jcr/branches/1.15.x/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/cache/jbosscache/TestJBossCacheWorkspaceStorageCache.java	2012-03-06 07:08:30 UTC (rev 5808)
+++ jcr/branches/1.15.x/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/cache/jbosscache/TestJBossCacheWorkspaceStorageCache.java	2012-03-06 08:54:13 UTC (rev 5809)
@@ -291,6 +291,10 @@
       {
       }
 
+      public void prepare() throws IllegalStateException, RepositoryException
+      {
+      }
+
       public void update(NodeData data) throws RepositoryException, UnsupportedOperationException,
          InvalidItemStateException, IllegalStateException
       {

Modified: jcr/branches/1.15.x/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/faq/jcr-faq.xml
===================================================================
--- jcr/branches/1.15.x/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/faq/jcr-faq.xml	2012-03-06 07:08:30 UTC (rev 5808)
+++ jcr/branches/1.15.x/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/faq/jcr-faq.xml	2012-03-06 08:54:13 UTC (rev 5809)
@@ -307,8 +307,9 @@
      &lt;properties&gt;
         &lt;property name="jbosscache-configuration" value="test-jbosscache-data.xml" /&gt;
         &lt;property name="jgroups-configuration" value="udp-mux.xml" /&gt;
-        &lt;property name="jgroups-multiplexer-stack" value="true" /&gt;
-        &lt;property name="jbosscache-cluster-name" value="JCR-cluster-db1-ws" /&gt;
+        &lt;property name="jgroups-multiplexer-stack" value="false" /&gt;
+        &lt;property name="jbosscache-cluster-name" value="JCR-cluster-data" /&gt;
+        &lt;property name="jbosscache-shareable" value="true"/&gt;
      &lt;/properties&gt;
 &lt;/cache&gt;</programlisting>
 
@@ -325,8 +326,9 @@
               </listitem>
 
               <listitem>
-                <para>"jgroups-multiplexer-stack" just simply "true". Strongly
-                recommended;</para>
+                <para>"jgroups-multiplexer-stack" set to "false" with the
+                jgroups configuration with the shared transport enabled in
+                order to use the shared transport.</para>
               </listitem>
 
               <listitem>
@@ -335,6 +337,11 @@
                 component. I.e.:
                 &lt;repository_name&gt;-&lt;ws_name&gt;-&lt;component(cache\|lock\|index)&gt;</para>
               </listitem>
+
+              <listitem>
+                <para>"jbosscache-shareable" set "true" in order to share the
+                same JBoss Cache instance between several workspaces.</para>
+              </listitem>
             </itemizedlist>
           </listitem>
         </itemizedlist>
@@ -356,8 +363,9 @@
 
                 <programlisting language="xml">&lt;property name="jbosscache-configuration" value="test-jbosscache-indexer.xml" /&gt;
 &lt;property name="jgroups-configuration" value="udp-mux.xml" /&gt;
-&lt;property name="jgroups-multiplexer-stack" value="true" /&gt;
-&lt;property name="jbosscache-cluster-name" value="JCR-cluster-indexer-db1-ws" /&gt;
+&lt;property name="jgroups-multiplexer-stack" value="false" /&gt;
+&lt;property name="jbosscache-cluster-name" value="JCR-cluster-indexer" /&gt;
+&lt;property name="jbosscache-shareable" value="true"/&gt;
 &lt;property name="max-volatile-time" value="60" /&gt;</programlisting>
               </listitem>
             </itemizedlist>
@@ -384,16 +392,17 @@
       &lt;property name="time-out" value="15m" /&gt;
       &lt;property name="jbosscache-configuration" value="test-jbosscache-lock.xml" /&gt;
       &lt;property name="jgroups-configuration" value="udp-mux.xml" /&gt;
-      &lt;property name="jgroups-multiplexer-stack" value="true" /&gt;
-      &lt;property name="jbosscache-cluster-name" value="JCR-cluster-locks-db1-ws" /&gt;
-      &lt;property name="jbosscache-cl-cache.jdbc.table.name" value="jcrlocks_db1_ws" /&gt;
+      &lt;property name="jgroups-multiplexer-stack" value="false" /&gt;
+      &lt;property name="jbosscache-cluster-name" value="JCR-cluster-locks" /&gt;
+      &lt;property name="jbosscache-cl-cache.jdbc.table.name" value="jcrlocks" /&gt;
       &lt;property name="jbosscache-cl-cache.jdbc.table.create" value="true" /&gt;
       &lt;property name="jbosscache-cl-cache.jdbc.table.drop" value="false" /&gt;
-      &lt;property name="jbosscache-cl-cache.jdbc.table.primarykey" value="jcrlocks_db1_ws_pk" /&gt;
+      &lt;property name="jbosscache-cl-cache.jdbc.table.primarykey" value="jcrlocks_pk" /&gt;
       &lt;property name="jbosscache-cl-cache.jdbc.fqn.column" value="fqn" /&gt;
       &lt;property name="jbosscache-cl-cache.jdbc.node.column" value="node" /&gt;
       &lt;property name="jbosscache-cl-cache.jdbc.parent.column" value="parent" /&gt;
       &lt;property name="jbosscache-cl-cache.jdbc.datasource" value="jdbcjcr" /&gt;
+      &lt;property name="jbosscache-shareable" value="true"/&gt;
    &lt;/properties&gt;
 &lt;/lock-manager&gt;
 

Modified: jcr/branches/1.15.x/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/cluster-config.xml
===================================================================
--- jcr/branches/1.15.x/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/cluster-config.xml	2012-03-06 07:08:30 UTC (rev 5808)
+++ jcr/branches/1.15.x/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/cluster-config.xml	2012-03-06 08:54:13 UTC (rev 5809)
@@ -224,8 +224,9 @@
    &lt;properties&gt;
       &lt;property name="jbosscache-configuration" value="jar:/conf/portal/test-jbosscache-data.xml" /&gt;     &lt;!--    path to JBoss Cache configuration for data storage --&gt;
       &lt;property name="jgroups-configuration" value="jar:/conf/portal/udp-mux.xml" /&gt;                     &lt;!--    path to JGroups configuration --&gt;
-      &lt;property name="jbosscache-cluster-name" value="JCR_Cluster_cache_production" /&gt;                   &lt;!--    JBoss Cache data storage cluster name --&gt;
-      &lt;property name="jgroups-multiplexer-stack" value="true" /&gt;
+      &lt;property name="jbosscache-cluster-name" value="JCR_Cluster_cache" /&gt;                              &lt;!--    JBoss Cache data storage cluster name --&gt;
+      &lt;property name="jgroups-multiplexer-stack" value="false" /&gt;
+      &lt;property name="jbosscache-shareable" value="true" /&gt;
    &lt;/properties&gt;
 &lt;/cache&gt; </programlisting>
         </listitem>
@@ -239,8 +240,9 @@
       &lt;property name="index-dir" value="/mnt/tornado/temp/jcrlucenedb/production" /&gt;                       &lt;!--    path within NFS where ValueStorage will hold it's data --&gt;
       &lt;property name="jbosscache-configuration" value="jar:/conf/portal/test-jbosscache-indexer.xml" /&gt;    &lt;!--    path to JBoss Cache configuration for indexer --&gt;
       &lt;property name="jgroups-configuration" value="jar:/conf/portal/udp-mux.xml" /&gt;                       &lt;!--    path to JGroups configuration --&gt;
-      &lt;property name="jbosscache-cluster-name" value="JCR_Cluster_indexer_production" /&gt;                   &lt;!--    JBoss Cache indexer cluster name --&gt;
-      &lt;property name="jgroups-multiplexer-stack" value="true" /&gt;
+      &lt;property name="jbosscache-cluster-name" value="JCR_Cluster_indexer" /&gt;                              &lt;!--    JBoss Cache indexer cluster name --&gt;
+      &lt;property name="jgroups-multiplexer-stack" value="false" /&gt;
+      &lt;property name="jbosscache-shareable" value="true" /&gt;
    &lt;/properties&gt;
 &lt;/query-handler&gt; </programlisting>
         </listitem>
@@ -253,17 +255,17 @@
       &lt;property name="time-out" value="15m" /&gt;
       &lt;property name="jbosscache-configuration" value="jar:/conf/portal/test-jbosscache-lock.xml" /&gt;       &lt;!--    path to JBoss Cache configuration for lock manager --&gt;
       &lt;property name="jgroups-configuration" value="jar:/conf/portal/udp-mux.xml" /&gt;                       &lt;!--    path to JGroups configuration --&gt;
-      &lt;property name="jgroups-multiplexer-stack" value="true" /&gt;
-      &lt;property name="jbosscache-cluster-name" value="JCR_Cluster_lock_production" /&gt;                      &lt;!--    JBoss Cache locks cluster name --&gt;
-                     
-      &lt;property name="jbosscache-cl-cache.jdbc.table.name" value="jcrlocks_production"/&gt;                   &lt;!--    the name of the DB table where lock's data will be stored --&gt;
+      &lt;property name="jbosscache-cluster-name" value="JCR_Cluster_locks" /&gt;                                &lt;!--    JBoss Cache locks cluster name --&gt;                    
+      &lt;property name="jbosscache-cl-cache.jdbc.table.name" value="jcrlocks"/&gt;                              &lt;!--    the name of the DB table where lock's data will be stored --&gt;
       &lt;property name="jbosscache-cl-cache.jdbc.table.create" value="true"/&gt;
       &lt;property name="jbosscache-cl-cache.jdbc.table.drop" value="false"/&gt;
-      &lt;property name="jbosscache-cl-cache.jdbc.table.primarykey" value="jcrlocks_production_pk"/&gt;
+      &lt;property name="jbosscache-cl-cache.jdbc.table.primarykey" value="jcrlocks_pk"/&gt;
       &lt;property name="jbosscache-cl-cache.jdbc.fqn.column" value="fqn"/&gt;
       &lt;property name="jbosscache-cl-cache.jdbc.node.column" value="node"/&gt;
       &lt;property name="jbosscache-cl-cache.jdbc.parent.column" value="parent"/&gt;
       &lt;property name="jbosscache-cl-cache.jdbc.datasource" value="jdbcjcr"/&gt;
+      &lt;property name="jgroups-multiplexer-stack" value="false" /&gt;
+      &lt;property name="jbosscache-shareable" value="true" /&gt;
    &lt;/properties&gt;
 &lt;/lock-manager&gt;</programlisting>
         </listitem>

Modified: jcr/branches/1.15.x/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/jbosscache-configuration-templates.xml
===================================================================
--- jcr/branches/1.15.x/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/jbosscache-configuration-templates.xml	2012-03-06 07:08:30 UTC (rev 5808)
+++ jcr/branches/1.15.x/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/jbosscache-configuration-templates.xml	2012-03-06 08:54:13 UTC (rev 5809)
@@ -67,6 +67,15 @@
 
     <programlisting language="xml">&lt;property name="jgroups-configuration" value="jar:/conf/portal/udp-mux.xml" /&gt;
 &lt;property name="jgroups-multiplexer-stack" value="true" /&gt;</programlisting>
+
+    <para>I<emphasis>t is now highly recommended to use the shared transport
+    instead of the multiplexer</emphasis>, to do so simply disable the
+    multiplexer stack in the configuration of each component then set the
+    property <emphasis>singleton_name</emphasis> of your JGroups configuration
+    to a unique name.</para>
+
+    <programlisting language="xml">&lt;property name="jgroups-configuration" value="jar:/conf/portal/udp-mux.xml" /&gt;
+&lt;property name="jgroups-multiplexer-stack" value="false" /&gt;</programlisting>
   </section>
 
   <section>
@@ -114,22 +123,21 @@
       <programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
 &lt;jbosscache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:jboss:jbosscache-core:config:3.1"&gt;
 
-   &lt;locking useLockStriping="false" concurrencyLevel="50000" lockParentForChildInsertRemove="false"
+   &lt;locking useLockStriping="false" concurrencyLevel="500" lockParentForChildInsertRemove="false"
       lockAcquisitionTimeout="20000" /&gt;
 
    &lt;clustering mode="replication" clusterName="${jbosscache-cluster-name}"&gt;
       &lt;stateRetrieval timeout="20000" fetchInMemoryState="false" /&gt;
-      &lt;jgroupsConfig multiplexerStack="jcr.stack" /&gt;
       &lt;sync /&gt;
    &lt;/clustering&gt;
 
    &lt;!-- Eviction configuration --&gt;
    &lt;eviction wakeUpInterval="5000"&gt;
-      &lt;default algorithmClass="org.jboss.cache.eviction.LRUAlgorithm"
+      &lt;default algorithmClass="org.jboss.cache.eviction.ExpirationAlgorithm"
          actionPolicyClass="org.exoplatform.services.jcr.impl.dataflow.persistent.jbosscache.ParentNodeEvictionActionPolicy"
          eventQueueSize="1000000"&gt;
          &lt;property name="maxNodes" value="1000000" /&gt;
-         &lt;property name="timeToLive" value="120000" /&gt;
+         &lt;property name="warnNoExpirationKey" value="false" /&gt;
       &lt;/default&gt;
    &lt;/eviction&gt;
 &lt;/jbosscache&gt;</programlisting>
@@ -163,18 +171,17 @@
       <programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
 &lt;jbosscache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:jboss:jbosscache-core:config:3.1"&gt;
 
-   &lt;locking useLockStriping="false" concurrencyLevel="50000" lockParentForChildInsertRemove="false"
+   &lt;locking useLockStriping="false" concurrencyLevel="500" lockParentForChildInsertRemove="false"
       lockAcquisitionTimeout="20000" /&gt;
    &lt;clustering mode="replication" clusterName="${jbosscache-cluster-name}"&gt;
       &lt;stateRetrieval timeout="20000" fetchInMemoryState="false" /&gt;
-      &lt;jgroupsConfig multiplexerStack="jcr.stack" /&gt;
       &lt;sync /&gt;
    &lt;/clustering&gt;
    &lt;loaders passivation="false" shared="true"&gt;
       &lt;preload&gt;
          &lt;node fqn="/" /&gt;
       &lt;/preload&gt;
-      &lt;loader class="org.jboss.cache.loader.JDBCCacheLoader" async="false" fetchPersistentState="false"
+      &lt;loader class="org.exoplatform.services.jcr.impl.core.lock.jbosscache.JDBCCacheLoader" async="false" fetchPersistentState="false"
          ignoreModifications="false" purgeOnStartup="false"&gt;
          &lt;properties&gt;
             cache.jdbc.table.name=${jbosscache-cl-cache.jdbc.table.name}
@@ -192,6 +199,13 @@
    &lt;/loaders&gt;
 &lt;/jbosscache&gt;</programlisting>
 
+      <note>
+        <para>To prevent any consistency issue regarding the lock data please
+        ensure that your cache loader is
+        <emphasis>org.exoplatform.services.jcr.impl.core.lock.jbosscache.JDBCCacheLoader</emphasis>
+        and that your database engine is transactional.</para>
+      </note>
+
       <table>
         <title>Template variables</title>
 
@@ -258,20 +272,12 @@
 
       <programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
 &lt;jbosscache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:jboss:jbosscache-core:config:3.1"&gt;
-   &lt;locking useLockStriping="false" concurrencyLevel="50000" lockParentForChildInsertRemove="false"
+   &lt;locking useLockStriping="false" concurrencyLevel="500" lockParentForChildInsertRemove="false"
       lockAcquisitionTimeout="20000" /&gt;
    &lt;clustering mode="replication" clusterName="${jbosscache-cluster-name}"&gt;
       &lt;stateRetrieval timeout="20000" fetchInMemoryState="false" /&gt;
-      &lt;jgroupsConfig multiplexerStack="jcr.stack" /&gt;
       &lt;sync /&gt;
    &lt;/clustering&gt;
-   &lt;!-- Eviction configuration --&gt;
-   &lt;eviction wakeUpInterval="5000"&gt;
-      &lt;default algorithmClass="org.jboss.cache.eviction.FIFOAlgorithm" eventQueueSize="1000000"&gt;
-         &lt;property name="maxNodes" value="10000" /&gt;
-         &lt;property name="minTimeToLive" value="60000" /&gt;
-      &lt;/default&gt;
-   &lt;/eviction&gt;
 &lt;/jbosscache&gt;</programlisting>
 
       <table>

Modified: jcr/branches/1.15.x/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/lock-manager-config.xml
===================================================================
--- jcr/branches/1.15.x/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/lock-manager-config.xml	2012-03-06 07:08:30 UTC (rev 5808)
+++ jcr/branches/1.15.x/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/lock-manager-config.xml	2012-03-06 08:54:13 UTC (rev 5809)
@@ -25,10 +25,16 @@
         <para><classname>org.exoplatform.services.jcr.impl.core.lock.jbosscache.CacheableLockManagerImpl</classname>;</para>
       </listitem>
     </itemizedlist>
+  </section>
 
-    <para>In this article, we will mostly mention about
-    CacheableLockManagerImpl.</para>
+  <section>
+    <title>CacheableLockManagerImpl</title>
 
+    <para>CacheableLockManagerImpl stores Lock objects in JBoss-cache, so
+    Locks are replicable and affect on cluster, not only a single node. Also,
+    JBoss-cache has JDBCCacheLoader, so Locks will be stored to the
+    database.</para>
+
     <para>You can enable LockManager by adding lock-manager-configuration to
     workspace-configuration.</para>
 
@@ -44,26 +50,11 @@
    &lt;/lock-manager&gt;               
    ...
 &lt;/workspace&gt;</programlisting>
-  </section>
 
-  <section>
-    <title>CacheableLockManagerImpl</title>
+    <para>Wher <emphasis>time-out</emphasis> parameter represents interval to
+    remove Expired Locks. LockRemover separates threads, that periodically ask
+    LockManager to remove Locks that live so long.</para>
 
-    <para>CacheableLockManagerImpl stores Lock objects in JBoss-cache, so
-    Locks are replicable and affect on cluster, not only a single node. Also,
-    JBoss-cache has JDBCCacheLoader, so Locks will be stored to the
-    database.</para>
-
-    <para>It supports to remove Expired Locks. LockRemover separates threads,
-    that periodically ask LockManager to remove Locks that live so long. So,
-    the timeout for LockRemover may be set as follows, the default value is
-    30m.</para>
-
-    <programlisting language="xml">&lt;properties&gt;
-   &lt;property name="time-out" value="10m" /&gt;
-   ...
-&lt;/properties&gt;</programlisting>
-
     <section>
       <title>Configuration</title>
 
@@ -77,12 +68,11 @@
       <programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
 &lt;jbosscache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:jboss:jbosscache-core:config:3.1"&gt;
 
-   &lt;locking useLockStriping="false" concurrencyLevel="50000" lockParentForChildInsertRemove="false"
+   &lt;locking useLockStriping="false" concurrencyLevel="500" lockParentForChildInsertRemove="false"
       lockAcquisitionTimeout="20000" /&gt;
 
    &lt;clustering mode="replication" clusterName="${jbosscache-cluster-name}"&gt;
       &lt;stateRetrieval timeout="20000" fetchInMemoryState="false" /&gt;
-      &lt;jgroupsConfig multiplexerStack="jcr.stack" /&gt;
       &lt;sync /&gt;
    &lt;/clustering&gt;
 
@@ -95,7 +85,7 @@
       For another cache-loader class you should use another template with
       cache-loader specific parameters
       -&gt;
-      &lt;loader class="org.jboss.cache.loader.JDBCCacheLoader" async="false" fetchPersistentState="false"
+      &lt;loader class="org.exoplatform.services.jcr.impl.core.lock.jbosscache.JDBCCacheLoader" async="false" fetchPersistentState="false"
          ignoreModifications="false" purgeOnStartup="false"&gt;
          &lt;properties&gt;
             cache.jdbc.table.name=${jbosscache-cl-cache.jdbc.table.name}
@@ -113,6 +103,13 @@
    &lt;/loaders&gt;
 &lt;/jbosscache&gt;</programlisting>
 
+      <note>
+        <para>To prevent any consistency issue regarding the lock data +
+        please ensure that your cache loader is
+        <emphasis>org.exoplatform.services.jcr.impl.core.lock.jbosscache.JDBCCacheLoader</emphasis>
+        and that your database engine is transactional.</para>
+      </note>
+
       <para>As you see, all configurable parameters are filled by templates
       and will be replaced by LockManagers configuration parameters:</para>
 
@@ -143,9 +140,8 @@
             and <parameter>jbosscache-cl-cache.jdbc.node.type</parameter> is
             the same as cache.jdbc.fqn.type and cache.jdbc.node.type in
             JBoss-Cache configuration. You can set those data types according
-            to database type (See <link endterm="datatypes.title"
-            linkend="datatypes"></link>) or set it as AUTO (or do not set at
-            all) and data type will be detected automatically.</para>
+            to your database type or set it as AUTO (or do not set at all) and
+            data type will be detected automatically.</para>
           </listitem>
 
           <listitem>
@@ -157,41 +153,73 @@
           </listitem>
         </itemizedlist></para>
 
-      <para><filename>our-udp-mux.xml</filename></para>
+      <para><filename>our udp-mux.xml</filename></para>
 
-      <programlisting language="xml">&lt;protocol_stacks&gt;
-   &lt;stack name="jcr.stack"&gt;
-      &lt;config&gt;
-         &lt;UDP mcast_addr="228.10.10.10" mcast_port="45588" tos="8" ucast_recv_buf_size="20000000"
-            ucast_send_buf_size="640000" mcast_recv_buf_size="25000000" mcast_send_buf_size="640000" loopback="false"
-            discard_incompatible_packets="true" max_bundle_size="64000" max_bundle_timeout="30"
-            use_incoming_packet_handler="true" ip_ttl="2" enable_bundling="true" enable_diagnostics="true"
-            thread_naming_pattern="cl" use_concurrent_stack="true" thread_pool.enabled="true" thread_pool.min_threads="2"
-            thread_pool.max_threads="8" thread_pool.keep_alive_time="5000" thread_pool.queue_enabled="true"
-            thread_pool.queue_max_size="1000" thread_pool.rejection_policy="discard" oob_thread_pool.enabled="true"
-            oob_thread_pool.min_threads="1" oob_thread_pool.max_threads="8" oob_thread_pool.keep_alive_time="5000"
-            oob_thread_pool.queue_enabled="false" oob_thread_pool.queue_max_size="100" oob_thread_pool.rejection_policy="Run" /&gt;
+      <programlisting language="xml">&lt;config&gt;
+    &lt;UDP
+         singleton_name="JCR-cluster" 
+         mcast_addr="${jgroups.udp.mcast_addr:228.10.10.10}"
+         mcast_port="${jgroups.udp.mcast_port:45588}"
+         tos="8" 
+         ucast_recv_buf_size="20000000"
+         ucast_send_buf_size="640000" 
+         mcast_recv_buf_size="25000000" 
+         mcast_send_buf_size="640000" 
+         loopback="false"
+         discard_incompatible_packets="true" 
+         max_bundle_size="64000" 
+         max_bundle_timeout="30"
+         use_incoming_packet_handler="true" 
+         ip_ttl="${jgroups.udp.ip_ttl:2}"
+         enable_bundling="false" 
+         enable_diagnostics="true"
+         thread_naming_pattern="cl" 
 
-         &lt;PING timeout="2000" num_initial_members="3" /&gt;
-         &lt;MERGE2 max_interval="30000" min_interval="10000" /&gt;
-         &lt;FD_SOCK /&gt;
-         &lt;FD timeout="10000" max_tries="5" shun="true" /&gt;
-         &lt;VERIFY_SUSPECT timeout="1500" /&gt;
-         &lt;BARRIER /&gt;
-         &lt;pbcast.NAKACK use_stats_for_retransmission="false" exponential_backoff="150" use_mcast_xmit="true"
-            gc_lag="0" retransmit_timeout="50,300,600,1200" discard_delivered_msgs="true" /&gt;
-         &lt;UNICAST timeout="300,600,1200" /&gt;
-         &lt;pbcast.STABLE stability_delay="1000" desired_avg_gossip="50000" max_bytes="1000000" /&gt;
-         &lt;VIEW_SYNC avg_send_interval="60000" /&gt;
-         &lt;pbcast.GMS print_local_addr="true" join_timeout="3000" shun="false" view_bundling="true" /&gt;
-         &lt;FC max_credits="500000" min_threshold="0.20" /&gt;
-         &lt;FRAG2 frag_size="60000" /&gt;
-         &lt;!--pbcast.STREAMING_STATE_TRANSFER /--&gt;
-         &lt;pbcast.STATE_TRANSFER /&gt;
-         &lt;!-- pbcast.FLUSH  /--&gt;
-      &lt;/config&gt;
-   &lt;/stack&gt;
-&lt;/protocol_stacks&gt; </programlisting>
+         use_concurrent_stack="true" 
+
+         thread_pool.enabled="true" 
+         thread_pool.min_threads="2"
+         thread_pool.max_threads="8" 
+         thread_pool.keep_alive_time="5000" 
+         thread_pool.queue_enabled="true"
+         thread_pool.queue_max_size="1000"
+         thread_pool.rejection_policy="discard"
+
+         oob_thread_pool.enabled="true"
+         oob_thread_pool.min_threads="1"
+         oob_thread_pool.max_threads="8"
+         oob_thread_pool.keep_alive_time="5000"
+         oob_thread_pool.queue_enabled="false" 
+         oob_thread_pool.queue_max_size="100" 
+         oob_thread_pool.rejection_policy="Run" /&gt;
+
+    &lt;PING timeout="2000"
+            num_initial_members="3"/&gt;
+    &lt;MERGE2 max_interval="30000"
+            min_interval="10000"/&gt;
+   &lt;FD_SOCK /&gt;
+   &lt;FD timeout="10000" max_tries="5" shun="true" /&gt;
+   &lt;VERIFY_SUSPECT timeout="1500" /&gt;
+   &lt;BARRIER /&gt;
+    &lt;pbcast.NAKACK use_stats_for_retransmission="false"
+                   exponential_backoff="150"
+                   use_mcast_xmit="true" gc_lag="0"
+                   retransmit_timeout="50,300,600,1200"
+                   discard_delivered_msgs="true"/&gt;
+   &lt;UNICAST timeout="300,600,1200" /&gt;
+    &lt;pbcast.STABLE stability_delay="1000" desired_avg_gossip="50000"
+                   max_bytes="1000000"/&gt;
+   &lt;VIEW_SYNC avg_send_interval="60000" /&gt;
+    &lt;pbcast.GMS print_local_addr="true" join_timeout="3000"
+                shun="false"
+                view_bundling="true"/&gt;
+    &lt;FC max_credits="500000"
+                    min_threshold="0.20"/&gt;
+   &lt;FRAG2 frag_size="60000" /&gt;
+   &lt;!--pbcast.STREAMING_STATE_TRANSFER /--&gt;
+   &lt;pbcast.STATE_TRANSFER /&gt;
+   &lt;pbcast.FLUSH /&gt;
+&lt;/config&gt;</programlisting>
     </section>
 
     <section id="datatypes">

Modified: jcr/branches/1.15.x/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/query-handler-config.xml
===================================================================
--- jcr/branches/1.15.x/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/query-handler-config.xml	2012-03-06 07:08:30 UTC (rev 5808)
+++ jcr/branches/1.15.x/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/query-handler-config.xml	2012-03-06 08:54:13 UTC (rev 5809)
@@ -282,12 +282,13 @@
             value="org.exoplatform.services.jcr.impl.core.query.jbosscache.JBossCacheIndexChangesFilter" /&gt;
          &lt;property name="jbosscache-configuration" value="jbosscache-indexer.xml" /&gt;
          &lt;property name="jgroups-configuration" value="udp-mux.xml" /&gt;
-         &lt;property name="jgroups-multiplexer-stack" value="true" /&gt;
-         &lt;property name="jbosscache-cluster-name" value="JCR-cluster-indexer-ws" /&gt;
+         &lt;property name="jgroups-multiplexer-stack" value="false" /&gt;
+         &lt;property name="jbosscache-cluster-name" value="JCR-cluster-indexer" /&gt;
          &lt;property name="max-volatile-time" value="60" /&gt;
          &lt;property name="rdbms-reindexing" value="true" /&gt;
          &lt;property name="reindexing-page-size" value="1000" /&gt;
          &lt;property name="index-recovery-mode" value="from-coordinator" /&gt;
+         &lt;property name="jbosscache-shareable" value="true" /&gt;
       &lt;/properties&gt;
    &lt;/query-handler&gt;
 &lt;/workspace&gt;</programlisting>
@@ -306,12 +307,13 @@
             value="org.exoplatform.services.jcr.impl.core.query.jbosscache.LocalIndexChangesFilter" /&gt;
          &lt;property name="jbosscache-configuration" value="jbosscache-indexer.xml" /&gt;
          &lt;property name="jgroups-configuration" value="udp-mux.xml" /&gt;
-         &lt;property name="jgroups-multiplexer-stack" value="true" /&gt;
-         &lt;property name="jbosscache-cluster-name" value="JCR-cluster-indexer-ws" /&gt;
+         &lt;property name="jgroups-multiplexer-stack" value="false" /&gt;
+         &lt;property name="jbosscache-cluster-name" value="JCR-cluster-indexer" /&gt;
          &lt;property name="max-volatile-time" value="60" /&gt;
          &lt;property name="rdbms-reindexing" value="true" /&gt;
          &lt;property name="reindexing-page-size" value="1000" /&gt;
          &lt;property name="index-recovery-mode" value="from-coordinator" /&gt;
+         &lt;property name="jbosscache-shareable" value="true" /&gt;
       &lt;/properties&gt;
    &lt;/query-handler&gt;
 &lt;/workspace&gt;
@@ -411,17 +413,8 @@
 
    &lt;clustering mode="replication" clusterName="${jbosscache-cluster-name}"&gt;
       &lt;stateRetrieval timeout="20000" fetchInMemoryState="false" /&gt;
-      &lt;jgroupsConfig multiplexerStack="jcr.stack" /&gt;
       &lt;sync /&gt;
    &lt;/clustering&gt;
-   &lt;!-- Eviction configuration --&gt;
-   &lt;eviction wakeUpInterval="5000"&gt;
-      &lt;default algorithmClass="org.jboss.cache.eviction.FIFOAlgorithm" eventQueueSize="1000000"&gt;
-         &lt;property name="maxNodes" value="10000" /&gt;
-         &lt;property name="minTimeToLive" value="60000" /&gt;
-      &lt;/default&gt;
-   &lt;/eviction&gt;
-
 &lt;/jbosscache&gt;</programlisting>
 
       <para>See more about template configurations <link



More information about the exo-jcr-commits mailing list