# HG changeset patch # User Sebastien Jodogne # Date 1368632655 -7200 # Node ID 23e5b35e3c5ca0ad68168fb7a24d080b6978e77d # Parent 081a44d5110b7d71865cdbf28b4f7bc8e191a6f1 statistics for patient/studies/series/instances diff -r 081a44d5110b -r 23e5b35e3c5c NEWS --- 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 diff -r 081a44d5110b -r 23e5b35e3c5c OrthancServer/DatabaseWrapper.cpp --- 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& 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(s.ColumnInt(0))); + } + } + bool DatabaseWrapper::LookupAttachment(FileInfo& attachment, int64_t id, FileContentType contentType) diff -r 081a44d5110b -r 23e5b35e3c5c OrthancServer/DatabaseWrapper.h --- 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& result, + int64_t id); + bool LookupAttachment(FileInfo& attachment, int64_t id, FileContentType contentType); diff -r 081a44d5110b -r 23e5b35e3c5c OrthancServer/OrthancRestApi.cpp --- 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); Register("/series/{id}/archive", GetArchive); + 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); diff -r 081a44d5110b -r 23e5b35e3c5c OrthancServer/ServerIndex.cpp --- 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 #include +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(cs); + target["TotalDiskSize"] = boost::lexical_cast(cs); target["TotalUncompressedSize"] = boost::lexical_cast(us); - target["TotalDiskSpaceMB"] = boost::lexical_cast(cs / MB); - target["TotalUncompressedSizeMB"] = boost::lexical_cast(us / MB); + target["TotalDiskSizeMB"] = boost::lexical_cast(cs / MEGA_BYTES); + target["TotalUncompressedSizeMB"] = boost::lexical_cast(us / MEGA_BYTES); target["CountPatients"] = static_cast(db_->GetResourceCount(ResourceType_Patient)); target["CountStudies"] = static_cast(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 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 f; + db_->ListAvailableAttachments(f, resource); + + for (std::list::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 tmp; + db_->GetChildrenInternalId(tmp, resource); + for (std::list::const_iterator + it = tmp.begin(); it != tmp.end(); it++) + { + toExplore.push(*it); + } + } + } + + target = Json::objectValue; + target["DiskSize"] = boost::lexical_cast(compressedSize); + target["DiskSizeMB"] = boost::lexical_cast(compressedSize / MEGA_BYTES); + target["UncompressedSize"] = boost::lexical_cast(uncompressedSize); + target["UncompressedSizeMB"] = boost::lexical_cast(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; + } + } } diff -r 081a44d5110b -r 23e5b35e3c5c OrthancServer/ServerIndex.h --- a/OrthancServer/ServerIndex.h Wed May 15 17:10:52 2013 +0200 +++ b/OrthancServer/ServerIndex.h Wed May 15 17:44:15 2013 +0200 @@ -171,5 +171,8 @@ void DeleteChanges(); void DeleteExportedResources(); + + void GetStatistics(Json::Value& target, + const std::string& publicId); }; }