| | |
| | | private Environment env; |
| | | private EnvironmentConfig envConfig; |
| | | private MemoryQuota memQuota; |
| | | /** |
| | | * The cache size of the configuration this storage opened with, in bytes - what the memory quota |
| | | * was asked for - and of it, what the quota granted, which is what {@link #close()} gives back. |
| | | * Both are zero while the storage is closed. Neither is read from {@link #config} again: a |
| | | * configuration change replaces that while the environment and the reservation stay as the open |
| | | * made them, so a release computed from it would give back a size that was never taken. For a |
| | | * cache sized by db-cache-percent this is the quota's count, a percent of its reservable pool, and |
| | | * not the cache JE runs: JE takes that percent of the maximum heap. |
| | | */ |
| | | private long configuredCacheSize; |
| | | private long reservedCacheSize; |
| | | private JEMonitor monitor; |
| | | private DiskSpaceMonitor diskMonitor; |
| | | private StorageStatus storageStatus = StorageStatus.working(); |
| | |
| | | |
| | | diskMonitor = serverContext.getDiskSpaceMonitor(); |
| | | memQuota = serverContext.getMemoryQuota(); |
| | | if (config.getDBCacheSize() > 0) |
| | | { |
| | | memQuota.acquireMemory(config.getDBCacheSize()); |
| | | } |
| | | else |
| | | { |
| | | memQuota.acquireMemory(memQuota.memPercentToBytes(config.getDBCachePercent())); |
| | | } |
| | | configuredCacheSize = computeSize(config); |
| | | // A reservation the quota refuses - its budget spent by the other backends, which an open at |
| | | // startup is not checked against - is nothing to give back: the open goes ahead without it. |
| | | reservedCacheSize = memQuota.acquireMemory(configuredCacheSize) ? configuredCacheSize : 0; |
| | | } |
| | | |
| | | private DatabaseConfig dbConfig() |
| | |
| | | // another backend be admitted while this one's cache is still resident. |
| | | if (memQuota != null) |
| | | { |
| | | if (config.getDBCacheSize() > 0) |
| | | { |
| | | memQuota.releaseMemory(config.getDBCacheSize()); |
| | | } |
| | | else |
| | | { |
| | | memQuota.releaseMemory(memQuota.memPercentToBytes(config.getDBCachePercent())); |
| | | } |
| | | // What the open reserved, not what the configuration says by now: a cache size changed |
| | | // while the storage was open is applied by the next open, which reserves it then. |
| | | memQuota.releaseMemory(reservedCacheSize); |
| | | reservedCacheSize = 0; |
| | | configuredCacheSize = 0; |
| | | // Released once: what an open takes, the next open takes again, and a close which follows |
| | | // a close - BackendImpl.importLDIF closes the storage of its root container however the |
| | | // import ended, on top of the close the import itself made - releases nothing more. |
| | |
| | | public boolean isConfigurationChangeAcceptable(JEBackendCfg newCfg, |
| | | List<LocalizableMessage> unacceptableReasons) |
| | | { |
| | | long newSize = computeSize(newCfg); |
| | | long oldSize = computeSize(config); |
| | | return (newSize <= oldSize || memQuota.isMemoryAvailable(newSize - oldSize)) |
| | | // A size which does not grow past the one configured asks the quota for nothing, as before: every |
| | | // change of the backend entry comes here, the disable of an online import included, and after an |
| | | // open the quota refused this storage holds nothing to measure such a change against. A growth is |
| | | // measured against what this storage holds, which is what the next open adds to - not against |
| | | // config, which a change admitted but not yet applied has already moved to the new size. |
| | | final long newSize = computeSize(newCfg); |
| | | final MemoryQuota quota = serverContext.getMemoryQuota(); |
| | | return (newSize <= Math.max(reservedCacheSize, computeSize(config)) |
| | | || quota.isMemoryAvailable(newSize - reservedCacheSize)) |
| | | && checkConfigurationDirectories(newCfg, unacceptableReasons); |
| | | } |
| | | |
| | | private long computeSize(JEBackendCfg cfg) |
| | | { |
| | | return cfg.getDBCacheSize() > 0 ? cfg.getDBCacheSize() : memQuota.memPercentToBytes(cfg.getDBCachePercent()); |
| | | return cfg.getDBCacheSize() > 0 |
| | | ? cfg.getDBCacheSize() |
| | | : serverContext.getMemoryQuota().memPercentToBytes(cfg.getDBCachePercent()); |
| | | } |
| | | |
| | | /** |
| | |
| | | return ccr; |
| | | } |
| | | } |
| | | final long newCacheSize = computeSize(cfg); |
| | | if (env != null && newCacheSize != configuredCacheSize) |
| | | { |
| | | // The cache is sized when the environment opens and this storage never resizes it: the next |
| | | // open of the backend builds it to the new size and reserves that, and until then the |
| | | // reservation stays with the cache it was made for. |
| | | ccr.setAdminActionRequired(true); |
| | | ccr.addMessage( |
| | | NOTE_CONFIG_DB_CACHE_REQUIRES_RESTART.get(cfg.getBackendId(), configuredCacheSize, newCacheSize)); |
| | | } |
| | | registerMonitoredDirectory(cfg); |
| | | config = cfg; |
| | | } |