Skip to content

Commit

Permalink
Merge pull request #1653 from EventStore/tfchunk-verify-hash-fix
Browse files Browse the repository at this point in the history
Off by one bug in TFChunkDB causing pre-last chunk file not to be verified
  • Loading branch information
gregoryyoung committed Jun 8, 2018
2 parents 9dfeba5 + bbdea89 commit 7e98bd4
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 3 deletions.
@@ -1,4 +1,6 @@
using System;
using System.IO;
using System.Threading;
using EventStore.Core.Exceptions;
using EventStore.Core.TransactionLog.Checkpoint;
using EventStore.Core.TransactionLog.Chunks;
Expand Down Expand Up @@ -439,5 +441,55 @@ public void temporary_files_are_removed()
Assert.AreEqual(3, Directory.GetFiles(PathName, "*").Length);
}
}
[Test]
public void when_prelast_chunk_corrupted_throw_hash_validation_exception()
{
var config = TFChunkHelper.CreateDbConfig(PathName, 15000);
using (var db = new TFChunkDb(config))
{
byte[] contents = new byte[config.ChunkSize];
for(var i=0; i< config.ChunkSize;i++){
contents[i] = 0;
}
/*
Create a completed chunk and an ongoing chunk
*/
DbUtil.CreateSingleChunk(config, 0, GetFilePathFor("chunk-000000.000000"),
actualDataSize: config.ChunkSize,
contents: contents);
DbUtil.CreateOngoingChunk(config, 1, GetFilePathFor("chunk-000001.000000"));
/**
Corrupt the prelast completed chunk by modifying bytes of its content
*/
using (Stream stream = File.Open(GetFilePathFor("chunk-000000.000000"), FileMode.Open))
{
var data = new byte[3];
data[0] = 1;
data[1] = 2;
data[2] = 3;
stream.Position = ChunkHeader.Size + 15; //arbitrary choice of position to modify
stream.Write(data, 0, data.Length);
}
/**
Exception being thrown in another thread, using the output to check for the exception
*/
var output="";
using (StringWriter sw = new StringWriter())
{
Console.SetOut(sw);
db.Open(verifyHash: true);
//arbitrary wait
Thread.Sleep(2000);
output = sw.ToString();
}
var standardOutput = new StreamWriter(Console.OpenStandardOutput());
standardOutput.AutoFlush = true;
Console.SetOut(standardOutput);
Console.WriteLine(output);
Assert.IsTrue(output.Contains("EXCEPTION(S) OCCURRED:"));
Assert.IsTrue(output.Contains("EventStore.Core.Exceptions.HashValidationException"));
}

}
}
}
1 change: 1 addition & 0 deletions src/EventStore.Core/Exceptions/CorruptDatabaseException.cs
Expand Up @@ -5,5 +5,6 @@ namespace EventStore.Core.Exceptions
public class CorruptDatabaseException : Exception
{
public CorruptDatabaseException(Exception inner) : base("Corrupt database detected.", inner) { }
public CorruptDatabaseException(string message, Exception inner) : base(message, inner) { }
}
}
5 changes: 2 additions & 3 deletions src/EventStore.Core/TransactionLog/Chunks/TFChunkDb.cs
Expand Up @@ -122,7 +122,7 @@ public void Open(bool verifyHash = true, bool readOnly = false)
if (verifyHash && lastChunkNum > 0)
{
var preLastChunk = Manager.GetChunk(lastChunkNum - 1);
var lastBgChunkNum = preLastChunk.ChunkHeader.ChunkStartNumber - 1;
var lastBgChunkNum = preLastChunk.ChunkHeader.ChunkStartNumber;
ThreadPool.QueueUserWorkItem(_ =>
{
for (int chunkNum = lastBgChunkNum; chunkNum >= 0; )
Expand All @@ -143,8 +143,7 @@ public void Open(bool verifyHash = true, bool readOnly = false)
{
var msg = string.Format("Verification of chunk {0} failed, terminating server...", chunk);
Log.FatalException(exc, msg);
Application.Exit(ExitCode.Error, msg);
return;
throw new CorruptDatabaseException(msg, exc);
}
chunkNum = chunk.ChunkHeader.ChunkStartNumber - 1;
}
Expand Down

0 comments on commit 7e98bd4

Please sign in to comment.