Пример #1
0
 public StudyItem(Study study)
 {
     _study               = study;
     StudyStorage         = StudyStorage.Load(_study.StudyStorageKey);
     StudyStorageLocation = StudyStorageLocation.FindStorageLocations(StudyStorage).FirstOrDefault();
     _status              = StudyStorage.StudyStatusEnum.Description;
 }
Пример #2
0
        public override void DataBind()
        {
            ExistingPatientSeriesGridView.DataSource    = ReconcileDetails.ExistingStudy.Series;
            ConflictingPatientSeriesGridView.DataSource = ReconcileDetails.ConflictingStudyInfo.Series;

            StudyStorage storage =
                StudyStorage.Load(HttpContextData.Current.ReadContext, StudyIntegrityQueueItem.StudyStorageKey);

            IList <StudyStorageLocation> studyLocations = StudyStorageLocation.FindStorageLocations(storage);
            StudyStorageLocation         location       = studyLocations[0];

            StudyLocation.Text = location.GetStudyPath();

            ConflictingStudyLocation.Text = ReconcileDetails != null
                                                ? ReconcileDetails.GetFolderPath()
                                                : SR.NotSpecified;

            string reason;

            CanReconcile         = _controller.CanReconcile(location, out reason);
            MessagePanel.Visible = !CanReconcile;
            AlertMessage.Text    = reason;
            OKButton.Enabled     = CanReconcile;
            OptionRow.Visible    = CanReconcile;
            base.DataBind();
        }
Пример #3
0
        protected void DeleteItemButton_Click(object sender, EventArgs e)
        {
            RestoreQueueItemList.RefreshCurrentPage();

            IList <Model.RestoreQueue> items = RestoreQueueItemList.SelectedItems;

            if (items != null && items.Count > 0)
            {
                if (items.Count > 1)
                {
                    MessageBox.Message = string.Format(SR.MultipleRestoreQueueDelete);
                }
                else
                {
                    MessageBox.Message = string.Format(SR.SingleRestoreQueueDelete);
                }

                MessageBox.Message += "<table>";
                foreach (Model.RestoreQueue item in items)
                {
                    String text = "";
                    String.Format("<tr align='left'><td>{0}:{1}</td></tr>",
                                  SR.StudyInstanceUID,
                                  StudyStorage.Load(item.StudyStorageKey).StudyInstanceUid);
                    MessageBox.Message += text;
                }
                MessageBox.Message += "</table>";

                MessageBox.MessageType = MessageBox.MessageTypeEnum.YESNO;
                MessageBox.Data        = items;
                MessageBox.Show();
            }
        }
        public string GetFolderPath()
        {
            if (_location == null)
            {
                if (_studyStorage == null)
                {
                    using (IReadContext context = PersistentStoreRegistry.GetDefaultStore().OpenReadContext())
                    {
                        _studyStorage = StudyStorage.Load(context, _item.StudyStorageKey);
                    }
                }

                _location = StudyStorageLocation.FindStorageLocations(_studyStorage)[0];
            }

            String path = Path.Combine(_location.FilesystemPath, _location.PartitionFolder);

            path = Path.Combine(path, ServerPlatform.ReconcileStorageFolder);
            if (!string.IsNullOrEmpty(_item.GroupID))
            {
                path = Path.Combine(path, _item.GroupID);
            }
            path = Path.Combine(path, _location.StudyInstanceUid);

            return(path);
        }
Пример #5
0
        /// <summary>
        /// Returns the name of the directory in the filesytem
        /// where the study with the specified information will be stored.
        /// </summary>
        /// <returns></returns>
        ///
        private static string ResolveStorageFolder(ServerEntityKey partitionKey, string studyInstanceUid, string studyDate, IPersistenceContext persistenceContext, bool checkExisting)
        {
            string folder;

            if (checkExisting)
            {
                StudyStorage storage = StudyStorage.Load(persistenceContext, partitionKey, studyInstanceUid);
                if (storage != null)
                {
                    folder = ImageServerCommonConfiguration.UseReceiveDateAsStudyFolder
                                                                 ? storage.InsertTime.ToString("yyyyMMdd")
                                                                 : String.IsNullOrEmpty(studyDate)
                                                                           ? ImageServerCommonConfiguration.DefaultStudyRootFolder
                                                                           : studyDate;
                    return(folder);
                }
            }

            folder = ImageServerCommonConfiguration.UseReceiveDateAsStudyFolder
                                                 ? Platform.Time.ToString("yyyyMMdd")
                                                 : String.IsNullOrEmpty(studyDate)
                                                           ? ImageServerCommonConfiguration.DefaultStudyRootFolder
                                                           : studyDate;
            return(folder);
        }
