package com.sleepycat.je.dbi;
import java.util.Iterator;
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.config.EnvironmentParams;
import com.sleepycat.je.tree.BIN;
import com.sleepycat.je.tree.DBIN;
import com.sleepycat.je.tree.DIN;
import com.sleepycat.je.tree.IN;
import de.ovgu.cide.jakutil.*;
/**
* MemoryBudget calculates the available memory for JE and how to apportion it
* between cache and log buffers. It is meant to centralize all memory
* calculations. Objects that ask for memory budgets should get settings from
* this class, rather than using the configuration parameter values directly.
*/
public class MemoryBudget implements EnvConfigObserver {
static {
sinit();
}
private static void sinit(){
new MemoryBudget_sinit().execute();
}
public final static long MIN_MAX_MEMORY_SIZE=96 * 1024;
public final static String MIN_MAX_MEMORY_SIZE_STRING=Long.toString(MIN_MAX_MEMORY_SIZE);
private final static long N_64MB=(1 << 26);
private long maxMemory;
private long logBufferBudget;
private EnvironmentImpl envImpl;
MemoryBudget( EnvironmentImpl envImpl, DbConfigManager configManager) throws DatabaseException {
this.envImpl=envImpl;
envImpl.addConfigObserver(this);
reset(configManager);
this.hook351(configManager);
}
/**
* Respond to config updates.
*/
public void envConfigUpdate( DbConfigManager configManager) throws DatabaseException {
long oldLogBufferBudget=logBufferBudget;
reset(configManager);
if (oldLogBufferBudget != logBufferBudget) {
envImpl.getLogManager().resetPool(configManager);
}
}
/**
* Initialize at construction time and when the cache is resized.
*/
private void reset( DbConfigManager configManager) throws DatabaseException {
new MemoryBudget_reset(this,configManager).execute();
}
/**
* Returns Runtime.maxMemory(), accounting for a MacOS bug. May return
* Long.MAX_VALUE if there is no inherent limit. Used by unit tests as well
* as by this class.
*/
public static long getRuntimeMaxMemory(){
if ("Mac OS X".equals(System.getProperty("os.name"))) {
String jvmVersion=System.getProperty("java.version");
if (jvmVersion != null && jvmVersion.startsWith("1.4.2")) {
return Long.MAX_VALUE;
}
}
return Runtime.getRuntime().maxMemory();
}
public long getLogBufferBudget(){
return logBufferBudget;
}
public long getMaxMemory(){
return maxMemory;
}
@MethodObject static class MemoryBudget_sinit {
void execute(){
this.hook348();
}
protected boolean is64;
protected boolean isJVM14;
protected String overrideArch;
protected String arch;
protected RuntimeException RE;
protected void hook348(){
}
}
@MethodObject static class MemoryBudget_reset {
MemoryBudget_reset( MemoryBudget _this, DbConfigManager configManager){
this._this=_this;
this.configManager=configManager;
}
void execute() throws DatabaseException {
newMaxMemory=configManager.getLong(EnvironmentParams.MAX_MEMORY);
jvmMemory=_this.getRuntimeMaxMemory();
if (newMaxMemory != 0) {
if (jvmMemory < newMaxMemory) {
throw new IllegalArgumentException(EnvironmentParams.MAX_MEMORY.getName() + " has a value of " + newMaxMemory+ " but the JVM is only configured for "+ jvmMemory+ ". Consider using je.maxMemoryPercent.");
}
if (newMaxMemory < _this.MIN_MAX_MEMORY_SIZE) {
throw new IllegalArgumentException(EnvironmentParams.MAX_MEMORY.getName() + " is " + newMaxMemory+ " which is less than the minimum: "+ _this.MIN_MAX_MEMORY_SIZE);
}
}
else {
if (jvmMemory == Long.MAX_VALUE) {
jvmMemory=_this.N_64MB;
}
maxMemoryPercent=configManager.getInt(EnvironmentParams.MAX_MEMORY_PERCENT);
newMaxMemory=(maxMemoryPercent * jvmMemory) / 100;
}
newLogBufferBudget=configManager.getLong(EnvironmentParams.LOG_MEM_SIZE);
if (newLogBufferBudget == 0) {
newLogBufferBudget=newMaxMemory >> 4;
}
else if (newLogBufferBudget > newMaxMemory / 2) {
newLogBufferBudget=newMaxMemory / 2;
}
numBuffers=configManager.getInt(EnvironmentParams.NUM_LOG_BUFFERS);
startingBufferSize=newLogBufferBudget / numBuffers;
logBufferSize=configManager.getInt(EnvironmentParams.LOG_BUFFER_MAX_SIZE);
if (startingBufferSize > logBufferSize) {
startingBufferSize=logBufferSize;
newLogBufferBudget=numBuffers * startingBufferSize;
}
else if (startingBufferSize < EnvironmentParams.MIN_LOG_BUFFER_SIZE) {
startingBufferSize=EnvironmentParams.MIN_LOG_BUFFER_SIZE;
newLogBufferBudget=numBuffers * startingBufferSize;
}
this.hook350();
newTrackerBudget=(newMaxMemory * _this.envImpl.getConfigManager().getInt(EnvironmentParams.CLEANER_DETAIL_MAX_MEMORY_PERCENTAGE)) / 100;
_this.maxMemory=newMaxMemory;
this.hook349();
_this.logBufferBudget=newLogBufferBudget;
}
protected MemoryBudget _this;
protected DbConfigManager configManager;
protected long newMaxMemory;
protected long jvmMemory;
protected int maxMemoryPercent;
protected long newLogBufferBudget;
protected int numBuffers;
protected long startingBufferSize;
protected int logBufferSize;
protected long newCriticalThreshold;
protected long newTrackerBudget;
protected void hook349() throws DatabaseException {
}
protected void hook350() throws DatabaseException {
}
}
protected void hook351( DbConfigManager configManager) throws DatabaseException {
}
}