/// <summary>
        /// Gets the <see cref="StudyStorageLocation"/> for the study associated with the specified <see cref="WorkQueue"/> item.
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public static StudyStorageLocation GetLoadStorageLocation(WorkQueue item)
        {

			var select = HttpContext.Current.GetSharedPersistentContext().GetBroker<IQueryStudyStorageLocation>();

            var parms = new StudyStorageLocationQueryParameters();
            parms.StudyStorageKey = item.StudyStorageKey;

            IList<StudyStorageLocation> storages = select.Find(parms);

            if (storages == null || storages.Count == 0)
            {
                Platform.Log(LogLevel.Error, "Unable to find storage location for WorkQueue item: {0}",
                             item.Key.ToString());
                throw new ApplicationException("Unable to find storage location for WorkQueue item.");
            }

            if (storages.Count > 1)
            {
                Platform.Log(LogLevel.Warn,
                             "WorkQueueController:LoadWritableStorageLocation: multiple study storage found for work queue item {0}",
                             item.Key.Key);
            }

            return storages[0];

        }
Example #2
0
        protected override void OnExecute(CommandProcessor theProcessor, IUpdateContext updateContext)
        {
            var insert = updateContext.GetBroker<IInsertWorkQueue>();
            var parms = new InsertWorkQueueParameters
                            {
                                WorkQueueTypeEnum = WorkQueueTypeEnum.StudyProcess,
                                StudyStorageKey = _storageLocation.GetKey(),
                                ServerPartitionKey = _storageLocation.ServerPartitionKey,
                                SeriesInstanceUid = _message.DataSet[DicomTags.SeriesInstanceUid].GetString(0, String.Empty),
                                SopInstanceUid = _message.DataSet[DicomTags.SopInstanceUid].GetString(0, String.Empty),
                                ScheduledTime = Platform.Time,
                                WorkQueueGroupID = _uidGroupId
                            };

        	if (_duplicate)
            {
                parms.Duplicate = _duplicate;
                parms.Extension = _extension;
                parms.UidGroupID = _uidGroupId;
            }

            _insertedWorkQueue = insert.FindOne(parms);

            if (_insertedWorkQueue == null)
                throw new ApplicationException("UpdateWorkQueueCommand failed");
        }
Example #3
0
        /// <summary>
        /// Gets the <see cref="StudyStorageLocation"/> for the study associated with the specified <see cref="WorkQueue"/> item.
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        static public String GetLoadDuplicateStorageLocation(WorkQueue item)
        {
            XmlDocument document = item.Data;
            
           
            return document.ToString();

        }
        public WorkQueueProcessDuplicateSop(WorkQueue workQueue)
        {
            SetKey(workQueue.GetKey());
            Data                  = workQueue.Data;
            ExpirationTime        = workQueue.ExpirationTime;
            FailureCount          = workQueue.FailureCount;
            FailureDescription    = workQueue.FailureDescription;
            InsertTime            = workQueue.InsertTime;
            ProcessorID           = workQueue.ProcessorID;
            ScheduledTime         = workQueue.ScheduledTime;
            ServerPartitionKey    = workQueue.ServerPartitionKey;
            StudyHistoryKey       = workQueue.StudyHistoryKey;
            StudyStorageKey       = workQueue.StudyStorageKey;
            WorkQueuePriorityEnum = workQueue.WorkQueuePriorityEnum;
            WorkQueueStatusEnum   = workQueue.WorkQueueStatusEnum;
            WorkQueueTypeEnum     = workQueue.WorkQueueTypeEnum;

            _queueData = (ProcessDuplicateQueueEntryQueueData)_serializer.Deserialize(new XmlNodeReader(workQueue.Data.DocumentElement));
        }
        public WorkQueueProcessDuplicateSop(WorkQueue workQueue)
        {
            SetKey(workQueue.GetKey());
            Data = workQueue.Data;
            ExpirationTime = workQueue.ExpirationTime;
            FailureCount = workQueue.FailureCount;
            FailureDescription = workQueue.FailureDescription;
            InsertTime = workQueue.InsertTime;
            ProcessorID = workQueue.ProcessorID;
            ScheduledTime = workQueue.ScheduledTime;
            ServerPartitionKey = workQueue.ServerPartitionKey;
            StudyHistoryKey = workQueue.StudyHistoryKey;
            StudyStorageKey = workQueue.StudyStorageKey;
            WorkQueuePriorityEnum = workQueue.WorkQueuePriorityEnum;
            WorkQueueStatusEnum = workQueue.WorkQueueStatusEnum;
            WorkQueueTypeEnum = workQueue.WorkQueueTypeEnum;

            _queueData = (ProcessDuplicateQueueEntryQueueData)_serializer.Deserialize(new XmlNodeReader(workQueue.Data.DocumentElement));

        }
