public DicomPixelData GetPixelData(string seriesInstanceUid, string sopInstanceUid, string nextSeriesInstanceUid, string nextSopInstanceUid)
        {
            DicomPixelData pd = null;

            for (int i = 0; i < 5; i++)
            {
                // look at the cache first
                pd = DicomPixelDataCache.Find(_storage, _storage.StudyInstanceUid, seriesInstanceUid, sopInstanceUid);
                if (pd != null)
                {
                    break;
                }

                // Check if the file has been requested to open by the client
                string key = string.Format("ImageStreamPrefetchStream/{0}/{1}/{2}/{3}",
                                           _storage.ServerPartition.AeTitle, _storage.StudyInstanceUid,
                                           seriesInstanceUid, sopInstanceUid);

                Stream preopenStream = HttpRuntime.Cache[key] as Stream;
                if (preopenStream != null)
                {
                    pd = DicomPixelData.CreateFrom(_storage.GetSopInstancePath(seriesInstanceUid, sopInstanceUid), preopenStream, DicomReadOptions.StorePixelDataReferences);
                    DicomPixelDataCache.Insert(_storage, _storage.StudyInstanceUid, seriesInstanceUid, sopInstanceUid, pd);
                    preopenStream.Close();
                    HttpRuntime.Cache.Remove(key);
                    break;
                }
                else
                {
                    try
                    {
                        pd = DicomPixelData.CreateFrom(_storage.GetSopInstancePath(seriesInstanceUid, sopInstanceUid),
                                                       DicomReadOptions.StorePixelDataReferences);
                        DicomPixelDataCache.Insert(_storage, _storage.StudyInstanceUid, seriesInstanceUid, sopInstanceUid, pd);
                        break;
                    }
                    catch (FileNotFoundException)
                    {
                        throw;
                    }
                    catch (IOException)
                    {
                        Random rand = new Random();
                        Thread.Sleep(rand.Next(100, 500));
                    }
                }
            }
            OnPixelDataLoaded(sopInstanceUid, nextSeriesInstanceUid, nextSopInstanceUid);
            return(pd);
        }
Esempio n. 2
0
        public DicomPixelData GetPixelData(string seriesInstanceUid, string sopInstanceUid)
        {
            DicomPixelData pd = null;

            for (int i = 0; i < 5; i++)
            {
                // look at the cache first
                pd = DicomPixelDataCache.Find(_storage, _storage.StudyInstanceUid, seriesInstanceUid, sopInstanceUid);
                if (pd != null)
                {
                    break;
                }

                try
                {
                    pd = DicomPixelData.CreateFrom(_storage.GetSopInstancePath(seriesInstanceUid, sopInstanceUid), DicomReadOptions.StorePixelDataReferences);
                    DicomPixelDataCache.Insert(_storage, _storage.StudyInstanceUid, seriesInstanceUid, sopInstanceUid, pd);
                    break;
                }
                catch (FileNotFoundException)
                {
                    throw;
                }
                catch (IOException)
                {
                    var rand = new Random();
                    Thread.Sleep(rand.Next(100, 500));
                }
            }
            return(pd);
        }
        private void RestoreFilesystem()
        {
            if (!RequiresRollback || !_initialized || _backupDir == null)
            {
                return;
            }

            if (NewStudyPath == _oldStudyPath)
            {
                // Study folder was not changed. Files were overwritten.

                // restore header
                Platform.Log(LogLevel.Info, "Restoring old study header...");

                FileUtils.Copy(Path.Combine(_backupDir, _study.StudyInstanceUid + ".xml"), _oldStudyLocation.GetStudyXmlPath(), true);
                FileUtils.Copy(Path.Combine(_backupDir, _study.StudyInstanceUid + ".xml.gz"),
                               _oldStudyLocation.GetCompressedStudyXmlPath(), true);

                // restore updated SOPs
                Platform.Log(LogLevel.Info, "Restoring old study folder... {0} sop need to be restored", _updatedSopList.Count);
                int restoredCount = 0;
                foreach (InstanceInfo sop in _updatedSopList)
                {
                    string backupSopPath = Path.Combine(_backupDir, sop.SopInstanceUid + ServerPlatform.DicomFileExtension);

                    FileUtils.Copy(backupSopPath, _oldStudyLocation.GetSopInstancePath(sop.SeriesInstanceUid, sop.SopInstanceUid), true);

                    restoredCount++;
                    Platform.Log(ServerPlatform.InstanceLogLevel, "Restored SOP {0} [{1} of {2}]", sop.SopInstanceUid, restoredCount,
                                 _updatedSopList.Count);

                    SimulateErrors();
                }

                if (restoredCount > 0)
                {
                    Platform.Log(LogLevel.Info, "{0} SOP(s) have been restored.", restoredCount);
                }
            }
            else
            {
                // Different study folder was used. Original folder must be kept around
                // because we are rolling back.
                _deleteOriginalFolder = false;
            }
        }
