comparison OrthancServer/OrthancRestApi/OrthancRestArchive.cpp @ 1777:0f5c416969dc

more memory-efficient ArchiveIndex
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 13 Nov 2015 11:51:19 +0100
parents 3c28f5f6c9b7
children 776573e592da
comparison
equal deleted inserted replaced
1776:3c28f5f6c9b7 1777:0f5c416969dc
510 id_(id), dicom_(dicom) 510 id_(id), dicom_(dicom)
511 { 511 {
512 } 512 }
513 }; 513 };
514 514
515 // A "NULL" value for ArchiveIndex indicates a non-expanded node
515 typedef std::map<std::string, ArchiveIndex*> Resources; 516 typedef std::map<std::string, ArchiveIndex*> Resources;
516 517
517 ServerIndex& index_; 518 ResourceType level_;
518 ResourceType level_; 519 Resources resources_; // Only at patient/study/series level
519 Resources resources_; 520 std::list<Instance> instances_; // Only at instance level
520 std::vector<Instance> instances_; 521
521 522
522 void AddResourceToExpand(const std::string& id) 523 void AddResourceToExpand(ServerIndex& index,
523 { 524 const std::string& id)
524 resources_[id] = NULL; 525 {
525 } 526 if (level_ == ResourceType_Instance)
527 {
528 FileInfo tmp;
529 if (index.LookupAttachment(tmp, id, FileContentType_Dicom))
530 {
531 instances_.push_back(Instance(id, tmp));
532 }
533 }
534 else
535 {
536 resources_[id] = NULL;
537 }
538 }
539
526 540
527 public: 541 public:
528 ArchiveIndex(ServerIndex& index, 542 ArchiveIndex(ResourceType level) :
529 ResourceType level) :
530 index_(index),
531 level_(level) 543 level_(level)
532 { 544 {
533 } 545 }
534 546
535 ~ArchiveIndex() 547 ~ArchiveIndex()
539 { 551 {
540 delete it->second; 552 delete it->second;
541 } 553 }
542 } 554 }
543 555
544 void Add(const ResourceIdentifiers& resource) 556
557 void Add(ServerIndex& index,
558 const ResourceIdentifiers& resource)
545 { 559 {
546 const std::string& id = resource.GetIdentifier(level_); 560 const std::string& id = resource.GetIdentifier(level_);
547 Resources::iterator previous = resources_.find(id); 561 Resources::iterator previous = resources_.find(id);
548 562
549 if (resource.GetLevel() == level_) 563 if (level_ == ResourceType_Instance)
564 {
565 AddResourceToExpand(index, id);
566 }
567 else if (resource.GetLevel() == level_)
550 { 568 {
551 // Mark this resource for further expansion 569 // Mark this resource for further expansion
552 if (previous != resources_.end()) 570 if (previous != resources_.end())
553 { 571 {
554 delete previous->second; 572 delete previous->second;
557 resources_[id] = NULL; 575 resources_[id] = NULL;
558 } 576 }
559 else if (previous == resources_.end()) 577 else if (previous == resources_.end())
560 { 578 {
561 // This is the first time we meet this resource 579 // This is the first time we meet this resource
562 std::auto_ptr<ArchiveIndex> child(new ArchiveIndex(index_, GetChildResourceType(level_))); 580 std::auto_ptr<ArchiveIndex> child(new ArchiveIndex(GetChildResourceType(level_)));
563 child->Add(resource); 581 child->Add(index, resource);
564 resources_[id] = child.release(); 582 resources_[id] = child.release();
565 } 583 }
566 else if (previous->second != NULL) 584 else if (previous->second != NULL)
567 { 585 {
568 previous->second->Add(resource); 586 previous->second->Add(index, resource);
569 } 587 }
570 else 588 else
571 { 589 {
572 // Nothing to do: This item is marked for further expansion 590 // Nothing to do: This item is marked for further expansion
573 } 591 }
574 } 592 }
575 593
576 594
577 void Expand() 595 void Expand(ServerIndex& index)
578 { 596 {
579 if (level_ == ResourceType_Instance) 597 if (level_ == ResourceType_Instance)
580 { 598 {
581 // At the instance level, locate all the DICOM files 599 // Expanding an instance node makes no sense
582 // associated with the instances 600 return;
583 instances_.reserve(resources_.size()); 601 }
584 602
585 for (Resources::iterator it = resources_.begin(); 603 for (Resources::iterator it = resources_.begin();
586 it != resources_.end(); ++it) 604 it != resources_.end(); ++it)
587 { 605 {
588 assert(it->second == NULL); 606 if (it->second == NULL)
589 607 {
590 FileInfo tmp; 608 // This is resource is marked for expansion
591 if (index_.LookupAttachment(tmp, it->first, FileContentType_Dicom)) 609 std::list<std::string> children;
610 index.GetChildren(children, it->first);
611
612 std::auto_ptr<ArchiveIndex> child(new ArchiveIndex(GetChildResourceType(level_)));
613
614 for (std::list<std::string>::const_iterator
615 it2 = children.begin(); it2 != children.end(); ++it2)
592 { 616 {
593 instances_.push_back(Instance(it->first, tmp)); 617 child->AddResourceToExpand(index, *it2);
594 } 618 }
595 } 619
596 } 620 it->second = child.release();
597 else 621 }
598 { 622
599 // At the patient, study or series level 623 assert(it->second != NULL);
600 for (Resources::iterator it = resources_.begin(); 624 it->second->Expand(index);
601 it != resources_.end(); ++it) 625 }
602 {
603 if (it->second == NULL)
604 {
605 // This is resource is marked for expansion
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();
618 }
619
620 assert(it->second != NULL);
621 it->second->Expand();
622 }
623 }
624 } 626 }
625 627
626 628
627 void Apply(IArchiveVisitor& visitor) const 629 void Apply(IArchiveVisitor& visitor) const
628 { 630 {
629 if (level_ == ResourceType_Instance) 631 if (level_ == ResourceType_Instance)
630 { 632 {
631 for (size_t i = 0; i < instances_.size(); i++) 633 for (std::list<Instance>::const_iterator
632 { 634 it = instances_.begin(); it != instances_.end(); ++it)
633 visitor.AddInstance(instances_[i].id_, instances_[i].dicom_); 635 {
636 visitor.AddInstance(it->id_, it->dicom_);
634 } 637 }
635 } 638 }
636 else 639 else
637 { 640 {
638 for (Resources::const_iterator it = resources_.begin(); 641 for (Resources::const_iterator it = resources_.begin();
732 735
733 Json::Value resources; 736 Json::Value resources;
734 if (call.ParseJsonRequest(resources) && 737 if (call.ParseJsonRequest(resources) &&
735 resources.type() == Json::arrayValue) 738 resources.type() == Json::arrayValue)
736 { 739 {
737 ArchiveIndex archive(index, ResourceType_Patient); // root 740 ArchiveIndex archive(ResourceType_Patient); // root
738 741
739 for (Json::Value::ArrayIndex i = 0; i < resources.size(); i++) 742 for (Json::Value::ArrayIndex i = 0; i < resources.size(); i++)
740 { 743 {
741 if (resources[i].type() != Json::stringValue) 744 if (resources[i].type() != Json::stringValue)
742 { 745 {
743 return; // Bad request 746 return; // Bad request
744 } 747 }
745 748
746 ResourceIdentifiers resource(index, resources[i].asString()); 749 ResourceIdentifiers resource(index, resources[i].asString());
747 archive.Add(resource); 750 archive.Add(index, resource);
748 } 751 }
749 752
750 archive.Expand(); 753 archive.Expand(index);
751 754
752 PrintVisitor v(std::cout); 755 PrintVisitor v(std::cout);
753 archive.Apply(v); 756 archive.Apply(v);
754 757
755 StatisticsVisitor s; 758 StatisticsVisitor s;