mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-01-27 09:24:47 +00:00
Correctly invalidate the ROM mount cache
Before it would remain the same across world reloads, and thus would be out-of-date after leaving the first world. This architecture technically allows for running multiple servers at once, though that's not going to matter that soon.
This commit is contained in:
parent
642351af1a
commit
3b7300543a
@ -6,11 +6,9 @@
|
|||||||
|
|
||||||
package dan200.computercraft;
|
package dan200.computercraft;
|
||||||
|
|
||||||
import dan200.computercraft.api.filesystem.IMount;
|
|
||||||
import dan200.computercraft.api.turtle.event.TurtleAction;
|
import dan200.computercraft.api.turtle.event.TurtleAction;
|
||||||
import dan200.computercraft.core.apis.AddressPredicate;
|
import dan200.computercraft.core.apis.AddressPredicate;
|
||||||
import dan200.computercraft.core.apis.http.websocket.Websocket;
|
import dan200.computercraft.core.apis.http.websocket.Websocket;
|
||||||
import dan200.computercraft.core.filesystem.ResourceMount;
|
|
||||||
import dan200.computercraft.shared.Config;
|
import dan200.computercraft.shared.Config;
|
||||||
import dan200.computercraft.shared.computer.blocks.BlockComputer;
|
import dan200.computercraft.shared.computer.blocks.BlockComputer;
|
||||||
import dan200.computercraft.shared.computer.core.ClientComputerRegistry;
|
import dan200.computercraft.shared.computer.core.ClientComputerRegistry;
|
||||||
@ -194,13 +192,6 @@ public final class ComputerCraft
|
|||||||
return "${version}";
|
return "${version}";
|
||||||
}
|
}
|
||||||
|
|
||||||
static IMount createResourceMount( String domain, String subPath )
|
|
||||||
{
|
|
||||||
IReloadableResourceManager manager = ServerLifecycleHooks.getCurrentServer().getResourceManager();
|
|
||||||
ResourceMount mount = new ResourceMount( domain, subPath, manager );
|
|
||||||
return mount.exists( "" ) ? mount : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static InputStream getResourceFile( String domain, String subPath )
|
public static InputStream getResourceFile( String domain, String subPath )
|
||||||
{
|
{
|
||||||
IReloadableResourceManager manager = ServerLifecycleHooks.getCurrentServer().getResourceManager();
|
IReloadableResourceManager manager = ServerLifecycleHooks.getCurrentServer().getResourceManager();
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
package dan200.computercraft;
|
package dan200.computercraft;
|
||||||
|
|
||||||
|
import com.google.common.collect.MapMaker;
|
||||||
import dan200.computercraft.api.ComputerCraftAPI.IComputerCraftAPI;
|
import dan200.computercraft.api.ComputerCraftAPI.IComputerCraftAPI;
|
||||||
import dan200.computercraft.api.filesystem.IMount;
|
import dan200.computercraft.api.filesystem.IMount;
|
||||||
import dan200.computercraft.api.filesystem.IWritableMount;
|
import dan200.computercraft.api.filesystem.IWritableMount;
|
||||||
@ -20,20 +21,26 @@ import dan200.computercraft.api.redstone.IBundledRedstoneProvider;
|
|||||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||||
import dan200.computercraft.core.apis.ApiFactories;
|
import dan200.computercraft.core.apis.ApiFactories;
|
||||||
import dan200.computercraft.core.filesystem.FileMount;
|
import dan200.computercraft.core.filesystem.FileMount;
|
||||||
|
import dan200.computercraft.core.filesystem.ResourceMount;
|
||||||
import dan200.computercraft.shared.*;
|
import dan200.computercraft.shared.*;
|
||||||
import dan200.computercraft.shared.peripheral.modem.wireless.WirelessNetwork;
|
import dan200.computercraft.shared.peripheral.modem.wireless.WirelessNetwork;
|
||||||
import dan200.computercraft.shared.util.IDAssigner;
|
import dan200.computercraft.shared.util.IDAssigner;
|
||||||
import dan200.computercraft.shared.wired.CapabilityWiredElement;
|
import dan200.computercraft.shared.wired.CapabilityWiredElement;
|
||||||
import dan200.computercraft.shared.wired.WiredNode;
|
import dan200.computercraft.shared.wired.WiredNode;
|
||||||
|
import net.minecraft.resources.IReloadableResourceManager;
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.IBlockReader;
|
import net.minecraft.world.IBlockReader;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraftforge.common.util.LazyOptional;
|
import net.minecraftforge.common.util.LazyOptional;
|
||||||
|
import net.minecraftforge.fml.server.ServerLifecycleHooks;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public final class ComputerCraftAPIImpl implements IComputerCraftAPI
|
public final class ComputerCraftAPIImpl implements IComputerCraftAPI
|
||||||
{
|
{
|
||||||
@ -43,6 +50,9 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private WeakReference<IReloadableResourceManager> currentResources;
|
||||||
|
private final Map<ResourceLocation, ResourceMount> mountCache = new MapMaker().weakValues().concurrencyLevel( 1 ).makeMap();
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public String getInstalledVersion()
|
public String getInstalledVersion()
|
||||||
@ -72,7 +82,9 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
|
|||||||
@Override
|
@Override
|
||||||
public IMount createResourceMount( @Nonnull String domain, @Nonnull String subPath )
|
public IMount createResourceMount( @Nonnull String domain, @Nonnull String subPath )
|
||||||
{
|
{
|
||||||
return ComputerCraft.createResourceMount( domain, subPath );
|
IReloadableResourceManager manager = ServerLifecycleHooks.getCurrentServer().getResourceManager();
|
||||||
|
ResourceMount mount = ResourceMount.get( domain, subPath, manager );
|
||||||
|
return mount.exists( "" ) ? mount : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -56,9 +56,6 @@ final class ComputerExecutor
|
|||||||
{
|
{
|
||||||
private static final int QUEUE_LIMIT = 256;
|
private static final int QUEUE_LIMIT = 256;
|
||||||
|
|
||||||
private static IMount romMount;
|
|
||||||
private static final Object romMountLock = new Object();
|
|
||||||
|
|
||||||
private final Computer computer;
|
private final Computer computer;
|
||||||
private final List<ILuaAPI> apis = new ArrayList<>();
|
private final List<ILuaAPI> apis = new ArrayList<>();
|
||||||
final TimeoutState timeout = new TimeoutState();
|
final TimeoutState timeout = new TimeoutState();
|
||||||
@ -329,16 +326,10 @@ final class ComputerExecutor
|
|||||||
|
|
||||||
private IMount getRomMount()
|
private IMount getRomMount()
|
||||||
{
|
{
|
||||||
if( romMount != null ) return romMount;
|
return computer.getComputerEnvironment().createResourceMount( "computercraft", "lua/rom" );
|
||||||
|
|
||||||
synchronized( romMountLock )
|
|
||||||
{
|
|
||||||
if( romMount != null ) return romMount;
|
|
||||||
return romMount = computer.getComputerEnvironment().createResourceMount( "computercraft", "lua/rom" );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IWritableMount getRootMount()
|
private IWritableMount getRootMount()
|
||||||
{
|
{
|
||||||
if( rootMount == null )
|
if( rootMount == null )
|
||||||
{
|
{
|
||||||
|
@ -8,13 +8,16 @@ package dan200.computercraft.core.filesystem;
|
|||||||
|
|
||||||
import com.google.common.cache.Cache;
|
import com.google.common.cache.Cache;
|
||||||
import com.google.common.cache.CacheBuilder;
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.collect.MapMaker;
|
||||||
import com.google.common.io.ByteStreams;
|
import com.google.common.io.ByteStreams;
|
||||||
|
import dan200.computercraft.ComputerCraft;
|
||||||
import dan200.computercraft.api.filesystem.IMount;
|
import dan200.computercraft.api.filesystem.IMount;
|
||||||
import dan200.computercraft.core.apis.handles.ArrayByteChannel;
|
import dan200.computercraft.core.apis.handles.ArrayByteChannel;
|
||||||
import net.minecraft.resources.IReloadableResourceManager;
|
import net.minecraft.resources.IReloadableResourceManager;
|
||||||
import net.minecraft.resources.IResource;
|
import net.minecraft.resources.IResource;
|
||||||
import net.minecraft.resources.IResourceManager;
|
import net.minecraft.resources.IResourceManager;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
import net.minecraft.util.ResourceLocationException;
|
||||||
import net.minecraftforge.resource.IResourceType;
|
import net.minecraftforge.resource.IResourceType;
|
||||||
import net.minecraftforge.resource.ISelectiveResourceReloadListener;
|
import net.minecraftforge.resource.ISelectiveResourceReloadListener;
|
||||||
|
|
||||||
@ -29,7 +32,7 @@ import java.util.*;
|
|||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
public class ResourceMount implements IMount
|
public final class ResourceMount implements IMount
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Only cache files smaller than 1MiB.
|
* Only cache files smaller than 1MiB.
|
||||||
@ -55,6 +58,13 @@ public class ResourceMount implements IMount
|
|||||||
.<FileEntry, byte[]>weigher( ( k, v ) -> v.length )
|
.<FileEntry, byte[]>weigher( ( k, v ) -> v.length )
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
private static final MapMaker CACHE_TEMPLATE = new MapMaker().weakValues().concurrencyLevel( 1 );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maintain a cache of currently loaded resource mounts. This cache is invalidated when currentManager changes.
|
||||||
|
*/
|
||||||
|
private static final Map<IReloadableResourceManager, Map<ResourceLocation, ResourceMount>> MOUNT_CACHE = new WeakHashMap<>( 2 );
|
||||||
|
|
||||||
private final String namespace;
|
private final String namespace;
|
||||||
private final String subPath;
|
private final String subPath;
|
||||||
private final IReloadableResourceManager manager;
|
private final IReloadableResourceManager manager;
|
||||||
@ -62,7 +72,26 @@ public class ResourceMount implements IMount
|
|||||||
@Nullable
|
@Nullable
|
||||||
private FileEntry root;
|
private FileEntry root;
|
||||||
|
|
||||||
public ResourceMount( String namespace, String subPath, IReloadableResourceManager manager )
|
public static ResourceMount get( String namespace, String subPath, IReloadableResourceManager manager )
|
||||||
|
{
|
||||||
|
Map<ResourceLocation, ResourceMount> cache;
|
||||||
|
|
||||||
|
synchronized( MOUNT_CACHE )
|
||||||
|
{
|
||||||
|
cache = MOUNT_CACHE.get( manager );
|
||||||
|
if( cache == null ) MOUNT_CACHE.put( manager, cache = CACHE_TEMPLATE.makeMap() );
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceLocation path = new ResourceLocation( namespace, subPath );
|
||||||
|
synchronized( cache )
|
||||||
|
{
|
||||||
|
ResourceMount mount = cache.get( path );
|
||||||
|
if( mount == null ) cache.put( path, mount = new ResourceMount( namespace, subPath, manager ) );
|
||||||
|
return mount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResourceMount( String namespace, String subPath, IReloadableResourceManager manager )
|
||||||
{
|
{
|
||||||
this.namespace = namespace;
|
this.namespace = namespace;
|
||||||
this.subPath = subPath;
|
this.subPath = subPath;
|
||||||
@ -119,7 +148,17 @@ public class ResourceMount implements IMount
|
|||||||
FileEntry nextEntry = lastEntry.children.get( part );
|
FileEntry nextEntry = lastEntry.children.get( part );
|
||||||
if( nextEntry == null )
|
if( nextEntry == null )
|
||||||
{
|
{
|
||||||
lastEntry.children.put( part, nextEntry = new FileEntry( new ResourceLocation( namespace, subPath + "/" + path ) ) );
|
ResourceLocation childPath;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
childPath = new ResourceLocation( namespace, subPath + "/" + path );
|
||||||
|
}
|
||||||
|
catch( ResourceLocationException e )
|
||||||
|
{
|
||||||
|
ComputerCraft.log.warn( "Cannot create resource location for {} ({})", part, e.getMessage() );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lastEntry.children.put( part, nextEntry = new FileEntry( childPath ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
lastEntry = nextEntry;
|
lastEntry = nextEntry;
|
||||||
|
@ -31,7 +31,7 @@ public class ResourceMountTest
|
|||||||
SimpleReloadableResourceManager manager = new SimpleReloadableResourceManager( ResourcePackType.SERVER_DATA, null );
|
SimpleReloadableResourceManager manager = new SimpleReloadableResourceManager( ResourcePackType.SERVER_DATA, null );
|
||||||
manager.addResourcePack( new FolderPack( new File( "src/main/resources" ) ) );
|
manager.addResourcePack( new FolderPack( new File( "src/main/resources" ) ) );
|
||||||
|
|
||||||
mount = new ResourceMount( "computercraft", "lua/rom", manager );
|
mount = ResourceMount.get( "computercraft", "lua/rom", manager );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
Loading…
Reference in New Issue
Block a user