From 1a00850ce21cfae75e9706baa23989744f534df3 Mon Sep 17 00:00:00 2001 From: "Brian S. O'Neill" Date: Sun, 16 May 2010 17:11:36 +0000 Subject: Comments and compatibility for new backup features. --- .../carbonado/repo/sleepycat/BDBRepository.java | 268 ++++++++++++--------- .../repo/sleepycat/HotBackupCapability.java | 84 ++++--- 2 files changed, 191 insertions(+), 161 deletions(-) (limited to 'src/main/java/com/amazon/carbonado/repo/sleepycat') diff --git a/src/main/java/com/amazon/carbonado/repo/sleepycat/BDBRepository.java b/src/main/java/com/amazon/carbonado/repo/sleepycat/BDBRepository.java index ed90278..27b4109 100644 --- a/src/main/java/com/amazon/carbonado/repo/sleepycat/BDBRepository.java +++ b/src/main/java/com/amazon/carbonado/repo/sleepycat/BDBRepository.java @@ -159,7 +159,7 @@ abstract class BDBRepository extends AbstractRepository mRunCheckpointer = !builder.getReadOnly() && builder.getRunCheckpointer(); mKeepOldLogFiles = builder.getKeepOldLogFiles(); - mLogInMemory = builder.getLogInMemory(); + mLogInMemory = builder.getLogInMemory(); mRunDeadlockDetector = builder.getRunDeadlockDetector(); mStorableCodecFactory = builder.getStorableCodecFactory(); mPreShutdownHook = builder.getPreShutdownHook(); @@ -221,57 +221,66 @@ abstract class BDBRepository extends AbstractRepository @Override public Backup startBackup() throws RepositoryException { - return startBackup(false); + return startBackup(false); } @Override public Backup startBackup(boolean deleteOldLogFiles) throws RepositoryException { - if (mLogInMemory) { - throw new IllegalStateException("Log files are only kept in memory and backups cannot be performed"); - } + if (mLogInMemory) { + throw new IllegalStateException + ("Log files are only kept in memory and backups cannot be performed"); + } synchronized (mBackupLock) { int count = mBackupCount; if (count == 0) { try { - enterBackupMode(deleteOldLogFiles); + if (deleteOldLogFiles) { + // TODO: If backup rejects log deletion, queue up for later. + enterBackupMode(true); + } else { + // Call old API for backwards compatibility. + enterBackupMode(); + } } catch (Exception e) { throw mExTransformer.toRepositoryException(e); } } mBackupCount = count + 1; - return new FullBackup(); + return new FullBackup(); } } @Override public Backup startIncrementalBackup(long lastLogNumber) - throws RepositoryException + throws RepositoryException { - return startIncrementalBackup(lastLogNumber, false); + return startIncrementalBackup(lastLogNumber, false); } @Override public Backup startIncrementalBackup(long lastLogNumber, boolean deleteOldLogFiles) - throws RepositoryException + throws RepositoryException { - if (mLogInMemory) { - throw new IllegalStateException("Log files are only kept in memory and incremental backup cannot be performed"); - } - - if (lastLogNumber < 0) { - throw new IllegalArgumentException("The number of the last backup cannot be negative"); - } - synchronized (mBackupLock) { - try { - enterIncrementalBackupMode(lastLogNumber, deleteOldLogFiles); - ++mIncrementalBackupCount; - } catch (Exception e) { - throw mExTransformer.toRepositoryException(e); - } - } - return new IncrementalBackup(lastLogNumber); + if (mLogInMemory) { + throw new IllegalStateException + ("Log files are only kept in memory and incremental backup cannot be performed"); + } + + if (lastLogNumber < 0) { + throw new IllegalArgumentException + ("The number of the last backup cannot be negative: " + lastLogNumber); + } + synchronized (mBackupLock) { + try { + enterIncrementalBackupMode(lastLogNumber, deleteOldLogFiles); + ++mIncrementalBackupCount; + } catch (Exception e) { + throw mExTransformer.toRepositoryException(e); + } + } + return new IncrementalBackup(lastLogNumber); } /** @@ -663,6 +672,14 @@ abstract class BDBRepository extends AbstractRepository abstract BDBStorage createBDBStorage(Class type) throws Exception; + /** + * Called only the first time a backup is started. Old API is kept for + * backwards compatibility. + */ + void enterBackupMode() throws Exception { + enterBackupMode(false); + } + /** * Called only the first time a backup is started. */ @@ -676,13 +693,22 @@ abstract class BDBRepository extends AbstractRepository /** * Called only when an incremental backup is started. */ - abstract void enterIncrementalBackupMode(long lastLogNumber, boolean deleteOldLogFiles) throws Exception; + abstract void enterIncrementalBackupMode(long lastLogNumber, boolean deleteOldLogFiles) + throws Exception; /** * Called only after incremental backup ends. */ abstract void exitIncrementalBackupMode() throws Exception; + /** + * Called only if in backup mode. Old API is kept for backwards + * compatibility. + */ + File[] backupFiles() throws Exception { + return backupFiles(new long[1]); + } + /** * Called only if in backup mode. * @@ -914,100 +940,106 @@ abstract class BDBRepository extends AbstractRepository } abstract class AbstractBackup implements Backup { - boolean mDone; - long mFinalLogNumber; - - AbstractBackup() { - mFinalLogNumber = -1; - } - - @Override - public void endBackup() throws RepositoryException { - synchronized (mBackupLock) { - if (mDone) { - return; - } - mDone = true; - finishBackup(); - } - } - - @Override - public File[] getFiles() throws RepositoryException { - synchronized (mBackupLock) { - if (mDone) { - throw new IllegalStateException("Backup has ended"); - } - - try { - long[] newLastLogNum = {-1}; - File[] toReturn = getBackupFiles(newLastLogNum); - mFinalLogNumber = newLastLogNum[0]; - return toReturn; - } catch (Exception e) { - throw mExTransformer.toRepositoryException(e); - } - } - } - - @Override - public long getLastLogNumber() throws RepositoryException { - if (mFinalLogNumber < 0) { - throw new IllegalStateException("Must get files prior to retrieving the last log number"); - } - return mFinalLogNumber; - } - - abstract void finishBackup() throws RepositoryException; - - abstract File[] getBackupFiles(long[] newLastLogNum) throws Exception; + boolean mDone; + long mFinalLogNumber; + + AbstractBackup() { + mFinalLogNumber = -1; + } + + @Override + public void endBackup() throws RepositoryException { + synchronized (mBackupLock) { + if (mDone) { + return; + } + mDone = true; + finishBackup(); + } + } + + @Override + public File[] getFiles() throws RepositoryException { + synchronized (mBackupLock) { + if (mDone) { + throw new IllegalStateException("Backup has ended"); + } + + try { + long[] newLastLogNum = {-1}; + File[] toReturn = getBackupFiles(newLastLogNum); + mFinalLogNumber = newLastLogNum[0]; + return toReturn; + } catch (Exception e) { + throw mExTransformer.toRepositoryException(e); + } + } + } + + @Override + public long getLastLogNumber() throws RepositoryException { + if (mFinalLogNumber < 0) { + throw new IllegalStateException + ("Must get files prior to retrieving the last log number"); + } + return mFinalLogNumber; + } + + abstract void finishBackup() throws RepositoryException; + + abstract File[] getBackupFiles(long[] newLastLogNum) throws Exception; } class IncrementalBackup extends AbstractBackup { - private final long mLastLogNumber; - - IncrementalBackup(long lastLogNumber) { - super(); - mLastLogNumber = lastLogNumber; - } - - @Override - public void finishBackup() throws RepositoryException { - --mIncrementalBackupCount; - - try { - exitIncrementalBackupMode(); - } catch (Exception e) { - throw mExTransformer.toRepositoryException(e); - } - } - - @Override - public File[] getBackupFiles(long[] newLastLogNum) throws Exception { - return incrementalBackup(mLastLogNumber, newLastLogNum); - } + private final long mLastLogNumber; + + IncrementalBackup(long lastLogNumber) { + super(); + mLastLogNumber = lastLogNumber; + } + + @Override + void finishBackup() throws RepositoryException { + --mIncrementalBackupCount; + + try { + exitIncrementalBackupMode(); + } catch (Exception e) { + throw mExTransformer.toRepositoryException(e); + } + } + + @Override + File[] getBackupFiles(long[] newLastLogNum) throws Exception { + return incrementalBackup(mLastLogNumber, newLastLogNum); + } } class FullBackup extends AbstractBackup { - @Override - void finishBackup() throws RepositoryException { - int count = mBackupCount - 1; - try { - if (count == 0) { - try { - exitBackupMode(); - } catch (Exception e) { - throw mExTransformer.toRepositoryException(e); - } - } - } finally { - mBackupCount = count; - } - } - - @Override - public File[] getBackupFiles(long[] newLastLogNum) throws Exception { - return backupFiles(newLastLogNum); - } - } -} \ No newline at end of file + @Override + void finishBackup() throws RepositoryException { + int count = mBackupCount - 1; + try { + if (count == 0) { + try { + exitBackupMode(); + } catch (Exception e) { + throw mExTransformer.toRepositoryException(e); + } + } + } finally { + mBackupCount = count; + } + } + + @Override + File[] getBackupFiles(long[] newLastLogNum) throws Exception { + try { + return backupFiles(newLastLogNum); + } catch (AbstractMethodError e) { + // Call old API for backwards compatibility. + return backupFiles(); + } + } + } +} diff --git a/src/main/java/com/amazon/carbonado/repo/sleepycat/HotBackupCapability.java b/src/main/java/com/amazon/carbonado/repo/sleepycat/HotBackupCapability.java index 76cfb7e..05d8a6d 100644 --- a/src/main/java/com/amazon/carbonado/repo/sleepycat/HotBackupCapability.java +++ b/src/main/java/com/amazon/carbonado/repo/sleepycat/HotBackupCapability.java @@ -25,32 +25,28 @@ import com.amazon.carbonado.RepositoryException; import com.amazon.carbonado.capability.Capability; /** - * Capability for performing a backup of an active BDB environment. To restore - * from a hot backup, it is critical that a full recovery be - * performed. BDB-JE does not require this, however. Pass true to {@link - * BDBRepositoryBuilder#setRunFullRecovery(boolean)} to enable. + * Capability for performing a backup of an active BDB environment. If {@link + * BDBRepositoryBuilder#setLogInMemory(boolean) in-memory logging} is enabled, + * backups cannot be performed. To restore from a hot backup, it is + * critical that a full recovery be performed. Pass true to {@link + * BDBRepositoryBuilder#setRunFullRecovery(boolean) setRunFullRecovery} to + * enable. {@link BDBProduct#JE BDB-JE} does not require this, however. * - *

- * If incremental backups are performed it is required that - * log file removal is disabled in the underlying database. + *

To support incremental backups against the {@link BDBProduct#DB native + * BDB product}, old log files must be kept. Pass true to {@link + * BDBRepositoryBuilder#setKeepOldLogFiles(boolean) setKeepOldLogFiles}. * * @author Brian S O'Neill * @author Olga Kuznetsova * @since 1.2.1 */ public interface HotBackupCapability extends Capability { -///TODO:Have log file deletion be queued after all backups are completed /** * Starts the backup by disabling log file deletion. Be sure to call * endBackup when done to resume log file cleanup. Concurrent backups are * supported. * - *

- * To perform incremental backups use the builder option of setLogInMemory(false) - * so that old log files are not deleted. Log files can be deleted in the - * future before starting a new backup (see method below). - * - * @throws IllegalStateException if log files are being removed (setLogInMemory(true)) + * @throws IllegalStateException if configuration doesn't support backups */ Backup startBackup() throws RepositoryException; @@ -58,23 +54,24 @@ public interface HotBackupCapability extends Capability { * Starts the backup by disabling log file deletion. Be sure to call * endBackup when done to resume log file cleanup. Concurrent backups are supported. * - *

- * Caution should be observed when deleting old log files by force as log files as they may be required - * for future incremental backups (if concurrent backups are running). - * If any concurrent backups are occurring, log fail deletion will fail. + *

Caution should be observed when deleting old log files by force, if + * an external process is also performing backups. If a concurrent backup + * is issued by this repository instance, log file deletion is suppressed. * - * @param deleteOldLogFiles deletes log files that are no longer in use and have been backed up. False by default. - * @throws IllegalStateException if log files are being removed (setLogInMemory(true)) + * @param deleteOldLogFiles deletes log files that are no longer in use and + * have been backed up. False by default. + * @throws IllegalStateException if configuration doesn't support backups */ Backup startBackup(boolean deleteOldLogFiles) throws RepositoryException; /** - * Starts an incremental backup. Log files that are newer than the lastLogNumber will be copied - * during the backup. Should only be run after performing a full backup. + * Starts an incremental backup. Log files that are newer than the + * lastLogNumber will be copied during the backup. Should only be run after + * performing a full backup. * - * @param lastLogNumber number of the last log file that was copied in a previous backup. + * @param lastLogNumber number of the last log file that was copied in a previous backup * @throws IllegalArgumentException if lastLogNumber is negative - * @throws IllegalStateException if log files are being removed (setLogInMemory(true)) + * @throws IllegalStateException if configuration doesn't support backups */ Backup startIncrementalBackup(long lastLogNumber) throws RepositoryException; @@ -82,43 +79,44 @@ public interface HotBackupCapability extends Capability { * Starts an incremental backup. Log files that are newer than the lastLogNumber will be copied * during the backup. Can only be run after performing a full backup. * - *

- * Caution should be observed when deleting old log files by force as log files as they may be required - * for future incremental backups (if concurrent backups are running). - * If any concurrent backups are occurring, log fail deletion will fail. + *

Caution should be observed when deleting old log files by force, if + * an external process is also performing backups. If a concurrent backup + * is issued by this repository instance, log file deletion is suppressed. * * @param lastLogNumber number of the last log file that was copied in a previous backup. - * @param deleteOldLogFiles deletes log files that are no longer in use and have been backed up. False by default. + * @param deleteOldLogFiles deletes log files that are no longer in use and + * have been backed up. False by default. * @throws IllegalArgumentException if lastLogNumber is negative - * @throws IllegalStateException if log files are being removed (setLogInMemory(true)) + * @throws IllegalStateException if configuration doesn't support backups */ - Backup startIncrementalBackup(long lastLogNumber, boolean deleteOldLogFiles) throws RepositoryException; + Backup startIncrementalBackup(long lastLogNumber, boolean deleteOldLogFiles) + throws RepositoryException; public static interface Backup { /** - * Resume normal operation. + * Resume normal operation. */ void endBackup() throws RepositoryException; /** * Returns all the files to be copied, in the exact order in which they * must be copied. - * - *

- * These files must be copied prior to calling endBackup(). + * + *

These files must be durably copied prior to calling {@link #endBackup()}. * * @return ordered array of absolute files * @throws IllegalStateException if backup has ended */ File[] getFiles() throws RepositoryException; - /** - * Can be called after a backup has been performed to find the last log file - * that has been backed up. - * - * @return the file number of the last file in the current backup set. - * This number is required to perform incremental backups. - */ - long getLastLogNumber() throws RepositoryException; + /** + * Can be called after a backup has been performed to find the last log file + * that has been backed up. + * + * @return the file number of the last file in the current backup set. + * This number is required to perform incremental backups. + * @throws IllegalStateException if {@link #getFiles()} was not called + */ + long getLastLogNumber() throws RepositoryException; } } -- cgit v1.2.3