Mercurial > hg > orthanc
diff OrthancServer/ServerIndex.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 | ec69658b031b |
children | 67e6400fca03 401a9633e492 |
line wrap: on
line diff
--- a/OrthancServer/ServerIndex.cpp Thu Oct 17 14:21:50 2013 +0200 +++ b/OrthancServer/ServerIndex.cpp Wed Apr 16 16:04:55 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -91,7 +91,7 @@ { for (std::list<std::string>::iterator it = pendingFilesToRemove_.begin(); - it != pendingFilesToRemove_.end(); it++) + it != pendingFilesToRemove_.end(); ++it) { context_.RemoveFile(*it); } @@ -255,6 +255,7 @@ try { + boost::mutex::scoped_lock lock(that->mutex_); std::string sleepString = that->db_->GetGlobalProperty(GlobalProperty_FlushSleep); sleep = boost::lexical_cast<unsigned int>(sleepString); } @@ -290,11 +291,11 @@ int64_t series, const DicomMap& dicomSummary) { - const DicomValue* value; - const DicomValue* value2; - try { + const DicomValue* value; + const DicomValue* value2; + if ((value = dicomSummary.TestAndGetValue(DICOM_TAG_IMAGES_IN_ACQUISITION)) != NULL && (value2 = dicomSummary.TestAndGetValue(DICOM_TAG_NUMBER_OF_TEMPORAL_POSITIONS)) != NULL) { @@ -407,7 +408,7 @@ // Ensure there is enough room in the storage for the new instance uint64_t instanceSize = 0; for (Attachments::const_iterator it = attachments.begin(); - it != attachments.end(); it++) + it != attachments.end(); ++it) { instanceSize += it->GetCompressedSize(); } @@ -512,7 +513,7 @@ // Attach the files to the newly created instance for (Attachments::const_iterator it = attachments.begin(); - it != attachments.end(); it++) + it != attachments.end(); ++it) { db_->AddAttachment(instance, *it); } @@ -593,10 +594,6 @@ try { expected = boost::lexical_cast<size_t>(s); - if (expected < 0) - { - return SeriesStatus_Unknown; - } } catch (boost::bad_lexical_cast&) { @@ -609,7 +606,7 @@ std::set<size_t> instances; for (std::list<int64_t>::const_iterator - it = children.begin(); it != children.end(); it++) + it = children.begin(); it != children.end(); ++it) { // Get the index of this instance in the series s = db_->GetMetadata(*it, MetadataType_Instance_IndexInSeries); @@ -623,7 +620,7 @@ return SeriesStatus_Unknown; } - if (index <= 0 || index > expected) + if (!(index > 0 && index <= expected)) { // Out-of-range instance index return SeriesStatus_Inconsistent; @@ -715,7 +712,7 @@ Json::Value c = Json::arrayValue; for (std::list<std::string>::const_iterator - it = children.begin(); it != children.end(); it++) + it = children.begin(); it != children.end(); ++it) { c.append(*it); } @@ -823,8 +820,7 @@ int64_t id; ResourceType type; - if (!db_->LookupResource(instanceUuid, id, type) || - type != ResourceType_Instance) + if (!db_->LookupResource(instanceUuid, id, type)) { throw OrthancException(ErrorCode_InternalError); } @@ -1112,6 +1108,37 @@ } + void ServerIndex::GetChildren(std::list<std::string>& result, + const std::string& publicId) + { + result.clear(); + + boost::mutex::scoped_lock lock(mutex_); + + ResourceType type; + int64_t resource; + if (!db_->LookupResource(publicId, resource, type)) + { + throw OrthancException(ErrorCode_UnknownResource); + } + + if (type == ResourceType_Instance) + { + // An instance cannot have a child + throw OrthancException(ErrorCode_BadParameterType); + } + + std::list<int64_t> tmp; + db_->GetChildrenInternalId(tmp, resource); + + for (std::list<int64_t>::const_iterator + it = tmp.begin(); it != tmp.end(); ++it) + { + result.push_back(db_->GetPublicId(*it)); + } + } + + void ServerIndex::GetChildInstances(std::list<std::string>& result, const std::string& publicId) { @@ -1153,7 +1180,7 @@ // Tag all the children of this resource as to be explored db_->GetChildrenInternalId(tmp, resource); for (std::list<int64_t>::const_iterator - it = tmp.begin(); it != tmp.end(); it++) + it = tmp.begin(); it != tmp.end(); ++it) { toExplore.push(*it); } @@ -1212,7 +1239,7 @@ } - bool ServerIndex::ListAvailableMetadata(std::list<MetadataType>& target, + void ServerIndex::ListAvailableMetadata(std::list<MetadataType>& target, const std::string& publicId) { boost::mutex::scoped_lock lock(mutex_); @@ -1224,7 +1251,25 @@ throw OrthancException(ErrorCode_UnknownResource); } - return db_->ListAvailableMetadata(target, id); + db_->ListAvailableMetadata(target, id); + } + + + void ServerIndex::ListAvailableAttachments(std::list<FileContentType>& target, + const std::string& publicId, + ResourceType expectedType) + { + boost::mutex::scoped_lock lock(mutex_); + + ResourceType type; + int64_t id; + if (!db_->LookupResource(publicId, id, type) || + expectedType != type) + { + throw OrthancException(ErrorCode_UnknownResource); + } + + db_->ListAvailableAttachments(target, id); } @@ -1301,26 +1346,22 @@ } - void ServerIndex::GetStatistics(Json::Value& target, - const std::string& publicId) + void ServerIndex::GetStatisticsInternal(/* out */ uint64_t& compressedSize, + /* out */ uint64_t& uncompressedSize, + /* out */ unsigned int& countStudies, + /* out */ unsigned int& countSeries, + /* out */ unsigned int& countInstances, + /* in */ int64_t id, + /* in */ ResourceType type) { - boost::mutex::scoped_lock lock(mutex_); + std::stack<int64_t> toExplore; + toExplore.push(id); - ResourceType type; - int64_t top; - if (!db_->LookupResource(publicId, top, type)) - { - throw OrthancException(ErrorCode_UnknownResource); - } - - std::stack<int64_t> toExplore; - toExplore.push(top); - - int countInstances = 0; - int countSeries = 0; - int countStudies = 0; - uint64_t compressedSize = 0; - uint64_t uncompressedSize = 0; + countInstances = 0; + countSeries = 0; + countStudies = 0; + compressedSize = 0; + uncompressedSize = 0; while (!toExplore.empty()) { @@ -1330,22 +1371,22 @@ ResourceType thisType = db_->GetResourceType(resource); + std::list<FileContentType> f; + db_->ListAvailableAttachments(f, resource); + + for (std::list<FileContentType>::const_iterator + it = f.begin(); it != f.end(); ++it) + { + FileInfo attachment; + if (db_->LookupAttachment(attachment, resource, *it)) + { + compressedSize += attachment.GetCompressedSize(); + uncompressedSize += attachment.GetUncompressedSize(); + } + } + if (thisType == ResourceType_Instance) { - std::list<FileContentType> f; - db_->ListAvailableAttachments(f, resource); - - for (std::list<FileContentType>::const_iterator - it = f.begin(); it != f.end(); it++) - { - FileInfo attachment; - if (db_->LookupAttachment(attachment, resource, *it)) - { - compressedSize += attachment.GetCompressedSize(); - uncompressedSize += attachment.GetUncompressedSize(); - } - } - countInstances++; } else @@ -1368,13 +1409,46 @@ std::list<int64_t> tmp; db_->GetChildrenInternalId(tmp, resource); for (std::list<int64_t>::const_iterator - it = tmp.begin(); it != tmp.end(); it++) + it = tmp.begin(); it != tmp.end(); ++it) { toExplore.push(*it); } } } + if (countStudies == 0) + { + countStudies = 1; + } + + if (countSeries == 0) + { + countSeries = 1; + } + } + + + + void ServerIndex::GetStatistics(Json::Value& target, + const std::string& publicId) + { + boost::mutex::scoped_lock lock(mutex_); + + ResourceType type; + int64_t top; + if (!db_->LookupResource(publicId, top, type)) + { + throw OrthancException(ErrorCode_UnknownResource); + } + + uint64_t uncompressedSize; + uint64_t compressedSize; + unsigned int countStudies; + unsigned int countSeries; + unsigned int countInstances; + GetStatisticsInternal(compressedSize, uncompressedSize, countStudies, + countSeries, countInstances, top, type); + target = Json::objectValue; target["DiskSize"] = boost::lexical_cast<std::string>(compressedSize); target["DiskSizeMB"] = boost::lexical_cast<unsigned int>(compressedSize / MEGA_BYTES); @@ -1400,6 +1474,27 @@ } + void ServerIndex::GetStatistics(/* out */ uint64_t& compressedSize, + /* out */ uint64_t& uncompressedSize, + /* out */ unsigned int& countStudies, + /* out */ unsigned int& countSeries, + /* out */ unsigned int& countInstances, + const std::string& publicId) + { + boost::mutex::scoped_lock lock(mutex_); + + ResourceType type; + int64_t top; + if (!db_->LookupResource(publicId, top, type)) + { + throw OrthancException(ErrorCode_UnknownResource); + } + + GetStatisticsInternal(compressedSize, uncompressedSize, countStudies, + countSeries, countInstances, top, type); + } + + void ServerIndex::UnstableResourcesMonitorThread(ServerIndex* that) { int stableAge = GetGlobalIntegerParameter("StableAge", 60); @@ -1473,6 +1568,29 @@ void ServerIndex::LookupTagValue(std::list<std::string>& result, DicomTag tag, + const std::string& value, + ResourceType type) + { + result.clear(); + + boost::mutex::scoped_lock lock(mutex_); + + std::list<int64_t> id; + db_->LookupTagValue(id, tag, value); + + for (std::list<int64_t>::const_iterator + it = id.begin(); it != id.end(); ++it) + { + if (db_->GetResourceType(*it) == type) + { + result.push_back(db_->GetPublicId(*it)); + } + } + } + + + void ServerIndex::LookupTagValue(std::list<std::string>& result, + DicomTag tag, const std::string& value) { result.clear(); @@ -1483,7 +1601,7 @@ db_->LookupTagValue(id, tag, value); for (std::list<int64_t>::const_iterator - it = id.begin(); it != id.end(); it++) + it = id.begin(); it != id.end(); ++it) { result.push_back(db_->GetPublicId(*it)); } @@ -1501,9 +1619,78 @@ db_->LookupTagValue(id, value); for (std::list<int64_t>::const_iterator - it = id.begin(); it != id.end(); it++) + it = id.begin(); it != id.end(); ++it) { result.push_back(db_->GetPublicId(*it)); } } + + + StoreStatus ServerIndex::AddAttachment(const FileInfo& attachment, + const std::string& publicId) + { + boost::mutex::scoped_lock lock(mutex_); + + Transaction t(*this); + + ResourceType resourceType; + int64_t resourceId; + if (!db_->LookupResource(publicId, resourceId, resourceType)) + { + return StoreStatus_Failure; // Inexistent resource + } + + // Remove possible previous attachment + db_->DeleteAttachment(resourceId, attachment.GetContentType()); + + // Locate the patient of the target resource + int64_t patientId = resourceId; + for (;;) + { + int64_t parent; + if (db_->LookupParent(parent, patientId)) + { + // We have not reached the patient level yet + patientId = parent; + } + else + { + // We have reached the patient level + break; + } + } + + // Possibly apply the recycling mechanism while preserving this patient + assert(db_->GetResourceType(patientId) == ResourceType_Patient); + Recycle(attachment.GetCompressedSize(), db_->GetPublicId(patientId)); + + db_->AddAttachment(resourceId, attachment); + + t.Commit(attachment.GetCompressedSize()); + + return StoreStatus_Success; + } + + + void ServerIndex::DeleteAttachment(const std::string& publicId, + FileContentType type) + { + boost::mutex::scoped_lock lock(mutex_); + listener_->Reset(); + + Transaction t(*this); + + ResourceType rtype; + int64_t id; + if (!db_->LookupResource(publicId, id, rtype)) + { + throw OrthancException(ErrorCode_UnknownResource); + } + + db_->DeleteAttachment(id, type); + + t.Commit(0); + } + + }