Esempio n. 4
0
        protected override SopDataSource LoadNextSopDataSource()
        {
            if (!_instances.MoveNext())
            {
                return(null);
            }

            return(new ImageServerSopDataSource(_instances.Current, _location.GetSopInstancePath(
                                                    _instances.Current.Collection[DicomTags.SeriesInstanceUid].ToString(),
                                                    _instances.Current.SopInstanceUid)));
        }
        private static SeriesSopUpdateCommand GetUidMappingCommand(StudyStorageLocation sourceStudy, StudyStorageLocation targetStudy, UidMapper uidMapper, string originalSopUid, string originalSeriesUid)
        {
            SeriesSopUpdateCommand cmd;
            string newSeriesUid = uidMapper.FindNewSeriesUid(originalSeriesUid);
            string newSopUid    = uidMapper.FindNewSopUid(originalSopUid);

            if (string.IsNullOrEmpty(newSeriesUid) == false)
            {
                // Series was assigned new uid
                if (string.IsNullOrEmpty(newSopUid))
                {
                    // this is new instance
                    newSopUid = DicomUid.GenerateUid().UID;
                    uidMapper.AddSop(originalSopUid, newSopUid);
                    cmd = new SeriesSopUpdateCommand(sourceStudy, targetStudy, uidMapper);
                }
                else
                {
                    Platform.Log(LogLevel.Info, "Map SOP UID {0} to {1}", originalSopUid, newSopUid);
                    // this is duplicate
                    if (File.Exists(targetStudy.GetSopInstancePath(newSeriesUid, newSopUid)))
                    {
                        throw new InstanceAlreadyExistsException("Instance already exists")
                              {
                                  SeriesInstanceUid = newSeriesUid,
                                  SopInstanceUid    = newSopUid
                              };
                    }

                    cmd = new SeriesSopUpdateCommand(sourceStudy, targetStudy, uidMapper);
                }
            }
            else
            {
                // this is new series
                newSopUid = DicomUid.GenerateUid().UID;
                uidMapper.AddSeries(sourceStudy.StudyInstanceUid, targetStudy.StudyInstanceUid, originalSeriesUid, newSopUid);
                cmd = new SeriesSopUpdateCommand(sourceStudy, targetStudy, uidMapper);

                Platform.Log(LogLevel.Info, "Map SOP UID {0} to {1}", originalSopUid, newSopUid);
            }

            return(cmd);
        }