Example #6
0
		/// <summary>
		/// Constructor.
		/// </summary>
		/// <param name="thePartition"></param>
		/// <param name="location"></param>
		/// <param name="thePatient"></param>
		/// <param name="theStudy"></param>
		public StudyEditor(ServerPartition thePartition, StudyStorageLocation location, Patient thePatient, Study theStudy, WorkQueue workQueue)
		{
			FailureReason = string.Empty;
			Platform.CheckForNullReference(thePartition, "thePartition");
			Platform.CheckForNullReference(location, "location");
			Platform.CheckForNullReference(thePatient, "thePatient");
			Platform.CheckForNullReference(theStudy, "theStudy");

			ServerPartition = thePartition;
			StorageLocation = location;
			
            Patient = thePatient;
            Study = theStudy;
			_workQueue = workQueue;

            // Scrub for invalid characters that may cause a failure when the Xml is generated for the history
		    Patient.PatientId = XmlUtils.XmlCharacterScrub(Patient.PatientId);
            Patient.PatientsName = XmlUtils.XmlCharacterScrub(Patient.PatientsName);
            
            Study.StudyDescription = XmlUtils.XmlCharacterScrub(Study.StudyDescription);
            Study.ReferringPhysiciansName = XmlUtils.XmlCharacterScrub(Study.ReferringPhysiciansName);
            Study.PatientId = XmlUtils.XmlCharacterScrub(Study.PatientId);
            Study.PatientsName = XmlUtils.XmlCharacterScrub(Study.PatientsName);            
		}
Example #7
0
 public static WorkQueue Insert(IUpdateContext update, WorkQueue entity)
 {
     var broker = update.GetBroker<IWorkQueueEntityBroker>();
     var updateColumns = new WorkQueueUpdateColumns();
     updateColumns.ServerPartitionKey = entity.ServerPartitionKey;
     updateColumns.StudyStorageKey = entity.StudyStorageKey;
     updateColumns.WorkQueueTypeEnum = entity.WorkQueueTypeEnum;
     updateColumns.WorkQueueStatusEnum = entity.WorkQueueStatusEnum;
     updateColumns.WorkQueuePriorityEnum = entity.WorkQueuePriorityEnum;
     updateColumns.FailureCount = entity.FailureCount;
     updateColumns.ScheduledTime = entity.ScheduledTime;
     updateColumns.InsertTime = entity.InsertTime;
     updateColumns.LastUpdatedTime = entity.LastUpdatedTime;
     updateColumns.FailureDescription = entity.FailureDescription;
     updateColumns.Data = entity.Data;
     updateColumns.ExternalRequestQueueKey = entity.ExternalRequestQueueKey;
     updateColumns.ProcessorID = entity.ProcessorID;
     updateColumns.GroupID = entity.GroupID;
     updateColumns.ExpirationTime = entity.ExpirationTime;
     updateColumns.DeviceKey = entity.DeviceKey;
     updateColumns.StudyHistoryKey = entity.StudyHistoryKey;
     WorkQueue newEntity = broker.Insert(updateColumns);
     return newEntity;
 }
