in environment/src/main/java/jetbrains/exodus/env/EnvironmentImpl.java [517:592]
public void close() {
// if this is already closed do nothing
synchronized (commitLock) {
if (!isOpen()) {
return;
}
}
final MetaServer metaServer = ec.getMetaServer();
if (metaServer != null) {
metaServer.stop(this);
}
backupController.unregister();
if (configMBean != null) {
configMBean.unregister();
}
if (statisticsMBean != null) {
statisticsMBean.unregister();
}
if (profilerMBean != null) {
profilerMBean.unregister();
}
runAllTransactionSafeTasks();
// in order to avoid deadlock, do not finish gc inside lock
// it is safe to invoke gc.finish() several times
gc.finish();
final float logCacheHitRate;
final float storeGetCacheHitRate;
synchronized (commitLock) {
// concurrent close() detected
if (throwableOnClose != null) {
throw new EnvironmentClosedException(throwableOnClose); // add combined stack trace information
}
final boolean closeForcedly = ec.getEnvCloseForcedly();
checkInactive(closeForcedly);
try {
if (!closeForcedly && !isReadOnly() && ec.isGcEnabled()) {
executeInTransaction(txn -> gc.getUtilizationProfile().forceSave(txn));
}
ec.removeChangedSettingsListener(envSettingsListener);
logCacheHitRate = log.getCacheHitRate();
if (!isReadOnly()) {
metaReadLock.lock();
try {
log.updateStartUpDbRoot(metaTree.rootAddress());
} finally {
metaReadLock.unlock();
}
}
if (syncTask != null) {
syncTask.cancel(false);
}
log.close();
} finally {
log.release();
}
if (storeGetCache == null) {
storeGetCacheHitRate = 0;
} else {
storeGetCacheHitRate = storeGetCache.hitRate();
storeGetCache.close();
}
if (txnProfiler != null) {
txnProfiler.dump();
}
throwableOnClose = new EnvironmentClosedException();
throwableOnCommit = throwableOnClose;
}
loggerDebug("Store get cache hit rate: " + ObjectCacheBase.formatHitRate(storeGetCacheHitRate));
loggerDebug("Exodus log cache hit rate: " + ObjectCacheBase.formatHitRate(logCacheHitRate));
}