Fix sqlite database files not being unlocked

This commit is contained in:
James Seibel
2024-04-09 21:29:12 -05:00
parent 77fffb1a9b
commit e560ddf3dc
10 changed files with 52 additions and 52 deletions
@@ -81,7 +81,7 @@ public class FullDataSourceProviderV2
* vs gracefully shutting down the thread ourselves.
*/
protected final AtomicBoolean migrationThreadRunning = new AtomicBoolean(true);
protected final FullDataSourceProviderV1 legacyFileHandler;
protected final FullDataSourceProviderV1<IDhLevel> legacyFileHandler;
/**
* Tracks which positions are currently being updated
@@ -106,7 +106,7 @@ public class FullDataSourceProviderV2
public FullDataSourceProviderV2(IDhLevel level, AbstractSaveStructure saveStructure, @Nullable File saveDirOverride)
{
super(level, saveStructure, saveDirOverride);
this.legacyFileHandler = new FullDataSourceProviderV1(level, saveStructure, saveDirOverride);
this.legacyFileHandler = new FullDataSourceProviderV1<>(level, saveStructure, saveDirOverride);
DebugRenderer.register(this, Config.Client.Advanced.Debugging.DebugWireframe.showFullDataUpdateStatus);
@@ -492,6 +492,8 @@ public class FullDataSourceProviderV2
super.close();
this.updateQueueProcessor.shutdownNow();
this.legacyFileHandler.close();
this.migrationThreadRunning.set(false);
this.migrationThreadPool.shutdown();
}
@@ -41,6 +41,7 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrap
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
import org.apache.logging.log4j.Logger;
import javax.annotation.WillNotClose;
import java.io.Closeable;
import java.util.ArrayList;
import java.util.concurrent.CompletableFuture;
@@ -54,6 +55,7 @@ public class ClientLevelModule implements Closeable, AbstractNewDataSourceHandle
private final IDhClientLevel clientLevel;
@WillNotClose
public final FullDataSourceProviderV2 fullDataSourceProvider;
public final AtomicReference<ClientRenderState> ClientRenderStateRef = new AtomicReference<>();
@@ -111,7 +113,7 @@ public class ClientLevelModule implements Closeable, AbstractNewDataSourceHandle
}
clientRenderState.close();
clientRenderState = new ClientRenderState(this.clientLevel, clientLevelWrapper, this.clientLevel.getFullDataProvider(), this.clientLevel.getSaveStructure());
clientRenderState = new ClientRenderState(this.clientLevel, clientLevelWrapper, this.clientLevel.getFullDataProvider());
if (!this.ClientRenderStateRef.compareAndSet(null, clientRenderState))
{
//FIXME: How to handle this?
@@ -144,7 +146,7 @@ public class ClientLevelModule implements Closeable, AbstractNewDataSourceHandle
public boolean startRenderer(IClientLevelWrapper clientLevelWrapper)
{
// TODO why are we passing in a level wrapper? Our client level is already defined.
ClientRenderState ClientRenderState = new ClientRenderState(this.clientLevel, clientLevelWrapper, this.clientLevel.getFullDataProvider(), this.clientLevel.getSaveStructure());
ClientRenderState ClientRenderState = new ClientRenderState(this.clientLevel, clientLevelWrapper, this.clientLevel.getFullDataProvider());
if (!this.ClientRenderStateRef.compareAndSet(null, ClientRenderState))
{
LOGGER.warn("Failed to start renderer due to concurrency");
@@ -324,9 +326,7 @@ public class ClientLevelModule implements Closeable, AbstractNewDataSourceHandle
public final LodQuadTree quadtree;
public final LodRenderer renderer;
public ClientRenderState(
IDhClientLevel dhClientLevel, IClientLevelWrapper clientLevelWrapper, FullDataSourceProviderV2 fullDataSourceProvider,
AbstractSaveStructure saveStructure)
public ClientRenderState(IDhClientLevel dhClientLevel, IClientLevelWrapper clientLevelWrapper, FullDataSourceProviderV2 fullDataSourceProvider)
{
this.clientLevelWrapper = clientLevelWrapper;
@@ -103,47 +103,37 @@ public class DhClientLevel extends AbstractDhLevel implements IDhClientLevel
//================//
@Override
public int computeBaseColor(DhBlockPos pos, IBiomeWrapper biome, IBlockStateWrapper block) { return levelWrapper.computeBaseColor(pos, biome, block); }
public int computeBaseColor(DhBlockPos pos, IBiomeWrapper biome, IBlockStateWrapper block) { return this.levelWrapper.computeBaseColor(pos, biome, block); }
@Override
public IClientLevelWrapper getClientLevelWrapper() { return levelWrapper; }
public IClientLevelWrapper getClientLevelWrapper() { return this.levelWrapper; }
@Override
public void clearRenderCache()
{
clientside.clearRenderCache();
}
public void clearRenderCache() { this.clientside.clearRenderCache(); }
@Override
public ILevelWrapper getLevelWrapper() { return levelWrapper; }
public ILevelWrapper getLevelWrapper() { return this.levelWrapper; }
@Override
public CompletableFuture<Void> updateDataSourcesAsync(FullDataSourceV2 data) { return this.clientside.updateDataSourcesAsync(data); }
@Override
public int getMinY() { return levelWrapper.getMinHeight(); }
public int getMinY() { return this.levelWrapper.getMinHeight(); }
@Override
public void close()
{
clientside.close();
this.clientside.close();
super.close();
dataFileHandler.close();
this.dataFileHandler.close();
LOGGER.info("Closed " + DhClientLevel.class.getSimpleName() + " for " + levelWrapper);
}
//=======================//
// misc helper functions //
//=======================//
@Override
public FullDataSourceProviderV2 getFullDataProvider() { return this.dataFileHandler; }
@Override
public AbstractSaveStructure getSaveStructure()
{
return saveStructure;
}
public AbstractSaveStructure getSaveStructure() { return this.saveStructure; }
@Override
public boolean hasSkyLight() { return this.levelWrapper.hasSkyLight(); }
@@ -23,14 +23,12 @@ import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhAp
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.file.fullDatafile.FullDataSourceProviderV2;
import com.seibel.distanthorizons.core.render.LodRenderSection;
import com.seibel.distanthorizons.core.render.renderer.DebugRenderer;
import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.pos.DhBlockPos;
import com.seibel.distanthorizons.core.pos.DhBlockPos2D;
import com.seibel.distanthorizons.core.pos.DhSectionPos;
import com.seibel.distanthorizons.core.util.objects.quadTree.QuadNode;
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
@@ -41,7 +39,6 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapp
import org.apache.logging.log4j.Logger;
import java.awt.*;
import java.util.Iterator;
import java.util.concurrent.CompletableFuture;
/** The level used on a singleplayer world */
@@ -103,7 +100,7 @@ public class DhClientServerLevel extends AbstractDhLevel implements IDhClientLev
// start world gen
// create a new queue
this.serverside.worldGenModule.startWorldGen(this.serverside.dataFileHandler, new ServerLevelModule.WorldGenState(this));
this.serverside.worldGenModule.startWorldGen(this.serverside.fullDataFileHandler, new ServerLevelModule.WorldGenState(this));
// TODO I think this used to queue the world gen
// is it still needed?
@@ -119,7 +116,7 @@ public class DhClientServerLevel extends AbstractDhLevel implements IDhClientLev
else if (!shouldDoWorldGen && isWorldGenRunning)
{
// stop world gen
this.serverside.worldGenModule.stopWorldGen(this.serverside.dataFileHandler);
this.serverside.worldGenModule.stopWorldGen(this.serverside.fullDataFileHandler);
}
if (isWorldGenRunning)
@@ -169,7 +166,7 @@ public class DhClientServerLevel extends AbstractDhLevel implements IDhClientLev
public ILevelWrapper getLevelWrapper() { return getServerLevelWrapper(); }
@Override
public FullDataSourceProviderV2 getFullDataProvider() { return this.serverside.dataFileHandler; }
public FullDataSourceProviderV2 getFullDataProvider() { return this.serverside.fullDataFileHandler; }
@Override
public AbstractSaveStructure getSaveStructure()
@@ -72,12 +72,12 @@ public class DhServerLevel extends AbstractDhLevel implements IDhServerLevel
if (shouldDoWorldGen && !isWorldGenRunning)
{
// start world gen
serverside.worldGenModule.startWorldGen(serverside.dataFileHandler, new ServerLevelModule.WorldGenState(this));
serverside.worldGenModule.startWorldGen(serverside.fullDataFileHandler, new ServerLevelModule.WorldGenState(this));
}
else if (!shouldDoWorldGen && isWorldGenRunning)
{
// stop world gen
serverside.worldGenModule.stopWorldGen(serverside.dataFileHandler);
serverside.worldGenModule.stopWorldGen(serverside.fullDataFileHandler);
}
if (serverside.worldGenModule.isWorldGenRunning())
@@ -93,7 +93,7 @@ public class DhServerLevel extends AbstractDhLevel implements IDhServerLevel
public ILevelWrapper getLevelWrapper() { return getServerLevelWrapper(); }
@Override
public FullDataSourceProviderV2 getFullDataProvider() { return this.serverside.dataFileHandler; }
public FullDataSourceProviderV2 getFullDataProvider() { return this.serverside.fullDataFileHandler; }
@Override
public AbstractSaveStructure getSaveStructure()
@@ -30,13 +30,13 @@ import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.coreapi.DependencyInjection.WorldGeneratorInjector;
import org.apache.logging.log4j.Logger;
public class ServerLevelModule
public class ServerLevelModule implements AutoCloseable
{
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
public final IDhServerLevel parentServerLevel;
public final AbstractSaveStructure saveStructure;
public final GeneratedFullDataSourceProvider dataFileHandler;
public final GeneratedFullDataSourceProvider fullDataFileHandler;
public final AppliedConfigState<Boolean> worldGeneratorEnabledConfig;
public final WorldGenModule worldGenModule;
@@ -47,18 +47,19 @@ public class ServerLevelModule
{
this.parentServerLevel = parentServerLevel;
this.saveStructure = saveStructure;
this.dataFileHandler = new GeneratedFullDataSourceProvider(parentServerLevel, saveStructure);
this.fullDataFileHandler = new GeneratedFullDataSourceProvider(parentServerLevel, saveStructure);
this.worldGeneratorEnabledConfig = new AppliedConfigState<>(Config.Client.Advanced.WorldGenerator.enableDistantGeneration);
this.worldGenModule = new WorldGenModule(this.dataFileHandler, this.parentServerLevel);
this.worldGenModule = new WorldGenModule(this.parentServerLevel);
}
@Override
public void close()
{
// shutdown the world-gen
this.worldGenModule.close();
this.dataFileHandler.close();
this.fullDataFileHandler.close();
}
@@ -34,7 +34,6 @@ public class WorldGenModule implements Closeable
{
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
private final GeneratedFullDataSourceProvider dataFileHandler;
private final GeneratedFullDataSourceProvider.IOnWorldGenCompleteListener onWorldGenCompleteListener;
private final AtomicReference<AbstractWorldGenState> worldGenStateRef = new AtomicReference<>();
@@ -42,9 +41,8 @@ public class WorldGenModule implements Closeable
public WorldGenModule(GeneratedFullDataSourceProvider dataFileHandler, GeneratedFullDataSourceProvider.IOnWorldGenCompleteListener onWorldGenCompleteListener)
public WorldGenModule(GeneratedFullDataSourceProvider.IOnWorldGenCompleteListener onWorldGenCompleteListener)
{
this.dataFileHandler = dataFileHandler;
this.onWorldGenCompleteListener = onWorldGenCompleteListener;
this.worldGenF3Message = new F3Screen.DynamicMessage(() ->
{
@@ -138,7 +136,6 @@ public class WorldGenModule implements Closeable
}
}
this.dataFileHandler.close();
this.worldGenF3Message.close();
}
@@ -37,6 +37,7 @@ import com.seibel.distanthorizons.coreapi.util.MathUtil;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.NotNull;
import javax.annotation.WillNotClose;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.concurrent.ConcurrentLinkedQueue;
@@ -59,6 +60,7 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements AutoClose
public final int blockRenderDistanceDiameter;
@WillNotClose
private final FullDataSourceProviderV2 fullDataSourceProvider;
/**
@@ -508,7 +510,7 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements AutoClose
break;
}
renderSection.tryQueuingMissingLodRetrieval(this.fullDataSourceProvider);
renderSection.tryQueuingMissingLodRetrieval();
}
// calculate an estimate for the max number of tasks for the queue
@@ -37,6 +37,7 @@ import com.seibel.distanthorizons.core.util.TimerUtil;
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
import org.apache.logging.log4j.Logger;
import javax.annotation.WillNotClose;
import java.awt.*;
import java.util.*;
import java.util.concurrent.CompletableFuture;
@@ -68,6 +69,7 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable
public final DhSectionPos pos;
private final IDhClientLevel level;
@WillNotClose
private final FullDataSourceProviderV2 fullDataSourceProvider;
@@ -279,14 +281,14 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable
public boolean missingPositionsCalculated() { return this.missingPositionsCalculated; }
public int ungeneratedPositionCount() { return (this.missingGenerationPos != null) ? this.missingGenerationPos.size() : 0; }
public void tryQueuingMissingLodRetrieval(FullDataSourceProviderV2 fullDataSourceProvider)
public void tryQueuingMissingLodRetrieval()
{
if (fullDataSourceProvider.canRetrieveMissingDataSources() && fullDataSourceProvider.canQueueRetrieval())
if (this.fullDataSourceProvider.canRetrieveMissingDataSources() && this.fullDataSourceProvider.canQueueRetrieval())
{
// calculate the missing positions if not already done
if (!this.missingPositionsCalculated)
{
this.missingGenerationPos = fullDataSourceProvider.getPositionsToRetrieve(this.pos);
this.missingGenerationPos = this.fullDataSourceProvider.getPositionsToRetrieve(this.pos);
if (this.missingGenerationPos != null)
{
this.missingPositionsCalculated = true;
@@ -299,14 +301,14 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable
// queue from last to first to prevent shifting the array unnecessarily
for (int i = this.missingGenerationPos.size() - 1; i >= 0; i--)
{
if (!fullDataSourceProvider.canQueueRetrieval())
if (!this.fullDataSourceProvider.canQueueRetrieval())
{
// the data source provider isn't accepting any more jobs
break;
}
DhSectionPos pos = this.missingGenerationPos.remove(i);
boolean positionQueued = fullDataSourceProvider.queuePositionForRetrieval(pos);
boolean positionQueued = this.fullDataSourceProvider.queuePositionForRetrieval(pos);
if (!positionQueued)
{
// shouldn't normally happen, but just in case
@@ -37,7 +37,7 @@ import java.util.concurrent.locks.ReentrantLock;
*
* @param <TDTO> DTO stands for "Data Transfer Object"
*/
public abstract class AbstractDhRepo<TKey, TDTO extends IBaseDTO<TKey>>
public abstract class AbstractDhRepo<TKey, TDTO extends IBaseDTO<TKey>> implements AutoCloseable
{
public static final int TIMEOUT_SECONDS = 30;
@@ -379,6 +379,7 @@ public abstract class AbstractDhRepo<TKey, TDTO extends IBaseDTO<TKey>>
}
}
@Override
public void close()
{
try
@@ -391,9 +392,17 @@ public abstract class AbstractDhRepo<TKey, TDTO extends IBaseDTO<TKey>>
{
if(this.connection != null)
{
LOGGER.info("Closing database connection ["+this.connectionString+"]");
CONNECTIONS_BY_CONNECTION_STRING.remove(this.connectionString);
this.connection.close();
if (!this.connection.isClosed())
{
LOGGER.info("Closing database connection: [" + this.connectionString + "]");
this.connection.close();
}
else
{
LOGGER.warn("Attempting to close already closed database connection: [" + this.connectionString + "]");
}
}
ACTIVE_CONNECTION_STRINGS_BY_REPO.remove(this);
}