Example #8
0
 static public WorkQueue Insert(IUpdateContext update, WorkQueue entity)
 {
     var broker = update.GetBroker<IWorkQueueEntityBroker>();
     var updateColumns = new WorkQueueUpdateColumns();
     updateColumns.ServerPartitionKey = entity.ServerPartitionKey;
     updateColumns.StudyStorageKey = entity.StudyStorageKey;
     updateColumns.WorkQueueTypeEnum = entity.WorkQueueTypeEnum;
     updateColumns.WorkQueueStatusEnum = entity.WorkQueueStatusEnum;
     updateColumns.WorkQueuePriorityEnum = entity.WorkQueuePriorityEnum;
     updateColumns.FailureCount = entity.FailureCount;
     updateColumns.ScheduledTime = entity.ScheduledTime;
     updateColumns.InsertTime = entity.InsertTime;
     updateColumns.LastUpdatedTime = entity.LastUpdatedTime;
     updateColumns.FailureDescription = entity.FailureDescription;
     updateColumns.Data = entity.Data;
     updateColumns.ExternalRequestQueueKey = entity.ExternalRequestQueueKey;
     updateColumns.ProcessorID = entity.ProcessorID;
     updateColumns.GroupID = entity.GroupID;
     updateColumns.ExpirationTime = entity.ExpirationTime;
     updateColumns.DeviceKey = entity.DeviceKey;
     updateColumns.StudyHistoryKey = entity.StudyHistoryKey;
     WorkQueue newEntity = broker.Insert(updateColumns);
     return newEntity;
 }
 public StudyProcessorContext(StudyStorageLocation storageLocation)
 {
     Platform.CheckForNullReference(storageLocation, "storageLocation");
     _storageLocation = storageLocation;
     _workQueue = null;
 }
        protected override void OnExecute(CommandProcessor theProcessor, IUpdateContext updateContext)
        {
            var insert = updateContext.GetBroker<IInsertWorkQueue>();
            var parms = new InsertWorkQueueParameters
                            {
                                WorkQueueTypeEnum = WorkQueueTypeEnum.StudyProcess,
                                StudyStorageKey = _storageLocation.GetKey(),
                                ServerPartitionKey = _storageLocation.ServerPartitionKey,
                                SeriesInstanceUid = _message.DataSet[DicomTags.SeriesInstanceUid].GetString(0, String.Empty),
                                SopInstanceUid = _message.DataSet[DicomTags.SopInstanceUid].GetString(0, String.Empty),
                                ScheduledTime = Platform.Time,
                                
                            };

	        if (_priority != null)
		        parms.WorkQueuePriorityEnum = _priority;

            if (_data != null)
            {
                parms.WorkQueueData = ImageServerSerializer.SerializeWorkQueueDataToXmlDocument(_data);
            }
            if (_request != null)
            {
                parms.ExternalRequestQueueKey = _request.Key;
            }
            if (_uidData != null)
            {
                parms.WorkQueueUidData = _uidData;
                parms.Extension = _uidData.Extension;
                parms.UidGroupID = _uidData.GroupId;
                parms.WorkQueueGroupID = _uidData.GroupId;
            }

            if (_duplicate)
            {
                parms.Duplicate = _duplicate;
            }

            _insertedWorkQueue = insert.FindOne(parms);

            if (_insertedWorkQueue == null)
                throw new ApplicationException("UpdateWorkQueueCommand failed");
        }
