private static ChunkHeader ReadChunkHeader(string chunkFileName) { ChunkHeader chunkHeader; using (var fs = new FileStream(chunkFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { chunkHeader = ChunkHeader.FromStream(fs); } return(chunkHeader); }
private ChunkHeader ReadHeader(Stream stream) { if (stream.Length < ChunkHeader.Size) { throw new CorruptDatabaseException(new BadChunkInDatabaseException( string.Format("Chunk file '{0}' is too short to even read ChunkHeader, its size is {1} bytes.", _filename, stream.Length))); } stream.Seek(0, SeekOrigin.Begin); var chunkHeader = ChunkHeader.FromStream(stream); return(chunkHeader); }
private static ChunkHeader ReadChunkHeader(string chunkFileName) { ChunkHeader chunkHeader; using (var fs = new FileStream(chunkFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { if (fs.Length < ChunkFooter.Size + ChunkHeader.Size) { throw new CorruptDatabaseException(new BadChunkInDatabaseException( string.Format("Chunk file '{0}' is bad. It does not have enough size for header and footer. File size is {1} bytes.", chunkFileName, fs.Length))); } chunkHeader = ChunkHeader.FromStream(fs); } return(chunkHeader); }
public void TruncateDb(long truncateChk) { var writerChk = _config.WriterCheckpoint.Read(); var oldLastChunkNum = (int)(writerChk / _config.ChunkSize); var newLastChunkNum = (int)(truncateChk / _config.ChunkSize); var excessiveChunks = _config.FileNamingStrategy.GetAllVersionsFor(oldLastChunkNum + 1); if (excessiveChunks.Length > 0) { throw new Exception(string.Format("During truncation of DB excessive TFChunks were found:\n{0}.", string.Join("\n", excessiveChunks))); } ChunkHeader newLastChunkHeader = null; string newLastChunkFilename = null; for (int chunkNum = 0; chunkNum <= newLastChunkNum;) { var chunks = _config.FileNamingStrategy.GetAllVersionsFor(chunkNum); if (chunks.Length == 0) { if (chunkNum != newLastChunkNum) { throw new Exception(string.Format("Couldn't find any chunk #{0}.", chunkNum)); } break; } using (var fs = File.OpenRead(chunks[0])) { var chunkHeader = ChunkHeader.FromStream(fs); if (chunkHeader.ChunkEndNumber >= newLastChunkNum) { newLastChunkHeader = chunkHeader; newLastChunkFilename = chunks[0]; break; } chunkNum = chunkHeader.ChunkEndNumber + 1; } } // we need to remove excessive chunks from largest number to lowest one, so in case of crash // mid-process, we don't end up with broken non-sequential chunks sequence. for (int i = oldLastChunkNum; i > newLastChunkNum; i -= 1) { foreach (var chunkFile in _config.FileNamingStrategy.GetAllVersionsFor(i)) { Log.Info("File {0} will be deleted during TruncateDb procedure.", chunkFile); File.SetAttributes(chunkFile, FileAttributes.Normal); File.Delete(chunkFile); } } // it's not bad if there is no file, it could have been deleted on previous run if (newLastChunkHeader != null) { // if the chunk we want to truncate into is already scavenged // we have to truncate (i.e., delete) the whole chunk, not just part of it if (newLastChunkHeader.IsScavenged) { truncateChk = newLastChunkHeader.ChunkStartPosition; // we need to delete EVERYTHING from ChunkStartNumber up to newLastChunkNum, inclusive Log.Info("Setting TruncateCheckpoint to {0} and deleting ALL chunks from #{1} inclusively " + "as truncation position is in the middle of scavenged chunk.", truncateChk, newLastChunkHeader.ChunkStartNumber); for (int i = newLastChunkNum; i >= newLastChunkHeader.ChunkStartNumber; --i) { var chunksToDelete = _config.FileNamingStrategy.GetAllVersionsFor(i); foreach (var chunkFile in chunksToDelete) { Log.Info("File {0} will be deleted during TruncateDb procedure.", chunkFile); File.SetAttributes(chunkFile, FileAttributes.Normal); File.Delete(chunkFile); } } } else { TruncateChunkAndFillWithZeros(newLastChunkHeader, newLastChunkFilename, truncateChk); } } if (_config.EpochCheckpoint.Read() >= truncateChk) { Log.Info("Truncating epoch from {0} (0x{0:X}) to {1} (0x{1:X}).", _config.EpochCheckpoint.Read(), -1); _config.EpochCheckpoint.Write(-1); _config.EpochCheckpoint.Flush(); } if (_config.ChaserCheckpoint.Read() > truncateChk) { Log.Info("Truncating chaser from {0} (0x{0:X}) to {1} (0x{1:X}).", _config.ChaserCheckpoint.Read(), truncateChk); _config.ChaserCheckpoint.Write(truncateChk); _config.ChaserCheckpoint.Flush(); } if (_config.WriterCheckpoint.Read() > truncateChk) { Log.Info("Truncating writer from {0} (0x{0:X}) to {1} (0x{1:X}).", _config.WriterCheckpoint.Read(), truncateChk); _config.WriterCheckpoint.Write(truncateChk); _config.WriterCheckpoint.Flush(); } Log.Info("Resetting TruncateCheckpoint to {0} (0x{0:X}).", -1); _config.TruncateCheckpoint.Write(-1); _config.TruncateCheckpoint.Flush(); }