Пример #1
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="reason"></param>
 /// <param name="key"></param>
 /// <exception cref="InvalidStudyStateOperationException">Study is in a state that reprocessing is not allowed</exception>
 public void ReprocessStudy(String reason, ServerEntityKey key)
 {
     StudyStorageAdaptor adaptor = new StudyStorageAdaptor();
     StudyStorage storage = adaptor.Get(key);
     StudyStorageLocation storageLocation = StudyStorageLocation.FindStorageLocations(storage)[0];
     StudyReprocessor reprocessor = new StudyReprocessor();
     reprocessor.ReprocessStudy(reason, storageLocation, Platform.Time);
 }
Пример #2
0
		/// <summary>
		/// Do the actual rebuild.  On error, will attempt to reprocess the study.
		/// </summary>
		public void RebuildXml()
		{
			string rootStudyPath = _location.GetStudyPath();

			try
			{
				using (ServerCommandProcessor processor = new ServerCommandProcessor("Rebuild XML"))
				{
				    var command = new RebuildStudyXmlCommand(_location.StudyInstanceUid, rootStudyPath);
					processor.AddCommand(command);

                    var updateCommand = new UpdateStudySizeInDBCommand(_location, command);
                    processor.AddCommand(updateCommand);

					if (!processor.Execute())
					{
						throw new ApplicationException(processor.FailureReason, processor.FailureException);
					}

                    Study theStudy = _location.Study;
                    if (theStudy.NumberOfStudyRelatedInstances != command.StudyXml.NumberOfStudyRelatedInstances)
                    {
                        // We rebuilt, but the counts don't match.
                        throw new StudyIntegrityValidationFailure(ValidationErrors.InconsistentObjectCount,
                                                                  new ValidationStudyInfo(theStudy,
                                                                                          _location.ServerPartition),
                                                                  string.Format(
                                                                      "Database study count {0} does not match study xml {1}",
                                                                      theStudy.NumberOfStudyRelatedInstances,
                                                                      command.StudyXml.NumberOfStudyRelatedInstances));
                    }

					Platform.Log(LogLevel.Info, "Completed reprocessing Study XML file for study {0}", _location.StudyInstanceUid);
				}
			}
			catch (Exception e)
			{
				Platform.Log(LogLevel.Error, e, "Unexpected error when rebuilding study XML for directory: {0}",
				             _location.FilesystemPath);
				StudyReprocessor reprocessor = new StudyReprocessor();
                try
                {
                    WorkQueue reprocessEntry = reprocessor.ReprocessStudy("Rebuild StudyXml", _location, Platform.Time);
                    if (reprocessEntry != null)
                    {
                        Platform.Log(LogLevel.Error, "Failure attempting to reprocess study: {0}",
                                     _location.StudyInstanceUid);
                    }
                    else
                        Platform.Log(LogLevel.Error, "Inserted reprocess request for study: {0}",
                                     _location.StudyInstanceUid);
                }
                catch(InvalidStudyStateOperationException ex)
                {
                    Platform.Log(LogLevel.Error, "Failure attempting to reprocess study {0}: {1}",
                                     _location.StudyInstanceUid, ex.Message);
                }
			}
		}
