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;
            }
        }
Exemple #2
0
 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;
 }
Exemple #3
0
 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;
 }
Exemple #4
0
 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;
        }