private IEnumerable<PartitionSopClass> LoadPartitionSopClasses(ServerPartition partition) { IList<PartitionSopClass> list = null; if (Cache.IsSupported()) { var cacheKey = "PartitionSopClasses-" + partition.Key; using (var cacheClient = Cache.CreateClient(_cacheId)) { list = cacheClient.Get(cacheKey, new CacheGetOptions("default")) as IList<PartitionSopClass>; if (list == null) { Platform.Log(LogLevel.Debug, "Loading PartitionSopClass from database"); list = LoadPartitionSopClassesFromDatabase(partition); cacheClient.Put(cacheKey, list, new CachePutOptions("default", TimeSpan.FromSeconds(30), false /*no sliding. Reload 60 seconds*/)); } } } else { list = LoadPartitionSopClassesFromDatabase(partition); } return list; }
/// <summary> /// Inserts delete request(s) to delete a series in a study. /// </summary> /// <param name="context">The persistence context used for database connection.</param> /// <param name="partition">The <see cref="ServerPartition"/> where the study resides</param> /// <param name="studyInstanceUid">The Study Instance Uid of the study</param> /// <param name="reason">The reason for deleting the series.</param> /// <returns>A list of DeleteSeries <see cref="WorkQueue"/> entries inserted into the system.</returns> /// <exception cref="InvalidStudyStateOperationException"></exception> public static WorkQueue DeleteStudy(IUpdateContext context, ServerPartition partition, string studyInstanceUid, string reason) { StudyStorageLocation location = FindStudyStorageLocation(context, partition, studyInstanceUid); string failureReason; try { if (LockStudyForDeletion(location.Key, out failureReason)) { WorkQueue deleteRequest = InsertDeleteStudyRequest(context, location, reason); if (deleteRequest == null) throw new ApplicationException( String.Format("Unable to insert a Delete Study request for study {0}", location.StudyInstanceUid)); return deleteRequest; } } catch (Exception ex) { Platform.Log(LogLevel.Error, ex, "Errors occurred when trying to insert study delete request"); if (!ReleaseDeletionLock(location.Key)) Platform.Log(LogLevel.Error, "Unable to unlock the study: " + location.StudyInstanceUid); throw; } throw new ApplicationException( String.Format("Unable to lock storage location {0} for deletion : {1}", location.Key, failureReason)); }
/// <summary> /// Inserts a move request to move one or more series in a study. /// </summary> /// <param name="context">The persistence context used for database connection.</param> /// <param name="partition">The <see cref="ServerPartition"/> where the study resides</param> /// <param name="studyInstanceUid">The Study Instance Uid of the study</param> /// <param name="deviceKey">The Key of the device to move the series to.</param> /// <param name="seriesInstanceUids">The Series Instance Uid of the series to be move.</param> /// <param name="externalRequest">Optional <see cref="ExternalRequestQueue"/> entry that triggered this move</param> /// <returns>A MoveSeries <see cref="WorkQueue"/> entry inserted into the system.</returns> /// <exception cref="InvalidStudyStateOperationException"></exception> public static IList<WorkQueue> MoveSeries(IUpdateContext context, ServerPartition partition, string studyInstanceUid, ServerEntityKey deviceKey, List<string> seriesInstanceUids, ExternalRequestQueue externalRequest=null) { // Find all location of the study in the system and insert series delete request IList<StudyStorageLocation> storageLocations = StudyStorageLocation.FindStorageLocations(partition.Key, studyInstanceUid); IList<WorkQueue> entries = new List<WorkQueue>(); foreach (StudyStorageLocation location in storageLocations) { try { // insert a move series request WorkQueue request = InsertMoveSeriesRequest(context, location, seriesInstanceUids, deviceKey, externalRequest); Debug.Assert(request.WorkQueueTypeEnum.Equals(WorkQueueTypeEnum.WebMoveStudy)); entries.Add(request); } catch (Exception ex) { Platform.Log(LogLevel.Error, ex, "Errors occurred when trying to insert move request"); if (!ServerHelper.UnlockStudy(location.Key)) throw new ApplicationException("Unable to unlock the study"); } } return entries; }
private void StartPartitionListener(ServerPartition part) { var parms = new DicomScpContext(part); if (DicomSettings.Default.ListenIPV4) { var ipV4Scp = new DicomScp<DicomScpContext>(parms, AssociationVerifier.Verify, AssociationAuditLogger.InstancesTransferredAuditLogger) { ListenPort = part.Port, AeTitle = part.AeTitle, ListenAddress = IPAddress.Any }; StartScp(ipV4Scp, _listenerList); } if (DicomSettings.Default.ListenIPV6) { var ipV6Scp = new DicomScp<DicomScpContext>(parms, AssociationVerifier.Verify, AssociationAuditLogger.InstancesTransferredAuditLogger) { ListenPort = part.Port, AeTitle = part.AeTitle, ListenAddress = IPAddress.IPv6Any }; StartScp(ipV6Scp, _listenerList); } }
/// <summary> /// Inserts delete request(s) to delete a series in a study. /// </summary> /// <param name="context">The persistence context used for database connection.</param> /// <param name="partition">The <see cref="ServerPartition"/> where the study resides</param> /// <param name="studyInstanceUid">The Study Instance Uid of the study</param> /// <param name="seriesInstanceUids">The Series Instance Uid of the series to be deleted.</param> /// <param name="reason">The reason for deleting the series.</param> /// <returns>A list of DeleteSeries <see cref="WorkQueue"/> entries inserted into the system.</returns> /// <exception cref="InvalidStudyStateOperationException"></exception> public static IList<WorkQueue> DeleteSeries(IUpdateContext context, ServerPartition partition, string studyInstanceUid, List<string> seriesInstanceUids, string reason) { // Find all location of the study in the system and insert series delete request IList<StudyStorageLocation> storageLocations = StudyStorageLocation.FindStorageLocations(partition.Key, studyInstanceUid); IList<WorkQueue> entries = new List<WorkQueue>(); foreach (StudyStorageLocation location in storageLocations) { try { string failureReason; if (ServerHelper.LockStudy(location.Key, QueueStudyStateEnum.WebDeleteScheduled, out failureReason)) { // insert a delete series request WorkQueue request = InsertDeleteSeriesRequest(context, location, seriesInstanceUids, reason); Debug.Assert(request.WorkQueueTypeEnum.Equals(WorkQueueTypeEnum.WebDeleteStudy)); entries.Add(request); } else { throw new ApplicationException(String.Format("Unable to lock storage location {0} for deletion : {1}", location.Key, failureReason)); } } catch(Exception ex) { Platform.Log(LogLevel.Error, ex, "Errors occurred when trying to insert delete request"); if (!ServerHelper.UnlockStudy(location.Key)) throw new ApplicationException("Unable to unlock the study"); } } return entries; }
public StudyRulesEngine(ServerRulesEngine studyRulesEngine, StudyStorageLocation location, ServerPartition partition, StudyXml studyXml) { _studyRulesEngine = studyRulesEngine; _studyXml = studyXml; _location = location; _partition = partition ?? ServerPartition.Load(_location.ServerPartitionKey); }
/// <summary> /// Returns the <see cref="PartitionSopClass"/> for the specified sop class and partition or NULL if the sop class UID is not set. /// </summary> /// <param name="partition"></param> /// <param name="sopClassUid"></param> /// <returns></returns> public PartitionSopClass GetPartitionSopClass(ServerPartition partition, string sopClassUid) { Platform.CheckForNullReference(partition, "partition"); Platform.CheckForEmptyString(sopClassUid, "sopClassUid"); var list = LoadPartitionSopClasses(partition); return list.SingleOrDefault(entry => entry.SopClassUid == sopClassUid); }
/// <summary> /// Creates an instance of <see cref="SopInstanceImporterContext"/> to be used /// by <see cref="SopInstanceImporter"/> /// </summary> /// <param name="contextID">The ID assigned to the context. This will be used as the name of storage folder in case of duplicate.</param> /// <param name="sourceAE">Source AE title of the image(s) to be imported</param> /// <param name="partition">The <see cref="ServerPartition"/> which the image(s) will be imported to</param> public SopInstanceImporterContext(string contextID, string sourceAE, ServerPartition partition) { Platform.CheckForEmptyString(contextID, "contextID"); Platform.CheckForNullReference(partition, "partition"); _contextID = contextID; _sourceAE = sourceAE; _partition = partition; }
public ValidationStudyInfo(Study theStudy, ServerPartition partition) { ServerAE = partition.AeTitle; PatientsName = theStudy.PatientsName; PatientsId = theStudy.PatientId; StudyInstaneUid = theStudy.StudyInstanceUid; AccessionNumber = theStudy.AccessionNumber; StudyDate = theStudy.StudyDate; }
public UpdateInstanceCommand(ServerPartition partition, StudyStorageLocation studyLocation, DicomFile file) : base("Update existing SOP Instance") { _partition = partition; _studyLocation = studyLocation; _file = file; }
public ImageServerDbGenerator(ServerPartition partition, DateTime startDate, int totalStudies, int studiesPerDay, int percentWeekend) { _startDate = startDate; _totalStudies = totalStudies; _studiesPerDay = studiesPerDay; _percentWeekend = percentWeekend; _partition = partition; _backroundTask = new BackgroundTask(Run, true); }
public ServerActionContext(DicomMessageBase msg, ServerEntityKey filesystemKey, ServerPartition partition, ServerEntityKey studyLocationKey) { Message = msg; ServerPartitionKey = partition.Key; StudyLocationKey = studyLocationKey; FilesystemKey = filesystemKey; ServerPartition = partition; }
public StudyDeleteRecord(ServerPartition partition, string studyInstanceUid, string accessionNumber, string patientId, string patientName) : base("StudyDeleteRecord") { this.ServerPartitionAE = partition.AeTitle; this.StudyInstanceUid = studyInstanceUid; this.Timestamp = Platform.Time; this.AccessionNumber = accessionNumber; this.PatientId = patientId; this.PatientsName = patientName; }
public ImageServerDbGenerator(string aeTitle, string host, int port, DateTime startDate, int totalStudies, int studiesPerDay, int percentWeekend) { _startDate = startDate; _totalStudies = totalStudies; _studiesPerDay = studiesPerDay; _percentWeekend = percentWeekend; _partition = null; _aeTitle = aeTitle; _host = host; _port = port; _backroundTask = new BackgroundTask(Run, true); }
/// <summary> /// Add a partition in the database. /// </summary> /// <param name="partition"></param> /// <param name="groupsWithDataAccess"></param> public bool AddPartition(ServerPartition partition, List<string> groupsWithDataAccess) { Platform.Log(LogLevel.Info, "Adding new server partition : AETitle = {0}", partition.AeTitle); bool result = _serverAdapter.AddServerPartition(partition, groupsWithDataAccess); if (result) Platform.Log(LogLevel.Info, "Server Partition added : AETitle = {0}", partition.AeTitle); else Platform.Log(LogLevel.Info, "Failed to add Server Partition: AETitle = {0}", partition.AeTitle); return result; }
/// <summary> /// Update the partition whose GUID and new information are specified in <paramref name="partition"/>. /// /// </summary> /// <param name="partition"></param> /// <param name="groupsWithDataAccess"></param> /// <returns></returns> public bool UpdatePartition(ServerPartition partition, List<string> groupsWithDataAccess) { Platform.Log(LogLevel.Info, "Updating server partition: AETitle = {0}", partition.AeTitle); bool result = _serverAdapter.Update(partition, groupsWithDataAccess); if (result) Platform.Log(LogLevel.Info, "Server Partition updated : AETitle = {0}", partition.AeTitle); else Platform.Log(LogLevel.Info, "Failed to update Server Partition: AETitle = {0}", partition.AeTitle); return result; }
public UpdateStudyCommand(ServerPartition partition, StudyStorageLocation studyLocation, IList<BaseImageLevelUpdateCommand> imageLevelCommands, ServerRuleApplyTimeEnum applyTime) : base("Update existing study") { _partition = partition; _oldStudyLocation = studyLocation; _commands = imageLevelCommands; _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> /// 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); }
/// <summary> /// Get the server partition /// </summary> /// <param name="partitionFolderName"></param> /// <param name="partition"></param> /// <returns></returns> private bool GetServerPartition(string partitionFolderName, out ServerPartition partition) { foreach (ServerPartition part in _partitions) { if (part.PartitionFolder == partitionFolderName) { partition = part; return true; } } partition = null; return false; }
/// <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; }
/// <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); }
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); }
public StudyRulesEngine(StudyStorageLocation location, ServerPartition partition) { _location = location; _partition = partition ?? ServerPartition.Load(_location.ServerPartitionKey); }
/// <summary> /// Delete the specified partition /// /// </summary> /// <param name="partition"></param> /// <returns></returns> public bool Delete(ServerPartition partition) { Platform.Log(LogLevel.Info, "Deleting server partition: AETitle = {0}", partition.AeTitle); try { using (IUpdateContext ctx = PersistentStoreRegistry.GetDefaultStore().OpenUpdateContext(UpdateContextSyncMode.Flush)) { var broker = ctx.GetBroker<IDeleteServerPartition>(); var parms = new ServerPartitionDeleteParameters { ServerPartitionKey = partition.Key }; if (!broker.Execute(parms)) throw new Exception("Unable to delete server partition from database"); ctx.Commit(); } Platform.Log(LogLevel.Info, "Server Partition deleted : AETitle = {0}", partition.AeTitle); return true; } catch (Exception e) { Platform.Log(LogLevel.Info, e, "Failed to delete Server Partition: AETitle = {0}", partition.AeTitle); return false; } }
/// <summary> /// Checks if a specified partition can be edited /// </summary> /// <param name="partition"></param> /// <returns></returns> public bool CanEdit(ServerPartition partition) { return !partition.ServerPartitionTypeEnum.Equals(ServerPartitionTypeEnum.VFS); }
/// <summary> /// Checks if a specified partition can be deleted /// </summary> /// <param name="partition"></param> /// <returns></returns> public bool CanDelete(ServerPartition partition) { return partition.StudyCount <= 0 && !partition.ServerPartitionTypeEnum.Equals(ServerPartitionTypeEnum.VFS); }
private static bool GetStudyStorage(ServerPartition partition, string studyInstanceUid, out StudyStorage storage) { using (ServerExecutionContext context = new ServerExecutionContext()) { storage = StudyStorage.Load(context.ReadContext, partition.Key, studyInstanceUid); if (storage != null) return true; return false; } }
/// <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; }
/// <summary> /// Inserts delete request(s) to delete a sop instance in a study. /// </summary> /// <param name="context">The persistence context used for database connection.</param> /// <param name="partition">The <see cref="ServerPartition"/> where the study resides</param> /// <param name="studyInstanceUid">The Study Instance Uid of the study</param> /// <param name="seriesInstanceUid">The Series Instance Uid of the study</param> /// <param name="sopInstanceUids">The SOP Instance Uid of the instances to be deleted.</param> /// <param name="reason">The reason for deleting the sops.</param> /// <returns>A list of DeleteStudy <see cref="WorkQueue"/> entries inserted into the system.</returns> /// <exception cref="InvalidStudyStateOperationException"></exception> /// <exception cref="ExternalRequestDelayProcessingException"></exception> public static WorkQueue DeleteInstances(IUpdateContext context, ServerPartition partition, string studyInstanceUid, string seriesInstanceUid, List<string> sopInstanceUids, string reason) { StudyStorageLocation location; FilesystemMonitor.Instance.GetWritableStudyStorageLocation(partition.Key, studyInstanceUid, StudyRestore.False, StudyCache.True, out location); string failureReason; try { if (LockStudyForDeletion(location.Key, out failureReason)) { WorkQueue deleteItem = null; // insert a delete series request foreach (string uid in sopInstanceUids) { deleteItem = InsertDeleteInstanceRequest(context, location, seriesInstanceUid, uid, reason); if (deleteItem == null) throw new ApplicationException( String.Format("Unable to insert a Delete Series request for SOP Instance {0} in study {1}", uid, location.StudyInstanceUid)); } return deleteItem; } } catch (Exception ex) { Platform.Log(LogLevel.Error, ex, "Errors occurred when trying to insert delete instance request"); if (!ReleaseDeletionLock(location.Key)) Platform.Log(LogLevel.Error, "Unable to unlock the study: " + location.StudyInstanceUid); throw; } throw new ApplicationException(String.Format("Unable to lock storage location {0} for deletion of sop instances: {1}", location.Key, failureReason)); }
protected void Page_Load(object sender, EventArgs e) { ServerPartitionDataAdapter adaptor = new ServerPartitionDataAdapter(); ServerPartitionSelectCriteria criteria = new ServerPartitionSelectCriteria(); criteria.AeTitle.EqualTo(Request.QueryString[ImageServerConstants.QueryStrings.ServerAE]); _partition = adaptor.GetFirst(criteria); for(int i=1;;i++) { string qs = string.Format(ImageServerConstants.QueryStrings.StudyUID + "{0}", i); string studyuid = Request.QueryString[qs]; if(!string.IsNullOrEmpty(studyuid)) { _studies.Add(LoadStudy(studyuid)); } else { break; } } StudyGridPanel.StudyList = _studies; LoadDevices(); if (DHCPFilter.Items.Count == 0) { DHCPFilter.Items.Add(new ListItem(SR.All)); DHCPFilter.Items.Add(new ListItem(SR.DHCP)); DHCPFilter.Items.Add(new ListItem(SR.NoDHCP)); } IList<DeviceTypeEnum> deviceTypes = DeviceTypeEnum.GetAll(); if (DeviceTypeFilter.Items.Count == 0) { foreach (DeviceTypeEnum t in deviceTypes) { DeviceTypeFilter.Items.Add(new ListItem(ServerEnumDescription.GetLocalizedDescription(t), t.Lookup)); } } else { ListItem[] typeItems = new ListItem[DeviceTypeFilter.Items.Count]; DeviceTypeFilter.Items.CopyTo(typeItems, 0); DeviceTypeFilter.Items.Clear(); int count = 0; foreach (DeviceTypeEnum t in deviceTypes) { DeviceTypeFilter.Items.Add(new ListItem(ServerEnumDescription.GetLocalizedDescription(t), t.Lookup)); DeviceTypeFilter.Items[count].Selected = typeItems[count].Selected; count++; } } }
protected void Page_Load(object sender, EventArgs e) { if (Page.IsPostBack) { if (ViewState["_EditMode"] != null) _editMode = (bool) ViewState["_EditMode"]; if (ViewState["_ServerPartition"] != null) _partition = (ServerPartition) ViewState["_ServerPartition"]; if (ViewState["_EdittedRule"] != null) { var ruleKey = ViewState["_EdittedRule"] as ServerEntityKey; _rule = ServerRule.Load(ruleKey); } } }