protected override bool OnExecute(ServerActionContext context)
        {
            DateTime scheduledTime = Platform.Time;

            if (_exprScheduledTime != null)
            {
                scheduledTime = Evaluate(_exprScheduledTime, context, scheduledTime);
            }

            scheduledTime = CalculateOffsetTime(scheduledTime, _offsetTime, _units);
            XmlDocument doc = new XmlDocument();

            XmlElement element = doc.CreateElement("compress");

            doc.AppendChild(element);
            XmlAttribute syntaxAttribute = doc.CreateAttribute("syntax");

            syntaxAttribute.Value = TransferSyntax.Jpeg2000ImageCompressionUid;
            element.Attributes.Append(syntaxAttribute);

            syntaxAttribute       = doc.CreateAttribute("ratio");
            syntaxAttribute.Value = _ratio.ToString();
            element.Attributes.Append(syntaxAttribute);

            Platform.Log(LogLevel.Debug, "Jpeg 2000 Lossy Compression Scheduling: This study will be compressed on {0}", scheduledTime);
            context.CommandProcessor.AddCommand(
                new InsertFilesystemQueueCommand(_queueType, context.FilesystemKey, context.StudyLocationKey,
                                                 scheduledTime, doc));

            return(true);
        }
Beispiel #2
0
 /// <summary>
 /// Creates an instance of <see cref="UpdateSeriesCommand"/> to update the existing Series record in the database
 /// </summary>
 public UpdateSeriesCommand(StudyStorageLocation storageLocation, ServerActionContext sopContext)
     : base(String.Concat("Update Series Command"))
 {
     _storageLocation = storageLocation;
     _data            = sopContext.Message.DataSet;
     _context         = sopContext;
 }
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="context">A contentxt in which to apply the AutoRoute request.</param>
        /// <param name="device">The AE Title of the device to AutoRoute to.</param>
        public InsertAutoRouteCommand(ServerActionContext context, string device)
            : base("Update/Insert an AutoRoute WorkQueue Entry")
        {
            Platform.CheckForNullReference(context, "ServerActionContext");

            _context  = context;
            _deviceAe = device;
        }
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="context">A contentxt in which to apply the GrantAccess request.</param>
        /// <param name="authorityGroupOid">The OID of the Authority Group to grant access to the Study.</param>
        public InsertStudyDataAccessCommand(ServerActionContext context, Guid authorityGroupOid)
            : base("Update/Insert a StudyDataAccess Entry")
        {
            Platform.CheckForNullReference(context, "ServerActionContext");

            _context = context;
            _authorityGroupOid = authorityGroupOid;
        }
 public ApplyRulesCommand(string directory, string studyInstanceUid, ServerActionContext context) : base("Apply Server Rules", true)
 {
     _directory        = directory;
     _studyInstanceUid = studyInstanceUid;
     _context          = context;
     _engine           = new ServerRulesEngine(ServerRuleApplyTimeEnum.StudyRestored, _context.ServerPartitionKey);
     _engine.Load();
 }
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="context">A contentxt in which to apply the AutoRoute request.</param>
        /// <param name="device">The AE Title of the device to AutoRoute to.</param>
        public InsertAutoRouteCommand(ServerActionContext context, string device)
            : base("Update/Insert an AutoRoute WorkQueue Entry")
        {
            Platform.CheckForNullReference(context, "ServerActionContext");

            _context = context;
            _deviceAe = device;
        }
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="context">A contentxt in which to apply the GrantAccess request.</param>
        /// <param name="authorityGroupOid">The OID of the Authority Group to grant access to the Study.</param>
        public InsertStudyDataAccessCommand(ServerActionContext context, Guid authorityGroupOid)
            : base("Update/Insert a StudyDataAccess Entry")
        {
            Platform.CheckForNullReference(context, "ServerActionContext");

            _context           = context;
            _authorityGroupOid = authorityGroupOid;
        }
