0N/A/*
0N/A * CDDL HEADER START
0N/A *
0N/A * The contents of this file are subject to the terms of the
0N/A * Common Development and Distribution License, Version 1.0 only
0N/A * (the "License"). You may not use this file except in compliance
0N/A * with the License.
0N/A *
6983N/A * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
6983N/A * or http://forgerock.org/license/CDDLv1.0.html.
0N/A * See the License for the specific language governing permissions
0N/A * and limitations under the License.
0N/A *
0N/A * When distributing Covered Code, include this CDDL HEADER in each
6983N/A * file and include the License file at legal-notices/CDDLv1_0.txt.
6983N/A * If applicable, add the following below this CDDL HEADER, with the
6983N/A * fields enclosed by brackets "[]" replaced with your own identifying
6983N/A * information:
0N/A * Portions Copyright [yyyy] [name of copyright owner]
0N/A *
0N/A * CDDL HEADER END
0N/A *
0N/A *
3215N/A * Copyright 2006-2008 Sun Microsystems, Inc.
0N/A */
0N/Apackage org.opends.server.tasks;
2086N/Aimport org.opends.messages.Message;
2728N/Aimport org.opends.messages.TaskMessages;
0N/A
0N/Aimport static org.opends.server.config.ConfigConstants.*;
0N/Aimport static org.opends.server.core.DirectoryServer.getAttributeType;
2086N/Aimport static org.opends.messages.TaskMessages.*;
2086N/Aimport static org.opends.messages.ToolMessages.*;
908N/Aimport static org.opends.server.util.ServerConstants.DATE_FORMAT_GMT_TIME;
1177N/Aimport static org.opends.server.util.StaticUtils.*;
0N/Aimport static org.opends.server.util.ServerConstants.
0N/A BACKUP_DIRECTORY_DESCRIPTOR_FILE;
0N/A
0N/Aimport org.opends.server.backends.task.Task;
0N/Aimport org.opends.server.backends.task.TaskState;
0N/Aimport org.opends.server.core.DirectoryServer;
0N/Aimport org.opends.server.core.LockFileManager;
0N/Aimport org.opends.server.api.Backend;
776N/Aimport org.opends.server.api.ClientConnection;
0N/Aimport org.opends.server.config.ConfigEntry;
0N/Aimport org.opends.server.config.ConfigException;
0N/Aimport org.opends.server.types.Attribute;
0N/Aimport org.opends.server.types.AttributeType;
0N/Aimport org.opends.server.types.BackupConfig;
0N/Aimport org.opends.server.types.BackupDirectory;
338N/Aimport org.opends.server.types.DirectoryException;
0N/Aimport org.opends.server.types.Entry;
1177N/Aimport org.opends.server.types.Operation;
776N/Aimport org.opends.server.types.Privilege;
776N/Aimport org.opends.server.types.ResultCode;
1329N/Aimport org.opends.server.admin.std.server.BackendCfg;
0N/A
0N/Aimport java.util.ArrayList;
0N/Aimport java.util.Date;
0N/Aimport java.util.List;
0N/Aimport java.util.Map;
0N/Aimport java.util.TimeZone;
2488N/Aimport java.util.HashMap;
0N/Aimport java.text.SimpleDateFormat;
0N/Aimport java.io.File;
0N/A
0N/A/**
0N/A * This class provides an implementation of a Directory Server task that may be
0N/A * used to back up a Directory Server backend in a binary form that may be
0N/A * quickly archived and restored.
0N/A */
0N/Apublic class BackupTask extends Task
0N/A{
0N/A
0N/A
2488N/A /**
2488N/A * Stores mapping between configuration attribute name and its label.
2488N/A */
2488N/A static private Map<String,Message> argDisplayMap =
2488N/A new HashMap<String,Message>();
2488N/A static {
2488N/A argDisplayMap.put(
2488N/A ATTR_TASK_BACKUP_ALL,
2488N/A INFO_BACKUP_ARG_BACKUPALL.get());
2488N/A
2488N/A argDisplayMap.put(
2488N/A ATTR_TASK_BACKUP_COMPRESS,
2488N/A INFO_BACKUP_ARG_COMPRESS.get());
2488N/A
2488N/A argDisplayMap.put(
2488N/A ATTR_TASK_BACKUP_ENCRYPT,
2488N/A INFO_BACKUP_ARG_ENCRYPT.get());
2488N/A
2488N/A argDisplayMap.put(
2488N/A ATTR_TASK_BACKUP_HASH,
2488N/A INFO_BACKUP_ARG_HASH.get());
2488N/A
2488N/A argDisplayMap.put(
2488N/A ATTR_TASK_BACKUP_INCREMENTAL,
2488N/A INFO_BACKUP_ARG_INCREMENTAL.get());
2488N/A
2488N/A argDisplayMap.put(
2488N/A ATTR_TASK_BACKUP_SIGN_HASH,
2488N/A INFO_BACKUP_ARG_SIGN_HASH.get());
2488N/A
2488N/A argDisplayMap.put(
2488N/A ATTR_TASK_BACKUP_BACKEND_ID,
2488N/A INFO_BACKUP_ARG_BACKEND_IDS.get());
2488N/A
2488N/A argDisplayMap.put(
2488N/A ATTR_BACKUP_ID,
2488N/A INFO_BACKUP_ARG_BACKUP_ID.get());
2488N/A
2488N/A argDisplayMap.put(
2488N/A ATTR_BACKUP_DIRECTORY_PATH,
2488N/A INFO_BACKUP_ARG_BACKUP_DIR.get());
2488N/A
2488N/A argDisplayMap.put(
2488N/A ATTR_TASK_BACKUP_INCREMENTAL_BASE_ID,
2488N/A INFO_BACKUP_ARG_INC_BASE_ID.get());
2488N/A }
2488N/A
0N/A
266N/A // The task arguments.
0N/A private boolean backUpAll;
0N/A private boolean compress;
0N/A private boolean encrypt;
0N/A private boolean hash;
0N/A private boolean incremental;
0N/A private boolean signHash;
0N/A private List<String> backendIDList;
0N/A private String backupID;
266N/A private File backupDirectory;
0N/A private String incrementalBase;
0N/A
2728N/A private BackupConfig backupConfig;
2728N/A
266N/A /**
266N/A * All the backend configuration entries defined in the server mapped
266N/A * by their backend ID.
266N/A */
266N/A private Map<String,ConfigEntry> configEntries;
266N/A
266N/A private ArrayList<Backend> backendsToArchive;
0N/A
0N/A /**
0N/A * {@inheritDoc}
0N/A */
4005N/A @Override
2488N/A public Message getDisplayName() {
2488N/A return INFO_TASK_BACKUP_NAME.get();
2488N/A }
2488N/A
2488N/A /**
2488N/A * {@inheritDoc}
2488N/A */
4005N/A @Override
2488N/A public Message getAttributeDisplayName(String attrName) {
2488N/A return argDisplayMap.get(attrName);
2488N/A }
2488N/A
2488N/A /**
2488N/A * {@inheritDoc}
2488N/A */
0N/A @Override public void initializeTask() throws DirectoryException
0N/A {
776N/A // If the client connection is available, then make sure the associated
776N/A // client has the BACKEND_BACKUP privilege.
776N/A Operation operation = getOperation();
776N/A if (operation != null)
776N/A {
776N/A ClientConnection clientConnection = operation.getClientConnection();
776N/A if (! clientConnection.hasPrivilege(Privilege.BACKEND_BACKUP, operation))
776N/A {
2086N/A Message message = ERR_TASK_BACKUP_INSUFFICIENT_PRIVILEGES.get();
776N/A throw new DirectoryException(ResultCode.INSUFFICIENT_ACCESS_RIGHTS,
2086N/A message);
776N/A }
776N/A }
0N/A
0N/A
0N/A Entry taskEntry = getTaskEntry();
0N/A
0N/A AttributeType typeBackupAll;
0N/A AttributeType typeCompress;
0N/A AttributeType typeEncrypt;
0N/A AttributeType typeHash;
0N/A AttributeType typeIncremental;
0N/A AttributeType typeSignHash;
0N/A AttributeType typeBackendID;
0N/A AttributeType typeBackupID;
0N/A AttributeType typeBackupDirectory;
0N/A AttributeType typeIncrementalBaseID;
0N/A
0N/A
0N/A typeBackupAll =
0N/A getAttributeType(ATTR_TASK_BACKUP_ALL, true);
0N/A typeCompress =
0N/A getAttributeType(ATTR_TASK_BACKUP_COMPRESS, true);
0N/A typeEncrypt =
0N/A getAttributeType(ATTR_TASK_BACKUP_ENCRYPT, true);
0N/A typeHash =
0N/A getAttributeType(ATTR_TASK_BACKUP_HASH, true);
0N/A typeIncremental =
0N/A getAttributeType(ATTR_TASK_BACKUP_INCREMENTAL, true);
0N/A typeSignHash =
0N/A getAttributeType(ATTR_TASK_BACKUP_SIGN_HASH, true);
0N/A typeBackendID =
0N/A getAttributeType(ATTR_TASK_BACKUP_BACKEND_ID, true);
0N/A typeBackupID =
0N/A getAttributeType(ATTR_BACKUP_ID, true);
0N/A typeBackupDirectory =
0N/A getAttributeType(ATTR_BACKUP_DIRECTORY_PATH, true);
0N/A typeIncrementalBaseID =
0N/A getAttributeType(ATTR_TASK_BACKUP_INCREMENTAL_BASE_ID, true);
0N/A
0N/A
0N/A List<Attribute> attrList;
0N/A
0N/A attrList = taskEntry.getAttribute(typeBackupAll);
0N/A backUpAll = TaskUtils.getBoolean(attrList, false);
0N/A
0N/A attrList = taskEntry.getAttribute(typeCompress);
0N/A compress = TaskUtils.getBoolean(attrList, false);
0N/A
0N/A attrList = taskEntry.getAttribute(typeEncrypt);
0N/A encrypt = TaskUtils.getBoolean(attrList, false);
0N/A
0N/A attrList = taskEntry.getAttribute(typeHash);
0N/A hash = TaskUtils.getBoolean(attrList, false);
0N/A
0N/A attrList = taskEntry.getAttribute(typeIncremental);
0N/A incremental = TaskUtils.getBoolean(attrList, false);
0N/A
0N/A attrList = taskEntry.getAttribute(typeSignHash);
0N/A signHash = TaskUtils.getBoolean(attrList, false);
0N/A
0N/A attrList = taskEntry.getAttribute(typeBackendID);
0N/A backendIDList = TaskUtils.getMultiValueString(attrList);
0N/A
0N/A attrList = taskEntry.getAttribute(typeBackupID);
0N/A backupID = TaskUtils.getSingleValueString(attrList);
0N/A
0N/A attrList = taskEntry.getAttribute(typeBackupDirectory);
266N/A String backupDirectoryPath = TaskUtils.getSingleValueString(attrList);
266N/A backupDirectory = new File(backupDirectoryPath);
266N/A if (! backupDirectory.isAbsolute())
266N/A {
266N/A backupDirectory =
3824N/A new File(DirectoryServer.getInstanceRoot(), backupDirectoryPath);
266N/A }
0N/A
0N/A attrList = taskEntry.getAttribute(typeIncrementalBaseID);
0N/A incrementalBase = TaskUtils.getSingleValueString(attrList);
0N/A
266N/A configEntries = TaskUtils.getBackendConfigEntries();
0N/A }
0N/A
0N/A
0N/A /**
266N/A * Validate the task arguments and construct the list of backends to be
266N/A * archived.
266N/A * @return true if the task arguments are valid.
0N/A */
266N/A private boolean argumentsAreValid()
0N/A {
0N/A // Make sure that either the backUpAll argument was provided or at least one
0N/A // backend ID was given. They are mutually exclusive.
0N/A if (backUpAll)
0N/A {
191N/A if (!backendIDList.isEmpty())
0N/A {
2086N/A Message message = ERR_BACKUPDB_CANNOT_MIX_BACKUP_ALL_AND_BACKEND_ID.get(
2086N/A ATTR_TASK_BACKUP_ALL, ATTR_TASK_BACKUP_BACKEND_ID);
2086N/A logError(message);
266N/A return false;
0N/A }
0N/A }
191N/A else if (backendIDList.isEmpty())
0N/A {
2086N/A Message message = ERR_BACKUPDB_NEED_BACKUP_ALL_OR_BACKEND_ID.get(
2086N/A ATTR_TASK_BACKUP_ALL, ATTR_TASK_BACKUP_BACKEND_ID);
2086N/A logError(message);
266N/A return false;
0N/A }
0N/A
0N/A
4005N/A // Use task id for backup id in case of recurring task.
4005N/A if (super.isRecurring()) {
4005N/A backupID = super.getTaskID();
4005N/A }
4005N/A
4005N/A
0N/A // If no backup ID was provided, then create one with the current timestamp.
0N/A if (backupID == null)
0N/A {
908N/A SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT_GMT_TIME);
0N/A dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
0N/A backupID = dateFormat.format(new Date());
0N/A }
0N/A
0N/A
0N/A // If the incremental base ID was specified, then make sure it is an
0N/A // incremental backup.
0N/A if (incrementalBase != null)
0N/A {
0N/A if (! incremental)
0N/A {
2086N/A Message message = ERR_BACKUPDB_INCREMENTAL_BASE_REQUIRES_INCREMENTAL.
2086N/A get(ATTR_TASK_BACKUP_INCREMENTAL_BASE_ID,
2086N/A ATTR_TASK_BACKUP_INCREMENTAL);
2086N/A logError(message);
266N/A return false;
0N/A }
0N/A }
0N/A
0N/A
0N/A // If the signHash option was provided, then make sure that the hash option
0N/A // was given.
0N/A if (signHash && (! hash))
0N/A {
2086N/A Message message = ERR_BACKUPDB_SIGN_REQUIRES_HASH.get(
2086N/A ATTR_TASK_BACKUP_SIGN_HASH, ATTR_TASK_BACKUP_HASH);
2086N/A logError(message);
266N/A return false;
0N/A }
0N/A
0N/A
0N/A // Make sure that the backup directory exists. If not, then create it.
266N/A if (! backupDirectory.exists())
0N/A {
0N/A try
0N/A {
266N/A backupDirectory.mkdirs();
0N/A }
0N/A catch (Exception e)
0N/A {
2086N/A Message message = ERR_BACKUPDB_CANNOT_CREATE_BACKUP_DIR.get(
2086N/A backupDirectory.getPath(), getExceptionMessage(e));
0N/A System.err.println(message);
266N/A return false;
0N/A }
0N/A }
0N/A
0N/A int numBackends = configEntries.size();
0N/A
0N/A
266N/A backendsToArchive = new ArrayList<Backend>(numBackends);
0N/A
0N/A if (backUpAll)
0N/A {
0N/A for (Map.Entry<String,ConfigEntry> mapEntry : configEntries.entrySet())
0N/A {
0N/A Backend b = DirectoryServer.getBackend(mapEntry.getKey());
0N/A if (b != null && b.supportsBackup())
0N/A {
0N/A backendsToArchive.add(b);
0N/A }
0N/A }
0N/A }
0N/A else
0N/A {
0N/A // Iterate through the set of requested backends and make sure they can
0N/A // be used.
0N/A for (String id : backendIDList)
0N/A {
0N/A Backend b = DirectoryServer.getBackend(id);
0N/A if (b == null || configEntries.get(id) == null)
0N/A {
2086N/A Message message = ERR_BACKUPDB_NO_BACKENDS_FOR_ID.get(id);
2086N/A logError(message);
0N/A }
0N/A else if (! b.supportsBackup())
0N/A {
2086N/A Message message =
2086N/A WARN_BACKUPDB_BACKUP_NOT_SUPPORTED.get(b.getBackendID());
2086N/A logError(message);
0N/A }
0N/A else
0N/A {
0N/A backendsToArchive.add(b);
0N/A }
0N/A }
0N/A
0N/A // It is an error if any of the requested backends could not be used.
0N/A if (backendsToArchive.size() != backendIDList.size())
0N/A {
266N/A return false;
0N/A }
0N/A }
0N/A
0N/A
0N/A // If there are no backends to archive, then print an error and exit.
0N/A if (backendsToArchive.isEmpty())
0N/A {
2086N/A Message message = WARN_BACKUPDB_NO_BACKENDS_TO_ARCHIVE.get();
2086N/A logError(message);
266N/A return false;
266N/A }
266N/A
266N/A
266N/A return true;
266N/A }
266N/A
266N/A
266N/A /**
266N/A * Archive a single backend, where the backend is known to support backups.
266N/A * @param b The backend to be archived.
266N/A * @param backupLocation The backup directory.
266N/A * @return true if the backend was successfully archived.
266N/A */
266N/A private boolean backupBackend(Backend b, File backupLocation)
266N/A {
266N/A // Get the config entry for this backend.
1329N/A BackendCfg cfg = TaskUtils.getConfigEntry(b);
266N/A
266N/A
266N/A // If the directory doesn't exist, then create it. If it does exist, then
266N/A // see if it has a backup descriptor file.
266N/A BackupDirectory backupDir;
266N/A if (backupLocation.exists())
266N/A {
266N/A String descriptorPath = backupLocation.getPath() + File.separator +
266N/A BACKUP_DIRECTORY_DESCRIPTOR_FILE;
266N/A File descriptorFile = new File(descriptorPath);
266N/A if (descriptorFile.exists())
266N/A {
266N/A try
266N/A {
266N/A backupDir = BackupDirectory.readBackupDirectoryDescriptor(
266N/A backupLocation.getPath());
3993N/A
3993N/A // Check the current backup directory corresponds to the provided
3993N/A // backend
3993N/A if (! backupDir.getConfigEntryDN().equals(cfg.dn()))
3993N/A {
3993N/A Message message = ERR_BACKUPDB_CANNOT_BACKUP_IN_DIRECTORY.get(
3993N/A b.getBackendID(),backupLocation.getPath(),
3993N/A backupDir.getConfigEntryDN().getRDN().
4134N/A getAttributeValue(0).toString());
3993N/A logError(message);
3993N/A return false ;
3993N/A }
266N/A }
266N/A catch (ConfigException ce)
266N/A {
2086N/A Message message = ERR_BACKUPDB_CANNOT_PARSE_BACKUP_DESCRIPTOR.get(
2086N/A descriptorPath, ce.getMessage());
2086N/A logError(message);
266N/A return false;
266N/A }
266N/A catch (Exception e)
266N/A {
2086N/A Message message = ERR_BACKUPDB_CANNOT_PARSE_BACKUP_DESCRIPTOR.get(
2086N/A descriptorPath, getExceptionMessage(e));
2086N/A logError(message);
266N/A return false;
266N/A }
266N/A }
266N/A else
266N/A {
1329N/A backupDir = new BackupDirectory(backupLocation.getPath(), cfg.dn());
266N/A }
266N/A }
266N/A else
266N/A {
266N/A try
266N/A {
266N/A backupLocation.mkdirs();
266N/A }
266N/A catch (Exception e)
266N/A {
2086N/A Message message = ERR_BACKUPDB_CANNOT_CREATE_BACKUP_DIR.get(
2086N/A backupLocation.getPath(), getExceptionMessage(e));
2086N/A logError(message);
266N/A return false;
266N/A }
266N/A
266N/A backupDir = new BackupDirectory(backupLocation.getPath(),
1329N/A cfg.dn());
266N/A }
266N/A
266N/A
274N/A // Create a backup configuration.
2728N/A backupConfig = new BackupConfig(backupDir, backupID,
266N/A incremental);
266N/A backupConfig.setCompressData(compress);
266N/A backupConfig.setEncryptData(encrypt);
266N/A backupConfig.setHashData(hash);
266N/A backupConfig.setSignHash(signHash);
266N/A backupConfig.setIncrementalBaseID(incrementalBase);
266N/A
266N/A
266N/A // Perform the backup.
266N/A try
266N/A {
965N/A DirectoryServer.notifyBackupBeginning(b, backupConfig);
1329N/A b.createBackup(backupConfig);
965N/A DirectoryServer.notifyBackupEnded(b, backupConfig, true);
266N/A }
266N/A catch (DirectoryException de)
266N/A {
965N/A DirectoryServer.notifyBackupEnded(b, backupConfig, false);
2086N/A Message message = ERR_BACKUPDB_ERROR_DURING_BACKUP.get(
2086N/A b.getBackendID(), de.getMessageObject());
2086N/A logError(message);
266N/A return false;
266N/A }
266N/A catch (Exception e)
266N/A {
965N/A DirectoryServer.notifyBackupEnded(b, backupConfig, false);
2086N/A Message message = ERR_BACKUPDB_ERROR_DURING_BACKUP.get(
2086N/A b.getBackendID(), getExceptionMessage(e));
2086N/A logError(message);
266N/A return false;
266N/A }
266N/A
266N/A return true;
266N/A }
266N/A
266N/A /**
266N/A * Acquire a shared lock on a backend.
266N/A * @param b The backend on which the lock is to be acquired.
266N/A * @return true if the lock was successfully acquired.
266N/A */
266N/A private boolean lockBackend(Backend b)
266N/A {
266N/A try
266N/A {
266N/A String lockFile = LockFileManager.getBackendLockFileName(b);
266N/A StringBuilder failureReason = new StringBuilder();
266N/A if (! LockFileManager.acquireSharedLock(lockFile, failureReason))
266N/A {
2086N/A Message message = ERR_BACKUPDB_CANNOT_LOCK_BACKEND.get(
2086N/A b.getBackendID(), String.valueOf(failureReason));
2086N/A logError(message);
266N/A return false;
266N/A }
266N/A }
266N/A catch (Exception e)
266N/A {
2086N/A Message message = ERR_BACKUPDB_CANNOT_LOCK_BACKEND.get(
2086N/A b.getBackendID(), getExceptionMessage(e));
2086N/A logError(message);
266N/A return false;
266N/A }
266N/A
266N/A return true;
266N/A }
266N/A
266N/A /**
266N/A * Release a lock on a backend.
266N/A * @param b The backend on which the lock is held.
266N/A * @return true if the lock was successfully released.
266N/A */
266N/A private boolean unlockBackend(Backend b)
266N/A {
266N/A try
266N/A {
266N/A String lockFile = LockFileManager.getBackendLockFileName(b);
266N/A StringBuilder failureReason = new StringBuilder();
266N/A if (! LockFileManager.releaseLock(lockFile, failureReason))
266N/A {
2086N/A Message message = WARN_BACKUPDB_CANNOT_UNLOCK_BACKEND.get(
2086N/A b.getBackendID(), String.valueOf(failureReason));
2086N/A logError(message);
266N/A return false;
266N/A }
266N/A }
266N/A catch (Exception e)
266N/A {
2086N/A Message message = WARN_BACKUPDB_CANNOT_UNLOCK_BACKEND.get(
2086N/A b.getBackendID(), getExceptionMessage(e));
2086N/A logError(message);
266N/A return false;
266N/A }
266N/A
266N/A return true;
266N/A }
266N/A
266N/A
266N/A /**
266N/A * {@inheritDoc}
266N/A */
4005N/A @Override
2728N/A public void interruptTask(TaskState interruptState, Message interruptReason)
2728N/A {
2728N/A if (TaskState.STOPPED_BY_ADMINISTRATOR.equals(interruptState) &&
2728N/A backupConfig != null)
2728N/A {
2728N/A addLogMessage(TaskMessages.INFO_TASK_STOPPED_BY_ADMIN.get(
2728N/A interruptReason));
2728N/A setTaskInterruptState(interruptState);
2728N/A backupConfig.cancel();
2728N/A }
2728N/A }
2728N/A
2728N/A
2728N/A /**
2728N/A * {@inheritDoc}
2728N/A */
4005N/A @Override
2728N/A public boolean isInterruptable() {
2728N/A return true;
2728N/A }
2728N/A
2728N/A
2728N/A /**
2728N/A * {@inheritDoc}
2728N/A */
4134N/A @Override
266N/A protected TaskState runTask()
266N/A {
266N/A if (!argumentsAreValid())
266N/A {
0N/A return TaskState.STOPPED_BY_ERROR;
0N/A }
0N/A
266N/A boolean multiple;
266N/A if (backUpAll)
266N/A {
266N/A // We'll proceed as if we're backing up multiple backends in this case
266N/A // even if there's just one.
266N/A multiple = true;
266N/A }
266N/A else
266N/A {
266N/A // See if there are multiple backends to archive.
266N/A multiple = (backendsToArchive.size() > 1);
266N/A }
266N/A
0N/A
0N/A // Iterate through the backends to archive and back them up individually.
0N/A boolean errorsEncountered = false;
0N/A for (Backend b : backendsToArchive)
0N/A {
2728N/A if (isCancelled())
2728N/A {
2728N/A break;
2728N/A }
2728N/A
0N/A // Acquire a shared lock for this backend.
266N/A if (!lockBackend(b))
0N/A {
0N/A errorsEncountered = true;
0N/A continue;
0N/A }
0N/A
0N/A
266N/A try
0N/A {
2086N/A Message message = NOTE_BACKUPDB_STARTING_BACKUP.get(b.getBackendID());
2086N/A logError(message);
0N/A
0N/A
266N/A // Get the path to the directory to use for this backup. If we will be
266N/A // backing up multiple backends (or if we are backing up all backends,
266N/A // even if there's only one of them), then create a subdirectory for
266N/A // each
266N/A // backend.
266N/A File backupLocation;
266N/A if (multiple)
0N/A {
266N/A backupLocation = new File(backupDirectory, b.getBackendID());
0N/A }
0N/A else
0N/A {
266N/A backupLocation = backupDirectory;
0N/A }
0N/A
0N/A
266N/A if (!backupBackend(b, backupLocation))
0N/A {
0N/A errorsEncountered = true;
0N/A }
0N/A }
266N/A finally
0N/A {
266N/A // Release the shared lock for the backend.
266N/A if (!unlockBackend(b))
266N/A {
266N/A errorsEncountered = true;
266N/A }
0N/A }
0N/A }
0N/A
0N/A
0N/A // Print a final completed message, indicating whether there were any errors
3115N/A // in the process. In this case it means that the backup could not be
3115N/A // completed at least for one of the backends.
0N/A if (errorsEncountered)
0N/A {
2086N/A Message message = NOTE_BACKUPDB_COMPLETED_WITH_ERRORS.get();
2086N/A logError(message);
3115N/A return TaskState.STOPPED_BY_ERROR;
0N/A }
2728N/A else if (isCancelled())
2728N/A {
2728N/A Message message = NOTE_BACKUPDB_CANCELLED.get();
2728N/A logError(message);
2728N/A return getTaskInterruptState();
2728N/A }
0N/A else
0N/A {
2086N/A Message message = NOTE_BACKUPDB_COMPLETED_SUCCESSFULLY.get();
2086N/A logError(message);
0N/A return TaskState.COMPLETED_SUCCESSFULLY;
0N/A }
0N/A }
0N/A
0N/A
0N/A}