Mercurial > hg > orthanc
comparison OrthancServer/OrthancRestApi/OrthancRestArchive.cpp @ 1775:1861e410a9d7
visitors
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 13 Nov 2015 11:18:48 +0100 |
parents | 784a6b92d2f1 |
children | 3c28f5f6c9b7 |
comparison
equal
deleted
inserted
replaced
1774:784a6b92d2f1 | 1775:1861e410a9d7 |
---|---|
32 | 32 |
33 #include "../PrecompiledHeadersServer.h" | 33 #include "../PrecompiledHeadersServer.h" |
34 #include "OrthancRestApi.h" | 34 #include "OrthancRestApi.h" |
35 | 35 |
36 #include "../DicomDirWriter.h" | 36 #include "../DicomDirWriter.h" |
37 #include "../../Core/FileStorage/StorageAccessor.h" | |
37 #include "../../Core/Compression/HierarchicalZipWriter.h" | 38 #include "../../Core/Compression/HierarchicalZipWriter.h" |
38 #include "../../Core/HttpServer/FilesystemHttpSender.h" | 39 #include "../../Core/HttpServer/FilesystemHttpSender.h" |
39 #include "../../Core/Logging.h" | 40 #include "../../Core/Logging.h" |
40 #include "../../Core/Uuid.h" | 41 #include "../../Core/Uuid.h" |
41 #include "../ServerContext.h" | 42 #include "../ServerContext.h" |
477 } | 478 } |
478 } | 479 } |
479 }; | 480 }; |
480 | 481 |
481 | 482 |
483 class IArchiveVisitor : public boost::noncopyable | |
484 { | |
485 public: | |
486 virtual ~IArchiveVisitor() | |
487 { | |
488 } | |
489 | |
490 virtual void Open(ResourceType level, | |
491 const std::string& publicId) = 0; | |
492 | |
493 virtual void Close() = 0; | |
494 | |
495 virtual void AddInstance(const std::string& instanceId, | |
496 const FileInfo& dicom) = 0; | |
497 }; | |
498 | |
499 | |
482 class ArchiveIndex | 500 class ArchiveIndex |
483 { | 501 { |
484 private: | 502 private: |
485 typedef std::map<std::string, ArchiveIndex*> Resources; | 503 struct Instance |
486 | 504 { |
487 ServerIndex& index_; | 505 std::string id_; |
488 ResourceType level_; | 506 FileInfo dicom_; |
489 Resources resources_; | 507 |
508 Instance(const std::string& id, | |
509 const FileInfo& dicom) : | |
510 id_(id), dicom_(dicom) | |
511 { | |
512 } | |
513 }; | |
514 | |
515 typedef std::map<std::string, ArchiveIndex*> Resources; | |
516 | |
517 ServerIndex& index_; | |
518 ResourceType level_; | |
519 Resources resources_; | |
520 std::vector<Instance> instances_; | |
490 | 521 |
491 void AddResourceToExpand(const std::string& id) | 522 void AddResourceToExpand(const std::string& id) |
492 { | 523 { |
493 resources_[id] = NULL; | 524 resources_[id] = NULL; |
494 } | 525 } |
545 | 576 |
546 void Expand() | 577 void Expand() |
547 { | 578 { |
548 if (level_ == ResourceType_Instance) | 579 if (level_ == ResourceType_Instance) |
549 { | 580 { |
550 return; | 581 // At the instance level, locate all the DICOM files |
551 } | 582 // associated with the instances |
552 | 583 instances_.reserve(resources_.size()); |
553 for (Resources::iterator it = resources_.begin(); | 584 |
554 it != resources_.end(); ++it) | 585 for (Resources::iterator it = resources_.begin(); |
555 { | 586 it != resources_.end(); ++it) |
556 if (it->second == NULL) | 587 { |
557 { | 588 assert(it->second == NULL); |
558 std::list<std::string> children; | 589 |
559 index_.GetChildren(children, it->first); | 590 FileInfo tmp; |
560 | 591 if (index_.LookupAttachment(tmp, it->first, FileContentType_Dicom)) |
561 std::auto_ptr<ArchiveIndex> child(new ArchiveIndex(index_, GetChildResourceType(level_))); | |
562 | |
563 for (std::list<std::string>::const_iterator | |
564 it2 = children.begin(); it2 != children.end(); ++it2) | |
565 { | 592 { |
566 child->AddResourceToExpand(*it2); | 593 instances_.push_back(Instance(it->first, tmp)); |
567 } | |
568 | |
569 it->second = child.release(); | |
570 } | |
571 | |
572 assert(it->second != NULL); | |
573 it->second->Expand(); | |
574 } | |
575 } | |
576 | |
577 | |
578 void ComputeStatistics(uint64_t& totalSize, | |
579 unsigned int& totalInstances) | |
580 { | |
581 for (Resources::iterator it = resources_.begin(); | |
582 it != resources_.end(); ++it) | |
583 { | |
584 if (level_ == ResourceType_Instance) | |
585 { | |
586 FileInfo dicom; | |
587 if (index_.LookupAttachment(dicom, it->first, FileContentType_Dicom)) | |
588 { | |
589 totalSize += dicom.GetUncompressedSize(); | |
590 totalInstances ++; | |
591 } | 594 } |
592 } | 595 } |
593 else | 596 } |
597 else | |
598 { | |
599 // At the patient, study or series level | |
600 for (Resources::iterator it = resources_.begin(); | |
601 it != resources_.end(); ++it) | |
594 { | 602 { |
595 if (it->second == NULL) | 603 if (it->second == NULL) |
596 { | 604 { |
597 // The method "Expand" was not called | 605 // This is resource is marked for expansion |
598 throw OrthancException(ErrorCode_InternalError); | 606 std::list<std::string> children; |
607 index_.GetChildren(children, it->first); | |
608 | |
609 std::auto_ptr<ArchiveIndex> child(new ArchiveIndex(index_, GetChildResourceType(level_))); | |
610 | |
611 for (std::list<std::string>::const_iterator | |
612 it2 = children.begin(); it2 != children.end(); ++it2) | |
613 { | |
614 child->AddResourceToExpand(*it2); | |
615 } | |
616 | |
617 it->second = child.release(); | |
599 } | 618 } |
600 | 619 |
601 it->second->ComputeStatistics(totalSize, totalInstances); | 620 assert(it->second != NULL); |
621 it->second->Expand(); | |
622 } | |
623 } | |
624 } | |
625 | |
626 | |
627 void Apply(IArchiveVisitor& visitor) const | |
628 { | |
629 if (level_ == ResourceType_Instance) | |
630 { | |
631 for (size_t i = 0; i < instances_.size(); i++) | |
632 { | |
633 visitor.AddInstance(instances_[i].id_, instances_[i].dicom_); | |
634 } | |
635 } | |
636 else | |
637 { | |
638 for (Resources::const_iterator it = resources_.begin(); | |
639 it != resources_.end(); ++it) | |
640 { | |
641 assert(it->second != NULL); // There must have been a call to "Expand()" | |
642 visitor.Open(level_, it->first); | |
643 it->second->Apply(visitor); | |
644 visitor.Close(); | |
602 } | 645 } |
603 } | 646 } |
604 } | 647 } |
605 | 648 }; |
606 | 649 |
607 void Print(std::ostream& o, | 650 |
608 const std::string& indent = "") const | 651 class StatisticsVisitor : public IArchiveVisitor |
609 { | 652 { |
610 for (Resources::const_iterator it = resources_.begin(); | 653 private: |
611 it != resources_.end(); ++it) | 654 uint64_t size_; |
612 { | 655 unsigned int instances_; |
613 o << indent << it->first << std::endl; | 656 |
614 if (it->second == NULL) | 657 public: |
615 { | 658 StatisticsVisitor() : size_(0), instances_(0) |
616 if (level_ != ResourceType_Instance) | 659 { |
617 { | 660 } |
618 o << indent << " *" << std::endl; | 661 |
619 } | 662 uint64_t GetUncompressedSize() const |
620 } | 663 { |
621 else | 664 return size_; |
622 { | 665 } |
623 it->second->Print(o, indent + " "); | 666 |
624 } | 667 unsigned int GetInstancesCount() const |
625 } | 668 { |
669 return instances_; | |
670 } | |
671 | |
672 virtual void Open(ResourceType level, | |
673 const std::string& publicId) | |
674 { | |
675 } | |
676 | |
677 virtual void Close() | |
678 { | |
679 } | |
680 | |
681 virtual void AddInstance(const std::string& instanceId, | |
682 const FileInfo& dicom) | |
683 { | |
684 instances_ ++; | |
685 size_ += dicom.GetUncompressedSize(); | |
686 } | |
687 }; | |
688 | |
689 | |
690 class PrintVisitor : public IArchiveVisitor | |
691 { | |
692 private: | |
693 std::ostream& out_; | |
694 std::string indent_; | |
695 | |
696 public: | |
697 PrintVisitor(std::ostream& out) : out_(out) | |
698 { | |
699 } | |
700 | |
701 virtual void Open(ResourceType level, | |
702 const std::string& publicId) | |
703 { | |
704 switch (level) | |
705 { | |
706 case ResourceType_Patient: indent_ = ""; break; | |
707 case ResourceType_Study: indent_ = " "; break; | |
708 case ResourceType_Series: indent_ = " "; break; | |
709 default: | |
710 throw OrthancException(ErrorCode_InternalError); | |
711 } | |
712 | |
713 out_ << indent_ << publicId << std::endl; | |
714 } | |
715 | |
716 virtual void Close() | |
717 { | |
718 } | |
719 | |
720 virtual void AddInstance(const std::string& instanceId, | |
721 const FileInfo& dicom) | |
722 { | |
723 out_ << " " << instanceId << std::endl; | |
626 } | 724 } |
627 }; | 725 }; |
628 } | 726 } |
629 | 727 |
630 | 728 |
649 archive.Add(resource); | 747 archive.Add(resource); |
650 } | 748 } |
651 | 749 |
652 archive.Expand(); | 750 archive.Expand(); |
653 | 751 |
654 archive.Print(std::cout); | 752 PrintVisitor v(std::cout); |
655 | 753 archive.Apply(v); |
656 uint64_t totalSize = 0; | 754 |
657 unsigned int totalInstances = 0; | 755 StatisticsVisitor s; |
658 archive.ComputeStatistics(totalSize, totalInstances); | 756 archive.Apply(s); |
659 | 757 |
660 std::cout << totalSize << " " << totalInstances << std::endl; | 758 std::cout << s.GetUncompressedSize() << " " << s.GetInstancesCount() << std::endl; |
661 } | 759 } |
662 } | 760 } |
663 | 761 |
664 | 762 |
665 | 763 |