Exemple #1
0
        public void SendMessages()
        {
            _logger.Debug("Sending messages in buffer");

            lock (_oBufferLock)
            {
                var newBatchHeaders = new List <IMessageHeader>();
                foreach ((DicomFileMessage message, IMessageHeader header) in _messageBuffer)
                {
                    newBatchHeaders.Add(_producerModel.SendMessage(message, header, _reprocessingRoutingKey));
                }

                // Confirm all messages in the batch
                _producerModel.WaitForConfirms();

                TotalProcessed += _messageBuffer.Count;

                foreach (IMessageHeader newHeader in newBatchHeaders)
                {
                    newHeader.Log(_logger, LogLevel.Trace, "Sent");
                }

                _messageBuffer.Clear();
            }
        }
Exemple #2
0
        public void TestMultipleConfirmsOk()
        {
            IProducerModel pm = _testAdapter.SetupProducer(_testProducerOptions, true);

            pm.SendMessage(new TestMessage(), null);

            for (var i = 0; i < 10; ++i)
            {
                pm.WaitForConfirms();
            }
        }
Exemple #3
0
        public override void Stop(string reason)
        {
            if (_fileMessageProducer != null)
            {
                try
                {
                    _fileMessageProducer.WaitForConfirms();
                }
                catch (AlreadyClosedException) { /* Ignored */ }
            }

            base.Stop(reason);
        }
Exemple #4
0
        public override void Stop(string reason)
        {
            if (_consumerId != Guid.Empty)
            {
                RabbitMqAdapter.StopConsumer(_consumerId, Smi.Common.RabbitMqAdapter.DefaultOperationTimeout);
            }
            try
            {
                // Wait for any unconfirmed messages before calling stop
                _producerModel.WaitForConfirms();
            }
            catch (AlreadyClosedException)
            {
            }

            _swapper?.LogProgress(Logger, LogLevel.Info);

            base.Stop(reason);
        }
Exemple #5
0
        public IdentifierMapperQueueConsumer(IProducerModel producer, ISwapIdentifiers swapper)
        {
            _producer = producer;
            _swapper  = swapper;
            acker     = new Thread(() =>
            {
                try
                {
                    while (true)
                    {
                        List <Tuple <IMessageHeader, ulong> > done = new List <Tuple <IMessageHeader, ulong> >();
                        Tuple <DicomFileMessage, IMessageHeader, ulong> t;
                        t = msgq.Take();

                        lock (_producer)
                        {
                            _producer.SendMessage(t.Item1, t.Item2, "");
                            done.Add(new Tuple <IMessageHeader, ulong>(t.Item2, t.Item3));
                            while (msgq.TryTake(out t))
                            {
                                _producer.SendMessage(t.Item1, t.Item2, "");
                                done.Add(new Tuple <IMessageHeader, ulong>(t.Item2, t.Item3));
                            }
                            _producer.WaitForConfirms();
                            foreach (var ack in done)
                            {
                                Ack(ack.Item1, ack.Item2);
                            }
                        }
                    }
                }
                catch (InvalidOperationException)
                {
                    // The BlockingCollection will throw this exception when closed by Shutdown()
                    return;
                }
            });
            acker.IsBackground = true;
            acker.Start();
        }
Exemple #6
0
        /// <summary>
        /// Process files from the directory referenced in the message
        /// </summary>
        /// <param name="header"></param>
        /// <param name="message"></param>
        public void ReadTags(IMessageHeader header, AccessionDirectoryMessage message)
        {
            _stopwatch.Restart();

            string dirPath = message.GetAbsolutePath(_filesystemRoot);

            Logger.Debug("TagReader: About to process files in " + dirPath);

            if (!_fs.Directory.Exists(dirPath))
            {
                throw new ApplicationException("Directory not found: " + dirPath);
            }

            if (!dirPath.StartsWith(_filesystemRoot, StringComparison.CurrentCultureIgnoreCase))
            {
                throw new ApplicationException("Directory " + dirPath + " is not below the given FileSystemRoot (" +
                                               _filesystemRoot + ")");
            }
            long beginEnumerate = _stopwatch.ElapsedTicks;

            string[] dicomFilePaths = _fs.Directory.EnumerateFiles(dirPath, _searchPattern).Where(Include).ToArray();
            string[] zipFilePaths   = _fs.Directory.EnumerateFiles(dirPath).Where(ZipHelper.IsZip).Where(Include).ToArray();

            _swTotals[0] += _stopwatch.ElapsedTicks - beginEnumerate;
            Logger.Debug("TagReader: Found " + dicomFilePaths.Length + " dicom files to process");
            Logger.Debug("TagReader: Found " + zipFilePaths.Length + " zip files to process");

            int toProcess = dicomFilePaths.Length + zipFilePaths.Length;

            if (toProcess == 0)
            {
                throw new ApplicationException("No dicom/zip files found in " + dirPath);
            }

            // We have files to process, let's do it!

            long beginRead = _stopwatch.ElapsedTicks;

            List <DicomFileMessage> fileMessages = ReadTagsImpl(dicomFilePaths.Select(p => new FileInfo(p)), message);

            fileMessages.AddRange(ReadZipFilesImpl(zipFilePaths.Select(p => new FileInfo(p)), message));

            _swTotals[1] += (_stopwatch.ElapsedTicks - beginRead) / toProcess;

            var seriesMessages = new Dictionary <string, SeriesMessage>();

            foreach (DicomFileMessage fileMessage in fileMessages)
            {
                string seriesUID = fileMessage.SeriesInstanceUID;

                // If we've already seen this seriesUID, just update the image count
                if (seriesMessages.ContainsKey(seriesUID))
                {
                    seriesMessages[seriesUID].ImagesInSeries++;
                    continue;
                }

                // Else create a new SeriesMessage
                var seriesMessage = new SeriesMessage
                {
                    NationalPACSAccessionNumber = fileMessage.NationalPACSAccessionNumber,
                    DirectoryPath = message.DirectoryPath,

                    StudyInstanceUID  = fileMessage.StudyInstanceUID,
                    SeriesInstanceUID = seriesUID,

                    ImagesInSeries = 1,

                    DicomDataset = fileMessage.DicomDataset
                };

                seriesMessages.Add(seriesUID, seriesMessage);
            }

            Logger.Debug("TagReader: Finished processing directory, sending messages");

            // Only send if have processed all files in the directory ok

            if (!fileMessages.Any())
            {
                throw new ApplicationException("No DicomFileMessage(s) to send after processing the directory");
            }

            if (!seriesMessages.Any())
            {
                throw new ApplicationException("No SeriesMessage(s) to send but we have file messages");
            }

            Logger.Info($"Sending {fileMessages.Count} DicomFileMessage(s)");

            long beginSend = _stopwatch.ElapsedTicks;
            var  headers   = new List <IMessageHeader>();

            foreach (DicomFileMessage fileMessage in fileMessages)
            {
                headers.Add(_fileMessageProducerModel.SendMessage(fileMessage, header));
            }

            _fileMessageProducerModel.WaitForConfirms();

            headers.ForEach(x => x.Log(Logger, LogLevel.Trace, $"Sent {header?.MessageGuid}"));

            Logger.Info($"Sending {seriesMessages.Count} SeriesMessage(s)");

            headers.Clear();
            foreach (KeyValuePair <string, SeriesMessage> kvp in seriesMessages)
            {
                headers.Add(_seriesMessageProducerModel.SendMessage(kvp.Value, header));
            }

            _seriesMessageProducerModel.WaitForConfirms();
            headers.ForEach(x => x.Log(Logger, LogLevel.Trace, $"Sent {x.MessageGuid}"));

            _swTotals[2]   += _stopwatch.ElapsedTicks - beginSend;
            _swTotals[3]   += _stopwatch.ElapsedTicks;
            _nMessagesSent += fileMessages.Count + seriesMessages.Count;

            if (++_nAccMessagesProcessed % 10 == 0)
            {
                LogRates();
            }
        }