Beispiel #8
0
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="context">A contentxt in which to apply the AutoRoute request.</param>
        /// <param name="device">The AE Title of the device to AutoRoute to.</param>
        /// <param name="scheduledTime">The scheduled time for the AutoRoute.</param>
        /// <param name="e">An option required QC StatusEnum value</param>
        public InsertStudyAutoRouteCommand(ServerActionContext context, string device, DateTime scheduledTime, QCStatusEnum e)
            : base("Update/Insert an AutoRoute WorkQueue Entry")
        {
            Platform.CheckForNullReference(context, "ServerActionContext");

            _context       = context;
            _deviceAe      = device;
            _scheduledTime = scheduledTime;
            _qcStatus      = e;
        }
		/// <summary>
		/// Constructor.
		/// </summary>
		/// <param name="context">A contentxt in which to apply the AutoRoute request.</param>
		/// <param name="device">The AE Title of the device to AutoRoute to.</param>
		/// <param name="scheduledTime">The scheduled time for the AutoRoute.</param>
		/// <param name="e">An option required QC StatusEnum value</param>
		public InsertStudyAutoRouteCommand(ServerActionContext context, string device, DateTime scheduledTime, QCStatusEnum e)
			: base("Update/Insert an AutoRoute WorkQueue Entry")
		{
			Platform.CheckForNullReference(context, "ServerActionContext");

			_context = context;
			_deviceAe = device;
			_scheduledTime = scheduledTime;
			_qcStatus = e;
		}
Beispiel #10
0
            public ReleaseInstanceWithExistingSession()
            {
                _context  = CreateContext(InitSessionAction);
                _instance = new InstanceObject();

                Mock.Setup(o => o.CreateInstance(It.IsAny <ServerActionContext>(), typeof(IMockContract))).Returns(_instance).Verifiable();
                Mock.Setup(o => o.GenerateSessionid()).Returns(SessionHeaderValue);

                Subject.GetInstanceAsync(_context, typeof(IMockContract)).GetAwaiter().GetResult();
                _session = _context.HttpContext.Features.Get <IContractSession>();
            }
        protected override object CreateInstance(ServerActionContext context, Type type)
        {
            var factory = _factory;

            if (factory == null)
            {
                factory  = ActivatorUtilities.CreateFactory(_type, Array.Empty <Type>());
                _factory = factory;
            }

            return(factory(context.HttpContext.RequestServices, null));
        }
        private RawContractMetadata CrateContractMetadata(ServerActionContext context)
        {
            var feature = context.HttpContext.Features.Get <IBoltFeature>();
            var m       = new RawContractMetadata
            {
                Actions      = context.Contract.Actions.ToArray().Select(a => a.Name).ToList(),
                ErrorHeader  = feature.ActionContext.Configuration.Options.ServerErrorHeader,
                ContentTypes = feature.ActionContext.Configuration.AvailableSerializers.Select(s => s.MediaType).ToArray()
            };

            return(m);
        }
        public virtual async Task HandleContractMetadataAsync(ServerActionContext context)
        {
            try
            {
                string result;
                string actionName = context.HttpContext.Request.Query["action"];

                Bolt.Metadata.ActionMetadata action = null;
                if (!string.IsNullOrEmpty(actionName))
                {
                    action = _actionResolver.Resolve(context.Contract, actionName.AsReadOnlySpan());
                }

                if (action == null)
                {
                    var contractMetadata = CrateContractMetadata(context);
                    result = JsonConvert.SerializeObject(contractMetadata, Formatting.Indented, CreateSettings());
                }
                else
                {
                    context.Action = action;
                    ActionMetadata actionMetadata = new ActionMetadata();

                    if (context.Action.HasSerializableParameters)
                    {
                        actionMetadata.Parameters = context.Action.Parameters.Where(p => p.IsSerializable).Select(p => p.Name).ToArray();
                    }

                    if (context.Action.HasResult)
                    {
                        actionMetadata.Response = context.Action.ResultType.Name;
                    }

                    result = JsonConvert.SerializeObject(actionMetadata, Formatting.Indented, CreateSettings());
                }

                context.HttpContext.Response.ContentType = "application/json";
                context.HttpContext.Response.StatusCode  = 200;
                await context.HttpContext.Response.WriteAsync(result);
            }
            catch (Exception e)
            {
                Logger.LogWarning(
                    BoltLogId.HandleContractMetadataError,
                    "Failed to generate Bolt metadata for contract '{0}'. Error: {1}",
                    context.Contract.Name,
                    e);
            }
        }
        /// <summary>
        /// Overwrites existing copy with the received duplicate. Update the database, study xml and applies any SOP rules.
        /// </summary>
        /// <param name="dupFile"></param>
        /// <param name="uid"></param>
        /// <param name="studyXml"></param>
        /// <returns></returns>
        private ProcessDuplicateResult OverwriteAndUpdateDuplicate(DicomFile dupFile, WorkQueueUid uid, StudyXml studyXml)
        {
            Platform.Log(LogLevel.Info, "Overwriting duplicate SOP {0}", uid.SopInstanceUid);

            var result = new ProcessDuplicateResult();

            result.ActionTaken = DuplicateProcessResultAction.Accept;

            using (var processor = new ServerCommandProcessor("Overwrite duplicate instance"))
            {
                var sopContext = new ServerActionContext(dupFile, Context.StorageLocation.FilesystemKey, Context.StorageLocation.ServerPartition, Context.StorageLocation.Key, processor);

                var destination = Context.StorageLocation.GetSopInstancePath(uid.SeriesInstanceUid, uid.SopInstanceUid);
                processor.AddCommand(new RenameFileCommand(dupFile.Filename, destination, false));

                // Do so that the FileSize calculation inInsertStudyXmlCommand works
                dupFile.Filename = destination;

                // Update the StudyStream object
                var insertStudyXmlCommand = new InsertStudyXmlCommand(dupFile, studyXml, Context.StorageLocation);
                processor.AddCommand(insertStudyXmlCommand);

                // Ideally we don't need to insert the instance into the database since it's a duplicate.
                // However, we need to do so to ensure the Study record is recreated if we are dealing with an orphan study.
                // For other cases, this will cause the instance count in the DB to be out of sync with the filesystem.
                // But it will be corrected at the end of the processing when the study verification is executed.
                processor.AddCommand(new UpdateInstanceCommand(Context.StorageLocation.ServerPartition, Context.StorageLocation, dupFile));

                processor.AddCommand(new DeleteWorkQueueUidCommand(uid));

                processor.AddCommand(new ApplySopRulesCommand(sopContext, Context.SopProcessedRulesEngine));

                if (!processor.Execute())
                {
                    EventManager.FireEvent(this, new FailedUpdateSopEventArgs {
                        File = dupFile, ServerPartitionEntry = Context.StorageLocation.ServerPartition, WorkQueueUidEntry = uid, WorkQueueEntry = WorkQueueItem, FileLength = (ulong)insertStudyXmlCommand.FileSize, FailureMessage = processor.FailureReason
                    });

                    // cause the item to fail
                    throw new Exception(string.Format("Error occurred when trying to overwrite duplicate in the filesystem."), processor.FailureException);
                }

                EventManager.FireEvent(this, new UpdateSopEventArgs {
                    File = dupFile, ServerPartitionEntry = Context.StorageLocation.ServerPartition, WorkQueueUidEntry = uid, WorkQueueEntry = WorkQueueItem, FileLength = (ulong)insertStudyXmlCommand.FileSize
                });
            }

            return(result);
        }
		protected override bool OnExecute(ServerActionContext context)
		{
			XmlDocument doc = new XmlDocument();

			XmlElement element = doc.CreateElement("compress");
			doc.AppendChild(element);
			XmlAttribute syntaxAttribute = doc.CreateAttribute("syntax");
			syntaxAttribute.Value = TransferSyntax.Jpeg2000ImageCompressionLosslessOnlyUid;
			element.Attributes.Append(syntaxAttribute);

			context.CommandProcessor.AddCommand(
				new DicomCompressCommand(context.Message, doc));

			return true;
		}
