Merge pull request #9 from z93blom/master

Added support for multithreaded access to chunks
This commit is contained in:
Justin Aquadro 2012-11-26 12:30:52 -08:00
commit 44ff3373d0

View file

@ -21,6 +21,15 @@ namespace Substrate.Core
private string fileName; private string fileName;
private FileStream file; private FileStream file;
/// <summary>
/// The file lock used so that we do not seek in different areas
/// of the same file at the same time. All file access should lock this
/// object before moving the file pointer.
/// The lock should also surround all access to the sectorFree free variable.
/// </summary>
private object fileLock = new object();
private int[] offsets; private int[] offsets;
private int[] chunkTimestamps; private int[] chunkTimestamps;
private List<Boolean> sectorFree; private List<Boolean> sectorFree;
@ -62,10 +71,12 @@ namespace Substrate.Core
// Cleanup unmanaged resources // Cleanup unmanaged resources
if (file != null) { if (file != null) {
lock (this.fileLock) {
file.Close(); file.Close();
file = null; file = null;
} }
} }
}
_disposed = true; _disposed = true;
} }
@ -93,6 +104,7 @@ namespace Substrate.Core
} }
try { try {
lock (this.fileLock) {
file = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite); file = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
//using (file) { //using (file) {
@ -161,7 +173,7 @@ namespace Substrate.Core
chunkTimestamps[i] = lastModValue; chunkTimestamps[i] = lastModValue;
} }
//} }
} }
catch (IOException e) { catch (IOException e) {
System.Console.WriteLine(e.Message); System.Console.WriteLine(e.Message);
@ -234,6 +246,8 @@ namespace Substrate.Core
int sectorNumber = offset >> 8; int sectorNumber = offset >> 8;
int numSectors = offset & 0xFF; int numSectors = offset & 0xFF;
lock (this.fileLock)
{
if (sectorNumber + numSectors > sectorFree.Count) { if (sectorNumber + numSectors > sectorFree.Count) {
Debugln("READ", x, z, "invalid sector"); Debugln("READ", x, z, "invalid sector");
return null; return null;
@ -281,6 +295,7 @@ namespace Substrate.Core
Debugln("READ", x, z, "unknown version " + version); Debugln("READ", x, z, "unknown version " + version);
return null; return null;
} }
}
catch (IOException) { catch (IOException) {
Debugln("READ", x, z, "exception"); Debugln("READ", x, z, "exception");
return null; return null;
@ -368,6 +383,7 @@ namespace Substrate.Core
else { else {
/* we need to allocate new sectors */ /* we need to allocate new sectors */
lock (this.fileLock) {
/* mark the sectors previously used for this chunk as free */ /* mark the sectors previously used for this chunk as free */
for (int i = 0; i < sectorsAllocated; ++i) { for (int i = 0; i < sectorsAllocated; ++i) {
sectorFree[sectorNumber + i] = true; sectorFree[sectorNumber + i] = true;
@ -420,6 +436,7 @@ namespace Substrate.Core
SetOffset(x, z, (sectorNumber << 8) | sectorsNeeded); SetOffset(x, z, (sectorNumber << 8) | sectorsNeeded);
} }
} }
}
SetTimestamp(x, z, timestamp); SetTimestamp(x, z, timestamp);
} }
catch (IOException e) { catch (IOException e) {
@ -430,6 +447,7 @@ namespace Substrate.Core
/* write a chunk data to the region file at specified sector number */ /* write a chunk data to the region file at specified sector number */
private void Write (int sectorNumber, byte[] data, int length) private void Write (int sectorNumber, byte[] data, int length)
{ {
lock (this.fileLock) {
Debugln(" " + sectorNumber); Debugln(" " + sectorNumber);
file.Seek(sectorNumber * SectorBytes, SeekOrigin.Begin); file.Seek(sectorNumber * SectorBytes, SeekOrigin.Begin);
@ -442,9 +460,11 @@ namespace Substrate.Core
file.WriteByte(VERSION_DEFLATE); // chunk version number file.WriteByte(VERSION_DEFLATE); // chunk version number
file.Write(data, 0, length); // chunk data file.Write(data, 0, length); // chunk data
} }
}
public void DeleteChunk (int x, int z) public void DeleteChunk (int x, int z)
{ {
lock (this.fileLock) {
int offset = GetOffset(x, z); int offset = GetOffset(x, z);
int sectorNumber = offset >> 8; int sectorNumber = offset >> 8;
int sectorsAllocated = offset & 0xFF; int sectorsAllocated = offset & 0xFF;
@ -457,6 +477,7 @@ namespace Substrate.Core
SetOffset(x, z, 0); SetOffset(x, z, 0);
SetTimestamp(x, z, 0); SetTimestamp(x, z, 0);
} }
}
/* is this an invalid chunk coordinate? */ /* is this an invalid chunk coordinate? */
private bool OutOfBounds (int x, int z) private bool OutOfBounds (int x, int z)
@ -476,6 +497,7 @@ namespace Substrate.Core
private void SetOffset (int x, int z, int offset) private void SetOffset (int x, int z, int offset)
{ {
lock (this.fileLock) {
offsets[x + z * 32] = offset; offsets[x + z * 32] = offset;
file.Seek((x + z * 32) * 4, SeekOrigin.Begin); file.Seek((x + z * 32) * 4, SeekOrigin.Begin);
@ -487,6 +509,7 @@ namespace Substrate.Core
file.Write(bytes, 0, 4); file.Write(bytes, 0, 4);
} }
}
private int Timestamp () private int Timestamp ()
{ {
@ -507,6 +530,7 @@ namespace Substrate.Core
public void SetTimestamp (int x, int z, int value) public void SetTimestamp (int x, int z, int value)
{ {
lock (this.fileLock) {
chunkTimestamps[x + z * 32] = value; chunkTimestamps[x + z * 32] = value;
file.Seek(SectorBytes + (x + z * 32) * 4, SeekOrigin.Begin); file.Seek(SectorBytes + (x + z * 32) * 4, SeekOrigin.Begin);
@ -518,11 +542,14 @@ namespace Substrate.Core
file.Write(bytes, 0, 4); file.Write(bytes, 0, 4);
} }
}
public void Close () public void Close ()
{ {
lock (this.fileLock) {
file.Close(); file.Close();
} }
}
protected virtual int SectorBytes protected virtual int SectorBytes
{ {