Exemple #7
0
        protected override void ProcessMessageImpl(IMessageHeader header, ExtractionRequestMessage request, ulong tag)
        {
            Logger.Info($"Received message: {request}");

            _auditor.AuditExtractionRequest(request);

            if (!request.ExtractionDirectory.StartsWith(request.ProjectNumber))
            {
                Logger.Debug("ExtractionDirectory did not start with the project number, doing ErrorAndNack");
                ErrorAndNack(header, tag, "", new InvalidEnumArgumentException("ExtractionDirectory"));
            }

            string extractionDirectory   = request.ExtractionDirectory.TrimEnd('/', '\\');
            string extractFileRoutingKey = request.IsIdentifiableExtraction ? _options.ExtractIdentRoutingKey : _options.ExtractAnonRoutingKey;

            foreach (ExtractImageCollection matchedFiles in _fulfiller.GetAllMatchingFiles(request, _auditor))
            {
                Logger.Info($"Accepted {matchedFiles.Accepted.Count} and rejected {matchedFiles.Rejected.Count} files for KeyValue {matchedFiles.KeyValue}");

                var infoMessage = new ExtractFileCollectionInfoMessage(request);

                foreach (QueryToExecuteResult accepted in matchedFiles.Accepted)
                {
                    var extractFileMessage = new ExtractFileMessage(request)
                    {
                        // Path to the original file
                        DicomFilePath = accepted.FilePathValue.TrimStart('/', '\\'),
                        // Extraction directory relative to the extract root
                        ExtractionDirectory = extractionDirectory,
                        // Output path for the anonymised file, relative to the extraction directory
                        OutputPath = _resolver.GetOutputPath(accepted, request).Replace('\\', '/')
                    };

                    Logger.Debug($"DicomFilePath={extractFileMessage.DicomFilePath}, OutputPath={extractFileMessage.OutputPath}");

                    // Send the extract file message
                    var sentHeader = (MessageHeader)_fileMessageProducer.SendMessage(extractFileMessage, header, extractFileRoutingKey);

                    // Record that we sent it
                    infoMessage.ExtractFileMessagesDispatched.Add(sentHeader, extractFileMessage.OutputPath);
                }

                // Wait for confirms from the batched messages
                Logger.Debug($"All file messages sent for {request.ExtractionJobIdentifier}, calling WaitForConfirms");
                _fileMessageProducer.WaitForConfirms();

                // For all the rejected messages log why (in the info message)
                foreach (QueryToExecuteResult rejectedResults in matchedFiles.Rejected)
                {
                    if (!infoMessage.RejectionReasons.ContainsKey(rejectedResults.RejectReason))
                    {
                        infoMessage.RejectionReasons.Add(rejectedResults.RejectReason, 0);
                    }

                    infoMessage.RejectionReasons[rejectedResults.RejectReason]++;
                }

                _auditor.AuditExtractFiles(request, matchedFiles);

                infoMessage.KeyValue = matchedFiles.KeyValue;
                _fileMessageInfoProducer.SendMessage(infoMessage, header);

                if (_fileMessageInfoProducer.GetType() == typeof(BatchProducerModel))
                {
                    _fileMessageInfoProducer.WaitForConfirms();
                }

                Logger.Info($"All messages sent and acknowledged for {matchedFiles.KeyValue}");
            }

            Logger.Info("Finished processing message");
            Ack(header, tag);
        }