public static string AxisLabel(TimeSpan timeSpan) { if (timeSpan <= TransactionFeeHelper.CalculateConfirmationTime(WalletWasabi.Helpers.Constants.FastestConfirmationTarget)) { return("fastest"); } return(TimeSpanFormatter.Format(timeSpan, new TimeSpanFormatter.Configuration("d", "h", "m"))); }
public static string SliderLabel(TimeSpan timeSpan) { if (timeSpan <= TransactionFeeHelper.CalculateConfirmationTime(WalletWasabi.Helpers.Constants.FastestConfirmationTarget)) { return("fastest"); } return("~" + TimeSpanFormatter.Format(timeSpan, new TimeSpanFormatter.Configuration(" days", " hours", " minutes"))); }
public void TimeSpanFormatterTests() { Assert.AreEqual("01:02:03", TimeSpanFormatter.Format(new TimeSpan(1, 2, 3), FormatVerbosities.SuperBrief, numberFormatCulture: System.Globalization.CultureInfo.InvariantCulture)); Assert.AreEqual("01:02:03.123", TimeSpanFormatter.Format(new TimeSpan(1, 2, 3) + TimeSpan.FromMilliseconds(123), FormatVerbosities.SuperBrief, numberFormatCulture: System.Globalization.CultureInfo.InvariantCulture)); Assert.AreEqual("2.04:02:03.456", TimeSpanFormatter.Format(new TimeSpan(4, 2, 3) + TimeSpan.FromDays(2) + TimeSpan.FromMilliseconds(456), FormatVerbosities.SuperBrief, unitSpacer: true, numberFormatCulture: System.Globalization.CultureInfo.InvariantCulture)); Assert.AreEqual("1h2m3s", TimeSpanFormatter.Format(new TimeSpan(1, 2, 3), FormatVerbosities.Brief, unitSpacer: false, numberFormatCulture: System.Globalization.CultureInfo.InvariantCulture)); Assert.AreEqual("1 h 2 m 3 s", TimeSpanFormatter.Format(new TimeSpan(1, 2, 3), FormatVerbosities.Brief, unitSpacer: true, numberFormatCulture: System.Globalization.CultureInfo.InvariantCulture)); Assert.AreEqual("1 h 2 m 3.456 s", TimeSpanFormatter.Format(new TimeSpan(1, 2, 3) + TimeSpan.FromMilliseconds(456), FormatVerbosities.Brief, unitSpacer: true, numberFormatCulture: System.Globalization.CultureInfo.InvariantCulture)); Assert.AreEqual("1 hour 2 min 3 sec", TimeSpanFormatter.Format(new TimeSpan(1, 2, 3), FormatVerbosities.Normal, unitSpacer: true, numberFormatCulture: System.Globalization.CultureInfo.InvariantCulture)); Assert.AreEqual("1 hour 2 min 3.456 sec", TimeSpanFormatter.Format(new TimeSpan(1, 2, 3) + TimeSpan.FromMilliseconds(456), FormatVerbosities.Normal, unitSpacer: true, numberFormatCulture: System.Globalization.CultureInfo.InvariantCulture)); Assert.AreEqual("1 hour 2 minutes 3 seconds", TimeSpanFormatter.Format(new TimeSpan(1, 2, 3), FormatVerbosities.Verbose, unitSpacer: true, numberFormatCulture: System.Globalization.CultureInfo.InvariantCulture)); Assert.AreEqual("2 days 4 hours 2 minutes 3.456 seconds", TimeSpanFormatter.Format(new TimeSpan(4, 2, 3) + TimeSpan.FromDays(2) + TimeSpan.FromMilliseconds(456), FormatVerbosities.Verbose, unitSpacer: true, numberFormatCulture: System.Globalization.CultureInfo.InvariantCulture)); }
private static string MatchReplacer(Match m, TimeSpan timeSpan, TimeSpanFormatter formatter) { string input; // the matched non-'\' char before the stuff we actually care about string firstChar = m.Groups[1].Success ? m.Groups[1].Value : string.Empty; if (m.Groups[4].Success) { // has additional formatting input = string.Format("{0},{1}", m.Groups[2].Value, m.Groups[4].Value); } else { input = m.Groups[2].Value; } string replacement = formatter.Format(input, timeSpan, formatter); if (string.IsNullOrEmpty(replacement)) { return firstChar; } return string.Format("{0}\\{1}", firstChar, string.Join("\\", replacement.ToCharArray())); }
/// <summary> /// Updates the 'State' of the filesystem associated with the 'FilesystemDelete' <see cref="ServiceLock"/> item /// </summary> /// <param name="item"></param> /// <param name="fs"></param> private static void UpdateState(Model.ServiceLock item, ServerFilesystemInfo fs) { FilesystemState state = null; if (item.State != null && item.State.DocumentElement != null) { //load from datatabase state = XmlUtils.Deserialize <FilesystemState>(item.State.DocumentElement); } if (state == null) { state = new FilesystemState(); } if (fs.AboveHighWatermark) { // we don't want to generate alert if the filesystem is offline or not accessible. if (fs.Online && (fs.Readable || fs.Writeable)) { TimeSpan ALERT_INTERVAL = TimeSpan.FromMinutes(ServiceLockSettings.Default.HighWatermarkAlertInterval); if (state.AboveHighWatermarkTimestamp == null) { state.AboveHighWatermarkTimestamp = Platform.Time; } TimeSpan elapse = (state.LastHighWatermarkAlertTimestamp != null) ? Platform.Time - state.LastHighWatermarkAlertTimestamp.Value : Platform.Time - state.AboveHighWatermarkTimestamp.Value; if (elapse.Duration() >= ALERT_INTERVAL) { ServerPlatform.Alert(AlertCategory.System, AlertLevel.Warning, "Filesystem", AlertTypeCodes.LowResources, null, TimeSpan.Zero, SR.AlertFilesystemAboveHW, fs.Filesystem.Description, TimeSpanFormatter.Format(Platform.Time - state.AboveHighWatermarkTimestamp.Value, true)); state.LastHighWatermarkAlertTimestamp = Platform.Time; } } else { state.AboveHighWatermarkTimestamp = null; state.LastHighWatermarkAlertTimestamp = null; } } else { state.AboveHighWatermarkTimestamp = null; state.LastHighWatermarkAlertTimestamp = null; } XmlDocument stateXml = new XmlDocument(); stateXml.AppendChild(stateXml.ImportNode(XmlUtils.Serialize(state), true)); IPersistentStore store = PersistentStoreRegistry.GetDefaultStore(); using (IUpdateContext ctx = store.OpenUpdateContext(UpdateContextSyncMode.Flush)) { ServiceLockUpdateColumns columns = new ServiceLockUpdateColumns(); columns.State = stateXml; IServiceLockEntityBroker broker = ctx.GetBroker <IServiceLockEntityBroker>(); broker.Update(item.GetKey(), columns); ctx.Commit(); } }
/// <summary> /// Migrates the study to new tier /// </summary> /// <param name="storage"></param> /// <param name="newFilesystem"></param> private void DoMigrateStudy(StudyStorageLocation storage, ServerFilesystemInfo newFilesystem) { Platform.CheckForNullReference(storage, "storage"); Platform.CheckForNullReference(newFilesystem, "newFilesystem"); TierMigrationStatistics stat = new TierMigrationStatistics { StudyInstanceUid = storage.StudyInstanceUid }; stat.ProcessSpeed.Start(); StudyXml studyXml = storage.LoadStudyXml(); stat.StudySize = (ulong)studyXml.GetStudySize(); Platform.Log(LogLevel.Info, "About to migrate study {0} from {1} to {2}", storage.StudyInstanceUid, storage.FilesystemTierEnum, newFilesystem.Filesystem.Description); string newPath = Path.Combine(newFilesystem.Filesystem.FilesystemPath, storage.PartitionFolder); DateTime startTime = Platform.Time; DateTime lastLog = Platform.Time; int fileCounter = 0; ulong bytesCopied = 0; long instanceCountInXml = studyXml.NumberOfStudyRelatedInstances; using (ServerCommandProcessor processor = new ServerCommandProcessor("Migrate Study")) { TierMigrationContext context = new TierMigrationContext { OriginalStudyLocation = storage, Destination = newFilesystem }; // The multiple CreateDirectoryCommands are done so that rollback of the directories being created happens properly if either of the directories already exist. var origFolder = context.OriginalStudyLocation.GetStudyPath(); processor.AddCommand(new CreateDirectoryCommand(newPath)); newPath = Path.Combine(newPath, context.OriginalStudyLocation.StudyFolder); processor.AddCommand(new CreateDirectoryCommand(newPath)); newPath = Path.Combine(newPath, context.OriginalStudyLocation.StudyInstanceUid); // don't create this directory so that it won't be backed up by MoveDirectoryCommand var copyDirCommand = new CopyDirectoryCommand(origFolder, newPath, delegate(string path) { // Update the progress. This is useful if the migration takes long time to complete. FileInfo file = new FileInfo(path); bytesCopied += (ulong)file.Length; fileCounter++; if (file.Extension != null && file.Extension.Equals(ServerPlatform.DicomFileExtension, StringComparison.InvariantCultureIgnoreCase)) { TimeSpan elapsed = Platform.Time - lastLog; TimeSpan totalElapsed = Platform.Time - startTime; double speedInMBPerSecond = 0; if (totalElapsed.TotalSeconds > 0) { speedInMBPerSecond = (bytesCopied / 1024f / 1024f) / totalElapsed.TotalSeconds; } if (elapsed > TimeSpan.FromSeconds(WorkQueueSettings.Instance.TierMigrationProgressUpdateInSeconds)) { #region Log Progress StringBuilder stats = new StringBuilder(); if (instanceCountInXml != 0) { float pct = (float)fileCounter / instanceCountInXml; stats.AppendFormat("{0} files moved [{1:0.0}MB] since {2} ({3:0}% completed). Speed={4:0.00}MB/s", fileCounter, bytesCopied / 1024f / 1024f, startTime, pct * 100, speedInMBPerSecond); } else { stats.AppendFormat("{0} files moved [{1:0.0}MB] since {2}. Speed={3:0.00}MB/s", fileCounter, bytesCopied / 1024f / 1024f, startTime, speedInMBPerSecond); } Platform.Log(LogLevel.Info, "Tier migration for study {0}: {1}", storage.StudyInstanceUid, stats.ToString()); try { using (IUpdateContext ctx = PersistentStoreRegistry.GetDefaultStore().OpenUpdateContext(UpdateContextSyncMode.Flush)) { IWorkQueueEntityBroker broker = ctx.GetBroker <IWorkQueueEntityBroker>(); WorkQueueUpdateColumns parameters = new WorkQueueUpdateColumns { FailureDescription = stats.ToString() }; broker.Update(WorkQueueItem.GetKey(), parameters); ctx.Commit(); } } catch { // can't log the progress so far... just ignore it } finally { lastLog = DateTime.Now; } #endregion } } }); processor.AddCommand(copyDirCommand); DeleteDirectoryCommand delDirCommand = new DeleteDirectoryCommand(origFolder, false) { RequiresRollback = false }; processor.AddCommand(delDirCommand); TierMigrateDatabaseUpdateCommand updateDbCommand = new TierMigrateDatabaseUpdateCommand(context); processor.AddCommand(updateDbCommand); Platform.Log(LogLevel.Info, "Start migrating study {0}.. expecting {1} to be moved", storage.StudyInstanceUid, ByteCountFormatter.Format(stat.StudySize)); if (!processor.Execute()) { if (processor.FailureException != null) { throw processor.FailureException; } throw new ApplicationException(processor.FailureReason); } stat.DBUpdate = updateDbCommand.Statistics; stat.CopyFiles = copyDirCommand.CopySpeed; stat.DeleteDirTime = delDirCommand.Statistics; } stat.ProcessSpeed.SetData(bytesCopied); stat.ProcessSpeed.End(); Platform.Log(LogLevel.Info, "Successfully migrated study {0} from {1} to {2} in {3} [ {4} files, {5} @ {6}, DB Update={7}, Remove Dir={8}]", storage.StudyInstanceUid, storage.FilesystemTierEnum, newFilesystem.Filesystem.FilesystemTierEnum, TimeSpanFormatter.Format(stat.ProcessSpeed.ElapsedTime), fileCounter, ByteCountFormatter.Format(bytesCopied), stat.CopyFiles.FormattedValue, stat.DBUpdate.FormattedValue, stat.DeleteDirTime.FormattedValue); string originalPath = storage.GetStudyPath(); if (Directory.Exists(storage.GetStudyPath())) { Platform.Log(LogLevel.Info, "Original study folder could not be deleted. It must be cleaned up manually: {0}", originalPath); ServerPlatform.Alert(AlertCategory.Application, AlertLevel.Warning, WorkQueueItem.WorkQueueTypeEnum.ToString(), 1000, GetWorkQueueContextData(WorkQueueItem), TimeSpan.Zero, "Study has been migrated to a new tier. Original study folder must be cleaned up manually: {0}", originalPath); } UpdateAverageStatistics(stat); }
private static void RetrieveImages(string serverAE, string studyPath) { Console.WriteLine("server={0}", serverAE); string baseUri = String.Format("http://{0}:{1}", serverHost, serverPort); StreamingClient client = new StreamingClient(new Uri(baseUri)); int totalFrameCount = 0; DirectoryInfo directoryInfo = new DirectoryInfo(studyPath); string studyUid = directoryInfo.Name; RateStatistics frameRate = new RateStatistics("Speed", "frame"); RateStatistics speed = new RateStatistics("Speed", RateType.BYTES); AverageRateStatistics averageSpeed = new AverageRateStatistics(RateType.BYTES); ByteCountStatistics totalSize = new ByteCountStatistics("Size"); frameRate.Start(); speed.Start(); Console.WriteLine("\n------------------------------------------------------------------------------------------------------------------------"); string[] seriesDirs = Directory.GetDirectories(studyPath); foreach (string seriesPath in seriesDirs) { DirectoryInfo dirInfo = new DirectoryInfo(seriesPath); string seriesUid = dirInfo.Name; string[] objectUidPath = Directory.GetFiles(seriesPath, "*.dcm"); foreach (string uidPath in objectUidPath) { FileInfo fileInfo = new FileInfo(uidPath); string uid = fileInfo.Name.Replace(".dcm", ""); Console.Write("{0,-64}... ", uid); try { Stream imageStream; StreamingResultMetaData imageMetaData; FrameStreamingResultMetaData frameMetaData; switch (type) { case ContentTypes.Dicom: imageStream = client.RetrieveImage(serverAE, studyUid, seriesUid, uid, out imageMetaData); totalFrameCount++; averageSpeed.AddSample(imageMetaData.Speed); totalSize.Value += (ulong)imageMetaData.ContentLength; Console.WriteLine("1 dicom sop [{0,10}] in {1,12}\t[mime={2}]", ByteCountFormatter.Format((ulong)imageStream.Length), TimeSpanFormatter.Format(imageMetaData.Speed.ElapsedTime), imageMetaData.ResponseMimeType); break; case ContentTypes.RawPixel: TimeSpanStatistics elapsedTime = new TimeSpanStatistics(); elapsedTime.Start(); ulong instanceSize = 0; int frameCount = 0; do { RetrievePixelDataResult result = client.RetrievePixelData(serverAE, studyUid, seriesUid, uid, frameCount); frameMetaData = result.MetaData; totalFrameCount++; frameCount++; averageSpeed.AddSample(frameMetaData.Speed); totalSize.Value += (ulong)frameMetaData.ContentLength; instanceSize += (ulong)frameMetaData.ContentLength; } while (!frameMetaData.IsLast); elapsedTime.End(); Console.WriteLine("{0,3} frame(s) [{1,10}] in {2,12}\t[mime={3}]", frameCount, ByteCountFormatter.Format(instanceSize), elapsedTime.FormattedValue, frameMetaData.ResponseMimeType); break; default: imageStream = client.RetrieveImage(serverAE, studyUid, seriesUid, uid, out imageMetaData); totalFrameCount++; averageSpeed.AddSample(imageMetaData.Speed); totalSize.Value += (ulong)imageMetaData.ContentLength; Console.WriteLine("1 object [{0,10}] in {1,12}\t[mime={2}]", ByteCountFormatter.Format((ulong)imageStream.Length), TimeSpanFormatter.Format(imageMetaData.Speed.ElapsedTime), imageMetaData.ResponseMimeType); break; } } catch (Exception ex) { if (ex is WebException) { HttpWebResponse rsp = ((ex as WebException).Response as HttpWebResponse); string msg = String.Format("Error: {0} : {1}", rsp.StatusCode, HttpUtility.HtmlDecode(rsp.StatusDescription) ); Console.WriteLine(msg); } else { Console.WriteLine(ex.Message); } } } } frameRate.SetData(totalFrameCount); frameRate.End(); speed.SetData(totalSize.Value); speed.End(); Console.WriteLine("\nTotal {0,3} image(s)/frame(s) [{1,10}] in {2,12} ==> [ Speed: {3,12} or {4,12}]", totalFrameCount, totalSize.FormattedValue, TimeSpanFormatter.Format(frameRate.ElapsedTime), frameRate.FormattedValue, speed.FormattedValue ); }