[AMQ-6441] add option to specify the hard limits on a usage such that spurious values from the file system can be overridden. this closes #202 thanks William Crowell for the patch with test

This commit is contained in:
gtully 2016-12-07 18:09:34 +00:00
parent 41bec0d658
commit 8a28c06555
6 changed files with 60 additions and 35 deletions

View File

@ -111,9 +111,9 @@ import org.apache.activemq.thread.TaskRunnerFactory;
import org.apache.activemq.transport.TransportFactorySupport;
import org.apache.activemq.transport.TransportServer;
import org.apache.activemq.transport.vm.VMTransportFactory;
import org.apache.activemq.usage.PercentLimitUsage;
import org.apache.activemq.usage.StoreUsage;
import org.apache.activemq.usage.SystemUsage;
import org.apache.activemq.usage.Usage;
import org.apache.activemq.util.BrokerSupport;
import org.apache.activemq.util.DefaultIOExceptionHandler;
import org.apache.activemq.util.IOExceptionHandler;
@ -2048,18 +2048,19 @@ public class BrokerService implements Service {
}
}
protected void checkUsageLimit(File dir, Usage<?> storeUsage, int percentLimit) throws ConfigurationException {
protected void checkUsageLimit(File dir, PercentLimitUsage<?> storeUsage, int percentLimit) throws ConfigurationException {
if (dir != null) {
dir = StoreUtil.findParentDirectory(dir);
String storeName = storeUsage instanceof StoreUsage ? "Store" : "Temporary Store";
long storeLimit = storeUsage.getLimit();
long storeCurrent = storeUsage.getUsage();
long totalSpace = dir.getTotalSpace();
if (totalSpace < 0) {
totalSpace = Long.MAX_VALUE;
LOG.info("Total space was negative. Setting to " + totalSpace);
long totalSpace = storeUsage.getTotal() > 0 ? storeUsage.getTotal() : dir.getTotalSpace();
long totalUsableSpace = (storeUsage.getTotal() > 0 ? storeUsage.getTotal() : dir.getUsableSpace()) + storeCurrent;
if (totalUsableSpace < 0 || totalSpace < 0) {
final String message = "File system space reported by: " + dir + " was negative, possibly a huge file system, set a sane usage.total to provide some guidance";
LOG.error(message);
throw new ConfigurationException(message);
}
long totalUsableSpace = dir.getUsableSpace() + storeCurrent;
//compute byte value of the percent limit
long bytePercentLimit = totalSpace * percentLimit / 100;
int oneMeg = 1024 * 1024;
@ -2069,6 +2070,7 @@ public class BrokerService implements Service {
//Changes in partition size (total space) as well as changes in usable space should
//be detected here
if (diskUsageCheckRegrowThreshold > -1 && percentLimit > 0
&& storeUsage.getTotal() == 0
&& storeLimit < bytePercentLimit && storeLimit < totalUsableSpace){
// set the limit to be bytePercentLimit or usableSpace if

View File

@ -17,9 +17,14 @@
package org.apache.activemq.usage;
import org.apache.activemq.util.StoreUtil;
import java.io.File;
public abstract class PercentLimitUsage <T extends Usage> extends Usage<T> {
protected int percentLimit = 0;
protected long total = 0;
/**
* @param parent
@ -49,5 +54,27 @@ public abstract class PercentLimitUsage <T extends Usage> extends Usage<T> {
}
}
public void setTotal(long max) {
this.total = max;
}
public long getTotal() {
return total;
}
protected void percentLimitFromFile(File directory) {
if (percentLimit > 0) {
if (total > 0) {
this.setLimit(total * percentLimit / 100);
} else if (directory != null) {
File dir = StoreUtil.findParentDirectory(directory);
if (dir != null) {
this.setLimit(dir.getTotalSpace() * percentLimit / 100);
}
}
}
}
protected abstract void updateLimitBasedOnPercent();
}

View File

@ -16,10 +16,7 @@
*/
package org.apache.activemq.usage;
import java.io.File;
import org.apache.activemq.store.PersistenceAdapter;
import org.apache.activemq.util.StoreUtil;
/**
* Used to keep track of how much of something is being used so that a
@ -96,14 +93,7 @@ public class StoreUsage extends PercentLimitUsage<StoreUsage> {
protected void updateLimitBasedOnPercent() {
usageLock.writeLock().lock();
try {
if (percentLimit > 0 && store != null) {
File dir = StoreUtil.findParentDirectory(store.getDirectory());
if (dir != null) {
this.setLimit(dir.getTotalSpace() * percentLimit / 100);
}
}
percentLimitFromFile(store != null ? store.getDirectory() : null);
} finally {
usageLock.writeLock().unlock();
}

View File

@ -17,10 +17,7 @@
package org.apache.activemq.usage;
import java.io.File;
import org.apache.activemq.store.PListStore;
import org.apache.activemq.util.StoreUtil;
/**
* Used to keep track of how much of something is being used so that a
@ -89,15 +86,10 @@ public class TempUsage extends PercentLimitUsage<TempUsage> {
protected void updateLimitBasedOnPercent() {
usageLock.writeLock().lock();
try {
if (percentLimit > 0 && store != null) {
File dir = StoreUtil.findParentDirectory(store.getDirectory());
if (dir != null) {
this.setLimit(dir.getTotalSpace() * percentLimit / 100);
}
}
percentLimitFromFile(store != null ? store.getDirectory() : null);
} finally {
usageLock.writeLock().unlock();
}
}
}

View File

@ -103,20 +103,29 @@ public class BrokerServiceTest extends TestCase {
PersistenceAdapter persistenceAdapter = service.createPersistenceAdapter();
persistenceAdapter.setDirectory(dataDirectory);
service.setPersistenceAdapter(persistenceAdapter);
service.setUseJmx(false);
mockStatic(StoreUtil.class);
// Return a simulated handle to a very large file system that will return a negative totalSpace.
when(StoreUtil.findParentDirectory(dataDirectory)).thenReturn(new LargeFile(dataDirectory.getParentFile(), "KahaDB"));
when(StoreUtil.findParentDirectory(tmpDataDirectory)).thenReturn(tmpDataDirectory);
when(StoreUtil.findParentDirectory(tmpDataDirectory)).thenReturn(tmpDataDirectory.getParentFile());
service.setPersistent(false);
service.setUseJmx(false);
TransportConnector connector = service.addConnector("tcp://localhost:0");
service.start();
try {
service.start();
fail("Expect error on negative totalspace");
} catch (Exception expected) {
// verify message
assertTrue(expected.getLocalizedMessage().contains("negative"));
}
finally {
service.stop();
}
service.removeConnector(connector);
connector.stop();
// configure a 2x value for the fs limit so it can start
service.getSystemUsage().getStoreUsage().setTotal( service.getSystemUsage().getStoreUsage().getLimit() * 2);
service.start(true);
service.stop();
verifyStatic();

View File

@ -22,4 +22,9 @@ public class LargeFile extends File {
public long getTotalSpace() {
return Long.MAX_VALUE + 4193L;
}
@Override
public long getUsableSpace() {
return getTotalSpace() - 1024L;
}
}