示例#1
0
 static public RestoreQueue Insert(RestoreQueue entity)
 {
     using (var update = PersistentStoreRegistry.GetDefaultStore().OpenUpdateContext(UpdateContextSyncMode.Flush))
     {
         RestoreQueue newEntity = Insert(update, entity);
         update.Commit();
         return newEntity;
     }
 }
        public bool DeleteRestoreQueueItem(RestoreQueue item)
        {
        	using (IUpdateContext updateContext = PersistentStoreRegistry.GetDefaultStore().OpenUpdateContext(UpdateContextSyncMode.Flush))
			{
				ILockStudy lockStudyBroker = updateContext.GetBroker<ILockStudy>();
				LockStudyParameters parms = new LockStudyParameters
				                            	{
				                            		StudyStorageKey = item.StudyStorageKey,
				                            		QueueStudyStateEnum = QueueStudyStateEnum.Idle
				                            	};
				if (!lockStudyBroker.Execute(parms))
					return false;
				if (!parms.Successful)
					return false;

				bool retValue = _adaptor.Delete(updateContext, item.Key);

				updateContext.Commit();

				return retValue;
			}
        }
 /// <summary>
 /// Creates an instance of <see cref="RestoreProcessorContext"/>
 /// </summary>
 /// <param name="item"></param>
 public RestoreProcessorContext(RestoreQueue item)
     :base(item.GetKey().Key.ToString())
 {
     Platform.CheckForNullReference(item, "item");
     _item = item;
 }
		/// <summary>
		/// Do the restore.
		/// </summary>
		/// <param name="queueItem">The queue item to restore.</param>
		public void Run(RestoreQueue queueItem)
		{
            using (RestoreProcessorContext context = new RestoreProcessorContext(queueItem))
            {
                try
                {
                    // Load up related classes.
                    using (IReadContext readContext = _nasArchive.PersistentStore.OpenReadContext())
                    {
                        _archiveStudyStorage = ArchiveStudyStorage.Load(readContext, queueItem.ArchiveStudyStorageKey);
                        _serverSyntax = ServerTransferSyntax.Load(readContext, _archiveStudyStorage.ServerTransferSyntaxKey);
                        _syntax = TransferSyntax.GetTransferSyntax(_serverSyntax.Uid);

                        StudyStorageLocationQueryParameters parms = new StudyStorageLocationQueryParameters
                                                                    	{StudyStorageKey = queueItem.StudyStorageKey};
                    	IQueryStudyStorageLocation broker = readContext.GetBroker<IQueryStudyStorageLocation>();
                        _location = broker.FindOne(parms);
                        if (_location == null)
                        {
                            _studyStorage = StudyStorage.Load(readContext, queueItem.StudyStorageKey);
							if (_studyStorage==null)
							{
								DateTime scheduleTime = Platform.Time.AddMinutes(5);
								Platform.Log(LogLevel.Error, "Unable to find storage location, rescheduling restore request to {0}",
											 scheduleTime);
								queueItem.FailureDescription = "Unable to find storage location, rescheduling request.";
								_nasArchive.UpdateRestoreQueue(queueItem, RestoreQueueStatusEnum.Pending, scheduleTime);
								return;
							}
                        }
                    }

					if (_location == null)
						Platform.Log(LogLevel.Info, "Starting restore of nearline study: {0}", _studyStorage.StudyInstanceUid);
					else
                        Platform.Log(LogLevel.Info, "Starting restore of online study: {0}", _location.StudyInstanceUid);

                    // If restoring a Nearline study, select a filesystem
                    string destinationFolder;
                    if (_location == null)
                    {
                        ServerFilesystemInfo fs = _nasArchive.Selector.SelectFilesystem();
                        if (fs == null)
                        {
                            DateTime scheduleTime = Platform.Time.AddMinutes(5);
                            Platform.Log(LogLevel.Error, "No writeable filesystem for restore, rescheduling restore request to {0}",
                                         scheduleTime);
                            queueItem.FailureDescription = "No writeable filesystem for restore, rescheduling request.";
                            _nasArchive.UpdateRestoreQueue(queueItem, RestoreQueueStatusEnum.Pending, scheduleTime);
                            return;
                        }
                        destinationFolder = Path.Combine(fs.Filesystem.FilesystemPath, _nasArchive.ServerPartition.PartitionFolder);
                    }
                    else
                        destinationFolder = _location.GetStudyPath();


                    // Get the zip file path from the xml data in the ArchiveStudyStorage entry
                    // Also store the "StudyFolder" for use below
                    string studyFolder = String.Empty;
                    string filename = String.Empty;
                    string studyInstanceUid = String.Empty;
                    XmlElement element = _archiveStudyStorage.ArchiveXml.DocumentElement;
					if (element!=null)
						foreach (XmlElement node in element.ChildNodes)
							if (node.Name.Equals("StudyFolder"))
								studyFolder = node.InnerText;
							else if (node.Name.Equals("Filename"))
								filename = node.InnerText;
							else if (node.Name.Equals("Uid"))
								studyInstanceUid = node.InnerText;

                    string zipFile = Path.Combine(_nasArchive.NasPath, studyFolder);
                    zipFile = Path.Combine(zipFile, studyInstanceUid);
                    zipFile = Path.Combine(zipFile, filename);


                    // Do a test read of the zip file.  If it succeeds, the file is available, if it 
                    // fails, we just set back to pending and recheck.
                    try
                    {
                        FileStream stream = File.OpenRead(zipFile);
                        // Read a byte, just in case that makes a difference.
                        stream.ReadByte();
                        stream.Close();
                        stream.Dispose();
                    }
                    catch (Exception ex)
                    {
                        DateTime scheduledTime = Platform.Time.AddSeconds(NasSettings.Default.ReadFailRescheduleDelaySeconds);
                        Platform.Log(LogLevel.Error, ex, "Archive {0} for Study  {1} is unreadable, rescheduling restore to {2}",
                                     zipFile, _studyStorage == null ? (_location == null ? string.Empty : _location.StudyInstanceUid) : _studyStorage.StudyInstanceUid,
                                     scheduledTime);
                        // Just reschedule in "Restoring" state, the file is unreadable.
                        _nasArchive.UpdateRestoreQueue(queueItem, RestoreQueueStatusEnum.Restoring,
                                                       scheduledTime);
                        return;
                    }

                    if (_location == null)
                        RestoreNearlineStudy(queueItem, zipFile, destinationFolder, studyFolder);
                    else
                        RestoreOnlineStudy(queueItem, zipFile, destinationFolder);
                }
                catch (Exception e)
                {
                    Platform.Log(LogLevel.Error, e, "Unexpected exception processing restore request for {0} on archive {1}",
                        _studyStorage == null ? (_location == null ? string.Empty : _location.StudyInstanceUid) : _studyStorage.StudyInstanceUid,
                        _nasArchive.PartitionArchive.Description);
                    queueItem.FailureDescription = e.Message;
                    _nasArchive.UpdateRestoreQueue(queueItem, RestoreQueueStatusEnum.Failed, Platform.Time);
                }
            }
			
		}
        private void RestoreOnlineStudy(RestoreQueue queueItem, string zipFile, string destinationFolder)
		{
			try
			{
				using (ServerCommandProcessor processor = new ServerCommandProcessor("NAS Restore Online Study"))
				{
					using (ZipFile zip = new ZipFile(zipFile))
					{
						foreach (string file in zip.EntryFileNames)
						{
							processor.AddCommand(new ExtractZipFileAndReplaceCommand(zipFile, file, destinationFolder));
						}
					}

					// We rebuild the StudyXml, in case any settings or issues have happened since archival
					processor.AddCommand(new RebuildStudyXmlCommand(_location.StudyInstanceUid, destinationFolder));

					StudyStatusEnum status;

					if (_syntax.Encapsulated && _syntax.LosslessCompressed)
						status = StudyStatusEnum.OnlineLossless;
					else if (_syntax.Encapsulated && _syntax.LossyCompressed)
						status = StudyStatusEnum.OnlineLossy;
					else
						status = StudyStatusEnum.Online;

					processor.AddCommand(new UpdateStudyStateCommand(_location, status, _serverSyntax));

					// Apply the rules engine.
					ServerActionContext context =
						new ServerActionContext(null, _location.FilesystemKey, _nasArchive.ServerPartition,
												queueItem.StudyStorageKey) {CommandProcessor = processor};
					processor.AddCommand(
						new ApplyRulesCommand(destinationFolder, _location.StudyInstanceUid, context));

					if (!processor.Execute())
					{
						Platform.Log(LogLevel.Error, "Unexpected error processing restore request for {0} on archive {1}",
									 _location.StudyInstanceUid, _nasArchive.PartitionArchive.Description);
						queueItem.FailureDescription = processor.FailureReason;
						_nasArchive.UpdateRestoreQueue(queueItem, RestoreQueueStatusEnum.Failed, Platform.Time);
					}
					else
					{
						// Unlock the Queue Entry and set to complete
						using (IUpdateContext update = PersistentStoreRegistry.GetDefaultStore().OpenUpdateContext(UpdateContextSyncMode.Flush))
						{
							_nasArchive.UpdateRestoreQueue(update, queueItem, RestoreQueueStatusEnum.Completed, Platform.Time.AddSeconds(60));
							ILockStudy studyLock = update.GetBroker<ILockStudy>();
							LockStudyParameters parms = new LockStudyParameters
							                            	{
							                            		StudyStorageKey = queueItem.StudyStorageKey,
							                            		QueueStudyStateEnum = QueueStudyStateEnum.Idle
							                            	};
							bool retVal = studyLock.Execute(parms);
							if (!parms.Successful || !retVal)
							{
								Platform.Log(LogLevel.Info, "Study {0} on partition {1} failed to unlock.", _location.StudyInstanceUid,
											 _nasArchive.ServerPartition.Description);
							}

							update.Commit();

							Platform.Log(LogLevel.Info, "Successfully restored study: {0} on archive {1}", _location.StudyInstanceUid,
										 _nasArchive.PartitionArchive.Description);

                            OnStudyRestored(_location);
						}
					}
				}
			}
			catch (Exception e)
			{
				Platform.Log(LogLevel.Error, e, "Unexpected exception processing restore request for {0} on archive {1}",
							 _location.StudyInstanceUid, _nasArchive.PartitionArchive.Description);
				queueItem.FailureDescription = e.Message;
				_nasArchive.UpdateRestoreQueue(queueItem, RestoreQueueStatusEnum.Failed, Platform.Time);
			}
		}
		public void RestoreNearlineStudy(RestoreQueue queueItem, string zipFile, string destinationFolder, string studyFolder)
		{
            ServerFilesystemInfo fs = _nasArchive.Selector.SelectFilesystem();
			if (fs == null)
			{
				DateTime scheduleTime = Platform.Time.AddMinutes(5);
				Platform.Log(LogLevel.Error, "No writeable filesystem for restore, rescheduling restore request to {0}", scheduleTime);
				queueItem.FailureDescription = "No writeable filesystem for restore, rescheduling restore request";
				_nasArchive.UpdateRestoreQueue(queueItem, RestoreQueueStatusEnum.Pending, scheduleTime);
				return;
			}

		    StudyStorageLocation restoredLocation = null;
			try
			{
				using (ServerCommandProcessor processor = 
                    new ServerCommandProcessor("NAS Restore Offline Study"))
				{
					processor.AddCommand(new CreateDirectoryCommand(destinationFolder));
					destinationFolder = Path.Combine(destinationFolder, studyFolder);
					processor.AddCommand(new CreateDirectoryCommand(destinationFolder));
					destinationFolder = Path.Combine(destinationFolder, _studyStorage.StudyInstanceUid);
					processor.AddCommand(new CreateDirectoryCommand(destinationFolder));
					processor.AddCommand(new ExtractZipCommand(zipFile, destinationFolder));

					// We rebuild the StudyXml, in case any settings or issues have happened since archival
					processor.AddCommand(new RebuildStudyXmlCommand(_studyStorage.StudyInstanceUid, destinationFolder));

                    // Apply the rules engine.
					ServerActionContext context =
						new ServerActionContext(null, fs.Filesystem.GetKey(), _nasArchive.ServerPartition,
						                        queueItem.StudyStorageKey) {CommandProcessor = processor};
					processor.AddCommand(
						new ApplyRulesCommand(destinationFolder, _studyStorage.StudyInstanceUid, context));

					// Do the actual insert into the DB
					InsertFilesystemStudyStorageCommand insertStorageCommand = new InsertFilesystemStudyStorageCommand(
													_nasArchive.PartitionArchive.ServerPartitionKey,
						                            _studyStorage.StudyInstanceUid,
						                            studyFolder,
						                            fs.Filesystem.GetKey(), _syntax);
					processor.AddCommand(insertStorageCommand);

					if (!processor.Execute())
					{
						Platform.Log(LogLevel.Error, "Unexpected error processing restore request for {0} on archive {1}",
						             _studyStorage.StudyInstanceUid, _nasArchive.PartitionArchive.Description);
						queueItem.FailureDescription = processor.FailureReason;
						_nasArchive.UpdateRestoreQueue(queueItem, RestoreQueueStatusEnum.Failed, Platform.Time);
					}
					else
					{
					    restoredLocation = insertStorageCommand.Location;

						// Unlock the Queue Entry
						using (
							IUpdateContext update = PersistentStoreRegistry.GetDefaultStore().OpenUpdateContext(UpdateContextSyncMode.Flush))
						{
							bool retVal = _nasArchive.UpdateRestoreQueue(update, queueItem, RestoreQueueStatusEnum.Completed, Platform.Time.AddSeconds(60));
							ILockStudy studyLock = update.GetBroker<ILockStudy>();
							LockStudyParameters parms = new LockStudyParameters
							                            	{
							                            		StudyStorageKey = queueItem.StudyStorageKey,
							                            		QueueStudyStateEnum = QueueStudyStateEnum.Idle
							                            	};
							retVal = retVal && studyLock.Execute(parms);
							if (!parms.Successful || !retVal)
							{
								string message =
									String.Format("Study {0} on partition {1} failed to unlock.", _studyStorage.StudyInstanceUid,
									              _nasArchive.ServerPartition.Description);
								Platform.Log(LogLevel.Info, message);
								throw new ApplicationException(message);
							}
							update.Commit();

							Platform.Log(LogLevel.Info, "Successfully restored study: {0} on archive {1}", _studyStorage.StudyInstanceUid,
										 _nasArchive.PartitionArchive.Description);

                            OnStudyRestored(restoredLocation);
						}
					}
				}
			}
            catch(StudyIntegrityValidationFailure ex)
            {
                Debug.Assert(restoredLocation != null);
                // study has been restored but it seems corrupted. Need to reprocess it.
                ReprocessStudy(restoredLocation, ex.Message);
            }
			catch (Exception e)
			{
				Platform.Log(LogLevel.Error, e, "Unexpected exception processing restore request for {0} on archive {1}",
							 _studyStorage.StudyInstanceUid, _nasArchive.PartitionArchive.Description);
				_nasArchive.UpdateRestoreQueue(queueItem, RestoreQueueStatusEnum.Failed, Platform.Time);
			}
		}
		/// <summary>
		/// Constructs an instance of <see cref="WorkQueue"/> based on a <see cref="WorkQueueSummary"/> object.
		/// </summary>
		/// <param name="item"></param>
		/// <returns></returns>
		/// <remark>
		/// 
		/// </remark>
		private RestoreQueueSummary CreateWorkQueueSummary(RestoreQueue item)
		{
			RestoreQueueSummary summary = new RestoreQueueSummary();
			summary.TheRestoreQueueItem = item;
			summary.ThePartition = Partition;

			if (item.FailureDescription == null)
				summary.Notes = String.Empty;
			else
				summary.Notes = item.FailureDescription;

			// Fetch the patient info:
			StudyStorageAdaptor ssAdaptor = new StudyStorageAdaptor();
			summary.StudyStorage = ssAdaptor.Get(item.StudyStorageKey);
			if (summary.StudyStorage == null)
			{
				summary.PatientId = "N/A";
				summary.PatientsName = "N/A";
				return summary;
			}
			StudyAdaptor studyAdaptor = new StudyAdaptor();
			StudySelectCriteria studycriteria = new StudySelectCriteria();
			studycriteria.StudyInstanceUid.EqualTo(summary.StudyStorage.StudyInstanceUid);
			studycriteria.ServerPartitionKey.EqualTo(summary.StudyStorage.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;
			}

			return summary;
		}