Пример #6
0
        protected override string GetTemporaryPath()
        {
            StudyStorageLocation storage = StudyStorageLocation.FindStorageLocations(StudyStorage.Load(_item.StudyStorageKey))[0];

            if (storage == null)
            {
                return(base.GetTemporaryPath());
            }
            else
            {
                String basePath = GetTempPathRoot();

                if (String.IsNullOrEmpty(basePath))
                {
                    basePath = Path.Combine(storage.FilesystemPath, "temp");
                }
                String tempDirectory = Path.Combine(basePath, String.Format("ArchiveQueue-{0}", _item.GetKey()));

                for (int i = 2; i < 1000; i++)
                {
                    if (!Directory.Exists(tempDirectory))
                    {
                        break;
                    }

                    tempDirectory = Path.Combine(basePath, String.Format("ArchiveQueue-{0}({1})", _item.GetKey(), i));
                }

                if (!Directory.Exists(tempDirectory))
                {
                    Directory.CreateDirectory(tempDirectory);
                }
                return(tempDirectory);
            }
        }
Пример #7
0
        /// <summary>
        /// Creates an instance of <see cref="StudyDetails"/> base on a <see cref="Study"/> object.
        /// </summary>
        /// <param name="study"></param>
        /// <returns></returns>
        public StudyDetails CreateStudyDetail(Study study)
        {
            var details = new StudyDetails();

            details.StudyInstanceUID = study.StudyInstanceUid;
            details.PatientName      = study.PatientsName;
            details.AccessionNumber  = study.AccessionNumber;
            details.PatientID        = study.PatientId;
            details.StudyDescription = study.StudyDescription;
            details.StudyDate        = study.StudyDate;
            details.StudyTime        = study.StudyTime;

            var controller = new StudyController();

            using (IReadContext ctx = PersistentStoreRegistry.GetDefaultStore().OpenReadContext())
            {
                details.Modalities = controller.GetModalitiesInStudy(ctx, study);
            }

            if (study.StudyInstanceUid != null)
            {
                StudyStorage storages = StudyStorage.Load(study.StudyStorageKey);
                if (storages != null)
                {
                    details.WriteLock = storages.WriteLock;
                    details.ReadLock  = storages.ReadLock;
                    details.Status    = storages.StudyStatusEnum.ToString();
                }
            }

            return(details);
        }
Пример #8
0
        protected void DeleteItemButton_Click(object sender, EventArgs e)
        {
            IList <Model.ArchiveQueue> items = ArchiveQueueItemList.SelectedItems;

            if (items != null && items.Count > 0)
            {
                if (items.Count > 1)
                {
                    MessageBox.Message = string.Format(SR.MultipleArchiveQueueDelete);
                }
                else
                {
                    MessageBox.Message = string.Format(SR.SingleArchiveQueueDelete);
                }

                MessageBox.Message += "<table style=\"border: solid #CCCCCC 2px; margin-top: 5px;\">";
                foreach (Model.ArchiveQueue item in items)
                {
                    MessageBox.Message += String.Format("<tr><td style=\"font-weight: bold; color: #618FAD\">{0}:</td><td style=\"font-weight: normal; color: black;\">{1}</td></tr>",
                                                        SR.StudyInstanceUID,
                                                        StudyStorage.Load(item.StudyStorageKey).StudyInstanceUid);
                }
                MessageBox.Message += "</table>";

                MessageBox.MessageType  = MessageBox.MessageTypeEnum.YESNO;
                MessageBox.MessageStyle = "color: #FF0000; font-weight: bold;";
                MessageBox.Data         = items;
                MessageBox.Show();
            }
        }
 private void LoadStorageLocation()
 {
     if (_storageLocation == null)
     {
         var studyStorage = StudyStorage.Load(HttpContext.Current.GetSharedPersistentContext(), TheStudyIntegrityQueueItem.StudyStorageKey);
         _storageLocation = StudyStorageLocation.FindStorageLocations(studyStorage)[0];
     }
 }
Пример #10
0
 private void LoadStorageLocation()
 {
     if (_storageLocation == null)
     {
         var studyStorage = StudyStorage.Load(HttpContextData.Current.ReadContext, TheStudyIntegrityQueueItem.StudyStorageKey);
         _storageLocation = StudyStorageLocation.FindStorageLocations(studyStorage)[0];
     }
 }
