Mercurial > hg > orthanc
changeset 440:23e5b35e3c5c
statistics for patient/studies/series/instances
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 15 May 2013 17:44:15 +0200 |
parents | 081a44d5110b |
children | 9d876ea52df4 40deb6525337 |
files | NEWS OrthancServer/DatabaseWrapper.cpp OrthancServer/DatabaseWrapper.h OrthancServer/OrthancRestApi.cpp OrthancServer/ServerIndex.cpp OrthancServer/ServerIndex.h |
diffstat | 6 files changed, 142 insertions(+), 6 deletions(-) [+] |
line wrap: on
line diff
--- a/NEWS Wed May 15 17:10:52 2013 +0200 +++ b/NEWS Wed May 15 17:44:15 2013 +0200 @@ -13,6 +13,7 @@ Other ----- +* Statistics about patients, studies, series and instances * Fixes for Red Hat and Debian packaging * Fixes for boost::thread, as reported by Cyril Paulus
--- a/OrthancServer/DatabaseWrapper.cpp Wed May 15 17:10:52 2013 +0200 +++ b/OrthancServer/DatabaseWrapper.cpp Wed May 15 17:44:15 2013 +0200 @@ -438,6 +438,21 @@ s.Run(); } + void DatabaseWrapper::ListAvailableAttachments(std::list<FileContentType>& result, + int64_t id) + { + result.clear(); + + SQLite::Statement s(db_, SQLITE_FROM_HERE, + "SELECT fileType FROM AttachedFiles WHERE id=?"); + s.BindInt(0, id); + + while (s.Step()) + { + result.push_back(static_cast<FileContentType>(s.ColumnInt(0))); + } + } + bool DatabaseWrapper::LookupAttachment(FileInfo& attachment, int64_t id, FileContentType contentType)
--- a/OrthancServer/DatabaseWrapper.h Wed May 15 17:10:52 2013 +0200 +++ b/OrthancServer/DatabaseWrapper.h Wed May 15 17:44:15 2013 +0200 @@ -129,6 +129,9 @@ void AddAttachment(int64_t id, const FileInfo& attachment); + void ListAvailableAttachments(std::list<FileContentType>& result, + int64_t id); + bool LookupAttachment(FileInfo& attachment, int64_t id, FileContentType contentType);
--- a/OrthancServer/OrthancRestApi.cpp Wed May 15 17:10:52 2013 +0200 +++ b/OrthancServer/OrthancRestApi.cpp Wed May 15 17:44:15 2013 +0200 @@ -1573,6 +1573,16 @@ } + static void GetResourceStatistics(RestApi::GetCall& call) + { + RETRIEVE_CONTEXT(call); + std::string publicId = call.GetUriComponent("id", ""); + Json::Value result; + context.GetIndex().GetStatistics(result, publicId); + call.GetOutput().AnswerJson(result); + } + + // Registration of the various REST handlers -------------------------------- @@ -1608,6 +1618,11 @@ Register("/studies/{id}/archive", GetArchive<ResourceType_Study>); Register("/series/{id}/archive", GetArchive<ResourceType_Series>); + Register("/instances/{id}/statistics", GetResourceStatistics); + Register("/patients/{id}/statistics", GetResourceStatistics); + Register("/studies/{id}/statistics", GetResourceStatistics); + Register("/series/{id}/statistics", GetResourceStatistics); + Register("/instances/{id}/metadata", ListMetadata); Register("/instances/{id}/metadata/{name}", DeleteMetadata); Register("/instances/{id}/metadata/{name}", GetMetadata);
--- a/OrthancServer/ServerIndex.cpp Wed May 15 17:10:52 2013 +0200 +++ b/OrthancServer/ServerIndex.cpp Wed May 15 17:44:15 2013 +0200 @@ -48,6 +48,8 @@ #include <stdio.h> #include <glog/logging.h> +static const uint64_t MEGA_BYTES = 1024 * 1024; + namespace Orthanc { namespace Internals @@ -515,18 +517,16 @@ void ServerIndex::ComputeStatistics(Json::Value& target) { - static const uint64_t MB = 1024 * 1024; - boost::mutex::scoped_lock lock(mutex_); target = Json::objectValue; uint64_t cs = currentStorageSize_; assert(cs == db_->GetTotalCompressedSize()); uint64_t us = db_->GetTotalUncompressedSize(); - target["TotalDiskSpace"] = boost::lexical_cast<std::string>(cs); + target["TotalDiskSize"] = boost::lexical_cast<std::string>(cs); target["TotalUncompressedSize"] = boost::lexical_cast<std::string>(us); - target["TotalDiskSpaceMB"] = boost::lexical_cast<unsigned int>(cs / MB); - target["TotalUncompressedSizeMB"] = boost::lexical_cast<unsigned int>(us / MB); + target["TotalDiskSizeMB"] = boost::lexical_cast<unsigned int>(cs / MEGA_BYTES); + target["TotalUncompressedSizeMB"] = boost::lexical_cast<unsigned int>(us / MEGA_BYTES); target["CountPatients"] = static_cast<unsigned int>(db_->GetResourceCount(ResourceType_Patient)); target["CountStudies"] = static_cast<unsigned int>(db_->GetResourceCount(ResourceType_Study)); @@ -1001,7 +1001,7 @@ } else { - LOG(WARNING) << "At most " << (size / (1024 * 1024)) << "MB will be used for the storage area"; + LOG(WARNING) << "At most " << (size / MEGA_BYTES) << "MB will be used for the storage area"; } StandaloneRecycling(); @@ -1244,4 +1244,103 @@ boost::mutex::scoped_lock lock(mutex_); db_->ClearTable("ExportedResources"); } + + + 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); + } + + 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; + + while (!toExplore.empty()) + { + // Get the internal ID of the current resource + int64_t resource = toExplore.top(); + toExplore.pop(); + + ResourceType thisType = db_->GetResourceType(resource); + + 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 + { + switch (thisType) + { + case ResourceType_Study: + countStudies++; + break; + + case ResourceType_Series: + countSeries++; + break; + + default: + break; + } + + // Tag all the children of this resource as to be explored + std::list<int64_t> tmp; + db_->GetChildrenInternalId(tmp, resource); + for (std::list<int64_t>::const_iterator + it = tmp.begin(); it != tmp.end(); it++) + { + toExplore.push(*it); + } + } + } + + target = Json::objectValue; + target["DiskSize"] = boost::lexical_cast<std::string>(compressedSize); + target["DiskSizeMB"] = boost::lexical_cast<unsigned int>(compressedSize / MEGA_BYTES); + target["UncompressedSize"] = boost::lexical_cast<std::string>(uncompressedSize); + target["UncompressedSizeMB"] = boost::lexical_cast<unsigned int>(uncompressedSize / MEGA_BYTES); + + switch (type) + { + // Do NOT add "break" below this point! + case ResourceType_Patient: + target["CountStudies"] = countStudies; + + case ResourceType_Study: + target["CountSeries"] = countSeries; + + case ResourceType_Series: + target["CountInstances"] = countInstances; + + case ResourceType_Instance: + default: + break; + } + } }