/*
|
* 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
|
* trunk/opends/resource/legal-notices/OpenDS.LICENSE
|
* or https://OpenDS.dev.java.net/OpenDS.LICENSE.
|
* 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
|
* trunk/opends/resource/legal-notices/OpenDS.LICENSE. 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 2010 Sun Microsystems, Inc.
|
*/
|
|
package org.opends.server.extensions;
|
|
import org.opends.server.admin.std.server.MonitorProviderCfg;
|
import org.opends.server.api.DiskSpaceMonitorHandler;
|
import org.opends.server.api.MonitorProvider;
|
import org.opends.server.config.ConfigException;
|
import org.opends.server.core.DirectoryServer;
|
import org.opends.server.loggers.ErrorLogger;
|
import org.opends.server.loggers.debug.DebugTracer;
|
import org.opends.server.types.*;
|
|
import static org.opends.messages.CoreMessages.
|
ERR_DISK_SPACE_MONITOR_UPDATE_FAILED;
|
import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
|
import static org.opends.server.loggers.debug.DebugLogger.getTracer;
|
|
import java.io.File;
|
import java.util.ArrayList;
|
import java.util.List;
|
import java.util.concurrent.*;
|
|
/**
|
* This class provides an application-wide disk space monitoring service.
|
* It provides the ability for registered handlers to receive notifications
|
* when the free disk space falls below a certain threshold.
|
*
|
* The handler will only be notified once when when the free space
|
* have dropped below any of the thresholds. Once the "full" threshold
|
* have been reached, the handler will not be notified again until the
|
* free space raises above the "low" threshold.
|
*/
|
public class DiskSpaceMonitor extends MonitorProvider<MonitorProviderCfg>
|
implements Runnable
|
{
|
/**
|
* The tracer object for the debug logger.
|
*/
|
private static final DebugTracer TRACER = getTracer();
|
|
private volatile File directory;
|
private volatile long lowThreshold;
|
private volatile long fullThreshold;
|
private final DiskSpaceMonitorHandler handler;
|
private final int interval;
|
private final TimeUnit unit;
|
private final String instanceName;
|
private int lastState = 0;
|
|
/**
|
* Constructs a new DiskSpaceMonitor that will notify the specified
|
* DiskSpaceMonitorHandler when the specified disk
|
* falls below the provided thresholds.
|
*
|
* @param instanceName A unique name for this monitor.
|
* @param directory The directory to monitor.
|
* @param lowThreshold The "low" threshold.
|
* @param fullThreshold The "full" threshold.
|
* @param interval The polling interval for checking free space.
|
* @param unit the time unit of the interval parameter.
|
* @param handler The handler to get notified when the provided thresholds are
|
* reached or <code>null</code> if no notification is needed;
|
*/
|
public DiskSpaceMonitor(String instanceName, File directory,
|
long lowThreshold,
|
long fullThreshold, int interval, TimeUnit unit,
|
DiskSpaceMonitorHandler handler) {
|
this.directory = directory;
|
this.lowThreshold = lowThreshold;
|
this.fullThreshold = fullThreshold;
|
this.interval = interval;
|
this.unit = unit;
|
this.handler = handler;
|
this.instanceName = instanceName+",cn=Disk Space Monitor";
|
}
|
|
/**
|
* Retrieves the directory currently being monitored.
|
*
|
* @return The directory currently being monitored.
|
*/
|
public File getDirectory() {
|
return directory;
|
}
|
|
/**
|
* Sets the directory to monitor.
|
*
|
* @param directory The directory to monitor.
|
*/
|
public void setDirectory(File directory) {
|
this.directory = directory;
|
}
|
|
/**
|
* Retrieves the currently "low" space threshold currently being enforced.
|
*
|
* @return The currently "low" space threshold currently being enforced.
|
*/
|
public long getLowThreshold() {
|
return lowThreshold;
|
}
|
|
/**
|
* Sets the "low" space threshold to enforce.
|
*
|
* @param lowThreshold The "low" space threshold to enforce.
|
*/
|
public void setLowThreshold(long lowThreshold) {
|
this.lowThreshold = lowThreshold;
|
}
|
|
/**
|
* Retrieves the currently full threshold currently being enforced.
|
*
|
* @return The currently full space threshold currently being enforced.
|
*/
|
public long getFullThreshold() {
|
return fullThreshold;
|
}
|
|
/**
|
* Sets the full threshold to enforce.
|
*
|
* @param fullThreshold The full space threshold to enforce.
|
*/
|
public void setFullThreshold(long fullThreshold) {
|
this.fullThreshold = fullThreshold;
|
}
|
|
/**
|
* Retrieves the free space currently on the disk.
|
*
|
* @return The free space currently on the disk.
|
*/
|
public long getFreeSpace() {
|
return directory.getUsableSpace();
|
}
|
|
/**
|
* Indicates if the "full" threshold is reached.
|
*
|
* @return <code>true</code> if the free space is lower than the "full"
|
* threshold or <code>false</code> otherwise.
|
*/
|
public boolean isFullThresholdReached()
|
{
|
return lastState >= 2;
|
}
|
|
/**
|
* Indicates if the "low" threshold is reached.
|
*
|
* @return <code>true</code> if the free space is lower than the "low"
|
* threshold or <code>false</code> otherwise.
|
*/
|
public boolean isLowThresholdReached()
|
{
|
return lastState >= 1;
|
}
|
|
/**
|
* {@inheritDoc}
|
*/
|
@Override
|
public void initializeMonitorProvider(MonitorProviderCfg configuration)
|
throws ConfigException, InitializationException {
|
scheduleUpdate(this, 0, interval, unit);
|
}
|
|
/**
|
* {@inheritDoc}
|
*/
|
@Override
|
public String getMonitorInstanceName() {
|
return instanceName;
|
}
|
|
/**
|
* {@inheritDoc}
|
*/
|
@Override
|
public List<Attribute> getMonitorData() {
|
ArrayList<Attribute> monitorAttrs = new ArrayList<Attribute>();
|
|
AttributeType attrType =
|
DirectoryServer.getDefaultAttributeType("disk-dir",
|
DirectoryServer.getDefaultStringSyntax());
|
monitorAttrs.add(Attributes.create(attrType, directory.getPath()));
|
|
attrType =
|
DirectoryServer.getDefaultAttributeType("disk-free",
|
DirectoryServer.getDefaultIntegerSyntax());
|
monitorAttrs.add(Attributes.create(attrType,
|
String.valueOf(getFreeSpace())));
|
|
attrType =
|
DirectoryServer.getDefaultAttributeType("disk-state",
|
DirectoryServer.getDefaultStringSyntax());
|
switch(lastState)
|
{
|
case 0 : monitorAttrs.add(Attributes.create(attrType, "normal"));
|
break;
|
case 1 : monitorAttrs.add(Attributes.create(attrType, "low"));
|
break;
|
case 2 : monitorAttrs.add(Attributes.create(attrType, "full"));
|
break;
|
}
|
|
|
return monitorAttrs;
|
}
|
|
/**
|
* {@inheritDoc}
|
*/
|
public void run() {
|
try
|
{
|
long lastFreeSpace = directory.getUsableSpace();
|
|
if(debugEnabled())
|
{
|
TRACER.debugInfo("Free space for %s: %d, " +
|
"low threshold: %d, full threshold: %d, state: %d",
|
directory.getPath(), lastFreeSpace, lowThreshold, fullThreshold,
|
lastState);
|
}
|
|
if(lastFreeSpace < fullThreshold)
|
{
|
if(lastState < 2)
|
{
|
if(debugEnabled())
|
{
|
TRACER.debugInfo("State change: %d -> %d", lastState, 2);
|
}
|
|
lastState = 2;
|
if(handler != null)
|
{
|
handler.diskFullThresholdReached(this);
|
}
|
}
|
}
|
else if(lastFreeSpace < lowThreshold)
|
{
|
if(lastState < 1)
|
{
|
if(debugEnabled())
|
{
|
TRACER.debugInfo("State change: %d -> %d", lastState, 1);
|
}
|
lastState = 1;
|
if(handler != null)
|
{
|
handler.diskLowThresholdReached(this);
|
}
|
}
|
}
|
else if(lastState != 0)
|
{
|
if(debugEnabled())
|
{
|
TRACER.debugInfo("State change: %d -> %d", lastState, 0);
|
}
|
lastState = 0;
|
if(handler != null)
|
{
|
handler.diskSpaceRestored(this);
|
}
|
}
|
}
|
catch(Exception e)
|
{
|
ErrorLogger.logError(ERR_DISK_SPACE_MONITOR_UPDATE_FAILED.get(
|
directory.getPath(), e.toString()));
|
|
TRACER.debugCaught(DebugLogLevel.ERROR, e);
|
}
|
}
|
}
|