Permalink
Browse files

Merge with saving-read-cache

  • Loading branch information...
2 parents 6320b1d + 66409a9 commit 0d9bbc481942eae596ef65d05421887703962b61 @Tamschi Tamschi committed Mar 21, 2012
View
57 MarsMiner.Saving/GameSave.cs
@@ -47,6 +47,8 @@ public class GameSave
private IntRangeList[] _freeSpace;
private Stack<long>[] _blobFileStreamPositions;
+ private Dictionary<Tuple<int, uint>, WeakReference> _blockStructureCache = new Dictionary<Tuple<int, uint>, WeakReference>();
+
public event Action MarkingFreeSpace;
private void OnMarkingFreeSpace()
@@ -85,6 +87,8 @@ internal FileStream GetBlobFile(int x)
{
OnMarkingFreeSpace();
+ _blockStructureCache.Clear();
+
if (header is IHeader == false)
{
throw new ArgumentException(header.GetType() + " doesn't implement IHeader", "header");
@@ -98,7 +102,7 @@ internal FileStream GetBlobFile(int x)
for (int i = 0; i < _freeSpace.Length; i++)
{
_freeSpace[i] = new IntRangeList();
- _freeSpace[i] += new Tuple<int, int>(HeaderLength, (int) _blobFiles[i].Length);
+ _freeSpace[i] += new Tuple<int, int>(HeaderLength, (int)_blobFiles[i].Length);
}
foreach (var kv in header.RecursiveUsedSpace)
@@ -215,8 +219,8 @@ internal void BindBlock(BlockStructure blockStructure)
bestMatch = new Tuple<int, Tuple<int, int>>(
fileIndex,
new Tuple<int, int>(
- (int) _blobFiles[fileIndex].Length,
- (int) _blobFiles[fileIndex].Length + blockLength));
+ (int)_blobFiles[fileIndex].Length,
+ (int)_blobFiles[fileIndex].Length + blockLength));
_blobFiles[fileIndex].SetLength(_blobFiles[fileIndex].Length + blockLength);
@@ -231,8 +235,8 @@ internal void BindBlock(BlockStructure blockStructure)
bestMatch = new Tuple<int, Tuple<int, int>>(newBlobIndex,
new Tuple<int, int>(
- (int) _blobFiles[newBlobIndex].Length,
- (int) _blobFiles[newBlobIndex].Length + blockLength));
+ (int)_blobFiles[newBlobIndex].Length,
+ (int)_blobFiles[newBlobIndex].Length + blockLength));
}
if (bestMatch.Item2.Item2 - bestMatch.Item2.Item1 != blockLength)
@@ -243,7 +247,7 @@ internal void BindBlock(BlockStructure blockStructure)
AllocateSpace(bestMatch.Item1, bestMatch.Item2);
- blockStructure.Address = new Tuple<int, uint>(bestMatch.Item1, (uint) bestMatch.Item2.Item1);
+ blockStructure.Address = new Tuple<int, uint>(bestMatch.Item1, (uint)bestMatch.Item2.Item1);
{
var uniqueBlockStructure = blockStructure as UniqueBlockStructure;
@@ -286,7 +290,7 @@ private void AllocateSpace(int fileIndex, Tuple<int, int> spaceArea)
{
long oldlength = _blobFiles[fileIndex].Length;
_blobFiles[fileIndex].SetLength(oldlength + spaceArea.Item2);
- _freeSpace[fileIndex] += new Tuple<int, int>((int) oldlength, (int) _blobFiles[fileIndex].Length);
+ _freeSpace[fileIndex] += new Tuple<int, int>((int)oldlength, (int)_blobFiles[fileIndex].Length);
}
_freeSpace[fileIndex] -= spaceArea;
}
@@ -383,13 +387,13 @@ public static GameSave Create(string path)
{
// Mark free space and read strings
ConstructorInfo headerConstructorInfo =
- typeof (T).GetConstructor(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
+ typeof(T).GetConstructor(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
null,
- new[] { typeof (GameSave) }, null);
+ new[] { typeof(GameSave) }, null);
if (headerConstructorInfo == null) throw new Exception("Header constructor not found.");
- header = (T) (headerConstructorInfo.Invoke(new object[] { gameSave }));
+ header = (T)(headerConstructorInfo.Invoke(new object[] { gameSave }));
gameSave.MarkFreeSpace(header);
}
}
@@ -428,5 +432,38 @@ internal void PopStreamPosition(int blobIndex)
{
_blobFiles[blobIndex].Seek(_blobFileStreamPositions[blobIndex].Pop(), SeekOrigin.Begin);
}
+
+ internal void AddToBlockStructureCache(Tuple<int, uint> address, BlockStructure blockStructure)
+ {
+ _blockStructureCache[address] = new WeakReference(blockStructure);
+ }
+
+ internal bool TryGetFromBlockStructureCache<TBlockStructure>(Tuple<int, uint> address, out TBlockStructure blockStructure) where TBlockStructure : BlockStructure
+ {
+ WeakReference blockRef;
+ if (!_blockStructureCache.TryGetValue(address, out blockRef))
+ {
+#if DebugVerboseCache
+ Console.WriteLine("Not cached: {0} ({1})", address, typeof(TBlockStructure));
+#endif
+ blockStructure = null;
+ return false;
+ }
+ blockStructure = (TBlockStructure)blockRef.Target;
+ if (blockStructure != null)
+ {
+#if DebugVerboseCache
+ Console.WriteLine("Cache hit: {0} ({1})", address, typeof(TBlockStructure));
+#endif
+ return true;
+ }
+ else
+ {
+#if DebugVerboseCache
+ Console.WriteLine("Cache expired {0} ({1})", address, typeof(TBlockStructure));
+#endif
+ return false;
+ }
+ }
}
}
View
15 MarsMiner.Saving/Structures/V0/BlockTypeTable.cs
@@ -31,11 +31,22 @@ public sealed class BlockTypeTable : UniqueBlockStructure<BlockTypeTable>, IEnum
private int[] _blockSubTypes;
private StringBlock[] _blockTypeNames;
- internal BlockTypeTable(GameSave gameSave, Tuple<int, uint> address)
+ private BlockTypeTable(GameSave gameSave, Tuple<int, uint> address)
: base(gameSave, address)
{
}
+ internal static BlockTypeTable FromSave(GameSave gameSave, Tuple<int, uint> address)
+ {
+ BlockTypeTable blockTypeTable;
+ if (!gameSave.TryGetFromBlockStructureCache(address, out blockTypeTable))
+ {
+ blockTypeTable = new BlockTypeTable(gameSave, address);
+ gameSave.AddToBlockStructureCache(address, blockTypeTable);
+ }
+ return blockTypeTable;
+ }
+
public BlockTypeTable(GameSave gameSave, StringBlock[] blockTypeNames, int[] blockSubTypes)
: base(gameSave)
{
@@ -124,7 +135,7 @@ protected override void ReadData(BinaryReader reader)
for (int i = 0; i < blockTypeNameCount; i++)
{
- _blockTypeNames[i] = new StringBlock(GameSave, ReadAddress(reader));
+ _blockTypeNames[i] = StringBlock.FromSave(GameSave, ReadAddress(reader));
_blockSubTypes[i] = reader.ReadInt32();
}
}
View
13 MarsMiner.Saving/Structures/V0/ByteArray.cs
@@ -27,10 +27,21 @@ public sealed class ByteArray : BlockStructure
{
private byte[] _data;
- internal ByteArray(GameSave gameSave, Tuple<int, uint> address) : base(gameSave, address)
+ private ByteArray(GameSave gameSave, Tuple<int, uint> address) : base(gameSave, address)
{
}
+ internal static ByteArray FromSave(GameSave gameSave, Tuple<int, uint> address)
+ {
+ ByteArray byteArray;
+ if (!gameSave.TryGetFromBlockStructureCache(address, out byteArray))
+ {
+ byteArray = new ByteArray(gameSave, address);
+ gameSave.AddToBlockStructureCache(address, byteArray);
+ }
+ return byteArray;
+ }
+
public ByteArray(GameSave gameSave, byte[] data) : base(gameSave)
{
_data = new byte[data.Length];
View
17 MarsMiner.Saving/Structures/V0/Chunk.cs
@@ -29,10 +29,21 @@ public sealed class Chunk : BlockStructure
private BlockTypeTable _blockTypeTable;
private Octree[] _octrees;
- internal Chunk(GameSave gameSave, Tuple<int, uint> address) : base(gameSave, address)
+ private Chunk(GameSave gameSave, Tuple<int, uint> address) : base(gameSave, address)
{
}
+ internal static Chunk FromSave(GameSave gameSave, Tuple<int, uint> address)
+ {
+ Chunk chunk;
+ if (!gameSave.TryGetFromBlockStructureCache(address, out chunk))
+ {
+ chunk = new Chunk(gameSave, address);
+ gameSave.AddToBlockStructureCache(address, chunk);
+ }
+ return chunk;
+ }
+
public Chunk(GameSave gameSave, BlockTypeTable blockTypeTable, Octree[] octrees) : base(gameSave)
{
_blockTypeTable = blockTypeTable;
@@ -73,14 +84,14 @@ public override BlockStructure[] ReferencedBlocks
protected override void ReadData(BinaryReader reader)
{
- _blockTypeTable = new BlockTypeTable(GameSave, ReadAddress(reader));
+ _blockTypeTable = BlockTypeTable.FromSave(GameSave, ReadAddress(reader));
byte octreeCount = reader.ReadByte();
_octrees = new Octree[octreeCount];
for (int i = 0; i < octreeCount; i++)
{
- _octrees[i] = new Octree(GameSave, ReadAddress(reader));
+ _octrees[i] = Octree.FromSave(GameSave, ReadAddress(reader));
}
}
View
15 MarsMiner.Saving/Structures/V0/ChunkTable.cs
@@ -32,10 +32,21 @@ public sealed class ChunkTable : BlockStructure
private int[] _xLocations;
private int[] _zLocations;
- internal ChunkTable(GameSave gameSave, Tuple<int, uint> address) : base(gameSave, address)
+ private ChunkTable(GameSave gameSave, Tuple<int, uint> address) : base(gameSave, address)
{
}
+ internal static ChunkTable FromSave(GameSave gameSave, Tuple<int, uint> address)
+ {
+ ChunkTable chunkTable;
+ if (!gameSave.TryGetFromBlockStructureCache(address, out chunkTable))
+ {
+ chunkTable = new ChunkTable(gameSave, address);
+ gameSave.AddToBlockStructureCache(address, chunkTable);
+ }
+ return chunkTable;
+ }
+
public ChunkTable(GameSave gameSave, int[] xLocations, int[] zLocations, Chunk[] chunks) : base(gameSave)
{
if (xLocations.Length != zLocations.Length || zLocations.Length != chunks.Length)
@@ -85,7 +96,7 @@ protected override void ReadData(BinaryReader reader)
{
_xLocations[i] = reader.ReadInt32();
_zLocations[i] = reader.ReadInt32();
- _chunks[i] = new Chunk(GameSave, ReadAddress(reader));
+ _chunks[i] = Chunk.FromSave(GameSave, ReadAddress(reader));
}
}
View
2 MarsMiner.Saving/Structures/V0/Header.cs
@@ -72,7 +72,7 @@ protected override void ReadData(BinaryReader reader)
throw new InvalidDataException("Expected file version " + Version + ", was " + version + ".");
}
- SaveIndex = new SavedStateIndex(GameSave, ReadAddress(reader));
+ SaveIndex = SavedStateIndex.FromSave(GameSave, ReadAddress(reader));
}
protected override void ForgetData()
View
13 MarsMiner.Saving/Structures/V0/Octree.cs
@@ -31,10 +31,21 @@ public sealed class Octree : BlockStructure
private BitArray _octreeFlags;
private byte[] _octreeValues;
- internal Octree(GameSave gameSave, Tuple<int, uint> address) : base(gameSave, address)
+ private Octree(GameSave gameSave, Tuple<int, uint> address) : base(gameSave, address)
{
}
+ internal static Octree FromSave(GameSave gameSave, Tuple<int, uint> address)
+ {
+ Octree octree;
+ if (!gameSave.TryGetFromBlockStructureCache(address, out octree))
+ {
+ octree = new Octree(gameSave, address);
+ gameSave.AddToBlockStructureCache(address, octree);
+ }
+ return octree;
+ }
+
public Octree(GameSave gameSave, BitArray octreeFlags, byte[] octreeValues)
: base(gameSave)
{
View
17 MarsMiner.Saving/Structures/V0/SavedStateIndex.cs
@@ -29,11 +29,22 @@ public sealed class SavedStateIndex : BlockStructure
private StringBlock _saveName;
private long _timestamp;
- internal SavedStateIndex(GameSave gameSave, Tuple<int, uint> address)
+ private SavedStateIndex(GameSave gameSave, Tuple<int, uint> address)
: base(gameSave, address)
{
}
+ internal static SavedStateIndex FromSave(GameSave gameSave, Tuple<int, uint> address)
+ {
+ SavedStateIndex savedStateIndex;
+ if (!gameSave.TryGetFromBlockStructureCache(address, out savedStateIndex))
+ {
+ savedStateIndex = new SavedStateIndex(gameSave, address);
+ gameSave.AddToBlockStructureCache(address, savedStateIndex);
+ }
+ return savedStateIndex;
+ }
+
public SavedStateIndex(GameSave gameSave, long timestamp, StringBlock saveName, ChunkTable chunkTable)
: base(gameSave)
{
@@ -84,8 +95,8 @@ protected override void ReadData(BinaryReader reader)
{
_timestamp = reader.ReadInt64();
- _saveName = new StringBlock(GameSave, ReadAddress(reader));
- _chunkTable = new ChunkTable(GameSave, ReadAddress(reader));
+ _saveName = StringBlock.FromSave(GameSave, ReadAddress(reader));
+ _chunkTable = ChunkTable.FromSave(GameSave, ReadAddress(reader));
}
protected override void ForgetData()
View
13 MarsMiner.Saving/Structures/V0/StringBlock.cs
@@ -31,11 +31,22 @@ public sealed class StringBlock : UniqueBlockStructure<StringBlock>
private string _value;
- internal StringBlock(GameSave gameSave, Tuple<int, uint> address)
+ private StringBlock(GameSave gameSave, Tuple<int, uint> address)
: base(gameSave, address)
{
}
+ internal static StringBlock FromSave(GameSave gameSave, Tuple<int, uint> address)
+ {
+ StringBlock stringBlock;
+ if (!gameSave.TryGetFromBlockStructureCache(address, out stringBlock))
+ {
+ stringBlock = new StringBlock(gameSave, address);
+ gameSave.AddToBlockStructureCache(address, stringBlock);
+ }
+ return stringBlock;
+ }
+
public StringBlock(GameSave gameSave, string value)
: base(gameSave)
{
View
24 MarsMiner.Saving/Structures/V0/StringBlockStructureDictionary.cs
@@ -30,10 +30,22 @@ public sealed class StringBlockStructureDictionary<TValue> : BlockStructure wher
{
private KeyValuePair<StringBlock, TValue>[] _keyValuePairs;
- internal StringBlockStructureDictionary(GameSave gameSave, Tuple<int, uint> address) : base(gameSave, address)
+ private StringBlockStructureDictionary(GameSave gameSave, Tuple<int, uint> address)
+ : base(gameSave, address)
{
}
+ internal static StringBlockStructureDictionary<TValue> FromSave(GameSave gameSave, Tuple<int, uint> address)
+ {
+ StringBlockStructureDictionary<TValue> stringBlockStructureDictionary;
+ if (!gameSave.TryGetFromBlockStructureCache(address, out stringBlockStructureDictionary))
+ {
+ stringBlockStructureDictionary = new StringBlockStructureDictionary<TValue>(gameSave, address);
+ gameSave.AddToBlockStructureCache(address, stringBlockStructureDictionary);
+ }
+ return stringBlockStructureDictionary;
+ }
+
public StringBlockStructureDictionary(GameSave gameSave,
IEnumerable<KeyValuePair<StringBlock, TValue>> keyValuePairs)
: base(gameSave)
@@ -73,17 +85,17 @@ protected override void ReadData(BinaryReader reader)
_keyValuePairs = new KeyValuePair<StringBlock, TValue>[length];
ConstructorInfo blockConstructorInfo =
- typeof (TValue).GetConstructor(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
+ typeof(TValue).GetConstructor(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
null,
- new[] { typeof (GameSave), typeof (Tuple<int, uint>) }, null);
+ new[] { typeof(GameSave), typeof(Tuple<int, uint>) }, null);
if (blockConstructorInfo == null)
- throw new Exception("Constructor for bound " + typeof (TValue) + " not found.");
+ throw new Exception("Constructor for bound " + typeof(TValue) + " not found.");
for (int i = 0; i < length; i++)
{
- var key = new StringBlock(GameSave, ReadAddress(reader));
- var value = (TValue) (blockConstructorInfo.Invoke(new object[] { GameSave, ReadAddress(reader) }));
+ var key = StringBlock.FromSave(GameSave, ReadAddress(reader));
+ var value = (TValue)(blockConstructorInfo.Invoke(new object[] { GameSave, ReadAddress(reader) }));
_keyValuePairs[i] = new KeyValuePair<StringBlock, TValue>(key, value);
}
}

0 comments on commit 0d9bbc4

Please sign in to comment.