Esempio n. 6
0
        private void Prefetch(PrefetchQueueItem item)
        {
            try{
                string key = string.Format("ImageStreamPrefetchStream/{0}/{1}/{2}/{3}",
                                           _storage.ServerPartition.AeTitle, _storage.StudyInstanceUid,
                                           item.SeriesInstanceUid, item.SopInstanceUid);

                for (int i = 0; i < 5; i++)
                {
                    Stream stream = HttpRuntime.Cache[key] as Stream;
                    if (stream != null)
                    {
                        // already pre-open
                        break;
                    }

                    else
                    {
                        try
                        {
                            stream = new BufferedStream(File.OpenRead(_storage.GetSopInstancePath(item.SeriesInstanceUid, item.SopInstanceUid)));
                            HttpRuntime.Cache.Insert(key, stream, null, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.Default, PrefetchUnloaded);
                            break;
                        }
                        catch (FileNotFoundException)
                        {
                            throw;
                        }
                        catch (IOException)
                        {
                            Random rand = new Random();
                            Thread.Sleep(rand.Next(100, 500));
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Platform.Log(LogLevel.Error, ex, "Error occurred during prefetch SOP: {0}", item.SopInstanceUid);
            }
        }
Esempio n. 7
0
        protected override void OnExecute(CommandProcessor theProcessor)
        {
            if (_path == null)
            {
                String seriesUid = _file.DataSet[DicomTags.SeriesInstanceUid].GetString(0, String.Empty);
                String sopUid    = _file.DataSet[DicomTags.SopInstanceUid].GetString(0, String.Empty);
                _path = _storageLocation.GetSopInstancePath(seriesUid, sopUid);
            }

            // Make sure the directory exists where we're storing the file.
            var p = Path.GetDirectoryName(_path);

            if (string.IsNullOrEmpty(p) || !Directory.Exists(p))
            {
                if (!theProcessor.ExecuteSubCommand(this, new CreateDirectoryCommand(Path.GetDirectoryName(_path))))
                {
                    throw new ApplicationException(theProcessor.FailureReason);
                }
            }

            if (RequiresRollback)
            {
                Backup();
            }

            string path = _saveTemp ? GetTempPath() : _path;

            using (FileStream stream = FileStreamOpener.OpenForSoleUpdate(path, FileMode.Create))
            {
                // Set _fileCreated here, because the file has been opened.
                if (!_saveTemp)
                {
                    _fileCreated = true;
                }

                _saveSpeed.Start();
                _file.Save(stream, DicomWriteOptions.Default);
                stream.Flush();
                stream.Close();
                _saveSpeed.End();

                var fi = new FileInfo(path);
                _saveSpeed.SetData(fi.Length);
            }

            if (_saveTemp)
            {
                if (File.Exists(_path))
                {
                    if (_failOnExists)
                    {
                        try
                        {
                            FileUtils.Delete(path);
                        }
                        catch (Exception x)
                        {
                            throw new ApplicationException(String.Format("DICOM File unexpectedly already exists: {0}", _path), x);
                        }
                        throw new ApplicationException(String.Format("DICOM File unexpectedly already exists: {0}", _path));
                    }
                    FileUtils.Delete(_path);
                }

                File.Move(path, _path);
                _fileCreated = true;
            }
        }
        /// <summary>
        /// Imports the specified <see cref="DicomMessageBase"/> object into the system.
        /// The object will be inserted into the <see cref="WorkQueue"/> for processing and
        /// if it's a duplicate, proper checks will be done and depending on the policy, it will be
        /// ignored, rejected or inserted into the <see cref="StudyIntegrityQueue"/> for manual intervention.
        /// </summary>
        /// <param name="message">The DICOM object to be imported.</param>
        /// <returns>An instance of <see cref="DicomProcessingResult"/> that describes the result of the processing.</returns>
        /// <exception cref="DicomDataException">Thrown when the DICOM object contains invalid data</exception>
        public DicomProcessingResult Import(DicomMessageBase message)
        {
            Platform.CheckForNullReference(message, "message");
            String studyInstanceUid;
            String seriesInstanceUid;
            String sopInstanceUid;
            String accessionNumber;
            String patientsName;

            LoadMessageUids(message, out studyInstanceUid, out seriesInstanceUid, out sopInstanceUid,
                            out accessionNumber, out patientsName);

            DicomFile file = null;

            // Scrub the name for invalid characters.
            string newName = XmlUtils.XmlCharacterScrub(patientsName);

            if (!newName.Equals(patientsName))
            {
                message.DataSet[DicomTags.PatientsName].SetStringValue(newName);
            }

            var result = new DicomProcessingResult
            {
                Successful        = true,
                StudyInstanceUid  = studyInstanceUid,
                SeriesInstanceUid = seriesInstanceUid,
                SopInstanceUid    = sopInstanceUid,
                AccessionNumber   = accessionNumber
            };

            try
            {
                Validate(message);
            }
            catch (DicomDataException e)
            {
                result.SetError(DicomStatuses.ProcessingFailure, e.Message);
                return(result);
            }

            // Use the command processor for rollback capabilities.
            using (var commandProcessor = new ServerCommandProcessor(String.Format("Processing Sop Instance {0}", sopInstanceUid)))
            {
                try
                {
                    string failureMessage;
                    StudyStorageLocation studyLocation = GetWritableOnlineStorage(message);

                    // GetWritableOnlineStorage should throw an exception if the study location cannot be found.
                    Platform.CheckForNullReference(studyLocation, "studyLocation");

                    if (!studyLocation.QueueStudyStateEnum.Equals(QueueStudyStateEnum.Idle) &&
                        (!studyLocation.QueueStudyStateEnum.Equals(QueueStudyStateEnum.ProcessingScheduled)))
                    {
                        failureMessage = String.Format("Study {0} on partition {1} is being processed: {2}, can't accept new images.",
                                                       studyLocation.StudyInstanceUid, _context.Partition.Description, studyLocation.QueueStudyStateEnum.Description);
                        result.SetError(DicomStatuses.StorageStorageOutOfResources, failureMessage);
                        return(result);
                    }
                    if (studyLocation.StudyStatusEnum.Equals(StudyStatusEnum.OnlineLossy))
                    {
                        if (studyLocation.IsLatestArchiveLossless)
                        {
                            result.DicomStatus = DicomStatuses.StorageStorageOutOfResources;
                            failureMessage     = String.Format("Study {0} on partition {1} can't accept new images due to lossy compression of the study.  Restoring study.",
                                                               studyLocation.StudyInstanceUid, _context.Partition.Description);
                            Platform.Log(LogLevel.Error, failureMessage);
                            if (ServerHelper.InsertRestoreRequest(studyLocation) == null)
                            {
                                Platform.Log(LogLevel.Warn, "Unable to insert Restore Request for Study");
                            }

                            result.SetError(DicomStatuses.StorageStorageOutOfResources, failureMessage);
                            result.RestoreRequested = true;
                            return(result);
                        }
                    }

                    String path      = studyLocation.FilesystemPath;
                    String finalDest = studyLocation.GetSopInstancePath(seriesInstanceUid, sopInstanceUid);
                    file = ConvertToDicomFile(message, finalDest, _context.SourceAE);

                    if (HasUnprocessedCopy(studyLocation.Key, seriesInstanceUid, sopInstanceUid))
                    {
                        var accept = false;

                        // This is a special case: #10569
                        // Allow user to revive an orphaned study by reprocessing the files found in the filesystem
                        if (File.Exists(finalDest))
                        {
                            accept = DuplicatePolicy.IsParitionDuplicatePolicyOverridden(studyLocation);
                        }

                        if (!accept)
                        {
                            failureMessage = string.Format("Another copy of the SOP Instance was received but has not been processed: {0}", sopInstanceUid);
                            result.SetError(DicomStatuses.DuplicateSOPInstance, failureMessage);
                            return(result);
                        }
                    }

                    var data = new StudyProcessWorkQueueData
                    {
                        ReceivingAeTitle = _context.AlternateAe == null
                                                  ? _context.Partition.AeTitle
                                                  : _context.AlternateAe.AeTitle
                    };

                    if (File.Exists(finalDest))
                    {
                        result = HandleDuplicate(sopInstanceUid, studyLocation, commandProcessor, file, data);
                        if (!result.Successful)
                        {
                            return(result);
                        }
                    }
                    else
                    {
                        HandleNonDuplicate(seriesInstanceUid, sopInstanceUid, studyLocation, commandProcessor, file, path,
                                           false, data);
                    }

                    if (commandProcessor.Execute())
                    {
                        result.DicomStatus = DicomStatuses.Success;
                    }
                    else
                    {
                        failureMessage =
                            String.Format("Failure processing message: {0}. Sending failure status.",
                                          commandProcessor.FailureReason);
                        result.SetError(DicomStatuses.ProcessingFailure, failureMessage);
                        // processor already rolled back
                        return(result);
                    }
                }
                catch (NoWritableFilesystemException)
                {
                    String failureMessage = String.Format("Unable to process image, no writable filesystem found for Study UID {0}.", sopInstanceUid);
                    commandProcessor.Rollback();
                    result.SetError(DicomStatuses.StorageStorageOutOfResources, failureMessage);
                }
                catch (StudyIsNearlineException e)
                {
                    String failureMessage = e.RestoreRequested
                                                ? String.Format("{0}. Restore has been requested.", e.Message)
                                                : e.Message;

                    Platform.Log(LogLevel.Error, failureMessage);
                    commandProcessor.Rollback();
                    result.SetError(DicomStatuses.ProcessingFailure, failureMessage);
                }
                catch (FilesystemNotWritableException)
                {
                    commandProcessor.Rollback();

                    string folder;
                    if (!FilesystemMonitor.Instance.GetWriteableIncomingFolder(_context.Partition, out folder))
                    {
                        String failureMessage =
                            String.Format("Unable to process image, study storage location is missing or not writeable: {0}.", sopInstanceUid);
                        result.SetError(DicomStatuses.StorageStorageOutOfResources, failureMessage);
                        return(result);
                    }

                    if (file == null)
                    {
                        file = ConvertToDicomFile(message, string.Empty, _context.SourceAE);
                    }

                    if (!SaveToFolder(folder, sopInstanceUid, studyInstanceUid, file))
                    {
                        String failureMessage =
                            String.Format("Study storage location not writeable and no writeable incoming folder: {0}.", sopInstanceUid);
                        result.SetError(DicomStatuses.StorageStorageOutOfResources, failureMessage);
                        return(result);
                    }

                    Platform.Log(LogLevel.Info, "Saved existing SOP without writeable storage location to {0} folder: {1}",
                                 FilesystemMonitor.ImportDirectorySuffix, sopInstanceUid);
                    result.DicomStatus = DicomStatuses.Success;
                    return(result);
                }
                catch (Exception e)
                {
                    Platform.Log(LogLevel.Error, e, "Unexpected exception when {0}.  Rolling back operation.", commandProcessor.Description);
                    commandProcessor.Rollback();
                    result.SetError(result.DicomStatus ?? DicomStatuses.ProcessingFailure, e.Message);
                }
            }

            return(result);
        }
Esempio n. 9
0
        private static SeriesSopUpdateCommand GetUidMappingCommand(StudyStorageLocation sourceStudy, StudyStorageLocation targetStudy, UidMapper uidMapper, string originalSopUid, string originalSeriesUid)
        {
            SeriesSopUpdateCommand cmd;
            string newSeriesUid = uidMapper.FindNewSeriesUid(originalSeriesUid);
            string newSopUid = uidMapper.FindNewSopUid(originalSopUid);
            if (string.IsNullOrEmpty(newSeriesUid) == false)
            {
                // Series was assigned new uid
                if (string.IsNullOrEmpty(newSopUid))
                {
                    // this is new instance
                    newSopUid = DicomUid.GenerateUid().UID;
                    uidMapper.AddSop(originalSopUid, newSopUid);
                    cmd = new SeriesSopUpdateCommand(sourceStudy, targetStudy, uidMapper);

                }
                else
                {
                    Platform.Log(LogLevel.Info, "Map SOP UID {0} to {1}", originalSopUid, newSopUid);
                    // this is duplicate
                    if (File.Exists(targetStudy.GetSopInstancePath(newSeriesUid, newSopUid)))
                    {
                        throw new InstanceAlreadyExistsException("Instance already exists")
                                  {
                                      SeriesInstanceUid = newSeriesUid,
                                      SopInstanceUid = newSopUid
                                  };

                    }

                    cmd = new SeriesSopUpdateCommand(sourceStudy, targetStudy, uidMapper);
                }
            }
            else
            {
                // this is new series
                newSopUid = DicomUid.GenerateUid().UID;
                uidMapper.AddSeries(sourceStudy.StudyInstanceUid, targetStudy.StudyInstanceUid, originalSeriesUid, newSopUid);
                cmd = new SeriesSopUpdateCommand(sourceStudy, targetStudy, uidMapper);

                Platform.Log(LogLevel.Info, "Map SOP UID {0} to {1}", originalSopUid, newSopUid);
            }

            return cmd;
        }