Example #11
0
 static public WorkQueue Insert(WorkQueue entity)
 {
     using (var update = PersistentStoreRegistry.GetDefaultStore().OpenUpdateContext(UpdateContextSyncMode.Flush))
     {
         WorkQueue newEntity = Insert(update, entity);
         update.Commit();
         return newEntity;
     }
 }
 static public bool CanReprocess(WorkQueue item)
 {
     return
         item.WorkQueueStatusEnum == WorkQueueStatusEnum.Failed && item.WorkQueueTypeEnum == WorkQueueTypeEnum.StudyProcess;
 }
		public bool ReprocessWorkQueueItem(WorkQueue item)
		{
            // #10620: Get a list of remaining WorkQueueUids which need to be reprocess
            // Note: currently only WorkQueueUIDs in failed StudyProcess will be reprocessed
            var remainingWorkQueueUidPaths = item.GetAllWorkQueueUidPaths();

            IPersistentStore store = PersistentStoreRegistry.GetDefaultStore();
			using (IUpdateContext ctx = store.OpenUpdateContext(UpdateContextSyncMode.Flush))
			{
				// delete current workqueue
				IWorkQueueUidEntityBroker uidBroker = ctx.GetBroker<IWorkQueueUidEntityBroker>();
				WorkQueueUidSelectCriteria criteria = new WorkQueueUidSelectCriteria();
				criteria.WorkQueueKey.EqualTo(item.GetKey());

				if (uidBroker.Delete(criteria) >= 0)
				{
					IWorkQueueEntityBroker workQueueBroker = ctx.GetBroker<IWorkQueueEntityBroker>();
					if (workQueueBroker.Delete(item.GetKey()))
					{
					    IList<StudyStorageLocation> locations = item.LoadStudyLocations(ctx);
                        if (locations!=null && locations.Count>0)
                        {
                            StudyReprocessor reprocessor = new StudyReprocessor();
                            String reason = String.Format("User reprocesses failed {0}", item.WorkQueueTypeEnum);
                            WorkQueue reprocessEntry = reprocessor.ReprocessStudy(ctx, reason, locations[0], remainingWorkQueueUidPaths, Platform.Time);
							if (reprocessEntry!=null)
								ctx.Commit();
                        	return reprocessEntry!=null;
                        }	
					}
				}
			}
			return false;
		}
        /// <summary>
        /// Returns a value indicating whether the specified <see cref="WorkQueue"/> can be manually reset.
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        static public bool CanReset(WorkQueue item)
        {
            if (item == null)
                return false;

            return
                /* failed item */
                item.WorkQueueStatusEnum == WorkQueueStatusEnum.Failed
                /* nobody claimed it */
                || (item.WorkQueueStatusEnum == WorkQueueStatusEnum.InProgress && String.IsNullOrEmpty(item.ProcessorID))
                /* allow reset "stuck" items (except items that are InProgress)*/
                || (!item.WorkQueueStatusEnum.Equals(WorkQueueStatusEnum.InProgress) && !WorkQueueHelper.IsActiveWorkQueue(item));

        }
        /// <summary>
        /// Returns a value indicating whether the specified <see cref="WorkQueue"/> can be manually deleted from the queue.
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        static public bool CanDelete(WorkQueue item)
        {
            if (item == null)
                return false;

            return
                /* failed item */
                item.WorkQueueStatusEnum == WorkQueueStatusEnum.Failed
                /* completed item */
                || (item.WorkQueueStatusEnum == WorkQueueStatusEnum.Completed)
                /* nobody claimed it */
                ||
                (item.WorkQueueStatusEnum == WorkQueueStatusEnum.InProgress &&
                 String.IsNullOrEmpty(item.ProcessorID))
                // allow deletes of some pending entries
                ||
                (item.WorkQueueStatusEnum != WorkQueueStatusEnum.InProgress &&
                 item.WorkQueueTypeEnum == WorkQueueTypeEnum.WebMoveStudy)
                ||
                (item.WorkQueueStatusEnum != WorkQueueStatusEnum.InProgress &&
                 item.WorkQueueTypeEnum == WorkQueueTypeEnum.WebEditStudy)
                ||
                (item.WorkQueueStatusEnum != WorkQueueStatusEnum.InProgress &&
                 item.WorkQueueTypeEnum == WorkQueueTypeEnum.AutoRoute)
                ||
                (item.WorkQueueStatusEnum != WorkQueueStatusEnum.InProgress &&
                 item.WorkQueueTypeEnum == WorkQueueTypeEnum.WebDeleteStudy)

				/* allow deletes of "stuck" items (except items that are InProgress)*/
                || (!item.WorkQueueStatusEnum.Equals(WorkQueueStatusEnum.InProgress) && !WorkQueueHelper.IsActiveWorkQueue(item));
		}