Пример #11
0
        public InconsistentDataSIQRecord(StudyIntegrityQueue queue)
        {
            _queueItem = queue;
            ReconcileStudyWorkQueueData data = XmlUtils.Deserialize <ReconcileStudyWorkQueueData>(queue.Details);

            _conflictingImageDetails    = data.Details;
            _conflictingImageDescriptor = XmlUtils.Deserialize <ImageSetDescriptor>(queue.StudyData);
            StudyStorage storage = StudyStorage.Load(HttpContextData.Current.ReadContext, queue.StudyStorageKey);
            Study        study   = storage.LoadStudy(HttpContextData.Current.ReadContext);

            _existingStudyInfo = new StudyInformation(new ServerEntityAttributeProvider(study));
        }
Пример #12
0
        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);
            }
        }
Пример #13
0
 private void DetermineTargetLocation()
 {
     if (Context.History.DestStudyStorageKey != null)
     {
         _destinationStudyStorage =
             StudyStorageLocation.FindStorageLocations(StudyStorage.Load(Context.History.DestStudyStorageKey))[0];
     }
     else
     {
         _destinationStudyStorage            = Context.WorkQueueItemStudyStorage;
         Context.History.DestStudyStorageKey = _destinationStudyStorage.Key;
     }
 }
Пример #14
0
        public static ReconcileHistoryRecord ReadReconcileRecord(StudyHistory historyRecord)
        {
            Platform.CheckTrue(historyRecord.StudyHistoryTypeEnum == StudyHistoryTypeEnum.StudyReconciled,
                               "History record has invalid history record type");

            ReconcileHistoryRecord record = new ReconcileHistoryRecord();

            record.InsertTime           = historyRecord.InsertTime;
            record.StudyStorageLocation = StudyStorageLocation.FindStorageLocations(StudyStorage.Load(historyRecord.StudyStorageKey))[0];
            StudyReconcileDescriptorParser parser = new StudyReconcileDescriptorParser();

            record.UpdateDescription = parser.Parse(historyRecord.ChangeDescription);
            return(record);
        }
Пример #15
0
        /// <summary>
        /// Inserts an External edit request(s) to update a study.
        /// </summary>
        /// <remarks>
        /// The External Edit request can be for a study in any state.  The study could be offline/nearline/etc.
        /// </remarks>
        /// <param name="context">The persistence context used for database connection.</param>
        /// <param name="studyStorageKey">The StudyStorage record key</param>
        /// <param name="reason">The reason the study is being editted</param>
        /// <param name="user">A string identifying the user that triggered the edit and is stored with the history for the edit.</param>
        /// <exception cref="InvalidStudyStateOperationException"></exception>
        /// <param name="updateItems"></param>
        /// <param name="editType">The request is a web edit request </param>
        public static IList <WorkQueue> ExternalEditStudy(IUpdateContext context, ServerEntityKey studyStorageKey, List <UpdateItem> updateItems, string reason, string user, EditType editType)
        {
            // Find all location of the study in the system and insert series delete request
            StudyStorage      s       = StudyStorage.Load(studyStorageKey);
            IList <WorkQueue> entries = new List <WorkQueue>();

            // insert an edit request
            WorkQueue request = InsertExternalEditStudyRequest(context, s.Key, s.ServerPartitionKey,
                                                               WorkQueueTypeEnum.ExternalEdit, updateItems, reason, user,
                                                               editType);

            entries.Add(request);

            return(entries);
        }
Пример #16
0
        protected override string GetTemporaryPath()
        {
            IList <StudyStorageLocation> storages =
                StudyStorageLocation.FindStorageLocations(StudyStorage.Load(_item.StudyStorageKey));

            if (storages == null || storages.Count == 0)
            {
                // ???
                return(base.GetTemporaryPath());
            }

            ServerFilesystemInfo filesystem = FilesystemMonitor.Instance.GetFilesystemInfo(storages[0].FilesystemKey);

            if (filesystem == null)
            {
                // not ready?
                return(base.GetTemporaryPath());
            }
            string basePath = GetTempPathRoot();

            if (String.IsNullOrEmpty(basePath))
            {
                basePath = Path.Combine(filesystem.Filesystem.FilesystemPath, "temp");
            }

            String tempDirectory = Path.Combine(basePath,
                                                String.Format("{0}-{1}", _item.WorkQueueTypeEnum.Lookup, _item.GetKey()));

            for (int i = 2; i < 1000; i++)
            {
                if (!Directory.Exists(tempDirectory))
                {
                    break;
                }

                tempDirectory = Path.Combine(basePath, String.Format("{0}-{1}({2})",
                                                                     _item.WorkQueueTypeEnum.Lookup, _item.GetKey(), i));
            }

            if (!Directory.Exists(tempDirectory))
            {
                Directory.CreateDirectory(tempDirectory);
            }

            return(tempDirectory);
        }
