[exo-jcr-commits] exo-jcr SVN: r5067 - in jcr/trunk/exo.jcr.component.core/src: main/java/org/exoplatform/services/jcr/impl/core/query and 6 other directories.
do-not-reply at jboss.org
do-not-reply at jboss.org
Wed Oct 19 03:55:26 EDT 2011
Author: nzamosenchuk
Date: 2011-10-19 03:55:25 -0400 (Wed, 19 Oct 2011)
New Revision: 5067
Added:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/AbstractRepositorySuspender.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/InspectionLog.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/InspectionLogWriter.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/RepositoryCheckController.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainerChecker.java
jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/TestInspectionLogFile.java
jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/TestRepositoryCheckController.java
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/RepositorySuspendController.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/QueryHandler.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/lucene/SearchIndex.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/DBConstants.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/value/fs/FileIOChannel.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/storage/value/ValueIOChannel.java
jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/core/query/lucene/SlowQueryHandler.java
Log:
EXOJCR-1471 : commit patch with comments added to the code.
Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/AbstractRepositorySuspender.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/AbstractRepositorySuspender.java (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/AbstractRepositorySuspender.java 2011-10-19 07:55:25 UTC (rev 5067)
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2011 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.exoplatform.services.jcr.impl;
+
+import org.exoplatform.services.jcr.core.ManageableRepository;
+import org.exoplatform.services.jcr.core.security.JCRRuntimePermissions;
+
+import javax.jcr.RepositoryException;
+
+/**
+ * @author <a href="mailto:skarpenko at exoplatform.com">Sergiy Karpenko</a>
+ * @version $Id: exo-jboss-codetemplates.xml 34360 4.10.2011 skarpenko $
+ *
+ */
+public abstract class AbstractRepositorySuspender
+{
+ /**
+ * The current repository.
+ */
+ private final ManageableRepository repository;
+
+ /**
+ * AbstractRepositorySuspender constructor.
+ */
+ public AbstractRepositorySuspender(ManageableRepository repository)
+ {
+ this.repository = repository;
+ }
+
+ /**
+ * Suspend repository which means that allow only read operations.
+ * All writing threads will wait until resume operations invoked.
+ */
+ protected void suspendRepository() throws RepositoryException
+ {
+ // Need privileges to manage repository.
+ SecurityManager security = System.getSecurityManager();
+ if (security != null)
+ {
+ security.checkPermission(JCRRuntimePermissions.MANAGE_REPOSITORY_PERMISSION);
+ }
+ repository.setState(ManageableRepository.SUSPENDED);
+ }
+
+ /**
+ * Resume repository. All previously suspended threads continue working.
+ */
+ protected void resumeRepository() throws RepositoryException
+ {
+ // Need privileges to manage repository.
+ SecurityManager security = System.getSecurityManager();
+ if (security != null)
+ {
+ security.checkPermission(JCRRuntimePermissions.MANAGE_REPOSITORY_PERMISSION);
+ }
+ repository.setState(ManageableRepository.ONLINE);
+ }
+
+ /**
+ * Returns repository state title.
+ */
+ protected String getRepositoryStateTitle()
+ {
+ return repository.getStateTitle();
+ }
+
+ /**
+ * Returns repository state.
+ */
+ protected int getRepositoryState()
+ {
+ return repository.getState();
+ }
+
+}
Property changes on: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/AbstractRepositorySuspender.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/InspectionLog.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/InspectionLog.java (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/InspectionLog.java 2011-10-19 07:55:25 UTC (rev 5067)
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2011 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.exoplatform.services.jcr.impl;
+
+import java.io.IOException;
+
+/**
+ * Interface of inspection log. It provides general methods for logging consistency issues.
+ *
+ * @author <a href="mailto:skarpenko at exoplatform.com">Sergiy Karpenko</a>
+ * @version $Id: exo-jboss-codetemplates.xml 34360 4.10.2011 skarpenko $
+ *
+ */
+public interface InspectionLog
+{
+ // represents broken object state
+ public enum InspectionStatus {
+ ERR("Error"), WARN("Warning"), REINDEX("Reindex");
+ final String text;
+
+ InspectionStatus(String text)
+ {
+ this.text = text;
+ }
+
+ public String toString()
+ {
+ return text;
+ }
+ }
+
+ /**
+ * @return true, if inconsistency was found
+ */
+ boolean hasInconsistency();
+
+ /**
+ * @return true, if inconsistency or warning was found
+ */
+ boolean hasWarnings();
+
+ /**
+ * Adds comment to log
+ */
+ void logComment(String message) throws IOException;
+
+ /**
+ * Adds description to log
+ */
+ void logInspectionDescription(String description) throws IOException;
+
+ /**
+ * Adds detailed event to log, with issue found
+ */
+ void logBrokenObjectInfo(String brokenObjectDesc, String comment, InspectionStatus status) throws IOException;
+
+ /**
+ * Adds exception with full trace to the log
+ */
+ void logException(String message, Exception ex) throws IOException;
+}
Property changes on: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/InspectionLog.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/InspectionLogWriter.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/InspectionLogWriter.java (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/InspectionLogWriter.java 2011-10-19 07:55:25 UTC (rev 5067)
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2011 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.exoplatform.services.jcr.impl;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Text-based inspection log implementation. It uses any compatible Writer instance for output.
+ *
+ * @author <a href="mailto:skarpenko at exoplatform.com">Sergiy Karpenko</a>
+ * @version $Id: exo-jboss-codetemplates.xml 34360 6.10.2011 skarpenko $
+ *
+ */
+public class InspectionLogWriter implements InspectionLog
+{
+ private static final String LINE_COMMENT = "//";
+
+ private static final String LINE_DELIMITER = "\n";
+
+ private static final String WSP = " ";
+
+ private final Writer out;
+
+ private final Set<InspectionStatus> statusSet = new HashSet<InspectionStatus>();
+
+ public InspectionLogWriter(Writer out)
+ {
+ this.out = out;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean hasInconsistency()
+ {
+ return statusSet.contains(InspectionStatus.ERR) || statusSet.contains(InspectionStatus.REINDEX);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean hasWarnings()
+ {
+ return statusSet.contains(InspectionStatus.WARN);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void logComment(String message) throws IOException
+ {
+ writeLine(message);
+ out.flush();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void logInspectionDescription(String description) throws IOException
+ {
+ writeLine(description);
+ out.flush();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void logBrokenObjectInfo(String brokenObjectDesc, String comment, InspectionStatus status) throws IOException
+ {
+ statusSet.add(status);
+
+ out.write(status.toString());
+ out.write(WSP);
+ out.write(brokenObjectDesc);
+ out.write(WSP);
+ out.write(comment);
+ out.write(LINE_DELIMITER);
+ out.flush();
+ }
+
+ public void logException(String message, Exception ex) throws IOException
+ {
+ statusSet.add(InspectionStatus.ERR);
+
+ writeLine(message);
+ writeStackTrace(ex);
+ out.flush();
+ }
+
+ private void writeLine(String message) throws IOException
+ {
+ out.write(LINE_COMMENT);
+ out.write(message);
+ out.write(LINE_DELIMITER);
+ }
+
+ private void writeStackTrace(Throwable e) throws IOException
+ {
+ writeLine(e.getMessage());
+ writeLine(e.toString());
+ StackTraceElement[] trace = e.getStackTrace();
+ for (int i = 0; i < trace.length; i++)
+ {
+ writeLine("\tat " + trace[i]);
+ }
+
+ Throwable ourCause = e.getCause();
+ if (ourCause != null)
+ {
+ writeLine("Cause:");
+ writeStackTrace(ourCause);
+ }
+ }
+}
Property changes on: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/InspectionLogWriter.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/RepositoryCheckController.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/RepositoryCheckController.java (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/RepositoryCheckController.java 2011-10-19 07:55:25 UTC (rev 5067)
@@ -0,0 +1,424 @@
+/*
+ * Copyright (C) 2011 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.exoplatform.services.jcr.impl;
+
+import org.exoplatform.commons.utils.PrivilegedFileHelper;
+import org.exoplatform.management.annotations.Managed;
+import org.exoplatform.management.annotations.ManagedDescription;
+import org.exoplatform.management.jmx.annotations.NameTemplate;
+import org.exoplatform.management.jmx.annotations.Property;
+import org.exoplatform.services.jcr.core.ManageableRepository;
+import org.exoplatform.services.jcr.impl.core.query.SearchManager;
+import org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer;
+import org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainerChecker;
+import org.exoplatform.services.jcr.storage.value.ValueStoragePluginProvider;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+import org.picocontainer.Startable;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import javax.jcr.RepositoryException;
+
+/**
+ * Repository check controller allows check jcr repository consistency:
+ * <ul>
+ * <li>Check DB consistency</li>
+ * <li>Check value storage</li>
+ * <li>Check index</li>
+ * </ul>
+ *
+ * @author <a href="mailto:skarpenko at exoplatform.com">Sergiy Karpenko</a>
+ * @version $Id: exo-jboss-codetemplates.xml 34360 3.10.2011 skarpenko $
+ */
+ at Managed
+ at NameTemplate(@Property(key = "service", value = "RepositoryCheckController"))
+public class RepositoryCheckController extends AbstractRepositorySuspender implements Startable
+{
+ /**
+ * Logger.
+ */
+ protected static Log LOG = ExoLogger.getLogger("exo.jcr.component.core.RepositorySuspendController");
+
+ protected static final String FILE_NAME = "report";
+
+ protected class InspectorThread extends Thread
+ {
+ private final DataStorage[] checkData;
+
+ InspectorThread(DataStorage[] checkData)
+ {
+ super();
+ this.checkData = checkData;
+ this.setDaemon(true);
+ }
+
+ /**
+ * @see java.lang.Runnable#run()
+ */
+ @Override
+ public void run()
+ {
+ String result = checkRepositoryDataConsistency(checkData);
+ inspectionFinished(result);
+ }
+ }
+
+ protected enum DataStorage {
+ DB, VALUE_STORAGE, LUCENE_INDEX
+ };
+
+ private InspectorThread inspectorThread = null;
+
+ private File inspectionLogFile = null;
+
+ private String lastResult = null;
+
+ /**
+ * The current repository.
+ */
+ private final ManageableRepository repository;
+
+ /**
+ * RepositoryCheckController constructor.
+ */
+ public RepositoryCheckController(ManageableRepository repository)
+ {
+ super(repository);
+ this.repository = repository;
+ }
+
+ /**
+ * This method will make next steps:
+ * <ul>
+ * <li>Suspend repository</li>
+ * <li>Check DB consistency</li>
+ * <li>Check value storage</li>
+ * <li>Check index</li>
+ * <li>Resume repository</li>
+ * </ul>
+ *
+ * @return String check consistency report
+ */
+ @Managed
+ @ManagedDescription("Check repository data consistency. DB data, value storage and lucene index will be checked."
+ + "All writing threads will wait until check become finished.")
+ public String checkRepositoryDataConsistency()
+ {
+ return startInspectionInThread(new DataStorage[]{DataStorage.DB, DataStorage.VALUE_STORAGE,
+ DataStorage.LUCENE_INDEX});
+ }
+
+ @Managed
+ @ManagedDescription("Check repository database consistency."
+ + "All writing threads will wait until check become finished.")
+ public String checkRepositoryDataBaseConsistency()
+ {
+ return startInspectionInThread(new DataStorage[]{DataStorage.DB});
+ }
+
+ @Managed
+ @ManagedDescription("Check repository value storage consistency."
+ + "All writing threads will wait until check become finished.")
+ public String checkRepositoryValueStorageConsistency()
+ {
+ return startInspectionInThread(new DataStorage[]{DataStorage.VALUE_STORAGE});
+ }
+
+ @Managed
+ @ManagedDescription("Check repository search index consistency."
+ + "All writing threads will wait until check become finished.")
+ public String checkRepositorySearchIndexConsistency()
+ {
+ return startInspectionInThread(new DataStorage[]{DataStorage.LUCENE_INDEX});
+ }
+
+ @Managed
+ @ManagedDescription("Get inspection status.")
+ public String getStatus()
+ {
+ if (inspectorThread != null)
+ {
+ return "Data consistency inspection in progress..";
+ }
+ else
+ {
+ return lastResult;
+ }
+ }
+
+ protected void inspectionFinished(String resultMessage)
+ {
+ this.lastResult = resultMessage;
+ inspectorThread = null;
+ }
+
+ protected synchronized String startInspectionInThread(DataStorage[] checkData)
+ {
+ if (inspectorThread == null)
+ {
+ inspectorThread = new InspectorThread(checkData);
+ inspectorThread.start();
+
+ return "Data consistency inspection started.";
+ }
+ else
+ {
+ return "Current inspection process is not finished.";
+ }
+ }
+
+ protected String checkRepositoryDataConsistency(DataStorage[] checkData)
+ {
+ inspectionLogFile = null;
+ try
+ {
+ if (getRepositoryState() == ManageableRepository.SUSPENDED)
+ {
+ return "Can not check data consistency. Repository is already suspended.";
+ }
+
+ Writer reportWriter = null;
+ try
+ {
+ try
+ {
+ suspendRepository();
+ }
+ catch (RepositoryException e)
+ {
+ return "Can not check data consistency. Repository was not suspended. Error: " + e.getMessage();
+ }
+
+ // DO CHECK
+ inspectionLogFile =
+ new File(FILE_NAME + "-" + repository.getConfiguration().getName() + "-"
+ + new SimpleDateFormat("dd-MMM-yy-HH-mm").format(new Date()) + ".txt");
+ if (!PrivilegedFileHelper.exists(inspectionLogFile)
+ && !PrivilegedFileHelper.createNewFile(inspectionLogFile))
+ {
+ LOG.error("Inspection log file was not created. "
+ + PrivilegedFileHelper.getAbsolutePath(inspectionLogFile));
+ return "Can not check data consistency. Inspection log file was not created. "
+ + PrivilegedFileHelper.getAbsolutePath(inspectionLogFile);
+ }
+
+ reportWriter =
+ new BufferedWriter(new OutputStreamWriter(PrivilegedFileHelper.fileOutputStream(inspectionLogFile)));
+ InspectionLog report = new InspectionLogWriter(reportWriter);
+ for (DataStorage cd : checkData)
+ {
+ switch (cd)
+ {
+ case DB :
+ try
+ {
+ checkDB(report);
+ }
+ catch (RepositoryException e)
+ {
+ report.logException("RepositoryException occures during DB consistency check.", e);
+ return "RepositoryException occures during DB consistency check. Error: " + e.getMessage()
+ + ". See log here: " + PrivilegedFileHelper.getAbsolutePath(inspectionLogFile);
+ }
+ catch (IOException e)
+ {
+ report.logException("IOException occures during DB consistency check.", e);
+ return "IOException occures during DB consistency check. Error: " + e.getMessage()
+ + ". See log here: " + PrivilegedFileHelper.getAbsolutePath(inspectionLogFile);
+ }
+ break;
+ case VALUE_STORAGE :
+ try
+ {
+ checkVS(report);
+ }
+ catch (RepositoryException e)
+ {
+ report.logException("RepositoryException occures during ValueStorage consistency check.", e);
+ return "RepositoryException occures during ValueStorage consistency check. Error: "
+ + e.getMessage() + ". See log here: "
+ + PrivilegedFileHelper.getAbsolutePath(inspectionLogFile);
+ }
+ catch (IOException e)
+ {
+ report.logException("IOException occures during ValueStorage consistency check.", e);
+ return "IOException occures during ValueStorage consistency check. Error: " + e.getMessage()
+ + ". See log here: " + PrivilegedFileHelper.getAbsolutePath(inspectionLogFile);
+ }
+ break;
+ case LUCENE_INDEX :
+ try
+ {
+ checkLuceneIndex(report);
+ }
+ catch (RepositoryException e)
+ {
+ report.logException("RepositoryException occures during SearchIndex consistency check.", e);
+ return "RepositoryException occures during SearchIndex consistency check. Error: "
+ + e.getMessage() + ". See log here: "
+ + PrivilegedFileHelper.getAbsolutePath(inspectionLogFile);
+ }
+ catch (IOException e)
+ {
+ report.logException("IOException occures during SearchIndex consistency check.", e);
+ return "IOException occures during SearchIndex consistency check. Error: " + e.getMessage()
+ + ". See log here: " + PrivilegedFileHelper.getAbsolutePath(inspectionLogFile);
+ }
+ break;
+ }
+ }
+
+ if (report.hasInconsistency())
+ {
+ report.logComment("Repository data is NOT consistent.");
+ return "Repository data is inconsistent. See full report by path "
+ + PrivilegedFileHelper.getAbsolutePath(inspectionLogFile);
+ }
+ else if (report.hasWarnings())
+ {
+ report.logComment("Repository data is consistent, except some warnings.");
+ return "Repository data is consistent, except some warnings. See full report by path "
+ + PrivilegedFileHelper.getAbsolutePath(inspectionLogFile);
+ }
+ else
+ {
+ report.logComment("Repository data is consistent");
+ return "Repository data is consistent. See full report by path "
+ + PrivilegedFileHelper.getAbsolutePath(inspectionLogFile);
+ }
+ }
+ finally
+ {
+ if (reportWriter != null)
+ {
+ try
+ {
+ reportWriter.flush();
+ reportWriter.close();
+ }
+ catch (IOException e)
+ {
+ LOG.error("Can not close file " + PrivilegedFileHelper.getAbsolutePath(inspectionLogFile), e);
+ }
+ }
+
+ //resume repository
+ try
+ {
+ resumeRepository();
+ }
+ catch (RepositoryException e)
+ {
+ LOG.error("Can not resume repository. Error: " + e.getMessage(), e);
+ }
+ if (getRepositoryState() != ManageableRepository.ONLINE)
+ {
+ LOG.error("Repository was not resumed and now it is OFFLINE");
+ }
+ }
+ }
+ catch (Throwable e)
+ {
+ LOG.error(e.getMessage(), e);
+ return "Exception thrown during repository data validation: "
+ + e
+ + (inspectionLogFile != null ? " See log by path "
+ + PrivilegedFileHelper.getAbsolutePath(inspectionLogFile) : "");
+ }
+ }
+
+ private void checkDB(InspectionLog inspectionLog) throws RepositoryException, IOException
+ {
+ String[] wsNames = repository.getWorkspaceNames();
+ for (String wsName : wsNames)
+ {
+ inspectionLog.logComment("Check DB consistency. Workspace " + wsName);
+ JDBCWorkspaceDataContainer dataContainer =
+ (JDBCWorkspaceDataContainer)repository.getWorkspaceContainer(wsName).getComponent(
+ JDBCWorkspaceDataContainer.class);
+ JDBCWorkspaceDataContainerChecker.checkDB(dataContainer, inspectionLog);
+ }
+ }
+
+ private void checkVS(InspectionLog inspectionLog) throws RepositoryException, IOException
+ {
+ String[] wsNames = repository.getWorkspaceNames();
+ for (String wsName : wsNames)
+ {
+ inspectionLog.logComment("Check ValueStorage consistency. Workspace " + wsName);
+
+ JDBCWorkspaceDataContainer dataContainer =
+ (JDBCWorkspaceDataContainer)repository.getWorkspaceContainer(wsName).getComponent(
+ JDBCWorkspaceDataContainer.class);
+
+ ValueStoragePluginProvider vsPlugin =
+ (ValueStoragePluginProvider)repository.getWorkspaceContainer(wsName).getComponent(
+ ValueStoragePluginProvider.class);
+
+ JDBCWorkspaceDataContainerChecker.checkValueStorage(dataContainer, vsPlugin, inspectionLog);
+ }
+ }
+
+ private void checkLuceneIndex(InspectionLog inspectionLog) throws RepositoryException, IOException
+ {
+ final String[] wsNames = repository.getWorkspaceNames();
+ final String systemWS = repository.getConfiguration().getSystemWorkspaceName();
+ for (String wsName : wsNames)
+ {
+ inspectionLog.logComment("Check SearchIndex consistency. Workspace " + wsName);
+ SearchManager searchManager =
+ (SearchManager)repository.getWorkspaceContainer(wsName).getComponent(SearchManager.class);
+ searchManager.checkIndex(inspectionLog, systemWS.equals(wsName));
+ }
+ }
+
+ /**
+ * For test purposes.
+ * @return
+ */
+ protected File getLastLogFile()
+ {
+ return inspectionLogFile;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void start()
+ {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void stop()
+ {
+ if (inspectorThread != null)
+ {
+ inspectorThread.interrupt();
+ }
+ }
+}
Property changes on: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/RepositoryCheckController.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
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-10-18 13:35:56 UTC (rev 5066)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/RepositoryContainer.java 2011-10-19 07:55:25 UTC (rev 5067)
@@ -610,6 +610,7 @@
{
registerComponentImplementation(RepositorySuspendController.class);
+ registerComponentImplementation(RepositoryCheckController.class);
registerComponentImplementation(IdGenerator.class);
registerComponentImplementation(RepositoryIndexSearcherHolder.class);
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/RepositorySuspendController.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/RepositorySuspendController.java 2011-10-18 13:35:56 UTC (rev 5066)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/RepositorySuspendController.java 2011-10-19 07:55:25 UTC (rev 5067)
@@ -23,7 +23,6 @@
import org.exoplatform.management.jmx.annotations.NameTemplate;
import org.exoplatform.management.jmx.annotations.Property;
import org.exoplatform.services.jcr.core.ManageableRepository;
-import org.exoplatform.services.jcr.core.security.JCRRuntimePermissions;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.picocontainer.Startable;
@@ -38,14 +37,9 @@
*/
@Managed
@NameTemplate(@Property(key = "service", value = "RepositorySuspendController"))
-public class RepositorySuspendController implements Startable
+public class RepositorySuspendController extends AbstractRepositorySuspender implements Startable
{
/**
- * The current repository.
- */
- private final ManageableRepository repository;
-
- /**
* Logger.
*/
protected static Log log = ExoLogger.getLogger("exo.jcr.component.core.RepositorySuspendController");
@@ -55,7 +49,7 @@
*/
public RepositorySuspendController(ManageableRepository repository)
{
- this.repository = repository;
+ super(repository);
}
/**
@@ -69,23 +63,15 @@
"All writing threads will wait until resume operations invoked.")
public String suspend()
{
- // Need privileges to manage repository.
- SecurityManager security = System.getSecurityManager();
- if (security != null)
- {
- security.checkPermission(JCRRuntimePermissions.MANAGE_REPOSITORY_PERMISSION);
- }
-
try
{
- repository.setState(ManageableRepository.SUSPENDED);
+ suspendRepository();
}
catch (RepositoryException e)
{
log.error(e);
}
-
- return getState();
+ return getRepositoryStateTitle();
}
/**
@@ -97,23 +83,15 @@
@ManagedDescription("Resume repository. All previously suspended threads continue working.")
public String resume()
{
- // Need privileges to manage repository.
- SecurityManager security = System.getSecurityManager();
- if (security != null)
- {
- security.checkPermission(JCRRuntimePermissions.MANAGE_REPOSITORY_PERMISSION);
- }
-
try
{
- repository.setState(ManageableRepository.ONLINE);
+ resumeRepository();
}
catch (RepositoryException e)
{
log.error(e);
}
-
- return getState();
+ return getRepositoryStateTitle();
}
/**
@@ -123,7 +101,7 @@
@ManagedDescription("Returns repository state.")
public String getState()
{
- return repository.getStateTitle();
+ return getRepositoryStateTitle();
}
/**
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/QueryHandler.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/QueryHandler.java 2011-10-18 13:35:56 UTC (rev 5066)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/QueryHandler.java 2011-10-19 07:55:25 UTC (rev 5067)
@@ -18,7 +18,9 @@
import org.apache.lucene.search.Query;
import org.exoplatform.services.jcr.config.RepositoryConfigurationException;
+import org.exoplatform.services.jcr.dataflow.ItemDataConsumer;
import org.exoplatform.services.jcr.datamodel.NodeData;
+import org.exoplatform.services.jcr.impl.InspectionLog;
import org.exoplatform.services.jcr.impl.core.SessionDataManager;
import org.exoplatform.services.jcr.impl.core.SessionImpl;
import org.exoplatform.services.jcr.impl.core.query.lucene.ChangesHolder;
@@ -222,4 +224,17 @@
*/
boolean isOnline();
+ /**
+ * Check index consistency. Iterator goes through index documents and check, does each document have
+ * according jcr-node. If <b>autoRepair</b> is true - all broken index-documents will be reindexed,
+ * and documents that do not have corresponding jcr-node will be removed.
+ *
+ * @param itemStateManager
+ * @param isSystem
+ * @param inspectionLog
+ * @throws RepositoryException
+ * @throws IOException
+ */
+ void checkIndex(ItemDataConsumer itemStateManager, boolean isSystem, InspectionLog inspectionLog)
+ throws RepositoryException, IOException;
}
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-10-18 13:35:56 UTC (rev 5066)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/SearchManager.java 2011-10-19 07:55:25 UTC (rev 5067)
@@ -22,6 +22,7 @@
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.WildcardQuery;
import org.exoplatform.commons.utils.PrivilegedFileHelper;
+import org.exoplatform.commons.utils.SecurityHelper;
import org.exoplatform.container.ExoContainerContext;
import org.exoplatform.container.configuration.ConfigurationManager;
import org.exoplatform.management.annotations.Managed;
@@ -48,6 +49,7 @@
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.InspectionLog;
import org.exoplatform.services.jcr.impl.backup.BackupException;
import org.exoplatform.services.jcr.impl.backup.Backupable;
import org.exoplatform.services.jcr.impl.backup.DataRestore;
@@ -88,6 +90,8 @@
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
@@ -391,6 +395,78 @@
}
/**
+ * Check index consistency. Iterator goes through index documents and check, does each document have
+ * according jcr-node. If index is suspended then it will be temporary resumed, while check is running and suspended afterwards.
+ */
+ public void checkIndex(final InspectionLog inspectionLog, final boolean isSystem) throws RepositoryException, IOException
+ {
+
+ if (isSuspended)
+ {
+ try
+ {
+ SecurityHelper.doPrivilegedExceptionAction(new PrivilegedExceptionAction<Object>()
+ {
+ public Object run() throws RepositoryException, IOException
+ {
+ // try resuming the workspace
+ try
+ {
+ if (isSystem && parentSearchManager != null && parentSearchManager.isSuspended)
+ {
+ parentSearchManager.resume();
+ }
+ resume();
+
+ handler.checkIndex(itemMgr, isSystem, inspectionLog);
+ return null;
+ }
+ catch (ResumeException e)
+ {
+ throw new RepositoryException("Can not resume SearchManager for inspection purposes.", e);
+ }
+ finally
+ {
+ // safely return the state of the workspace
+ try
+ {
+ suspend();
+ if (isSystem && parentSearchManager != null && !parentSearchManager.isSuspended)
+ {
+ parentSearchManager.suspend();
+ }
+ }
+ catch (SuspendException e)
+ {
+ log.error(e.getMessage(), e);
+ }
+ }
+ }
+ });
+ }
+ catch (PrivilegedActionException e)
+ {
+ Throwable ex = e.getCause();
+ if (ex instanceof RepositoryException)
+ {
+ throw (RepositoryException)ex;
+ }
+ else if (ex instanceof IOException)
+ {
+ throw (IOException)ex;
+ }
+ else
+ {
+ throw new RepositoryException(ex.getMessage(), ex);
+ }
+ }
+ }else{
+ // simply run checkIndex, if not suspended
+ handler.checkIndex(itemMgr, isSystem, inspectionLog);
+ }
+ }
+
+ /**
* {@inheritDoc}
*/
public Set<String> getFieldNames() throws IndexException
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-10-18 13:35:56 UTC (rev 5066)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SearchIndex.java 2011-10-19 07:55:25 UTC (rev 5067)
@@ -44,12 +44,15 @@
import org.exoplatform.services.jcr.config.QueryHandlerParams;
import org.exoplatform.services.jcr.config.RepositoryConfigurationException;
import org.exoplatform.services.jcr.dataflow.ItemDataConsumer;
+import org.exoplatform.services.jcr.dataflow.ItemDataTraversingVisitor;
import org.exoplatform.services.jcr.datamodel.ItemData;
import org.exoplatform.services.jcr.datamodel.NodeData;
import org.exoplatform.services.jcr.datamodel.NodeDataIndexing;
import org.exoplatform.services.jcr.datamodel.PropertyData;
import org.exoplatform.services.jcr.datamodel.QPath;
import org.exoplatform.services.jcr.impl.Constants;
+import org.exoplatform.services.jcr.impl.InspectionLog;
+import org.exoplatform.services.jcr.impl.InspectionLog.InspectionStatus;
import org.exoplatform.services.jcr.impl.backup.ResumeException;
import org.exoplatform.services.jcr.impl.backup.SuspendException;
import org.exoplatform.services.jcr.impl.backup.Suspendable;
@@ -864,6 +867,127 @@
}
/**
+ * {@inheritDoc}
+ */
+ public void checkIndex(ItemDataConsumer itemStateManager, boolean isSystem, final InspectionLog inspectionLog)
+ throws RepositoryException, IOException
+ {
+
+ // The visitor, that performs item enumeration and checks if all nodes present in
+ // persistent layer are indexed. Also collects the list of all indexed nodes
+ // to optimize the process of backward check, when index is traversed to find
+ // references to already deleted nodes
+ class ItemDataIndexConsistencyVisitor extends ItemDataTraversingVisitor
+ {
+ private final IndexReader indexReader;
+
+ private final Set<String> indexedNodes = new HashSet<String>();
+
+ /**
+ * @param dataManager
+ */
+ public ItemDataIndexConsistencyVisitor(ItemDataConsumer dataManager, IndexReader indexReader)
+ {
+ super(dataManager);
+ this.indexReader = indexReader;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void entering(PropertyData property, int level) throws RepositoryException
+ {
+ // ignore properties;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void entering(NodeData node, int level) throws RepositoryException
+ {
+ // process node uuids one-by-one
+ try
+ {
+ String uuid = node.getIdentifier();
+ TermDocs docs = indexReader.termDocs(new Term(FieldNames.UUID, uuid));
+
+ if (docs.next())
+ {
+ indexedNodes.add(uuid);
+ docs.doc();
+ if (docs.next())
+ {
+ //multiple entries
+ inspectionLog.logBrokenObjectInfo("ID=" + uuid, "Multiple entires.", InspectionStatus.REINDEX);
+ }
+ }
+ else
+ {
+ inspectionLog.logBrokenObjectInfo("ID=" + uuid, "Not indexed.", InspectionStatus.REINDEX);
+ }
+ }
+ catch (IOException e)
+ {
+ throw new RepositoryException(e.getMessage(), e);
+ }
+ }
+
+ @Override
+ protected void leaving(PropertyData property, int level) throws RepositoryException
+ {
+ // ignore properties
+ }
+
+ @Override
+ protected void leaving(NodeData node, int level) throws RepositoryException
+ {
+ // do nothing
+ }
+
+ @Override
+ protected void visitChildProperties(NodeData node) throws RepositoryException
+ {
+ //do nothing
+ }
+
+ public Set<String> getIndexedNodes()
+ {
+ return indexedNodes;
+ }
+ }
+
+ // check relation Persistent Layer -> Index
+ // If current workspace is system, then need to invoke reader correspondent to system index
+ IndexReader indexReader = getIndexReader(isSystem);
+ ItemData root = itemStateManager.getItemData(Constants.ROOT_UUID);
+ ItemDataIndexConsistencyVisitor visitor = new ItemDataIndexConsistencyVisitor(itemStateManager, indexReader);
+ root.accept(visitor);
+
+ Set<String> documentUUIDs = visitor.getIndexedNodes();
+
+ // check relation Index -> Persistent Layer
+ // find document that do not corresponds to real node
+ // iterate on documents one-by-one
+ for (int i = 0; i < indexReader.maxDoc(); i++)
+ {
+ if (indexReader.isDeleted(i))
+ {
+ continue;
+ }
+ final int currentIndex = i;
+ Document d = indexReader.document(currentIndex, FieldSelectors.UUID);
+ String uuid = d.get(FieldNames.UUID);
+ if (!documentUUIDs.contains(uuid))
+ {
+ inspectionLog.logBrokenObjectInfo("ID=" + uuid, "Document corresponds to removed node.",
+ InspectionStatus.REINDEX);
+ }
+ }
+ }
+
+ /**
* @return the errorLogfileSize
*/
public int getErrorLogfileSize()
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/DBConstants.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/DBConstants.java 2011-10-18 13:35:56 UTC (rev 5066)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/DBConstants.java 2011-10-19 07:55:25 UTC (rev 5067)
@@ -247,6 +247,11 @@
// VALUE table
/**
+ * PROPERTY_ID
+ */
+ protected static final String COLUMN_VPROPERTY_ID = "PROPERTY_ID";
+
+ /**
* COLUMN_VDATA.
*/
protected static final String COLUMN_VDATA = "DATA";
@@ -340,9 +345,8 @@
/**
* DB_DIALECTS.
*/
- public final static String[] DB_DIALECTS =
- {DB_DIALECT_GENERIC, DB_DIALECT_ORACLE, DB_DIALECT_ORACLEOCI, DB_DIALECT_PGSQL, DB_DIALECT_MYSQL,
- DB_DIALECT_HSQLDB, DB_DIALECT_DB2, DB_DIALECT_DB2V8, DB_DIALECT_MSSQL, DB_DIALECT_SYBASE, DB_DIALECT_DERBY,
- DB_DIALECT_MYSQL_UTF8, DB_DIALECT_INGRES, DB_DIALECT_H2};
+ public final static String[] DB_DIALECTS = {DB_DIALECT_GENERIC, DB_DIALECT_ORACLE, DB_DIALECT_ORACLEOCI,
+ DB_DIALECT_PGSQL, DB_DIALECT_MYSQL, DB_DIALECT_HSQLDB, DB_DIALECT_DB2, DB_DIALECT_DB2V8, DB_DIALECT_MSSQL,
+ DB_DIALECT_SYBASE, DB_DIALECT_DERBY, DB_DIALECT_MYSQL_UTF8, DB_DIALECT_INGRES, DB_DIALECT_H2};
}
Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainerChecker.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainerChecker.java (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainerChecker.java 2011-10-19 07:55:25 UTC (rev 5067)
@@ -0,0 +1,415 @@
+/*
+ * Copyright (C) 2011 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.exoplatform.services.jcr.impl.storage.jdbc;
+
+import org.exoplatform.commons.utils.SecurityHelper;
+import org.exoplatform.services.jcr.impl.InspectionLog;
+import org.exoplatform.services.jcr.impl.InspectionLog.InspectionStatus;
+import org.exoplatform.services.jcr.impl.storage.value.ValueDataNotFoundException;
+import org.exoplatform.services.jcr.impl.storage.value.ValueStorageNotFoundException;
+import org.exoplatform.services.jcr.storage.value.ValueIOChannel;
+import org.exoplatform.services.jcr.storage.value.ValueStoragePluginProvider;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+
+import java.io.IOException;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.jcr.RepositoryException;
+
+/**
+ * @author <a href="mailto:skarpenko at exoplatform.com">Sergiy Karpenko</a>
+ * @version $Id: exo-jboss-codetemplates.xml 34360 14 жовт. 2011 skarpenko $
+ *
+ */
+public class JDBCWorkspaceDataContainerChecker
+{
+ protected static final Log LOG = ExoLogger.getLogger("exo.jcr.component.core.JDBCWorkspaceDataContainerChecker");
+
+ /**
+ * Check database.
+ * <p>
+ * Check that database is not broken, and all base relation between jcr-items are not corrupted.
+ * </p>
+ *
+ * @param inspectionLog - log where inspection results will be placed
+ * @return InspectionLog
+ * @throws RepositoryException
+ * @throws IOException
+ */
+ public static void checkDB(JDBCWorkspaceDataContainer jdbcDataContainer, InspectionLog inspectionLog)
+ throws RepositoryException, IOException
+ {
+
+ /**
+ * Data class, contains a combination of SQL states, description, field names and status
+ */
+ class InspectionQuery
+ {
+ /**
+ * SQL query that must be executed.
+ */
+ private final String statement;
+
+ /**
+ * Inspection query description.
+ */
+ private final String description;
+
+ /**
+ * Field names that must be showed in inspection log if something wrong.
+ */
+ private final String[] fieldNames;
+
+ /**
+ * Corruption status. Is it critical - <b>ERR</b>, or not - <b>WARN</b>.
+ */
+ private final InspectionStatus status;
+
+ public InspectionQuery(String statement, String[] fieldNames, String headerMessage, InspectionStatus status)
+ {
+ this.statement = statement;
+ this.description = headerMessage;
+ this.fieldNames = fieldNames;
+ this.status = status;
+ }
+
+ public String getStatement()
+ {
+ return statement;
+ }
+
+ public String getDescription()
+ {
+ return description;
+ }
+
+ public String[] getFieldNames()
+ {
+ return fieldNames;
+ }
+
+ public InspectionStatus getStatus()
+ {
+ return status;
+ }
+ }
+
+ Set<InspectionQuery> queries = new HashSet<InspectionQuery>();
+
+ // preload queries
+ queries.add(new InspectionQuery(jdbcDataContainer.multiDb
+ ? "select * from JCR_MITEM as I where NOT EXISTS(select * from JCR_MITEM AS P where P.ID = I.PARENT_ID)"
+ : "select * from JCR_SITEM as I where I.CONTAINER_NAME='" + jdbcDataContainer.containerName
+ + "' and NOT EXISTS(select * from JCR_SITEM AS P where P.ID = I.PARENT_ID)", new String[]{
+ DBConstants.COLUMN_ID, DBConstants.COLUMN_PARENTID, DBConstants.COLUMN_NAME, DBConstants.COLUMN_CLASS},
+ "Items that do not have parent nodes", InspectionStatus.ERR));
+ queries
+ .add(new InspectionQuery(
+ jdbcDataContainer.multiDb
+ ? "select * from JCR_MITEM as N where N.I_CLASS=1 and NOT EXISTS (select * from JCR_MITEM AS P where P.I_CLASS=2 and P.PARENT_ID=N.ID)"
+ : "select * from JCR_SITEM as N where N.CONTAINER_NAME='"
+ + jdbcDataContainer.containerName
+ + "' and N.I_CLASS=1 and NOT EXISTS (select * from JCR_SITEM AS P where P.I_CLASS=2 and P.PARENT_ID=N.ID)",
+ new String[]{DBConstants.COLUMN_ID, DBConstants.COLUMN_PARENTID, DBConstants.COLUMN_NAME},
+ "Nodes that do not have at least one property", InspectionStatus.ERR));
+ queries
+ .add(new InspectionQuery(
+ jdbcDataContainer.multiDb
+ ? "select * from JCR_MVALUE as V where NOT EXISTS(select * from JCR_MITEM as P where V.PROPERTY_ID = P.ID and P.I_CLASS=2)"
+ : "select * from JCR_SVALUE as V where NOT EXISTS(select * from JCR_SITEM as P where P.CONTAINER_NAME='"
+ + jdbcDataContainer.containerName + "' and V.PROPERTY_ID = P.ID and P.I_CLASS=2)", new String[]{
+ DBConstants.COLUMN_ID, DBConstants.COLUMN_VPROPERTY_ID},
+ "All value records that has not owner-property record", InspectionStatus.ERR));
+ queries
+ .add(new InspectionQuery(
+ jdbcDataContainer.multiDb
+ ? "select * from JCR_MITEM as P where P.I_CLASS=2 and NOT EXISTS( select * from JCR_MVALUE as V where V.PROPERTY_ID=P.ID)"
+ : "select * from JCR_SITEM as P where P.CONTAINER_NAME='" + jdbcDataContainer.containerName
+ + "' and P.I_CLASS=2 and NOT EXISTS( select * from JCR_SVALUE as V where V.PROPERTY_ID=P.ID)",
+ new String[]{DBConstants.COLUMN_ID, DBConstants.COLUMN_PARENTID, DBConstants.COLUMN_NAME},
+ "All properties that have not value record.", InspectionStatus.WARN));
+ queries
+ .add(new InspectionQuery(
+ jdbcDataContainer.multiDb
+ ? "select * from JCR_MVALUE where (STORAGE_DESC is null and DATA is null) or (STORAGE_DESC is not null and DATA is not null)"
+ : "select * from JCR_SVALUE where (STORAGE_DESC is null and DATA is null) or (STORAGE_DESC is not null and DATA is not null)",
+ new String[]{DBConstants.COLUMN_ID}, "Incorrect JCR_VALUE records", InspectionStatus.ERR));
+ queries
+ .add(new InspectionQuery(
+ jdbcDataContainer.multiDb
+ ? "select * from JCR_MITEM AS P where P.P_TYPE=9 and NOT EXISTS( select * from JCR_MREF AS R where P.ID=R.PROPERTY_ID)"
+ : "select * from JCR_SITEM AS P where P.CONTAINER_NAME='" + jdbcDataContainer.containerName
+ + "' and P.P_TYPE=9 and NOT EXISTS( select * from JCR_SREF AS R where P.ID=R.PROPERTY_ID)",
+ new String[]{DBConstants.COLUMN_ID, DBConstants.COLUMN_PARENTID, DBConstants.COLUMN_NAME},
+ "Reference properties without reference records", InspectionStatus.ERR));
+
+ // properties can refer to missing node. It is possible to perform this usecase via JCR API with no exceptions
+ queries.add(new InspectionQuery(jdbcDataContainer.multiDb
+ ? "select * from JCR_MREF AS R where NOT EXISTS(select * from JCR_MITEM AS N where R.NODE_ID=N.ID)"
+ : "select * from JCR_SREF AS R where NOT EXISTS(select * from JCR_SITEM AS N where N.CONTAINER_NAME='"
+ + jdbcDataContainer.containerName + "' and R.NODE_ID=N.ID)", new String[]{"NODE_ID", "PROPERTY_ID",
+ DBConstants.COLUMN_VORDERNUM},
+ "Reference records that linked to unexisted nodes. Can be normal for some usecases.", InspectionStatus.WARN));
+
+ // using existing DataSource to get a JDBC Connection.
+ Connection jdbcConn = jdbcDataContainer.getConnectionFactory().getJdbcConnection();
+
+ try
+ {
+ // perform all queries on-by-one
+ for (InspectionQuery query : queries)
+ {
+ PreparedStatement st = null;
+ ResultSet resultSet = null;
+ try
+ {
+ st = jdbcConn.prepareStatement(query.getStatement());
+ // the result of query is expected to be empty
+ resultSet = st.executeQuery();
+ if (resultSet.next())
+ {
+ // but if result not empty, then inconsistency takes place
+ inspectionLog.logInspectionDescription(query.getDescription());
+ do
+ {
+ StringBuilder record = new StringBuilder();
+ for (String fieldName : query.getFieldNames())
+ {
+ record.append(fieldName);
+ record.append('=');
+ if (fieldName.equals(DBConstants.COLUMN_NORDERNUM)
+ || fieldName.equals(DBConstants.COLUMN_VORDERNUM))
+ {
+ record.append(resultSet.getInt(fieldName));
+ }
+ else
+ {
+ record.append(resultSet.getString(fieldName));
+ }
+ record.append(' ');
+ }
+ // log inconsistency issue.
+ inspectionLog.logBrokenObjectInfo(record.toString(), "", query.getStatus());
+ }
+ while (resultSet.next());
+ }
+ }
+ // safely free resources
+ finally
+ {
+ if (resultSet != null)
+ {
+ try
+ {
+ resultSet.close();
+ }
+ catch (SQLException e)
+ {
+ LOG.error(e.getMessage(), e);
+ }
+ }
+ if (st != null)
+ {
+ try
+ {
+ st.close();
+ }
+ catch (SQLException e)
+ {
+ LOG.error(e.getMessage(), e);
+ }
+ }
+ }
+ }
+ }
+ catch (SQLException e)
+ {
+ // log unexpected exceptions to log
+ inspectionLog.logException("Exception during DB inspection.", e);
+ }
+ finally
+ {
+ // safely close connection
+ if (jdbcConn != null)
+ {
+ try
+ {
+ jdbcConn.close();
+ }
+ catch (SQLException e)
+ {
+ LOG.error(e.getMessage(), e);
+ }
+ }
+ }
+ }
+
+ /**
+ * Inspect ValueStorage.
+ * <p>
+ * All ValueDatas that have storage description (that means, value data stored in value storage) will be inspected:
+ * <ul>
+ * <li> does value exists in value storage;</li>
+ * <li> is this value readable;</li>
+ * <ul>
+ *
+ *
+ * @param vsPlugin - value storages
+ * @param inspectionLog - log where inspection results will be placed
+ * @return resulting InspectionLog
+ * @throws RepositoryException
+ * @throws IOException
+ */
+ public static void checkValueStorage(JDBCWorkspaceDataContainer jdbcDataContainer,
+ ValueStoragePluginProvider vsPlugin, InspectionLog inspectionLog) throws RepositoryException, IOException
+ {
+ final String valueRecordFormat = "ValueData[PROPERTY_ID=%s ORDER_NUM=%d STORAGE_DESC=%s]";
+
+ Connection connection = jdbcDataContainer.getConnectionFactory().getJdbcConnection();
+ PreparedStatement st = null;
+ ResultSet resultSet = null;
+ try
+ {
+ st =
+ connection.prepareStatement(jdbcDataContainer.multiDb
+ ? "SELECT PROPERTY_ID, ORDER_NUM, STORAGE_DESC from JCR_MVALUE where STORAGE_DESC is not null"
+ : "SELECT PROPERTY_ID, ORDER_NUM, STORAGE_DESC from JCR_SVALUE where STORAGE_DESC is not null");
+
+ resultSet = st.executeQuery();
+ // traverse all values, written to value storage
+ if (resultSet.next())
+ {
+ ValueIOChannel channel = null;
+ do
+ {
+ final String propertyId = resultSet.getString(DBConstants.COLUMN_VPROPERTY_ID);
+ final int orderNumber = resultSet.getInt(DBConstants.COLUMN_VORDERNUM);
+ final String storageDesc = resultSet.getString(DBConstants.COLUMN_VSTORAGE_DESC);
+
+ // don't acquire channel if it is already open
+ if (channel == null || !channel.getStorageId().equals(storageDesc))
+ {
+ try
+ {
+ if (channel != null)
+ {
+ channel.close();
+ }
+ channel = vsPlugin.getChannel(storageDesc);
+ }
+ catch (ValueStorageNotFoundException e)
+ {
+ inspectionLog.logBrokenObjectInfo("ValueStorage " + storageDesc + " not found. "
+ + String.format(valueRecordFormat, propertyId, orderNumber, storageDesc), e.getMessage(),
+ InspectionStatus.ERR);
+ continue;
+ }
+ }
+
+ try
+ {
+ // check value data
+ final ValueIOChannel vdChannel = channel;
+ SecurityHelper.doPrivilegedExceptionAction(new PrivilegedExceptionAction<Object>()
+ {
+ public Object run() throws ValueDataNotFoundException, IOException
+ {
+ vdChannel.checkValueData(propertyId, orderNumber);
+ return null;
+ }
+ });
+ }
+ // process exception thrown by checkValueData
+ catch (PrivilegedActionException e)
+ {
+ Throwable ex = e.getCause();
+ if (ex instanceof ValueDataNotFoundException)
+ {
+ inspectionLog.logBrokenObjectInfo(String.format(valueRecordFormat, propertyId, orderNumber,
+ storageDesc)
+ + " not found.", ex.getMessage(), InspectionStatus.ERR);
+ }
+ else if (ex instanceof IOException)
+ {
+ inspectionLog.logException(ex.getMessage(), (IOException)ex);
+ }
+ else
+ {
+ throw new RepositoryException(ex.getMessage(), ex);
+ }
+ }
+ }
+ while (resultSet.next());
+ }
+ }
+ catch (SQLException e)
+ {
+ // log unexpceted exception
+ inspectionLog.logException("Exception during ValueStorage inspection.", e);
+ }
+ finally
+ {
+ // safely free resources
+ if (resultSet != null)
+ {
+ try
+ {
+ resultSet.close();
+ }
+ catch (SQLException e)
+ {
+ LOG.error(e.getMessage(), e);
+ }
+ }
+
+ if (st != null)
+ {
+ try
+ {
+ st.close();
+ }
+ catch (SQLException e)
+ {
+ LOG.error(e.getMessage(), e);
+ }
+ }
+
+ if (connection != null)
+ {
+ try
+ {
+ connection.close();
+ }
+ catch (SQLException e)
+ {
+ LOG.error(e.getMessage(), e);
+ }
+ }
+ }
+ }
+
+}
Property changes on: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainerChecker.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/value/fs/FileIOChannel.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/value/fs/FileIOChannel.java 2011-10-18 13:35:56 UTC (rev 5066)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/value/fs/FileIOChannel.java 2011-10-19 07:55:25 UTC (rev 5067)
@@ -19,6 +19,7 @@
package org.exoplatform.services.jcr.impl.storage.value.fs;
import org.exoplatform.services.jcr.datamodel.ValueData;
+import org.exoplatform.services.jcr.impl.storage.value.ValueDataNotFoundException;
import org.exoplatform.services.jcr.impl.storage.value.ValueDataResourceHolder;
import org.exoplatform.services.jcr.impl.storage.value.ValueOperation;
import org.exoplatform.services.jcr.impl.storage.value.fs.operations.DeleteValues;
@@ -30,7 +31,9 @@
import org.exoplatform.services.log.Log;
import java.io.File;
+import java.io.FileInputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
@@ -166,6 +169,48 @@
}
/**
+ * {@inheritDoc}
+ */
+ public void checkValueData(String propertyId, int orderNumber) throws ValueDataNotFoundException, IOException
+ {
+ try
+ {
+ //check that file exists
+ File f = getFile(propertyId, orderNumber);
+ if (!f.exists())
+ {
+ throw new ValueDataNotFoundException("Value data of property with [id=" + propertyId + ", ordernum="
+ + orderNumber + "] do not exists.");
+ }
+ else
+ {
+ //check readability
+ InputStream is = new FileInputStream(f);
+ try
+ {
+ is.read();
+ }
+ finally
+ {
+ try
+ {
+ is.close();
+ }
+ catch (IOException e)
+ {
+ }
+ }
+ }
+ }
+ catch (IOException e)
+ {
+ throw new ValueDataNotFoundException("Value data of property [id=" + propertyId + ", ordernum=" + orderNumber
+ + "] can not be read.");
+
+ }
+ }
+
+ /**
* Makes storage file path by propertyId and order number.<br/>
*
* @param propertyId
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/storage/value/ValueIOChannel.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/storage/value/ValueIOChannel.java 2011-10-18 13:35:56 UTC (rev 5066)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/storage/value/ValueIOChannel.java 2011-10-19 07:55:25 UTC (rev 5067)
@@ -19,6 +19,7 @@
package org.exoplatform.services.jcr.storage.value;
import org.exoplatform.services.jcr.datamodel.ValueData;
+import org.exoplatform.services.jcr.impl.storage.value.ValueDataNotFoundException;
import java.io.IOException;
@@ -46,6 +47,16 @@
ValueData read(String propertyId, int orderNumber, int maxBufferSize) throws IOException;
/**
+ * Check ValueData. Check that value storage contain this value and value is readable.
+ *
+ * @param propertyId - Property ID
+ * @param orderNumber - Property order number
+ * @throws ValueDataNotFoundException thrown if value data not exist or can not be read
+ * @throws IOException
+ */
+ void checkValueData(String propertyId, int orderNumber) throws ValueDataNotFoundException, IOException;
+
+ /**
* Add or update Property value.
*
* @param propertyId
Modified: jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/core/query/lucene/SlowQueryHandler.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/core/query/lucene/SlowQueryHandler.java 2011-10-18 13:35:56 UTC (rev 5066)
+++ jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/core/query/lucene/SlowQueryHandler.java 2011-10-19 07:55:25 UTC (rev 5067)
@@ -17,7 +17,9 @@
package org.exoplatform.services.jcr.api.core.query.lucene;
import org.apache.lucene.search.Query;
+import org.exoplatform.services.jcr.dataflow.ItemDataConsumer;
import org.exoplatform.services.jcr.datamodel.NodeData;
+import org.exoplatform.services.jcr.impl.InspectionLog;
import org.exoplatform.services.jcr.impl.core.SessionDataManager;
import org.exoplatform.services.jcr.impl.core.SessionImpl;
import org.exoplatform.services.jcr.impl.core.query.AbstractQueryHandler;
@@ -123,4 +125,14 @@
// TODO Auto-generated method stub
}
+
+ /**
+ * @see org.exoplatform.services.jcr.impl.core.query.QueryHandler#checkIndex(org.exoplatform.services.jcr.dataflow.ItemDataConsumer, boolean, InspectionLog)
+ */
+ @Override
+ public void checkIndex(ItemDataConsumer itemStateManager, boolean isSystem, InspectionLog inspectionLog) throws RepositoryException,
+ IOException
+ {
+ // do nothing
+ }
}
Added: jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/TestInspectionLogFile.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/TestInspectionLogFile.java (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/TestInspectionLogFile.java 2011-10-19 07:55:25 UTC (rev 5067)
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2011 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.exoplatform.services.jcr.impl;
+
+import junit.framework.TestCase;
+
+import org.exoplatform.commons.utils.PrivilegedFileHelper;
+import org.exoplatform.services.jcr.impl.InspectionLog.InspectionStatus;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.Writer;
+
+/**
+ * @author <a href="mailto:skarpenko at exoplatform.com">Sergiy Karpenko</a>
+ * @version $Id: exo-jboss-codetemplates.xml 34360 11 ����. 2011 skarpenko $
+ *
+ */
+public class TestInspectionLogFile extends TestCase
+{
+
+ private File f;
+
+ private Writer writer;
+
+ public void setUp() throws Exception
+ {
+ super.setUp();
+ f = File.createTempFile("testlog", "suf");
+ writer = new OutputStreamWriter(PrivilegedFileHelper.fileOutputStream(f));
+ }
+
+ public void tearDown() throws Exception
+ {
+ writer.close();
+ f.delete();
+ super.tearDown();
+ }
+
+ public void testLogComment() throws Exception
+ {
+ InspectionLog report = new InspectionLogWriter(writer);
+ report.logComment("test message");
+
+ // read file;
+ Reader reader = new FileReader(f);
+ BufferedReader br = new BufferedReader(reader);
+ String s = br.readLine();
+ br.close();
+ assertEquals("//test message", s);
+ assertFalse(report.hasInconsistency());
+ }
+
+ public void testLogInspectionDescription() throws Exception
+ {
+ InspectionLog report = new InspectionLogWriter(writer);
+ report.logInspectionDescription("description");
+
+ // read file;
+ Reader reader = new FileReader(f);
+ BufferedReader br = new BufferedReader(reader);
+ String s = br.readLine();
+ br.close();
+ assertEquals("//description", s);
+ assertFalse(report.hasInconsistency());
+ }
+
+ public void testLogBrokenObjectInfo() throws Exception
+ {
+ InspectionLog report = new InspectionLogWriter(writer);
+ report.logBrokenObjectInfo("broken object descr", "message", InspectionStatus.REINDEX);
+
+ // read file;
+ Reader reader = new FileReader(f);
+ BufferedReader br = new BufferedReader(reader);
+ String s = br.readLine();
+ br.close();
+
+ assertEquals("Reindex broken object descr message", s);
+ assertTrue(report.hasInconsistency());
+ }
+
+ public void testLogException() throws Exception
+ {
+ Exception e = new Exception("Exception message.");
+
+ InspectionLog report = new InspectionLogWriter(writer);
+ report.logException("message", e);
+
+ // read file;
+ Reader reader = new FileReader(f);
+ BufferedReader br = new BufferedReader(reader);
+ String s = br.readLine();
+ assertEquals("//message", s);
+ s = br.readLine();
+ assertEquals("//" + e.getMessage(), s);
+ s = br.readLine();
+ assertEquals("//" + e.toString(), s);
+ br.close();
+ assertTrue(report.hasInconsistency());
+ }
+
+}
Property changes on: jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/TestInspectionLogFile.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/TestRepositoryCheckController.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/TestRepositoryCheckController.java (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/TestRepositoryCheckController.java 2011-10-19 07:55:25 UTC (rev 5067)
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2011 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.exoplatform.services.jcr.impl;
+
+import org.exoplatform.services.jcr.BaseStandaloneTest;
+import org.exoplatform.services.jcr.impl.RepositoryCheckController.DataStorage;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+
+import javax.jcr.Node;
+
+/**
+ * @author <a href="mailto:skarpenko at exoplatform.com">Sergiy Karpenko</a>
+ * @version $Id: exo-jboss-codetemplates.xml 34360 10.10.2011 skarpenko $
+ *
+ */
+public class TestRepositoryCheckController extends BaseStandaloneTest
+{
+
+ private RepositoryCheckController checkController;
+
+ /**
+ * @see org.exoplatform.services.jcr.BaseStandaloneTest#getRepositoryName()
+ */
+ @Override
+ protected String getRepositoryName()
+ {
+ String repName = System.getProperty("test.repository");
+ if (repName == null)
+ {
+ throw new RuntimeException(
+ "Test repository is undefined. Set test.repository system property "
+ + "(For maven: in project.properties: maven.junit.sysproperties=test.repository\ntest.repository=<rep-name>)");
+ }
+ return repName;
+
+ }
+
+ public void setUp() throws Exception
+ {
+ super.setUp();
+ checkController = new RepositoryCheckController(repositoryService.getRepository("db1"));
+ }
+
+ public void tearDown() throws Exception
+ {
+ File f = checkController.getLastLogFile();
+ if (f != null)
+ {
+ f.delete();
+ }
+ super.tearDown();
+ }
+
+ public void testDB()
+ {
+ String result = checkController.checkRepositoryDataConsistency(new DataStorage[]{DataStorage.DB});
+ System.out.println("\n\n\n\n\n\n"+result+"\n\n\n\n\n\n");
+ assertEquals("Repository data is consistent. See full report by path "
+ + checkController.getLastLogFile().getAbsolutePath(), result);
+ }
+
+ public void testValueStorage() throws Exception
+ {
+ File f = this.createBLOBTempFile(20);
+ InputStream is = new FileInputStream(f);
+ try
+ {
+ Node n = root.addNode("node");
+ n.setProperty("prop", is);
+
+ root.save();
+
+ String result = checkController.checkRepositoryDataConsistency(new DataStorage[]{DataStorage.VALUE_STORAGE});
+ assertEquals("Repository data is consistent. See full report by path "
+ + checkController.getLastLogFile().getAbsolutePath(), result);
+ }
+ finally
+ {
+ is.close();
+ f.delete();
+ }
+ }
+
+ public void testSearchIndex()
+ {
+ String result = checkController.checkRepositoryDataConsistency(new DataStorage[]{DataStorage.LUCENE_INDEX});
+ assertEquals("Repository data is consistent. See full report by path "
+ + checkController.getLastLogFile().getAbsolutePath(), result);
+ }
+
+ public void testAll()
+ {
+ String result =
+ checkController.checkRepositoryDataConsistency(new DataStorage[]{DataStorage.DB, DataStorage.VALUE_STORAGE,
+ DataStorage.LUCENE_INDEX});
+ System.out.println("\n\n\n\n\n\n"+result+"\n\n\n\n\n\n");
+ assertEquals("Repository data is consistent. See full report by path "
+ + checkController.getLastLogFile().getAbsolutePath(), result);
+ }
+}
Property changes on: jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/TestRepositoryCheckController.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
More information about the exo-jcr-commits
mailing list