} // end Transfer() private ExceptionGuard _CompleteTransfer() { lock ( m_syncRoot ) { _CheckDisposed(); var eg = new ExceptionGuard(m_disposables); m_disposables = new List <IDisposable>(); return(eg); } } // end _CompleteTransfer()
} // end CommitTransfer() /// <summary> /// To be called in the even that the transfer was not able to be /// committed. (For instance, if the originating thread failed to post the /// transfer to the receiving thread.) /// </summary> internal void CancelTransferIfNecessary() { lock ( m_syncRoot ) { if (null == m_source) { return; // transfer is already committed or redeemed. } // If the destination thread is stuck waiting, we'll prepare an empty // ExceptionGuard to give to it and then unblock it. m_transferred = new ExceptionGuard(); m_source = null; Monitor.PulseAll(m_syncRoot); } // end lock } // end CancelTransferIfNecessary()
} // end Redeem() public void CommitTransfer() { lock ( m_syncRoot ) { if (null == m_source) { throw new InvalidOperationException("Transfer already committed."); } m_transferred = m_source._CompleteTransfer(); m_source = null; // The thread that will Redeem() the transfer may or may not be // waiting. If it is, signal it: Monitor.PulseAll(m_syncRoot); } // end lock } // end CommitTransfer()
public ExceptionGuard Redeem() { lock ( m_syncRoot ) { if ((null == m_source) && (null == m_transferred)) { throw new InvalidOperationException("Transfer already redeemed."); } if (null == m_transferred) { // We need to wait for the transfer to be committed by // CommitTransfer(). Monitor.Wait(m_syncRoot); Util.Assert(null != m_transferred); } // else the CommitTransfer call already went through. var tmp = m_transferred; m_transferred = null; return(tmp); } // end lock } // end Redeem()
internal TransferTicket(ExceptionGuard source) { m_source = source; }
} // end _PruneLogFiles() private static void _PruneFilesNotInUse(string dir, string pattern, long cbMaxSize) { const int MIN_LOG_BYTES = 1024 * 1024; if (cbMaxSize < MIN_LOG_BYTES) { Util.Fail("should not happen"); // safe to use Util.Fail here cbMaxSize = MIN_LOG_BYTES; } using (ExceptionGuard disposer = new ExceptionGuard()) { DirectoryInfo di = new DirectoryInfo(dir); FileSystemInfo[] fsis = di.GetFileSystemInfos(pattern); List <FileInfo> files = new List <FileInfo>(fsis.Length); List <FileStream> fileLocks = new List <FileStream>(fsis.Length); disposer.ProtectAll(fileLocks); // it does not make a copy of the list, so it's okay that we haven't put anything in yet. long totalSize = 0; foreach (FileSystemInfo fsi in fsis) { FileInfo fi = fsi as FileInfo; if (null != fi) { // We only count not-in-use files against our disk limit. If the // file is not in use, this will "lock" it (making it appear // in-use to anybody else) and put the resulting FileStream in the // fileLocks list. if (_FileNotInUse(fi, fileLocks)) { #if DEBUG_LOG_PRUNING Trace("File \"{0}\" is NOT in use. (it will be considered for pruning)", fi.FullName); #endif fi.Refresh(); // in case _FileNotInUse finalized it. totalSize += fi.Length; files.Add(fi); } #if DEBUG_LOG_PRUNING else { Trace("File \"{0}\" is in use.", fi.FullName); } #endif } } if (totalSize <= cbMaxSize) { // Don't need to prune anything. return; } // Sort by age: oldest first. files.Sort((x, y) => x.CreationTime.CompareTo(y.CreationTime)); long cbDeletedSoFar = 0; long cbNeedToDelete = totalSize - cbMaxSize; int idxCandidate = 0; while ((idxCandidate < files.Count) && (cbDeletedSoFar < cbNeedToDelete)) { if (_TryDeleteOldFile(files[idxCandidate].FullName)) { cbDeletedSoFar += files[idxCandidate].Length; } idxCandidate++; } if (cbDeletedSoFar < cbNeedToDelete) { Trace("Warning: could not delete enough log files matching \"{0}\" from \"{1}\" to get under the limit of {2}.", pattern, dir, Util.FormatByteSize(cbMaxSize)); } } // end using( disposer ) <-- the files will actually get deleted here when we close the FileStream handles. } // end _PruneFilesNotInUse()