Index: exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SearchIndex.java
===================================================================
--- exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SearchIndex.java	(revision 5970)
+++ exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SearchIndex.java	(working copy)
@@ -81,8 +81,20 @@
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.security.PrivilegedAction;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
 
 import javax.jcr.RepositoryException;
 import javax.jcr.query.InvalidQueryException;
@@ -202,7 +214,7 @@
     * Default name of the error log file
     */
    private static final String ERROR_LOG = "error.log";
-   
+
    /**
     * The actual index
     */
@@ -464,12 +476,12 @@
     * Indicates if this <code>SearchIndex</code> is closed and cannot be used
     * anymore.
     */
-   private boolean closed = false;
+   private final AtomicBoolean closed = new AtomicBoolean(false);
 
    /**
     * Allows or denies queries while index is offline.
     */
-   private boolean allowQuery = true;
+   private final AtomicBoolean allowQuery = new AtomicBoolean(true);
 
    /**
     * Text extractor for extracting text content of binary properties.
@@ -516,12 +528,12 @@
    /**
     * Waiting query execution until resume. 
     */
-   protected CountDownLatch latcher = null;
+   protected final AtomicReference<CountDownLatch> latcher = new AtomicReference<CountDownLatch>();
 
    /**
     * Indicates if component suspended or not.
     */
-   protected boolean isSuspended = false;
+   protected final AtomicBoolean isSuspended = new AtomicBoolean(false);
 
    protected final Set<String> recoveryFilterClasses;
 
@@ -1233,11 +1245,21 @@
 
    /**
     * Closes this <code>QueryHandler</code> and frees resources attached to
-    * this handler.
+    * this handler. Also resume waiting threads.
     */
    public void close()
    {
-      if (!closed)
+      closeAndKeepWaitingThreads();
+      resumeWaitingThreads();
+   }
+
+   /**
+    * Closes this <code>QueryHandler</code> and frees resources attached to
+    * this handler.
+    */
+   public void closeAndKeepWaitingThreads()
+   {
+      if (!closed.get())
       {
          // cleanup resources obtained by filters
          if (recoveryFilters != null)
@@ -1268,7 +1290,7 @@
          errorLog.close();
          index.close();
          getContext().destroy();
-         closed = true;
+         closed.set(true);
          log.info("Index closed: " + path);
       }
    }
