Mercurial > hg > orthanc
comparison OrthancServer/DatabaseWrapper.cpp @ 759:8cfc6119a5bd dicom-rt
integration mainline -> dicom-rt
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 16 Apr 2014 16:04:55 +0200 |
parents | fd36c80f096f |
children | a811bdf8b8eb |
comparison
equal
deleted
inserted
replaced
605:b82292ba2083 | 759:8cfc6119a5bd |
---|---|
1 /** | 1 /** |
2 * Orthanc - A Lightweight, RESTful DICOM Store | 2 * Orthanc - A Lightweight, RESTful DICOM Store |
3 * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, | 3 * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, |
4 * Belgium | 4 * Belgium |
5 * | 5 * |
6 * This program is free software: you can redistribute it and/or | 6 * This program is free software: you can redistribute it and/or |
7 * modify it under the terms of the GNU General Public License as | 7 * modify it under the terms of the GNU General Public License as |
8 * published by the Free Software Foundation, either version 3 of the | 8 * published by the Free Software Foundation, either version 3 of the |
60 return "SignalFileDeleted"; | 60 return "SignalFileDeleted"; |
61 } | 61 } |
62 | 62 |
63 virtual unsigned int GetCardinality() const | 63 virtual unsigned int GetCardinality() const |
64 { | 64 { |
65 return 5; | 65 return 7; |
66 } | 66 } |
67 | 67 |
68 virtual void Compute(SQLite::FunctionContext& context) | 68 virtual void Compute(SQLite::FunctionContext& context) |
69 { | 69 { |
70 std::string uncompressedMD5, compressedMD5; | |
71 | |
72 if (!context.IsNullValue(5)) | |
73 { | |
74 uncompressedMD5 = context.GetStringValue(5); | |
75 } | |
76 | |
77 if (!context.IsNullValue(6)) | |
78 { | |
79 compressedMD5 = context.GetStringValue(6); | |
80 } | |
81 | |
70 FileInfo info(context.GetStringValue(0), | 82 FileInfo info(context.GetStringValue(0), |
71 static_cast<FileContentType>(context.GetIntValue(1)), | 83 static_cast<FileContentType>(context.GetIntValue(1)), |
72 static_cast<uint64_t>(context.GetInt64Value(2)), | 84 static_cast<uint64_t>(context.GetInt64Value(2)), |
85 uncompressedMD5, | |
73 static_cast<CompressionType>(context.GetIntValue(3)), | 86 static_cast<CompressionType>(context.GetIntValue(3)), |
74 static_cast<uint64_t>(context.GetInt64Value(4))); | 87 static_cast<uint64_t>(context.GetInt64Value(4)), |
88 compressedMD5); | |
75 | 89 |
76 listener_.SignalFileDeleted(info); | 90 listener_.SignalFileDeleted(info); |
77 } | 91 } |
78 }; | 92 }; |
79 | 93 |
83 bool hasRemainingAncestor_; | 97 bool hasRemainingAncestor_; |
84 std::string remainingPublicId_; | 98 std::string remainingPublicId_; |
85 ResourceType remainingType_; | 99 ResourceType remainingType_; |
86 | 100 |
87 public: | 101 public: |
102 SignalRemainingAncestor() : | |
103 hasRemainingAncestor_(false) | |
104 { | |
105 } | |
106 | |
88 void Reset() | 107 void Reset() |
89 { | 108 { |
90 hasRemainingAncestor_ = false; | 109 hasRemainingAncestor_ = false; |
91 } | 110 } |
92 | 111 |
367 target = s.ColumnString(0); | 386 target = s.ColumnString(0); |
368 return true; | 387 return true; |
369 } | 388 } |
370 } | 389 } |
371 | 390 |
372 bool DatabaseWrapper::ListAvailableMetadata(std::list<MetadataType>& target, | 391 void DatabaseWrapper::ListAvailableMetadata(std::list<MetadataType>& target, |
373 int64_t id) | 392 int64_t id) |
374 { | 393 { |
375 target.clear(); | 394 target.clear(); |
376 | 395 |
377 SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT type FROM Metadata WHERE id=?"); | 396 SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT type FROM Metadata WHERE id=?"); |
379 | 398 |
380 while (s.Step()) | 399 while (s.Step()) |
381 { | 400 { |
382 target.push_back(static_cast<MetadataType>(s.ColumnInt(0))); | 401 target.push_back(static_cast<MetadataType>(s.ColumnInt(0))); |
383 } | 402 } |
384 | |
385 return true; | |
386 } | 403 } |
387 | 404 |
388 | 405 |
389 std::string DatabaseWrapper::GetMetadata(int64_t id, | 406 std::string DatabaseWrapper::GetMetadata(int64_t id, |
390 MetadataType type, | 407 MetadataType type, |
426 | 443 |
427 | 444 |
428 void DatabaseWrapper::AddAttachment(int64_t id, | 445 void DatabaseWrapper::AddAttachment(int64_t id, |
429 const FileInfo& attachment) | 446 const FileInfo& attachment) |
430 { | 447 { |
431 SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO AttachedFiles VALUES(?, ?, ?, ?, ?, ?)"); | 448 SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO AttachedFiles VALUES(?, ?, ?, ?, ?, ?, ?, ?)"); |
432 s.BindInt64(0, id); | 449 s.BindInt64(0, id); |
433 s.BindInt(1, attachment.GetContentType()); | 450 s.BindInt(1, attachment.GetContentType()); |
434 s.BindString(2, attachment.GetUuid()); | 451 s.BindString(2, attachment.GetUuid()); |
435 s.BindInt64(3, attachment.GetCompressedSize()); | 452 s.BindInt64(3, attachment.GetCompressedSize()); |
436 s.BindInt64(4, attachment.GetUncompressedSize()); | 453 s.BindInt64(4, attachment.GetUncompressedSize()); |
437 s.BindInt(5, attachment.GetCompressionType()); | 454 s.BindInt(5, attachment.GetCompressionType()); |
455 s.BindString(6, attachment.GetUncompressedMD5()); | |
456 s.BindString(7, attachment.GetCompressedMD5()); | |
438 s.Run(); | 457 s.Run(); |
439 } | 458 } |
459 | |
460 | |
461 void DatabaseWrapper::DeleteAttachment(int64_t id, | |
462 FileContentType attachment) | |
463 { | |
464 SQLite::Statement s(db_, SQLITE_FROM_HERE, "DELETE FROM AttachedFiles WHERE id=? AND fileType=?"); | |
465 s.BindInt64(0, id); | |
466 s.BindInt(1, attachment); | |
467 s.Run(); | |
468 } | |
469 | |
470 | |
440 | 471 |
441 void DatabaseWrapper::ListAvailableAttachments(std::list<FileContentType>& result, | 472 void DatabaseWrapper::ListAvailableAttachments(std::list<FileContentType>& result, |
442 int64_t id) | 473 int64_t id) |
443 { | 474 { |
444 result.clear(); | 475 result.clear(); |
456 bool DatabaseWrapper::LookupAttachment(FileInfo& attachment, | 487 bool DatabaseWrapper::LookupAttachment(FileInfo& attachment, |
457 int64_t id, | 488 int64_t id, |
458 FileContentType contentType) | 489 FileContentType contentType) |
459 { | 490 { |
460 SQLite::Statement s(db_, SQLITE_FROM_HERE, | 491 SQLite::Statement s(db_, SQLITE_FROM_HERE, |
461 "SELECT uuid, uncompressedSize, compressionType, compressedSize FROM AttachedFiles WHERE id=? AND fileType=?"); | 492 "SELECT uuid, uncompressedSize, compressionType, compressedSize, uncompressedMD5, compressedMD5 FROM AttachedFiles WHERE id=? AND fileType=?"); |
462 s.BindInt64(0, id); | 493 s.BindInt64(0, id); |
463 s.BindInt(1, contentType); | 494 s.BindInt(1, contentType); |
464 | 495 |
465 if (!s.Step()) | 496 if (!s.Step()) |
466 { | 497 { |
468 } | 499 } |
469 else | 500 else |
470 { | 501 { |
471 attachment = FileInfo(s.ColumnString(0), | 502 attachment = FileInfo(s.ColumnString(0), |
472 contentType, | 503 contentType, |
473 s.ColumnInt(1), | 504 s.ColumnInt64(1), |
505 s.ColumnString(4), | |
474 static_cast<CompressionType>(s.ColumnInt(2)), | 506 static_cast<CompressionType>(s.ColumnInt(2)), |
475 s.ColumnInt(3)); | 507 s.ColumnInt64(3), |
508 s.ColumnString(5)); | |
476 return true; | 509 return true; |
477 } | 510 } |
478 } | 511 } |
479 | 512 |
480 void DatabaseWrapper::SetMainDicomTags(int64_t id, | 513 void DatabaseWrapper::SetMainDicomTags(int64_t id, |
552 | 585 |
553 result.clear(); | 586 result.clear(); |
554 | 587 |
555 while (s.Step()) | 588 while (s.Step()) |
556 { | 589 { |
557 result.push_back(s.ColumnInt(0)); | 590 result.push_back(s.ColumnInt64(0)); |
558 } | 591 } |
559 } | 592 } |
560 | 593 |
561 | 594 |
562 void DatabaseWrapper::LogChange(ChangeType changeType, | 595 void DatabaseWrapper::LogChange(ChangeType changeType, |
581 Json::Value changes = Json::arrayValue; | 614 Json::Value changes = Json::arrayValue; |
582 int64_t last = since; | 615 int64_t last = since; |
583 | 616 |
584 while (changes.size() < maxResults && s.Step()) | 617 while (changes.size() < maxResults && s.Step()) |
585 { | 618 { |
586 int64_t seq = s.ColumnInt(0); | 619 int64_t seq = s.ColumnInt64(0); |
587 ChangeType changeType = static_cast<ChangeType>(s.ColumnInt(1)); | 620 ChangeType changeType = static_cast<ChangeType>(s.ColumnInt(1)); |
588 int64_t internalId = s.ColumnInt(2); | 621 int64_t internalId = s.ColumnInt64(2); |
589 ResourceType resourceType = static_cast<ResourceType>(s.ColumnInt(3)); | 622 ResourceType resourceType = static_cast<ResourceType>(s.ColumnInt(3)); |
590 const std::string& date = s.ColumnString(4); | 623 const std::string& date = s.ColumnString(4); |
591 std::string publicId = GetPublicId(internalId); | 624 std::string publicId = GetPublicId(internalId); |
592 | 625 |
593 Json::Value item = Json::objectValue; | 626 Json::Value item = Json::objectValue; |
649 | 682 |
650 s.Run(); | 683 s.Run(); |
651 } | 684 } |
652 | 685 |
653 | 686 |
654 void DatabaseWrapper::GetExportedResources(Json::Value& target, | 687 void DatabaseWrapper::GetExportedResourcesInternal(Json::Value& target, |
655 SQLite::Statement& s, | 688 SQLite::Statement& s, |
656 int64_t since, | 689 int64_t since, |
657 unsigned int maxResults) | 690 unsigned int maxResults) |
658 { | 691 { |
659 Json::Value changes = Json::arrayValue; | 692 Json::Value changes = Json::arrayValue; |
660 int64_t last = since; | 693 int64_t last = since; |
661 | 694 |
662 while (changes.size() < maxResults && s.Step()) | 695 while (changes.size() < maxResults && s.Step()) |
663 { | 696 { |
664 int64_t seq = s.ColumnInt(0); | 697 int64_t seq = s.ColumnInt64(0); |
665 ResourceType resourceType = static_cast<ResourceType>(s.ColumnInt(1)); | 698 ResourceType resourceType = static_cast<ResourceType>(s.ColumnInt(1)); |
666 std::string publicId = s.ColumnString(2); | 699 std::string publicId = s.ColumnString(2); |
667 | 700 |
668 Json::Value item = Json::objectValue; | 701 Json::Value item = Json::objectValue; |
669 item["Seq"] = static_cast<int>(seq); | 702 item["Seq"] = static_cast<int>(seq); |
711 { | 744 { |
712 SQLite::Statement s(db_, SQLITE_FROM_HERE, | 745 SQLite::Statement s(db_, SQLITE_FROM_HERE, |
713 "SELECT * FROM ExportedResources WHERE seq>? ORDER BY seq LIMIT ?"); | 746 "SELECT * FROM ExportedResources WHERE seq>? ORDER BY seq LIMIT ?"); |
714 s.BindInt64(0, since); | 747 s.BindInt64(0, since); |
715 s.BindInt(1, maxResults + 1); | 748 s.BindInt(1, maxResults + 1); |
716 GetExportedResources(target, s, since, maxResults); | 749 GetExportedResourcesInternal(target, s, since, maxResults); |
717 } | 750 } |
718 | 751 |
719 | 752 |
720 void DatabaseWrapper::GetLastExportedResource(Json::Value& target) | 753 void DatabaseWrapper::GetLastExportedResource(Json::Value& target) |
721 { | 754 { |
722 SQLite::Statement s(db_, SQLITE_FROM_HERE, | 755 SQLite::Statement s(db_, SQLITE_FROM_HERE, |
723 "SELECT * FROM ExportedResources ORDER BY seq DESC LIMIT 1"); | 756 "SELECT * FROM ExportedResources ORDER BY seq DESC LIMIT 1"); |
724 GetExportedResources(target, s, 0, 1); | 757 GetExportedResourcesInternal(target, s, 0, 1); |
725 } | 758 } |
726 | 759 |
727 | 760 |
728 | 761 |
729 | 762 |
805 std::string query; | 838 std::string query; |
806 EmbeddedResources::GetFileResource(query, EmbeddedResources::PREPARE_DATABASE); | 839 EmbeddedResources::GetFileResource(query, EmbeddedResources::PREPARE_DATABASE); |
807 db_.Execute(query); | 840 db_.Execute(query); |
808 } | 841 } |
809 | 842 |
810 // Sanity check of the version of the database | 843 // Check the version of the database |
811 std::string version = GetGlobalProperty(GlobalProperty_DatabaseSchemaVersion, "Unknown"); | 844 std::string version = GetGlobalProperty(GlobalProperty_DatabaseSchemaVersion, "Unknown"); |
812 bool ok = false; | 845 bool ok = false; |
813 try | 846 try |
814 { | 847 { |
815 LOG(INFO) << "Version of the Orthanc database: " << version; | 848 LOG(INFO) << "Version of the Orthanc database: " << version; |
816 unsigned int v = boost::lexical_cast<unsigned int>(version); | 849 unsigned int v = boost::lexical_cast<unsigned int>(version); |
817 | 850 |
818 // This version of Orthanc is only compatible with version 3 of | 851 /** |
819 // the DB schema (since Orthanc 0.3.2) | 852 * History of the database versions: |
820 ok = (v == 3); | 853 * - Version 3: from Orthanc 0.3.2 to Orthanc 0.7.2 (inclusive) |
854 * - Version 4: from Orthanc 0.7.3 (inclusive) | |
855 **/ | |
856 | |
857 // This version of Orthanc is only compatible with versions 3 of 4 of the DB schema | |
858 ok = (v == 3 || v == 4); | |
859 | |
860 if (v == 3) | |
861 { | |
862 LOG(WARNING) << "Upgrading database version from 3 to 4"; | |
863 std::string upgrade; | |
864 EmbeddedResources::GetFileResource(upgrade, EmbeddedResources::UPGRADE_DATABASE_3_TO_4); | |
865 db_.BeginTransaction(); | |
866 db_.Execute(upgrade); | |
867 db_.CommitTransaction(); | |
868 } | |
821 } | 869 } |
822 catch (boost::bad_lexical_cast&) | 870 catch (boost::bad_lexical_cast&) |
823 { | 871 { |
824 } | 872 } |
825 | 873 |
826 if (!ok) | 874 if (!ok) |
827 { | 875 { |
876 LOG(ERROR) << "Incompatible version of the Orthanc database: " << version; | |
828 throw OrthancException(ErrorCode_IncompatibleDatabaseVersion); | 877 throw OrthancException(ErrorCode_IncompatibleDatabaseVersion); |
829 } | 878 } |
830 | 879 |
831 signalRemainingAncestor_ = new Internals::SignalRemainingAncestor; | 880 signalRemainingAncestor_ = new Internals::SignalRemainingAncestor; |
832 db_.Register(signalRemainingAncestor_); | 881 db_.Register(signalRemainingAncestor_); |