Example #16
0
        /// <summary>
        /// Returns a boolean indicating whether the entry is still "active"
        /// </summary>
        /// <remarks>
        /// </remarks>
        static public bool IsActiveWorkQueue(WorkQueue item)
        {
            // The following code assumes InactiveWorkQueueMinTime is set appropirately

            if (item.WorkQueueStatusEnum.Equals(WorkQueueStatusEnum.Failed))
                return false;

            if (item.WorkQueueStatusEnum.Equals(WorkQueueStatusEnum.Pending) ||
                item.WorkQueueStatusEnum.Equals(WorkQueueStatusEnum.Idle))
            {
                // Assuming that if the entry is picked up and rescheduled recently (the ScheduledTime would have been updated), 
                // the item is inactive if its ScheduledTime still indicated it was scheduled long time ago.
                // Note: this logic still works if the entry has never been processed (new). It will be
                // considered as "inactive" if it was scheduled long time ago and had never been updated.

                DateTime lastActiveTime = item.LastUpdatedTime.GetValueOrDefault(item.ScheduledTime);
	            return (Platform.Time - lastActiveTime < Settings.Default.InactiveWorkQueueMinTime);
            }
            else if (item.WorkQueueStatusEnum.Equals(WorkQueueStatusEnum.InProgress))
            {
                if (String.IsNullOrEmpty(item.ProcessorID))
                {
                    // This is a special case, the item is not assigned but is set to InProgress. 
                    // It's definitely stuck cause it won't be picked up by any servers.
                    return false;
                }
                // TODO: Need more elaborate logic to detect if it's stuck when the status is InProgress.
                // Ideally, we can assume item is stuck if it has not been updated for a while. 
                // Howerver, some operations were designed to process everything in a single run 
                // instead of batches.One example is the StudyProcess, research studies may take days to process 
                // and the item stays in "InProgress" for the entire period without any update 
                // (eventhough the WorkQueueUid records are removed)
                // For now, we assume it's stucked if it is not updated for long time.
                if (item.ScheduledTime < Platform.Time - Settings.Default.InactiveWorkQueueMinTime)
                    return false;
            }

            return true;
        }
        /// <summary>
        /// Returns a value indicating whether the specified <see cref="WorkQueue"/> can be manually rescheduled.
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        static public bool CanReschedule(WorkQueue item)
        {
            if (item == null)
                return false;

            return
                // it's pending
                item.WorkQueueStatusEnum == WorkQueueStatusEnum.Pending
                // it's idle
                || item.WorkQueueStatusEnum == WorkQueueStatusEnum.Idle;
                
        }
Example #18
0
 public static WorkQueue Load(IPersistenceContext read, ServerEntityKey key)
 {
     var broker = read.GetBroker<IWorkQueueEntityBroker>();
     WorkQueue theObject = broker.Load(key);
     return theObject;
 }
Example #19
0
 /// <summary>
 /// Helper method to return the path to the folder containing the duplicate images (in the Reconcile folder)
 /// </summary>
 /// <param name="storageLocation"></param>
 /// <param name="queueItem"></param>
 /// <returns></returns>
 public static string GetDuplicateGroupPath(StudyStorageLocation storageLocation, WorkQueue queueItem)
 {
     string path = Path.Combine(storageLocation.FilesystemPath, storageLocation.PartitionFolder);
     path = Path.Combine(path, ServerPlatform.ReconcileStorageFolder);
     path = Path.Combine(path, queueItem.GroupID);
     return path;
 }
		public UpdateStudyCommand(ServerPartition partition, 
		                          StudyStorageLocation studyLocation,
		                          IList<BaseImageLevelUpdateCommand> imageLevelCommands,
								  ServerRuleApplyTimeEnum applyTime,
								  WorkQueue workQueue) 
			: base("Update existing study")
		{
			_partition = partition;
			_oldStudyLocation = studyLocation;
			_commands = imageLevelCommands;
			_workQueue = workQueue;
			_statistics = new UpdateStudyStatistics(_oldStudyLocation.StudyInstanceUid);
			// Load the engine for editing rules.
			_rulesEngine = new ServerRulesEngine(applyTime, _partition.Key);
			if (applyTime.Equals(ServerRuleApplyTimeEnum.SopProcessed))
				_rulesEngine.AddIncludeType(ServerRuleTypeEnum.AutoRoute);
			_rulesEngine.Load();
		}
		/// <summary>
		/// Create Duplicate SIQ Entry
		/// </summary>
		/// <param name="file"></param>
		/// <param name="location"></param>
		/// <param name="sourcePath"></param>
		/// <param name="queue"></param>
		/// <param name="uid"></param>
		/// <param name="data"></param>
		public static void CreateDuplicateSIQEntry(DicomFile file, StudyStorageLocation location, string sourcePath,
		                                           WorkQueue queue, WorkQueueUid uid, StudyProcessWorkQueueData data)
		{
			Platform.Log(LogLevel.Info, "Creating Work Queue Entry for duplicate...");
			String uidGroup = queue.GroupID ?? queue.GetKey().Key.ToString();
			using (var commandProcessor = new ServerCommandProcessor("Insert Work Queue entry for duplicate"))
			{
				commandProcessor.AddCommand(new FileDeleteCommand(sourcePath, true));

				var sopProcessingContext = new SopInstanceProcessorContext(commandProcessor, location, uidGroup);
				DicomProcessingResult result = Process(sopProcessingContext, file, data);
				if (!result.Successful)
				{
					FailUid(uid, true);
					return;
				}

				commandProcessor.AddCommand(new DeleteWorkQueueUidCommand(uid));

				if (!commandProcessor.Execute())
				{
					Platform.Log(LogLevel.Error, "Unexpected error when creating duplicate study integrity queue entry: {0}",
					             commandProcessor.FailureReason);
					FailUid(uid, true);
				}
			}
		}