Пример #17
0
        public override void DataBind()
        {
            ExistingPatientSeriesGridView.DataSource    = DuplicateEntryDetails.ExistingStudy.Series;
            ConflictingPatientSeriesGridView.DataSource = DuplicateEntryDetails.ConflictingImageSet.StudyInfo.Series;
            StudyStorage storage =
                StudyStorage.Load(HttpContext.Current.GetSharedPersistentContext(), StudyIntegrityQueueItem.StudyStorageKey);

            IList <StudyStorageLocation> studyLocations = StudyStorageLocation.FindStorageLocations(storage);

            StudyLocation.Text = studyLocations[0].GetStudyPath();

            var entry = new DuplicateSopReceivedQueue(StudyIntegrityQueueItem);

            DuplicateSopLocation.Text = entry.GetFolderPath(HttpContext.Current.GetSharedPersistentContext());

            ComparisonResultGridView.DataSource = DuplicateEntryDetails.QueueData.ComparisonResults;
            base.DataBind();
        }
Пример #18
0
        private void CreateDestinationStudyStorage()
        {
            // This really should never happen;
            if (Context.History.DestStudyStorageKey != null)
            {
                _destinationStudyStorage =
                    StudyStorageLocation.FindStorageLocations(StudyStorage.Load(Context.History.DestStudyStorageKey))[0];
                return;
            }

            string newStudyInstanceUid = string.Empty;

            // Get the new Study Instance Uid by looking through the update commands
            foreach (BaseImageLevelUpdateCommand command in Commands)
            {
                SetTagCommand setTag = command as SetTagCommand;
                if (setTag != null && setTag.Tag.TagValue.Equals(DicomTags.StudyInstanceUid))
                {
                    newStudyInstanceUid = setTag.Value;
                    break;
                }
            }

            if (string.IsNullOrEmpty(newStudyInstanceUid))
            {
                throw new ApplicationException("Unexpectedly could not find new Study Instance Uid value for Create Study");
            }


            using (ServerCommandProcessor processor = new ServerCommandProcessor("Reconciling image processor"))
            {
                // Assign new series and instance uid
                InitializeStorageCommand command = new InitializeStorageCommand(Context, newStudyInstanceUid, Context.WorkQueueItemStudyStorage.StudyFolder,
                                                                                TransferSyntax.GetTransferSyntax(Context.WorkQueueItemStudyStorage.TransferSyntaxUid));
                processor.AddCommand(command);

                if (!processor.Execute())
                {
                    throw new ApplicationException(String.Format("Unable to create Study Storage for study: {0}", newStudyInstanceUid), processor.FailureException);
                }

                _destinationStudyStorage = command.Location;
            }
        }
Пример #19
0
        public static WebEditStudyHistoryRecord ReadEditRecord(StudyHistory historyRecord)
        {
            Platform.CheckTrue(historyRecord.StudyHistoryTypeEnum == StudyHistoryTypeEnum.WebEdited ||
                               historyRecord.StudyHistoryTypeEnum == StudyHistoryTypeEnum.ExternalEdit,
                               "History record has invalid history record type");

            WebEditStudyHistoryRecord record = new WebEditStudyHistoryRecord
            {
                InsertTime           = historyRecord.InsertTime,
                StudyStorageLocation =
                    StudyStorageLocation.FindStorageLocations(
                        StudyStorage.Load(historyRecord.StudyStorageKey))[0],
                UpdateDescription =
                    XmlUtils.Deserialize <WebEditStudyHistoryChangeDescription>(
                        historyRecord.ChangeDescription)
            };

            return(record);
        }
Пример #20
0
        protected override void OnExecute(CommandProcessor theProcessor)
        {
            Platform.CheckForNullReference(Context, "Context");

            _destinationStudyStorage = Context.History.DestStudyStorageKey != null
                                ? StudyStorageLocation.FindStorageLocations(StudyStorage.Load(Context.History.DestStudyStorageKey))[0]
                                : Context.WorkQueueItemStudyStorage;

            EnsureStudyCanBeUpdated(_destinationStudyStorage);

            if (_updateDestination)
            {
                UpdateExistingStudy();
            }

            LoadMergedStudyEntities();



            try
            {
                LoadUidMappings();

                if (Context.WorkQueueUidList.Count > 0)
                {
                    ProcessUidList();
                    LogResult();
                }
            }
            finally
            {
                UpdateHistory(_destinationStudyStorage);
            }

            if (_complete)
            {
                StudyRulesEngine engine = new StudyRulesEngine(_destinationStudyStorage, Context.Partition);
                engine.Apply(ServerRuleApplyTimeEnum.StudyProcessed, theProcessor);
            }
        }
