Author: tolusha
Date: 2011-01-26 11:18:11 -0500 (Wed, 26 Jan 2011)
New Revision: 3890
Added:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/BackupException.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/Backupable.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/ComplexDataRestor.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/DataRestor.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/DummyDataRestor.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/JCRRestor.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/ResumeException.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/SuspendException.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/Suspendable.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/rdbms/
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/rdbms/DBBackup.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/rdbms/DBRestor.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/rdbms/DirectoryRestor.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/rdbms/RestoreTableRule.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/clean/
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/clean/rdbms/
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/clean/rdbms/DBClean.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/clean/rdbms/DBCleanHelper.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/clean/rdbms/DBCleanService.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/clean/rdbms/IngresSQLDBClean.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/clean/rdbms/OracleDBClean.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/clean/rdbms/PgSQLDBClean.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/util/io/DirectoryHelper.java
Removed:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/cleaner/
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/RepositoryContainer.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/BackupWorkspaceInitializer.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/RepositoryImpl.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cacheable/AbstractCacheableLockManager.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/infinispan/ISPNCacheableLockManagerImpl.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/CacheableLockManagerImpl.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/AbstractQueryHandler.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/SearchManager.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/SystemSearchManager.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/jbosscache/JBossCacheIndexInfos.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/jbosscache/JBossCacheIndexUpdateMonitor.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/MultiIndex.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SearchIndex.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/CacheableWorkspaceDataManager.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/WorkspacePersistentDataManager.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/ISPNCacheWorkspaceStorageCache.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/BufferedJBossCache.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/JBossCacheWorkspaceStorageCache.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/inmemory/InmemoryContainerImpl.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainer.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/jbosscache/PrivilegedJBossCacheHelper.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/storage/DataContainer.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/storage/WorkspaceDataContainer.java
jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/TestCacheableWorkspaceDataManager.java
jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/util/jdbc/TestDBCleaner.java
jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-configuration.xml
jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-jcr-config.xml
jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/test-configuration.xml
Log:
EXOJCR-1153: Support atomic restore
EXOJCR-1147: Make backup/restore to be cluster aware
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/RepositoryContainer.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/RepositoryContainer.java 2011-01-26
15:23:23 UTC (rev 3889)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/RepositoryContainer.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -245,7 +245,7 @@
final boolean isSystem =
config.getSystemWorkspaceName().equals(wsConfig.getName());
if (getWorkspaceContainer(wsConfig.getName()) != null)
- throw new RepositoryException("Workspace " + wsConfig.getName() +
" already registred");
+ throw new RepositoryException("Workspace " + wsConfig.getName() +
" already registered");
WorkspaceContainer workspaceContainer = new WorkspaceContainer(this, wsConfig);
Added:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/BackupException.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/BackupException.java
(rev 0)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/BackupException.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2009 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.backup;
+
+/**
+ * @author <a href="mailto:anatoliy.bazko@gmail.com">Anatoliy
Bazko</a>
+ * @version $Id: BackupException.java 34360 2009-07-22 23:58:59Z tolusha $
+ */
+public class BackupException extends Exception
+{
+ /**
+ * Constructor BackupException.
+ *
+ * @param message
+ * the message
+ */
+ public BackupException(String message)
+ {
+ super(message);
+ }
+
+ /**
+ * Constructor BackupException.
+ *
+ * @param cause
+ * the cause
+ */
+ public BackupException(Throwable cause)
+ {
+ super(cause);
+ }
+
+ /**
+ * Constructor BackupException.
+ *
+ * @param message
+ * the message
+ * @param cause
+ * the cause
+ */
+ public BackupException(String message, Throwable cause)
+ {
+ super(message, cause);
+ }
+}
Added:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/Backupable.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/Backupable.java
(rev 0)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/Backupable.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2009 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.backup;
+
+import java.io.File;
+import java.sql.Connection;
+
+/**
+ * @author <a href="mailto:anatoliy.bazko@gmail.com">Anatoliy
Bazko</a>
+ * @version $Id: Backupable.java 34360 2009-07-22 23:58:59Z tolusha $
+ */
+public interface Backupable
+{
+ /**
+ * Backup data.
+ *
+ * @param storageDir
+ * the directory to store backup
+ * @throws BackupException
+ * if any exception occurred
+ */
+ void backup(File storageDir) throws BackupException;
+
+ /**
+ * Clean data.
+ *
+ * @throws BackupException
+ * if any exception occurred
+ */
+ void clean() throws BackupException;
+
+ /**
+ * Get data restorer to support atomic restore.
+ *
+ * @param storageDir
+ * the directory where backup is stored
+ * @param jdbcConn
+ * the shared connection to database if need, may be null
+ * @throws RestoreException
+ * if any exception occurred
+ */
+ DataRestor getDataRestorer(File storageDir, Connection jdbcConn) throws
BackupException;
+
+}
Added:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/ComplexDataRestor.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/ComplexDataRestor.java
(rev 0)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/ComplexDataRestor.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2003-2010 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not,
see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.impl.backup;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * Date: 21 01 2011
+ *
+ * @author <a href="mailto:anatoliy.bazko@exoplatform.com.ua">Anatoliy
Bazko</a>
+ * @version $Id: ComplexDataRestor.java 34360 2010-11-11 11:11:11Z tolusha $
+ */
+public class ComplexDataRestor implements DataRestor
+{
+
+ /**
+ * List of restorers.
+ */
+ private List<DataRestor> restorers = new ArrayList<DataRestor>();
+
+ /**
+ * Constructor ComplexDataRestor.
+ *
+ * @param restorers
+ */
+ public ComplexDataRestor(List<DataRestor> restorers)
+ {
+ this.restorers.addAll(restorers);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void clean() throws BackupException
+ {
+ for (DataRestor restorer : restorers)
+ {
+ restorer.clean();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void restore() throws BackupException
+ {
+ for (DataRestor restorer : restorers)
+ {
+ restorer.restore();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void commit() throws BackupException
+ {
+ for (DataRestor restorer : restorers)
+ {
+ restorer.commit();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void rollback() throws BackupException
+ {
+ for (DataRestor restorer : restorers)
+ {
+ restorer.rollback();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void close() throws BackupException
+ {
+ try
+ {
+ for (DataRestor restorer : restorers)
+ {
+ restorer.close();
+ }
+ }
+ finally
+ {
+ restorers.clear();
+ }
+ }
+}
Added:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/DataRestor.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/DataRestor.java
(rev 0)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/DataRestor.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2003-2010 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not,
see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.impl.backup;
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * Date: 22 01 2011
+ *
+ * @author <a href="mailto:anatoliy.bazko@exoplatform.com.ua">Anatoliy
Bazko</a>
+ * @version $Id: DataRestor.java.java 34360 2010-11-11 11:11:11Z tolusha $
+ */
+public interface DataRestor
+{
+
+ /**
+ * Clean old data from the storage.
+ *
+ * @throws RestoreException
+ * if any exception is occurred
+ */
+ void clean() throws BackupException;
+
+ /**
+ * Restore new data into storage.
+ *
+ * @throws RestoreException
+ * if any exception is occurred
+ */
+ void restore() throws BackupException;
+
+ /**
+ * Commit changes.
+ *
+ * @throws RestoreException
+ * if any exception is occurred
+ */
+ void commit() throws BackupException;
+
+ /**
+ * Rollback changes.
+ *
+ * @throws RestoreException
+ * if any exception is occurred
+ */
+ void rollback() throws BackupException;
+
+ /**
+ * Close DataRestor.
+ *
+ * @throws RestoreException
+ * if any exception is occurred
+ */
+ void close() throws BackupException;
+}
Added:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/DummyDataRestor.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/DummyDataRestor.java
(rev 0)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/DummyDataRestor.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2003-2010 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not,
see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.impl.backup;
+
+/***
+ * Created by The eXo Platform SAS.
+ *
+ * Date: 21 01 2011
+ *
+ * @author <a href="mailto:anatoliy.bazko@exoplatform.com.ua">Anatoliy
Bazko</a>
+ * @version $Id: DummyDataRestor.java 34360 2010-11-11 11:11:11Z tolusha $
+ */
+public class DummyDataRestor implements DataRestor
+{
+ /**
+ * {@inheritDoc}
+ */
+ public void restore() throws BackupException
+ {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void clean() throws BackupException
+ {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void commit() throws BackupException
+ {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void rollback() throws BackupException
+ {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void close() throws BackupException
+ {
+ }
+}
Added:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/JCRRestor.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/JCRRestor.java
(rev 0)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/JCRRestor.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -0,0 +1,449 @@
+/*
+ * Copyright (C) 2009 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.backup;
+
+import org.exoplatform.commons.utils.PrivilegedFileHelper;
+import org.exoplatform.commons.utils.PrivilegedSystemHelper;
+import org.exoplatform.services.jcr.dataflow.ChangesLogIterator;
+import org.exoplatform.services.jcr.dataflow.DataManager;
+import org.exoplatform.services.jcr.dataflow.ItemState;
+import org.exoplatform.services.jcr.dataflow.PlainChangesLog;
+import org.exoplatform.services.jcr.dataflow.PlainChangesLogImpl;
+import org.exoplatform.services.jcr.dataflow.TransactionChangesLog;
+import org.exoplatform.services.jcr.dataflow.persistent.PersistedPropertyData;
+import org.exoplatform.services.jcr.datamodel.ItemData;
+import org.exoplatform.services.jcr.datamodel.ValueData;
+import org.exoplatform.services.jcr.impl.Constants;
+import org.exoplatform.services.jcr.impl.dataflow.persistent.StreamPersistedValueData;
+import org.exoplatform.services.jcr.impl.storage.JCRInvalidItemStateException;
+import org.exoplatform.services.jcr.impl.storage.JCRItemExistsException;
+import org.exoplatform.services.jcr.impl.util.io.FileCleaner;
+import org.exoplatform.services.jcr.impl.util.io.SpoolFile;
+import org.exoplatform.services.jcr.observation.ExtendedEvent;
+
+import java.io.EOFException;
+import java.io.Externalizable;
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutput;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.jcr.RepositoryException;
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * Date: 24 01 2011
+ *
+ * Class contains commons method for JCR restore operation.
+ * - get path to full backup<br>
+ * - get list of incremental backup files<br>
+ * - perform incremental restore function<br>
+ *
+ * @author <a href="mailto:anatoliy.bazko@exoplatform.com.ua">Anatoliy
Bazko</a>
+ * @version $Id: JCRRestorerHelper.java 34360 2010-11-11 11:11:11Z tolusha $
+ */
+public class JCRRestor
+{
+
+ private final DataManager dataManager;
+
+ private final FileCleaner fileCleaner;
+
+ private final File tempDir = new
File(PrivilegedSystemHelper.getProperty("java.io.tmpdir"));
+
+ public JCRRestor(DataManager dataManager, FileCleaner fileCleaner)
+ {
+ this.dataManager = dataManager;
+ this.fileCleaner = fileCleaner;
+ }
+
+ /**
+ * Returns file with full backup. In case of RDBMS backup
+ * it may be a directory.
+ *
+ * @param restoreDir
+ * @return
+ */
+ public static File getFullBackupFile(File restoreDir)
+ {
+ Pattern p = Pattern.compile(".+\\.0");
+
+ for (File f : PrivilegedFileHelper.listFiles(restoreDir, new FileFilter()
+ {
+ public boolean accept(File pathname)
+ {
+ Pattern p = Pattern.compile(".+\\.[0-9]+");
+ Matcher m = p.matcher(pathname.getName());
+ return m.matches();
+ }
+ }))
+ {
+ Matcher m = p.matcher(f.getName());
+ if (m.matches())
+ {
+ return f;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Get list of incremental backup files.
+ *
+ * @param restoreDir
+ * @return list of files
+ */
+ public static List<File> getIncrementalFiles(File restoreDir)
+ {
+ ArrayList<File> list = new ArrayList<File>();
+
+ Pattern fullBackupPattern = Pattern.compile(".+\\.0");
+
+ for (File f : PrivilegedFileHelper.listFiles(restoreDir, new FileFilter()
+ {
+ public boolean accept(File pathname)
+ {
+ Pattern p = Pattern.compile(".+\\.[0-9]+");
+ Matcher m = p.matcher(pathname.getName());
+ return m.matches();
+ }
+ }))
+ {
+ if (fullBackupPattern.matcher(f.getName()).matches() == false)
+ {
+ list.add(f);
+ }
+ }
+
+ return list;
+ }
+
+ /**
+ * Perform incremental restore operation.
+ *
+ * @param incrementalBackupFile
+ * incremental backup file
+ * @throws FileNotFoundException
+ * @throws IOException
+ * @throws ClassNotFoundException
+ * @throws RepositoryException
+ */
+ public void incrementalRestore(File incrementalBackupFile) throws
FileNotFoundException, IOException,
+ ClassNotFoundException, RepositoryException
+ {
+ ObjectInputStream ois = null;
+ try
+ {
+ ois = new
ObjectInputStream(PrivilegedFileHelper.fileInputStream(incrementalBackupFile));
+
+ while (true)
+ {
+ TransactionChangesLog changesLog = readExternal(ois);
+
changesLog.setSystemId(Constants.JCR_CORE_RESTORE_WORKSPACE_INITIALIZER_SYSTEM_ID); //
mark changes
+
+ ChangesLogIterator cli = changesLog.getLogIterator();
+ while (cli.hasNextLog())
+ {
+ if (cli.nextLog().getEventType() == ExtendedEvent.LOCK)
+ cli.removeLog();
+ }
+
+ saveChangesLog(changesLog);
+ }
+ }
+ catch (EOFException ioe)
+ {
+ // ok - reading all data from backup file;
+ }
+ }
+
+ private void saveChangesLog(TransactionChangesLog changesLog) throws
RepositoryException
+ {
+ try
+ {
+ dataManager.save(changesLog);
+ }
+ catch (JCRInvalidItemStateException e)
+ {
+ TransactionChangesLog normalizeChangesLog =
+ getNormalizedChangesLog(e.getIdentifier(), e.getState(), changesLog);
+ if (normalizeChangesLog != null)
+ saveChangesLog(normalizeChangesLog);
+ else
+ throw new RepositoryException(
+ "Collisions found during save of restore changes log, but caused item
is not found by ID "
+ + e.getIdentifier() + ". " + e, e);
+ }
+ catch (JCRItemExistsException e)
+ {
+ TransactionChangesLog normalizeChangesLog =
+ getNormalizedChangesLog(e.getIdentifier(), e.getState(), changesLog);
+ if (normalizeChangesLog != null)
+ saveChangesLog(normalizeChangesLog);
+ else
+ throw new RepositoryException(
+ "Collisions found during save of restore changes log, but caused item
is not found by ID "
+ + e.getIdentifier() + ". " + e, e);
+ }
+ }
+
+ private TransactionChangesLog getNormalizedChangesLog(String collisionID, int state,
TransactionChangesLog changesLog)
+ {
+ ItemState citem = changesLog.getItemState(collisionID);
+
+ if (citem != null)
+ {
+
+ TransactionChangesLog result = new TransactionChangesLog();
+ result.setSystemId(changesLog.getSystemId());
+
+ ChangesLogIterator cli = changesLog.getLogIterator();
+ while (cli.hasNextLog())
+ {
+ ArrayList<ItemState> normalized = new ArrayList<ItemState>();
+ PlainChangesLog next = cli.nextLog();
+ for (ItemState change : next.getAllStates())
+ {
+ if (state == change.getState())
+ {
+ ItemData item = change.getData();
+ // targeted state
+ if (citem.isNode())
+ {
+ // Node... by ID and desc path
+ if (!item.getIdentifier().equals(collisionID)
+ &&
!item.getQPath().isDescendantOf(citem.getData().getQPath()))
+ normalized.add(change);
+ }
+ else if (!item.getIdentifier().equals(collisionID))
+ {
+ // Property... by ID
+ normalized.add(change);
+ }
+ }
+ else
+ // another state
+ normalized.add(change);
+ }
+
+ PlainChangesLog plog = new PlainChangesLogImpl(normalized,
next.getSessionId(), next.getEventType());
+ result.addLog(plog);
+ }
+
+ return result;
+ }
+
+ return null;
+ }
+
+ private TransactionChangesLog readExternal(ObjectInputStream in) throws IOException,
ClassNotFoundException
+ {
+ int changesLogType = in.readInt();
+
+ TransactionChangesLog transactionChangesLog = null;
+
+ if (changesLogType == RestoreChangesLog.Type.ItemDataChangesLog_with_Streams)
+ {
+
+ // read ChangesLog
+ transactionChangesLog = (TransactionChangesLog)in.readObject();
+
+ // read FixupStream count
+ int iFixupStream = in.readInt();
+
+ ArrayList<FixupStream> listFixupStreams = new
ArrayList<FixupStream>();
+
+ for (int i = 0; i < iFixupStream; i++)
+ {
+ FixupStream fs = new FixupStream();
+ fs.readExternal(in);
+ listFixupStreams.add(fs);
+ }
+
+ // read stream data
+ int iStreamCount = in.readInt();
+ ArrayList<File> listFiles = new ArrayList<File>();
+
+ for (int i = 0; i < iStreamCount; i++)
+ {
+
+ // read file size
+ long fileSize = in.readLong();
+
+ // read content file
+ File contentFile = getAsFile(in, fileSize);
+ listFiles.add(contentFile);
+ }
+
+ RestoreChangesLog restoreChangesLog =
+ new RestoreChangesLog(transactionChangesLog, listFixupStreams, listFiles,
fileCleaner);
+
+ restoreChangesLog.restore();
+
+ }
+ else if (changesLogType ==
RestoreChangesLog.Type.ItemDataChangesLog_without_Streams)
+ {
+ transactionChangesLog = (TransactionChangesLog)in.readObject();
+ }
+
+ return transactionChangesLog;
+ }
+
+ private File getAsFile(ObjectInputStream ois, long fileSize) throws IOException
+ {
+ int bufferSize = 1024 * 8;
+ byte[] buf = new byte[bufferSize];
+
+ File tempFile = SpoolFile.createTempFile("vdincb" +
System.currentTimeMillis(), ".stmp", tempDir);
+ FileOutputStream fos = PrivilegedFileHelper.fileOutputStream(tempFile);
+ long readBytes = fileSize;
+
+ while (readBytes > 0)
+ {
+ // long longTemp = readByte - bufferSize;
+ if (readBytes >= bufferSize)
+ {
+ ois.readFully(buf);
+ fos.write(buf);
+ }
+ else if (readBytes < bufferSize)
+ {
+ ois.readFully(buf, 0, (int)readBytes);
+ fos.write(buf, 0, (int)readBytes);
+ }
+ readBytes -= bufferSize;
+ }
+
+ fos.flush();
+ fos.close();
+
+ return tempFile;
+ }
+
+ class RestoreChangesLog
+ {
+ public class Type
+ {
+ public static final int ItemDataChangesLog_without_Streams = 1;
+
+ public static final int ItemDataChangesLog_with_Streams = 2;
+ }
+
+ private TransactionChangesLog itemDataChangesLog;
+
+ private List<FixupStream> listFixupStream;
+
+ private List<File> listFile;
+
+ private FileCleaner fileCleaner;
+
+ public RestoreChangesLog(TransactionChangesLog transactionChangesLog,
List<FixupStream> listFixupStreams,
+ List<File> listFiles, FileCleaner fileCleaner)
+ {
+ this.itemDataChangesLog = transactionChangesLog;
+ this.listFixupStream = listFixupStreams;
+ this.listFile = listFiles;
+ this.fileCleaner = fileCleaner;
+ }
+
+ public TransactionChangesLog getItemDataChangesLog()
+ {
+ return itemDataChangesLog;
+ }
+
+ public void restore() throws IOException
+ {
+ List<ItemState> listItemState = itemDataChangesLog.getAllStates();
+ for (int i = 0; i < this.listFixupStream.size(); i++)
+ {
+ ItemState itemState =
listItemState.get(listFixupStream.get(i).getItemSateId());
+ ItemData itemData = itemState.getData();
+
+ PersistedPropertyData propertyData = (PersistedPropertyData)itemData;
+ ValueData vd =
(propertyData.getValues().get(listFixupStream.get(i).getValueDataId()));
+
+ // re-init the value
+ propertyData.getValues().set(listFixupStream.get(i).getValueDataId(),
+ new StreamPersistedValueData(vd.getOrderNumber(), new
SpoolFile(listFile.get(i).getAbsolutePath())));
+ }
+
+ for (int i = 0; i < listFile.size(); i++)
+ fileCleaner.addFile(listFile.get(i));
+ }
+ }
+
+ class FixupStream implements Externalizable
+ {
+ int iItemStateId = -1;
+
+ int iValueDataId = -1;
+
+ public FixupStream()
+ {
+ }
+
+ public FixupStream(int itemState_, int valueData_)
+ {
+ iItemStateId = itemState_;
+ iValueDataId = valueData_;
+ }
+
+ public int getItemSateId()
+ {
+ return iItemStateId;
+ }
+
+ public int getValueDataId()
+ {
+ return iValueDataId;
+ }
+
+ public boolean compare(FixupStream fs)
+ {
+ boolean b = true;
+ if (fs.getItemSateId() != this.getItemSateId())
+ b = false;
+ if (fs.getValueDataId() != this.getValueDataId())
+ b = false;
+ return b;
+ }
+
+ public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException
+ {
+ iItemStateId = in.readInt();
+ iValueDataId = in.readInt();
+ }
+
+ public void writeExternal(ObjectOutput out) throws IOException
+ {
+ out.writeInt(iItemStateId);
+ out.writeInt(iValueDataId);
+ }
+ }
+}
Added:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/ResumeException.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/ResumeException.java
(rev 0)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/ResumeException.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2009 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.backup;
+
+/**
+ * @author <a href="mailto:anatoliy.bazko@gmail.com">Anatoliy
Bazko</a>
+ * @version $Id: ResumeException.java 34360 2009-07-22 23:58:59Z tolusha $
+ */
+public class ResumeException extends Exception
+{
+ /**
+ * Constructor ResumeException.
+ *
+ * @param cause
+ * the cause
+ */
+ public ResumeException(Throwable cause)
+ {
+ super(cause);
+ }
+
+ /**
+ * Constructor ResumeException.
+ *
+ * @param message
+ * the message
+ */
+ public ResumeException(String message)
+ {
+ super(message);
+ }
+
+ /**
+ * Constructor ResumeException.
+ *
+ * @param message
+ * the message
+ * @param cause
+ * the cause
+ */
+ public ResumeException(String message, Throwable cause)
+ {
+ super(message, cause);
+ }
+}
Added:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/SuspendException.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/SuspendException.java
(rev 0)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/SuspendException.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2009 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.backup;
+
+/**
+ * @author <a href="mailto:anatoliy.bazko@gmail.com">Anatoliy
Bazko</a>
+ * @version $Id: SuspendException.java 34360 2009-07-22 23:58:59Z tolusha $
+ */
+public class SuspendException extends Exception
+{
+ /**
+ * Constructor SuspendException.
+ *
+ * @param cause
+ * the cause
+ */
+ public SuspendException(Throwable cause)
+ {
+ super(cause);
+ }
+
+ /**
+ * Constructor SuspendException.
+ *
+ * @param message
+ * the message
+ */
+ public SuspendException(String message)
+ {
+ super(message);
+ }
+
+ /**
+ * Constructor SuspendException.
+ *
+ * @param message
+ * the message
+ * @param cause
+ * the cause
+ */
+ public SuspendException(String message, Throwable cause)
+ {
+ super(message, cause);
+ }
+}
Added:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/Suspendable.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/Suspendable.java
(rev 0)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/Suspendable.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2009 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.backup;
+
+/**
+ * @author <a href="mailto:anatoliy.bazko@gmail.com">Anatoliy
Bazko</a>
+ * @version $Id: Suspendable.java 34360 2009-07-22 23:58:59Z tolusha $
+ */
+public interface Suspendable
+{
+
+ /**
+ * Suspend component.
+ *
+ * @throws SuspendException of error occurred
+ */
+ void suspend() throws SuspendException;
+
+ /**
+ * Resume component.
+ *
+ * @throws ResumeException of error occurred
+ */
+ void resume() throws ResumeException;
+
+}
Added:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/rdbms/DBBackup.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/rdbms/DBBackup.java
(rev 0)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/rdbms/DBBackup.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2009 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.backup.rdbms;
+
+import org.exoplatform.commons.utils.PrivilegedFileHelper;
+import org.exoplatform.services.jcr.core.security.JCRRuntimePermissions;
+import org.exoplatform.services.jcr.impl.Constants;
+import org.exoplatform.services.jcr.impl.backup.BackupException;
+import org.exoplatform.services.jcr.impl.dataflow.serialization.ObjectZipWriterImpl;
+import org.exoplatform.services.jcr.impl.storage.jdbc.DBConstants;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.zip.ZipEntry;
+
+/**
+ * @author <a href="mailto:anatoliy.bazko@gmail.com">Anatoliy
Bazko</a>
+ * @version $Id: DBBackup.java 34360 2009-07-22 23:58:59Z tolusha $
+ */
+public class DBBackup
+{
+ /**
+ * Suffix for content file.
+ */
+ public static final String CONTENT_FILE_SUFFIX = ".dump";
+
+ /**
+ * Suffix for content length file.
+ */
+ public static final String CONTENT_LEN_FILE_SUFFIX = ".len";
+
+ /**
+ * MySQL dialect.
+ */
+ public static final int DB_DIALECT_MYSQL = DBConstants.DB_DIALECT_MYSQL.hashCode();
+
+ /**
+ * MySQL-UTF8 dialect.
+ */
+ public static final int DB_DIALECT_MYSQL_UTF8 =
DBConstants.DB_DIALECT_MYSQL_UTF8.hashCode();
+
+ /**
+ * DB2 dialect.
+ */
+ public static final int DB_DIALECT_DB2 = DBConstants.DB_DIALECT_DB2.hashCode();
+
+ /**
+ * DB2V8 dialect.
+ */
+ public static final int DB_DIALECT_DB2V8 = DBConstants.DB_DIALECT_DB2V8.hashCode();
+
+ /**
+ * PGSQL dialect.
+ */
+ public static final int DB_DIALECT_PGSQL = DBConstants.DB_DIALECT_PGSQL.hashCode();
+
+ /**
+ * SYBASE dialect.
+ */
+ public static final int DB_DIALECT_SYBASE = DBConstants.DB_DIALECT_SYBASE.hashCode();
+
+ /**
+ * Backup tables.
+ *
+ * @param storageDir
+ * the directory to store data
+ * @param jdbcConn
+ * the connection to database
+ * @param scripts
+ * map which contains table name and respective SQL query to get data
+ * @throws BackupException
+ * if any exception occurred
+ */
+ public static void backup(File storageDir, Connection jdbcConn, Map<String,
String> scripts) throws BackupException
+ {
+ try
+ {
+ for (Entry<String, String> entry : scripts.entrySet())
+ {
+ dumpTable(jdbcConn, entry.getKey(), entry.getValue(), storageDir);
+ }
+ }
+ catch (IOException e)
+ {
+ throw new BackupException(e);
+ }
+ catch (SQLException e)
+ {
+ SQLException next = e.getNextException();
+ String errorTrace = "";
+ while (next != null)
+ {
+ errorTrace += next.getMessage() + "; ";
+ next = next.getNextException();
+ }
+
+ Throwable cause = e.getCause();
+ String msg = "SQL Exception: " + errorTrace + (cause != null ? "
(Cause: " + cause.getMessage() + ")" : "");
+
+ throw new BackupException(msg, e);
+ }
+ finally
+ {
+ if (jdbcConn != null)
+ {
+ try
+ {
+ jdbcConn.close();
+ }
+ catch (SQLException e)
+ {
+ throw new BackupException(e);
+ }
+ }
+ }
+ }
+
+ /**
+ * Dump table.
+ *
+ * @throws IOException
+ * @throws SQLException
+ */
+ private static void dumpTable(Connection jdbcConn, String tableName, String script,
File storageDir)
+ throws IOException, SQLException
+ {
+ // Need privileges
+ SecurityManager security = System.getSecurityManager();
+ if (security != null)
+ {
+ security.checkPermission(JCRRuntimePermissions.MANAGE_REPOSITORY_PERMISSION);
+ }
+
+ ObjectZipWriterImpl contentWriter = null;
+ ObjectZipWriterImpl contentLenWriter = null;
+ PreparedStatement stmt = null;
+ ResultSet rs = null;
+ try
+ {
+ File contentFile = new File(storageDir, tableName + CONTENT_FILE_SUFFIX);
+ contentWriter = new
ObjectZipWriterImpl(PrivilegedFileHelper.zipOutputStream(contentFile));
+ contentWriter.putNextEntry(new ZipEntry(tableName));
+
+ File contentLenFile = new File(storageDir, tableName +
CONTENT_LEN_FILE_SUFFIX);
+ contentLenWriter = new
ObjectZipWriterImpl(PrivilegedFileHelper.zipOutputStream(contentLenFile));
+ contentLenWriter.putNextEntry(new ZipEntry(tableName));
+
+ stmt = jdbcConn.prepareStatement(script);
+ rs = stmt.executeQuery();
+ ResultSetMetaData metaData = rs.getMetaData();
+
+ int columnCount = metaData.getColumnCount();
+ int[] columnType = new int[columnCount];
+
+ contentWriter.writeInt(columnCount);
+ for (int i = 0; i < columnCount; i++)
+ {
+ columnType[i] = metaData.getColumnType(i + 1);
+ contentWriter.writeInt(columnType[i]);
+ contentWriter.writeString(metaData.getColumnName(i + 1));
+ }
+
+ // Now we can output the actual data
+ while (rs.next())
+ {
+ for (int i = 0; i < columnCount; i++)
+ {
+ InputStream value;
+ if (columnType[i] == Types.VARBINARY || columnType[i] ==
Types.LONGVARBINARY
+ || columnType[i] == Types.BLOB || columnType[i] == Types.BINARY ||
columnType[i] == Types.OTHER)
+ {
+ value = rs.getBinaryStream(i + 1);
+ }
+ else
+ {
+ String str = rs.getString(i + 1);
+ value = str == null ? null : new
ByteArrayInputStream(str.getBytes(Constants.DEFAULT_ENCODING));
+ }
+
+ if (value == null)
+ {
+ contentLenWriter.writeLong(-1);
+ }
+ else
+ {
+ long len = 0;
+ int read = 0;
+ byte[] tmpBuff = new byte[2048];
+
+ while ((read = value.read(tmpBuff)) >= 0)
+ {
+ contentWriter.write(tmpBuff, 0, read);
+ len += read;
+ }
+ contentLenWriter.writeLong(len);
+ }
+ }
+ }
+ }
+ finally
+ {
+ if (contentWriter != null)
+ {
+ contentWriter.closeEntry();
+ contentWriter.close();
+ }
+
+ if (contentLenWriter != null)
+ {
+ contentLenWriter.closeEntry();
+ contentLenWriter.close();
+ }
+
+ if (rs != null)
+ {
+ rs.close();
+ }
+
+ if (stmt != null)
+ {
+ stmt.close();
+ }
+ }
+ }
+
+}
Added:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/rdbms/DBRestor.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/rdbms/DBRestor.java
(rev 0)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/rdbms/DBRestor.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -0,0 +1,661 @@
+/*
+ * Copyright (C) 2009 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.backup.rdbms;
+
+import org.exoplatform.commons.utils.PrivilegedFileHelper;
+import org.exoplatform.commons.utils.PrivilegedSystemHelper;
+import org.exoplatform.commons.utils.SecurityHelper;
+import org.exoplatform.services.jcr.config.RepositoryConfigurationException;
+import org.exoplatform.services.jcr.config.WorkspaceEntry;
+import org.exoplatform.services.jcr.core.security.JCRRuntimePermissions;
+import org.exoplatform.services.jcr.dataflow.serialization.ObjectReader;
+import org.exoplatform.services.jcr.impl.Constants;
+import org.exoplatform.services.jcr.impl.backup.BackupException;
+import org.exoplatform.services.jcr.impl.backup.DataRestor;
+import org.exoplatform.services.jcr.impl.clean.rdbms.DBClean;
+import org.exoplatform.services.jcr.impl.clean.rdbms.DBCleanService;
+import org.exoplatform.services.jcr.impl.dataflow.serialization.ObjectZipReaderImpl;
+import org.exoplatform.services.jcr.impl.storage.jdbc.DialectDetecter;
+import org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer;
+import org.exoplatform.services.jcr.impl.util.io.FileCleaner;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+
+import java.io.ByteArrayInputStream;
+import java.io.EOFException;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.PrivilegedExceptionAction;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Types;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.naming.InitialContext;
+import javax.naming.NameNotFoundException;
+import javax.naming.NamingException;
+import javax.sql.DataSource;
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * Date: 22 01 2011
+ *
+ * @author <a href="mailto:anatoliy.bazko@exoplatform.com.ua">Anatoliy
Bazko</a>
+ * @version $Id: DBRestor.java 34360 2010-11-11 11:11:11Z tolusha $
+ */
+public class DBRestor implements DataRestor
+{
+ /**
+ * List of temporary files.
+ */
+ private final List<File> spoolFileList = new ArrayList<File>();
+
+ /**
+ * The file cleaner.
+ */
+ private final FileCleaner fileCleaner;
+
+ /**
+ * Temporary directory.
+ */
+ private final File tempDir = new
File(PrivilegedSystemHelper.getProperty("java.io.tmpdir"));
+
+ /**
+ * Maximum buffer size.
+ */
+ private final int maxBufferSize;
+
+ /**
+ * Logger.
+ */
+ protected static final Log LOG =
ExoLogger.getLogger("exo.jcr.component.core.DBRestor");
+
+ /**
+ * Connection to database.
+ */
+ private final Connection jdbcConn;
+
+ /**
+ * Directory with tables dump.
+ */
+ private final File storageDir;
+
+ /**
+ * Restore table rules.
+ */
+ private final Map<String, RestoreTableRule> tables;
+
+ /**
+ * Database cleaner.
+ */
+ private final DBClean dbClean;
+
+ /**
+ * Constructor DBRestor.
+ *
+ * @throws NamingException
+ * @throws SQLException
+ * @throws RepositoryConfigurationException
+ */
+ public DBRestor(File storageDir, Connection jdbcConn, Map<String,
RestoreTableRule> tables,
+ WorkspaceEntry wsConfig, FileCleaner fileCleaner) throws NamingException,
SQLException,
+ RepositoryConfigurationException
+ {
+ String dsName =
wsConfig.getContainer().getParameterValue(JDBCWorkspaceDataContainer.SOURCE_NAME);
+
+ if (jdbcConn == null)
+ {
+ final DataSource ds = (DataSource)new InitialContext().lookup(dsName);
+ if (ds == null)
+ {
+ throw new NameNotFoundException("Data source " + dsName + "
not found");
+ }
+
+ this.jdbcConn = SecurityHelper.doPrivilegedSQLExceptionAction(new
PrivilegedExceptionAction<Connection>()
+ {
+ public Connection run() throws Exception
+ {
+ return ds.getConnection();
+
+ }
+ });
+ this.jdbcConn.setAutoCommit(false);
+ }
+ else
+ {
+ this.jdbcConn = jdbcConn;
+ }
+
+ this.fileCleaner = fileCleaner;
+ this.maxBufferSize =
+
wsConfig.getContainer().getParameterInteger(JDBCWorkspaceDataContainer.MAXBUFFERSIZE_PROP,
+ JDBCWorkspaceDataContainer.DEF_MAXBUFFERSIZE);
+
+ this.storageDir = storageDir;
+ this.tables = tables;
+ this.dbClean = DBCleanService.getDBCleaner(this.jdbcConn, wsConfig);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void clean() throws BackupException
+ {
+ try
+ {
+ dbClean.clean();
+ }
+ catch (SQLException e)
+ {
+ throw new BackupException(e);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void restore() throws BackupException
+ {
+ Statement st = null;
+
+ try
+ {
+ int dialect = DialectDetecter.detect(jdbcConn.getMetaData()).hashCode();
+
+ for (Entry<String, RestoreTableRule> entry : tables.entrySet())
+ {
+ String tableName = entry.getKey();
+ RestoreTableRule restoreRule = entry.getValue();
+
+ String constraint = null;
+ if (tableName.equals("JCR_SITEM") ||
tableName.equals("JCR_MITEM"))
+ {
+ if (dialect != DBBackup.DB_DIALECT_MYSQL && dialect !=
DBBackup.DB_DIALECT_MYSQL_UTF8
+ && dialect != DBBackup.DB_DIALECT_SYBASE)
+ {
+ // resolve constraint name depends on database
+ String constraintName;
+ if (dialect == DBBackup.DB_DIALECT_DB2 || dialect ==
DBBackup.DB_DIALECT_DB2V8)
+ {
+ constraintName = "JCR_FK_" + (restoreRule.getDstMultiDb()
? "M" : "S") + "ITEM_PAREN";
+ }
+ else
+ {
+ constraintName = "JCR_FK_" + (restoreRule.getDstMultiDb()
? "M" : "S") + "ITEM_PARENT";
+ }
+ constraint =
+ "CONSTRAINT " + constraintName + " FOREIGN
KEY(PARENT_ID) REFERENCES " + tableName + "(ID)";
+
+ // drop constraint
+ st = jdbcConn.createStatement();
+ st.execute("ALTER TABLE " + tableName + " DROP
CONSTRAINT " + constraintName);
+ }
+ }
+
+ restoreTable(storageDir, jdbcConn, tableName, restoreRule);
+
+ if (constraint != null)
+ {
+ // add constraint
+ st.execute("ALTER TABLE " + tableName + " ADD " +
constraint);
+ }
+ }
+ }
+ catch (IOException e)
+ {
+ throw new BackupException(e);
+ }
+ catch (SQLException e)
+ {
+ SQLException next = e.getNextException();
+ String errorTrace = "";
+ while (next != null)
+ {
+ errorTrace += next.getMessage() + "; ";
+ next = next.getNextException();
+ }
+
+ Throwable cause = e.getCause();
+ String msg = "SQL Exception: " + errorTrace + (cause != null ? "
(Cause: " + cause.getMessage() + ")" : "");
+
+ throw new BackupException(msg, e);
+ }
+ finally
+ {
+ if (st != null)
+ {
+ try
+ {
+ st.close();
+ }
+ catch (SQLException e)
+ {
+ LOG.warn("Can't close statemnt", e);
+ }
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void commit() throws BackupException
+ {
+ try
+ {
+ jdbcConn.commit();
+ }
+ catch (SQLException e)
+ {
+ throw new BackupException(e);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void rollback() throws BackupException
+ {
+ try
+ {
+ jdbcConn.rollback();
+ }
+ catch (SQLException e)
+ {
+ throw new BackupException(e);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void close() throws BackupException
+ {
+ try
+ {
+ // in case for shared connection
+ if (!jdbcConn.isClosed())
+ {
+ jdbcConn.close();
+ }
+ }
+ catch (SQLException e)
+ {
+ throw new BackupException(e);
+ }
+ }
+
+ /**
+ * Restore table.
+ */
+ private void restoreTable(File storageDir, Connection jdbcConn, String tableName,
RestoreTableRule restoreRule)
+ throws IOException, SQLException
+ {
+ // Need privileges
+ SecurityManager security = System.getSecurityManager();
+ if (security != null)
+ {
+ security.checkPermission(JCRRuntimePermissions.MANAGE_REPOSITORY_PERMISSION);
+ }
+
+ ObjectZipReaderImpl contentReader = null;
+ ObjectZipReaderImpl contentLenReader = null;
+
+ PreparedStatement insertNode = null;
+ ResultSet tableMetaData = null;
+
+ int dialect = DialectDetecter.detect(jdbcConn.getMetaData()).hashCode();
+
+ // switch table name to lower case
+ if (dialect == DBBackup.DB_DIALECT_PGSQL)
+ {
+ tableName = tableName.toLowerCase();
+ }
+
+ try
+ {
+ contentReader = new
ObjectZipReaderImpl(PrivilegedFileHelper.zipInputStream(restoreRule.getContentFile()));
+ contentReader.getNextEntry();
+
+ contentLenReader =
+ new
ObjectZipReaderImpl(PrivilegedFileHelper.zipInputStream(restoreRule.getContentLenFile()));
+ contentLenReader.getNextEntry();
+
+ // get information about source table
+ int sourceColumnCount = contentReader.readInt();
+
+ List<Integer> columnType = new ArrayList<Integer>();
+ List<String> columnName = new ArrayList<String>();
+
+ for (int i = 0; i < sourceColumnCount; i++)
+ {
+ columnType.add(contentReader.readInt());
+ columnName.add(contentReader.readString());
+ }
+
+ int targetColumnCount = sourceColumnCount;
+ if (restoreRule.getDeleteColumnIndex() != null)
+ {
+ targetColumnCount--;
+ }
+ else if (restoreRule.getNewColumnIndex() != null)
+ {
+ targetColumnCount++;
+
+ columnType.add(restoreRule.getNewColumnIndex(),
restoreRule.getNewColumnType());
+
+ String newColumnName =
+ dialect == DBBackup.DB_DIALECT_PGSQL ?
restoreRule.getNewColumnName().toLowerCase() : restoreRule
+ .getNewColumnName();
+ columnName.add(restoreRule.getNewColumnIndex(), newColumnName);
+ }
+
+ // construct statement
+ String names = "";
+ String parameters = "";
+ for (int i = 0; i < targetColumnCount; i++)
+ {
+ if (restoreRule.getSkipColumnIndex() != null &&
restoreRule.getSkipColumnIndex() == i)
+ {
+ continue;
+ }
+ names += columnName.get(i) + (i == targetColumnCount - 1 ? "" :
",");
+ parameters += "?" + (i == targetColumnCount - 1 ? "" :
",");
+ }
+ insertNode =
+ jdbcConn.prepareStatement("INSERT INTO " + tableName + "
(" + names + ") VALUES(" + parameters + ")");
+
+ // set data
+ outer : while (true)
+ {
+ for (int i = 0, targetIndex = 0; i < columnType.size(); i++,
targetIndex++)
+ {
+ InputStream stream;
+ long len;
+
+ if (restoreRule.getNewColumnIndex() != null &&
restoreRule.getNewColumnIndex() == i)
+ {
+ stream =
+ new
ByteArrayInputStream(restoreRule.getDstContainerName().getBytes(Constants.DEFAULT_ENCODING));
+ len = ((ByteArrayInputStream)stream).available();
+ }
+ else
+ {
+ try
+ {
+ len = contentLenReader.readLong();
+ }
+ catch (EOFException e)
+ {
+ if (i == 0)
+ {
+ // content length file is empty check content file
+ try
+ {
+ contentReader.readByte();
+ }
+ catch (EOFException e1)
+ {
+ break outer;
+ }
+ }
+
+ throw new IOException("Content length file is empty but content
still present", e);
+ }
+ stream = len == -1 ? null : spoolInputStream(contentReader, len);
+ }
+
+ if (restoreRule.getSkipColumnIndex() != null &&
restoreRule.getSkipColumnIndex() == i)
+ {
+ targetIndex--;
+ continue;
+ }
+ else if (restoreRule.getDeleteColumnIndex() != null &&
restoreRule.getDeleteColumnIndex() == i)
+ {
+ targetIndex--;
+ continue;
+ }
+
+ // set
+ if (stream != null)
+ {
+ if (restoreRule.getConvertColumnIndex() != null &&
restoreRule.getConvertColumnIndex().contains(i))
+ {
+ // convert column value
+ ByteArrayInputStream ba = (ByteArrayInputStream)stream;
+ byte[] readBuffer = new byte[ba.available()];
+ ba.read(readBuffer);
+
+ String currentValue = new String(readBuffer,
Constants.DEFAULT_ENCODING);
+ if (currentValue.equals(Constants.ROOT_PARENT_UUID))
+ {
+ stream = new
ByteArrayInputStream(Constants.ROOT_PARENT_UUID.getBytes());
+ }
+ else
+ {
+ if (restoreRule.getDstMultiDb())
+ {
+ if (!restoreRule.getSrcMultiDb())
+ {
+ stream =
+ new ByteArrayInputStream(new String(readBuffer,
Constants.DEFAULT_ENCODING).substring(
+
restoreRule.getSrcContainerName().length()).getBytes());
+ }
+ }
+ else
+ {
+ if (restoreRule.getSrcMultiDb())
+ {
+ StringBuilder builder = new StringBuilder();
+ builder.append(restoreRule.getDstContainerName());
+ builder.append(currentValue);
+
+ stream = new
ByteArrayInputStream(builder.toString().getBytes());
+ }
+ else
+ {
+ StringBuilder builder = new StringBuilder();
+ builder.append(restoreRule.getDstContainerName());
+ builder.append(new String(readBuffer,
Constants.DEFAULT_ENCODING).substring(restoreRule
+ .getSrcContainerName().length()));
+
+ stream = new
ByteArrayInputStream(builder.toString().getBytes());
+ }
+ }
+ }
+
+ len = ((ByteArrayInputStream)stream).available();
+ }
+
+ if (columnType.get(i) == Types.INTEGER || columnType.get(i) ==
Types.BIGINT
+ || columnType.get(i) == Types.SMALLINT || columnType.get(i) ==
Types.TINYINT)
+ {
+ ByteArrayInputStream ba = (ByteArrayInputStream)stream;
+ byte[] readBuffer = new byte[ba.available()];
+ ba.read(readBuffer);
+
+ String value = new String(readBuffer, Constants.DEFAULT_ENCODING);
+ insertNode.setLong(targetIndex + 1, Integer.parseInt(value));
+ }
+ else if (columnType.get(i) == Types.BIT)
+ {
+ ByteArrayInputStream ba = (ByteArrayInputStream)stream;
+ byte[] readBuffer = new byte[ba.available()];
+ ba.read(readBuffer);
+
+ String value = new String(readBuffer);
+ if (dialect == DBBackup.DB_DIALECT_PGSQL)
+ {
+ insertNode.setBoolean(targetIndex + 1,
value.equals("t"));
+ }
+ else
+ {
+ insertNode.setBoolean(targetIndex + 1,
value.equals("1"));
+ }
+ }
+ else if (columnType.get(i) == Types.BOOLEAN)
+ {
+ ByteArrayInputStream ba = (ByteArrayInputStream)stream;
+ byte[] readBuffer = new byte[ba.available()];
+ ba.read(readBuffer);
+
+ String value = new String(readBuffer);
+ insertNode.setBoolean(targetIndex + 1,
value.equals("true"));
+ }
+ else if (columnType.get(i) == Types.VARBINARY || columnType.get(i) ==
Types.LONGVARBINARY
+ || columnType.get(i) == Types.BLOB || columnType.get(i) ==
Types.BINARY
+ || columnType.get(i) == Types.OTHER)
+ {
+ insertNode.setBinaryStream(targetIndex + 1, stream, (int)len);
+ }
+ else
+ {
+ byte[] readBuffer = new byte[(int)len];
+ stream.read(readBuffer);
+
+ insertNode.setString(targetIndex + 1, new String(readBuffer,
Constants.DEFAULT_ENCODING));
+ }
+ }
+ else
+ {
+ insertNode.setNull(targetIndex + 1, columnType.get(i));
+ }
+ }
+ insertNode.addBatch();
+ }
+
+ insertNode.executeBatch();
+ }
+ finally
+ {
+ if (contentReader != null)
+ {
+ contentReader.close();
+ }
+
+ if (contentLenReader != null)
+ {
+ contentLenReader.close();
+ }
+
+ if (insertNode != null)
+ {
+ insertNode.close();
+ }
+
+ // delete all temporary files
+ for (File file : spoolFileList)
+ {
+ if (!PrivilegedFileHelper.delete(file))
+ {
+ fileCleaner.addFile(file);
+ }
+ }
+
+ if (tableMetaData != null)
+ {
+ tableMetaData.close();
+ }
+ }
+ }
+
+ /**
+ * Spool input stream.
+ */
+ private InputStream spoolInputStream(ObjectReader in, long contentLen) throws
IOException
+ {
+ byte[] buffer = new byte[0];
+ byte[] tmpBuff;
+ long readLen = 0;
+ File sf = null;
+ OutputStream sfout = null;
+
+ try
+ {
+ while (true)
+ {
+ int needToRead = contentLen - readLen > 2048 ? 2048 : (int)(contentLen -
readLen);
+ tmpBuff = new byte[needToRead];
+
+ if (needToRead == 0)
+ {
+ break;
+ }
+
+ in.readFully(tmpBuff);
+
+ if (sfout != null)
+ {
+ sfout.write(tmpBuff);
+ }
+ else if (readLen + needToRead > maxBufferSize && fileCleaner !=
null)
+ {
+ sf = PrivilegedFileHelper.createTempFile("jcrvd", null,
tempDir);
+ sfout = PrivilegedFileHelper.fileOutputStream(sf);
+
+ sfout.write(buffer);
+ sfout.write(tmpBuff);
+ buffer = null;
+ }
+ else
+ {
+ // reallocate new buffer and spool old buffer contents
+ byte[] newBuffer = new byte[(int)(readLen + needToRead)];
+ System.arraycopy(buffer, 0, newBuffer, 0, (int)readLen);
+ System.arraycopy(tmpBuff, 0, newBuffer, (int)readLen, needToRead);
+ buffer = newBuffer;
+ }
+
+ readLen += needToRead;
+ }
+
+ if (buffer != null)
+ {
+ return new ByteArrayInputStream(buffer);
+ }
+ else
+ {
+ return PrivilegedFileHelper.fileInputStream(sf);
+ }
+ }
+ finally
+ {
+ if (sfout != null)
+ {
+ sfout.close();
+ }
+
+ if (sf != null)
+ {
+ spoolFileList.add(sf);
+ }
+ }
+ }
+}
+
+
Added:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/rdbms/DirectoryRestor.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/rdbms/DirectoryRestor.java
(rev 0)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/rdbms/DirectoryRestor.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2003-2010 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not,
see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.impl.backup.rdbms;
+
+import org.exoplatform.commons.utils.PrivilegedFileHelper;
+import org.exoplatform.commons.utils.PrivilegedSystemHelper;
+import org.exoplatform.services.jcr.impl.backup.BackupException;
+import org.exoplatform.services.jcr.impl.backup.DataRestor;
+import org.exoplatform.services.jcr.impl.util.io.DirectoryHelper;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:anatoliy.bazko@gmail.com">Anatoliy
Bazko</a>
+ * @version $Id: DirectoryRestorer.java 34360 2009-07-22 23:58:59Z tolusha $
+ */
+public class DirectoryRestor implements DataRestor
+{
+
+ /**
+ * Logger.
+ */
+ protected final static Log LOG =
ExoLogger.getLogger("exo.jcr.component.core.DirectoryRestorer");
+
+ /**
+ * The list of directories with actual data.
+ */
+ protected final List<File> dataDirs = new ArrayList<File>();
+
+ /**
+ * The list of directories with backuped data.
+ */
+ protected final List<File> backupDirs = new ArrayList<File>();
+
+ /**
+ * The list of temporary directories.
+ */
+ private final List<File> tmpDirs = new ArrayList<File>();
+
+ /**
+ * Java temporary directory.
+ */
+ protected final File tempDir = new
File(PrivilegedSystemHelper.getProperty("java.io.tmpdir"));
+
+ /**
+ * The prefix for temporary directories.
+ */
+ private static final String PREFIX = "fsrestorer";
+
+ /**
+ * Constructor DirectoryRestorer.
+ *
+ * @param dataDirs
+ * @param backupDirs
+ */
+ public DirectoryRestor(List<File> dataDirs, List<File> backupDirs)
+ {
+ this.dataDirs.addAll(dataDirs);
+ this.backupDirs.addAll(backupDirs);
+ }
+
+ /**
+ * Constructor DirectoryRestorer.
+ *
+ * @param dataDir
+ * @param backupDir
+ */
+ public DirectoryRestor(File dataDir, File backupDir)
+ {
+ this.dataDirs.add(dataDir);
+ this.backupDirs.add(backupDir);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void clean() throws BackupException
+ {
+ for (File dataDir : dataDirs)
+ {
+ try
+ {
+ File tmpDir = new File(tempDir, PREFIX + System.currentTimeMillis());
+ DirectoryHelper.copyDirectory(dataDir, tmpDir);
+
+ tmpDirs.add(tmpDir);
+
+ DirectoryHelper.removeDirectory(dataDir);
+ }
+ catch (IOException e)
+ {
+ throw new BackupException(e);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void restore() throws BackupException
+ {
+ for (int i = 0; i < backupDirs.size(); i++)
+ {
+ File backupDir = backupDirs.get(i);
+ File dataDir = dataDirs.get(i);
+
+ try
+ {
+ DirectoryHelper.uncompressDirectory(backupDir, dataDir);
+ }
+ catch (IOException e)
+ {
+ throw new BackupException(e);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void commit() throws BackupException
+ {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void rollback() throws BackupException
+ {
+ for (int i = 0; i < tmpDirs.size(); i++)
+ {
+ try
+ {
+ File tmpDir = tmpDirs.get(i);
+ File dataDir = dataDirs.get(i);
+
+ if (PrivilegedFileHelper.exists(dataDir))
+ {
+ DirectoryHelper.removeDirectory(dataDir);
+ }
+
+ DirectoryHelper.copyDirectory(tmpDir, dataDir);
+ }
+ catch (IOException e)
+ {
+ throw new BackupException(e);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void close() throws BackupException
+ {
+ for (File tmpDir : tmpDirs)
+ {
+ try
+ {
+ DirectoryHelper.removeDirectory(tmpDir);
+ }
+ catch (IOException e)
+ {
+ LOG.error("Can't remove temporary directory " +
PrivilegedFileHelper.getAbsolutePath(tmpDir), e);
+ }
+ }
+
+ dataDirs.clear();
+ backupDirs.clear();
+ tmpDirs.clear();
+ }
+}
Added:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/rdbms/RestoreTableRule.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/rdbms/RestoreTableRule.java
(rev 0)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/b/rdbms/RestoreTableRule.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2009 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.backup.rdbms;
+
+import java.io.File;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:anatoliy.bazko@gmail.com">Anatoliy
Bazko</a>
+ * @version $Id: RestoreTableRule.java 34360 2009-07-22 23:58:59Z tolusha $
+ */
+public class RestoreTableRule
+{
+ private File contentFile;
+
+ private File contentLenFile;
+
+ private Integer deleteColumnIndex = null;
+
+ private Integer skipColumnIndex = null;
+
+ private Integer newColumnIndex = null;
+
+ private String newColumnName = null;
+
+ private Integer newColumnType = null;
+
+ private Set<Integer> convertColumnIndex = new HashSet<Integer>();
+
+ private String srcContainerName = null;
+
+ private String dstContainerName = null;
+
+ private Boolean srcMultiDb = null;
+
+ private Boolean dstMultiDb = null;
+
+ public File getContentFile()
+ {
+ return contentFile;
+ }
+
+ public void setContentFile(File contentFile)
+ {
+ this.contentFile = contentFile;
+ }
+
+ public File getContentLenFile()
+ {
+ return contentLenFile;
+ }
+
+ public void setContentLenFile(File contentLenFile)
+ {
+ this.contentLenFile = contentLenFile;
+ }
+
+ public Integer getDeleteColumnIndex()
+ {
+ return deleteColumnIndex;
+ }
+
+ public void setDeleteColumnIndex(Integer deleteColumnIndex)
+ {
+ this.deleteColumnIndex = deleteColumnIndex;
+ }
+
+ public Integer getSkipColumnIndex()
+ {
+ return skipColumnIndex;
+ }
+
+ public void setSkipColumnIndex(Integer skipColumnIndex)
+ {
+ this.skipColumnIndex = skipColumnIndex;
+ }
+
+ public Integer getNewColumnIndex()
+ {
+ return newColumnIndex;
+ }
+
+ public void setNewColumnIndex(Integer newColumnIndex)
+ {
+ this.newColumnIndex = newColumnIndex;
+ }
+
+ public Set<Integer> getConvertColumnIndex()
+ {
+ return convertColumnIndex;
+ }
+
+ public void setConvertColumnIndex(Set<Integer> convertColumnIndex)
+ {
+ this.convertColumnIndex = convertColumnIndex;
+ }
+
+ public String getSrcContainerName()
+ {
+ return srcContainerName;
+ }
+
+ public void setSrcContainerName(String srcContainerName)
+ {
+ this.srcContainerName = srcContainerName;
+ }
+
+ public String getDstContainerName()
+ {
+ return dstContainerName;
+ }
+
+ public void setDstContainerName(String dstContainerName)
+ {
+ this.dstContainerName = dstContainerName;
+ }
+
+ public Boolean getSrcMultiDb()
+ {
+ return srcMultiDb;
+ }
+
+ public void setSrcMultiDb(Boolean srcMultiDb)
+ {
+ this.srcMultiDb = srcMultiDb;
+ }
+
+ public Boolean getDstMultiDb()
+ {
+ return dstMultiDb;
+ }
+
+ public void setDstMultiDb(Boolean dstMultiDb)
+ {
+ this.dstMultiDb = dstMultiDb;
+ }
+
+ public String getNewColumnName()
+ {
+ return newColumnName;
+ }
+
+ public void setNewColumnName(String newColumnName)
+ {
+ this.newColumnName = newColumnName;
+ }
+
+ public Integer getNewColumnType()
+ {
+ return newColumnType;
+ }
+
+ public void setNewColumnType(Integer newColumnType)
+ {
+ this.newColumnType = newColumnType;
+ }
+
+}
Added:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/clean/rdbms/DBClean.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/clean/rdbms/DBClean.java
(rev 0)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/clean/rdbms/DBClean.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2003-2010 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not,
see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.impl.clean.rdbms;
+
+import org.exoplatform.commons.utils.SecurityHelper;
+import org.exoplatform.services.jcr.core.security.JCRRuntimePermissions;
+import org.exoplatform.services.jcr.impl.util.jdbc.DBInitializer;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+
+import java.security.PrivilegedExceptionAction;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * The goal of this class is removing workspace data from database.
+ *
+ * @author <a href="karpenko.sergiy(a)gmail.com">Karpenko Sergiy</a>
+ * @version $Id: DBClean.java 3769 2011-01-04 15:36:06Z areshetnyak $
+ */
+public class DBClean
+{
+ /**
+ * Logger.
+ */
+ protected final static Log LOG =
ExoLogger.getLogger("exo.jcr.component.core.DBClean");
+
+ /**
+ * Connection to database.
+ */
+ protected final Connection connection;
+
+ /**
+ * Pattern for JCR tables.
+ */
+ protected final Pattern dbObjectNamePattern;
+
+ /**
+ * Common clean scripts for database.
+ */
+ protected final List<String> cleanScripts = new ArrayList<String>();
+
+ /**
+ * DB clean helper.
+ */
+ protected final DBCleanHelper dbCleanHelper;
+
+ /**
+ * WorkspaceDBCleaner constructor.
+ *
+ * @param containerName
+ * container name (workspace name)
+ * @param connection
+ * connection to database where workspace tables is placed
+ */
+ public DBClean(Connection connection, List<String> cleanScripts)
+ {
+ this(connection, cleanScripts, null);
+ }
+
+ /**
+ * WorkspaceDBCleaner constructor.
+ *
+ * @param containerName
+ * container name (workspace name)
+ * @param connection
+ * connection to database where workspace tables is placed
+ * @param dbCleanHelper
+ */
+ public DBClean(Connection connection, List<String> cleanScripts, DBCleanHelper
dbCleanHelper)
+ {
+ this.dbObjectNamePattern = Pattern.compile(DBInitializer.SQL_OBJECTNAME,
Pattern.CASE_INSENSITIVE);
+ this.connection = connection;
+ this.cleanScripts.addAll(cleanScripts);
+ this.dbCleanHelper = dbCleanHelper;
+ }
+
+ /**
+ * Clean data from database. The method doesn't close connection or perform
commit.
+ *
+ * @throws SQLException
+ * if any errors occurred
+ */
+ public void clean() throws SQLException
+ {
+ SecurityManager security = System.getSecurityManager();
+ if (security != null)
+ {
+ security.checkPermission(JCRRuntimePermissions.MANAGE_REPOSITORY_PERMISSION);
+ }
+
+ String sql = null;
+ Statement st = null;
+ try
+ {
+ st = connection.createStatement();
+ for (String scr : cleanScripts)
+ {
+ String s = cleanWhitespaces(scr.trim());
+ if (s.length() > 0)
+ {
+ if (!canExecuteQuery(sql = s))
+ {
+ // table from query not found, so try drop other
+ continue;
+ }
+
+ if (LOG.isDebugEnabled())
+ {
+ LOG.debug("Execute script: \n[" + sql + "]");
+ }
+ executeQuery(st, sql);
+ }
+ }
+
+ if (dbCleanHelper != null)
+ {
+ dbCleanHelper.clean();
+ }
+ }
+ finally
+ {
+ if (st != null)
+ {
+ try
+ {
+ st.close();
+ }
+ catch (SQLException e)
+ {
+ LOG.error("Can't close the Statement." + e);
+ }
+ }
+ }
+ }
+
+ /**
+ * Check if we can execute query.
+ * If tables used in query does not exists, we can not execute query.
+ */
+ protected boolean canExecuteQuery(String sql) throws SQLException
+ {
+ Matcher tMatcher = dbObjectNamePattern.matcher(sql);
+ while (tMatcher.find())
+ {
+ // get table name
+ String tableName = sql.substring(tMatcher.start(), tMatcher.end());
+ if (!isTableExists(connection, tableName))
+ {
+ LOG.warn("Table [" + tableName + "] from query [" + sql +
"] was not found. So query will not be executed.");
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Execute query.
+ */
+ protected void executeQuery(final Statement statement, final String sql) throws
SQLException
+ {
+ SecurityHelper.doPrivilegedSQLExceptionAction(new
PrivilegedExceptionAction<Object>()
+ {
+ public Object run() throws Exception
+ {
+ statement.executeUpdate(sql);
+ return null;
+ }
+ });
+ }
+
+ /**
+ * Indicates if table exists or not.
+ */
+ protected boolean isTableExists(Connection conn, String tableName) throws
SQLException
+ {
+ ResultSet trs = conn.getMetaData().getTables(null, null, tableName, null);
+ try
+ {
+ boolean res = false;
+ while (trs.next())
+ {
+ res = true; // check for columns/table type matching etc.
+ }
+ return res;
+ }
+ finally
+ {
+ try
+ {
+ trs.close();
+ }
+ catch (SQLException e)
+ {
+ LOG.error("Can't close the ResultSet: " + e);
+ }
+ }
+ }
+
+ /**
+ * Cleans redundant whitespaces from query.
+ */
+ private String cleanWhitespaces(String string)
+ {
+ if (string != null)
+ {
+ char[] cc = string.toCharArray();
+ for (int ci = cc.length - 1; ci > 0; ci--)
+ {
+ if (Character.isWhitespace(cc[ci]))
+ {
+ cc[ci] = ' ';
+ }
+ }
+ return new String(cc);
+ }
+ return string;
+ }
+}
Added:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/clean/rdbms/DBCleanHelper.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/clean/rdbms/DBCleanHelper.java
(rev 0)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/clean/rdbms/DBCleanHelper.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2003-2010 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not,
see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.impl.clean.rdbms;
+
+import org.exoplatform.commons.utils.SecurityHelper;
+import org.exoplatform.services.jcr.impl.Constants;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+
+import java.security.PrivilegedExceptionAction;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+/**
+ *
+ * Created by The eXo Platform SAS.
+ *
+ * Date: 21.01.2011
+ *
+ * @author <a href="mailto:anatoliy.bazko@exoplatform.com.ua">Anatoliy
Bazko</a>
+ * @version $Id: DBCleanHelper.java.java 34360 2010-11-11 11:11:11Z tolusha $
+ */
+public class DBCleanHelper
+{
+
+ /**
+ * Logger.
+ */
+ protected final static Log LOG =
ExoLogger.getLogger("exo.jcr.component.core.DBCleanHelper");
+
+ /**
+ * Select items query.
+ */
+ private final String selectItems;
+
+ /**
+ * Remove items query.
+ */
+ private final String removeItems;
+
+ /**
+ * Connection to database.
+ */
+ protected final Connection connection;
+
+ /**
+ * DBCleanerHelper constructor.
+ */
+ public DBCleanHelper(Connection connection, String selectItemds, String removeItems)
+ {
+ this.connection = connection;
+ this.selectItems = selectItemds;
+ this.removeItems = removeItems;
+ }
+
+ /**
+ * Removing rows from table. Some database do not support cascade delete,
+ * or need special sittings. In such case will be used deleting like
+ * visitor does. First traverse to the bottom of the tree and then go up to the root
+ * and perform deleting children.
+ *
+ * @throws SQLException
+ * SQL exception.
+ */
+ public void clean() throws SQLException
+ {
+ recursiveClean(Constants.ROOT_PARENT_UUID);
+ }
+
+ private void recursiveClean(String parentID) throws SQLException
+ {
+ PreparedStatement selectStatement = null;
+ PreparedStatement removeStatement = null;
+ ResultSet result = null;
+
+ try
+ {
+ selectStatement = connection.prepareStatement(this.selectItems);
+ selectStatement.setString(1, parentID);
+
+ final PreparedStatement fSelectStatement = selectStatement;
+ result = (ResultSet)SecurityHelper.doPrivilegedSQLExceptionAction(new
PrivilegedExceptionAction<Object>()
+ {
+ public Object run() throws Exception
+ {
+ return fSelectStatement.executeQuery();
+ }
+ });
+
+ // recursive traversing to the bottom of the tree
+ if (result.next())
+ {
+ do
+ {
+ recursiveClean(result.getString(1));
+ }
+ while (result.next());
+
+ // go up to the root and remove all nodes
+ removeStatement = connection.prepareStatement(this.removeItems);
+ removeStatement.setString(1, parentID);
+
+ final PreparedStatement fRemoveStatement = removeStatement;
+ SecurityHelper.doPrivilegedSQLExceptionAction(new
PrivilegedExceptionAction<Object>()
+ {
+ public Object run() throws Exception
+ {
+ fRemoveStatement.executeUpdate();
+ return null;
+ }
+ });
+ }
+ }
+ finally
+ {
+ if (selectStatement != null)
+ {
+ selectStatement.close();
+ }
+
+ if (removeStatement != null)
+ {
+ removeStatement.close();
+ }
+
+ if (result != null)
+ {
+ result.close();
+ }
+ }
+ }
+}
Added:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/clean/rdbms/DBCleanService.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/clean/rdbms/DBCleanService.java
(rev 0)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/clean/rdbms/DBCleanService.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2003-2010 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not,
see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.impl.clean.rdbms;
+
+import org.exoplatform.commons.utils.SecurityHelper;
+import org.exoplatform.services.jcr.config.RepositoryConfigurationException;
+import org.exoplatform.services.jcr.config.RepositoryEntry;
+import org.exoplatform.services.jcr.config.WorkspaceEntry;
+import org.exoplatform.services.jcr.impl.Constants;
+import org.exoplatform.services.jcr.impl.storage.jdbc.DBConstants;
+import org.exoplatform.services.jcr.impl.storage.jdbc.DialectDetecter;
+import org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer;
+
+import java.security.PrivilegedExceptionAction;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.naming.InitialContext;
+import javax.naming.NameNotFoundException;
+import javax.naming.NamingException;
+import javax.sql.DataSource;
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * Date: 24 01 2011
+ *
+ * @author <a href="mailto:anatoliy.bazko@exoplatform.com.ua">Anatoliy
Bazko</a>
+ * @version $Id: DBCleanService.java 34360 2010-11-11 11:11:11Z tolusha $
+ */
+public class DBCleanService
+{
+ /**
+ * Cleans workspace data from database.
+ *
+ * @param wsEntry
+ * workspace configuration
+ * @throws RepositoryConfigurationException
+ * @throws NamingException
+ * @throws SQLException
+ */
+ public static void cleanWorkspaceData(WorkspaceEntry wsEntry) throws
RepositoryConfigurationException,
+ NamingException, SQLException
+ {
+ String dsName =
wsEntry.getContainer().getParameterValue(JDBCWorkspaceDataContainer.SOURCE_NAME);
+
+ final DataSource ds = (DataSource)new InitialContext().lookup(dsName);
+ if (ds == null)
+ {
+ throw new NameNotFoundException("Data source " + dsName + " not
found");
+ }
+
+ Connection jdbcConn = SecurityHelper.doPrivilegedSQLExceptionAction(new
PrivilegedExceptionAction<Connection>()
+ {
+ public Connection run() throws Exception
+ {
+ return ds.getConnection();
+
+ }
+ });
+ jdbcConn.setAutoCommit(false);
+
+ try
+ {
+ getDBCleaner(jdbcConn, wsEntry).clean();
+ jdbcConn.commit();
+ }
+ catch (SQLException e)
+ {
+ jdbcConn.rollback();
+ }
+ finally
+ {
+ jdbcConn.close();
+ }
+ }
+
+ /**
+ * Cleans repository data from database.
+ *
+ * @param rEntry
+ * the repository configuration
+ * @throws RepositoryConfigurationException
+ * @throws NamingException
+ * @throws SQLException
+ */
+ public static void cleanRepositoryData(RepositoryEntry rEntry) throws
RepositoryConfigurationException,
+ NamingException, SQLException
+ {
+ for (WorkspaceEntry wsEntry : rEntry.getWorkspaceEntries())
+ {
+ cleanWorkspaceData(wsEntry);
+ }
+ }
+
+ /**
+ * Returns database cleaner for manual cleaning.
+ *
+ * @param jdbcConn
+ * database connection which need to use
+ * @param wsEntry
+ * workspace configuration
+ * @return
+ * @throws SQLException
+ * @throws RepositoryConfigurationException
+ */
+ public static DBClean getDBCleaner(Connection jdbcConn, WorkspaceEntry wsEntry) throws
SQLException,
+ RepositoryConfigurationException
+ {
+ boolean multiDb =
+
Boolean.parseBoolean(wsEntry.getContainer().getParameterValue(JDBCWorkspaceDataContainer.MULTIDB));
+
+ String containerName = wsEntry.getName();
+
+ String dialect = DialectDetecter.detect(jdbcConn.getMetaData());
+
+ List<String> cleanScripts = new ArrayList<String>();
+ if (multiDb)
+ {
+ cleanScripts.add("delete from JCR_MVALUE");
+ cleanScripts.add("delete from JCR_MREF");
+
+ if (dialect.equals(DBConstants.DB_DIALECT_HSQLDB))
+ {
+ cleanScripts.add("delete from JCR_MITEM where I_CLASS=2");
+
+ String selectItems = "select ID from JCR_MITEM where I_CLASS=1 and
PARENT_ID=?";
+ String deleteItems = "delete from JCR_MITEM where I_CLASS=1 and
PARENT_ID=?";
+
+ return new DBClean(jdbcConn, cleanScripts, new DBCleanHelper(jdbcConn,
selectItems, deleteItems));
+ }
+
+ cleanScripts.add("delete from JCR_MITEM where JCR_MITEM.name <>
'" + Constants.ROOT_PARENT_NAME + "'");
+ }
+ else
+ {
+ cleanScripts
+ .add("delete from JCR_SVALUE where exists(select * from JCR_SITEM where
JCR_SITEM.ID=JCR_SVALUE.PROPERTY_ID and JCR_SITEM.CONTAINER_NAME='"
+ + containerName + "')");
+ cleanScripts
+ .add("delete from JCR_SREF where exists(select * from JCR_SITEM where
JCR_SITEM.ID=JCR_SREF.PROPERTY_ID and JCR_SITEM.CONTAINER_NAME='"
+ + containerName + "')");
+
+ if (dialect.equals(DBConstants.DB_DIALECT_HSQLDB))
+ {
+ cleanScripts.add("delete from JCR_SITEM where I_CLASS=2 and
CONTAINER_NAME='" + containerName + "'");
+
+ String selectItems =
+ "select ID from JCR_SITEM where I_CLASS=1 and
CONTAINER_NAME='" + containerName + "' and PARENT_ID=?";
+ String deleteItems =
+ "delete from JCR_SITEM where I_CLASS=1 and CONTAINER_NAME='"
+ containerName + "' and PARENT_ID=?";
+
+ return new DBClean(jdbcConn, cleanScripts, new DBCleanHelper(jdbcConn,
selectItems, deleteItems));
+ }
+
+ cleanScripts.add("delete from JCR_SITEM where CONTAINER_NAME='" +
containerName + "'");
+ }
+
+ if (dialect.equals(DBConstants.DB_DIALECT_PGSQL))
+ {
+ return new PgSQLDBClean(jdbcConn, cleanScripts);
+ }
+ else if (dialect.equals(DBConstants.DB_DIALECT_INGRES))
+ {
+ return new IngresSQLDBClean(jdbcConn, cleanScripts);
+ }
+ else if (dialect.equals(DBConstants.DB_DIALECT_ORACLE) ||
dialect.equals(DBConstants.DB_DIALECT_ORACLEOCI))
+ {
+ return new OracleDBClean(jdbcConn, cleanScripts);
+ }
+ else
+ {
+ return new DBClean(jdbcConn, cleanScripts);
+ }
+ }
+}
Added:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/clean/rdbms/IngresSQLDBClean.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/clean/rdbms/IngresSQLDBClean.java
(rev 0)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/clean/rdbms/IngresSQLDBClean.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2003-2010 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not,
see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.impl.clean.rdbms;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.List;
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * <br/>Date:
+ *
+ * @author <a href="karpenko.sergiy(a)gmail.com">Karpenko Sergiy</a>
+ * @version $Id: IngresSQLDBClean.java 3655 2010-12-10 08:25:41Z tolusha $
+ */
+public class IngresSQLDBClean extends DBClean
+{
+
+ /**
+ * IngresSQLDBClean constructor.
+ */
+ public IngresSQLDBClean(Connection connection, List<String> cleanScripts)
+ {
+ super(connection, cleanScripts);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected boolean isTableExists(Connection conn, String tableName) throws
SQLException
+ {
+ return super.isTableExists(conn, tableName.toLowerCase());
+ }
+}
Added:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/clean/rdbms/OracleDBClean.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/clean/rdbms/OracleDBClean.java
(rev 0)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/clean/rdbms/OracleDBClean.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2003-2010 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not,
see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.impl.clean.rdbms;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.List;
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * <br/>Date:
+ *
+ * @author <a href="karpenko.sergiy(a)gmail.com">Karpenko Sergiy</a>
+ * @version $Id: OracleDBClean.java 3655 2010-12-10 08:25:41Z tolusha $
+ */
+public class OracleDBClean extends DBClean
+{
+
+ /**
+ * PgSQLDBClean constructor.
+ */
+ public OracleDBClean(Connection connection, List<String> cleanScripts)
+ {
+ super(connection, cleanScripts);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected boolean isTableExists(Connection conn, String tableName) throws
SQLException
+ {
+ Statement st = null;
+ try
+ {
+ st = conn.createStatement();
+ st.executeUpdate("SELECT 1 FROM " + tableName);
+ return true;
+ }
+ catch (SQLException e)
+ {
+ // check: ORA-00942: table or view does not exist
+ if (e.getMessage().indexOf("ORA-00942") >= 0)
+ return false;
+ throw e;
+ }
+ finally
+ {
+ if (st != null)
+ {
+ try
+ {
+ st.close();
+ }
+ catch (SQLException e)
+ {
+ LOG.error("Can't close the Statement: " + e);
+ }
+ }
+ }
+ }
+}
Added:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/clean/rdbms/PgSQLDBClean.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/clean/rdbms/PgSQLDBClean.java
(rev 0)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/clean/rdbms/PgSQLDBClean.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2003-2010 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not,
see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.impl.clean.rdbms;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.List;
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * <br/>Date:
+ *
+ * @author <a href="karpenko.sergiy(a)gmail.com">Karpenko Sergiy</a>
+ * @version $Id: PgSQLDBClean.java 3655 2010-12-10 08:25:41Z tolusha $
+ */
+public class PgSQLDBClean extends DBClean
+{
+
+ /**
+ * PgSQLDBClean constructor.
+ */
+ public PgSQLDBClean(Connection connection, List<String> cleanScripts)
+ {
+ super(connection, cleanScripts);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected boolean isTableExists(Connection conn, String tableName) throws
SQLException
+ {
+ return super.isTableExists(conn, tableName.toLowerCase());
+ }
+}
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/BackupWorkspaceInitializer.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/BackupWorkspaceInitializer.java 2011-01-26
15:23:23 UTC (rev 3889)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/BackupWorkspaceInitializer.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -23,42 +23,19 @@
import org.exoplatform.services.jcr.config.RepositoryConfigurationException;
import org.exoplatform.services.jcr.config.RepositoryEntry;
import org.exoplatform.services.jcr.config.WorkspaceEntry;
-import org.exoplatform.services.jcr.dataflow.ChangesLogIterator;
-import org.exoplatform.services.jcr.dataflow.ItemState;
import org.exoplatform.services.jcr.dataflow.PlainChangesLog;
-import org.exoplatform.services.jcr.dataflow.PlainChangesLogImpl;
import org.exoplatform.services.jcr.dataflow.TransactionChangesLog;
-import org.exoplatform.services.jcr.dataflow.persistent.PersistedPropertyData;
import org.exoplatform.services.jcr.datamodel.IllegalNameException;
-import org.exoplatform.services.jcr.datamodel.ItemData;
import org.exoplatform.services.jcr.datamodel.NodeData;
-import org.exoplatform.services.jcr.datamodel.ValueData;
import org.exoplatform.services.jcr.impl.Constants;
+import org.exoplatform.services.jcr.impl.backup.JCRRestor;
import org.exoplatform.services.jcr.impl.core.nodetype.NodeTypeManagerImpl;
import org.exoplatform.services.jcr.impl.core.value.ValueFactoryImpl;
import
org.exoplatform.services.jcr.impl.dataflow.persistent.CacheableWorkspaceDataManager;
-import org.exoplatform.services.jcr.impl.dataflow.persistent.StreamPersistedValueData;
-import org.exoplatform.services.jcr.impl.storage.JCRInvalidItemStateException;
-import org.exoplatform.services.jcr.impl.storage.JCRItemExistsException;
-import org.exoplatform.services.jcr.impl.util.io.FileCleaner;
import org.exoplatform.services.jcr.impl.util.io.FileCleanerHolder;
-import org.exoplatform.services.jcr.impl.util.io.SpoolFile;
-import org.exoplatform.services.jcr.observation.ExtendedEvent;
-import java.io.EOFException;
-import java.io.Externalizable;
import java.io.File;
-import java.io.FileFilter;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutput;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
@@ -78,15 +55,15 @@
public BackupWorkspaceInitializer(WorkspaceEntry config, RepositoryEntry repConfig,
CacheableWorkspaceDataManager dataManager, NamespaceRegistryImpl
namespaceRegistry,
LocationFactory locationFactory, NodeTypeManagerImpl nodeTypeManager,
ValueFactoryImpl valueFactory,
- AccessManager accessManager, FileCleanerHolder cleanerHolder) throws
RepositoryConfigurationException,
- PathNotFoundException, RepositoryException
+ AccessManager accessManager, FileCleanerHolder cleanerHolder) throws
RepositoryConfigurationException,
+ PathNotFoundException, RepositoryException
{
super(config, repConfig, dataManager, namespaceRegistry, locationFactory,
nodeTypeManager, valueFactory,
accessManager, cleanerHolder);
restoreDir = restorePath;
- String fullBackupPath = getFullBackupPath();
+ String fullBackupPath =
PrivilegedFileHelper.getAbsolutePath(JCRRestor.getFullBackupFile(new File(restoreDir)));
if (fullBackupPath == null)
{
@@ -120,7 +97,11 @@
dataManager.save(tLog);
// restore from incremental backup
- incrementalRead();
+ JCRRestor restorer = new JCRRestor(dataManager, fileCleaner);
+ for (File incrBackupFile : JCRRestor.getIncrementalFiles(new File(restoreDir)))
+ {
+ restorer.incrementalRestore(incrBackupFile);
+ }
final NodeData root = (NodeData)dataManager.getItemData(Constants.ROOT_UUID);
@@ -145,367 +126,9 @@
{
throw new RepositoryException(e);
}
- }
-
- protected void incrementalRead() throws RepositoryException
- {
- try
- {
- for (File incrBackupFile : getIncrementalFiles())
- {
- incrementalRestore(incrBackupFile);
- }
- }
- catch (FileNotFoundException e)
- {
- throw new RepositoryException("Restore of incremental backup file error
" + e, e);
- }
- catch (IOException e)
- {
- throw new RepositoryException("Restore of incremental backup file I/O error
" + e, e);
- }
catch (ClassNotFoundException e)
{
- throw new RepositoryException("Restore of incremental backup error " +
e, e);
+ throw new RepositoryException(e);
}
}
-
- private void incrementalRestore(File incrementalBackupFile) throws
FileNotFoundException, IOException,
- ClassNotFoundException, RepositoryException
- {
- ObjectInputStream ois = null;
- try
- {
- ois = new
ObjectInputStream(PrivilegedFileHelper.fileInputStream(incrementalBackupFile));
-
- while (true)
- {
- TransactionChangesLog changesLog = readExternal(ois);
-
changesLog.setSystemId(Constants.JCR_CORE_RESTORE_WORKSPACE_INITIALIZER_SYSTEM_ID); //
mark changes
-
- ChangesLogIterator cli = changesLog.getLogIterator();
- while (cli.hasNextLog())
- {
- if (cli.nextLog().getEventType() == ExtendedEvent.LOCK)
- cli.removeLog();
- }
-
- saveChangesLog(changesLog);
- }
- }
- catch (EOFException ioe)
- {
- // ok - reading all data from backup file;
- }
- }
-
- private void saveChangesLog(TransactionChangesLog changesLog) throws
RepositoryException
- {
- try
- {
- dataManager.save(changesLog);
- }
- catch (JCRInvalidItemStateException e)
- {
- TransactionChangesLog normalizeChangesLog =
- getNormalizedChangesLog(e.getIdentifier(), e.getState(), changesLog);
- if (normalizeChangesLog != null)
- saveChangesLog(normalizeChangesLog);
- else
- throw new RepositoryException(
- "Collisions found during save of restore changes log, but caused item
is not found by ID "
- + e.getIdentifier() + ". " + e, e);
- }
- catch (JCRItemExistsException e)
- {
- TransactionChangesLog normalizeChangesLog =
- getNormalizedChangesLog(e.getIdentifier(), e.getState(), changesLog);
- if (normalizeChangesLog != null)
- saveChangesLog(normalizeChangesLog);
- else
- throw new RepositoryException(
- "Collisions found during save of restore changes log, but caused item
is not found by ID "
- + e.getIdentifier() + ". " + e, e);
- }
-
- }
-
- private TransactionChangesLog getNormalizedChangesLog(String collisionID, int state,
TransactionChangesLog changesLog)
- {
- ItemState citem = changesLog.getItemState(collisionID);
-
- if (citem != null)
- {
-
- TransactionChangesLog result = new TransactionChangesLog();
- result.setSystemId(changesLog.getSystemId());
-
- ChangesLogIterator cli = changesLog.getLogIterator();
- while (cli.hasNextLog())
- {
- ArrayList<ItemState> normalized = new ArrayList<ItemState>();
- PlainChangesLog next = cli.nextLog();
- for (ItemState change : next.getAllStates())
- {
- if (state == change.getState())
- {
- ItemData item = change.getData();
- // targeted state
- if (citem.isNode())
- {
- // Node... by ID and desc path
- if (!item.getIdentifier().equals(collisionID)
- &&
!item.getQPath().isDescendantOf(citem.getData().getQPath()))
- normalized.add(change);
- }
- else if (!item.getIdentifier().equals(collisionID))
- {
- // Property... by ID
- normalized.add(change);
- }
- }
- else
- // another state
- normalized.add(change);
- }
-
- PlainChangesLog plog = new PlainChangesLogImpl(normalized,
next.getSessionId(), next.getEventType());
- result.addLog(plog);
- }
-
- return result;
- }
-
- return null;
- }
-
- private List<File> getIncrementalFiles()
- {
- ArrayList<File> list = new ArrayList<File>();
-
- File rDir = new File(restoreDir);
- Pattern fullBackupPattern = Pattern.compile(".+\\.0");
-
- for (File f : PrivilegedFileHelper.listFiles(rDir, new BackupFilesFilter()))
- {
- if (fullBackupPattern.matcher(f.getName()).matches() == false)
- {
- list.add(f);
- }
- }
-
- return list;
- }
-
- class BackupFilesFilter implements FileFilter
- {
- public boolean accept(File pathname)
- {
- Pattern p = Pattern.compile(".+\\.[0-9]+");
- Matcher m = p.matcher(pathname.getName());
- return m.matches();
- }
- }
-
- private String getFullBackupPath()
- {
- File rDir = new File(restoreDir);
- Pattern p = Pattern.compile(".+\\.0");
-
- for (File f : PrivilegedFileHelper.listFiles(rDir, new BackupFilesFilter()))
- {
- Matcher m = p.matcher(f.getName());
- if (m.matches())
- {
- return PrivilegedFileHelper.getAbsolutePath(f);
- }
- }
-
- return null;
- }
-
- private TransactionChangesLog readExternal(ObjectInputStream in) throws IOException,
ClassNotFoundException
- {
- int changesLogType = in.readInt();
-
- TransactionChangesLog transactionChangesLog = null;
-
- if (changesLogType == RestoreChangesLog.Type.ItemDataChangesLog_with_Streams)
- {
-
- // read ChangesLog
- transactionChangesLog = (TransactionChangesLog)in.readObject();
-
- // read FixupStream count
- int iFixupStream = in.readInt();
-
- ArrayList<FixupStream> listFixupStreams = new
ArrayList<FixupStream>();
-
- for (int i = 0; i < iFixupStream; i++)
- {
- FixupStream fs = new FixupStream();
- fs.readExternal(in);
- listFixupStreams.add(fs);
- }
-
- // read stream data
- int iStreamCount = in.readInt();
- ArrayList<File> listFiles = new ArrayList<File>();
-
- for (int i = 0; i < iStreamCount; i++)
- {
-
- // read file size
- long fileSize = in.readLong();
-
- // read content file
- File contentFile = getAsFile(in, fileSize);
- listFiles.add(contentFile);
- }
-
- RestoreChangesLog restoreChangesLog =
- new RestoreChangesLog(transactionChangesLog, listFixupStreams, listFiles,
fileCleaner);
-
- restoreChangesLog.restore();
-
- }
- else if (changesLogType ==
RestoreChangesLog.Type.ItemDataChangesLog_without_Streams)
- {
- transactionChangesLog = (TransactionChangesLog)in.readObject();
- }
-
- return transactionChangesLog;
- }
-
- private File getAsFile(ObjectInputStream ois, long fileSize) throws IOException
- {
- int bufferSize = 1024 * 8;
- byte[] buf = new byte[bufferSize];
-
- File tempFile = SpoolFile.createTempFile("vdincb" +
System.currentTimeMillis(), ".stmp", tempDir);
- FileOutputStream fos = PrivilegedFileHelper.fileOutputStream(tempFile);
- long readBytes = fileSize;
-
- while (readBytes > 0)
- {
- // long longTemp = readByte - bufferSize;
- if (readBytes >= bufferSize)
- {
- ois.readFully(buf);
- fos.write(buf);
- }
- else if (readBytes < bufferSize)
- {
- ois.readFully(buf, 0, (int)readBytes);
- fos.write(buf, 0, (int)readBytes);
- }
- readBytes -= bufferSize;
- }
-
- fos.flush();
- fos.close();
-
- return tempFile;
- }
-
- class RestoreChangesLog
- {
- public class Type
- {
- public static final int ItemDataChangesLog_without_Streams = 1;
-
- public static final int ItemDataChangesLog_with_Streams = 2;
- }
-
- private TransactionChangesLog itemDataChangesLog;
-
- private List<FixupStream> listFixupStream;
-
- private List<File> listFile;
-
- private FileCleaner fileCleaner;
-
- public RestoreChangesLog(TransactionChangesLog transactionChangesLog,
List<FixupStream> listFixupStreams,
- List<File> listFiles, FileCleaner fileCleaner)
- {
- this.itemDataChangesLog = transactionChangesLog;
- this.listFixupStream = listFixupStreams;
- this.listFile = listFiles;
- this.fileCleaner = fileCleaner;
- }
-
- public TransactionChangesLog getItemDataChangesLog()
- {
- return itemDataChangesLog;
- }
-
- public void restore() throws IOException
- {
- List<ItemState> listItemState = itemDataChangesLog.getAllStates();
- for (int i = 0; i < this.listFixupStream.size(); i++)
- {
- ItemState itemState =
listItemState.get(listFixupStream.get(i).getItemSateId());
- ItemData itemData = itemState.getData();
-
- PersistedPropertyData propertyData = (PersistedPropertyData)itemData;
- ValueData vd =
(propertyData.getValues().get(listFixupStream.get(i).getValueDataId()));
-
- // re-init the value
- propertyData.getValues().set(listFixupStream.get(i).getValueDataId(),
- new StreamPersistedValueData(vd.getOrderNumber(), new
SpoolFile(listFile.get(i).getAbsolutePath())));
- }
-
- for (int i = 0; i < listFile.size(); i++)
- fileCleaner.addFile(listFile.get(i));
- }
- }
-
- class FixupStream implements Externalizable
- {
- int iItemStateId = -1;
-
- int iValueDataId = -1;
-
- public FixupStream()
- {
- }
-
- public FixupStream(int itemState_, int valueData_)
- {
- iItemStateId = itemState_;
- iValueDataId = valueData_;
- }
-
- public int getItemSateId()
- {
- return iItemStateId;
- }
-
- public int getValueDataId()
- {
- return iValueDataId;
- }
-
- public boolean compare(FixupStream fs)
- {
- boolean b = true;
- if (fs.getItemSateId() != this.getItemSateId())
- b = false;
- if (fs.getValueDataId() != this.getValueDataId())
- b = false;
- return b;
- }
-
- public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException
- {
- iItemStateId = in.readInt();
- iValueDataId = in.readInt();
- }
-
- public void writeExternal(ObjectOutput out) throws IOException
- {
- out.writeInt(iItemStateId);
- out.writeInt(iValueDataId);
- }
- }
}
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/RepositoryImpl.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/RepositoryImpl.java 2011-01-26
15:23:23 UTC (rev 3889)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/RepositoryImpl.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -456,21 +456,17 @@
security.checkPermission(JCRRuntimePermissions.MANAGE_REPOSITORY_PERMISSION);
}
- WorkspaceContainer workspaceContainer = null;
- if (isWorkspaceInitialized(workspaceName))
+ WorkspaceContainer workspaceContainer =
repositoryContainer.getWorkspaceContainer(workspaceName);
+ try
{
- workspaceContainer = repositoryContainer.getWorkspaceContainer(workspaceName);
- try
- {
- workspaceContainer.stop();
- }
- catch (Exception e)
- {
- throw new RepositoryException(e);
- }
- repositoryContainer.unregisterComponentByInstance(workspaceContainer);
- repositoryContainer.unregisterComponent(workspaceName);
+ workspaceContainer.stop();
}
+ catch (Exception e)
+ {
+ throw new RepositoryException(e);
+ }
+ repositoryContainer.unregisterComponentByInstance(workspaceContainer);
+ repositoryContainer.unregisterComponent(workspaceName);
}
/**
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cacheable/AbstractCacheableLockManager.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cacheable/AbstractCacheableLockManager.java 2011-01-26
15:23:23 UTC (rev 3889)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cacheable/AbstractCacheableLockManager.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -16,8 +16,7 @@
*/
package org.exoplatform.services.jcr.impl.core.lock.cacheable;
-import org.exoplatform.commons.utils.PrivilegedSystemHelper;
-import org.exoplatform.commons.utils.SecurityHelper;
+import org.exoplatform.commons.utils.PrivilegedFileHelper;
import org.exoplatform.management.annotations.Managed;
import org.exoplatform.management.annotations.ManagedDescription;
import org.exoplatform.services.jcr.config.RepositoryConfigurationException;
@@ -37,6 +36,10 @@
import org.exoplatform.services.jcr.datamodel.PropertyData;
import org.exoplatform.services.jcr.datamodel.QPathEntry;
import org.exoplatform.services.jcr.impl.Constants;
+import org.exoplatform.services.jcr.impl.backup.BackupException;
+import org.exoplatform.services.jcr.impl.backup.Backupable;
+import org.exoplatform.services.jcr.impl.backup.DataRestor;
+import org.exoplatform.services.jcr.impl.backup.rdbms.DBBackup;
import org.exoplatform.services.jcr.impl.core.SessionDataManager;
import org.exoplatform.services.jcr.impl.core.lock.LockRemover;
import org.exoplatform.services.jcr.impl.core.lock.LockRemoverHolder;
@@ -45,44 +48,32 @@
import org.exoplatform.services.jcr.impl.dataflow.TransientPropertyData;
import
org.exoplatform.services.jcr.impl.dataflow.persistent.WorkspacePersistentDataManager;
import org.exoplatform.services.jcr.impl.storage.JCRInvalidItemStateException;
-import org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer;
-import org.exoplatform.services.jcr.impl.storage.jdbc.backup.BackupException;
-import org.exoplatform.services.jcr.impl.storage.jdbc.backup.Backupable;
-import org.exoplatform.services.jcr.impl.storage.jdbc.backup.CleanException;
-import org.exoplatform.services.jcr.impl.storage.jdbc.backup.DataCleaner;
-import org.exoplatform.services.jcr.impl.storage.jdbc.backup.RestoreException;
-import org.exoplatform.services.jcr.impl.storage.jdbc.backup.util.BackupTables;
-import org.exoplatform.services.jcr.impl.storage.jdbc.backup.util.RestoreTableRule;
-import org.exoplatform.services.jcr.impl.storage.jdbc.backup.util.RestoreTables;
-import org.exoplatform.services.jcr.impl.storage.jdbc.cleaner.DBCleaner;
import org.exoplatform.services.jcr.observation.ExtendedEvent;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.exoplatform.services.security.IdentityConstants;
+import org.jboss.cache.Cache;
import org.picocontainer.Startable;
+import java.io.BufferedOutputStream;
import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
-import java.security.PrivilegedExceptionAction;
import java.sql.Connection;
-import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.HashMap;
import java.util.HashSet;
-import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.jcr.RepositoryException;
import javax.jcr.lock.LockException;
-import javax.naming.InitialContext;
-import javax.naming.NameNotFoundException;
-import javax.naming.NamingException;
-import javax.sql.DataSource;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
@@ -812,104 +803,182 @@
/**
* {@inheritDoc}
*/
- public void backup(File storageDir) throws BackupException
+ public void clean() throws BackupException
{
- Map<String, String> scripts = new HashMap<String, String>();
- for (String tableName : getTableNames())
- {
- scripts.put(tableName, "SELECT * FROM " + tableName);
- }
-
- BackupTables.backup(storageDir, getDatasourceName(), scripts);
+ cleanCacheDirectly();
}
/**
* {@inheritDoc}
*/
- public void restore(File storageDir) throws RestoreException
+ public void backup(File storageDir) throws BackupException
{
- Map<String, RestoreTableRule> tables = new LinkedHashMap<String,
RestoreTableRule>();
- for (String tableName : getTableNames())
+ ObjectOutputStream out = null;
+ try
{
- RestoreTableRule restoreTableRule = new RestoreTableRule();
- restoreTableRule.setSrcContainerName(null);
- restoreTableRule.setSrcMultiDb(null);
- restoreTableRule.setDstContainerName(null);
- restoreTableRule.setDstMultiDb(null);
- restoreTableRule.setSkipColumnIndex(null);
- restoreTableRule.setDeleteColumnIndex(null);
- restoreTableRule.setNewColumnIndex(null);
- restoreTableRule.setConvertColumnIndex(null);
- restoreTableRule.setContentFile(new File(storageDir, tableName +
BackupTables.CONTENT_FILE_SUFFIX));
- restoreTableRule.setContentLenFile(new File(storageDir, tableName +
BackupTables.CONTENT_LEN_FILE_SUFFIX));
+ File contentFile = new File(storageDir, "CacheLocks" +
DBBackup.CONTENT_FILE_SUFFIX);
+ out = new ObjectOutputStream(new
BufferedOutputStream(PrivilegedFileHelper.fileOutputStream(contentFile)));
+
+ List<LockData> locks = getLockList();
- tables.put(tableName, restoreTableRule);
+ out.writeInt(locks.size());
+ for (LockData lockData : locks)
+ {
+ lockData.writeExternal(out);
+ }
}
+ catch (FileNotFoundException e)
+ {
+ throw new BackupException(e);
+ }
+ catch (IOException e)
+ {
+ throw new BackupException(e);
+ }
+ finally
+ {
+ if (out != null)
+ {
+ try
+ {
+ out.flush();
+ out.close();
+ }
+ catch (IOException e)
+ {
+ LOG.error("Can't close output stream", e);
+ }
+ }
+ }
+ }
- File tempDir = new
File(PrivilegedSystemHelper.getProperty("java.io.tmpdir"));
- int maxBufferSize =
-
config.getContainer().getParameterInteger(JDBCWorkspaceDataContainer.MAXBUFFERSIZE_PROP,
- JDBCWorkspaceDataContainer.DEF_MAXBUFFERSIZE);
-
- RestoreTables restoreTable = new RestoreTables(null, tempDir, maxBufferSize);
- restoreTable.restore(storageDir, getDatasourceName(), tables);
- }
-
/**
* {@inheritDoc}
*/
- public DataCleaner getDataCleaner() throws CleanException
+ public DataRestor getDataRestorer(File storageDir, Connection jdbcConn) throws
BackupException
{
+ List<LockData> locks = new ArrayList<LockData>();
+
+ ObjectInputStream in = null;
try
{
- String dsName = getDatasourceName();
+ File contentFile = new File(storageDir, "CacheLocks" +
DBBackup.CONTENT_FILE_SUFFIX);
+ in = new ObjectInputStream(PrivilegedFileHelper.fileInputStream(contentFile));
- final DataSource ds = (DataSource)new InitialContext().lookup(dsName);
- if (ds == null)
+ int count = in.readInt();
+ for (int i = 0; i < count; i++)
{
- throw new NameNotFoundException("Data source " + dsName + "
not found");
+ LockData lockData = new LockData();
+ lockData.readExternal(in);
+
+ locks.add(lockData);
}
-
- Connection jdbcConn =
- SecurityHelper.doPrivilegedSQLExceptionAction(new
PrivilegedExceptionAction<Connection>()
+ }
+ catch (FileNotFoundException e)
+ {
+ throw new BackupException(e);
+ }
+ catch (IOException e)
+ {
+ throw new BackupException(e);
+ }
+ catch (ClassNotFoundException e)
+ {
+ throw new BackupException(e);
+ }
+ finally
+ {
+ if (in != null)
+ {
+ try
{
- public Connection run() throws Exception
- {
- return ds.getConnection();
+ in.close();
+ }
+ catch (IOException e)
+ {
+ LOG.error("Can't close output stream", e);
+ }
+ }
+ }
- }
- });
+ return new CacheLocksRestor(locks);
+ }
- List<String> cleanScripts = new ArrayList<String>();
- for (String tableName : getTableNames())
+ /**
+ * Cache restorer.
+ */
+ protected class CacheLocksRestor implements DataRestor
+ {
+
+ final private List<LockData> backupLocks = new ArrayList<LockData>();
+
+ private List<LockData> actualLocks;
+
+ CacheLocksRestor(final List<LockData> backupLocks)
+ {
+ this.backupLocks.addAll(backupLocks);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void clean() throws BackupException
+ {
+ actualLocks.addAll(getLockList());
+ cleanCacheDirectly();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void restore() throws BackupException
+ {
+ for (LockData lockData : backupLocks)
{
- cleanScripts.add("drop table " + tableName);
+ putDirectly(lockData);
}
+ }
- return new DBCleaner(jdbcConn, cleanScripts);
+ /**
+ * {@inheritDoc}
+ */
+ public void commit() throws BackupException
+ {
}
- catch (SQLException e)
+
+ /**
+ * {@inheritDoc}
+ */
+ public void rollback() throws BackupException
{
- throw new CleanException(e);
+ cleanCacheDirectly();
+ for (LockData lockData : actualLocks)
+ {
+ putDirectly(lockData);
+ }
}
- catch (NamingException e)
+
+ /**
+ * {@inheritDoc}
+ */
+ public void close() throws BackupException
{
- throw new CleanException(e);
+ backupLocks.clear();
+ actualLocks.clear();
}
}
/**
- * Get list of tables names used by CacheableLockManager.
+ * Puts lock data directly into cache.
*
- * @return List
+ * @param lockData
+ * the lock data to put
*/
- protected abstract List<String> getTableNames();
+ protected abstract void putDirectly(LockData lockData);
/**
- * Get data source name used by CacheableLockManager.
- *
- * @return String
+ * Clean cache directly.
*/
- protected abstract String getDatasourceName();
+ protected abstract void cleanCacheDirectly();
}
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/infinispan/ISPNCacheableLockManagerImpl.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/infinispan/ISPNCacheableLockManagerImpl.java 2011-01-26
15:23:23 UTC (rev 3889)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/infinispan/ISPNCacheableLockManagerImpl.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -21,10 +21,8 @@
import org.exoplatform.management.annotations.Managed;
import org.exoplatform.management.jmx.annotations.NameTemplate;
import org.exoplatform.management.jmx.annotations.Property;
-import org.exoplatform.services.jcr.config.LockManagerEntry;
import org.exoplatform.services.jcr.config.MappedParametrizedObjectEntry;
import org.exoplatform.services.jcr.config.RepositoryConfigurationException;
-import org.exoplatform.services.jcr.config.SimpleParameterEntry;
import org.exoplatform.services.jcr.config.WorkspaceEntry;
import org.exoplatform.services.jcr.impl.core.lock.LockRemoverHolder;
import
org.exoplatform.services.jcr.impl.core.lock.cacheable.AbstractCacheableLockManager;
@@ -33,7 +31,6 @@
import
org.exoplatform.services.jcr.impl.dataflow.persistent.WorkspacePersistentDataManager;
import org.exoplatform.services.jcr.impl.storage.jdbc.DBConstants;
import org.exoplatform.services.jcr.impl.storage.jdbc.DialectDetecter;
-import org.exoplatform.services.jcr.impl.storage.jdbc.backup.Backupable;
import org.exoplatform.services.jcr.infinispan.ISPNCacheFactory;
import org.exoplatform.services.jcr.infinispan.PrivilegedISPNCacheHelper;
import org.exoplatform.services.log.ExoLogger;
@@ -64,7 +61,7 @@
*/
@Managed
@NameTemplate(@Property(key = "service", value = "lockmanager"))
-public class ISPNCacheableLockManagerImpl extends AbstractCacheableLockManager implements
Backupable
+public class ISPNCacheableLockManagerImpl extends AbstractCacheableLockManager
{
/**
@@ -399,48 +396,20 @@
}
/**
- * {@inheritDoc}
- */
+ * {@inheritDoc}
+ */
@Override
- protected List<String> getTableNames()
+ protected void putDirectly(LockData lockData)
{
- List<String> tableNames = new ArrayList<String>();
-
- LockManagerEntry lockManagerEntry = config.getLockManager();
- if (lockManagerEntry != null)
- {
- for (SimpleParameterEntry entry : lockManagerEntry.getParameters())
- {
- if (entry.getName().equals(INFINISPAN_JDBC_TABLE_NAME))
- {
- tableNames.add(entry.getValue());
-
- return tableNames;
- }
- }
- }
-
- return tableNames;
+ PrivilegedISPNCacheHelper.putIfAbsent(cache, lockData.getNodeIdentifier(),
lockData);
}
/**
* {@inheritDoc}
*/
@Override
- protected String getDatasourceName()
+ protected void cleanCacheDirectly()
{
- LockManagerEntry lockManagerEntry = config.getLockManager();
- if (lockManagerEntry != null)
- {
- for (SimpleParameterEntry entry : lockManagerEntry.getParameters())
- {
- if (entry.getName().equals(INFINISPAN_JDBC_CL_DATASOURCE))
- {
- return entry.getValue();
- }
- }
- }
-
- return null;
+ cache.clear();
}
}
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/CacheableLockManagerImpl.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/CacheableLockManagerImpl.java 2011-01-26
15:23:23 UTC (rev 3889)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/CacheableLockManagerImpl.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -20,10 +20,8 @@
import org.exoplatform.management.annotations.Managed;
import org.exoplatform.management.jmx.annotations.NameTemplate;
import org.exoplatform.management.jmx.annotations.Property;
-import org.exoplatform.services.jcr.config.LockManagerEntry;
import org.exoplatform.services.jcr.config.MappedParametrizedObjectEntry;
import org.exoplatform.services.jcr.config.RepositoryConfigurationException;
-import org.exoplatform.services.jcr.config.SimpleParameterEntry;
import org.exoplatform.services.jcr.config.WorkspaceEntry;
import org.exoplatform.services.jcr.impl.core.lock.LockRemoverHolder;
import
org.exoplatform.services.jcr.impl.core.lock.cacheable.AbstractCacheableLockManager;
@@ -165,8 +163,6 @@
{
super(dataManager, config, transactionManager, lockRemoverHolder);
- lockRoot = Fqn.fromElements(LOCKS);
-
// make cache
if (config.getLockManager() != null)
{
@@ -180,6 +176,9 @@
cache = factory.createCache(config.getLockManager());
Fqn<String> rootFqn = Fqn.fromElements(config.getUniqueName());
+
+ lockRoot = Fqn.fromRelativeElements(rootFqn, LOCKS);
+
shareable =
config.getLockManager().getParameterBoolean(JBOSSCACHE_SHAREABLE,
JBOSSCACHE_SHAREABLE_DEFAULT)
.booleanValue();
@@ -575,45 +574,22 @@
/**
* {@inheritDoc}
*/
- protected List<String> getTableNames()
+ @Override
+ protected void putDirectly(LockData lockData)
{
- List<String> tableNames = new ArrayList<String>();
+ Fqn<String> lockPath = makeLockFqn(lockData.getNodeIdentifier());
- LockManagerEntry lockManagerEntry = config.getLockManager();
- if (lockManagerEntry != null)
- {
- for (SimpleParameterEntry entry : lockManagerEntry.getParameters())
- {
- if (entry.getName().equals(JBOSSCACHE_JDBC_TABLE_NAME))
- {
- tableNames.add(entry.getValue());
- tableNames.add(entry.getValue() + "_D");
-
- return tableNames;
- }
- }
- }
-
- return tableNames;
+ Node<Serializable, Object> node = cache.getRoot().addChild(lockPath);
+ node.putIfAbsent(LOCK_DATA, lockData);
}
-
+
/**
* {@inheritDoc}
*/
- protected String getDatasourceName()
+ @Override
+ protected void cleanCacheDirectly()
{
- LockManagerEntry lockManagerEntry = config.getLockManager();
- if (lockManagerEntry != null)
- {
- for (SimpleParameterEntry entry : lockManagerEntry.getParameters())
- {
- if (entry.getName().equals(JBOSSCACHE_JDBC_CL_DATASOURCE))
- {
- return entry.getValue();
- }
- }
- }
-
- return null;
+ cache.removeNode(lockRoot);
+ createStructuredNode(lockRoot);
}
}
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/AbstractQueryHandler.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/AbstractQueryHandler.java 2011-01-26
15:23:23 UTC (rev 3889)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/AbstractQueryHandler.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -74,7 +74,7 @@
*/
protected IndexInfos indexInfos;
- private IndexUpdateMonitor indexUpdateMonitor;
+ protected IndexUpdateMonitor indexUpdateMonitor;
public boolean isInitialized()
{
@@ -209,6 +209,7 @@
*
* @param idleTime the query handler idle time.
*/
+ @Deprecated
public void setIdleTime(String idleTime)
{
log.warn("Parameter 'idleTime' is not supported anymore. "
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/SearchManager.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/SearchManager.java 2011-01-26
15:23:23 UTC (rev 3889)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/SearchManager.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -21,6 +21,7 @@
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.WildcardQuery;
+import org.exoplatform.commons.utils.PrivilegedFileHelper;
import org.exoplatform.container.configuration.ConfigurationManager;
import org.exoplatform.services.document.DocumentReaderService;
import org.exoplatform.services.jcr.config.QueryHandlerEntry;
@@ -39,6 +40,13 @@
import org.exoplatform.services.jcr.datamodel.QPath;
import org.exoplatform.services.jcr.datamodel.ValueData;
import org.exoplatform.services.jcr.impl.Constants;
+import org.exoplatform.services.jcr.impl.backup.BackupException;
+import org.exoplatform.services.jcr.impl.backup.Backupable;
+import org.exoplatform.services.jcr.impl.backup.DataRestor;
+import org.exoplatform.services.jcr.impl.backup.ResumeException;
+import org.exoplatform.services.jcr.impl.backup.SuspendException;
+import org.exoplatform.services.jcr.impl.backup.Suspendable;
+import org.exoplatform.services.jcr.impl.backup.rdbms.DirectoryRestor;
import org.exoplatform.services.jcr.impl.core.LocationFactory;
import org.exoplatform.services.jcr.impl.core.NamespaceRegistryImpl;
import org.exoplatform.services.jcr.impl.core.SessionDataManager;
@@ -52,17 +60,23 @@
import org.exoplatform.services.jcr.impl.core.value.PathValue;
import org.exoplatform.services.jcr.impl.core.value.ValueFactoryImpl;
import
org.exoplatform.services.jcr.impl.dataflow.persistent.WorkspacePersistentDataManager;
-import org.exoplatform.services.jcr.impl.storage.jdbc.backup.ResumeException;
-import org.exoplatform.services.jcr.impl.storage.jdbc.backup.SuspendException;
-import org.exoplatform.services.jcr.impl.storage.jdbc.backup.Suspendable;
+import org.exoplatform.services.jcr.impl.util.io.DirectoryHelper;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
+import org.exoplatform.services.rpc.RPCException;
+import org.exoplatform.services.rpc.RPCService;
+import org.exoplatform.services.rpc.RemoteCommand;
+import org.exoplatform.services.rpc.TopologyChangeEvent;
+import org.exoplatform.services.rpc.TopologyChangeListener;
import org.jboss.cache.factories.annotations.NonVolatile;
import org.picocontainer.Startable;
+import java.io.File;
import java.io.IOException;
+import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
+import java.sql.Connection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
@@ -89,7 +103,8 @@
* @version $Id: SearchManager.java 1008 2009-12-11 15:14:51Z nzamosenchuk $
*/
@NonVolatile
-public class SearchManager implements Startable, MandatoryItemsPersistenceListener,
Suspendable
+public class SearchManager implements Startable, MandatoryItemsPersistenceListener,
Suspendable, Backupable,
+ TopologyChangeListener
{
/**
@@ -145,6 +160,36 @@
protected final String wsId;
/**
+ * The service for executing commands on all nodes of cluster.
+ */
+ protected final RPCService rpcService;
+
+ /**
+ * Indicates if component suspended or not.
+ */
+ protected boolean isSuspended = false;
+
+ /**
+ * Indicates that node keep responsible for resuming.
+ */
+ protected Boolean isResponsibleForResuming = false;
+
+ /**
+ * Suspend remote command.
+ */
+ private RemoteCommand suspend;
+
+ /**
+ * Resume remote command.
+ */
+ private RemoteCommand resume;
+
+ /**
+ * Request to all nodes to check if there is someone who responsible for resuming.
+ */
+ private RemoteCommand requestForResponsibleForResuming;
+
+ /**
* Creates a new <code>SearchManager</code>.
*
* @param config
@@ -168,11 +213,47 @@
* @throws RepositoryConfigurationException
*/
- public SearchManager(WorkspaceEntry wsConfig, QueryHandlerEntry config,
NamespaceRegistryImpl nsReg, NodeTypeDataManager ntReg,
- WorkspacePersistentDataManager itemMgr, SystemSearchManagerHolder
parentSearchManager,
+ public SearchManager(WorkspaceEntry wsConfig, QueryHandlerEntry config,
NamespaceRegistryImpl nsReg,
+ NodeTypeDataManager ntReg, WorkspacePersistentDataManager itemMgr,
SystemSearchManagerHolder parentSearchManager,
DocumentReaderService extractor, ConfigurationManager cfm, final
RepositoryIndexSearcherHolder indexSearcherHolder)
throws RepositoryException, RepositoryConfigurationException
{
+ this(wsConfig, config, nsReg, ntReg, itemMgr, parentSearchManager, extractor, cfm,
indexSearcherHolder, null);
+ }
+
+ /**
+ * Creates a new <code>SearchManager</code>.
+ *
+ * @param config
+ * the search configuration.
+ * @param nsReg
+ * the namespace registry.
+ * @param ntReg
+ * the node type registry.
+ * @param itemMgr
+ * the shared item state manager.
+ * @param rootNodeId
+ * the id of the root node.
+ * @param parentMgr
+ * the parent search manager or <code>null</code> if there is
no
+ * parent search manager.
+ * @param excludedNodeId
+ * id of the node that should be excluded from indexing. Any
+ * descendant of that node will also be excluded from indexing.
+ * @param rpcService
+ * the service for executing commands on all nodes of cluster
+ * @throws RepositoryException
+ * if the search manager cannot be initialized
+ * @throws RepositoryConfigurationException
+ */
+
+ public SearchManager(WorkspaceEntry wsConfig, QueryHandlerEntry config,
NamespaceRegistryImpl nsReg,
+ NodeTypeDataManager ntReg, WorkspacePersistentDataManager itemMgr,
SystemSearchManagerHolder parentSearchManager,
+ DocumentReaderService extractor, ConfigurationManager cfm,
+ final RepositoryIndexSearcherHolder indexSearcherHolder, RPCService rpcService)
throws RepositoryException,
+ RepositoryConfigurationException
+ {
+ this.rpcService = rpcService;
this.wsId = wsConfig.getUniqueName();
this.extractor = extractor;
indexSearcherHolder.addIndexSearcher(this);
@@ -187,6 +268,11 @@
{
((WorkspacePersistentDataManager)this.itemMgr).addItemPersistenceListener(this);
}
+
+ if (rpcService != null)
+ {
+ doInitRemoteCommands();
+ }
}
public void createNewOrAdd(String key, ItemState state, Map<String,
List<ItemState>> updatedNodes)
@@ -459,7 +545,6 @@
indexingTree = new IndexingTree(indexingRootData, excludedPath);
}
initializeQueryHandler();
-
}
catch (RepositoryException e)
{
@@ -578,7 +663,7 @@
{
QueryHandlerContext context =
- new QueryHandlerContext(itemMgr, indexingTree, nodeTypeDataManager, nsReg,
parentHandler, getIndexDir(),
+ new QueryHandlerContext(itemMgr, indexingTree, nodeTypeDataManager, nsReg,
parentHandler, getIndexDirectory(),
extractor, true, virtualTableResolver);
return context;
}
@@ -862,10 +947,27 @@
*/
public void suspend() throws SuspendException
{
- if (handler instanceof Suspendable)
+ isResponsibleForResuming = true;
+
+ if (rpcService != null)
{
- ((Suspendable)handler).suspend();
+ try
+ {
+ rpcService.executeCommandOnAllNodes(suspend, true);
+ }
+ catch (SecurityException e)
+ {
+ throw new SuspendException(e);
+ }
+ catch (RPCException e)
+ {
+ throw new SuspendException(e);
+ }
}
+ else
+ {
+ suspendLocally();
+ }
}
/**
@@ -873,10 +975,257 @@
*/
public void resume() throws ResumeException
{
+ if (rpcService != null)
+ {
+ try
+ {
+ rpcService.executeCommandOnAllNodes(resume, true);
+ }
+ catch (SecurityException e)
+ {
+ throw new ResumeException(e);
+ }
+ catch (RPCException e)
+ {
+ throw new ResumeException(e);
+ }
+ }
+ else
+ {
+ resumeLocally();
+ }
+
+ isResponsibleForResuming = false;
+ }
+
+ /**
+ * Register remote commands.
+ */
+ private void doInitRemoteCommands()
+ {
+ // register commands
+ suspend = rpcService.registerCommand(new RemoteCommand()
+ {
+
+ public String getId()
+ {
+ return
"org.exoplatform.services.jcr.impl.core.query.SearchManager-suspend-" + wsId;
+ }
+
+ public Serializable execute(Serializable[] args) throws Throwable
+ {
+ suspendLocally();
+ return null;
+ }
+ });
+
+ resume = rpcService.registerCommand(new RemoteCommand()
+ {
+
+ public String getId()
+ {
+ return
"org.exoplatform.services.jcr.impl.core.query.SearchManager-resume-" + wsId;
+ }
+
+ public Serializable execute(Serializable[] args) throws Throwable
+ {
+ resumeLocally();
+ return null;
+ }
+ });
+
+ requestForResponsibleForResuming = rpcService.registerCommand(new RemoteCommand()
+ {
+
+ public String getId()
+ {
+ return
"org.exoplatform.services.jcr.impl.core.query.SearchManager-requestForResponsibilityForResuming-"
+ + wsId;
+ }
+
+ public Serializable execute(Serializable[] args) throws Throwable
+ {
+ return isResponsibleForResuming;
+ }
+ });
+
+ rpcService.registerTopologyChangeListener(this);
+ }
+
+ protected void suspendLocally() throws SuspendException
+ {
+ if (isSuspended)
+ {
+ throw new SuspendException("Component already suspended.");
+ }
+
+ isSuspended = true;
+
+ stop();
+
if (handler instanceof Suspendable)
{
+ ((Suspendable)handler).suspend();
+ }
+ }
+
+ protected void resumeLocally() throws ResumeException
+ {
+ if (!isSuspended)
+ {
+ throw new ResumeException("Component is not suspended.");
+ }
+
+ start();
+
+ if (handler instanceof Suspendable)
+ {
((Suspendable)handler).resume();
}
+
+ isSuspended = false;
}
+ /**
+ * {@inheritDoc}
+ */
+ public void onChange(TopologyChangeEvent event)
+ {
+ if (isSuspended)
+ {
+ new Thread()
+ {
+ @Override
+ public synchronized void run()
+ {
+ try
+ {
+ List<Object> results =
rpcService.executeCommandOnAllNodes(requestForResponsibleForResuming, true);
+
+ for (Object result : results)
+ {
+ if ((Boolean)result)
+ {
+ return;
+ }
+ }
+
+ // node which was responsible for resuming leave the cluster, so resume
component
+ try
+ {
+ resumeLocally();
+ }
+ catch (ResumeException e)
+ {
+ log.error("Can not resume component", e);
+ }
+ }
+ catch (SecurityException e1)
+ {
+ log.error("You haven't privileges to execute remote
command", e1);
+ }
+ catch (RPCException e1)
+ {
+ log.error("Exception during command execution", e1);
+ }
+ }
+ }.start();
+ }
+ }
+
+ /**
+ * {@inheritDoc}}
+ */
+ public void clean() throws BackupException
+ {
+ try
+ {
+ DirectoryHelper.removeDirectory(new File(getIndexDirectory()));
+ }
+ catch (IOException e)
+ {
+ throw new BackupException(e);
+ }
+ catch (RepositoryConfigurationException e)
+ {
+ throw new BackupException(e);
+ }
+ }
+
+ /**
+ * {@inheritDoc}}
+ */
+ public void backup(File storageDir) throws BackupException
+ {
+ try
+ {
+ File indexDir = new File(getIndexDirectory());
+
+ if (!PrivilegedFileHelper.exists(indexDir))
+ {
+ throw new BackupException("Can't backup index. Directory "
+ + PrivilegedFileHelper.getCanonicalPath(indexDir) + " doesn't
exists");
+ }
+ else
+ {
+ File destDir = new File(storageDir, getStorageName());
+ DirectoryHelper.compressDirectory(indexDir, destDir);
+ }
+ }
+ catch (RepositoryConfigurationException e)
+ {
+ throw new BackupException(e);
+ }
+ catch (IOException e)
+ {
+ throw new BackupException(e);
+ }
+ }
+
+ /**
+ * Return index directory.
+ *
+ * @return String
+ * @throws RepositoryConfigurationException
+ */
+ protected String getIndexDirectory() throws RepositoryConfigurationException
+ {
+ return getIndexDir();
+ }
+
+ /**
+ * Returns storage name of index.
+ *
+ * @return String
+ */
+ protected String getStorageName()
+ {
+ return "index";
+ }
+
+ /**
+ * {@inheritDoc}}
+ */
+ public DataRestor getDataRestorer(File storageDir, Connection jdbcConn) throws
BackupException
+ {
+ try
+ {
+ File indexDir = new File(getIndexDirectory());
+ File backupDir = new File(storageDir, getStorageName());
+
+ if (!PrivilegedFileHelper.exists(backupDir))
+ {
+ throw new RepositoryConfigurationException("Can't restore index.
Directory " + backupDir.getName()
+ + " doesn't exists");
+ }
+ else
+ {
+ return new DirectoryRestor(indexDir, backupDir);
+ }
+ }
+ catch (RepositoryConfigurationException e)
+ {
+ throw new BackupException(e);
+ }
+ }
}
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/SystemSearchManager.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/SystemSearchManager.java 2011-01-26
15:23:23 UTC (rev 3889)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/SystemSearchManager.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -25,6 +25,7 @@
import org.exoplatform.services.jcr.datamodel.NodeData;
import org.exoplatform.services.jcr.datamodel.QPath;
import org.exoplatform.services.jcr.impl.Constants;
+import org.exoplatform.services.jcr.impl.backup.SuspendException;
import org.exoplatform.services.jcr.impl.core.NamespaceRegistryImpl;
import
org.exoplatform.services.jcr.impl.dataflow.persistent.WorkspacePersistentDataManager;
import org.exoplatform.services.log.ExoLogger;
@@ -107,8 +108,33 @@
throws RepositoryConfigurationException
{
QueryHandlerContext context =
- new QueryHandlerContext(itemMgr, indexingTree, nodeTypeDataManager, nsReg,
parentHandler, getIndexDir() + "_"
- + INDEX_DIR_SUFFIX, extractor, true, virtualTableResolver);
+ new QueryHandlerContext(itemMgr, indexingTree, nodeTypeDataManager, nsReg,
parentHandler, getIndexDirectory(),
+ extractor, true, virtualTableResolver);
return context;
}
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected String getIndexDirectory() throws RepositoryConfigurationException
+ {
+ return getIndexDir() + "_" + INDEX_DIR_SUFFIX;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected String getStorageName()
+ {
+ return super.getStorageName() + "_" + INDEX_DIR_SUFFIX;
+ }
+
+ @Override
+ protected void suspendLocally() throws SuspendException
+ {
+ super.suspendLocally();
+ isStarted = false;
+ }
}
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/jbosscache/JBossCacheIndexInfos.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/jbosscache/JBossCacheIndexInfos.java 2011-01-26
15:23:23 UTC (rev 3889)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/jbosscache/JBossCacheIndexInfos.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -103,8 +103,9 @@
modeHandler.addIndexerIoModeListener(this);
// store parsed FQN to avoid it's parsing each time cache event is generated
namesFqn = Fqn.fromRelativeElements(rootFqn, system ? SYSINDEX_NAMES :
INDEX_NAMES);
+
Node<Serializable, Object> cacheRoot = cache.getRoot();
- // prepare cache structures
+
if (!cacheRoot.hasChild(namesFqn))
{
cache.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
@@ -114,6 +115,7 @@
{
cache.getNode(namesFqn).setResident(true);
}
+
if (modeHandler.getMode() == IndexerIoMode.READ_ONLY)
{
// Currently READ_ONLY is set, so new lists should be fired to multiIndex.
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/jbosscache/JBossCacheIndexUpdateMonitor.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/jbosscache/JBossCacheIndexUpdateMonitor.java 2011-01-26
15:23:23 UTC (rev 3889)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/jbosscache/JBossCacheIndexUpdateMonitor.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -87,9 +87,9 @@
// store parsed FQN to avoid it's parsing each time cache event is generated
this.parametersFqn = Fqn.fromRelativeElements(rootFqn, system ? INDEX_PARAMETERS :
SYSINDEX_PARAMETERS);
modeHandler.addIndexerIoModeListener(this);
+
Node<Serializable, Object> cacheRoot = cache.getRoot();
- // prepare cache structures
if (!cacheRoot.hasChild(parametersFqn))
{
cache.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
@@ -112,7 +112,6 @@
Object value = cache.get(parametersFqn, PARAMETER_NAME);
localUpdateInProgress = value != null ? (Boolean)value : false;
}
-
}
/**
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/MultiIndex.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/MultiIndex.java 2011-01-26
15:23:23 UTC (rev 3889)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/MultiIndex.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -2576,43 +2576,6 @@
}
/**
- * Suspends multi index: flush volatile index and stop merger.
- *
- * @throws IOException
- */
- protected void suspend() throws IOException
- {
- if (modeHandler.getMode() == IndexerIoMode.READ_WRITE)
- {
- try
- {
- indexUpdateMonitor.setUpdateInProgress(true, true);
- flush();
-
- merger.dispose();
- }
- finally
- {
- indexUpdateMonitor.setUpdateInProgress(false, true);
- }
- }
- }
-
- /**
- * Resume mulit index by starting merger.
- *
- * @throws IOException
- */
- protected void resume() throws IOException
- {
- if (modeHandler.getMode() == IndexerIoMode.READ_WRITE)
- {
- merger = doInitIndexMerger();
- merger.start();
- }
- }
-
- /**
* Refresh list of indexes. Used to be called asynchronously when list changes. New,
actual list is read from
* IndexInfos.
* @throws IOException
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SearchIndex.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SearchIndex.java 2011-01-26
15:23:23 UTC (rev 3889)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SearchIndex.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -62,9 +62,6 @@
import org.exoplatform.services.jcr.impl.core.query.SearchIndexConfigurationHelper;
import org.exoplatform.services.jcr.impl.core.query.lucene.directory.DirectoryManager;
import org.exoplatform.services.jcr.impl.core.query.lucene.directory.FSDirectoryManager;
-import org.exoplatform.services.jcr.impl.storage.jdbc.backup.ResumeException;
-import org.exoplatform.services.jcr.impl.storage.jdbc.backup.SuspendException;
-import org.exoplatform.services.jcr.impl.storage.jdbc.backup.Suspendable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Element;
@@ -98,7 +95,7 @@
* Implements a {@link org.apache.jackrabbit.core.query.QueryHandler} using
* Lucene.
*/
-public class SearchIndex extends AbstractQueryHandler implements IndexerIoModeListener,
Suspendable
+public class SearchIndex extends AbstractQueryHandler implements IndexerIoModeListener
{
private static final DefaultQueryNodeFactory DEFAULT_QUERY_NODE_FACTORY = new
DefaultQueryNodeFactory();
@@ -2809,34 +2806,4 @@
log.error("Can not recover error log.", e);
}
}
-
- /**
- * {@inheritDoc}
- */
- public void suspend() throws SuspendException
- {
- try
- {
- index.suspend();
- }
- catch (IOException e)
- {
- throw new SuspendException(e);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public void resume() throws ResumeException
- {
- try
- {
- index.resume();
- }
- catch (IOException e)
- {
- throw new ResumeException(e);
- }
- }
}
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/CacheableWorkspaceDataManager.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/CacheableWorkspaceDataManager.java 2011-01-26
15:23:23 UTC (rev 3889)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/CacheableWorkspaceDataManager.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -31,17 +31,27 @@
import org.exoplatform.services.jcr.datamodel.QPathEntry;
import org.exoplatform.services.jcr.datamodel.ValueData;
import org.exoplatform.services.jcr.impl.Constants;
+import org.exoplatform.services.jcr.impl.backup.ResumeException;
+import org.exoplatform.services.jcr.impl.backup.SuspendException;
+import org.exoplatform.services.jcr.impl.backup.Suspendable;
import
org.exoplatform.services.jcr.impl.dataflow.persistent.jbosscache.JBossCacheWorkspaceStorageCache;
import org.exoplatform.services.jcr.impl.storage.SystemDataContainerHolder;
import org.exoplatform.services.jcr.impl.storage.jdbc.JDBCStorageConnection;
import org.exoplatform.services.jcr.storage.WorkspaceDataContainer;
+import org.exoplatform.services.rpc.RPCException;
+import org.exoplatform.services.rpc.RPCService;
+import org.exoplatform.services.rpc.RemoteCommand;
+import org.exoplatform.services.rpc.TopologyChangeEvent;
+import org.exoplatform.services.rpc.TopologyChangeListener;
import org.exoplatform.services.transaction.TransactionService;
+import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicInteger;
import javax.jcr.RepositoryException;
import javax.transaction.TransactionManager;
@@ -55,7 +65,8 @@
*
* @version $Id$
*/
-public class CacheableWorkspaceDataManager extends WorkspacePersistentDataManager
+public class CacheableWorkspaceDataManager extends WorkspacePersistentDataManager
implements Suspendable,
+ TopologyChangeListener
{
/**
@@ -71,6 +82,46 @@
private TransactionManager transactionManager;
/**
+ * The service for executing commands on all nodes of cluster.
+ */
+ protected final RPCService rpcService;
+
+ /**
+ * The amount of current working threads.
+ */
+ protected AtomicInteger workingThreads = new AtomicInteger();
+
+ /**
+ * Indicates if component suspended or not.
+ */
+ protected boolean isSuspended = false;
+
+ /**
+ * Allows to make all threads waiting until resume.
+ */
+ protected CountDownLatch latcher = null;
+
+ /**
+ * Indicates that node keep responsible for resuming.
+ */
+ protected Boolean isResponsibleForResuming = false;
+
+ /**
+ * Request to all nodes to check if there is someone who responsible for resuming.
+ */
+ private RemoteCommand requestForResponsibleForResuming;
+
+ /**
+ * Suspend remote command.
+ */
+ private RemoteCommand suspend;
+
+ /**
+ * Resume remote command.
+ */
+ private RemoteCommand resume;
+
+ /**
* ItemData request, used on get operations.
*
*/
@@ -318,18 +369,73 @@
* Items cache
* @param systemDataContainerHolder
* System Workspace data container (persistent level)
+ * @param transactionService
+ * TransactionService
+ * @param rpcService
+ * the service for executing commands on all nodes of cluster
+ */
+ public CacheableWorkspaceDataManager(WorkspaceDataContainer dataContainer,
WorkspaceStorageCache cache,
+ SystemDataContainerHolder systemDataContainerHolder, TransactionService
transactionService, RPCService rpcService)
+ {
+ super(dataContainer, systemDataContainerHolder);
+ this.cache = cache;
+
+ this.requestCache = new ConcurrentHashMap<Integer, DataRequest>();
+ addItemPersistenceListener(new CacheItemsPersistenceListener());
+
+ transactionManager = transactionService.getTransactionManager();
+
+ this.rpcService = rpcService;
+ doInitRemoteCommands();
+ }
+
+ /**
+ * CacheableWorkspaceDataManager constructor.
+ *
+ * @param dataContainer
+ * Workspace data container (persistent level)
+ * @param cache
+ * Items cache
+ * @param systemDataContainerHolder
+ * System Workspace data container (persistent level)
* @param transactionService TransactionService
*/
public CacheableWorkspaceDataManager(WorkspaceDataContainer dataContainer,
WorkspaceStorageCache cache,
SystemDataContainerHolder systemDataContainerHolder, TransactionService
transactionService)
{
+ this(dataContainer, cache, systemDataContainerHolder, transactionService, null);
+ }
+
+ /**
+ * CacheableWorkspaceDataManager constructor.
+ *
+ * @param dataContainer
+ * Workspace data container (persistent level)
+ * @param cache
+ * Items cache
+ * @param systemDataContainerHolder
+ * System Workspace data container (persistent level)
+ */
+ public CacheableWorkspaceDataManager(WorkspaceDataContainer dataContainer,
WorkspaceStorageCache cache,
+ SystemDataContainerHolder systemDataContainerHolder, RPCService rpcService)
+ {
super(dataContainer, systemDataContainerHolder);
this.cache = cache;
this.requestCache = new ConcurrentHashMap<Integer, DataRequest>();
addItemPersistenceListener(new CacheItemsPersistenceListener());
- transactionManager = transactionService.getTransactionManager();
+ if (cache instanceof JBossCacheWorkspaceStorageCache)
+ {
+ transactionManager =
((JBossCacheWorkspaceStorageCache)cache).getTransactionManager();
+ }
+ else
+ {
+ transactionManager = null;
+ }
+
+ this.rpcService = rpcService;
+ doInitRemoteCommands();
}
/**
@@ -359,6 +465,8 @@
{
transactionManager = null;
}
+
+ this.rpcService = null;
}
/**
@@ -566,19 +674,41 @@
@Override
public void save(final ItemStateChangesLog changesLog) throws RepositoryException
{
- if (isTxAware())
+ if (isSuspended)
{
- // save in dedicated XA transaction
- new SaveInTransaction(changesLog).perform();
+ try
+ {
+ latcher.await();
+ }
+ catch (InterruptedException e)
+ {
+ throw new RepositoryException(e);
+ }
}
- else
+
+ workingThreads.incrementAndGet();
+
+ try
{
- // save normaly
- super.save(changesLog);
+ if (isTxAware())
+ {
+ // save in dedicated XA transaction
+ new SaveInTransaction(changesLog).perform();
+ }
+ else
+ {
- // notify listeners after storage commit
- notifySaveItems(changesLog, false);
+ // save normaly
+ super.save(changesLog);
+
+ // notify listeners after storage commit
+ notifySaveItems(changesLog, false);
+ }
}
+ finally
+ {
+ workingThreads.decrementAndGet();
+ }
}
/**
@@ -961,4 +1091,200 @@
conn.close();
}
}
+
+ /**
+ * {@inheritDoc}
+ */
+ public void suspend() throws SuspendException
+ {
+ isResponsibleForResuming = true;
+
+ if (rpcService != null)
+ {
+ try
+ {
+ rpcService.executeCommandOnAllNodes(suspend, true, null);
+ }
+ catch (SecurityException e)
+ {
+ throw new SuspendException(e);
+ }
+ catch (RPCException e)
+ {
+ throw new SuspendException(e);
+ }
+ }
+ else
+ {
+ suspendLocally();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void resume() throws ResumeException
+ {
+ if (rpcService != null)
+ {
+ try
+ {
+ rpcService.executeCommandOnAllNodes(resume, true, null);
+ }
+ catch (SecurityException e)
+ {
+ throw new ResumeException(e);
+ }
+ catch (RPCException e)
+ {
+ throw new ResumeException(e);
+ }
+ }
+ else
+ {
+ resumeLocally();
+ }
+
+ isResponsibleForResuming = false;
+ }
+
+ private void suspendLocally() throws SuspendException
+ {
+ if (isSuspended)
+ {
+ throw new SuspendException("Component already suspended.");
+ }
+
+ latcher = new CountDownLatch(1);
+ isSuspended = true;
+
+ while (workingThreads.get() != 0)
+ {
+ try
+ {
+ Thread.sleep(50);
+ }
+ catch (InterruptedException e)
+ {
+ throw new SuspendException(e);
+ }
+ }
+ }
+
+ private void resumeLocally() throws ResumeException
+ {
+ if (!isSuspended)
+ {
+ throw new ResumeException("Component is not suspended.");
+ }
+
+ isSuspended = false;
+ latcher.countDown();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void onChange(TopologyChangeEvent event)
+ {
+ if (isSuspended)
+ {
+ new Thread()
+ {
+ @Override
+ public synchronized void run()
+ {
+ try
+ {
+ List<Object> results =
rpcService.executeCommandOnAllNodes(requestForResponsibleForResuming, true);
+
+ for (Object result : results)
+ {
+ if ((Boolean)result)
+ {
+ return;
+ }
+ }
+
+ // node which was responsible for resuming leave the cluster, so resume
component
+ try
+ {
+ resumeLocally();
+ }
+ catch (ResumeException e)
+ {
+ LOG.error("Can not resume component", e);
+ }
+ }
+ catch (SecurityException e1)
+ {
+ LOG.error("You haven't privileges to execute remote
command", e1);
+ }
+ catch (RPCException e1)
+ {
+ LOG.error("Exception during command execution", e1);
+ }
+ }
+ }.start();
+ }
+ }
+
+ /**
+ * Initialization remote commands.
+ */
+ private void doInitRemoteCommands()
+ {
+ if (rpcService != null)
+ {
+ // register commands
+ suspend = rpcService.registerCommand(new RemoteCommand()
+ {
+
+ public String getId()
+ {
+ return
"org.exoplatform.services.jcr.impl.dataflow.persistent.CacheableWorkspaceDataManager-suspend-"
+ + dataContainer.getUniqueName();
+ }
+
+ public Serializable execute(Serializable[] args) throws Throwable
+ {
+ suspendLocally();
+ return null;
+ }
+ });
+
+ resume = rpcService.registerCommand(new RemoteCommand()
+ {
+
+ public String getId()
+ {
+ return
"org.exoplatform.services.jcr.impl.dataflow.persistent.CacheableWorkspaceDataManager-resume-"
+ + dataContainer.getUniqueName();
+ }
+
+ public Serializable execute(Serializable[] args) throws Throwable
+ {
+ resumeLocally();
+ return null;
+ }
+ });
+
+ requestForResponsibleForResuming = rpcService.registerCommand(new
RemoteCommand()
+ {
+
+ public String getId()
+ {
+ return
"org.exoplatform.services.jcr.impl.dataflow.persistent.CacheableWorkspaceDataManager-requestForResponsibilityForResuming-"
+ + dataContainer.getUniqueName();
+ }
+
+ public Serializable execute(Serializable[] args) throws Throwable
+ {
+ return isResponsibleForResuming;
+ }
+ });
+
+ rpcService.registerTopologyChangeListener(this);
+ }
+ }
}
\ No newline at end of file
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/WorkspacePersistentDataManager.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/WorkspacePersistentDataManager.java 2011-01-26
15:23:23 UTC (rev 3889)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/WorkspacePersistentDataManager.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -42,9 +42,6 @@
import org.exoplatform.services.jcr.impl.Constants;
import org.exoplatform.services.jcr.impl.dataflow.TransientValueData;
import org.exoplatform.services.jcr.impl.storage.SystemDataContainerHolder;
-import org.exoplatform.services.jcr.impl.storage.jdbc.backup.ResumeException;
-import org.exoplatform.services.jcr.impl.storage.jdbc.backup.SuspendException;
-import org.exoplatform.services.jcr.impl.storage.jdbc.backup.Suspendable;
import org.exoplatform.services.jcr.storage.WorkspaceDataContainer;
import org.exoplatform.services.jcr.storage.WorkspaceStorageConnection;
import org.exoplatform.services.log.ExoLogger;
@@ -58,7 +55,6 @@
import java.util.Iterator;
import java.util.List;
import java.util.Set;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
import javax.jcr.InvalidItemStateException;
import javax.jcr.RepositoryException;
@@ -71,7 +67,7 @@
* @author <a href="mailto:gennady.azarenkov@exoplatform.com">Gennady
Azarenkov</a>
* @version $Id$
*/
-public abstract class WorkspacePersistentDataManager implements PersistentDataManager,
Suspendable
+public abstract class WorkspacePersistentDataManager implements PersistentDataManager
{
/**
@@ -110,8 +106,6 @@
*/
protected boolean readOnly = false;
- protected ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(true);
-
/**
* WorkspacePersistentDataManager constructor.
*
@@ -136,8 +130,6 @@
*/
public void save(final ItemStateChangesLog changesLog) throws RepositoryException
{
- rwl.readLock().lock();
-
// check if this workspace container is not read-only
if (readOnly && !(changesLog instanceof ReadOnlyThroughChanges))
{
@@ -186,8 +178,6 @@
}
notifySaveItems(persistedLog, true);
-
- rwl.readLock().unlock();
}
class ChangesLogPersister
@@ -841,21 +831,4 @@
{
this.readOnly = status;
}
-
- /**
- * {@inheritDoc}
- */
- public void suspend() throws SuspendException
- {
- rwl.writeLock().lock();
- }
-
- /**
- * {@inheritDoc}
- */
- public void resume() throws ResumeException
- {
- rwl.writeLock().unlock();
- }
-
}
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/ISPNCacheWorkspaceStorageCache.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/ISPNCacheWorkspaceStorageCache.java 2011-01-26
15:23:23 UTC (rev 3889)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/ISPNCacheWorkspaceStorageCache.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -40,6 +40,9 @@
import org.exoplatform.services.jcr.datamodel.QPathEntry;
import org.exoplatform.services.jcr.datamodel.ValueData;
import org.exoplatform.services.jcr.impl.Constants;
+import org.exoplatform.services.jcr.impl.backup.BackupException;
+import org.exoplatform.services.jcr.impl.backup.Backupable;
+import org.exoplatform.services.jcr.impl.backup.DataRestor;
import org.exoplatform.services.jcr.impl.dataflow.TransientNodeData;
import org.exoplatform.services.jcr.impl.dataflow.TransientPropertyData;
import org.exoplatform.services.jcr.infinispan.ISPNCacheFactory;
@@ -47,11 +50,11 @@
import org.exoplatform.services.log.Log;
import org.infinispan.Cache;
+import java.io.File;
import java.io.IOException;
import java.io.Serializable;
-import java.lang.ref.Reference;
-import java.lang.ref.SoftReference;
import java.security.PrivilegedExceptionAction;
+import java.sql.Connection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -87,7 +90,7 @@
* @author <a href="anatoliy.bazko(a)exoplatform.org">Anatoliy
Bazko</a>
* @version $Id: ISPNCacheWorkspaceStorageCache.java 3514 2010-11-22 16:14:36Z
nzamosenchuk $
*/
-public class ISPNCacheWorkspaceStorageCache implements WorkspaceStorageCache
+public class ISPNCacheWorkspaceStorageCache implements WorkspaceStorageCache, Backupable
{
private static final Log LOG =
ExoLogger.getLogger("exo.jcr.component.core.ISPNCacheWorkspaceStorageCache");
@@ -1133,4 +1136,65 @@
return null;
}
}
+
+ /**
+ * {@inheritDoc}
+ */
+ public void backup(File storageDir) throws BackupException
+ {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void clean() throws BackupException
+ {
+ cache.clear();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DataRestor getDataRestorer(File storageDir, Connection jdbcConn) throws
BackupException
+ {
+ return new DataRestor()
+ {
+ /**
+ * {@inheritDoc}
+ */
+ public void clean() throws BackupException
+ {
+ cache.clear();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void restore() throws BackupException
+ {
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void commit() throws BackupException
+ {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void rollback() throws BackupException
+ {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void close() throws BackupException
+ {
+ }
+ };
+ }
}
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/BufferedJBossCache.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/BufferedJBossCache.java 2011-01-26
15:23:23 UTC (rev 3889)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/BufferedJBossCache.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -18,6 +18,7 @@
*/
package org.exoplatform.services.jcr.impl.dataflow.persistent.jbosscache;
+import org.exoplatform.services.jcr.jbosscache.PrivilegedJBossCacheHelper;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.jboss.cache.Cache;
@@ -988,7 +989,7 @@
public void apply()
{
setCacheLocalMode();
- cache.removeNode(fqn);
+ PrivilegedJBossCacheHelper.removeNode(cache, fqn);
}
}
}
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/JBossCacheWorkspaceStorageCache.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/JBossCacheWorkspaceStorageCache.java 2011-01-26
15:23:23 UTC (rev 3889)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/JBossCacheWorkspaceStorageCache.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -37,6 +37,9 @@
import org.exoplatform.services.jcr.datamodel.QPathEntry;
import org.exoplatform.services.jcr.datamodel.ValueData;
import org.exoplatform.services.jcr.impl.Constants;
+import org.exoplatform.services.jcr.impl.backup.BackupException;
+import org.exoplatform.services.jcr.impl.backup.Backupable;
+import org.exoplatform.services.jcr.impl.backup.DataRestor;
import org.exoplatform.services.jcr.impl.dataflow.TransientNodeData;
import org.exoplatform.services.jcr.impl.dataflow.TransientPropertyData;
import org.exoplatform.services.jcr.jbosscache.ExoJBossCacheFactory;
@@ -47,13 +50,15 @@
import org.jboss.cache.Cache;
import org.jboss.cache.Fqn;
import org.jboss.cache.Node;
+import org.jboss.cache.config.Configuration.CacheMode;
import org.jboss.cache.config.EvictionRegionConfig;
-import org.jboss.cache.config.Configuration.CacheMode;
import org.jboss.cache.eviction.ExpirationAlgorithmConfig;
import org.picocontainer.Startable;
+import java.io.File;
import java.io.IOException;
import java.io.Serializable;
+import java.sql.Connection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -100,7 +105,7 @@
* @author <a href="mailto:peter.nedonosko@exoplatform.com">Peter
Nedonosko</a>
* @version $Id: JBossCacheWorkspaceStorageCache.java 13869 2008-05-05 08:40:10Z
pnedonosko $
*/
-public class JBossCacheWorkspaceStorageCache implements WorkspaceStorageCache, Startable
+public class JBossCacheWorkspaceStorageCache implements WorkspaceStorageCache, Startable,
Backupable
{
private static final Log LOG =
ExoLogger.getLogger("exo.jcr.component.core.JBossCacheWorkspaceStorageCache");
@@ -1518,9 +1523,9 @@
}
/**
- * Allows to commit the cache changes in a dedicated XA Tx in order to avoid
potential
- * deadlocks
- */
+ * Allows to commit the cache changes in a dedicated XA Tx in order to avoid
potential
+ * deadlocks
+ */
private void dedicatedTxCommit()
{
// Ensure that the commit is done in a dedicated tx to avoid deadlock due
@@ -1557,4 +1562,89 @@
}
}
}
+
+ /**
+ * {@inheritDoc}
+ */
+ public void backup(File storageDir) throws BackupException
+ {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void clean() throws BackupException
+ {
+ cleanCache();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DataRestor getDataRestorer(File storageDir, Connection jdbcConn) throws
BackupException
+ {
+ return new DataRestor()
+ {
+ /**
+ * {@inheritDoc}
+ */
+ public void clean() throws BackupException
+ {
+ cleanCache();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void restore() throws BackupException
+ {
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void commit() throws BackupException
+ {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void rollback() throws BackupException
+ {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void close() throws BackupException
+ {
+ }
+ };
+ }
+
+ /**
+ * Clean all cache data.
+ */
+ private void cleanCache()
+ {
+ cache.beginTransaction();
+
+ cache.removeNode(itemsRoot);
+ cache.removeNode(refRoot);
+ cache.removeNode(childNodes);
+ cache.removeNode(childProps);
+ cache.removeNode(childNodesList);
+ cache.removeNode(childPropsList);
+
+ cache.commitTransaction();
+
+ createResidentNode(childNodes);
+ createResidentNode(refRoot);
+ createResidentNode(childNodesList);
+ createResidentNode(childProps);
+ createResidentNode(childPropsList);
+ createResidentNode(itemsRoot);
+ }
}
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/inmemory/InmemoryContainerImpl.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/inmemory/InmemoryContainerImpl.java 2011-01-26
15:23:23 UTC (rev 3889)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/inmemory/InmemoryContainerImpl.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -107,4 +107,12 @@
{
return true;
}
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getUniqueName()
+ {
+ return name;
+ }
}
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainer.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainer.java 2011-01-26
15:23:23 UTC (rev 3889)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainer.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -23,26 +23,23 @@
import org.exoplatform.commons.utils.SecurityHelper;
import org.exoplatform.services.jcr.config.RepositoryConfigurationException;
import org.exoplatform.services.jcr.config.RepositoryEntry;
+import org.exoplatform.services.jcr.config.ValueStorageEntry;
import org.exoplatform.services.jcr.config.WorkspaceEntry;
import org.exoplatform.services.jcr.dataflow.serialization.ObjectReader;
import org.exoplatform.services.jcr.dataflow.serialization.ObjectWriter;
import org.exoplatform.services.jcr.impl.Constants;
+import org.exoplatform.services.jcr.impl.backup.BackupException;
+import org.exoplatform.services.jcr.impl.backup.Backupable;
+import org.exoplatform.services.jcr.impl.backup.ComplexDataRestor;
+import org.exoplatform.services.jcr.impl.backup.DataRestor;
+import org.exoplatform.services.jcr.impl.backup.rdbms.DBBackup;
+import org.exoplatform.services.jcr.impl.backup.rdbms.DBRestor;
+import org.exoplatform.services.jcr.impl.backup.rdbms.DirectoryRestor;
+import org.exoplatform.services.jcr.impl.backup.rdbms.RestoreTableRule;
+import org.exoplatform.services.jcr.impl.clean.rdbms.DBCleanService;
import org.exoplatform.services.jcr.impl.dataflow.serialization.ObjectReaderImpl;
import org.exoplatform.services.jcr.impl.dataflow.serialization.ObjectWriterImpl;
import org.exoplatform.services.jcr.impl.storage.WorkspaceDataContainerBase;
-import org.exoplatform.services.jcr.impl.storage.jdbc.backup.BackupException;
-import org.exoplatform.services.jcr.impl.storage.jdbc.backup.Backupable;
-import org.exoplatform.services.jcr.impl.storage.jdbc.backup.CleanException;
-import org.exoplatform.services.jcr.impl.storage.jdbc.backup.DataCleaner;
-import org.exoplatform.services.jcr.impl.storage.jdbc.backup.RestoreException;
-import org.exoplatform.services.jcr.impl.storage.jdbc.backup.util.BackupTables;
-import org.exoplatform.services.jcr.impl.storage.jdbc.backup.util.RestoreTableRule;
-import org.exoplatform.services.jcr.impl.storage.jdbc.backup.util.RestoreTables;
-import org.exoplatform.services.jcr.impl.storage.jdbc.cleaner.DBCleanHelper;
-import org.exoplatform.services.jcr.impl.storage.jdbc.cleaner.DBCleaner;
-import org.exoplatform.services.jcr.impl.storage.jdbc.cleaner.IngresSQLDBCleaner;
-import org.exoplatform.services.jcr.impl.storage.jdbc.cleaner.OracleDBCleaner;
-import org.exoplatform.services.jcr.impl.storage.jdbc.cleaner.PgSQLDBCleaner;
import org.exoplatform.services.jcr.impl.storage.jdbc.db.GenericConnectionFactory;
import org.exoplatform.services.jcr.impl.storage.jdbc.db.HSQLDBConnectionFactory;
import org.exoplatform.services.jcr.impl.storage.jdbc.db.MySQLConnectionFactory;
@@ -54,6 +51,8 @@
import org.exoplatform.services.jcr.impl.storage.jdbc.init.StorageDBInitializer;
import
org.exoplatform.services.jcr.impl.storage.jdbc.statistics.StatisticsJDBCStorageConnection;
import org.exoplatform.services.jcr.impl.storage.jdbc.update.StorageUpdateManager;
+import org.exoplatform.services.jcr.impl.storage.value.fs.FileValueStorage;
+import org.exoplatform.services.jcr.impl.util.io.DirectoryHelper;
import org.exoplatform.services.jcr.impl.util.io.FileCleaner;
import org.exoplatform.services.jcr.impl.util.io.FileCleanerHolder;
import org.exoplatform.services.jcr.impl.util.jdbc.DBInitializerException;
@@ -136,6 +135,8 @@
protected final String containerName;
+ protected final String uniqueName;
+
protected final String dbSourceName;
protected final boolean multiDb;
@@ -171,6 +172,11 @@
protected boolean useQueryHints;
/**
+ * Workspace configuration.
+ */
+ protected final WorkspaceEntry wsConfig;
+
+ /**
* Shared connection factory.
*
* Issued to share JDBC connection between system and regular workspace in case of
same database
@@ -246,7 +252,9 @@
contextInit.recall();
checkIntegrity(wsConfig, repConfig);
+ this.wsConfig = wsConfig;
this.containerName = wsConfig.getName();
+ this.uniqueName = wsConfig.getUniqueName();
this.multiDb =
Boolean.parseBoolean(wsConfig.getContainer().getParameterValue(MULTIDB));
this.valueStorageProvider = valueStorageProvider;
@@ -877,6 +885,14 @@
{
return containerName;
}
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getUniqueName()
+ {
+ return uniqueName;
+ }
/**
* {@inheritDoc}
@@ -1014,6 +1030,45 @@
/**
* {@inheritDoc}
*/
+ public void clean() throws BackupException
+ {
+ try
+ {
+ DBCleanService.cleanWorkspaceData(wsConfig);
+
+ if (wsConfig.getContainer().getValueStorages() != null)
+ {
+ for (ValueStorageEntry valueStorage :
wsConfig.getContainer().getValueStorages())
+ {
+ File valueStorageDir = new
File(valueStorage.getParameterValue(FileValueStorage.PATH));
+ if (PrivilegedFileHelper.exists(valueStorageDir))
+ {
+ DirectoryHelper.removeDirectory(valueStorageDir);
+ }
+ }
+ }
+ }
+ catch (RepositoryConfigurationException e)
+ {
+ throw new BackupException(e);
+ }
+ catch (NamingException e)
+ {
+ throw new BackupException(e);
+ }
+ catch (SQLException e)
+ {
+ throw new BackupException(e);
+ }
+ catch (IOException e)
+ {
+ throw new BackupException(e);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public void backup(File storageDir) throws BackupException
{
ObjectWriter backupInfo = null;
@@ -1051,12 +1106,61 @@
+ containerName + "')");
}
- BackupTables.backup(storageDir, dbSourceName, scripts);
+ final DataSource ds = (DataSource)new InitialContext().lookup(dbSourceName);
+ if (ds == null)
+ {
+ throw new NameNotFoundException("Data source " + dbSourceName +
" not found");
+ }
+
+ Connection jdbcConn =
+ SecurityHelper.doPrivilegedSQLExceptionAction(new
PrivilegedExceptionAction<Connection>()
+ {
+ public Connection run() throws Exception
+ {
+ return ds.getConnection();
+
+ }
+ });
+
+ DBBackup.backup(storageDir, jdbcConn, scripts);
+
+ // backup value storage
+ if (wsConfig.getContainer().getValueStorages() != null)
+ {
+ for (ValueStorageEntry valueStorage :
wsConfig.getContainer().getValueStorages())
+ {
+ File srcDir = new
File(valueStorage.getParameterValue(FileValueStorage.PATH));
+ if (!PrivilegedFileHelper.exists(srcDir))
+ {
+ throw new BackupException("Can't backup value storage.
Directory " + srcDir.getName()
+ + " doesn't exists");
+ }
+ else
+ {
+ File destValuesDir = new File(storageDir, "values");
+ File destDir = new File(destValuesDir, valueStorage.getId());
+
+ DirectoryHelper.compressDirectory(srcDir, destDir);
+ }
+ }
+ }
}
catch (IOException e)
{
throw new BackupException(e);
}
+ catch (RepositoryConfigurationException e)
+ {
+ throw new BackupException(e);
+ }
+ catch (NamingException e)
+ {
+ throw new BackupException(e);
+ }
+ catch (SQLException e)
+ {
+ throw new BackupException(e);
+ }
finally
{
if (backupInfo != null)
@@ -1076,10 +1180,11 @@
/**
* {@inheritDoc}
*/
- public void restore(File storageDir) throws RestoreException
+ public DataRestor getDataRestorer(File storageDir, Connection jdbcConn) throws
BackupException
{
+ List<DataRestor> restorers = new ArrayList<DataRestor>();
+
ObjectReader backupInfo = null;
-
try
{
backupInfo =
@@ -1100,8 +1205,8 @@
restoreTableRule.setSrcMultiDb(srcMultiDb);
restoreTableRule.setDstContainerName(containerName);
restoreTableRule.setDstMultiDb(multiDb);
- restoreTableRule.setContentFile(new File(storageDir, srcTableName +
BackupTables.CONTENT_FILE_SUFFIX));
- restoreTableRule.setContentLenFile(new File(storageDir, srcTableName +
BackupTables.CONTENT_LEN_FILE_SUFFIX));
+ restoreTableRule.setContentFile(new File(storageDir, srcTableName +
DBBackup.CONTENT_FILE_SUFFIX));
+ restoreTableRule.setContentLenFile(new File(storageDir, srcTableName +
DBBackup.CONTENT_LEN_FILE_SUFFIX));
if (multiDb)
{
@@ -1153,8 +1258,8 @@
restoreTableRule.setSrcMultiDb(srcMultiDb);
restoreTableRule.setDstContainerName(containerName);
restoreTableRule.setDstMultiDb(multiDb);
- restoreTableRule.setContentFile(new File(storageDir, srcTableName +
BackupTables.CONTENT_FILE_SUFFIX));
- restoreTableRule.setContentLenFile(new File(storageDir, srcTableName +
BackupTables.CONTENT_LEN_FILE_SUFFIX));
+ restoreTableRule.setContentFile(new File(storageDir, srcTableName +
DBBackup.CONTENT_FILE_SUFFIX));
+ restoreTableRule.setContentLenFile(new File(storageDir, srcTableName +
DBBackup.CONTENT_LEN_FILE_SUFFIX));
// auto increment ID column
restoreTableRule.setSkipColumnIndex(0);
@@ -1177,8 +1282,8 @@
restoreTableRule.setSrcMultiDb(srcMultiDb);
restoreTableRule.setDstContainerName(containerName);
restoreTableRule.setDstMultiDb(multiDb);
- restoreTableRule.setContentFile(new File(storageDir, srcTableName +
BackupTables.CONTENT_FILE_SUFFIX));
- restoreTableRule.setContentLenFile(new File(storageDir, srcTableName +
BackupTables.CONTENT_LEN_FILE_SUFFIX));
+ restoreTableRule.setContentFile(new File(storageDir, srcTableName +
DBBackup.CONTENT_FILE_SUFFIX));
+ restoreTableRule.setContentLenFile(new File(storageDir, srcTableName +
DBBackup.CONTENT_LEN_FILE_SUFFIX));
if (!multiDb || !srcMultiDb)
{
@@ -1189,121 +1294,89 @@
restoreTableRule.setConvertColumnIndex(convertColumnIndex);
}
tables.put(dstTableName, restoreTableRule);
+
+ restorers.add(new DBRestor(storageDir, jdbcConn, tables, wsConfig,
swapCleaner));
-
- File tempDir = new
File(PrivilegedSystemHelper.getProperty("java.io.tmpdir"));
- RestoreTables restoreTable = new RestoreTables(swapCleaner, tempDir,
maxBufferSize);
-
- restoreTable.restore(storageDir, dbSourceName, tables);
- }
- catch (FileNotFoundException e)
- {
- throw new RestoreException(e);
- }
- catch (IOException e)
- {
- throw new RestoreException(e);
- }
- finally
- {
- if (backupInfo != null)
+ // prepare value storage restorer
+ File backupValueStorageDir = new File(storageDir, "values");
+ if (wsConfig.getContainer().getValueStorages() != null)
{
- try
+ List<File> dataDirs = new ArrayList<File>();
+ List<File> backupDirs = new ArrayList<File>();
+
+ List<ValueStorageEntry> valueStorages =
wsConfig.getContainer().getValueStorages();
+ String[] valueStoragesFiles =
PrivilegedFileHelper.list(backupValueStorageDir);
+
+ if ((valueStoragesFiles == null && valueStorages.size() != 0)
+ || (valueStoragesFiles != null && valueStoragesFiles.length !=
valueStorages.size()))
{
- backupInfo.close();
+ throw new RepositoryConfigurationException("Workspace configuration
[" + wsConfig.getName()
+ + "] has a different amount of value storages than exist in
backup");
}
- catch (IOException e)
- {
- throw new RestoreException(e);
- }
- }
- }
- }
- /**
- * {@inheritDoc}
- */
- public DataCleaner getDataCleaner() throws CleanException
- {
- DataCleaner dbCleaner;
-
- try
- {
- final DataSource ds = (DataSource)new InitialContext().lookup(dbSourceName);
- if (ds == null)
- {
- throw new NameNotFoundException("Data source " + dbSourceName +
" not found");
- }
-
- Connection jdbcConn =
- SecurityHelper.doPrivilegedSQLExceptionAction(new
PrivilegedExceptionAction<Connection>()
+ for (ValueStorageEntry valueStorage : valueStorages)
{
- public Connection run() throws Exception
+ File backupDir = new File(backupValueStorageDir, valueStorage.getId());
+ if (!PrivilegedFileHelper.exists(backupDir))
{
- return ds.getConnection();
+ throw new RepositoryConfigurationException("Can't restore
value storage. Directory "
+ + backupDir.getName() + " doesn't exists");
+ }
+ else
+ {
+ File dataDir = new
File(valueStorage.getParameterValue(FileValueStorage.PATH));
+ dataDirs.add(dataDir);
+ backupDirs.add(backupDir);
}
- });
+ }
- String dialect = DialectDetecter.detect(jdbcConn.getMetaData());
-
- List<String> cleanScripts = new ArrayList<String>();
- if (multiDb)
- {
- cleanScripts.add("drop table JCR_MREF");
- cleanScripts.add("drop table JCR_MVALUE");
- cleanScripts.add("drop table JCR_MITEM");
+ restorers.add(new DirectoryRestor(dataDirs, backupDirs));
}
else
{
- cleanScripts
- .add("delete from JCR_SVALUE where exists(select * from JCR_SITEM
where JCR_SITEM.ID=JCR_SVALUE.PROPERTY_ID and JCR_SITEM.CONTAINER_NAME='"
- + containerName + "')");
- cleanScripts
- .add("delete from JCR_SREF where exists(select * from JCR_SITEM where
JCR_SITEM.ID=JCR_SREF.PROPERTY_ID and JCR_SITEM.CONTAINER_NAME='"
- + containerName + "')");
- }
-
- if (!multiDb && dialect.equals(DBConstants.DB_DIALECT_HSQLDB))
- {
- cleanScripts.add("delete from JCR_SITEM where I_CLASS=2 and
CONTAINER_NAME='" + containerName + "'");
-
- dbCleaner = new DBCleaner(jdbcConn, cleanScripts, new
DBCleanHelper(containerName, jdbcConn));
- }
- else
- {
- if (!multiDb)
+ if (PrivilegedFileHelper.exists(backupValueStorageDir))
{
- cleanScripts.add("delete from JCR_SITEM where
CONTAINER_NAME='" + containerName + "'");
+ throw new RepositoryConfigurationException("Value storage didn't
configure in workspace ["
+ + wsConfig.getName() + "] configuration but value storage backup
files exist");
}
-
- if (dialect.equals(DBConstants.DB_DIALECT_PGSQL))
- {
- dbCleaner = new PgSQLDBCleaner(jdbcConn, cleanScripts);
- }
- else if (dialect.equals(DBConstants.DB_DIALECT_INGRES))
- {
- dbCleaner = new IngresSQLDBCleaner(jdbcConn, cleanScripts);
- }
- else if (dialect.equals(DBConstants.DB_DIALECT_ORACLE) ||
dialect.equals(DBConstants.DB_DIALECT_ORACLEOCI))
- {
- dbCleaner = new OracleDBCleaner(jdbcConn, cleanScripts);
- }
- else
- {
- dbCleaner = new DBCleaner(jdbcConn, cleanScripts);
- }
}
- return dbCleaner;
+ return new ComplexDataRestor(restorers);
}
+ catch (FileNotFoundException e)
+ {
+ throw new BackupException(e);
+ }
+ catch (IOException e)
+ {
+ throw new BackupException(e);
+ }
catch (NamingException e)
{
- throw new CleanException(e);
+ throw new BackupException(e);
}
catch (SQLException e)
{
- throw new CleanException(e);
+ throw new BackupException(e);
}
+ catch (RepositoryConfigurationException e)
+ {
+ throw new BackupException(e);
+ }
+ finally
+ {
+ if (backupInfo != null)
+ {
+ try
+ {
+ backupInfo.close();
+ }
+ catch (IOException e)
+ {
+ LOG.error("Can't close object reader", e);
+ }
+ }
+ }
}
}
Added:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/util/io/DirectoryHelper.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/util/io/DirectoryHelper.java
(rev 0)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/util/io/DirectoryHelper.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2009 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.util.io;
+
+import org.exoplatform.commons.utils.PrivilegedFileHelper;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import java.util.zip.ZipOutputStream;
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * Helper contains method to perform operations with not empty directory.
+ *
+ * Date: 25 01 2011
+ *
+ * @author <a href="mailto:anatoliy.bazko@exoplatform.com.ua">Anatoliy
Bazko</a>
+ * @version $Id: FSDirectory.java 34360 2010-11-11 11:11:11Z tolusha $
+ */
+public class DirectoryHelper
+{
+
+ /**
+ * Copy directory.
+ *
+ * @param srcPath
+ * source path
+ * @param dstPath
+ * destination path
+ * @throws IOException
+ * if any exception occurred
+ */
+ public static void copyDirectory(File srcPath, File dstPath) throws IOException
+ {
+ if (PrivilegedFileHelper.isDirectory(srcPath))
+ {
+ if (!PrivilegedFileHelper.exists(dstPath))
+ {
+ PrivilegedFileHelper.mkdirs(dstPath);
+ }
+
+ String files[] = PrivilegedFileHelper.list(srcPath);
+ for (int i = 0; i < files.length; i++)
+ {
+ copyDirectory(new File(srcPath, files[i]), new File(dstPath, files[i]));
+ }
+ }
+ else
+ {
+ InputStream in = null;
+ OutputStream out = null;
+
+ try
+ {
+ in = PrivilegedFileHelper.fileInputStream(srcPath);
+ out = PrivilegedFileHelper.fileOutputStream(dstPath);
+
+ // Transfer bytes from in to out
+ byte[] buf = new byte[2048];
+
+ int len;
+
+ while ((len = in.read(buf)) > 0)
+ {
+ out.write(buf, 0, len);
+ }
+ }
+ finally
+ {
+ if (in != null)
+ {
+ in.close();
+ }
+
+ if (out != null)
+ {
+ out.flush();
+ out.close();
+ }
+ }
+ }
+ }
+
+ /**
+ * Remove directory.
+ *
+ * @param dir
+ * directory to remove
+ * @throws IOException
+ * if any exception occurred
+ */
+ public static void removeDirectory(File dir) throws IOException
+ {
+ if (PrivilegedFileHelper.isDirectory(dir))
+ {
+ for (File subFile : PrivilegedFileHelper.listFiles(dir))
+ {
+ removeDirectory(subFile);
+ }
+
+ if (!PrivilegedFileHelper.delete(dir))
+ {
+ throw new IOException("Can't remove folder : " +
PrivilegedFileHelper.getCanonicalPath(dir));
+ }
+ }
+ else
+ {
+ if (!PrivilegedFileHelper.delete(dir))
+ {
+ throw new IOException("Can't remove file : " +
PrivilegedFileHelper.getCanonicalPath(dir));
+ }
+ }
+ }
+
+ /**
+ * Compress directory.
+ *
+ * @param srcPath
+ * source path
+ * @param dstPath
+ * destination path
+ * @throws IOException
+ * if any exception occurred
+ */
+ public static void compressDirectory(File srcPath, File dstPath) throws IOException
+ {
+ if (PrivilegedFileHelper.isDirectory(srcPath))
+ {
+ if (!PrivilegedFileHelper.exists(dstPath))
+ {
+ PrivilegedFileHelper.mkdirs(dstPath);
+ }
+
+ String files[] = PrivilegedFileHelper.list(srcPath);
+ for (int i = 0; i < files.length; i++)
+ {
+ compressDirectory(new File(srcPath, files[i]), new File(dstPath, files[i]));
+ }
+ }
+ else
+ {
+ InputStream in = null;
+ ZipOutputStream out = null;
+
+ try
+ {
+ in = PrivilegedFileHelper.fileInputStream(srcPath);
+ out = PrivilegedFileHelper.zipOutputStream(dstPath);
+ out.putNextEntry(new ZipEntry(srcPath.getName()));
+
+ // Transfer bytes from in to out
+ byte[] buf = new byte[2048];
+
+ int len;
+
+ while ((len = in.read(buf)) > 0)
+ {
+ out.write(buf, 0, len);
+ }
+ }
+ finally
+ {
+ if (in != null)
+ {
+ in.close();
+ }
+
+ if (out != null)
+ {
+ out.flush();
+ out.closeEntry();
+ out.close();
+ }
+ }
+ }
+ }
+
+ /**
+ * Uncompress directory.
+ *
+ * @param srcPath
+ * source path
+ * @param dstPath
+ * destination path
+ * @throws IOException
+ * if any exception occurred
+ */
+ public static void uncompressDirectory(File srcPath, File dstPath) throws IOException
+ {
+ if (PrivilegedFileHelper.isDirectory(srcPath))
+ {
+ if (!PrivilegedFileHelper.exists(dstPath))
+ {
+ PrivilegedFileHelper.mkdirs(dstPath);
+ }
+
+ String files[] = PrivilegedFileHelper.list(srcPath);
+ for (int i = 0; i < files.length; i++)
+ {
+ uncompressDirectory(new File(srcPath, files[i]), new File(dstPath,
files[i]));
+ }
+ }
+ else
+ {
+ ZipInputStream in = null;
+ OutputStream out = null;
+
+ try
+ {
+ in = PrivilegedFileHelper.zipInputStream(srcPath);
+ in.getNextEntry();
+ out = PrivilegedFileHelper.fileOutputStream(dstPath);
+
+ // Transfer bytes from in to out
+ byte[] buf = new byte[2048];
+
+ int len;
+
+ while ((len = in.read(buf)) > 0)
+ {
+ out.write(buf, 0, len);
+ }
+ }
+ finally
+ {
+ if (in != null)
+ {
+ in.close();
+ }
+
+ if (out != null)
+ {
+ out.close();
+ }
+ }
+ }
+ }
+}
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/jbosscache/PrivilegedJBossCacheHelper.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/jbosscache/PrivilegedJBossCacheHelper.java 2011-01-26
15:23:23 UTC (rev 3889)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/jbosscache/PrivilegedJBossCacheHelper.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -164,4 +164,39 @@
}
}
+ /**
+ * Remove node in privileged mode.
+ *
+ * @param cache
+ */
+ public static Object removeNode(final Cache<Serializable, Object> cache, final
Fqn fqn) throws CacheException
+ {
+ PrivilegedExceptionAction<Object> action = new
PrivilegedExceptionAction<Object>()
+ {
+ public Object run() throws Exception
+ {
+ return cache.removeNode(fqn);
+ }
+ };
+ try
+ {
+ return AccessController.doPrivileged(action);
+ }
+ catch (PrivilegedActionException pae)
+ {
+ Throwable cause = pae.getCause();
+ if (cause instanceof CacheException)
+ {
+ throw (CacheException)cause;
+ }
+ else if (cause instanceof RuntimeException)
+ {
+ throw (RuntimeException)cause;
+ }
+ else
+ {
+ throw new RuntimeException(cause);
+ }
+ }
+ }
}
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/storage/DataContainer.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/storage/DataContainer.java 2011-01-26
15:23:23 UTC (rev 3889)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/storage/DataContainer.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -41,6 +41,11 @@
String getName();
/**
+ * @return unique name of this container
+ */
+ String getUniqueName();
+
+ /**
* @return current storage version
*/
String getStorageVersion();
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/storage/WorkspaceDataContainer.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/storage/WorkspaceDataContainer.java 2011-01-26
15:23:23 UTC (rev 3889)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/storage/WorkspaceDataContainer.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -97,4 +97,5 @@
* @return the value of 'check-sns-new-connection' parameter
*/
boolean isCheckSNSNewConnection();
+
}
Modified:
jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/TestCacheableWorkspaceDataManager.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/TestCacheableWorkspaceDataManager.java 2011-01-26
15:23:23 UTC (rev 3889)
+++
jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/TestCacheableWorkspaceDataManager.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -586,6 +586,12 @@
return "0";
}
+ @Override
+ public String getUniqueName()
+ {
+ return "MyWorkspaceDataContainer";
+ }
+
};
}
Modified:
jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/util/jdbc/TestDBCleaner.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/util/jdbc/TestDBCleaner.java 2011-01-26
15:23:23 UTC (rev 3889)
+++
jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/util/jdbc/TestDBCleaner.java 2011-01-26
16:18:11 UTC (rev 3890)
@@ -20,10 +20,10 @@
import org.exoplatform.services.jcr.RepositoryService;
import org.exoplatform.services.jcr.config.RepositoryEntry;
import org.exoplatform.services.jcr.config.WorkspaceEntry;
+import org.exoplatform.services.jcr.impl.clean.rdbms.DBCleanService;
import org.exoplatform.services.jcr.impl.core.NodeImpl;
import org.exoplatform.services.jcr.impl.core.RepositoryImpl;
import org.exoplatform.services.jcr.impl.core.SessionImpl;
-import org.exoplatform.services.jcr.impl.storage.jdbc.backup.Backupable;
import org.exoplatform.services.jcr.util.IdGenerator;
import org.exoplatform.services.jcr.util.TesterConfigurationHelper;
@@ -31,8 +31,6 @@
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
-import java.util.ArrayList;
-import java.util.List;
import javax.jcr.Node;
import javax.jcr.Session;
@@ -174,28 +172,12 @@
assertTrue(res.next());
// remove content
- List<Backupable> backupable = new ArrayList<Backupable>();
- for (String name :
repositoryService.getRepository(repositoryName).getWorkspaceNames())
- {
-
backupable.addAll(repositoryService.getRepository(repositoryName).getWorkspaceContainer(name)
- .getComponentInstancesOfType(Backupable.class));
- }
+ DBCleanService.cleanRepositoryData(repositoryEntry);
- for (Backupable component : backupable)
- {
- component.getDataCleaner().clean();
- }
-
// check - does JCR_SITEM become empty
- try
- {
- res = statement.executeQuery("select * from JCR_MITEM where ID='"
+ id + "'");
- fail();
- }
- catch (SQLException e)
- {
- //ok
- }
+ res = statement.executeQuery("select * from JCR_MITEM where ID='" +
id + "'");
+ assertFalse(res.next());
+
statement.close();
service.removeRepository(repositoryName);
@@ -227,18 +209,8 @@
assertTrue(res.next());
// remove content
- List<Backupable> backupable = new ArrayList<Backupable>();
- for (String name :
repositoryService.getRepository(repositoryName).getWorkspaceNames())
- {
-
backupable.addAll(repositoryService.getRepository(repositoryName).getWorkspaceContainer(name)
- .getComponentInstancesOfType(Backupable.class));
- }
+ DBCleanService.cleanRepositoryData(repositoryEntry);
- for (Backupable component : backupable)
- {
- component.getDataCleaner().clean();
- }
-
// check - does JCR_SITEM become empty
res = statement.executeQuery("select * from JCR_SITEM where ID='" +
wsName + id + "'");
assertFalse(res.next());
@@ -273,25 +245,11 @@
assertTrue(res.next());
// remove content
- List<Backupable> backupable =
- repositoryService.getRepository(repositoryName).getWorkspaceContainer(wsName)
- .getComponentInstancesOfType(Backupable.class);
+ DBCleanService.cleanWorkspaceData(repositoryEntry.getWorkspaceEntries().get(0));
- for (Backupable component : backupable)
- {
- component.getDataCleaner().clean();
- }
-
// check - does JCR_SITEM become empty
- try
- {
- res = statement.executeQuery("select * from JCR_MITEM where ID='"
+ id + "'");
- fail();
- }
- catch (SQLException e)
- {
- //ok
- }
+ res = statement.executeQuery("select * from JCR_MITEM where ID='" +
id + "'");
+ assertFalse(res.next());
statement.close();
service.removeRepository(repositoryName);
@@ -337,15 +295,8 @@
assertTrue(res.next());
// remove content
- List<Backupable> backupable =
-
repositoryService.getRepository(repositoryName).getWorkspaceContainer(workspaceEntry.getName())
- .getComponentInstancesOfType(Backupable.class);
+ DBCleanService.cleanWorkspaceData(repositoryEntry.getWorkspaceEntries().get(0));
- for (Backupable component : backupable)
- {
- component.getDataCleaner().clean();
- }
-
// check - does JCR_SITEM become empty
res = statement.executeQuery("select * from JCR_SITEM where ID='" +
workspaceEntry.getName() + id + "'");
assertFalse(res.next());
Modified:
jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-configuration.xml
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-configuration.xml 2011-01-26
15:23:23 UTC (rev 3889)
+++
jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-configuration.xml 2011-01-26
16:18:11 UTC (rev 3890)
@@ -597,6 +597,33 @@
</properties-param>
</init-params>
</component-plugin>
+ <component-plugin>
+ <name>bind.datasource</name>
+ <set-method>addPlugin</set-method>
+ <type>org.exoplatform.services.naming.BindReferencePlugin</type>
+ <init-params>
+ <value-param>
+ <name>bind-name</name>
+ <value>testdbcleaner</value>
+ </value-param>
+ <value-param>
+ <name>class-name</name>
+ <value>javax.sql.DataSource</value>
+ </value-param>
+ <value-param>
+ <name>factory</name>
+ <value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
+ </value-param>
+ <properties-param>
+ <name>ref-addresses</name>
+ <description>ref-addresses</description>
+ <property name="driverClassName"
value="org.hsqldb.jdbcDriver"/>
+ <property name="url"
value="jdbc:hsqldb:file:target/temp/data/testdbcleaner"/>
+ <property name="username" value="sa"/>
+ <property name="password" value=""/>
+ </properties-param>
+ </init-params>
+ </component-plugin>
<component-plugin>
<name>bind.jcr</name>
<set-method>addPlugin</set-method>
Modified:
jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-jcr-config.xml
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-jcr-config.xml 2011-01-26
15:23:23 UTC (rev 3889)
+++
jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-jcr-config.xml 2011-01-26
16:18:11 UTC (rev 3890)
@@ -27,6 +27,7 @@
<property name="update-storage" value="false"
/>
<property name="max-buffer-size" value="200k"
/>
<property name="swap-directory"
value="target/temp/swap/ws" />
+ <property name="dialect" value="auto" />
</properties>
<value-storages>
<value-storage id="ws"
@@ -96,6 +97,7 @@
<property name="update-storage" value="false"
/>
<property name="max-buffer-size" value="200k"
/>
<property name="swap-directory"
value="target/temp/swap/ws1" />
+ <property name="dialect" value="auto" />
</properties>
<value-storages>
<value-storage id="ws1"
@@ -170,6 +172,7 @@
<property name="update-storage" value="false"
/>
<property name="max-buffer-size" value="200k"
/>
<property name="swap-directory"
value="target/temp/swap/ws2" />
+ <property name="dialect" value="auto" />
</properties>
<value-storages>
<value-storage id="ws2"
@@ -245,6 +248,7 @@
<property name="update-storage" value="false"
/>
<property name="max-buffer-size" value="200k"
/>
<property name="swap-directory"
value="target/temp/swap/ws3" />
+ <property name="dialect" value="auto" />
</properties>
<value-storages>
<value-storage id="ws3_big"
@@ -344,6 +348,7 @@
<property name="update-storage" value="false"
/>
<property name="max-buffer-size" value="200k"
/>
<property name="swap-directory"
value="target/temp/swap/wsdb2" />
+ <property name="dialect" value="auto" />
</properties>
<value-storages>
<value-storage id="ws"
@@ -412,6 +417,7 @@
<property name="update-storage" value="false"
/>
<property name="max-buffer-size" value="200k"
/>
<property name="swap-directory"
value="target/temp/swap/ws1db2" />
+ <property name="dialect" value="auto" />
</properties>
<value-storages>
<value-storage id="ws1"
@@ -491,6 +497,7 @@
<property name="update-storage" value="false"
/>
<property name="max-buffer-size" value="200k"
/>
<property name="swap-directory"
value="target/temp/swap/wstck" />
+ <property name="dialect" value="auto" />
</properties>
<value-storages>
<value-storage id="ws"
@@ -572,6 +579,7 @@
<property name="update-storage" value="false"
/>
<property name="max-buffer-size" value="200k"
/>
<property name="swap-directory"
value="target/temp/swap/ws1tck" />
+ <property name="dialect" value="auto" />
</properties>
<value-storages>
<value-storage id="ws1"
@@ -651,6 +659,7 @@
<property name="update-storage" value="false"
/>
<property name="max-buffer-size" value="200k"
/>
<property name="swap-directory"
value="target/temp/swap/ws2tck" />
+ <property name="dialect" value="auto" />
</properties>
<value-storages>
<value-storage id="ws2"
Modified:
jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/test-configuration.xml
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/test-configuration.xml 2011-01-26
15:23:23 UTC (rev 3889)
+++
jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/test-configuration.xml 2011-01-26
16:18:11 UTC (rev 3890)
@@ -579,7 +579,7 @@
</properties-param>
</init-params>
</component-plugin>
-<component-plugin>
+ <component-plugin>
<name>bind.datasource</name>
<set-method>addPlugin</set-method>
<type>org.exoplatform.services.naming.BindReferencePlugin</type>