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