Beispiel #16
0
            public async Task ExecuteAsync(ServerActionContext context)
            {
                var result = _compiledLambda(context.ContractInstance, context.Parameters);

                if (_isTaskResult)
                {
                    await(Task) result;
                    if (_taskResultProvider != null)
                    {
                        context.ActionResult = _taskResultProvider((Task)result);
                    }
                }
                else
                {
                    context.ActionResult = result;
                }
            }
        protected override bool OnExecute(ServerActionContext context)
        {
            XmlDocument doc = new XmlDocument();

            XmlElement element = doc.CreateElement("compress");

            doc.AppendChild(element);
            XmlAttribute syntaxAttribute = doc.CreateAttribute("syntax");

            syntaxAttribute.Value = TransferSyntax.Jpeg2000ImageCompressionLosslessOnlyUid;
            element.Attributes.Append(syntaxAttribute);

            context.CommandProcessor.AddCommand(
                new DicomCompressCommand(context.Message, doc));

            return(true);
        }
Beispiel #18
0
        private void SaveFile(DicomFile file)
        {
            String seriesInstanceUid = file.DataSet[DicomTags.SeriesInstanceUid].GetString(0, String.Empty);
            String sopInstanceUid    = file.DataSet[DicomTags.SopInstanceUid].GetString(0, String.Empty);

            String destPath = _oldStudyLocation.FilesystemPath;

            using (ServerCommandProcessor filesystemUpdateProcessor = new ServerCommandProcessor("Update Study"))
            {
                filesystemUpdateProcessor.AddCommand(new CreateDirectoryCommand(destPath));

                destPath = Path.Combine(destPath, _partition.PartitionFolder);
                filesystemUpdateProcessor.AddCommand(new CreateDirectoryCommand(destPath));

                destPath = Path.Combine(destPath, _oldStudyFolder);
                filesystemUpdateProcessor.AddCommand(new CreateDirectoryCommand(destPath));

                destPath = Path.Combine(destPath, _newStudyInstanceUid);
                filesystemUpdateProcessor.AddCommand(new CreateDirectoryCommand(destPath));

                destPath = Path.Combine(destPath, seriesInstanceUid);
                filesystemUpdateProcessor.AddCommand(new CreateDirectoryCommand(destPath));

                destPath  = Path.Combine(destPath, sopInstanceUid);
                destPath += ServerPlatform.DicomFileExtension;

                // Overwrite the prior file
                SaveDicomFileCommand saveCommand = new SaveDicomFileCommand(destPath, file, false);
                filesystemUpdateProcessor.AddCommand(saveCommand);

                if (_rulesEngine != null)
                {
                    ServerActionContext context = new ServerActionContext(file, _oldStudyLocation.FilesystemKey, _partition, _oldStudyLocation.Key)
                    {
                        CommandProcessor = filesystemUpdateProcessor
                    };
                    _rulesEngine.Execute(context);
                }

                if (!filesystemUpdateProcessor.Execute())
                {
                    throw new ApplicationException(String.Format("Unable to update image {0} : {1}", file.Filename, filesystemUpdateProcessor.FailureReason));
                }
            }
        }
