diff --git a/test/source/scwx/provider/aws_level2_data_provider.test.cpp b/test/source/scwx/provider/aws_level2_data_provider.test.cpp index b7caee82..54299585 100644 --- a/test/source/scwx/provider/aws_level2_data_provider.test.cpp +++ b/test/source/scwx/provider/aws_level2_data_provider.test.cpp @@ -7,6 +7,32 @@ namespace scwx namespace provider { +TEST(AwsLevel2DataProvider, FindKeyFixed) +{ + using namespace std::chrono; + using sys_days = time_point; + + const auto date = sys_days {2021y / May / 27d}; + const auto time = date + 17h + 59min; + + AwsLevel2DataProvider provider("KLSX"); + + provider.ListObjects(date); + std::string key = provider.FindKey(time); + + EXPECT_EQ(key, "2021/05/27/KLSX/KLSX20210527_175717_V06"); +} + +TEST(AwsLevel2DataProvider, FindKeyNow) +{ + AwsLevel2DataProvider provider("KLSX"); + + provider.Refresh(); + std::string key = provider.FindKey(std::chrono::system_clock::now()); + + EXPECT_GT(key.size(), 0); +} + TEST(AwsLevel2DataProvider, LoadObjectByKey) { const std::string key = "2022/04/21/KLSX/KLSX20220421_160055_V06"; diff --git a/wxdata/include/scwx/provider/aws_level2_data_provider.hpp b/wxdata/include/scwx/provider/aws_level2_data_provider.hpp index 5ea5411f..4ade762b 100644 --- a/wxdata/include/scwx/provider/aws_level2_data_provider.hpp +++ b/wxdata/include/scwx/provider/aws_level2_data_provider.hpp @@ -30,7 +30,8 @@ public: size_t cache_size() const; - size_t ListObjects(std::chrono::system_clock::time_point date); + std::string FindKey(std::chrono::system_clock::time_point time); + size_t ListObjects(std::chrono::system_clock::time_point date); std::shared_ptr LoadObjectByKey(const std::string& key); void Refresh(); diff --git a/wxdata/include/scwx/util/map.hpp b/wxdata/include/scwx/util/map.hpp new file mode 100644 index 00000000..12ee96b5 --- /dev/null +++ b/wxdata/include/scwx/util/map.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include +#include + +namespace scwx +{ +namespace util +{ + +template +std::optional GetBoundedElement(std::map& map, Key key) +{ + std::optional element = std::nullopt; + + // Find the first element greater than the key requested + auto it = map.upper_bound(key); + + // An element with a key greater was found + if (it != map.cend()) + { + // Are there elements prior to this element? + if (it != map.cbegin()) + { + // Get the element immediately preceding, this the element we are + // looking for + element = (--it)->second; + } + } + else if (map.size() > 0) + { + // An element with a key greater was not found. If it exists, it must be + // the last element. + element = map.rbegin()->second; + } + + return element; +} + +} // namespace util +} // namespace scwx diff --git a/wxdata/source/scwx/provider/aws_level2_data_provider.cpp b/wxdata/source/scwx/provider/aws_level2_data_provider.cpp index c2f000c4..b7afbf35 100644 --- a/wxdata/source/scwx/provider/aws_level2_data_provider.cpp +++ b/wxdata/source/scwx/provider/aws_level2_data_provider.cpp @@ -1,5 +1,7 @@ #include #include +#include +#include #include #include @@ -76,6 +78,24 @@ size_t AwsLevel2DataProvider::cache_size() const return p->objects_.size(); } +std::string +AwsLevel2DataProvider::FindKey(std::chrono::system_clock::time_point time) +{ + logger_->debug("FindKey: {}", util::TimeString(time)); + + std::string key {}; + + std::optional element = + util::GetBoundedElement(p->objects_, time); + + if (element.has_value()) + { + key = *element; + } + + return key; +} + size_t AwsLevel2DataProvider::ListObjects(std::chrono::system_clock::time_point date) { diff --git a/wxdata/wxdata.cmake b/wxdata/wxdata.cmake index 7e5feb04..ae139823 100644 --- a/wxdata/wxdata.cmake +++ b/wxdata/wxdata.cmake @@ -39,6 +39,7 @@ set(SRC_PROVIDER source/scwx/provider/aws_level2_data_provider.cpp) set(HDR_UTIL include/scwx/util/float.hpp include/scwx/util/iterator.hpp include/scwx/util/logger.hpp + include/scwx/util/map.hpp include/scwx/util/rangebuf.hpp include/scwx/util/streams.hpp include/scwx/util/threads.hpp