From 8b806159078ce1308b27e676c0e8a6340f05e6e0 Mon Sep 17 00:00:00 2001
From: Fabio Pistolesi <fabio.pistolesi@forgerock.com>
Date: Mon, 02 Mar 2015 10:59:04 +0000
Subject: [PATCH] OPENDJ-1826 CR-6180 BackendImpl current DiskSpaceMonitoring should be done entirely at the Storage layer
---
opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/RootContainer.java | 30 ++
opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/BackendImpl.java | 238 +++++------------------
opendj-server-legacy/src/test/java/org/opends/server/backends/pluggable/persistit/PersistitTestCase.java | 10
opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/spi/Storage.java | 14
opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/spi/StorageStatus.java | 132 +++++++++++++
opendj-server-legacy/src/main/java/org/opends/server/backends/persistit/PersistItStorage.java | 104 +++++++++
opendj-server-legacy/src/main/java/org/opends/server/backends/persistit/PitBackend.java | 28 --
7 files changed, 324 insertions(+), 232 deletions(-)
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/persistit/PersistItStorage.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/persistit/PersistItStorage.java
index 3a3a43b..e8be95f 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/persistit/PersistItStorage.java
+++ b/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;
+ }
}
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/persistit/PitBackend.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/persistit/PitBackend.java
index 9c84a9c..128456c 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/persistit/PitBackend.java
+++ b/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;
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/BackendImpl.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/BackendImpl.java
index d2bc610..5dfb6f4 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/BackendImpl.java
+++ b/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());
- }
- }
}
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/RootContainer.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/RootContainer.java
index 7bee231..716ff46 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/RootContainer.java
+++ b/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);
}
}
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/spi/Storage.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/spi/Storage.java
index 004b604..084fe89 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/spi/Storage.java
+++ b/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();
}
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/spi/StorageStatus.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/spi/StorageStatus.java
new file mode 100644
index 0000000..dd55dd6
--- /dev/null
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/spi/StorageStatus.java
@@ -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;
+ }
+}
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/backends/pluggable/persistit/PersistitTestCase.java b/opendj-server-legacy/src/test/java/org/opends/server/backends/pluggable/persistit/PersistitTestCase.java
index e087d5c..8f5967a 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/backends/pluggable/persistit/PersistitTestCase.java
+++ b/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
--
Gitblit v1.10.0