Beispiel #19
0
        public virtual async Task<bool> HandleBoltMetadataAsync(ServerActionContext context, IEnumerable<IContractInvoker> contracts)
        {
            try
            {
                string result = JsonConvert.SerializeObject(
                    contracts.Select(c => BoltFramework.GetContractName(c.Contract)).ToList(),
                    Formatting.Indented,
                    new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });

                await context.HttpContext.Response.WriteAsync(result);
                return true;
            }
            catch (Exception e)
            {
                Logger.LogWarning(BoltLogId.HandleBoltRootError, "Failed to generate Bolt root metadata. Error: {0}", e);
                return false;
            }
        }
        public virtual async Task HandleBoltMetadataAsync(ServerActionContext context, IEnumerable <IContractInvoker> contracts)
        {
            try
            {
                string result = JsonConvert.SerializeObject(
                    contracts.Select(c => c.Contract.NormalizedName).ToList(),
                    Formatting.Indented,
                    new JsonSerializerSettings {
                    NullValueHandling = NullValueHandling.Ignore
                });

                await context.HttpContext.Response.WriteAsync(result);
            }
            catch (Exception e)
            {
                Logger.LogWarning(BoltLogId.HandleBoltRootError, "Failed to generate Bolt root metadata. Error: {0}", e);
            }
        }
        public sealed override async Task<object> GetInstanceAsync(ServerActionContext context, Type type)
        {
            IContractSession contractSession;

            if (context.Action == context.SessionContract.InitSession)
            {
                contractSession = await _sessionFactory.CreateAsync(context.HttpContext, await base.GetInstanceAsync(context, type));
                context.ContractInstance = contractSession.Instance;
                context.HttpContext.SetFeature(contractSession);

                await OnInstanceCreatedAsync(context, contractSession.SessionId);
                return contractSession.Instance;
            }

            contractSession = await _sessionFactory.GetExistingAsync(context.HttpContext, () => base.GetInstanceAsync(context, type));
            context.HttpContext.SetFeature(contractSession);
            return contractSession.Instance;
        }
