Exemple #1
0
        /// <summary>
        /// Find a <see cref="Study"/> with the specified study instance uid on the given partition.
        /// </summary>
        /// <param name="studyInstanceUid"></param>
        /// <param name="partition"></param>
        /// <returns></returns>
        ///
        static public Study Find(IPersistenceContext context, String studyInstanceUid, ServerPartition partition)
        {
            IStudyEntityBroker  broker   = context.GetBroker <IStudyEntityBroker>();
            StudySelectCriteria criteria = new StudySelectCriteria();

            criteria.ServerPartitionKey.EqualTo(partition.GetKey());
            criteria.StudyInstanceUid.EqualTo(studyInstanceUid);
            Study study = broker.FindOne(criteria);

            return(study);
        }
Exemple #2
0
 /// <summary>
 /// Find a <see cref="Study"/> with the specified study instance uid on the given partition.
 /// </summary>
 /// <param name="studyInstanceUid"></param>
 /// <param name="partition"></param>
 /// <returns></returns>
 /// 
 static public Study Find(IPersistenceContext context, String studyInstanceUid, ServerPartition partition)
 {
     IStudyEntityBroker broker = context.GetBroker<IStudyEntityBroker>();
     StudySelectCriteria criteria = new StudySelectCriteria();
     criteria.ServerPartitionKey.EqualTo(partition.GetKey());
     criteria.StudyInstanceUid.EqualTo(studyInstanceUid);
     Study study = broker.FindOne(criteria);
     return study;
    
 }
