/// <summary> /// Inserts a <see cref="StudyIntegrityQueue"/> entry for manual reconciliation. /// </summary> /// <param name="file">The DICOM file that needs to be reconciled.</param> /// <param name="reason">The type of <see cref="StudyIntegrityQueue"/> entry to be inserted.</param> /// <param name="uid">A UID to delete on insert.</param> /// <remarks> /// A copy of the DICOM file will be stored in a special folder allocated for /// reconciliation purpose. The caller is responsible for managing the original copy. /// </remarks> public void ScheduleReconcile(DicomFile file, StudyIntegrityReasonEnum reason, WorkQueueUid uid) { Platform.CheckForNullReference(_context.StudyLocation, "_context.StudyLocation"); Platform.Log(LogLevel.Info, "Scheduling new manual reconciliation for SOP {0}", file.MediaStorageSopInstanceUid); ServerFilesystemInfo fs = FilesystemMonitor.Instance.GetFilesystemInfo(_context.StudyLocation.FilesystemKey); Platform.CheckForNullReference(fs, "fs"); ReconcileStorage reconcileStorage = new ReconcileStorage(_context.StudyLocation, _context.Group); using (ServerCommandProcessor processor = new ServerCommandProcessor("Schedule Manual Reconciliation")) { string path = reconcileStorage.GetSopInstancePath(file.DataSet[DicomTags.SopInstanceUid].ToString()); DirectoryInfo dir = new DirectoryInfo(path); if (dir.Parent != null) { CreateDirectoryCommand mkdir = new CreateDirectoryCommand(dir.Parent.FullName); processor.AddCommand(mkdir); } SaveDicomFileCommand saveFileCommand = new SaveDicomFileCommand(path, file, true); processor.AddCommand(saveFileCommand); InsertSIQCommand updateStudyCommand = new InsertSIQCommand(_context.StudyLocation, reason, file, _context.Group, reconcileStorage); processor.AddCommand(updateStudyCommand); if (uid != null) { processor.AddCommand(new DeleteWorkQueueUidCommand(uid)); } if (processor.Execute() == false) { throw new ApplicationException(String.Format("Unable to schedule image reconcilation : {0}", processor.FailureReason), processor.FailureException); } } }
protected void ProcessFile(Model.WorkQueue item, WorkQueueUid sop, string path, StudyXml studyXml, IDicomCodecFactory theCodecFactory) { DicomFile file = null; _instanceStats = new CompressInstanceStatistics(); _instanceStats.ProcessTime.Start(); // Use the command processor for rollback capabilities. using (ServerCommandProcessor processor = new ServerCommandProcessor("Processing WorkQueue Compress DICOM File")) { string modality = String.Empty; try { file = new DicomFile(path); _instanceStats.FileLoadTime.Start(); file.Load(DicomReadOptions.StorePixelDataReferences | DicomReadOptions.Default); _instanceStats.FileLoadTime.End(); modality = file.DataSet[DicomTags.Modality].GetString(0, String.Empty); FileInfo fileInfo = new FileInfo(path); _instanceStats.FileSize = (ulong)fileInfo.Length; // Get the Patients Name for processing purposes. String patientsName = file.DataSet[DicomTags.PatientsName].GetString(0, ""); if (file.TransferSyntax.Equals(theCodecFactory.CodecTransferSyntax)) { // Delete the WorkQueueUid item processor.AddCommand(new DeleteWorkQueueUidCommand(sop)); // Do the actual processing if (!processor.Execute()) { Platform.Log(LogLevel.Warn, "Failure deleteing WorkQueueUid: {0} for SOP: {1}", processor.Description, file.MediaStorageSopInstanceUid); Platform.Log(LogLevel.Warn, "Compression file that failed: {0}", file.Filename); } else { Platform.Log(LogLevel.Warn, "Skip compressing SOP {0}. Its current transfer syntax is {1}", file.MediaStorageSopInstanceUid, file.TransferSyntax.Name); } } else { IDicomCodec codec = theCodecFactory.GetDicomCodec(); // Create a context for applying actions from the rules engine var context = new ServerActionContext(file, StorageLocation.FilesystemKey, ServerPartition, item.StudyStorageKey, processor); var parms = theCodecFactory.GetCodecParameters(item.Data); var compressCommand = new DicomCompressCommand(context.Message, theCodecFactory.CodecTransferSyntax, codec, parms); processor.AddCommand(compressCommand); var save = new SaveDicomFileCommand(file.Filename, file, false); processor.AddCommand(save); // Update the StudyStream object, must be done after compression // and after the compressed image has been successfully saved var insertStudyXmlCommand = new UpdateStudyXmlCommand(file, studyXml, StorageLocation); processor.AddCommand(insertStudyXmlCommand); // Delete the WorkQueueUid item processor.AddCommand(new DeleteWorkQueueUidCommand(sop)); // Do the actual processing if (!processor.Execute()) { EventManager.FireEvent(this, new FailedUpdateSopEventArgs { File = file, ServerPartitionEntry = context.ServerPartition, WorkQueueUidEntry = sop, WorkQueueEntry = WorkQueueItem, FileLength = (ulong)insertStudyXmlCommand.FileSize, FailureMessage = processor.FailureReason }); _instanceStats.CompressTime.Add(compressCommand.CompressTime); Platform.Log(LogLevel.Error, "Failure compressing command {0} for SOP: {1}", processor.Description, file.MediaStorageSopInstanceUid); Platform.Log(LogLevel.Error, "Compression file that failed: {0}", file.Filename); throw new ApplicationException( "Unexpected failure (" + processor.FailureReason + ") executing command for SOP: " + file.MediaStorageSopInstanceUid, processor.FailureException); } _instanceStats.CompressTime.Add(compressCommand.CompressTime); Platform.Log(ServerPlatform.InstanceLogLevel, "Compress SOP: {0} for Patient {1}", file.MediaStorageSopInstanceUid, patientsName); EventManager.FireEvent(this, new UpdateSopEventArgs { File = file, ServerPartitionEntry = context.ServerPartition, WorkQueueUidEntry = sop, WorkQueueEntry = WorkQueueItem, FileLength = (ulong)insertStudyXmlCommand.FileSize }); } } catch (Exception e) { EventManager.FireEvent(this, new FailedUpdateSopEventArgs { File = file, ServerPartitionEntry = ServerPartition, WorkQueueUidEntry = sop, WorkQueueEntry = WorkQueueItem, FileLength = (ulong)new FileInfo(path).Length, FailureMessage = processor.FailureReason }); Platform.Log(LogLevel.Error, e, "Unexpected exception when {0}. Rolling back operation.", processor.Description); processor.Rollback(); throw; } finally { _instanceStats.ProcessTime.End(); _studyStats.AddSubStats(_instanceStats); _studyStats.StudyInstanceUid = StorageLocation.StudyInstanceUid; if (String.IsNullOrEmpty(modality) == false) { _studyStats.Modality = modality; } // Update the statistics _studyStats.NumInstances++; } } }