Beispiel #22
0
        public sealed override async Task <object> GetInstanceAsync(ServerActionContext context, Type type)
        {
            IContractSession contractSession;

            if (context.Action == context.Contract.Session.InitSession)
            {
                contractSession = await _sessionFactory.CreateAsync(context.HttpContext, () => CreateInstance(context, type));

                context.ContractInstance = contractSession.Instance;
                context.HttpContext.Features.Set <IContractSession>(contractSession);

                await OnInstanceCreatedAsync(context, contractSession.SessionId);

                return(contractSession.Instance);
            }

            contractSession = await _sessionFactory.GetExistingAsync(context.HttpContext, () => CreateInstance(context, type));

            context.HttpContext.Features.Set <IContractSession>(contractSession);
            return(contractSession.Instance);
        }
        void SaveDuplicateReport(WorkQueueUid uid, string sourceFile, string destinationFile, DicomFile dupFile, StudyXml studyXml)
        {
            using (var processor = new ServerCommandProcessor("Save duplicate report"))
            {
                var sopContext = new ServerActionContext(dupFile, Context.StorageLocation.FilesystemKey, Context.StorageLocation.ServerPartition, Context.StorageLocation.Key, processor);

                processor.AddCommand(new RenameFileCommand(sourceFile, destinationFile, false));

                // Update the StudyStream object
                processor.AddCommand(new InsertStudyXmlCommand(dupFile, studyXml, Context.StorageLocation));

                // Update the series
                processor.AddCommand(new UpdateSeriesCommand(Context.StorageLocation, sopContext));

                processor.AddCommand(new DeleteWorkQueueUidCommand(uid));

                processor.AddCommand(new ApplySopRulesCommand(sopContext, Context.SopProcessedRulesEngine));

                processor.Execute();
            }
        }
Beispiel #24
0
        public sealed override async Task ReleaseInstanceAsync(ServerActionContext context, object obj, Exception error)
        {
            var session = context.HttpContext.Features.Get <IContractSession>();

            if (session == null)
            {
                return;
            }

            if (context.Action == context.Contract.Session.InitSession)
            {
                if (error != null)
                {
                    try
                    {
                        await session.DestroyAsync();
                        await OnInstanceReleasedAsync(context, session.SessionId);
                    }
                    catch (Exception e)
                    {
                        Debug.Assert(
                            false,
                            "Instance release failed after the session initialization error. This exception will be supressed and the session initialization error will be propagated to client.",
                            e.ToString());
                    }
                }
            }
            else if (context.Action == context.Contract.Session.DestroySession)
            {
                await session.DestroyAsync();
                await OnInstanceReleasedAsync(context, session.SessionId);
            }
            else
            {
                await session.CommitAsync();
            }
        }
        public sealed override async Task ReleaseInstanceAsync(ServerActionContext context, object obj, Exception error)
        {
            var session = context.HttpContext.GetFeature<IContractSession>();
            if (session == null)
            {
                return;
            }

            if (context.Action == context.SessionContract.InitSession)
            {
                if (error != null)
                {
                    try
                    {
                        await session.DestroyAsync();
                        await OnInstanceReleasedAsync(context, session.SessionId);
                    }
                    catch (Exception e)
                    {
                        Debug.Assert(
                            false,
                            "Instance release failed after the session initialization error. This exception will be supressed and the session initialization error will be propagated to client.",
                            e.ToString());
                    }
                }
            }
            else if (context.Action == context.SessionContract.DestroySession)
            {
                await session.DestroyAsync();
                await OnInstanceReleasedAsync(context, session.SessionId);
            }
            else
            {
                await session.CommitAsync();
            } 
        }
Beispiel #26
0
 public Task ReleaseInstanceAsync(ServerActionContext context, object obj, Exception error)
 {
     return(Task.FromResult(true));
 }
        private void RestoreOnlineStudy(RestoreQueue queueItem, string zipFile, string destinationFolder)
        {
            try
            {
                using (var processor = new ServerCommandProcessor("HSM Restore Online Study"))
                {
                    var zipService = Platform.GetService <IZipService>();
                    using (var zipWriter = zipService.OpenWrite(zipFile))
                    {
                        foreach (string file in zipWriter.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.
                    var context =
                        new ServerActionContext(null, _location.FilesystemKey, _hsmArchive.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, _hsmArchive.PartitionArchive.Description);
                        queueItem.FailureDescription = processor.FailureReason;
                        _hsmArchive.UpdateRestoreQueue(queueItem, RestoreQueueStatusEnum.Failed, Platform.Time);
                    }
                    else
                    {
                        // Unlock the Queue Entry and set to complete
                        using (IUpdateContext update = PersistentStoreRegistry.GetDefaultStore().OpenUpdateContext(UpdateContextSyncMode.Flush))
                        {
                            _hsmArchive.UpdateRestoreQueue(update, queueItem, RestoreQueueStatusEnum.Completed, Platform.Time.AddSeconds(60));
                            var studyLock = update.GetBroker <ILockStudy>();
                            var 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,
                                             _hsmArchive.ServerPartition.Description);
                            }

                            update.Commit();

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

                            _location = ReloadStorageLocation();
                            OnStudyRestored(_location);
                        }
                    }
                }
            }
            catch (StudyIntegrityValidationFailure ex)
            {
                // study has been restored but it seems corrupted. Need to reprocess it.
                ReprocessStudy(_location, ex.Message);
            }
            catch (Exception e)
            {
                Platform.Log(LogLevel.Error, e, "Unexpected exception processing restore request for {0} on archive {1}",
                             _location.StudyInstanceUid, _hsmArchive.PartitionArchive.Description);
                queueItem.FailureDescription = e.Message;
                _hsmArchive.UpdateRestoreQueue(queueItem, RestoreQueueStatusEnum.Failed, Platform.Time);
            }
        }