Exemple #3
0
    	/// <summary>
    	/// Lookup the device entity in the database corresponding to the remote AE of the association.
    	/// </summary>
    	/// <param name="partition">The partition to look up the devices</param>
    	/// <param name="association">The association</param>
    	/// <param name="isNew">Indicates whether the device returned is created by the call.</param>
    	/// <returns>The device record corresponding to the called AE of the association</returns>
		static public Device LookupDevice(ServerPartition partition, AssociationParameters association, out bool isNew)
    	{
    		isNew = false;

    		Device device = null;

    		using (
    			IUpdateContext updateContext =
    				PersistentStoreRegistry.GetDefaultStore().OpenUpdateContext(UpdateContextSyncMode.Flush))
    		{
    			var queryDevice = updateContext.GetBroker<IDeviceEntityBroker>();

    			// Setup the select parameters.
    			var queryParameters = new DeviceSelectCriteria();
    			queryParameters.AeTitle.EqualTo(association.CallingAE);
    			queryParameters.ServerPartitionKey.EqualTo(partition.GetKey());
                var devices = queryDevice.Find(queryParameters);
                foreach (var d in devices)
                {                    
                    if (string.Compare(d.AeTitle,association.CallingAE,false,CultureInfo.InvariantCulture) == 0)
                    {
                        device = d;
                        break;
                    }
                }

    			if (device == null)
    			{
    				if (!partition.AcceptAnyDevice)
    				{
    					return null;
    				}

    				if (partition.AutoInsertDevice)
    				{
    					// Auto-insert a new entry in the table.
    				    var updateColumns = new DeviceUpdateColumns
    				                            {
    				                                AeTitle = association.CallingAE,
    				                                Enabled = true,
    				                                Description = String.Format("AE: {0}", association.CallingAE),
    				                                Dhcp = false,
    				                                IpAddress = association.RemoteEndPoint.Address.ToString(),
    				                                ServerPartitionKey = partition.GetKey(),
    				                                Port = partition.DefaultRemotePort,
    				                                AllowQuery = true,
    				                                AllowRetrieve = true,
    				                                AllowStorage = true,
    				                                ThrottleMaxConnections = ImageServerCommonConfiguration.Device.MaxConnections,
    				                                DeviceTypeEnum = DeviceTypeEnum.Workstation
    				                            };

    				    var insert = updateContext.GetBroker<IDeviceEntityBroker>();

    					device = insert.Insert(updateColumns);

    					updateContext.Commit();

    					isNew = true;
    				}
    			}

    			if (device != null)
    			{
    				// For DHCP devices, we always update the remote ip address, if its changed from what is in the DB.
    				if (device.Dhcp && !association.RemoteEndPoint.Address.ToString().Equals(device.IpAddress))
    				{
    				    var updateColumns = new DeviceUpdateColumns
    				                            {
    				                                IpAddress = association.RemoteEndPoint.Address.ToString(),
    				                                LastAccessedTime = Platform.Time
    				                            };

    				    var update = updateContext.GetBroker<IDeviceEntityBroker>();

    					if (!update.Update(device.GetKey(), updateColumns))
    						Platform.Log(LogLevel.Error,
    						             "Unable to update IP Address for DHCP device {0} on partition '{1}'",
    						             device.AeTitle, partition.Description);
    					else
    						updateContext.Commit();
    				}
    				else if (!isNew)
    				{
    				    var updateColumns = new DeviceUpdateColumns {LastAccessedTime = Platform.Time};

    				    var update = updateContext.GetBroker<IDeviceEntityBroker>();

    					if (!update.Update(device.GetKey(), updateColumns))
    						Platform.Log(LogLevel.Error,
    						             "Unable to update LastAccessedTime device {0} on partition '{1}'",
    						             device.AeTitle, partition.Description);
    					else
    						updateContext.Commit();
    				}
    			}
    		}

    		return device;
    	}
		private static StudyStorageLocation FindStudyStorageLocation(IUpdateContext context, ServerPartition partition, string studyInstanceUid)
		{
			var procedure = context.GetBroker<IQueryStudyStorageLocation>();
			var parms = new StudyStorageLocationQueryParameters
			{
				ServerPartitionKey = partition.GetKey(),
				StudyInstanceUid = studyInstanceUid
			};
			return procedure.FindOne(parms);
		}
        private IList<PartitionSopClass> LoadPartitionSopClassesFromDatabase(ServerPartition partition)
        {
            using (IReadContext context = PersistentStoreRegistry.GetDefaultStore().OpenReadContext())
            {
                // Set the input parameters for query
                var inputParms = new PartitionSopClassQueryParameters {ServerPartitionKey = partition.GetKey()};

                var broker = context.GetBroker<IQueryServerPartitionSopClasses>();
                return broker.Find(inputParms);
            }
        }
        /// <summary>
        /// Load <see cref="Device"/> information for a Move destination.
        /// </summary>
        /// <param name="read"></param>
        /// <param name="partition"></param>
        /// <param name="remoteAe"></param>
        /// <returns></returns>
        private static Device LoadRemoteHost(IPersistenceContext read, ServerPartition partition, string remoteAe)
        {
            var select = read.GetBroker<IDeviceEntityBroker>();

            // Setup the select parameters.
            var selectParms = new DeviceSelectCriteria();
            selectParms.AeTitle.EqualTo(remoteAe);
            selectParms.ServerPartitionKey.EqualTo(partition.GetKey());
            var devices = select.Find(selectParms);
            foreach (var d in devices)
            {
                if (string.Compare(d.AeTitle, remoteAe, false, CultureInfo.InvariantCulture) == 0)
                {
                    return d;
                }
            }
            return null;
        }
		/// <summary>
		/// Reprocess a file systems
		/// </summary>
		/// <param name="partition"></param>
		private void ReprocessPartition(ServerPartition partition)
		{
			var engine = new ServerRulesEngine(ServerRuleApplyTimeEnum.StudyProcessed, partition.Key);
			engine.Load();

			var postArchivalEngine = new ServerRulesEngine(ServerRuleApplyTimeEnum.StudyArchived, partition.Key);
			postArchivalEngine.Load();

			var dataAccessEngine = new ServerRulesEngine(ServerRuleApplyTimeEnum.StudyProcessed, partition.Key);
			dataAccessEngine.AddIncludeType(ServerRuleTypeEnum.DataAccess);
			dataAccessEngine.Load();

			var filesystems = FilesystemMonitor.Instance.GetFilesystems();

			foreach (var f in filesystems)
			{
				var partitionDir = Path.Combine(f.Filesystem.FilesystemPath, partition.PartitionFolder);
				var filesystemDir = new DirectoryInfo(partitionDir);
				foreach (DirectoryInfo dateDir in filesystemDir.GetDirectories())
				{
					if (dateDir.FullName.EndsWith("Deleted")
						|| dateDir.FullName.EndsWith(ServerPlatform.ReconcileStorageFolder))
						continue;

					foreach (DirectoryInfo studyDir in dateDir.GetDirectories())
					{
						String studyInstanceUid = studyDir.Name;
						try
						{
							StudyStorageLocation location = LoadReadableStorageLocation(partition.GetKey(), studyInstanceUid);
							if (location == null)
							{
								foreach (DirectoryInfo seriesDir in studyDir.GetDirectories())
								{
									FileInfo[] sopInstanceFiles = seriesDir.GetFiles("*.dcm");

									DicomFile file = null;
									foreach (FileInfo sopFile in sopInstanceFiles)
									{
										if (!sopFile.FullName.EndsWith(ServerPlatform.DicomFileExtension))
											continue;

										try
										{
											file = new DicomFile(sopFile.FullName);
											file.Load(DicomTags.StudyId, DicomReadOptions.DoNotStorePixelDataInDataSet | DicomReadOptions.Default);
											break;
										}
										catch (Exception e)
										{
											Platform.Log(LogLevel.Warn, e, "Unexpected failure loading file: {0}.  Continuing to next file.",
														 sopFile.FullName);
											file = null;
										}
									}
									if (file != null)
									{
										studyInstanceUid = file.DataSet[DicomTags.StudyInstanceUid].ToString();
										break;
									}
								}

								location = LoadReadableStorageLocation(partition.GetKey(), studyInstanceUid);
								if (location == null)
									continue;
							}

							ProcessStudy(partition, location, engine, postArchivalEngine, dataAccessEngine);
							//_stats.NumStudies++;

							if (CancelPending) return;
						}
						catch (Exception e)
						{
							Platform.Log(LogLevel.Error, e,
										 "Unexpected error while processing study: {0} on partition {1}.", studyInstanceUid,
										 partition.Description);
						}
					}

					// Cleanup the directory, if its empty.
					DirectoryUtility.DeleteIfEmpty(dateDir.FullName);
				}
			}
		}
		/// <summary>
		/// Reprocess a specific study.
		/// </summary>
		/// <param name="partition">The ServerPartition the study is on.</param>
		/// <param name="location">The storage location of the study to process.</param>
		/// <param name="engine">The rules engine to use when processing the study.</param>
		/// <param name="postArchivalEngine">The rules engine used for studies that have been archived.</param>
		/// <param name="dataAccessEngine">The rules engine strictly used for setting data acess.</param>
		protected static void ProcessStudy(ServerPartition partition, StudyStorageLocation location, ServerRulesEngine engine, ServerRulesEngine postArchivalEngine, ServerRulesEngine dataAccessEngine)
		{
			if (!location.QueueStudyStateEnum.Equals(QueueStudyStateEnum.Idle) || !location.AcquireWriteLock())
			{
				Platform.Log(LogLevel.Error, "Unable to lock study {0}. The study is being processed. (Queue State: {1})", location.StudyInstanceUid,location.QueueStudyStateEnum.Description); 
			}
			else
			{
				try
				{
					DicomFile msg = LoadInstance(location);
					if (msg == null)
					{
						Platform.Log(LogLevel.Error, "Unable to load file for study {0}", location.StudyInstanceUid);
						return;
					}

					bool archiveQueueExists;
					bool archiveStudyStorageExists;
					bool filesystemDeleteExists;
					using (IReadContext read = PersistentStoreRegistry.GetDefaultStore().OpenReadContext())
					{
						// Check for existing archive queue entries
						var archiveQueueBroker = read.GetBroker<IArchiveQueueEntityBroker>();
						var archiveQueueCriteria = new ArchiveQueueSelectCriteria();
						archiveQueueCriteria.StudyStorageKey.EqualTo(location.Key);
						archiveQueueExists = archiveQueueBroker.Count(archiveQueueCriteria) > 0;


						var archiveStorageBroker = read.GetBroker<IArchiveStudyStorageEntityBroker>();
						var archiveStudyStorageCriteria = new ArchiveStudyStorageSelectCriteria();
						archiveStudyStorageCriteria.StudyStorageKey.EqualTo(location.Key);
						archiveStudyStorageExists = archiveStorageBroker.Count(archiveStudyStorageCriteria) > 0;

						var filesystemQueueBroker = read.GetBroker<IFilesystemQueueEntityBroker>();
						var filesystemQueueCriteria = new FilesystemQueueSelectCriteria();
						filesystemQueueCriteria.StudyStorageKey.EqualTo(location.Key);
						filesystemQueueCriteria.FilesystemQueueTypeEnum.EqualTo(FilesystemQueueTypeEnum.DeleteStudy);
						filesystemDeleteExists = filesystemQueueBroker.Count(filesystemQueueCriteria) > 0;
					}

					using (var commandProcessor = new ServerCommandProcessor("Study Rule Processor")
					{
						PrimaryServerPartitionKey = partition.GetKey(),
						PrimaryStudyKey = location.Study.GetKey()
					})
					{
						var context = new ServerActionContext(msg, location.FilesystemKey, partition, location.Key, commandProcessor);
					
						// Check if the Study has been archived 
						if (archiveStudyStorageExists && !archiveQueueExists && !filesystemDeleteExists)
						{
							// Add a command to delete the current filesystemQueue entries, so that they can 
							// be reinserted by the rules engine.
							context.CommandProcessor.AddCommand(new DeleteFilesystemQueueCommand(location.Key, ServerRuleApplyTimeEnum.StudyArchived));

							// How to deal with exiting FilesystemQueue entries is problematic here.  If the study
							// has been migrated off tier 1, we probably don't want to modify the tier migration 
							// entries.  Compression entries may have been entered when the Study was initially 
							// processed, we don't want to delete them, because they might still be valid.  
							// We just re-run the rules engine at this point, and delete only the StudyPurge entries,
							// since those we know at least would only be applied for archived studies.
							var studyRulesEngine = new StudyRulesEngine(postArchivalEngine, location, location.ServerPartition, location.LoadStudyXml());
							studyRulesEngine.Apply(ServerRuleApplyTimeEnum.StudyArchived, commandProcessor);

							// Post Archive doesn't allow data access rules.  Force Data Access rules to be reapplied
							// to these studies also.
							dataAccessEngine.Execute(context);
						}
						else
						{
							// Add a command to delete the current filesystemQueue entries, so that they can 
							// be reinserted by the rules engine.
							context.CommandProcessor.AddCommand(new DeleteFilesystemQueueCommand(location.Key,ServerRuleApplyTimeEnum.StudyProcessed));

							// Execute the rules engine, insert commands to update the database into the command processor.
							// Due to ticket #11673, we create a new rules engine instance for each study, since the Study QC rules
							// don't work right now with a single rules engine.
							//TODO CR (Jan 2014) - Check if we can go back to caching the rules engine to reduce database hits on the rules
							var studyRulesEngine = new StudyRulesEngine(location, location.ServerPartition, location.LoadStudyXml());
							studyRulesEngine.Apply(ServerRuleApplyTimeEnum.StudyProcessed, commandProcessor);
						}

						// Do the actual database updates.
						if (false == context.CommandProcessor.Execute())
						{
							Platform.Log(LogLevel.Error, "Unexpected failure processing Study level rules for study {0}", location.StudyInstanceUid);
						}

						// Log the FilesystemQueue related entries
						location.LogFilesystemQueue();
					}
				}
				finally
				{
					location.ReleaseWriteLock();
				}
			}
		}