示例#8
0
 static public RestoreQueue Insert(IUpdateContext update, RestoreQueue entity)
 {
     var broker = update.GetBroker<IRestoreQueueEntityBroker>();
     var updateColumns = new RestoreQueueUpdateColumns();
     updateColumns.ArchiveStudyStorageKey = entity.ArchiveStudyStorageKey;
     updateColumns.StudyStorageKey = entity.StudyStorageKey;
     updateColumns.ScheduledTime = entity.ScheduledTime;
     updateColumns.RestoreQueueStatusEnum = entity.RestoreQueueStatusEnum;
     updateColumns.ProcessorId = entity.ProcessorId;
     updateColumns.FailureDescription = entity.FailureDescription;
     RestoreQueue newEntity = broker.Insert(updateColumns);
     return newEntity;
 }
		/// <summary>
		/// Update a <see cref="RestoreQueue"/> entry.
		/// </summary>
		/// <param name="item">The item to update.</param>
		/// <param name="status">The status to set the entry to.</param>
		/// <param name="scheduledTime">The scheduled time to set the entry to.</param>
		/// <param name="updateContext">The update context</param>
		public bool UpdateRestoreQueue(IUpdateContext updateContext, RestoreQueue item, RestoreQueueStatusEnum status, DateTime scheduledTime)
		{
			UpdateRestoreQueueParameters parms = new UpdateRestoreQueueParameters();
			parms.RestoreQueueKey = item.GetKey();
			parms.RestoreQueueStatusEnum = status;
			parms.ScheduledTime = scheduledTime;
			parms.StudyStorageKey = item.StudyStorageKey;
			if (!String.IsNullOrEmpty(item.FailureDescription))
				parms.FailureDescription = item.FailureDescription;
				
			IUpdateRestoreQueue broker = updateContext.GetBroker<IUpdateRestoreQueue>();

			if (broker.Execute(parms))
			{
				return true;
			}
			
			Platform.Log(LogLevel.Error, "Unexpected failure updating RestoreQueue entry {0}", item.GetKey());
			return false;
		}
		/// <summary>
		/// Update a <see cref="RestoreQueue"/> entry.
		/// </summary>
		/// <param name="item">The item to update.</param>
		/// <param name="status">The status to set the entry to.</param>
		/// <param name="scheduledTime">The scheduled time to set the entry to.</param>
		public void UpdateRestoreQueue(RestoreQueue item, RestoreQueueStatusEnum status, DateTime scheduledTime)
		{
			using (IUpdateContext updateContext = PersistentStore.OpenUpdateContext(UpdateContextSyncMode.Flush))
			{
				if (UpdateRestoreQueue(updateContext, item, status, scheduledTime))
					updateContext.Commit();
			}
		}
