/* ********************************************************************** **
** Copyright notice **
** **
** (c) 2005-2009 RSSOwl Development Team **
** http://www.rssowl.org/ **
** **
** All rights reserved **
** **
** This program and the accompanying materials are made available under **
** the terms of the Eclipse Public License v1.0 which accompanies this **
** distribution, and is available at: **
** http://www.rssowl.org/legal/epl-v10.html **
** **
** A copy is found in the file epl-v10.html and important notices to the **
** license from the team is found in the textfile LICENSE.txt distributed **
** in this package. **
** **
** This copyright notice MUST APPEAR in all copies of the file! **
** **
** Contributors: **
** RSSOwl Development Team - initial API and implementation **
** **
** ********************************************************************** */
package org.rssowl.core.internal.persist.service;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.rssowl.core.Owl.StartLevel;
import org.rssowl.core.internal.Activator;
import org.rssowl.core.internal.InternalOwl;
import org.rssowl.core.persist.service.AbstractPersistenceService;
import org.rssowl.core.persist.service.PersistenceException;
import org.rssowl.core.util.LongOperationMonitor;
import org.rssowl.core.util.Pair;
import java.io.File;
import java.io.IOException;
import java.util.List;
/**
* The persistence service controls the lifecycle of the underlying database.
*
* @author bpasero
*/
public class PersistenceServiceImpl extends AbstractPersistenceService {
/** Default Constructor */
public PersistenceServiceImpl() {}
/*
* @see
* org.rssowl.core.persist.service.AbstractPersistenceService#startup(org.
* rssowl.core.util.LongOperationMonitor, boolean, boolean)
*/
@Override
public void startup(LongOperationMonitor monitor, boolean emergency, boolean forRestore) {
super.startup(monitor, emergency, forRestore);
/* Startup DB */
DBManager.getDefault().startup(monitor, emergency, forRestore);
InternalOwl.getDefault().setStartLevel(StartLevel.DB_OPENED);
/* Startup Model Search (not in case of emergency) */
if (!emergency) {
getModelSearch().startup();
InternalOwl.getDefault().setStartLevel(StartLevel.SEARCH_INDEX_OPENED);
}
}
/*
* @see org.rssowl.core.persist.service.IPersistenceService#shutdown(boolean)
*/
public void shutdown(boolean emergency) throws PersistenceException {
/* Shutdown ID Generator, Search and DB */
if (!emergency) {
/* ID Generator (safely) */
try {
getIDGenerator().shutdown();
} catch (Exception e) {
Activator.safeLogError(e.getMessage(), e);
}
/* Search (safely) */
try {
getModelSearch().shutdown(emergency);
} catch (Exception e) {
Activator.safeLogError(e.getMessage(), e);
}
/* DB */
DBManager.getDefault().shutdown();
}
/* Emergent Exit: Shutdown DB and Search */
else {
/* DB (safely) */
try {
DBManager.getDefault().shutdown();
} catch (Exception e) {
Activator.safeLogError(e.getMessage(), e);
}
/* Search */
getModelSearch().shutdown(emergency);
}
}
/**
* Instructs the persistence service to schedule an optimization run during
* the next time the application is started. The actual optimization type is
* dependent on the persistence system being used and implementors are free to
* leave this as a no-op in case the the persistence system tunes itself
* automatically during runtime.
*
* @throws PersistenceException in case a problem occurs while trying to
* schedule this operation.
*/
public void defragmentOnNextStartup() throws PersistenceException {
try {
DBManager.getDefault().getDefragmentFile().createNewFile();
} catch (IOException e) {
throw new PersistenceException(e);
}
}
/**
* Returns the profile {@link File} that contains all data and the
* {@link Long} timestamp when it was last successfully used.
*
* @return the profile {@link File} and the {@link Long} timestamp when it was
* last successfully used.
*/
public Pair<File, Long> getProfile() {
return DBManager.getDefault().getProfile();
}
/**
* Provides a list of available backups for the user to restore from in case
* of an unrecoverable error.
*
* @return a list of available backups for the user to restore from in case of
* an unrecoverable error.
*/
public List<File> getProfileBackups() {
return DBManager.getDefault().getProfileBackups();
}
/**
* Will rename the provided backup file to the operational RSSOwl profile
* database.
*
* @param backup the backup {@link File} to restore from.
* @throws PersistenceException in case a problem occurs while trying to
* execute this operation.
*/
public void restoreProfile(File backup) throws PersistenceException {
DBManager.getDefault().restoreProfile(backup);
}
/**
* Recreate the Profile of the persistence layer. In case of a Database, this
* would drop relations and create them again.
*
* @param needsEmergencyStartup if <code>true</code> causes this method to
* also trigger an emergency startup so that other operations can be normally
* done afterwards like importing from a OPML backup.
* @throws PersistenceException In case of an error while starting up the
* persistence layer.
*/
public void recreateProfile(boolean needsEmergencyStartup) throws PersistenceException {
Activator.safeLogInfo(needsEmergencyStartup ? "Start: Recreate Profile with OPML Import" : "Start: Start Over with Fresh Profile"); //$NON-NLS-1$ //$NON-NLS-2$
/* First check to delete the "rssowl.db.restore" file that is being used */
File restoreDBFile = new File(DBManager.getDBRestoreFilePath());
if (restoreDBFile.exists())
restoreDBFile.delete();
/* Delete the large blocksize marker if present because we start with an empty profile again */
File largeBlockSizeMarkerFile = DBManager.getLargeBlockSizeMarkerFile();
if (largeBlockSizeMarkerFile.exists())
largeBlockSizeMarkerFile.delete();
/* Communicate shutdown to listeners (mandatory before reopening for restore) */
DBManager.getDefault().shutdown();
/* Open new empty DB for restore */
if (!needsEmergencyStartup)
DBManager.getDefault().startup(new LongOperationMonitor(new NullProgressMonitor()) {}, true, true);
/* Otherwise if startup is needed, startup with empty DB */
else
InternalOwl.getDefault().startup(new LongOperationMonitor(new NullProgressMonitor()) {}, true, true);
/* Reindex on next startup */
InternalOwl.getDefault().getPersistenceService().getModelSearch().reIndexOnNextStartup();
Activator.safeLogInfo(needsEmergencyStartup ? "End: Recreate Profile with OPML Import" : "End: Start Over with Fresh Profile"); //$NON-NLS-1$ //$NON-NLS-2$
}
/**
* Only used from tests to get a clean start for each test case.
*
* @throws PersistenceException
*/
public void recreateSchemaForTests() throws PersistenceException {
DBManager.getDefault().dropDatabaseForTests();
DBManager.getDefault().startup(new LongOperationMonitor(new NullProgressMonitor()) {}, true, false);
getModelSearch().clearIndex();
}
}