Пример #21
0
        private AutoReconcilerResult ProcessImageAsIs(DicomFile file, StudyHistory lastHistory)
        {
            StudyStorage         destinationStudy = StudyStorage.Load(lastHistory.DestStudyStorageKey);
            StudyStorageLocation destStudy;
            AutoReconcilerResult preProcessingResult = new AutoReconcilerResult(StudyReconcileAction.ProcessAsIs);

            //Load the destination.  An exception will be thrown if any issues are encountered.
            FilesystemMonitor.Instance.GetWritableStudyStorageLocation(destinationStudy.ServerPartitionKey,
                                                                       destinationStudy.StudyInstanceUid, StudyRestore.True,
                                                                       StudyCache.True, out destStudy);

            bool belongsToAnotherStudy = !destStudy.Equals(StorageLocation);

            EnsureStudyCanBeUpdated(destStudy);

            if (belongsToAnotherStudy)
            {
                preProcessingResult.Changes = new List <UpdateItem>
                {
                    new UpdateItem(DicomTags.StudyInstanceUid, file.DataSet[DicomTags.StudyInstanceUid].ToString(), destStudy.StudyInstanceUid)
                };

                file.DataSet[DicomTags.StudyInstanceUid].SetStringValue(destStudy.StudyInstanceUid);
                SopInstanceImporterContext importContext = new SopInstanceImporterContext(
                    _contextID,
                    file.SourceApplicationEntityTitle, destStudy.ServerPartition);
                SopInstanceImporter   importer = new SopInstanceImporter(importContext);
                DicomProcessingResult result   = importer.Import(file);

                if (!result.Successful)
                {
                    throw new ApplicationException("Unable to import image to destination study");
                }
            }
            return(preProcessingResult);
        }
Пример #22
0
        private static WorkQueueAlertContextData GetWorkQueueContextData(Model.WorkQueue item)
        {
            Platform.CheckForNullReference(item, "item");

            WorkQueueAlertContextData contextData = new WorkQueueAlertContextData
            {
                WorkQueueItemKey = item.Key.Key.ToString()
            };

            StudyStorage storage = StudyStorage.Load(item.StudyStorageKey);
            IList <StudyStorageLocation> locations = StudyStorageLocation.FindStorageLocations(storage);

            if (locations != null && locations.Count > 0)
            {
                StudyStorageLocation location = locations[0];
                if (location != null)
                {
                    contextData.ValidationStudyInfo = new ValidationStudyInfo
                    {
                        StudyInstaneUid = location.StudyInstanceUid
                    };

                    // study info is not always available (eg, when all images failed to process)
                    if (location.Study != null)
                    {
                        contextData.ValidationStudyInfo.AccessionNumber = location.Study.AccessionNumber;
                        contextData.ValidationStudyInfo.PatientsId      = location.Study.PatientId;
                        contextData.ValidationStudyInfo.PatientsName    = location.Study.PatientsName;
                        contextData.ValidationStudyInfo.ServerAE        = location.ServerPartition.AeTitle;
                        contextData.ValidationStudyInfo.StudyDate       = location.Study.StudyDate;
                    }
                }
            }

            return(contextData);
        }