Example #22
0
		/// <summary>
		/// Constructs an instance of <see cref="WorkQueueSummary"/> based on a <see cref="WorkQueue"/> object.
		/// </summary>
		/// <param name="item"></param>
		/// <returns></returns>
		/// <remark>
		/// 
		/// </remark>
		private WorkQueueSummary CreateWorkQueueSummary(WorkQueue item)
		{
			WorkQueueSummary summary = new WorkQueueSummary
			                           	{
			                           		TheWorkQueueItem = item,
			                           		ThePartition = Partition
			                           	};

			// Fetch the patient info:
			StudyStorageAdaptor ssAdaptor = new StudyStorageAdaptor();
			StudyStorage storages = ssAdaptor.Get(item.StudyStorageKey);
			if (storages == null)
			{
				summary.PatientId = "N/A";
				summary.PatientsName = "N/A";
				return summary;
			}
			StudyAdaptor studyAdaptor = new StudyAdaptor();
			StudySelectCriteria studycriteria = new StudySelectCriteria();
			studycriteria.StudyInstanceUid.EqualTo(storages.StudyInstanceUid);
			studycriteria.ServerPartitionKey.EqualTo(item.ServerPartitionKey);
			IList<Study> studyList = studyAdaptor.Get(studycriteria);

			if (studyList == null || studyList.Count == 0)
			{
				summary.PatientId = "N/A";
				summary.PatientsName = "N/A";
			}
			else
			{
				summary.PatientId = studyList[0].PatientId;
				summary.PatientsName = studyList[0].PatientsName;
			}

			if (item.WorkQueueTypeEnum == WorkQueueTypeEnum.WebMoveStudy
			    || item.WorkQueueTypeEnum == WorkQueueTypeEnum.AutoRoute)
			{
				DeviceDataAdapter deviceAdaptor = new DeviceDataAdapter();
				Device dest = deviceAdaptor.Get(item.DeviceKey);

				summary.Notes = String.Format("Destination AE : {0}", dest.AeTitle);

				if (item.FailureDescription != null)
				{
					summary.FullDescription = String.Format("{0}, {1}", summary.Notes, item.FailureDescription);   //Set the FullDescription for the Tooltip in the GUI
					summary.Notes = summary.FullDescription.Length > 60 
						? summary.FullDescription.Substring(0, 60) 
						: summary.FullDescription;
				}
			}
			else if (item.FailureDescription != null)
			{
				// This used to only be shown when the status was "Failed" for a 
				// queue entry.  We now show it any time there's 
				if (item.FailureDescription.Length > 60)
				{
					summary.Notes = item.FailureDescription.Substring(0, 60);
					summary.Notes += " ...";
				    summary.FullDescription = item.FailureDescription;  //Set the FullDescription for the Tooltip in the GUI
				}
				else
					summary.Notes = item.FailureDescription;
			}

            summary.RequiresAttention = item.WorkQueueStatusEnum.Equals(WorkQueueStatusEnum.Failed) || !ServerPlatform.IsActiveWorkQueue(item);
			return summary;
		}