public TFChunk.TFChunk SwitchChunk(TFChunk.TFChunk chunk, bool verifyHash, bool removeChunksWithGreaterNumbers) { Ensure.NotNull(chunk, "chunk"); if (!chunk.IsReadOnly) throw new ArgumentException(string.Format("Passed TFChunk is not completed: {0}.", chunk.FileName)); var chunkHeader = chunk.ChunkHeader; var oldFileName = chunk.FileName; Log.Info("Switching chunk #{0}-{1} ({2})...", chunkHeader.ChunkStartNumber, chunkHeader.ChunkEndNumber, oldFileName); chunk.Dispose(); try { chunk.WaitForDestroy(0); // should happen immediately } catch (TimeoutException exc) { throw new Exception(string.Format("The chunk that is being switched #{0}-{1} ({2}) is used by someone else.", chunkHeader.ChunkStartNumber, chunkHeader.ChunkEndNumber, oldFileName), exc); } var newFileName = _config.FileNamingStrategy.DetermineBestVersionFilenameFor(chunkHeader.ChunkStartNumber); Log.Info("File {0} will be moved to file {1}", oldFileName, newFileName); File.Move(oldFileName, newFileName); var newChunk = TFChunk.TFChunk.FromCompletedFile(newFileName, verifyHash); lock (_chunksLocker) { if (!ReplaceChunksWith(newChunk, "Old")) { Log.Info("Chunk #{0}-{1} ({2}) will be not switched, marking for remove...", chunkHeader.ChunkStartNumber, chunkHeader.ChunkEndNumber,newFileName); newChunk.MarkForDeletion(); } if (removeChunksWithGreaterNumbers) { var oldChunksCount = _chunksCount; _chunksCount = newChunk.ChunkHeader.ChunkEndNumber + 1; RemoveChunks(chunkHeader.ChunkEndNumber + 1, oldChunksCount-1, "Excessive"); if (_chunks[_chunksCount] != null) throw new Exception(string.Format("Excessive chunk #{0} found after raw replication switch.", _chunksCount)); } TryCacheChunk(newChunk); return newChunk; } }
public static TFChunk FromOngoingFile(string filename, int writePosition) { var chunk = new TFChunk(filename, TFConsts.TFChunkReaderCount, TFConsts.MidpointsDepth); try { chunk.InitOngoing(writePosition); } catch { chunk.Dispose(); throw; } return chunk; }
public static TFChunk CreateNew(string filename, int chunkSize, int chunkNumber, int chunkScavengeVersion) { var chunkHeader = new ChunkHeader(CurrentChunkVersion, chunkSize, chunkNumber, chunkNumber, chunkScavengeVersion); var chunk = new TFChunk(filename, TFConsts.TFChunkReaderCount, TFConsts.MidpointsDepth); try { chunk.InitNew(chunkHeader); } catch { chunk.Dispose(); throw; } return chunk; }
public static TFChunk FromCompletedFile(string filename, bool verifyHash) { var chunk = new TFChunk(filename, TFConsts.TFChunkReaderCount, TFConsts.MidpointsDepth); try { chunk.InitCompleted(verifyHash); } catch { chunk.Dispose(); throw; } return chunk; }
public TFChunk.TFChunk SwitchChunk(TFChunk.TFChunk chunk, bool verifyHash, bool replaceChunksWithGreaterNumbers) { Ensure.NotNull(chunk, "chunk"); if (!chunk.IsReadOnly) throw new ArgumentException(string.Format("Passed TFChunk is not completed: {0}.", chunk.FileName)); var chunkHeader = chunk.ChunkHeader; var oldFileName = chunk.FileName; Log.Info("Switching chunk #{0}-{1} ({2})...", chunkHeader.ChunkStartNumber, chunkHeader.ChunkEndNumber, oldFileName); chunk.Dispose(); try { chunk.WaitForDestroy(0); // should happen immediately } catch (TimeoutException exc) { throw new Exception(string.Format("The chunk that is being switched #{0}-{1} ({2}) is used by someone else.", chunk.ChunkHeader.ChunkStartNumber, chunk.ChunkHeader.ChunkEndNumber, chunk.FileName), exc); } var newFileName = _config.FileNamingStrategy.DetermineBestVersionFilenameFor(chunkHeader.ChunkStartNumber); Log.Info("File {0} will be moved to file {1}", oldFileName, newFileName); File.Move(oldFileName, newFileName); var newChunk = TFChunk.TFChunk.FromCompletedFile(newFileName, verifyHash); for (int i = chunkHeader.ChunkStartNumber; i <= chunkHeader.ChunkEndNumber; ++i) { var oldChunk = Interlocked.Exchange(ref _chunks[i], newChunk); if (oldChunk != null) { oldChunk.MarkForDeletion(); Log.Info("Old chunk {0} is marked for deletion.", oldChunk.FileName); } } if (replaceChunksWithGreaterNumbers) { var oldChunksCount = _chunksCount; _chunksCount = newChunk.ChunkHeader.ChunkEndNumber + 1; for (int i = chunkHeader.ChunkEndNumber + 1; i < oldChunksCount; ++i) { var oldChunk = Interlocked.Exchange(ref _chunks[i], null); if (oldChunk != null) { oldChunk.MarkForDeletion(); Log.Info("Excessive chunk {0} is marked for deletion.", oldChunk.FileName); } } Debug.Assert(_chunks[_chunksCount] == null); } TryCacheChunk(newChunk); return newChunk; }