[exo-jcr-commits] exo-jcr SVN: r3596 - in jcr/trunk/exo.jcr.component.ext: src/main/java/org/exoplatform/services/jcr/ext/backup/impl and 3 other directories.
do-not-reply at jboss.org
do-not-reply at jboss.org
Thu Dec 2 10:44:14 EST 2010
Author: tolusha
Date: 2010-12-02 10:44:13 -0500 (Thu, 02 Dec 2010)
New Revision: 3596
Added:
jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/impl/rdbms/FullBackupJob.java
jcr/trunk/exo.jcr.component.ext/src/test/java/org/exoplatform/services/jcr/ext/backup/TestFullBackupJob.java
Modified:
jcr/trunk/exo.jcr.component.ext/pom.xml
jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/impl/IndexCleanHelper.java
jcr/trunk/exo.jcr.component.ext/src/test/resources/conf/standalone/test-jcr-ext-config.xml
Log:
EXOJCR-1078: add RDBMC full backup job
Modified: jcr/trunk/exo.jcr.component.ext/pom.xml
===================================================================
--- jcr/trunk/exo.jcr.component.ext/pom.xml 2010-12-02 14:02:19 UTC (rev 3595)
+++ jcr/trunk/exo.jcr.component.ext/pom.xml 2010-12-02 15:44:13 UTC (rev 3596)
@@ -187,6 +187,7 @@
<include>**/replication/async/**/*.java</include>
<include>**/backup/TestBackupManager.java</include>
<include>**/backup/TestFileNameProduser.java</include>
+ <include>**/**/TestFullBackupJob.java</include>
</includes>
<excludes>
<exclude>**/BaseStandaloneTest.java</exclude>
Modified: jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/impl/IndexCleanHelper.java
===================================================================
--- jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/impl/IndexCleanHelper.java 2010-12-02 14:02:19 UTC (rev 3595)
+++ jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/impl/IndexCleanHelper.java 2010-12-02 15:44:13 UTC (rev 3596)
@@ -20,6 +20,7 @@
import org.exoplatform.services.jcr.config.QueryHandlerParams;
import org.exoplatform.services.jcr.config.RepositoryConfigurationException;
import org.exoplatform.services.jcr.config.WorkspaceEntry;
+import org.exoplatform.services.jcr.impl.core.query.SystemSearchManager;
import java.io.File;
import java.io.IOException;
@@ -52,7 +53,7 @@
if (isSystem)
{
- removeFolder(new File(indexDir + "_system"));
+ removeFolder(new File(indexDir + "_" + SystemSearchManager.INDEX_DIR_SUFFIX));
}
}
Added: jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/impl/rdbms/FullBackupJob.java
===================================================================
--- jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/impl/rdbms/FullBackupJob.java (rev 0)
+++ jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/impl/rdbms/FullBackupJob.java 2010-12-02 15:44:13 UTC (rev 3596)
@@ -0,0 +1,454 @@
+/*
+ * 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.ext.backup.impl.rdbms;
+
+import org.exoplatform.commons.utils.PrivilegedFileHelper;
+import org.exoplatform.commons.utils.SecurityHelper;
+import org.exoplatform.services.jcr.config.QueryHandlerParams;
+import org.exoplatform.services.jcr.config.RepositoryConfigurationException;
+import org.exoplatform.services.jcr.config.ValueStorageEntry;
+import org.exoplatform.services.jcr.config.WorkspaceEntry;
+import org.exoplatform.services.jcr.core.ManageableRepository;
+import org.exoplatform.services.jcr.dataflow.serialization.ObjectWriter;
+import org.exoplatform.services.jcr.ext.backup.BackupConfig;
+import org.exoplatform.services.jcr.ext.backup.impl.AbstractFullBackupJob;
+import org.exoplatform.services.jcr.ext.backup.impl.FileNameProducer;
+import org.exoplatform.services.jcr.impl.core.query.SystemSearchManager;
+import org.exoplatform.services.jcr.impl.dataflow.serialization.ObjectWriterImpl;
+import org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer;
+import org.exoplatform.services.jcr.impl.storage.value.fs.FileValueStorage;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+import java.security.PrivilegedExceptionAction;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.util.Calendar;
+
+import javax.naming.InitialContext;
+import javax.naming.NameNotFoundException;
+import javax.naming.NamingException;
+import javax.sql.DataSource;
+
+/**
+ * Created by The eXo Platform SARL Author : Alex Reshetnyak alex.reshetnyak at exoplatform.com.ua Nov
+ * 21, 2007
+ */
+public class FullBackupJob extends AbstractFullBackupJob
+{
+
+ /**
+ * Logger.
+ */
+ protected static Log log = ExoLogger.getLogger("exo.jcr.component.ext.FullBackupJob");
+
+ /**
+ * Index directory in full backup storage.
+ */
+ public static final String INDEX_DIR = "index";
+
+ /**
+ * System index directory in full backup storage.
+ */
+ public static final String SYSTEM_INDEX_DIR = INDEX_DIR + "_" + SystemSearchManager.INDEX_DIR_SUFFIX;
+
+ /**
+ * Value storage directory in full backup storage.
+ */
+ public static final String VALUE_STORAGE_DIR = "values";
+
+ public static final String CONTENT_FILE_SUFFIX = "dump";
+
+ public static final String CONTENT_LEN_FILE_SUFFIX = "len";
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected URL createStorage() throws FileNotFoundException, IOException
+ {
+ FileNameProducer fnp =
+ new FileNameProducer(config.getRepository(), config.getWorkspace(),
+ PrivilegedFileHelper.getAbsolutePath(config.getBackupDir()), super.timeStamp, true, true);
+
+ return new URL("file:" + PrivilegedFileHelper.getAbsolutePath(fnp.getNextFile()));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void init(ManageableRepository repository, String workspaceName, BackupConfig config, Calendar timeStamp)
+ {
+ this.repository = repository;
+ this.workspaceName = workspaceName;
+ this.config = config;
+ this.timeStamp = timeStamp;
+
+ try
+ {
+ url = createStorage();
+ }
+ catch (FileNotFoundException e)
+ {
+ log.error("Full backup initialization failed ", e);
+ notifyError("Full backup initialization failed ", e);
+ }
+ catch (IOException e)
+ {
+ log.error("Full backup initialization failed ", e);
+ notifyError("Full backup initialization failed ", e);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void run()
+ {
+ notifyListeners();
+
+ Connection jdbcConn = null;
+ try
+ {
+ WorkspaceEntry workspaceEntry = null;
+ for (WorkspaceEntry entry : repository.getConfiguration().getWorkspaceEntries())
+ {
+ if (entry.getName().equals(workspaceName))
+ {
+ workspaceEntry = entry;
+ break;
+ }
+ }
+ if (workspaceEntry == null)
+ {
+ throw new RepositoryConfigurationException("Workpace name " + workspaceName
+ + " not found in repository configuration");
+ }
+
+ String dsName = workspaceEntry.getContainer().getParameterValue(JDBCWorkspaceDataContainer.SOURCE_NAME);
+ if (dsName == null)
+ {
+ throw new RepositoryConfigurationException("Source name not found in workspace configuration "
+ + workspaceName);
+ }
+
+ final DataSource ds = (DataSource)new InitialContext().lookup(dsName);
+ if (ds == null)
+ {
+ throw new NameNotFoundException("Data source name " + dsName + " not found");
+ }
+
+ jdbcConn =
+ SecurityHelper.doPriviledgedSQLExceptionAction(new PrivilegedExceptionAction<Connection>()
+ {
+ public Connection run() throws Exception
+ {
+ return ds.getConnection();
+
+ }
+ });
+
+
+ // dump JCR data
+ Boolean multiDb = Boolean.parseBoolean(workspaceEntry.getContainer().getParameterValue(JDBCWorkspaceDataContainer.MULTIDB));
+
+ String[][] scripts;
+ if (multiDb)
+ {
+ scripts =
+ new String[][]{{"JCR_MVALUE", "select * from JCR_MVALUE"}, {"JCR_MREF", "select * from JCR_MREF"},
+ {"JCR_MITEM", "select * from JCR_MITEM"}};
+ }
+ else
+ {
+ scripts =
+ new String[][]{
+ {
+ "JCR_SVALUE",
+ "select from JCR_SVALUE where exists(select * from JCR_SITEM where JCR_SITEM.ID=JCR_SVALUE.PROPERTY_ID and JCR_SITEM.CONTAINER_NAME="
+ + workspaceEntry.getName() + ")"},
+ {
+ "JCR_SREF",
+ "select from JCR_SREF where exists(select * from JCR_SITEM where JCR_SITEM.ID=JCR_SREF.PROPERTY_ID and JCR_SITEM.CONTAINER_NAME="
+ + workspaceEntry.getName() + ")"},
+ {"JCR_SITEM", "select from JCR_SITEM where CONTAINER_NAME=" + workspaceEntry.getName()}};
+ }
+
+ for (String script[] : scripts)
+ {
+ dumpTable(jdbcConn, script[0], script[1]);
+ }
+
+ // copy value storage directory
+ for (ValueStorageEntry valueStorage : workspaceEntry.getContainer().getValueStorages())
+ {
+ File srcDir = new File(valueStorage.getParameterValue(FileValueStorage.PATH));
+ if (!PrivilegedFileHelper.exists(srcDir))
+ {
+ throw new FileNotFoundException("File or directory " + srcDir.getName() + " doesn't exists");
+ }
+
+ File destValuesDir = new File(getStorageURL().getFile(), VALUE_STORAGE_DIR);
+ File destDir = new File(destValuesDir, valueStorage.getId());
+
+ copyDirectory(srcDir, destDir);
+ }
+
+ // copy index directory
+ File srcDir = new File(workspaceEntry.getQueryHandler().getParameterValue(QueryHandlerParams.PARAM_INDEX_DIR));
+ if (!PrivilegedFileHelper.exists(srcDir))
+ {
+ throw new FileNotFoundException("File or directory " + srcDir.getName() + " doesn't exists");
+ }
+
+ File destDir = new File(getStorageURL().getFile(), INDEX_DIR);
+ copyDirectory(srcDir, destDir);
+
+ if (repository.getConfiguration().getSystemWorkspaceName().equals(workspaceName))
+ {
+ srcDir = new File(PrivilegedFileHelper.getCanonicalPath(srcDir) + "_" + SystemSearchManager.INDEX_DIR_SUFFIX);
+ if (!PrivilegedFileHelper.exists(srcDir))
+ {
+ throw new FileNotFoundException("File or directory " + srcDir.getName() + " doesn't exists");
+ }
+
+ destDir = new File(getStorageURL().getFile(), SYSTEM_INDEX_DIR);
+ }
+ copyDirectory(srcDir, destDir);
+ }
+ catch (RepositoryConfigurationException e)
+ {
+ log.error("Full backup failed " + getStorageURL().getPath(), e);
+ notifyError("Full backup failed", e);
+ }
+ catch (NameNotFoundException e)
+ {
+ log.error("Full backup failed " + getStorageURL().getPath(), e);
+ notifyError("Full backup failed", e);
+ }
+ catch (NamingException e)
+ {
+ log.error("Full backup failed " + getStorageURL().getPath(), e);
+ notifyError("Full backup failed", e);
+ }
+ catch (SQLException e)
+ {
+ log.error("Full backup failed " + getStorageURL().getPath(), e);
+ notifyError("Full backup failed", e);
+ }
+ catch (IOException e)
+ {
+ log.error("Full backup failed " + getStorageURL().getPath(), e);
+ notifyError("Full backup failed", e);
+ }
+ finally
+ {
+ if (jdbcConn != null)
+ {
+ try
+ {
+ jdbcConn.close();
+ }
+ catch (SQLException e)
+ {
+ log.error("Full backup failed " + getStorageURL().getPath(), e);
+ notifyError("Full backup failed", e);
+ }
+ }
+ }
+
+ state = FINISHED;
+ notifyListeners();
+ }
+
+ /**
+ * Dump table.
+ */
+ private void dumpTable(Connection jdbcConn, String tableName, String script) throws SQLException, IOException
+ {
+ ObjectWriter contentWriter = null;
+ ObjectWriter contentLenWriter = null;
+ PreparedStatement stmt = null;
+ try
+ {
+ File contentFile = new File(getStorageURL().getFile(), tableName + "." + CONTENT_FILE_SUFFIX);
+ contentWriter = new ObjectWriterImpl(PrivilegedFileHelper.fileOutputStream(contentFile));
+
+ File contentLenFile = new File(getStorageURL().getFile(), tableName + "." + CONTENT_LEN_FILE_SUFFIX);
+ contentLenWriter = new ObjectWriterImpl(PrivilegedFileHelper.fileOutputStream(contentLenFile));
+
+ stmt = jdbcConn.prepareStatement(script);
+ ResultSet rs = stmt.executeQuery();
+ ResultSetMetaData metaData = rs.getMetaData();
+
+ int columnCount = metaData.getColumnCount();
+
+ contentWriter.writeInt(columnCount);
+ for (int i = 0; i < columnCount; i++)
+ {
+ contentWriter.writeInt(metaData.getColumnType(i + 1));
+ }
+
+ // Now we can output the actual data
+ while (rs.next())
+ {
+ for (int i = 0; i < columnCount; i++)
+ {
+ String str = rs.getString(i + 1);
+ InputStream value = str == null ? null : new ByteArrayInputStream(str.getBytes());
+ if (value == null)
+ {
+ contentLenWriter.writeByte((byte)0);
+ }
+ 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;
+ }
+ writeCompressedContentLen(contentLenWriter, len);
+ }
+ }
+ }
+ rs.close();
+ }
+ finally
+ {
+ if (contentWriter != null)
+ {
+ contentWriter.close();
+ }
+
+ if (contentLenWriter != null)
+ {
+ contentLenWriter.close();
+ }
+
+ if (stmt != null)
+ {
+ stmt.close();
+ }
+ }
+ }
+
+ /**
+ * @throws IOException
+ */
+ private void writeCompressedContentLen(ObjectWriter out, long len) throws IOException
+ {
+ if (len < Byte.MAX_VALUE)
+ {
+ out.writeByte((byte)1);
+ out.writeByte((byte)len);
+ }
+ else if (len < Integer.MAX_VALUE)
+ {
+ out.writeByte((byte)2);
+ out.writeInt((int)len);
+ }
+ else
+ {
+ out.writeByte((byte)3);
+ out.writeLong(len);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void stop()
+ {
+ log.info("Stop requested " + getStorageURL().getPath());
+ }
+
+ /**
+ * Copy directory.
+ *
+ * @param srcPath
+ * source path
+ * @param dstPath
+ * destination path
+ * @throws IOException
+ * if any exception occurred
+ */
+ private 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.close();
+ }
+ }
+ }
+ }
+}
Added: jcr/trunk/exo.jcr.component.ext/src/test/java/org/exoplatform/services/jcr/ext/backup/TestFullBackupJob.java
===================================================================
--- jcr/trunk/exo.jcr.component.ext/src/test/java/org/exoplatform/services/jcr/ext/backup/TestFullBackupJob.java (rev 0)
+++ jcr/trunk/exo.jcr.component.ext/src/test/java/org/exoplatform/services/jcr/ext/backup/TestFullBackupJob.java 2010-12-02 15:44:13 UTC (rev 3596)
@@ -0,0 +1,71 @@
+/*
+ * 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.ext.backup;
+
+import org.exoplatform.services.jcr.ext.backup.impl.rdbms.FullBackupJob;
+
+import java.io.File;
+import java.net.URL;
+import java.util.Calendar;
+
+/**
+ * @author <a href="mailto:anatoliy.bazko at gmail.com">Anatoliy Bazko</a>
+ * @version $Id: TestFullBackupJob.java 34360 2009-07-22 23:58:59Z tolusha $
+ */
+public class TestFullBackupJob extends AbstractBackupTestCase
+{
+
+ public void testRDBMSFullBackupJob() throws Exception
+ {
+ FullBackupJob job = new FullBackupJob();
+ BackupConfig config = new BackupConfig();
+ config.setRepository("db1");
+ config.setWorkspace("ws");
+ config.setBackupDir(new File("target/backup/testJob"));
+
+ Calendar calendar = Calendar.getInstance();
+
+ job.init(repositoryService.getRepository("db1"), "ws", config, calendar);
+ job.run();
+
+ URL url = job.getStorageURL();
+ assertNotNull(url);
+
+ File valuesDir = new File(url.getFile(), FullBackupJob.VALUE_STORAGE_DIR);
+ assertTrue(valuesDir.exists());
+ String values[] = valuesDir.list();
+
+ assertEquals(values.length, 1);
+ assertTrue(new File(valuesDir, values[0]).isDirectory());
+
+ File indexesDir = new File(url.getFile(), FullBackupJob.INDEX_DIR);
+ assertTrue(indexesDir.exists());
+
+ indexesDir = new File(url.getFile(), FullBackupJob.SYSTEM_INDEX_DIR);
+ assertTrue(indexesDir.exists());
+
+ assertTrue(new File(url.getFile(), "JCR_MITEM.dump").exists());
+ assertTrue(new File(url.getFile(), "JCR_MITEM.len").exists());
+ assertTrue(new File(url.getFile(), "JCR_MVALUE.dump").exists());
+ assertTrue(new File(url.getFile(), "JCR_MVALUE.len").exists());
+ assertTrue(new File(url.getFile(), "JCR_MREF.dump").exists());
+ assertTrue(new File(url.getFile(), "JCR_MREF.len").exists());
+
+ }
+}
Modified: jcr/trunk/exo.jcr.component.ext/src/test/resources/conf/standalone/test-jcr-ext-config.xml
===================================================================
--- jcr/trunk/exo.jcr.component.ext/src/test/resources/conf/standalone/test-jcr-ext-config.xml 2010-12-02 14:02:19 UTC (rev 3595)
+++ jcr/trunk/exo.jcr.component.ext/src/test/resources/conf/standalone/test-jcr-ext-config.xml 2010-12-02 15:44:13 UTC (rev 3596)
@@ -39,7 +39,7 @@
<value-storages>
<value-storage id="draft" class="org.exoplatform.services.jcr.impl.storage.value.fs.TreeFileValueStorage">
<properties>
- <property name="path" value="../temp/values/backup" />
+ <property name="path" value="target/temp/values/backup" />
</properties>
<filters>
<filter property-type="Binary" />
@@ -367,7 +367,7 @@
<value-storages>
<value-storage id="draft" class="org.exoplatform.services.jcr.impl.storage.value.fs.TreeFileValueStorage">
<properties>
- <property name="path" value="../temp/values/db7_ws" />
+ <property name="path" value="target/temp/values/db7_ws" />
</properties>
<filters>
<filter property-type="Binary" />
@@ -400,7 +400,7 @@
<value-storages>
<value-storage id="draft" class="org.exoplatform.services.jcr.impl.storage.value.fs.TreeFileValueStorage">
<properties>
- <property name="path" value="../temp/values/db7_ws1" />
+ <property name="path" value="target/temp/values/db7_ws1" />
</properties>
<filters>
<filter property-type="Binary" />
@@ -441,7 +441,7 @@
<value-storages>
<value-storage id="draft" class="org.exoplatform.services.jcr.impl.storage.value.fs.TreeFileValueStorage">
<properties>
- <property name="path" value="../temp/values/db8_ws" />
+ <property name="path" value="target/temp/values/db8_ws" />
</properties>
<filters>
<filter property-type="Binary" />
@@ -474,7 +474,7 @@
<value-storages>
<value-storage id="draft" class="org.exoplatform.services.jcr.impl.storage.value.fs.TreeFileValueStorage">
<properties>
- <property name="path" value="../temp/values/db8_ws1" />
+ <property name="path" value="target/temp/values/db8_ws1" />
</properties>
<filters>
<filter property-type="Binary" />
More information about the exo-jcr-commits
mailing list