Пример #3
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="item"></param>
        /// <param name="reason"></param>
        /// <returns></returns>
        /// <exception cref="InvalidStudyStateOperationException">Study is in a state that reprocessing is not allowed</exception>
        protected static AutoRecoveryResult PerformAutoRecovery(Model.WorkQueue item, string reason)
        {
            AutoRecoveryResult result;

            //Note: need to reload the storage location because it may have changed after the processing (eg, tier migration)
            IList<StudyStorageLocation> storageLocations = StudyStorageLocation.FindStorageLocations(StudyStorage.Load(item.StudyStorageKey));
            // storageLocations cannot be null for this operation
            Platform.CheckForNullReference(storageLocations, "storageLocations");
            Platform.CheckTrue(storageLocations.Count >= 1, "storageLocations.Count>=1");

            StudyStorageLocation storageLocation = storageLocations[0];
            Study study = storageLocation.LoadStudy(ServerExecutionContext.Current.PersistenceContext);

            Platform.Log(LogLevel.Info, "{4} failed. Reason:{5}. Attempting to perform auto-recovery for Study:{0}, A#:{1}, Patient:{2}, ID:{3}",
                         study.StudyInstanceUid, study.AccessionNumber, study.PatientsName, study.PatientId, item.WorkQueueTypeEnum.ToString(), reason);

            StudyXml studyXml = storageLocation.LoadStudyXml();
            Platform.CheckForNullReference(studyXml, "studyXml does not exist");
            
            // Do a secondary check on the filesystem vs. the Study Xml.  
            // If these match, then the DB is just update to reflect the valid counts.  
            // If they don't match, a Reprocess entry is inserted into the WorkQueue.
            String studyFolder = storageLocation.GetStudyPath();
            long fileCounter = DirectoryUtility.Count(studyFolder, "*.dcm", true, null);

            // cache these values to avoid looping again
            int numStudyRelatedSeriesInXml = studyXml.NumberOfStudyRelatedSeries;
            int numStudyRelatedInstancesInXml = studyXml.NumberOfStudyRelatedInstances;

            if (fileCounter != numStudyRelatedInstancesInXml)
            {
                // reprocess the study
                Log(LogLevel.Info, "AUTO-RECOVERY", "# of study related instances in study Xml ({0}) appears incorrect. Study needs to be reprocessed.", numStudyRelatedInstancesInXml);
                StudyReprocessor reprocessor = new StudyReprocessor();
                String reprocessReason = String.Format("Auto-recovery from {0}. {1}", item.WorkQueueTypeEnum, reason);
                Model.WorkQueue reprocessEntry = reprocessor.ReprocessStudy(reprocessReason, storageLocation, Platform.Time);

                result = new AutoRecoveryResult
                                                {
                                                    Successful = reprocessEntry!=null, 
                                                    ReprocessWorkQueueEntry=reprocessEntry
                                                };
                return result;
            }

        	Log(LogLevel.Info, "AUTO-RECOVERY", "# of study related instances in study Xml ({0}) appears correct. Update database based on study xml", numStudyRelatedInstancesInXml);
        	// update the counts in db to match the study xml
        	// Update count for each series 
        	IDictionary<string, Series> seriesList = storageLocation.Study.Series;


        	foreach (Series series in seriesList.Values)
        	{
        		SeriesXml seriesXml = studyXml[series.SeriesInstanceUid];
        		if (seriesXml != null)
        		{
        			int numInstancesInSeriesXml = seriesXml.NumberOfSeriesRelatedInstances;
        			if (numInstancesInSeriesXml != series.NumberOfSeriesRelatedInstances)
        			{
        				// Update the count in the series table. Assuming the stored procedure
        				// will also update the count in the Study/Patient tables based on 
        				// the new value.
        				Log(LogLevel.Info, "AUTO-RECOVERY", "Update series in the db. UID:{0}, #Instance:{1}==>{2}", series.SeriesInstanceUid, series.NumberOfSeriesRelatedInstances, numInstancesInSeriesXml);
        				using (IUpdateContext updateContext = PersistentStoreRegistry.GetDefaultStore().OpenUpdateContext(UpdateContextSyncMode.Flush))
        				{
        					ISetSeriesRelatedInstanceCount broker = updateContext.GetBroker<ISetSeriesRelatedInstanceCount>();
        					SetSeriesRelatedInstanceCountParameters criteria = new SetSeriesRelatedInstanceCountParameters(storageLocation.GetKey(), series.SeriesInstanceUid)
        					                                                       {
        					                                                           SeriesRelatedInstanceCount = numInstancesInSeriesXml
        					                                                       };
        				    if (!broker.Execute(criteria))
        					{
        						throw new ApplicationException("Unable to update series related instance count in db");
        					}
        					updateContext.Commit();
        				}
        			}
        		}
        		else
        		{
        			// TODO: series in the db doesn't exist in the xml... the series was deleted from the study?
        			// For now we just reprocess the study. Can we delete the series? If so, we need to take care of the counts.
        			Log(LogLevel.Info, "AUTO-RECOVERY", "Found series in the db which does not exist in the study xml. Force to reprocess the study.");
        			StudyReprocessor reprocessor = new StudyReprocessor();
        			String reprocessReason = String.Format("Auto-recovery from {0}. {1}", item.WorkQueueTypeEnum, reason);
        			Model.WorkQueue reprocessEntry = reprocessor.ReprocessStudy(reprocessReason, storageLocation, Platform.Time);
                    result = new AutoRecoveryResult
                    {
                        Successful = reprocessEntry != null,
                        ReprocessWorkQueueEntry = reprocessEntry
                    };

                    return result;
        		}
        	}

        	if (numStudyRelatedSeriesInXml != storageLocation.Study.NumberOfStudyRelatedSeries ||
        	    numStudyRelatedInstancesInXml != storageLocation.Study.NumberOfStudyRelatedInstances)
        	{
        		Log(LogLevel.Info, "AUTO-RECOVERY", "Updating study related series and instance counts in the db. #Series: {0} ==> {1}.  #Instances: {2}==>{3}",
        		    storageLocation.Study.NumberOfStudyRelatedSeries, numStudyRelatedSeriesInXml,
        		    storageLocation.Study.NumberOfStudyRelatedInstances, numStudyRelatedInstancesInXml);

        		using (IUpdateContext updateContext = PersistentStoreRegistry.GetDefaultStore().OpenUpdateContext(UpdateContextSyncMode.Flush))
        		{
        			var broker = updateContext.GetBroker<ISetStudyRelatedInstanceCount>();
        			var criteria = new SetStudyRelatedInstanceCountParameters(storageLocation.GetKey())
        			                                                      {
        			                                                          StudyRelatedSeriesCount = numStudyRelatedSeriesInXml,
        			                                                          StudyRelatedInstanceCount = numStudyRelatedInstancesInXml
        			                                                      };
        		    if (!broker.Execute(criteria))
        			{
        				throw new ApplicationException("Unable to update study related instance count in db");
        			}
        		
                    updateContext.Commit();
        		}
        	}

        	Log(LogLevel.Info, "AUTO-RECOVERY", "Object count in the db have been corrected.");
            
            result = new AutoRecoveryResult
            {
                Successful = true
            };

            return result;
        }
Пример #4
0
		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;
		}
        private void ReprocessStudy(StudyStorageLocation restoredLocation, string reason)
        {
            StudyReprocessor reprocessor = new StudyReprocessor();
            String reprocessReason = String.Format("Restore Validation Error: {0}", reason);
            reprocessor.ReprocessStudy(reprocessReason, restoredLocation, Platform.Time);
            string message = string.Format("Study {0} has been restored but failed the validation. Reprocess Study has been triggerred. Reason for validation failure: {1}", restoredLocation.StudyInstanceUid, reason);
            Platform.Log(LogLevel.Warn, message);

            ServerPlatform.Alert(AlertCategory.Application, AlertLevel.Informational, "Restore", 0, null, TimeSpan.Zero, message);
        }