opendj-server-legacy/src/main/java/org/opends/server/backends/persistit/PersistItStorage.java
@@ -30,13 +30,19 @@ import static org.opends.messages.ConfigMessages.ERR_CONFIG_BACKEND_INSANE_MODE; import static org.opends.messages.ConfigMessages.ERR_CONFIG_BACKEND_MODE_INVALID; import static org.opends.messages.JebMessages.*; import static org.opends.server.util.ServerConstants.ALERT_DESCRIPTION_DISK_FULL; import static org.opends.server.util.ServerConstants.ALERT_DESCRIPTION_DISK_SPACE_LOW; import static org.opends.server.util.ServerConstants.ALERT_TYPE_DISK_FULL; import static org.opends.server.util.ServerConstants.ALERT_TYPE_DISK_SPACE_LOW; import static org.opends.server.util.StaticUtils.*; import java.io.File; import java.io.FilenameFilter; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; import org.forgerock.i18n.LocalizableMessage; import org.forgerock.i18n.slf4j.LocalizedLogger; @@ -46,17 +52,22 @@ import org.opends.server.admin.server.ConfigurationChangeListener; import org.opends.server.admin.std.server.PersistitBackendCfg; import org.opends.server.admin.std.server.PluggableBackendCfg; import org.opends.server.api.AlertGenerator; import org.opends.server.api.DiskSpaceMonitorHandler; import org.opends.server.backends.pluggable.spi.Cursor; import org.opends.server.backends.pluggable.spi.Importer; import org.opends.server.backends.pluggable.spi.ReadOperation; import org.opends.server.backends.pluggable.spi.Storage; import org.opends.server.backends.pluggable.spi.StorageRuntimeException; import org.opends.server.backends.pluggable.spi.StorageStatus; import org.opends.server.backends.pluggable.spi.TreeName; import org.opends.server.backends.pluggable.spi.UpdateFunction; import org.opends.server.backends.pluggable.spi.WriteOperation; import org.opends.server.backends.pluggable.spi.WriteableStorage; import org.opends.server.config.ConfigException; import org.opends.server.core.DirectoryServer; import org.opends.server.extensions.DiskSpaceMonitor; import org.opends.server.types.DN; import org.opends.server.types.FilePermission; import com.persistit.Configuration; @@ -74,7 +85,8 @@ import com.persistit.exception.RollbackException; /** PersistIt database implementation of the {@link Storage} engine. */ public final class PersistItStorage implements Storage, ConfigurationChangeListener<PersistitBackendCfg> public final class PersistItStorage implements Storage, ConfigurationChangeListener<PersistitBackendCfg>, DiskSpaceMonitorHandler, AlertGenerator { private static final String VOLUME_NAME = "dj"; /** The buffer / page size used by the PersistIt storage. */ @@ -501,6 +513,7 @@ private Volume volume; private Configuration dbCfg; private PersistitBackendCfg config; private DiskSpaceMonitor diskMonitor; /** {@inheritDoc} */ @Override @@ -519,6 +532,8 @@ } } config.removePersistitChangeListener(this); DirectoryServer.deregisterMonitorProvider(diskMonitor); DirectoryServer.deregisterAlertGenerator(this); } /** {@inheritDoc} */ @@ -562,13 +577,6 @@ /** {@inheritDoc} */ @Override public boolean isValid() { return !db.isFatal(); } /** {@inheritDoc} */ @Override public void open() throws Exception { setupStorageFiles(); @@ -588,6 +596,11 @@ { throw new StorageRuntimeException(e); } // Register as disk space monitor handler diskMonitor = newDiskMonitor(config); DirectoryServer.registerMonitorProvider(diskMonitor); //Register as an AlertGenerator. DirectoryServer.registerAlertGenerator(this); } /** {@inheritDoc} */ @@ -900,6 +913,8 @@ setDBDirPermissions(cfg, newBackendDirectory); } diskMonitor.setFullThreshold(cfg.getDiskFullThreshold()); diskMonitor.setLowThreshold(cfg.getDiskLowThreshold()); config = cfg; } @@ -957,5 +972,78 @@ throw new StorageRuntimeException(message.toString(), e); } } @Override public StorageStatus getStorageStatus() { if (diskMonitor.isFullThresholdReached()) { return StorageStatus.unusable(WARN_JEB_OUT_OF_DISK_SPACE.get()); } if (diskMonitor.isLowThresholdReached()) { return StorageStatus.lockedDown(WARN_JEB_OUT_OF_DISK_SPACE.get()); } return StorageStatus.working(); } /** {@inheritDoc} */ @Override public void diskFullThresholdReached(DiskSpaceMonitor monitor) { LocalizableMessage msg = ERR_JEB_DISK_FULL_THRESHOLD_REACHED.get( monitor.getDirectory().getPath(), config.getBackendId(), monitor.getFreeSpace(), Math.max(monitor.getLowThreshold(), monitor.getFullThreshold())); DirectoryServer.sendAlertNotification(this, ALERT_TYPE_DISK_FULL, msg); } /** {@inheritDoc} */ @Override public void diskLowThresholdReached(DiskSpaceMonitor monitor) { LocalizableMessage msg = ERR_JEB_DISK_LOW_THRESHOLD_REACHED.get( monitor.getDirectory().getPath(), config.getBackendId(), monitor.getFreeSpace(), Math.max(monitor.getLowThreshold(), monitor.getFullThreshold())); DirectoryServer.sendAlertNotification(this, ALERT_TYPE_DISK_SPACE_LOW, msg); } /** {@inheritDoc} */ @Override public void diskSpaceRestored(DiskSpaceMonitor monitor) { logger.error(NOTE_JEB_DISK_SPACE_RESTORED, monitor.getFreeSpace(), monitor.getDirectory().getPath(), config.getBackendId(), Math.max(monitor.getLowThreshold(), monitor.getFullThreshold())); } private DiskSpaceMonitor newDiskMonitor(PersistitBackendCfg config) throws Exception { File parentDirectory = getFileForPath(config.getDBDirectory()); File backendDirectory = new File(parentDirectory, config.getBackendId()); DiskSpaceMonitor dm = new DiskSpaceMonitor(config.getBackendId() + " backend", backendDirectory, config.getDiskLowThreshold(), config.getDiskFullThreshold(), 5, TimeUnit.SECONDS, this); dm.initializeMonitorProvider(null); return dm; } /** {@inheritDoc} */ @Override public DN getComponentEntryDN() { return config.dn(); } /** {@inheritDoc} */ @Override public String getClassName() { return PersistItStorage.class.getName(); } /** {@inheritDoc} */ @Override public Map<String, String> getAlerts() { Map<String, String> alerts = new LinkedHashMap<String, String>(); alerts.put(ALERT_TYPE_DISK_SPACE_LOW, ALERT_DESCRIPTION_DISK_SPACE_LOW); alerts.put(ALERT_TYPE_DISK_FULL, ALERT_DESCRIPTION_DISK_FULL); return alerts; } } opendj-server-legacy/src/main/java/org/opends/server/backends/persistit/PitBackend.java
@@ -29,15 +29,11 @@ import static org.opends.server.util.StaticUtils.getFileForPath; import java.io.File; import java.util.concurrent.TimeUnit; import org.forgerock.opendj.config.server.ConfigException; import org.opends.server.admin.std.server.PersistitBackendCfg; import org.opends.server.admin.std.server.PluggableBackendCfg; import org.opends.server.backends.pluggable.BackendImpl; import org.opends.server.backends.pluggable.spi.Storage; import org.opends.server.extensions.DiskSpaceMonitor; import org.opends.server.types.InitializationException; /** * Class defined in the configuration for this backend type. @@ -52,30 +48,6 @@ } /** {@inheritDoc} */ @Override public DiskSpaceMonitor newDiskMonitor(PluggableBackendCfg cfg) throws ConfigException, InitializationException { PersistitBackendCfg config = (PersistitBackendCfg) cfg; File parentDirectory = getFileForPath(config.getDBDirectory()); File backendDirectory = new File(parentDirectory, config.getBackendId()); DiskSpaceMonitor dm = new DiskSpaceMonitor(getBackendID() + " backend", backendDirectory, config.getDiskLowThreshold(), config.getDiskFullThreshold(), 5, TimeUnit.SECONDS, this); dm.initializeMonitorProvider(null); return dm; } /** {@inheritDoc} */ @Override public void updateDiskMonitor(DiskSpaceMonitor dm, PluggableBackendCfg newConfig) { PersistitBackendCfg newCfg = (PersistitBackendCfg) newConfig; dm.setFullThreshold(newCfg.getDiskFullThreshold()); dm.setLowThreshold(newCfg.getDiskLowThreshold()); } /** {@inheritDoc} */ protected File getBackupDirectory(PluggableBackendCfg cfg) { PersistitBackendCfg config = (PersistitBackendCfg) cfg; opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/BackendImpl.java
@@ -49,9 +49,7 @@ import org.opends.server.admin.std.meta.BackendIndexCfgDefn; import org.opends.server.admin.std.server.PersistitBackendCfg; import org.opends.server.admin.std.server.PluggableBackendCfg; import org.opends.server.api.AlertGenerator; import org.opends.server.api.Backend; import org.opends.server.api.DiskSpaceMonitorHandler; import org.opends.server.api.MonitorProvider; import org.opends.server.backends.RebuildConfig; import org.opends.server.backends.VerifyConfig; @@ -60,7 +58,6 @@ import org.opends.server.backends.pluggable.spi.WriteOperation; import org.opends.server.backends.pluggable.spi.WriteableStorage; import org.opends.server.core.*; import org.opends.server.extensions.DiskSpaceMonitor; import org.opends.server.types.*; /** @@ -68,8 +65,7 @@ * locally in a Berkeley DB JE database. */ public abstract class BackendImpl extends Backend<PluggableBackendCfg> implements ConfigurationChangeListener<PluggableBackendCfg>, AlertGenerator, DiskSpaceMonitorHandler ConfigurationChangeListener<PluggableBackendCfg> { private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); @@ -85,9 +81,6 @@ private DN[] baseDNs; private MonitorProvider<?> rootContainerMonitor; /** Disk space monitoring if the storage supports it. */ private DiskSpaceMonitor diskMonitor; /** The controls supported by this backend. */ private static final Set<String> supportedControls = new HashSet<String>(Arrays.asList( OID_SUBTREE_DELETE_CONTROL, @@ -96,10 +89,24 @@ OID_SERVER_SIDE_SORT_REQUEST_CONTROL, OID_VLV_REQUEST_CONTROL)); /** Begin a Backend API method that accesses the database. */ private void accessBegin() /** * Begin a Backend API method that accesses the database and returns the <code>EntryContainer</code> for * <code>entryDN</code>. * @param operation requesting the storage * @param entryDN the target DN for the operation * @return <code>EntryContainer</code> where <code>entryDN</code> resides */ private EntryContainer accessBegin(Operation operation, DN entryDN) throws DirectoryException { checkRootContainerInitialized(); rootContainer.checkForEnoughResources(operation); EntryContainer ec = rootContainer.getEntryContainer(entryDN); if (ec == null) { throw new DirectoryException(ResultCode.UNDEFINED, ERR_BACKEND_ENTRY_DOESNT_EXIST.get(entryDN, getBackendID())); } threadTotalCount.getAndIncrement(); return ec; } /** End a Backend API method that accesses the database. */ @@ -181,39 +188,10 @@ rootContainerMonitor = rootContainer.getMonitorProvider(); DirectoryServer.registerMonitorProvider(rootContainerMonitor); // Register as disk space monitor handler diskMonitor = newDiskMonitor(cfg); if (diskMonitor != null) { DirectoryServer.registerMonitorProvider(diskMonitor); } //Register as an AlertGenerator. DirectoryServer.registerAlertGenerator(this); // Register this backend as a change listener. cfg.addPluggableChangeListener(this); } /** * Let the storage create a new disk monitor if supported. * * @param cfg this storage current configuration * @return a new disk monitor if supported or null * * @throws ConfigException if configuration is incorrect * @throws InitializationException when disk monitor cannot be initialized */ protected abstract DiskSpaceMonitor newDiskMonitor(PluggableBackendCfg cfg) throws ConfigException, InitializationException; /** * Updates the disk monitor when configuration changes. * * @param dm the disk monitor to update * @param newCfg the new configuration */ protected abstract void updateDiskMonitor(DiskSpaceMonitor dm, PluggableBackendCfg newCfg); /** {@inheritDoc} */ @Override public void finalizeBackend() @@ -235,7 +213,6 @@ } DirectoryServer.deregisterMonitorProvider(rootContainerMonitor); DirectoryServer.deregisterMonitorProvider(diskMonitor); // We presume the server will prevent more operations coming into this // backend, but there may be existing operations already in the @@ -254,8 +231,6 @@ logger.error(ERR_JEB_DATABASE_EXCEPTION, e.getMessage()); } DirectoryServer.deregisterAlertGenerator(this); // Make sure the thread counts are zero for next initialization. threadTotalCount.set(0); @@ -364,8 +339,7 @@ /** {@inheritDoc} */ @Override public ConditionResult hasSubordinates(DN entryDN) throws DirectoryException public ConditionResult hasSubordinates(DN entryDN) throws DirectoryException { long ret = numSubordinates(entryDN, false); if(ret < 0) @@ -379,17 +353,26 @@ /** {@inheritDoc} */ @Override public long numSubordinates(DN entryDN, boolean subtree) throws DirectoryException public long numSubordinates(DN entryDN, boolean subtree) throws DirectoryException { checkRootContainerInitialized(); EntryContainer ec = rootContainer.getEntryContainer(entryDN); if(ec == null) EntryContainer ec; /* * Only place where we need special handling. Should return -1 instead of an * error if the EntryContainer is null... */ try { ec = accessBegin(null, entryDN); } catch (DirectoryException de) { return -1; if (de.getResultCode() == ResultCode.UNDEFINED) { return -1; } throw de; } accessBegin(); ec.sharedLock.lock(); try { @@ -419,10 +402,8 @@ @Override public Entry getEntry(DN entryDN) throws DirectoryException { accessBegin(); EntryContainer ec = accessBegin(null, entryDN); checkRootContainerInitialized(); EntryContainer ec = rootContainer.getEntryContainer(entryDN); ec.sharedLock.lock(); Entry entry; try @@ -447,14 +428,10 @@ /** {@inheritDoc} */ @Override public void addEntry(Entry entry, AddOperation addOperation) throws DirectoryException, CanceledOperationException public void addEntry(Entry entry, AddOperation addOperation) throws DirectoryException, CanceledOperationException { checkDiskSpace(addOperation); accessBegin(); EntryContainer ec = accessBegin(addOperation, entry.getName()); checkRootContainerInitialized(); EntryContainer ec = rootContainer.getEntryContainer(entry.getName()); ec.sharedLock.lock(); try { @@ -479,11 +456,8 @@ public void deleteEntry(DN entryDN, DeleteOperation deleteOperation) throws DirectoryException, CanceledOperationException { checkDiskSpace(deleteOperation); accessBegin(); EntryContainer ec = accessBegin(deleteOperation, entryDN); checkRootContainerInitialized(); EntryContainer ec = rootContainer.getEntryContainer(entryDN); ec.sharedLock.lock(); try { @@ -505,15 +479,11 @@ /** {@inheritDoc} */ @Override public void replaceEntry(Entry oldEntry, Entry newEntry, ModifyOperation modifyOperation) throws DirectoryException, CanceledOperationException public void replaceEntry(Entry oldEntry, Entry newEntry, ModifyOperation modifyOperation) throws DirectoryException, CanceledOperationException { checkDiskSpace(modifyOperation); accessBegin(); EntryContainer ec = accessBegin(modifyOperation, newEntry.getName()); checkRootContainerInitialized(); EntryContainer ec = rootContainer.getEntryContainer(newEntry.getName()); ec.sharedLock.lock(); try @@ -536,23 +506,18 @@ /** {@inheritDoc} */ @Override public void renameEntry(DN currentDN, Entry entry, ModifyDNOperation modifyDNOperation) public void renameEntry(DN currentDN, Entry entry, ModifyDNOperation modifyDNOperation) throws DirectoryException, CanceledOperationException { checkDiskSpace(modifyDNOperation); accessBegin(); checkRootContainerInitialized(); EntryContainer currentContainer = rootContainer.getEntryContainer(currentDN); EntryContainer currentContainer = accessBegin(modifyDNOperation, currentDN); EntryContainer container = rootContainer.getEntryContainer(entry.getName()); if (currentContainer != container) { accessEnd(); // FIXME: No reason why we cannot implement a move between containers // since the containers share the same database environment. LocalizableMessage msg = WARN_JEB_FUNCTION_NOT_SUPPORTED.get(); throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, msg); throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, WARN_JEB_FUNCTION_NOT_SUPPORTED.get()); } currentContainer.sharedLock.lock(); @@ -576,13 +541,10 @@ /** {@inheritDoc} */ @Override public void search(SearchOperation searchOperation) throws DirectoryException, CanceledOperationException public void search(SearchOperation searchOperation) throws DirectoryException, CanceledOperationException { accessBegin(); EntryContainer ec = accessBegin(searchOperation, searchOperation.getBaseDN()); checkRootContainerInitialized(); EntryContainer ec = rootContainer.getEntryContainer(searchOperation.getBaseDN()); ec.sharedLock.lock(); try @@ -876,11 +838,6 @@ baseDNs = newBaseDNsArray; if (diskMonitor != null) { updateDiskMonitor(diskMonitor, newCfg); } // Put the new configuration in place. cfg = newCfg; } @@ -975,62 +932,18 @@ */ private DirectoryException createDirectoryException(StorageRuntimeException e) { if (true) // FIXME JNR Throwable cause = e.getCause(); if (cause instanceof OpenDsException) { Throwable cause = e.getCause(); if (cause instanceof OpenDsException) { return new DirectoryException( DirectoryServer.getServerErrorResultCode(), (OpenDsException) cause); } else { return new DirectoryException( DirectoryServer.getServerErrorResultCode(), LocalizableMessage.raw(e.getMessage()), e); } return new DirectoryException( DirectoryServer.getServerErrorResultCode(), (OpenDsException) cause); } if (/*e instanceof EnvironmentFailureException && */ !rootContainer.isValid()) { LocalizableMessage message = NOTE_BACKEND_ENVIRONMENT_UNUSABLE.get(getBackendID()); logger.info(message); DirectoryServer.sendAlertNotification(DirectoryServer.getInstance(), ALERT_TYPE_BACKEND_ENVIRONMENT_UNUSABLE, message); else { return new DirectoryException( DirectoryServer.getServerErrorResultCode(), LocalizableMessage.raw(e.getMessage()), e); } String jeMessage = e.getMessage(); if (jeMessage == null) { jeMessage = stackTraceToSingleLineString(e); } LocalizableMessage message = ERR_JEB_DATABASE_EXCEPTION.get(jeMessage); return new DirectoryException( DirectoryServer.getServerErrorResultCode(), message, e); } /** {@inheritDoc} */ @Override public String getClassName() { return BackendImpl.class.getName(); } /** {@inheritDoc} */ @Override public Map<String, String> getAlerts() { Map<String, String> alerts = new LinkedHashMap<String, String>(); alerts.put(ALERT_TYPE_BACKEND_ENVIRONMENT_UNUSABLE, ALERT_DESCRIPTION_BACKEND_ENVIRONMENT_UNUSABLE); alerts.put(ALERT_TYPE_DISK_SPACE_LOW, ALERT_DESCRIPTION_DISK_SPACE_LOW); alerts.put(ALERT_TYPE_DISK_FULL, ALERT_DESCRIPTION_DISK_FULL); return alerts; } /** {@inheritDoc} */ @Override public DN getComponentEntryDN() { return cfg.dn(); } private RootContainer initializeRootContainer() @@ -1056,43 +969,4 @@ EntryCachePreloader preloader = new EntryCachePreloader(this); preloader.preload(); } /** {@inheritDoc} */ @Override public void diskLowThresholdReached(DiskSpaceMonitor monitor) { LocalizableMessage msg = ERR_JEB_DISK_LOW_THRESHOLD_REACHED.get( monitor.getDirectory().getPath(), cfg.getBackendId(), monitor.getFreeSpace(), Math.max(monitor.getLowThreshold(), monitor.getFullThreshold())); DirectoryServer.sendAlertNotification(this, ALERT_TYPE_DISK_SPACE_LOW, msg); } /** {@inheritDoc} */ @Override public void diskFullThresholdReached(DiskSpaceMonitor monitor) { LocalizableMessage msg = ERR_JEB_DISK_FULL_THRESHOLD_REACHED.get( monitor.getDirectory().getPath(), cfg.getBackendId(), monitor.getFreeSpace(), Math.max(monitor.getLowThreshold(), monitor.getFullThreshold())); DirectoryServer.sendAlertNotification(this, ALERT_TYPE_DISK_FULL, msg); } /** {@inheritDoc} */ @Override public void diskSpaceRestored(DiskSpaceMonitor monitor) { logger.error(NOTE_JEB_DISK_SPACE_RESTORED, monitor.getFreeSpace(), monitor.getDirectory().getPath(), cfg.getBackendId(), Math.max(monitor.getLowThreshold(), monitor.getFullThreshold())); } private void checkDiskSpace(Operation operation) throws DirectoryException { if(diskMonitor.isFullThresholdReached() || (diskMonitor.isLowThresholdReached() && operation != null && !operation.getClientConnection().hasPrivilege( Privilege.BYPASS_LOCKDOWN, operation))) { throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, WARN_JEB_OUT_OF_DISK_SPACE.get()); } } } opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/RootContainer.java
@@ -53,6 +53,7 @@ import org.forgerock.i18n.slf4j.LocalizedLogger; import org.forgerock.opendj.config.server.ConfigChangeResult; import org.forgerock.opendj.config.server.ConfigException; import org.forgerock.opendj.ldap.ResultCode; import org.opends.server.admin.server.ConfigurationChangeListener; import org.opends.server.admin.std.server.PluggableBackendCfg; import org.opends.server.api.CompressedSchema; @@ -60,9 +61,11 @@ import org.opends.server.backends.pluggable.spi.ReadableStorage; import org.opends.server.backends.pluggable.spi.Storage; import org.opends.server.backends.pluggable.spi.StorageRuntimeException; import org.opends.server.backends.pluggable.spi.StorageStatus; import org.opends.server.backends.pluggable.spi.WriteOperation; import org.opends.server.backends.pluggable.spi.WriteableStorage; import org.opends.server.core.DirectoryServer; import org.opends.server.core.SearchOperation; import org.opends.server.types.DN; import org.opends.server.types.DirectoryException; import org.opends.server.types.Entry; @@ -70,6 +73,8 @@ import org.opends.server.types.LDIFImportConfig; import org.opends.server.types.LDIFImportResult; import org.opends.server.types.OpenDsException; import org.opends.server.types.Operation; import org.opends.server.types.Privilege; import org.opends.server.util.LDIFException; import org.opends.server.util.LDIFReader; import org.opends.server.util.RuntimeInformation; @@ -690,12 +695,27 @@ } /** * Returns whether this container JE database environment is open, valid and * can be used. * Checks the storage has enough resources for an operation. * * @return {@code true} if valid, or {@code false} otherwise. * @param operation the current operation * @throws DirectoryException if resources are in short supply */ public boolean isValid() { return storage.isValid(); public void checkForEnoughResources(Operation operation) throws DirectoryException { StorageStatus status = storage.getStorageStatus(); if (status.isUnusable() || (status.isLockedDown() && hasBypassLockdownPrivileges(operation))) { throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, status.getReason()); } } private boolean hasBypassLockdownPrivileges(Operation operation) { return operation != null // Read operations are always allowed in lock down mode && !(operation instanceof SearchOperation) && !operation.getClientConnection().hasPrivilege( Privilege.BYPASS_LOCKDOWN, operation); } } opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/spi/Storage.java
@@ -100,13 +100,6 @@ void closeTree(TreeName treeName); /** * Returns whether the storage engine is in a valid state, i.e. whether it can be used for processing. * * @return {@code true} if the storage engine is in a valid state, {@code false} otherwise */ boolean isValid(); /** * Returns a filename filter which selects the files to be included in a backup. * @return a filename filter which selects the files to be included in a backup */ @@ -122,4 +115,11 @@ * @throws StorageRuntimeException if removal fails */ void removeStorageFiles() throws StorageRuntimeException; /** * Returns the current status of the storage. * * @return the current status of the storage */ StorageStatus getStorageStatus(); } opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/spi/StorageStatus.java
New file @@ -0,0 +1,132 @@ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt * or http://forgerock.org/license/CDDLv1.0.html. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at legal-notices/CDDLv1_0.txt. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: * Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * * Copyright 2015 ForgeRock AS */ package org.opends.server.backends.pluggable.spi; import org.forgerock.i18n.LocalizableMessage; /** * Represents the current status of a storage with respect to its resources. */ public final class StorageStatus { /** Internal States. */ private enum Code { /** Storage is working normally. */ WORKING, /** Storage resources start getting scarce. */ LOCKED_DOWN, /** Storage has no resources to execute operations. */ UNUSABLE }; /** Hopefully resources are always in this state. */ private static final StorageStatus WORKING = new StorageStatus(Code.WORKING, null); /** Current status. */ private final Code code; /** Current warning/error message. */ private final LocalizableMessage reason; /** * Returns normal state. * * @return normal state */ public static StorageStatus working() { return WORKING; } /** * Returns state for resources getting scarce. * * @param reason the message to forward * @return state for resources getting scarce */ public static StorageStatus lockedDown(LocalizableMessage reason) { return new StorageStatus(Code.LOCKED_DOWN, reason); } /** * Returns state for no more resources. * * @param reason the message to forward * @return state for no more resources */ public static StorageStatus unusable(LocalizableMessage reason) { return new StorageStatus(Code.UNUSABLE, reason); } private StorageStatus(Code code, LocalizableMessage reason) { this.code = code; this.reason = reason; } /** * Returns true if resources are getting scarce. * * @return true if resources are getting scarce */ public boolean isLockedDown() { return code == Code.LOCKED_DOWN; } /** * Returns true if state is normal. * * @return true if state is normal */ public boolean isWorking() { return code == Code.WORKING; } /** * Returns true if no more resources are available. * * @return true if no more resources are available */ public boolean isUnusable() { return code == Code.UNUSABLE; } /** * Returns the error message for non working states. * * @return the error message for non working states */ public LocalizableMessage getReason() { return reason; } } opendj-server-legacy/src/test/java/org/opends/server/backends/pluggable/persistit/PersistitTestCase.java
@@ -28,7 +28,6 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.testng.Assert.assertTrue; import org.forgerock.opendj.config.server.ConfigException; import org.opends.server.TestCaseUtils; @@ -46,10 +45,17 @@ */ public class PersistitTestCase extends PluggableBackendImplTestCase { /** * Tests the storage API for resource checking. * The tested method has no return value, but an exception, while not systematic, may be thrown, * in which case the test must fail. * * @throws Exception if resources are low. */ @Test public void testPersistitCfg() throws Exception { assertTrue(backend.getRootContainer().isValid()); backend.getRootContainer().checkForEnoughResources(null); } @Override