@@ -1546,7 +1568,7 @@
    protected IndexReader getIndexReader(boolean includeSystemIndex) throws IOException
    {
       // deny query execution if index in offline mode and allowQuery is false
-      if (!index.isOnline() && !allowQuery)
+      if (!index.isOnline() && !allowQuery.get())
       {
          throw new IndexOfflineIOException("Index is offline");
       }
@@ -3202,7 +3224,7 @@
     */
    private void checkOpen() throws IOException
    {
-      if (closed)
+      if (closed.get())
       {
          throw new IOException("query handler closed and cannot be used anymore.");
       }
@@ -3358,11 +3380,11 @@
       checkOpen();
       if (isOnline)
       {
-         this.allowQuery = true;
+         this.allowQuery.set(true);
       }
       else
       {
-         this.allowQuery = allowQuery;
+         this.allowQuery.set(allowQuery);
       }
       index.setOnline(isOnline, dropStaleIndexes);
    }
@@ -3380,10 +3402,10 @@
     */
    public void suspend() throws SuspendException
    {
-      latcher = new CountDownLatch(1);
-      close();
+      latcher.set(new CountDownLatch(1));
+      closeAndKeepWaitingThreads();
 
-      isSuspended = true;
+      isSuspended.set(true);
    }
 
    /**
@@ -3393,12 +3415,12 @@
    {
       try
       {
-         closed = false;
+         closed.set(false);
          doInit();
 
-         latcher.countDown();
+         resumeWaitingThreads();
 
-         isSuspended = false;
+         isSuspended.set(false);
       }
       catch (IOException e)
       {
@@ -3415,7 +3437,7 @@
     */
    public boolean isSuspended()
    {
-      return isSuspended;
+      return isSuspended.get();
    }
 
    /**
@@ -3426,11 +3448,11 @@
     */
    private void waitForResuming() throws IOException
    {
-      if (isSuspended)
+      if (isSuspended.get())
       {
          try
          {
-            latcher.await();
+            latcher.get().await();
          }
          catch (InterruptedException e)
          {
@@ -3440,11 +3462,15 @@
    }
 
    /**
-    * {@inheritDoc}
+    * Count down latcher which makes for resuming all
+    * waiting threads.
     */
-   public int getPriority()
+   public void resumeWaitingThreads()
    {
-      return PRIORITY_NORMAL;
+      if (latcher.get() != null)
+      {
+         latcher.get().countDown();
+      }
    }
 
    /**
@@ -3462,4 +3488,12 @@
    {
       this.indexingThreadPoolSize = indexingThreadPoolSize;
    }
+
+   /**
+    * {@inheritDoc}
+    */
+   public int getPriority()
+   {
+      return PRIORITY_NORMAL;
+   }
 }
Index: exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/MultiIndex.java
===================================================================
--- exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/MultiIndex.java	(revision 5970)
+++ exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/MultiIndex.java	(working copy)
@@ -65,6 +65,7 @@
 import java.util.concurrent.Callable;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.atomic.AtomicReference;
@@ -242,12 +243,12 @@
     * Or for any other reason it should be switched
     * to offline mode.
     */
-   private boolean online = true;
+   private final AtomicBoolean online = new AtomicBoolean(true);
 
    /**
     * Flag indicating whether the index is stopped.
     */
-   private volatile boolean stopped;
+   private final AtomicBoolean stopped = new AtomicBoolean();
 
    /**
     * The index format version of this multi index.
@@ -267,7 +268,7 @@
       @Override
       public void run()
       {
-         stopped = true;
+         stopped.set(true);
       }
    };
 
@@ -592,12 +593,12 @@
     */
    public void reindex(ItemDataConsumer stateMgr) throws IOException, RepositoryException
    {
-      if (stopped)
+      if (stopped.get())
       {
          throw new IllegalStateException("Can't invoke reindexing on closed index.");
       }
 
-      if (online)
+      if (online.get())
       {
          throw new IllegalStateException("Can't invoke reindexing while index still online.");
       }
@@ -645,7 +646,7 @@
     */
    synchronized void update(final Collection<String> remove, final Collection<Document> add) throws IOException
    {
-      if (!online)
+      if (!online.get())
       {
          doUpdateOffline(remove, add);
       }
@@ -1215,7 +1216,7 @@
          try
          {
             // if we are reindexing there is already an active transaction
-            if (online)
+            if (online.get())
             {
                executeAndLog(new Start(Action.INTERNAL_TRANS_REPL_INDEXES));
             }
@@ -1246,7 +1247,7 @@
             }
             index.commit();
 
-            if (online)
+            if (online.get())
             {
                // only commit if we are not reindexing
                // when reindexing the final commit is done at the very end
@@ -1271,7 +1272,7 @@
             }
          }
       }
-      if (!online)
+      if (!online.get())
       {
          // do some cleanup right away when reindexing
          attemptDelete();
@@ -1335,7 +1336,7 @@
                   // if index in offline mode, due to hot async reindexing,
                   // need to return the reader containing only stale indexes (old),
                   // without newly created.
-                  List<PersistentIndex> persistedIndexesList = online ? indexes : staleIndexes;
+                  List<PersistentIndex> persistedIndexesList = online.get() ? indexes : staleIndexes;
                   List<ReadOnlyIndexReader> readerList = new ArrayList<ReadOnlyIndexReader>();
                   for (int i = 0; i < persistedIndexesList.size(); i++)
                   {
@@ -1388,15 +1389,6 @@
     */
    void close()
    {
-      // stop index merger
-      // when calling this method we must not lock this MultiIndex, otherwise
-      // a deadlock might occur
-      if (merger != null)
-      {
-         merger.dispose();
-         merger = null;
-      }
-
       synchronized (this)
       {
          // stop timer
@@ -1445,7 +1437,7 @@
          }
          modeHandler.removeIndexerIoModeListener(this);
          indexUpdateMonitor.removeIndexUpdateMonitorListener(this);
-         this.stopped = true;
+         this.stopped.set(true);
          // Remove the hook that will stop the threads if they are still running
          SecurityHelper.doPrivilegedAction(new PrivilegedAction<Object>()
          {
@@ -1465,6 +1457,14 @@
             }
          });
       }
+      // stop index merger after all possible flushes.
+      // when calling this method we must not lock this MultiIndex, otherwise
+      // a deadlock might occur
+      if (merger != null)
+      {
+         merger.dispose();
+         merger = null;
+      }
    }
 
    /**
@@ -1869,7 +1869,7 @@
    private void createIndex(final Queue<Callable<Void>> tasks, final NodeData node, final ItemDataConsumer stateMgr,
       final AtomicLong count) throws IOException, RepositoryException, InterruptedException
    {
-      if (stopped)
+      if (stopped.get())
       {
          throw new InterruptedException();
       }
@@ -2016,7 +2016,7 @@
    {
       for (NodeDataIndexing node : iterator.next())
       {
-         if (stopped)
+         if (stopped.get())
          {
             throw new InterruptedException();
          }
@@ -2142,7 +2142,7 @@
    private synchronized void checkFlush()
    {
       // avoid frequent flushes during reindexing;
-      long idleTime = online ? System.currentTimeMillis() - lastFlushTime : 0;
+      long idleTime = online.get() ? System.currentTimeMillis() - lastFlushTime : 0;
       long volatileTime = System.currentTimeMillis() - lastFileSystemFlushTime;
       // do not flush if volatileIdleTime is zero or negative
       if ((handler.getVolatileIdleTime() > 0 && idleTime > handler.getVolatileIdleTime() * 1000)
@@ -3470,7 +3470,7 @@
     */
    public boolean isOnline()
    {
-      return online;
+      return online.get();
    }
 
    /**
@@ -3478,7 +3478,7 @@
     */
    public boolean isStopped()
    {
-      return stopped;
+      return stopped.get();
    }
 
    /**
@@ -3490,7 +3490,7 @@
    public synchronized void setOnline(boolean isOnline, boolean dropStaleIndexes) throws IOException
    {
       // if mode really changed
-      if (online != isOnline)
+      if (online.get() != isOnline)
       {
          // switching to ONLINE
          if (isOnline)
@@ -3499,7 +3499,7 @@
             if (modeHandler.getMode() == IndexerIoMode.READ_WRITE)
             {
                offlineIndex.commit(true);
-               online = true;
+               online.set(true);
                // cleaning stale indexes
                for (PersistentIndex staleIndex : staleIndexes)
                {
@@ -3512,7 +3512,7 @@
             }
             else
             {
-               online = true;
+               online.set(true);
                staleIndexes.clear();
             }
          }
@@ -3538,10 +3538,10 @@
                staleIndexes.addAll(indexes);
             }
 
-            online = false;
+            online.set(false);
          }
       }
-      else if (!online)
+      else if (!online.get())
       {
          throw new IOException("Index is already in OFFLINE mode.");
       }
Index: exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/SearchManager.java
===================================================================
--- exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/SearchManager.java	(revision 5970)
+++ exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/SearchManager.java	(working copy)
@@ -104,6 +104,7 @@
 import java.util.NoSuchElementException;
 import java.util.Set;
 import java.util.StringTokenizer;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import javax.jcr.Node;
 import javax.jcr.PropertyType;
@@ -212,12 +213,12 @@
    /**
     * Indicates if component suspended or not.
     */
-   protected boolean isSuspended = false;
+   protected final AtomicBoolean isSuspended = new AtomicBoolean(false);
 
    /**
     * Indicates that node keep responsible for resuming.
     */
-   protected Boolean isResponsibleForResuming = false;
+   protected final AtomicBoolean isResponsibleForResuming = new AtomicBoolean(false);
 
    /**
     * Suspend remote command.
@@ -403,7 +404,7 @@
    public void checkIndex(final InspectionReport report, final boolean isSystem) throws RepositoryException,
       IOException
    {
-      if (isSuspended)
+      if (isSuspended.get())
       {
          try
          {
@@ -414,7 +415,7 @@
                   // try resuming the workspace
                   try
                   {
-                     if (isSystem && parentSearchManager != null && parentSearchManager.isSuspended)
+                     if (isSystem && parentSearchManager != null && parentSearchManager.isSuspended.get())
                      {
                         parentSearchManager.resume();
                      }
@@ -433,7 +434,7 @@
                      try
                      {
                         suspend();
-                        if (isSystem && parentSearchManager != null && !parentSearchManager.isSuspended)
+                        if (isSystem && parentSearchManager != null && !parentSearchManager.isSuspended.get())
                         {
                            parentSearchManager.suspend();
                         }
@@ -699,6 +700,7 @@
    public void stop()
    {
       handler.close();
+
       // ChangesFiler instance is one for both SearchManagers and close() must be invoked only once,  
       if (parentSearchManager != null)
       {
@@ -1202,7 +1204,7 @@
    {
       if (rpcService != null)
       {
-         isResponsibleForResuming = true;
+         isResponsibleForResuming.set(true);
 
          try
          {
@@ -1228,7 +1230,7 @@
     */
    public boolean isSuspended()
    {
-      return isSuspended;
+      return isSuspended.get();
    }
 
    /**
@@ -1275,7 +1277,7 @@
             throw new ResumeException(e);
          }
 
-         isResponsibleForResuming = false;
+         isResponsibleForResuming.set(false);
       }
       else
       {
@@ -1303,10 +1305,10 @@
          throw new IllegalStateException(
             "Index is not in READ_WRITE mode and reindexing can't be launched. Please start reindexing on coordinator node.");
       }
-      if (isSuspended || !handler.isOnline())
+      if (isSuspended.get() || !handler.isOnline())
       {
          throw new IllegalStateException("Can't start reindexing while index is "
-            + ((isSuspended) ? "SUSPENDED." : "already OFFLINE (it means that reindexing is in progress).") + ".");
+            + ((isSuspended.get()) ? "SUSPENDED." : "already OFFLINE (it means that reindexing is in progress).") + ".");
       }
 
       log.info("Starting hot reindexing on the " + handler.getContext().getRepositoryName() + "/"
@@ -1321,7 +1323,7 @@
             hotReindexingState = "Running. Started at " + sdf.format(Calendar.getInstance().getTime());
             try
             {
-               isResponsibleForResuming = true;
+               isResponsibleForResuming.set(true);
                // set offline cluster wide (will make merger disposed and volatile flushed)
                if (rpcService != null && changesFilter.isShared())
                {
@@ -1399,7 +1401,7 @@
                   hotReindexingState = "Stopped with errors at " + sdf.format(Calendar.getInstance().getTime());
                   log.info("Reindexing halted with errors.");
                }
-               isResponsibleForResuming = false;
+               isResponsibleForResuming.set(false);
             }
          }
       }, "HotReindexing-" + handler.getContext().getRepositoryName() + "-"
@@ -1512,7 +1514,7 @@
 
          public Serializable execute(Serializable[] args) throws Throwable
          {
-            return isResponsibleForResuming;
+            return isResponsibleForResuming.get();
          }
       });
 
@@ -1542,27 +1544,27 @@
          throw new SuspendException("Can't suspend index, while reindexing in progeress.");
       }
 
-      if (!isSuspended)
+      if (!isSuspended.get())
       {
          if (handler instanceof Suspendable)
          {
             ((Suspendable)handler).suspend();
          }
 
-         isSuspended = true;
+         isSuspended.set(true);
       }
    }
 
    protected void resumeLocally() throws ResumeException
    {
-      if (isSuspended)
+      if (isSuspended.get())
       {
          if (handler instanceof Suspendable)
          {
             ((Suspendable)handler).resume();
          }
 
-         isSuspended = false;
+         isSuspended.set(false);
       }
    }
 
@@ -1571,7 +1573,7 @@
     */
    public void onChange(TopologyChangeEvent event)
    {
-      if (isSuspended)
+      if (isSuspended.get())
       {
          new Thread()
          {
Index: exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/CacheableWorkspaceDataManager.java
===================================================================
--- exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/CacheableWorkspaceDataManager.java	(revision 5970)
+++ exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/CacheableWorkspaceDataManager.java	(working copy)
@@ -74,6 +74,7 @@
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
 
 import javax.jcr.RepositoryException;
 import javax.transaction.Status;
@@ -141,17 +142,22 @@
    /**
     * Indicates if component suspended or not.
     */
-   protected boolean isSuspended = false;
+   protected final AtomicBoolean isSuspended = new AtomicBoolean(false);
 
    /**
+    * Indicates if component stopped or not.
+    */
+   protected final AtomicBoolean isStopped = new AtomicBoolean(false);
+
+   /**
     * Allows to make all threads waiting until resume. 
     */
-   protected CountDownLatch latcher = null;
+   protected final AtomicReference<CountDownLatch> latcher = new AtomicReference<CountDownLatch>();
 
    /**
     * Indicates that node keep responsible for resuming.
     */
-   protected Boolean isResponsibleForResuming = false;
+   protected final AtomicBoolean isResponsibleForResuming = new AtomicBoolean(false);
 
    /**
     * Request to all nodes to check if there is someone who responsible for resuming.
@@ -927,11 +933,11 @@
     */
    public void save(final ItemStateChangesLog changesLog) throws RepositoryException
    {
-      if (isSuspended)
+      if (isSuspended.get())
       {
          try
          {
-            latcher.await();
+            latcher.get().await();
          }
          catch (InterruptedException e)
          {
@@ -971,7 +977,7 @@
       {
          workingThreads.decrementAndGet();
 
-         if (isSuspended && workingThreads.get() == 0)
+         if (isSuspended.get() && workingThreads.get() == 0)
          {
             synchronized (workingThreads)
             {
@@ -983,6 +989,11 @@
 
    private void doSave(final ItemStateChangesLog changesLog) throws RepositoryException
    {
+      if (isStopped.get())
+      {
+         throw new RepositoryException("Data container is stopped");
+      }
+      
       ChangesLogWrapper logWrapper = new ChangesLogWrapper(changesLog);
 
       if (isTxAware())
@@ -1933,7 +1944,7 @@
    {
       if (rpcService != null)
       {
-         isResponsibleForResuming = true;
+         isResponsibleForResuming.set(true);
 
          try
          {
@@ -1974,7 +1985,7 @@
             throw new ResumeException(e);
          }
 
-         isResponsibleForResuming = false;
+         isResponsibleForResuming.set(false);
       }
       else
       {
@@ -1987,15 +1998,15 @@
     */
    public boolean isSuspended()
    {
-      return isSuspended;
+      return isSuspended.get();
    }
 
    private void suspendLocally() throws SuspendException
    {
-      if (!isSuspended)
+      if (!isSuspended.get())
       {
-         latcher = new CountDownLatch(1);
-         isSuspended = true;
+         latcher.set(new CountDownLatch(1));
+         isSuspended.set(true);
 
          if (workingThreads.get() > 0)
          {
@@ -2020,12 +2031,12 @@
       }
    }
 
-   private void resumeLocally() throws ResumeException
+   private void resumeLocally()
    {
-      if (isSuspended)
+      if (isSuspended.get())
       {
-         latcher.countDown();
-         isSuspended = false;
+         latcher.get().countDown();
+         isSuspended.set(false);
       }
    }
 
@@ -2034,7 +2045,7 @@
     */
    public void onChange(TopologyChangeEvent event)
    {
-      if (isSuspended)
+      if (isSuspended.get())
       {
          new Thread()
          {
@@ -2054,14 +2065,7 @@
                   }
 
                   // node which was responsible for resuming leave the cluster, so resume component
-                  try
-                  {
-                     resumeLocally();
-                  }
-                  catch (ResumeException e)
-                  {
-                     LOG.error("Can not resume component", e);
-                  }
+                  resumeLocally();
                }
                catch (SecurityException e1)
                {
@@ -2127,7 +2131,7 @@
 
             public Serializable execute(Serializable[] args) throws Throwable
             {
-               return isResponsibleForResuming;
+               return isResponsibleForResuming.get();
             }
          });
 
@@ -2377,6 +2381,8 @@
     */
    public void start()
    {
+      isStopped.set(false);
+
       try
       {
          this.cache.addListener(this);
@@ -2478,6 +2484,9 @@
       {
          cache.removeListener(this);
       }
+
+      isStopped.set(true);
+      resumeLocally();
    }
 
    /**
