Mercurial > hg > orthanc
comparison OrthancServer/ServerIndex.cpp @ 187:8e673a65564d
refactoring of storing new instances
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 12 Nov 2012 17:29:11 +0100 |
parents | f68c039b0571 |
children | 090cefdab1d1 |
comparison
equal
deleted
inserted
replaced
186:f68c039b0571 | 187:8e673a65564d |
---|---|
237 void ServerIndex::CreateInstance(DicomInstanceHasher& hasher, | 237 void ServerIndex::CreateInstance(DicomInstanceHasher& hasher, |
238 const DicomMap& dicomSummary, | 238 const DicomMap& dicomSummary, |
239 const std::string& fileUuid, | 239 const std::string& fileUuid, |
240 uint64_t fileSize, | 240 uint64_t fileSize, |
241 const std::string& jsonUuid, | 241 const std::string& jsonUuid, |
242 const std::string& distantAet) | 242 const std::string& remoteAet) |
243 { | 243 { |
244 SQLite::Statement s2(db_, SQLITE_FROM_HERE, "INSERT INTO Resources VALUES(?, ?)"); | 244 SQLite::Statement s2(db_, SQLITE_FROM_HERE, "INSERT INTO Resources VALUES(?, ?)"); |
245 s2.BindString(0, hasher.HashInstance()); | 245 s2.BindString(0, hasher.HashInstance()); |
246 s2.BindInt(1, ResourceType_Instance); | 246 s2.BindInt(1, ResourceType_Instance); |
247 s2.Run(); | 247 s2.Run(); |
251 s.BindString(1, hasher.HashSeries()); | 251 s.BindString(1, hasher.HashSeries()); |
252 s.BindString(2, hasher.GetInstanceUid()); | 252 s.BindString(2, hasher.GetInstanceUid()); |
253 s.BindString(3, fileUuid); | 253 s.BindString(3, fileUuid); |
254 s.BindInt64(4, fileSize); | 254 s.BindInt64(4, fileSize); |
255 s.BindString(5, jsonUuid); | 255 s.BindString(5, jsonUuid); |
256 s.BindString(6, distantAet); | 256 s.BindString(6, remoteAet); |
257 | 257 |
258 const DicomValue* indexInSeries; | 258 const DicomValue* indexInSeries; |
259 if ((indexInSeries = dicomSummary.TestAndGetValue(DICOM_TAG_INSTANCE_NUMBER)) != NULL || | 259 if ((indexInSeries = dicomSummary.TestAndGetValue(DICOM_TAG_INSTANCE_NUMBER)) != NULL || |
260 (indexInSeries = dicomSummary.TestAndGetValue(DICOM_TAG_IMAGE_INDEX)) != NULL) | 260 (indexInSeries = dicomSummary.TestAndGetValue(DICOM_TAG_IMAGE_INDEX)) != NULL) |
261 { | 261 { |
509 db_.Execute(query); | 509 db_.Execute(query); |
510 } | 510 } |
511 } | 511 } |
512 | 512 |
513 | 513 |
514 StoreStatus ServerIndex::Store(std::string& instanceUuid, | 514 StoreStatus ServerIndex::Store2(const DicomMap& dicomSummary, |
515 const DicomMap& dicomSummary, | 515 const std::string& fileUuid, |
516 uint64_t uncompressedFileSize, | |
517 const std::string& jsonUuid, | |
518 const std::string& remoteAet) | |
519 { | |
520 boost::mutex::scoped_lock scoped_lock(mutex_); | |
521 | |
522 DicomInstanceHasher hasher(dicomSummary); | |
523 | |
524 try | |
525 { | |
526 std::auto_ptr<SQLite::Transaction> t(db2_->StartTransaction()); | |
527 t->Begin(); | |
528 | |
529 int64_t patient, study, series, instance; | |
530 ResourceType type; | |
531 bool isNewSeries = false; | |
532 | |
533 // Do nothing if the instance already exists | |
534 if (db2_->FindResource(hasher.HashInstance(), patient, type)) | |
535 { | |
536 assert(type == ResourceType_Patient); | |
537 return StoreStatus_AlreadyStored; | |
538 } | |
539 | |
540 // Create the patient/study/series/instance hierarchy | |
541 instance = db2_->CreateResource(hasher.HashInstance(), ResourceType_Instance); | |
542 | |
543 if (!db2_->FindResource(hasher.HashSeries(), series, type)) | |
544 { | |
545 // This is a new series | |
546 isNewSeries = true; | |
547 series = db2_->CreateResource(hasher.HashSeries(), ResourceType_Series); | |
548 db2_->AttachChild(series, instance); | |
549 | |
550 if (!db2_->FindResource(hasher.HashStudy(), study, type)) | |
551 { | |
552 // This is a new study | |
553 study = db2_->CreateResource(hasher.HashStudy(), ResourceType_Study); | |
554 db2_->AttachChild(study, series); | |
555 | |
556 if (!db2_->FindResource(hasher.HashPatient(), patient, type)) | |
557 { | |
558 // This is a new patient | |
559 patient = db2_->CreateResource(hasher.HashPatient(), ResourceType_Patient); | |
560 db2_->AttachChild(patient, study); | |
561 } | |
562 else | |
563 { | |
564 assert(type == ResourceType_Patient); | |
565 } | |
566 } | |
567 else | |
568 { | |
569 assert(type == ResourceType_Study); | |
570 } | |
571 } | |
572 else | |
573 { | |
574 assert(type == ResourceType_Series); | |
575 } | |
576 | |
577 // Attach the files to the newly created instance | |
578 db2_->AttachFile(instance, "_dicom", fileUuid, uncompressedFileSize); | |
579 db2_->AttachFile(instance, "_json", jsonUuid, 0); // TODO "0" | |
580 | |
581 // Attach the metadata | |
582 db2_->SetMetadata(instance, MetadataType_Instance_ReceptionDate, Toolbox::GetNowIsoString()); | |
583 db2_->SetMetadata(instance, MetadataType_Instance_RemoteAet, remoteAet); | |
584 | |
585 const DicomValue* value; | |
586 if ((value = dicomSummary.TestAndGetValue(DICOM_TAG_INSTANCE_NUMBER)) != NULL || | |
587 (value = dicomSummary.TestAndGetValue(DICOM_TAG_IMAGE_INDEX)) != NULL) | |
588 { | |
589 db2_->SetMetadata(instance, MetadataType_Instance_IndexInSeries, value->AsString()); | |
590 } | |
591 | |
592 if (isNewSeries) | |
593 { | |
594 if ((value = dicomSummary.TestAndGetValue(DICOM_TAG_NUMBER_OF_SLICES)) != NULL || | |
595 (value = dicomSummary.TestAndGetValue(DICOM_TAG_IMAGES_IN_ACQUISITION)) != NULL) | |
596 { | |
597 db2_->SetMetadata(series, MetadataType_Series_ExpectedNumberOfInstances, value->AsString()); | |
598 } | |
599 } | |
600 | |
601 t->Commit(); | |
602 } | |
603 catch (OrthancException& e) | |
604 { | |
605 LOG(ERROR) << "EXCEPTION2 [" << e.What() << "]" << " " << db_.GetErrorMessage(); | |
606 } | |
607 | |
608 return StoreStatus_Failure; | |
609 } | |
610 | |
611 | |
612 StoreStatus ServerIndex::Store(const DicomMap& dicomSummary, | |
516 const std::string& fileUuid, | 613 const std::string& fileUuid, |
517 uint64_t uncompressedFileSize, | 614 uint64_t uncompressedFileSize, |
518 const std::string& jsonUuid, | 615 const std::string& jsonUuid, |
519 const std::string& distantAet) | 616 const std::string& remoteAet) |
520 { | 617 { |
618 Store2(dicomSummary, fileUuid, uncompressedFileSize, jsonUuid, remoteAet); | |
619 | |
521 boost::mutex::scoped_lock scoped_lock(mutex_); | 620 boost::mutex::scoped_lock scoped_lock(mutex_); |
522 | 621 |
523 DicomInstanceHasher hasher(dicomSummary); | 622 DicomInstanceHasher hasher(dicomSummary); |
524 | 623 |
525 try | 624 try |
559 { | 658 { |
560 CreateSeries(hasher, dicomSummary); | 659 CreateSeries(hasher, dicomSummary); |
561 } | 660 } |
562 | 661 |
563 CreateInstance(hasher, dicomSummary, fileUuid, | 662 CreateInstance(hasher, dicomSummary, fileUuid, |
564 uncompressedFileSize, jsonUuid, distantAet); | 663 uncompressedFileSize, jsonUuid, remoteAet); |
565 | 664 |
566 t.Commit(); | 665 t.Commit(); |
567 return StoreStatus_Success; | 666 return StoreStatus_Success; |
568 //t.Rollback(); | 667 //t.Rollback(); |
569 } | 668 } |
574 | 673 |
575 return StoreStatus_Failure; | 674 return StoreStatus_Failure; |
576 } | 675 } |
577 | 676 |
578 | 677 |
579 StoreStatus ServerIndex::Store(std::string& instanceUuid, | 678 StoreStatus ServerIndex::Store(FileStorage& storage, |
580 FileStorage& storage, | |
581 const char* dicomFile, | 679 const char* dicomFile, |
582 size_t dicomSize, | 680 size_t dicomSize, |
583 const DicomMap& dicomSummary, | 681 const DicomMap& dicomSummary, |
584 const Json::Value& dicomJson, | 682 const Json::Value& dicomJson, |
585 const std::string& distantAet) | 683 const std::string& remoteAet) |
586 { | 684 { |
587 std::string fileUuid = storage.Create(dicomFile, dicomSize); | 685 std::string fileUuid = storage.Create(dicomFile, dicomSize); |
588 std::string jsonUuid = storage.Create(dicomJson.toStyledString()); | 686 std::string jsonUuid = storage.Create(dicomJson.toStyledString()); |
589 StoreStatus status = Store(instanceUuid, dicomSummary, fileUuid, | 687 StoreStatus status = Store(dicomSummary, fileUuid, dicomSize, jsonUuid, remoteAet); |
590 dicomSize, jsonUuid, distantAet); | |
591 | 688 |
592 if (status != StoreStatus_Success) | 689 if (status != StoreStatus_Success) |
593 { | 690 { |
594 storage.Remove(fileUuid); | 691 storage.Remove(fileUuid); |
595 storage.Remove(jsonUuid); | 692 storage.Remove(jsonUuid); |
596 } | 693 } |
597 | 694 |
598 switch (status) | 695 switch (status) |
599 { | 696 { |
600 case StoreStatus_Success: | 697 case StoreStatus_Success: |
601 LOG(WARNING) << "New instance stored: " << GetTotalSize() << " bytes"; | 698 LOG(WARNING) << "New instance stored"; |
602 break; | 699 break; |
603 | 700 |
604 case StoreStatus_AlreadyStored: | 701 case StoreStatus_AlreadyStored: |
605 LOG(WARNING) << "Already stored"; | 702 LOG(WARNING) << "Already stored"; |
606 break; | 703 break; |
611 } | 708 } |
612 | 709 |
613 return status; | 710 return status; |
614 } | 711 } |
615 | 712 |
616 uint64_t ServerIndex::GetTotalSize() | 713 uint64_t ServerIndex::GetTotalCompressedSize() |
617 { | 714 { |
618 boost::mutex::scoped_lock scoped_lock(mutex_); | 715 boost::mutex::scoped_lock scoped_lock(mutex_); |
619 SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT SUM(fileSize) FROM Instances"); | 716 return db2_->GetTotalCompressedSize(); |
620 s.Run(); | 717 } |
621 return s.ColumnInt64(0); | 718 |
622 } | 719 uint64_t ServerIndex::GetTotalUncompressedSize() |
720 { | |
721 boost::mutex::scoped_lock scoped_lock(mutex_); | |
722 return db2_->GetTotalUncompressedSize(); | |
723 } | |
724 | |
725 | |
623 | 726 |
624 | 727 |
625 SeriesStatus ServerIndex::GetSeriesStatus(const std::string& seriesUuid) | 728 SeriesStatus ServerIndex::GetSeriesStatus(const std::string& seriesUuid) |
626 { | 729 { |
627 SQLite::Statement s1(db_, SQLITE_FROM_HERE, "SELECT expectedNumberOfInstances FROM Series WHERE uuid=?"); | 730 SQLite::Statement s1(db_, SQLITE_FROM_HERE, "SELECT expectedNumberOfInstances FROM Series WHERE uuid=?"); |