Beispiel #28
0
 public Task ReleaseInstanceAsync(ServerActionContext context, object obj, Exception error)
 {
     return Task.FromResult(true);
 }
Beispiel #29
0
 private void SetupRelease(ServerActionContext ctxt = null)
 {
     Mock.Setup(o => o.OnInstanceReleased(ctxt ?? _context, SessionHeaderValue)).Verifiable();
 }
Beispiel #30
0
 private ContractMetadata CrateContractMetadata(ServerActionContext context)
 {
     var feature = context.HttpContext.GetFeature<IBoltFeature>();
     var m = new ContractMetadata
                 {
                     Actions = BoltFramework.GetContractActions(context.Contract).Select(a => a.Name).ToList(),
                     ErrorHeader = feature.ActionContext.Configuration.Options.ServerErrorHeader,
                     ContentType = feature.ActionContext.Configuration.Serializer.ContentType
                 };
     return m;
 }
Beispiel #31
0
 public BoltFeature(ServerActionContext actionContext)
 {
     ActionContext = actionContext;
 }
 protected virtual Task OnInstanceReleasedAsync(ServerActionContext context, string sessionId)
 {
     return CompletedTask.Done;
 }
Beispiel #33
0
        /// <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();
                }
            }
        }
Beispiel #34
0
 Task <object> IInstanceProvider.GetInstanceAsync(ServerActionContext context, Type type)
 {
     return(Task.FromResult(CurrentInstance));
 }