示例#11
0
		/// <summary>
		/// Do the restore.
		/// </summary>
		/// <param name="queueItem">The queue item to restore.</param>
		public void Run(RestoreQueue queueItem)
		{
            using (var context = new RestoreProcessorContext(queueItem))
            {
                try
                {
                    // Load up related classes.
                    using (IReadContext readContext = _hsmArchive.PersistentStore.OpenReadContext())
                    {
                        _archiveStudyStorage = ArchiveStudyStorage.Load(readContext, queueItem.ArchiveStudyStorageKey);
                        _serverSyntax = ServerTransferSyntax.Load(readContext, _archiveStudyStorage.ServerTransferSyntaxKey);
                        _syntax = TransferSyntax.GetTransferSyntax(_serverSyntax.Uid);

                        var parms = new StudyStorageLocationQueryParameters
                                                                    	{StudyStorageKey = queueItem.StudyStorageKey};
                    	var broker = readContext.GetBroker<IQueryStudyStorageLocation>();
                        _location = broker.FindOne(parms);
                        if (_location == null)
                        {
                            _studyStorage = StudyStorage.Load(readContext, queueItem.StudyStorageKey);
							if (_studyStorage==null)
							{
								DateTime scheduleTime = Platform.Time.AddMinutes(5);
								Platform.Log(LogLevel.Error, "Unable to find storage location, rescheduling restore request to {0}",
											 scheduleTime);
								queueItem.FailureDescription = "Unable to find storage location, rescheduling request.";
								_hsmArchive.UpdateRestoreQueue(queueItem, RestoreQueueStatusEnum.Pending, scheduleTime);
								return;
							}
                        }
                    }

                    if (_location == null)
                    {
                        Platform.Log(LogLevel.Info, "Starting restore of nearline study: {0}",
                                     _studyStorage.StudyInstanceUid);

                        // Get the zip file path from the xml data in the ArchiveStudyStorage entry
                        // Also store the "StudyFolder" for use below
                        string studyFolder;
                        string zipFile = GetZipFileName(out studyFolder);

                        // Do a test read of the zip file.  If it succeeds, the file is available, if it 
                        // fails, we just set back to pending and recheck.
                        if (!CanReadZip(zipFile, queueItem))
                            return;

                        RestoreNearlineStudy(queueItem, zipFile, studyFolder);
                    }
                    else
                    {
                        Platform.Log(LogLevel.Info, "Starting restore of online study: {0}", _location.StudyInstanceUid);

                         // Get the zip file path from the xml data in the ArchiveStudyStorage entry
                         // Also store the "StudyFolder" for use below
                         string studyFolder;
                         string zipFile = GetZipFileName(out studyFolder);

                         // Do a test read of the zip file.  If it succeeds, the file is available, if it 
                         // fails, we just set back to pending and recheck.
                         if (!CanReadZip(zipFile, queueItem))
                             return;

                        RestoreOnlineStudy(queueItem, zipFile, _location.GetStudyPath());
                    }       
                }
                catch (Exception e)
                {
                    Platform.Log(LogLevel.Error, e, "Unexpected exception processing restore request for {0} on archive {1}",
                        _studyStorage == null ? (_location == null ? string.Empty : _location.StudyInstanceUid) : _studyStorage.StudyInstanceUid,
                        _hsmArchive.PartitionArchive.Description);
                    queueItem.FailureDescription = e.Message;
                    _hsmArchive.UpdateRestoreQueue(queueItem, RestoreQueueStatusEnum.Failed, Platform.Time);
                }
            }
			
		}