Пример #23
0
        private void LoadMergedStudyEntities()
        {
            StudyStorage storage = StudyStorage.Load(_destinationStudyStorage.Key);

            _destinationStudyStorage = StudyStorageLocation.FindStorageLocations(storage)[0];
        }
        /// <summary>
        /// Do the restore.
        /// </summary>
        /// <param name="queueItem">The queue item to restore.</param>
        public void Run(RestoreQueue queueItem)
        {
            using (RestoreProcessorContext context = new RestoreProcessorContext(queueItem))
            {
                try
                {
                    // Load up related classes.
                    using (IReadContext readContext = _nasArchive.PersistentStore.OpenReadContext())
                    {
                        _archiveStudyStorage = ArchiveStudyStorage.Load(readContext, queueItem.ArchiveStudyStorageKey);
                        _serverSyntax        = ServerTransferSyntax.Load(readContext, _archiveStudyStorage.ServerTransferSyntaxKey);
                        _syntax = TransferSyntax.GetTransferSyntax(_serverSyntax.Uid);

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

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

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


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

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


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

                    if (_location == null)
                    {
                        RestoreNearlineStudy(queueItem, zipFile, destinationFolder, studyFolder);
                    }
                    else
                    {
                        RestoreOnlineStudy(queueItem, zipFile, destinationFolder);
                    }
                }
                catch (Exception e)
                {
                    Platform.Log(LogLevel.Error, e, "Unexpected exception processing restore request for {0} on archive {1}",
                                 _studyStorage == null ? (_location == null ? string.Empty : _location.StudyInstanceUid) : _studyStorage.StudyInstanceUid,
                                 _nasArchive.PartitionArchive.Description);
                    queueItem.FailureDescription = e.Message;
                    _nasArchive.UpdateRestoreQueue(queueItem, RestoreQueueStatusEnum.Failed, Platform.Time);
                }
            }
        }
Пример #25
0
 private void LoadEntities()
 {
     _storage = StudyStorage.Load(_oldStudyLocation.Key);
     _study   = _storage.LoadStudy(UpdateContext);
 }
Пример #26
0
        /// <summary>
        /// Populate the data from a <see cref="Series"/> entity into a DICOM C-FIND-RSP message.
        /// </summary>
        /// <param name="read">The connection to use to read the values.</param>
        /// <param name="request"></param>
        /// <param name="response"></param>
        /// <param name="tagList"></param>
        /// <param name="row">The <see cref="Series"/> table to populate the row from.</param>
        private void PopulateSeries(IPersistenceContext read, DicomAttributeCollection request, DicomMessageBase response, IEnumerable <uint> tagList,
                                    Series row)
        {
            DicomAttributeCollection dataSet = response.DataSet;

            Study        theStudy = Study.Load(read, row.StudyKey);
            StudyStorage storage  = StudyStorage.Load(read, theStudy.ServerPartitionKey, theStudy.StudyInstanceUid);

            dataSet[DicomTags.RetrieveAeTitle].SetStringValue(ServerPartitionMonitor.Instance.FindPartition(row.ServerPartitionKey).AeTitle);
            dataSet[DicomTags.InstanceAvailability].SetStringValue(storage.StudyStatusEnum == StudyStatusEnum.Nearline
                                                                       ? "NEARLINE"
                                                                       : "ONLINE");

            if (false == String.IsNullOrEmpty(theStudy.SpecificCharacterSet))
            {
                dataSet[DicomTags.SpecificCharacterSet].SetStringValue(theStudy.SpecificCharacterSet);
                dataSet.SpecificCharacterSet = theStudy.SpecificCharacterSet; // this will ensure the data is encoded using the specified character set
            }

            foreach (uint tag in tagList)
            {
                try
                {
                    switch (tag)
                    {
                    case DicomTags.PatientId:
                        dataSet[DicomTags.PatientId].SetStringValue(request[DicomTags.PatientId].ToString());
                        break;

                    case DicomTags.StudyInstanceUid:
                        dataSet[DicomTags.StudyInstanceUid].SetStringValue(
                            request[DicomTags.StudyInstanceUid].ToString());
                        break;

                    case DicomTags.SeriesInstanceUid:
                        dataSet[DicomTags.SeriesInstanceUid].SetStringValue(row.SeriesInstanceUid);
                        break;

                    case DicomTags.Modality:
                        dataSet[DicomTags.Modality].SetStringValue(row.Modality);
                        break;

                    case DicomTags.SeriesNumber:
                        dataSet[DicomTags.SeriesNumber].SetStringValue(row.SeriesNumber);
                        break;

                    case DicomTags.SeriesDescription:
                        dataSet[DicomTags.SeriesDescription].SetStringValue(row.SeriesDescription);
                        break;

                    case DicomTags.PerformedProcedureStepStartDate:
                        dataSet[DicomTags.PerformedProcedureStepStartDate].SetStringValue(
                            row.PerformedProcedureStepStartDate);
                        break;

                    case DicomTags.PerformedProcedureStepStartTime:
                        dataSet[DicomTags.PerformedProcedureStepStartTime].SetStringValue(
                            row.PerformedProcedureStepStartTime);
                        break;

                    case DicomTags.NumberOfSeriesRelatedInstances:
                        dataSet[DicomTags.NumberOfSeriesRelatedInstances].AppendInt32(row.NumberOfSeriesRelatedInstances);
                        break;

                    case DicomTags.RequestAttributesSequence:
                        LoadRequestAttributes(read, response, row);
                        break;

                    case DicomTags.QueryRetrieveLevel:
                        dataSet[DicomTags.QueryRetrieveLevel].SetStringValue("SERIES");
                        break;

                    default:
                        dataSet[tag].SetNullValue();
                        break;

                    // Meta tags that should have not been in the RQ, but we've already set
                    case DicomTags.RetrieveAeTitle:
                    case DicomTags.InstanceAvailability:
                    case DicomTags.SpecificCharacterSet:
                        break;
                    }
                }
                catch (Exception e)
                {
                    Platform.Log(LogLevel.Warn, e, "Unexpected error setting tag {0} in C-FIND-RSP",
                                 dataSet[tag].Tag.ToString());
                    dataSet[tag].SetNullValue();
                }
            }
        }
Пример #27
0
        private AutoReconcilerResult MergeImage(StudyReconcileAction action, DicomFile file, StudyHistory lastHistory)
        {
            string originalSeriesUid = file.DataSet[DicomTags.SeriesInstanceUid].ToString();
            string originalSopUid    = file.DataSet[DicomTags.SopInstanceUid].ToString();

            AutoReconcilerResult preProcessingResult = null;
            StudyStorageLocation destStudy;
            UidMapper            uidMapper = null;

            if (lastHistory.DestStudyStorageKey != null)
            {
                StudyStorage destinationStudy = StudyStorage.Load(lastHistory.DestStudyStorageKey);

                //Load the destination.  An exception will be thrown if any issues are encountered.
                FilesystemMonitor.Instance.GetWritableStudyStorageLocation(destinationStudy.ServerPartitionKey,
                                                                           destinationStudy.StudyInstanceUid,
                                                                           StudyRestore.True, StudyCache.True,
                                                                           out destStudy);

                EnsureStudyCanBeUpdated(destStudy);

                bool belongsToAnotherStudy = !destStudy.Equals(StorageLocation);

                ImageUpdateCommandBuilder           commandBuilder = new ImageUpdateCommandBuilder();
                IList <BaseImageLevelUpdateCommand> commands       = commandBuilder.BuildCommands <StudyMatchingMap>(destStudy);
                if (belongsToAnotherStudy)
                {
                    Platform.Log(LogLevel.Info, "AUTO-RECONCILE: Move SOP {0} to Study {1}, A#: {2}, Patient {3}", originalSopUid, destStudy.StudyInstanceUid, destStudy.Study.AccessionNumber, destStudy.Study.PatientsName);

                    // Load the Uid Map, either from cache or from disk
                    if (!_uidMapCache.TryGetValue(destStudy.Key, out uidMapper))
                    {
                        UidMapXml mapXml = new UidMapXml();
                        mapXml.Load(destStudy);
                        uidMapper = new UidMapper(mapXml);

                        _uidMapCache.Add(destStudy.Key, uidMapper);
                    }

                    try
                    {
                        commands.Add(GetUidMappingCommand(StorageLocation, destStudy, uidMapper, originalSopUid, originalSeriesUid));
                    }
                    catch (InstanceAlreadyExistsException ex)
                    {
                        Platform.Log(LogLevel.Info, "An instance already exists with the SOP Instance Uid {0}", ex.SopInstanceUid);
                        preProcessingResult = new AutoReconcilerResult(StudyReconcileAction.Discard)
                        {
                            DiscardImage = true
                        };

                        return(preProcessingResult);
                    }
                }


                preProcessingResult = new AutoReconcilerResult(action)
                {
                    Changes = GetUpdateList(file, commands)
                };

                UpdateImage(file, commands);

                // First, must update the map
                if (uidMapper != null && uidMapper.Dirty)
                {
                    UpdateUidMap(destStudy, uidMapper);
                }

                if (belongsToAnotherStudy)
                {
                    SopInstanceImporterContext importContext = new SopInstanceImporterContext(_contextID, file.SourceApplicationEntityTitle, destStudy.ServerPartition);
                    SopInstanceImporter        importer      = new SopInstanceImporter(importContext);
                    DicomProcessingResult      result        = importer.Import(file);

                    if (!result.Successful)
                    {
                        throw new ApplicationException(result.ErrorMessage);
                    }
                }
            }
            return(preProcessingResult);
        }
Пример #28
0
        /// <summary>
        /// Do the restore.
        /// </summary>
        /// <param name="queueItem">The queue item to restore.</param>
        public void Run(RestoreQueue queueItem)
        {
            using (var context = new RestoreProcessorContext(queueItem))
            {
                try
                {
                    // Load up related classes.
                    using (IReadContext readContext = _hsmArchive.PersistentStore.OpenReadContext())
                    {
                        _archiveStudyStorage = ArchiveStudyStorage.Load(readContext, queueItem.ArchiveStudyStorageKey);
                        _serverSyntax        = ServerTransferSyntax.Load(readContext, _archiveStudyStorage.ServerTransferSyntaxKey);
                        _syntax = TransferSyntax.GetTransferSyntax(_serverSyntax.Uid);

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

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

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

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

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

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

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

                        RestoreOnlineStudy(queueItem, zipFile, _location.GetStudyPath());
                    }
                }
                catch (Exception e)
                {
                    Platform.Log(LogLevel.Error, e, "Unexpected exception processing restore request for {0} on archive {1}",
                                 _studyStorage == null ? (_location == null ? string.Empty : _location.StudyInstanceUid) : _studyStorage.StudyInstanceUid,
                                 _hsmArchive.PartitionArchive.Description);
                    queueItem.FailureDescription = e.Message;
                    _hsmArchive.UpdateRestoreQueue(queueItem, RestoreQueueStatusEnum.Failed, Platform.Time);
                }
            }
        }
Пример #29
0
        /// <summary>
        /// Returns an instance of <see cref="StudySummary"/> based on a <see cref="Study"/> object.
        /// </summary>
        /// <param name="study"></param>
        /// <param name="read"></param>
        /// <returns></returns>
        /// <remark>
        ///
        /// </remark>
        static public StudySummary CreateStudySummary(IPersistenceContext read, Study study)
        {
            if (study == null)
            {
                return(null);
            }

            var studySummary = new StudySummary();
            var controller   = new StudyController();

            studySummary.TheStudy = study;

            studySummary.Key             = study.GetKey();
            studySummary.AccessionNumber = study.AccessionNumber;
            studySummary.NumberOfStudyRelatedInstances = study.NumberOfStudyRelatedInstances;
            studySummary.NumberOfStudyRelatedSeries    = study.NumberOfStudyRelatedSeries;
            studySummary.PatientId               = study.PatientId;
            studySummary.PatientsName            = study.PatientsName;
            studySummary.StudyDate               = study.StudyDate;
            studySummary.StudyInstanceUid        = study.StudyInstanceUid;
            studySummary.StudyDescription        = study.StudyDescription;
            studySummary.ModalitiesInStudy       = controller.GetModalitiesInStudy(read, study);
            studySummary.ReferringPhysiciansName = study.ReferringPhysiciansName;
            studySummary.ResponsibleOrganization = study.ResponsibleOrganization;
            studySummary.ResponsiblePerson       = study.ResponsiblePerson;
            studySummary.StudyTime               = study.StudyTime;
            studySummary.StudyId  = study.StudyId;
            studySummary.HasOrder = study.OrderKey != null;

            if (study.OrderKey != null)
            {
                var order = Order.Load(study.OrderKey);
                studySummary.OrderRequiresQC = order.QCExpected;
                studySummary.StudyIsQCed     = (study.QCStatusEnum != null && study.QCStatusEnum != QCStatusEnum.NA);
            }



            studySummary.ThePartition = ServerPartitionMonitor.Instance.FindPartition(study.ServerPartitionKey) ??
                                        ServerPartition.Load(read, study.ServerPartitionKey);

            studySummary.ReferringPhysiciansName = study.ReferringPhysiciansName;
            studySummary.TheStudyStorage         = StudyStorage.Load(read, study.StudyStorageKey);
            studySummary.StudyStatusEnum         = studySummary.TheStudyStorage.StudyStatusEnum;
            studySummary.QueueStudyStateEnum     = studySummary.TheStudyStorage.QueueStudyStateEnum;

            studySummary.TheArchiveLocation = controller.GetFirstArchiveStudyStorage(read, studySummary.TheStudyStorage.Key);

            studySummary.IsArchiving = controller.GetArchiveQueueCount(study) > 0;

            studySummary.IsProcessing = studySummary.TheStudyStorage.WriteLock;

            // the study is considered "locked" if it's being processed or some action which requires the lock has been scheduled
            // No additional action should be allowed on the study until everything is completed.
            studySummary.IsLocked = studySummary.IsProcessing ||
                                    (studySummary.TheStudyStorage.QueueStudyStateEnum != QueueStudyStateEnum.Idle);

            if (controller.GetStudyIntegrityQueueCount(studySummary.TheStudyStorage.Key) > 0)
            {
                studySummary.IsReconcileRequired = true;
            }

            studySummary.HasPendingExternalEdit = controller.GetCountPendingExternalEditWorkQueueItems(study) > 0;
            if (studySummary.HasPendingExternalEdit)
            {
                studySummary.HasPendingWorkQueueItems = true;
            }
            else
            {
                studySummary.HasPendingWorkQueueItems = controller.GetCountPendingWorkQueueItems(study) > 0;
            }

            var ep = new StudySummaryAssemblerExtensionPoint();

            foreach (IStudySummaryAssembler assemblerPlugin in ep.CreateExtensions())
            {
                assemblerPlugin.PopulateStudy(studySummary, study);
            }

            return(studySummary);
        }
Пример #30
0
        public StudyStorage GetStudyStorage(Study study)
        {
            Platform.CheckForNullReference(study, "Study");

            return(StudyStorage.Load(study.StudyStorageKey));
        }