Beispiel #35
0
        public virtual async Task<bool> HandleContractMetadataAsync(ServerActionContext context)
        {
            try
            {
                string result = string.Empty;
                string actionName = context.HttpContext.Request.Query["action"]?.Trim();
                MethodInfo action = null;

                if (!string.IsNullOrEmpty(actionName))
                {
                    action = _actionResolver.Resolve(context.Contract, actionName);
                }

                if (action == null)
                {
                    var contractMetadata = CrateContractMetadata(context);
                    result = JsonConvert.SerializeObject(
                        contractMetadata,
                        Formatting.Indented,
                        new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
                }
                else
                {
                    context.Action = action;
                    JsonSchema actionSchema = new JsonSchema
                                                  {
                                                      Properties = new Dictionary<string, JsonSchema>(),
                                                      Description = $"Request and response parameters for action '{actionName}'."
                                                  };

                    List<ParameterInfo> actionParameters = BoltFramework.GetSerializableParameters(action).ToList();
                    if (actionParameters.Any())
                    {
                        JsonSchemaGenerator generator = new JsonSchemaGenerator();
                        JsonSchema arguments = new JsonSchema
                                                   {
                                                       Properties =
                                                           actionParameters.ToDictionary(
                                                               p => p.Name,
                                                               p => generator.Generate(p.ParameterType)),
                                                       Required = true,
                                                       Type = JsonSchemaType.Object,
                                                   };

                        actionSchema.Properties.Add("request", arguments);
                    }

                    if (context.ResponseType != typeof(void))
                    {
                        JsonSchemaGenerator generator = new JsonSchemaGenerator();
                        actionSchema.Properties.Add("response", generator.Generate(context.ResponseType));
                    }

                    using (var sw = new StringWriter())
                    {
                        using (JsonTextWriter jw = new JsonTextWriter(sw))
                        {

                            jw.Formatting = Formatting.Indented;
                            actionSchema.WriteTo(jw);
                        }
                        result = sw.GetStringBuilder().ToString();
                    }
                }

                context.HttpContext.Response.ContentType = "application/json";
                context.HttpContext.Response.StatusCode = 200;
                await context.HttpContext.Response.WriteAsync(result);
                return true;
            }
            catch (Exception e)
            {
                Logger.LogWarning(
                    BoltLogId.HandleContractMetadataError,
                    "Failed to generate Bolt metadata for contract '{0}'. Error: {1}",
                    context.Contract.Name,
                    e);
                return false;
            }
        }
 public ApplySopRulesCommand(ServerActionContext context, ServerRulesEngine engine)
     : base("Apply SOP Rules Engine and insert Archival Request", false)
 {
     _context = context;
     _engine  = engine;
 }
Beispiel #37
0
 protected virtual object CreateInstance(ServerActionContext context, Type type)
 {
     var createFactory = _typeActivatorCache.GetOrAdd(type, t => ActivatorUtilities.CreateFactory(type, new Type[] { }));
     return createFactory(context.HttpContext.ApplicationServices, null);
 }
Beispiel #38
0
 private void SetupInit(ServerActionContext ctxt, string session = "testsession", object instance = null)
 {
     Mock.Setup(o => o.CreateInstance(ctxt, typeof(IMockContract))).Returns(instance ?? new object()).Verifiable();
     Mock.Setup(o => o.GenerateSessionid()).Returns(session ?? Guid.NewGuid().ToString()).Verifiable();
 }
 public Task ReleaseInstanceAsync(ServerActionContext context, object obj, Exception error)
 {
     return CompletedTask.Done;
 }
Beispiel #40
0
 protected override Task OnInstanceReleasedAsync(ServerActionContext context, string sessionId)
 {
     _actions.Object.OnInstanceReleased(context, sessionId);
     return(Task.FromResult(true));
 }
 public Task <object> GetInstanceAsync(ServerActionContext context, Type type)
 {
     return(Task.FromResult(_instance));
 }
 public Task ReleaseInstanceAsync(ServerActionContext context, object obj, Exception error)
 {
     return(CompletedTask.Done);
 }
Beispiel #43
0
 public virtual Task ReleaseInstanceAsync(ServerActionContext context, object obj, Exception error)
 {
     (obj as IDisposable)?.Dispose();
     return CompletedTask.Done;
 }
 public Task<object> GetInstanceAsync(ServerActionContext context, Type type)
 {
     return Task.FromResult(_instance);
 }
Beispiel #45
0
 public virtual Task<object> GetInstanceAsync(ServerActionContext context, Type type)
 {
     return Task.FromResult(CreateInstance(context, type));
 }
        public void RestoreNearlineStudy(RestoreQueue queueItem, string zipFile, string studyFolder)
        {
            ServerFilesystemInfo fs = _hsmArchive.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";
                _hsmArchive.UpdateRestoreQueue(queueItem, RestoreQueueStatusEnum.Pending, scheduleTime);
                return;
            }

            string destinationFolder = Path.Combine(fs.Filesystem.FilesystemPath, _hsmArchive.ServerPartition.PartitionFolder);

            StudyStorageLocation restoredLocation = null;

            try
            {
                using (var processor = new ServerCommandProcessor("HSM 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.
                    var context =
                        new ServerActionContext(null, fs.Filesystem.GetKey(), _hsmArchive.ServerPartition,
                                                queueItem.StudyStorageKey)
                    {
                        CommandProcessor = processor
                    };
                    processor.AddCommand(
                        new ApplyRulesCommand(destinationFolder, _studyStorage.StudyInstanceUid, context));

                    // Do the actual insert into the DB
                    var insertStorageCommand = new InsertFilesystemStudyStorageCommand(
                        _hsmArchive.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, _hsmArchive.PartitionArchive.Description);
                        queueItem.FailureDescription = processor.FailureReason;
                        _hsmArchive.UpdateRestoreQueue(queueItem, RestoreQueueStatusEnum.Failed, Platform.Time);
                    }
                    else
                    {
                        restoredLocation = insertStorageCommand.Location;

                        // Unlock the Queue Entry
                        using (
                            IUpdateContext update = PersistentStoreRegistry.GetDefaultStore().OpenUpdateContext(UpdateContextSyncMode.Flush))
                        {
                            bool retVal    = _hsmArchive.UpdateRestoreQueue(update, queueItem, RestoreQueueStatusEnum.Completed, Platform.Time.AddSeconds(60));
                            var  studyLock = update.GetBroker <ILockStudy>();
                            var  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,
                                                  _hsmArchive.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,
                                         _hsmArchive.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, _hsmArchive.PartitionArchive.Description);
                _hsmArchive.UpdateRestoreQueue(queueItem, RestoreQueueStatusEnum.Failed, Platform.Time);
            }
        }
Beispiel #47
0
        private void InsertInstance(DicomFile file, StudyXml stream, WorkQueueUid uid, string deleteFile)
        {
            using (ServerCommandProcessor processor = new ServerCommandProcessor("Processing WorkQueue DICOM file"))
            {
                EventsHelper.Fire(OnInsertingSop, this, new SopInsertingEventArgs {
                    Processor = processor
                });

                InsertInstanceCommand insertInstanceCommand = null;
                InsertStudyXmlCommand insertStudyXmlCommand = null;

                String patientsName = file.DataSet[DicomTags.PatientsName].GetString(0, String.Empty);
                _modality = file.DataSet[DicomTags.Modality].GetString(0, String.Empty);

                if (_context.UpdateCommands.Count > 0)
                {
                    foreach (BaseImageLevelUpdateCommand command in _context.UpdateCommands)
                    {
                        command.File = file;
                        processor.AddCommand(command);
                    }
                }

                try
                {
                    // Create a context for applying actions from the rules engine
                    ServerActionContext context =
                        new ServerActionContext(file, _context.StorageLocation.FilesystemKey, _context.Partition, _context.StorageLocation.Key);
                    context.CommandProcessor = processor;

                    _context.SopCompressionRulesEngine.Execute(context);
                    String seriesUid = file.DataSet[DicomTags.SeriesInstanceUid].GetString(0, String.Empty);
                    String sopUid    = file.DataSet[DicomTags.SopInstanceUid].GetString(0, String.Empty);
                    String finalDest = _context.StorageLocation.GetSopInstancePath(seriesUid, sopUid);

                    if (_context.UpdateCommands.Count > 0)
                    {
                        processor.AddCommand(new SaveDicomFileCommand(_context.StorageLocation, file, file.Filename != finalDest));
                    }
                    else if (file.Filename != finalDest || processor.CommandCount > 0)
                    {
                        // Have to be careful here about failure on exists vs. not failing on exists
                        // because of the different use cases of the importer.
                        // save the file in the study folder, or if its been compressed
                        processor.AddCommand(new SaveDicomFileCommand(finalDest, file, file.Filename != finalDest));
                    }

                    // Update the StudyStream object
                    insertStudyXmlCommand = new InsertStudyXmlCommand(file, stream, _context.StorageLocation);
                    processor.AddCommand(insertStudyXmlCommand);

                    // Have the rules applied during the command processor, and add the objects.
                    processor.AddCommand(new ApplySopRulesCommand(context, _context.SopProcessedRulesEngine));

                    // If specified, delete the file
                    if (deleteFile != null)
                    {
                        processor.AddCommand(new FileDeleteCommand(deleteFile, true));
                    }

                    // Insert into the database, but only if its not a duplicate so the counts don't get off
                    insertInstanceCommand = new InsertInstanceCommand(file, _context.StorageLocation);
                    processor.AddCommand(insertInstanceCommand);

                    // Do a check if the StudyStatus value should be changed in the StorageLocation.  This
                    // should only occur if the object has been compressed in the previous steps.
                    processor.AddCommand(new UpdateStudyStatusCommand(_context.StorageLocation, file));

                    if (uid != null)
                    {
                        processor.AddCommand(new DeleteWorkQueueUidCommand(uid));
                    }

                    // Do the actual processing
                    if (!processor.Execute())
                    {
                        Platform.Log(LogLevel.Error, "Failure processing command {0} for SOP: {1}", processor.Description, file.MediaStorageSopInstanceUid);
                        Platform.Log(LogLevel.Error, "File that failed processing: {0}", file.Filename);
                        throw new ApplicationException("Unexpected failure (" + processor.FailureReason + ") executing command for SOP: " + file.MediaStorageSopInstanceUid, processor.FailureException);
                    }
                    Platform.Log(ServerPlatform.InstanceLogLevel, "Processed SOP: {0} for Patient {1}", file.MediaStorageSopInstanceUid, patientsName);
                }
                catch (Exception e)
                {
                    Platform.Log(LogLevel.Error, e, "Unexpected exception when {0}.  Rolling back operation.",
                                 processor.Description);
                    processor.Rollback();
                    throw new ApplicationException("Unexpected exception when processing file.", e);
                }
                finally
                {
                    if (insertInstanceCommand != null && insertInstanceCommand.Statistics.IsSet)
                    {
                        _instanceStats.InsertDBTime.Add(insertInstanceCommand.Statistics);
                    }
                    if (insertStudyXmlCommand != null && insertStudyXmlCommand.Statistics.IsSet)
                    {
                        _instanceStats.InsertStreamTime.Add(insertStudyXmlCommand.Statistics);
                    }
                }
            }
        }
Beispiel #48
0
 Task<object> IInstanceProvider.GetInstanceAsync(ServerActionContext context, Type type)
 {
     return Task.FromResult(CurrentInstance);
 }