示例#12
0
        private bool CanReadZip(string zipFile, RestoreQueue queueItem)
        {
            // Do a test read of the zip file.  If it succeeds, the file is available, if it 
            // fails, we just set back to pending and recheck.
            try
            {
                FileStream stream = File.OpenRead(zipFile);
                // Read a byte, just in case that makes a difference.
                stream.ReadByte();
                stream.Close();
                stream.Dispose();

                return true;
            }
            catch (DirectoryNotFoundException ex)
            {
                Platform.Log(LogLevel.Error, ex, "Archive {0} for Study  {1} cannot be found, failing",
                              zipFile, _studyStorage == null
                              ? (_location == null
                                 ? string.Empty : _location.StudyInstanceUid)
                                 : _studyStorage.StudyInstanceUid);
                // Just "Fail", the directory is not found.
                queueItem.FailureDescription = string.Format("Directory not found for file, cannot restore: {0}", zipFile);
                _hsmArchive.UpdateRestoreQueue(queueItem, RestoreQueueStatusEnum.Failed,
                                               Platform.Time);
                return false;
            }
            catch (Exception ex)
            {
                DateTime scheduledTime = Platform.Time.AddSeconds(HsmSettings.Default.ReadFailRescheduleDelaySeconds);
                Platform.Log(LogLevel.Error, ex, "Archive {0} for Study  {1} is unreadable, rescheduling restore to {2}",
                             zipFile,
                             _studyStorage == null
                                 ? (_location == null ? string.Empty : _location.StudyInstanceUid)
                                 : _studyStorage.StudyInstanceUid,
                             scheduledTime);
                // Just reschedule in "Restoring" state, the file is unreadable.
                _hsmArchive.UpdateRestoreQueue(queueItem, RestoreQueueStatusEnum.Restoring,
                                               scheduledTime);
                return false;
            }
        }