From d2eb5f4e914093d0947b79c0aa06b6691640a0e2 Mon Sep 17 00:00:00 2001 From: Emanuele Danovaro Date: Sat, 7 Mar 2026 20:10:12 +0000 Subject: [PATCH 1/3] FDB-649 schema - optional with defaults - improved behaviour (not injecting the default in the index) --- src/fdb5/CMakeLists.txt | 2 +- src/fdb5/api/FDB.cc | 18 +- src/fdb5/database/IndexAxis.cc | 16 +- src/fdb5/rules/MatchOptional.cc | 4 +- src/fdb5/rules/Rule.cc | 72 +- src/fdb5/tools/compare/fdb-compare.cc | 1 - src/fdb5/tools/compare/grib/CompareBitwise.cc | 1 - tests/fdb/CMakeLists.txt | 1 + tests/fdb/api/test_auxiliary.cc | 6 +- tests/fdb/api/test_callback.cc | 2 +- tests/fdb/api/test_dist.cc | 2 +- tests/fdb/api/test_fdb_c.cc | 9 +- tests/fdb/api/test_select.cc | 23 +- tests/fdb/daos/test_daos_catalogue.cc | 6 +- tests/fdb/etc/fdb/schema | 546 ++++++++--- tests/fdb/test_service.cc | 69 +- tests/fdb/timespan/CMakeLists.txt | 7 + tests/fdb/timespan/in.grib | Bin 0 -> 10872 bytes tests/fdb/timespan/local1.yaml | 7 + tests/fdb/timespan/local2.yaml | 7 + tests/fdb/timespan/local3.yaml | 7 + tests/fdb/timespan/req | 12 + tests/fdb/timespan/schema1 | 113 +++ tests/fdb/timespan/schema2 | 896 ++++++++++++++++++ tests/fdb/timespan/schema3 | 113 +++ tests/fdb/timespan/timespan.sh.in | 286 ++++++ tests/fdb/tools/fdb_axes.sh.in | 6 +- 27 files changed, 2015 insertions(+), 217 deletions(-) create mode 100644 tests/fdb/timespan/CMakeLists.txt create mode 100644 tests/fdb/timespan/in.grib create mode 100644 tests/fdb/timespan/local1.yaml create mode 100644 tests/fdb/timespan/local2.yaml create mode 100644 tests/fdb/timespan/local3.yaml create mode 100644 tests/fdb/timespan/req create mode 100755 tests/fdb/timespan/schema1 create mode 100755 tests/fdb/timespan/schema2 create mode 100755 tests/fdb/timespan/schema3 create mode 100755 tests/fdb/timespan/timespan.sh.in diff --git a/src/fdb5/CMakeLists.txt b/src/fdb5/CMakeLists.txt index 64d1f4491..04ca62734 100644 --- a/src/fdb5/CMakeLists.txt +++ b/src/fdb5/CMakeLists.txt @@ -475,7 +475,7 @@ list( APPEND fdb5_tools if ( HAVE_GRIB ) list( APPEND fdb5_tools fdb-hammer - fdb-patch + # fdb-patch ) endif() diff --git a/src/fdb5/api/FDB.cc b/src/fdb5/api/FDB.cc index 55e1f8e77..a3f777856 100644 --- a/src/fdb5/api/FDB.cc +++ b/src/fdb5/api/FDB.cc @@ -30,6 +30,10 @@ #include "eckit/message/Message.h" #include "eckit/message/Reader.h" +#include "metkit/hypercube/HyperCube.h" +#include "metkit/mars/MarsLanguage.h" +#include "metkit/mars/MarsRequest.h" + #include "fdb5/LibFdb5.h" #include "fdb5/api/FDBFactory.h" #include "fdb5/api/helpers/FDBToolRequest.h" @@ -237,7 +241,19 @@ eckit::DataHandle* FDB::retrieve(const metkit::mars::MarsRequest& request) { } ListIterator FDB::inspect(const metkit::mars::MarsRequest& request) { - return internal_->inspect(request); + + ASSERT(!request.empty()); + + metkit::mars::MarsRequest indexingRequest{request.verb()}; + metkit::mars::MarsLanguage language{request.verb()}; + // Only copy data parameters, as these are the only ones relevant for the indexing + for (const auto& p : request.parameters()) { + if (!language.isPostProc(p.name()) && !language.isSink(p.name())) { + indexingRequest.setValuesTyped(&p.type(), p.values()); + } + } + + return internal_->inspect(indexingRequest); } ListIterator FDB::list(const FDBToolRequest& request, const ListMode mode, const int level) { diff --git a/src/fdb5/database/IndexAxis.cc b/src/fdb5/database/IndexAxis.cc index 9e089b290..67939d4fb 100644 --- a/src/fdb5/database/IndexAxis.cc +++ b/src/fdb5/database/IndexAxis.cc @@ -399,10 +399,13 @@ void IndexAxis::print(std::ostream& out) const { const char* sep = ""; out << "{"; - for (const auto& kv : axis_) { - out << sep << kv.first << "=("; + for (const auto& [k, vv] : axis_) { + if (vv->size() == 1 && vv->at(0).empty()) { + continue; + } + out << sep << k << "=("; const char* sep2 = ""; - for (const auto& v : *kv.second) { + for (const auto& v : *vv) { out << sep2 << v; sep2 = ","; } @@ -415,8 +418,11 @@ void IndexAxis::print(std::ostream& out) const { void IndexAxis::json(eckit::JSON& json) const { json.startObject(); - for (const auto& kv : axis_) { - json << kv.first << *kv.second; + for (const auto& [k, vv] : axis_) { + if (vv->size() == 1 && vv->at(0).empty()) { + continue; + } + json << k << *vv; } json.endObject(); } diff --git a/src/fdb5/rules/MatchOptional.cc b/src/fdb5/rules/MatchOptional.cc index f9a7385fd..ced0c1eb5 100644 --- a/src/fdb5/rules/MatchOptional.cc +++ b/src/fdb5/rules/MatchOptional.cc @@ -71,11 +71,13 @@ void MatchOptional::fill(Key& key, const std::string& keyword, const std::string const std::string& MatchOptional::value(const Key& key, const std::string& keyword) const { + static std::string empty{}; + if (const auto [iter, found] = key.find(keyword); found) { return iter->second; } - return default_[0]; + return empty; } const std::vector& MatchOptional::values(const metkit::mars::MarsRequest& rq, diff --git a/src/fdb5/rules/Rule.cc b/src/fdb5/rules/Rule.cc index 68f4f9521..f32133294 100644 --- a/src/fdb5/rules/Rule.cc +++ b/src/fdb5/rules/Rule.cc @@ -208,7 +208,13 @@ std::optional Rule::findMatchingKey(const eckit::StringList& values) const return {}; } - ASSERT(values.size() >= predicates_.size()); + size_t numPred = predicates_.size(); + for (const auto& p : predicates_) { + if (p->optional()) { + numPred--; + } + } + ASSERT(values.size() >= numPred); TypedKey key(registry_); @@ -282,7 +288,6 @@ std::vector Rule::findMatchingKeys(const metkit::mars::MarsRequest& request } } - /// @todo activate this graph.canonicalise(registry_); return graph.makeKeys(); @@ -295,13 +300,12 @@ std::vector Rule::findMatchingKeys(const metkit::mars::MarsRequest& request for (const auto& pred : predicates_) { const auto& keyword = pred->keyword(); - const auto& type = registry_.lookupType(keyword); - - - const auto& values = pred->values(request); + auto values = pred->values(request); - /// @note do we want to allow empty values? - // if (values.empty() && pred->optional()) { values.push_back(pred->defaultValue()); } + /// if the request does not have the keyword, but the predicate is optional, then use the default value + if (values.empty() && pred->optional()) { + values.push_back(pred->defaultValue()); + } auto& node = graph.push(keyword); @@ -311,6 +315,7 @@ std::vector Rule::findMatchingKeys(const metkit::mars::MarsRequest& request } } + /// if there are no matching values for this predicate, then there are no matching keys for the rule if (node.empty()) { return {}; } @@ -328,22 +333,25 @@ std::vector Rule::findMatchingKeys(const metkit::mars::MarsRequest& request for (const auto& pred : predicates_) { const auto& keyword = pred->keyword(); - const auto& type = registry_.lookupType(keyword); // performance optimization to avoid calling values() on visitor - if (!pred->optional() && request.countValues(keyword) == 0) { - return {}; - } - eckit::StringList values; - visitor.values(request, keyword, registry_, values); - - if (values.empty() && pred->optional()) { - values.push_back(pred->defaultValue()); + if (request.countValues(keyword) == 0) { + if (pred->optional()) { + values.push_back(pred->defaultValue()); + if (!pred->defaultValue().empty()) { + values.push_back(""); + } + } + else { + return {}; + } + } + else { + visitor.values(request, keyword, registry_, values); } auto& node = graph.push(keyword); - for (const auto& value : values) { if (pred->match(value)) { node.emplace_back(value); @@ -351,23 +359,17 @@ std::vector Rule::findMatchingKeys(const metkit::mars::MarsRequest& request } if (node.empty()) { - return {}; + if (pred->optional()) { + node.emplace_back(""); + } + else { + return {}; + } } } graph.canonicalise(registry_); - - auto out = graph.makeKeys(); - - LOG_DEBUG_LIB(LibFdb5) << "findMatchingKeys " << request << " ==> "; - std::string sep; - for (const auto& k : out) { - LOG_DEBUG_LIB(LibFdb5) << sep << k; - sep = " | "; - } - LOG_DEBUG_LIB(LibFdb5) << std::endl; - - return out; + return graph.makeKeys(); } //---------------------------------------------------------------------------------------------------------------------- @@ -399,7 +401,13 @@ bool Rule::tryFill(Key& key, const eckit::StringList& values) const { // --> HACK. // --> Stick a plaster over the symptom. - ASSERT(values.size() >= predicates_.size()); // Should be equal, except for quantile (FDB-103) + size_t numPred = predicates_.size(); + for (const auto& p : predicates_) { + if (p->optional()) { + numPred--; + } + } + ASSERT(values.size() >= numPred); // Should be equal, except for quantile (FDB-103) ASSERT(values.size() <= predicates_.size() + 1); auto it_value = values.begin(); diff --git a/src/fdb5/tools/compare/fdb-compare.cc b/src/fdb5/tools/compare/fdb-compare.cc index 43dd65867..62fdb29a0 100644 --- a/src/fdb5/tools/compare/fdb-compare.cc +++ b/src/fdb5/tools/compare/fdb-compare.cc @@ -62,7 +62,6 @@ class FDBCompare : public eckit::Tool { std::optional config2_; std::optional req1String_; std::optional req2String_; - bool singleFDB_ = false; }; //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/fdb5/tools/compare/grib/CompareBitwise.cc b/src/fdb5/tools/compare/grib/CompareBitwise.cc index a1c4dcf9b..c91b9a354 100644 --- a/src/fdb5/tools/compare/grib/CompareBitwise.cc +++ b/src/fdb5/tools/compare/grib/CompareBitwise.cc @@ -190,7 +190,6 @@ CompareResult bitComparison(const uint8_t* buffer1, const uint8_t* buffer2, size // Process sections based on edition for (int i = 0; i < numSections; ++i) { - // std::cout<<"offset " << offset< setup(FDB& fdb, std::set auxExtensions = {"foo", "bar"}, const std::vector& dates = {"20101010", "20111213"}, - const std::vector& types = {"fc", "pf"}, + const std::vector& types = {"fc", "an"}, const std::vector& steps = {"1", "2"} ) { @@ -126,7 +126,7 @@ CASE("Wipe with extensions") { EXPECT_EQUAL(element_counts[WipeElementType::STORE_AUX], 8); // over specified wipe: returns nothing - request = FDBToolRequest::requestsFromString("class=od,expver=xxxx,type=pf,step=1")[0]; + request = FDBToolRequest::requestsFromString("class=od,expver=xxxx,type=an,step=1")[0]; doit = true; iter = fdb.wipe(request, doit); element_counts.clear(); @@ -140,7 +140,7 @@ CASE("Wipe with extensions") { // partial wipe on the second level. Hits half the data files - request = FDBToolRequest::requestsFromString("class=od,expver=xxxx,type=pf")[0]; + request = FDBToolRequest::requestsFromString("class=od,expver=xxxx,type=an")[0]; doit = true; iter = fdb.wipe(request, doit); element_counts.clear(); diff --git a/tests/fdb/api/test_callback.cc b/tests/fdb/api/test_callback.cc index afbed70c4..be375f9f0 100644 --- a/tests/fdb/api/test_callback.cc +++ b/tests/fdb/api/test_callback.cc @@ -48,7 +48,7 @@ CASE("Archive and flush callback") { keys.push_back(key); fdb.archive(key, data, length); - key.set("type", "pf"); + key.set("type", "an"); keys.push_back(key); fdb.archive(key, data, length); diff --git a/tests/fdb/api/test_dist.cc b/tests/fdb/api/test_dist.cc index 102ac8989..89312c860 100644 --- a/tests/fdb/api/test_dist.cc +++ b/tests/fdb/api/test_dist.cc @@ -142,7 +142,7 @@ CASE("retrieves_distributed_according_to_dist") { // Do some archiving - metkit::mars::MarsRequest req; + metkit::mars::MarsRequest req{"retrieve"}; req.setValuesTyped(new metkit::mars::TypeAny("class"), std::vector{"od"}); req.setValuesTyped(new metkit::mars::TypeAny("expver"), std::vector{"xxxx"}); fdb.inspect(req); diff --git a/tests/fdb/api/test_fdb_c.cc b/tests/fdb/api/test_fdb_c.cc index ba4a43443..62d0f1979 100644 --- a/tests/fdb/api/test_fdb_c.cc +++ b/tests/fdb/api/test_fdb_c.cc @@ -35,7 +35,7 @@ int fdb_request_add1(fdb_request_t* req, const char* param, const char* value) { void key_compare(const std::vector& keys, fdb_listiterator_t* it, bool checkLevel = true) { const char* k; - const char* v; + const char* v = nullptr; size_t l; int err; @@ -47,7 +47,12 @@ void key_compare(const std::vector& keys, fdb_listiterator_t* it, boo size_t level = 0; for (const auto& key : keys) { for (const auto& k1 : key) { - int err = fdb_splitkey_next_metadata(sk, &k, &v, checkLevel ? &l : nullptr); + int err; + v = nullptr; + // skip empty values (optional metadata) + while (v == nullptr || strlen(v) == 0) { + err = fdb_splitkey_next_metadata(sk, &k, &v, checkLevel ? &l : nullptr); + } std::cerr << "k=" << k << " v=" << v << " l=" << l << std::endl; EXPECT(err == FDB_SUCCESS); EXPECT(k1.first == k); diff --git a/tests/fdb/api/test_select.cc b/tests/fdb/api/test_select.cc index 9d02de31e..d5e37ecc7 100644 --- a/tests/fdb/api/test_select.cc +++ b/tests/fdb/api/test_select.cc @@ -17,10 +17,13 @@ #include "eckit/testing/Test.h" -#include "fdb5/api/helpers/WipeIterator.h" +#include "metkit/mars/MarsLanguage.h" +#include "metkit/mars/MarsParser.h" +#include "metkit/mars/MarsRequest.h" #include "metkit/mars/TypeAny.h" #include "fdb5/api/helpers/FDBToolRequest.h" +#include "fdb5/api/helpers/WipeIterator.h" #include "fdb5/config/Config.h" #include "ApiSpy.h" @@ -153,8 +156,20 @@ CASE("retrieves_distributed_according_to_select") { // Build FDB from default config fdb5::FDB fdb(defaultConfig()); - fdb.list(metkit::mars::MarsRequest{"class=od"}); - fdb.list(metkit::mars::MarsRequest{"class=rd"}); + { + std::istringstream in("retrieve,class=od"); + metkit::mars::MarsParser parser(in); + auto reqs = parser.parse(); + ASSERT(reqs.size() == 1); + fdb.list(reqs[0]); + } + { + std::istringstream in("retrieve,class=rd"); + metkit::mars::MarsParser parser(in); + auto reqs = parser.parse(); + ASSERT(reqs.size() == 1); + fdb.list(reqs[0]); + } EXPECT(ApiSpy::knownSpies().size() == 3); ApiSpy& spy_od(*ApiSpy::knownSpies()[0]); @@ -163,7 +178,7 @@ CASE("retrieves_distributed_according_to_select") { // Do some archiving - metkit::mars::MarsRequest req; + metkit::mars::MarsRequest req{"retrieve"}; req.setValuesTyped(new metkit::mars::TypeAny("class"), std::vector{"od"}); req.setValuesTyped(new metkit::mars::TypeAny("expver"), std::vector{"xxxx"}); fdb.inspect(req); diff --git a/tests/fdb/daos/test_daos_catalogue.cc b/tests/fdb/daos/test_daos_catalogue.cc index 12b752744..cc4f58bfe 100644 --- a/tests/fdb/daos/test_daos_catalogue.cc +++ b/tests/fdb/daos/test_daos_catalogue.cc @@ -527,9 +527,9 @@ CASE("DaosCatalogue tests") { fdb5::Key db_key({{"a", "11"}, {"b", "22"}}); fdb5::Key index_key({{"a", "11"}, {"b", "22"}, {"c", "3"}, {"d", "4"}}); - fdb5::FDBToolRequest full_req{request_key.request("retrieve"), false, std::vector{"a", "b"}}; - fdb5::FDBToolRequest index_req{index_key.request("retrieve"), false, std::vector{"a", "b"}}; - fdb5::FDBToolRequest db_req{db_key.request("retrieve"), false, std::vector{"a", "b"}}; + fdb5::FDBToolRequest full_req{request_key.request(), false, std::vector{"a", "b"}}; + fdb5::FDBToolRequest index_req{index_key.request(), false, std::vector{"a", "b"}}; + fdb5::FDBToolRequest db_req{db_key.request(), false, std::vector{"a", "b"}}; fdb5::FDBToolRequest all_req{metkit::mars::MarsRequest{}, true, std::vector{}}; // initialise FDB diff --git a/tests/fdb/etc/fdb/schema b/tests/fdb/etc/fdb/schema index bceac97f4..e2e6af20f 100755 --- a/tests/fdb/etc/fdb/schema +++ b/tests/fdb/etc/fdb/schema @@ -19,7 +19,7 @@ # This will be used when matching rules. # * Attributes can be typed -# Globally, at the beginning of this file: +# Globally, at the begining of this file: # refdate: Date; @@ -30,7 +30,7 @@ # * Attributes can be optional # [ step, levelist?, param ] -# They will be replaced internally by an empty value. It is also possible to provide a default substitution value: e.g. [domain?g] will consider the domain to be 'g' if missing. +# They will be replaced internally by an empty value. It is also posiible to provide a default subtitution value: e.g. [domain?g] will consider the domain to be 'g' if missing. # * Attributes can be removed: # [grid-] @@ -61,6 +61,7 @@ step: Step; date: Date; hdate: Date; refdate: Date; +offsetdate: Date; latitude: Double; longitude: Double; levelist: Double; @@ -68,12 +69,15 @@ grid: Grid; expver: Expver; time: Time; +offsettime: Time; fcmonth: Integer; number: Integer; frequency: Integer; direction: Integer; channel: Integer; +chem: Integer; +coeffindex: Integer; instrument: Integer; ident: Integer; @@ -100,6 +104,7 @@ method: Integer; ######################################################## # These rules must be first, otherwise fields of These # classes will be index with the default rule for oper + [ class=ti/s2, expver, stream, date, time, model [ origin, type, levtype, hdate? [ step, number?, levelist?, param ]] @@ -112,8 +117,7 @@ method: Integer; [ class=ms, expver, stream, date, time, country=it [ domain, type, levtype, model, bcmodel, icmodel:First3 - [ step, levelist?, param ] - ] + [ step, levelist?, param ]] ] [ class=el, expver, stream, date, time, domain @@ -121,51 +125,317 @@ method: Integer; [ step, levelist?, param ]] ] +######################################################## +# These are the rules for class Cerise (mmsf/mmsa/msmm) +[ class=ci, expver, stream=mmsf, date, time, domain + [ type, levtype, origin, system? + [ step, number, levelist?, param ]] +] + +[ class=ci, expver, stream=mmsa/msmm, date, time, domain + [ type, levtype, origin, system? + [ fcmonth, number?, levelist?, param ]] +] + +######################################################## +# These are the rules for class=ai +[ class=ai, expver, stream, model?, date, time, domain + [ type, levtype, timespan?none + [ step, quantile?, number?, levelist?, param ]] +] + +######################################################## +# These are the rules for the Extremes DT +# oper/wave +[ class=d1, dataset=extremes-dt, expver, stream=oper/wave, date, time + [ type, levtype, timespan?none + [ step, levelist?, param, frequency?, direction? ]] +] +# enfo/waef +[ class=d1, dataset=extremes-dt, expver, stream=enfo/waef, date, time + [ type, levtype, timespan?none + [ step, number?, levelist?, param, frequency?, direction? ]] +] +# lwda/lwwv +[ class=d1, dataset=extremes-dt, expver, stream=lwda/lwwv, date, time + [ type, levtype, anoffset, timespan?none + [ step, levelist?, param, frequency?, direction? ]] +] + +######################################################## +# These are the rules for the On-Demand Extremes DT +# oper +[ class=d1, dataset=on-demand-extremes-dt, expver, stream=oper, date, time + [ type=ssd, georef, timespan?none + [ step, param, ident, instrument, channel ]] + [ type, levtype, georef, timespan?none + [ step, levelist?, param ]] +] + +# enfo +[ class=d1, dataset=on-demand-extremes-dt, expver, stream=enfo, date, time + [ type, levtype, georef, timespan?none + [ step, number?, levelist?, param ]] +] + +######################################################## +# These are the rules for class=e6 ERA6 + +# stream elda +[ class=e6, expver, stream=elda, date, domain?g + [ type=an, levtype=al/sfc, anoffset, timespan?none + [ number, time, step?0, levelist-, param, frequency?, direction?, wavelength?]] + [ type=an, levtype=ml/pl/sol/hl/pv/pt, anoffset, timespan?none + [ number, time, step?0, levelist, param, frequency?, direction?, wavelength?]] + [ type=eme, levtype, anoffset, timespan?none + [ number, time, step?0, levelist?, param, frequency?, direction?, wavelength?]] + [ type=fc, levtype=al/sfc/o2d, anoffset, timespan?none + [ number, time, step, levelist-, param, frequency?, direction?, wavelength?]] + [ type=fc, levtype=ml/pl/sol/hl/pv/pt/o3d, anoffset, timespan?none + [ number, time, step, levelist, param, frequency?, direction?, wavelength?]] + [ type=4i, levtype, anoffset, timespan?none + [ number?, time, step, iteration, levelist, param ]] + [ type=4v, levtype, anoffset, timespan?none + [ number, time, step, levelist?, param, frequency?, direction?, wavelength? ]] + [ type=est, levtype, anoffset, timespan?none + [ number?, time, step, levelist?, param, frequency?, direction?, wavelength? ]] + [ type=es/em, levtype, anoffset, timespan?none + [ number?, time, step, levelist?, param, channel?, wavelength? ]] + [ type=ses, levtype, anoffset, timespan?none + [ number?, time, step, levelist?, param, channel? ]] +] + +# stream lwda +[ class=e6, expver, stream=lwda, date, domain?g + [ type=an, levtype, anoffset, timespan?none + [ time, step?0, levelist?, param, frequency?, direction?, wavelength?]] + [ type=me, levtype, anoffset, timespan?none + [ number?, time, step?0, levelist?, param, frequency?, direction?, wavelength?]] + [ type=fc, levtype, anoffset, timespan?none + [ time, step, levelist?, param, frequency?, direction?, wavelength?]] + [ type=4i, levtype, anoffset, timespan?none + [ time, step, iteration, levelist, param ]] + [ type=4v, levtype, anoffset, timespan?none + [ time, step, levelist?, param, frequency?, direction?, wavelength? ]] +] + +# stream enda +[ class=e6, expver, stream=enda, date, domain?g + [ type, levtype, timespan?none + [ number, time, step?0, levelist?, param, channel?, frequency?, direction?, wavelength?]] +] + +# stream oper +[ class=e6, expver, stream=oper, date, domain?g + [ type=me, levtype, timespan?none + [ number?, time, step?0, levelist?, param, frequency?, direction?, wavelength?]] + [ type, levtype, timespan?none + [ time, step, levelist?, param, frequency?, direction?, wavelength?]] +] + +######################################################## +# Monthly and daily statistics for ERA6 + +[ class=e6, expver, stream=sttd, date, domain?g + [ stattype=moav/momn/momx/mosd/daac/daav/damn/damx/dasd/moav_daav/moav_damn/moav_damx/moav_dasd/momn_daav/momn_damn/momn_damx/momn_dasd/momx_daav/momx_damn/momx_damx/momx_dasd/mosd_daav/mosd_damn/mosd_damx/mosd_dasd, type, levtype, timespan?none + [ levelist?, param, frequency?, direction?, wavelength?]] +] + +[ class=e6, expver, stream=stte, date, domain?g + [ stattype=moav/momn/momx/mosd/daac/daav/damn/damx/dasd/moav_daav/moav_damn/moav_damx/moav_dasd/momn_daav/momn_damn/momn_damx/momn_dasd/momx_daav/momx_damn/momx_damx/momx_dasd/mosd_daav/mosd_damn/mosd_damx/mosd_dasd, type=em/es, levtype, timespan?none + [ levelist?, param, frequency?, direction?, wavelength?]] + [ stattype=moav/momn/momx/mosd/daac/daav/damn/damx/dasd/moav_daav/moav_damn/moav_damx/moav_dasd/momn_daav/momn_damn/momn_damx/momn_dasd/momx_daav/momx_damn/momx_damx/momx_dasd/mosd_daav/mosd_damn/mosd_damx/mosd_dasd, type, levtype, timespan?none + [ number, levelist?, param, frequency?, direction?, wavelength?]] +] + +######################################################## +######################################################## +## These are the rules for CAMS - classes cr/a5 +# stream oper +[ class=cr, expver, stream=oper, date, domain? + [ type=an, levtype, timespan?none + [ time, step?0, levelist?, param, chem, frequency?, direction?, wavelength?]] + [ type=me, levtype, timespan?none + [ number?, time, step?0, levelist?, param, chem?, frequency?, direction?, wavelength?]] + [ type=fc, levtype, timespan?none + [ time, step, levelist?, param, chem?, frequency?, direction?, wavelength?]] + [ type=4i, levtype, timespan?none + [ time, step, iteration, levelist, param, chem? ]] + [ type=4v, levtype, timespan?none + [ time, step, levelist?, param, chem?, frequency?, direction?, wavelength?]] +] + +[ class=cr, expver, stream=lwda, date, domain? + [ type=an, levtype, anoffset, timespan?none + [ time, step?0, levelist?, param, chem?, frequency?, direction?, wavelength?]] + [ type=me, levtype, anoffset, timespan?none + [ number, time, step?0, levelist?, param, chem?, frequency?, direction?, wavelength?]] + [ type=fc, levtype, anoffset, timespan?none + [ time, step, levelist?, param, chem?, frequency?, direction?, wavelength?]] + [ type=4i, levtype, anoffset, timespan?none + [ time, step, iteration, levelist, param, chem? ]] + [ type=4v, levtype, anoffset, timespan?none + [ time, step, levelist?, param, chem?, frequency?, direction?, wavelength?]] +] + +[ class=a5, expver, stream=oper, date, domain? + [ type=an, levtype, timespan?none + [ time, step?0, levelist?, param, chem?, frequency?, direction?, wavelength?]] + [ type=me, levtype, timespan?none + [ number?, time, step?0, levelist?, param, chem?, frequency?, direction?, wavelength?]] + [ type=fc, levtype, timespan?none + [ time, step, levelist?, param, chem?, frequency?, direction?, wavelength?]] + [ type=4i, levtype, timespan?none + [ time, step, iteration, levelist, param, chem? ]] + [ type=4v, levtype, timespan?none + [ time, step, levelist?, param, chem?, frequency?, direction?, wavelength?]] +] + +[ class=a5, expver, stream=lwda, date, domain? + [ type=an, levtype, anoffset, timespan?none + [ time, step?0, levelist?, param, chem?, frequency?, direction?, wavelength?]] + [ type=me, levtype, anoffset, timespan?none + [ number, time, step?0, levelist?, param, chem?, frequency?, direction?, wavelength?]] + [ type=fc, levtype, anoffset, timespan?none + [ time, step, levelist?, param, chem?, frequency?, direction?, wavelength?]] + [ type=4i, levtype, anoffset, timespan?none + [ time, step, iteration, levelist, param, chem? ]] + [ type=4v, levtype, anoffset, timespan?none + [ time, step, levelist?, param, chem?, frequency?, direction?, wavelength?]] +] + +######################################################## +# Monthly and daily statistics for EAC5 and CAMS research + +[ class=a5, expver, stream=sttd, date, domain? + [ stattype=moav/momn/momx/mosd/daac/daav/damn/damx/dasd/moav_daav/moav_damn/moav_damx/moav_dasd/momn_daav/momn_damn/momn_damx/momn_dasd/momx_daav/momx_damn/momx_damx/momx_dasd/mosd_daav/mosd_damn/mosd_damx/mosd_dasd, type, levtype, timespan?none + [ levelist?, param, chem?, frequency?, direction?, wavelength?]] +] + +[ class=a5, expver, stream=stte, date, domain? + [ stattype=moav/momn/momx/mosd/daac/daav/damn/damx/dasd/moav_daav/moav_damn/moav_damx/moav_dasd/momn_daav/momn_damn/momn_damx/momn_dasd/momx_daav/momx_damn/momx_damx/momx_dasd/mosd_daav/mosd_damn/mosd_damx/mosd_dasd, type, levtype, timespan?none + [ number, levelist?, param, chem?, frequency?, direction?, wavelength?]] +] + +[ class=cr, expver, stream=sttd, date, domain? + [ stattype=moav/momn/momx/mosd/daac/daav/damn/damx/dasd/moav_daav/moav_damn/moav_damx/moav_dasd/momn_daav/momn_damn/momn_damx/momn_dasd/momx_daav/momx_damn/momx_damx/momx_dasd/mosd_daav/mosd_damn/mosd_damx/mosd_dasd, type, levtype, timespan?none + [ levelist?, param, chem?, frequency?, direction?, wavelength?]] +] + +[ class=cr, expver, stream=stte, date, domain? + [ stattype=moav/momn/momx/mosd/daac/daav/damn/damx/dasd/moav_daav/moav_damn/moav_damx/moav_dasd/momn_daav/momn_damn/momn_damx/momn_dasd/momx_daav/momx_damn/momx_damx/momx_dasd/mosd_daav/mosd_damn/mosd_damx/mosd_dasd, type, levtype, timespan?none + [ number, levelist?, param, chem?, frequency?, direction?, wavelength?]] +] + +######################################################## +# rules for class RD +# rd/lwda +[ class, expver, stream=lwda, date, time, domain?g + [ type=an, levtype=pl/ml/sol/layer/o3d/pv/pt, anoffset, timespan?none + [ step?0, levelist, param ]] + [ type=an, levtype=o2d/al, anoffset, timespan?none + [ step?0, param ]] + [ type=an, levtype=sfc, anoffset, timespan?none + [ step?0, param, frequency?, direction? ]] + [ type=fc, levtype=pl/ml/sol/layer/o3d/pv/pt, anoffset, timespan?none + [ step, levelist, param ]] + [ type=fc, levtype=o2d/al, anoffset, timespan?none + [ step, param ]] + [ type=fc, levtype=sfc, anoffset, timespan?none + [ step, param, frequency?, direction? ]] + [ type=me, levtype=ml, anoffset, timespan?none + [ step?, number-, levelist, param, coeffindex? ]] + [ type=4i, levtype=ml, anoffset, timespan?none + [ step, iteration, levelist, param ]] + [ type=4v, levtype=pl/ml/sol/layer/o3d/pv/pt, anoffset, timespan?none + [ step, levelist, param ]] + [ type=4v, levtype=o2d/al, anoffset, timespan?none + [ step, param ]] + [ type=4v, levtype=sfc, anoffset, timespan?none + [ step, param, frequency?, direction? ]] + [ type=ssd, anoffset, timespan?none + [ step, param, ident, instrument, channel ]] + [ type=gai + [ param ]] + [ type=ai/ob/ofb/mfb/tf/oai + [ obsgroup, reportype ]] +] + +# MTG2 OD +[ class=od, expver=2249/2250, stream=oper, date, domain? + [ type=me, levtype, timespan?none + [ number?, time, step?0, levelist?, param, frequency?, direction?, wavelength?]] + [ type, levtype, timespan?none + [ time, step, levelist?, param, frequency?, direction?, wavelength?]] +] + +[ class, expver, stream=oper, date, time, domain?g + [ type=an, levtype=pl/ml/sol/layer/o3d/pt/pv, timespan?none + [ step?0, levelist, param ]] + [ type=an, levtype=o2d/al, timespan?none + [ step?0, param ]] + [ type=an, levtype=sfc, timespan?none + [ step?0, param, frequency?, direction? ]] + [ type=fc, levtype=ml/pl/sol/layer/o3d/pt/pv, timespan?none + [ step, levelist, param ]] + [ type=fc, levtype=o2d/al, timespan?none + [ step, param ]] + [ type=fc, levtype=sfc, timespan?none + [ step, param, frequency?, direction? ]] + [ type=me, levtype=ml, timespan?none + [ step?, number-, levelist, param, coeffindex? ]] + [ type=4i, levtype=ml, tmespan? + [ step, iteration, levelist, param ]] + [ type=4v, levtype=ml/pl/sol/layer/o3d/pv/pt, timespan?none + [ step, levelist, param ]] + [ type=4v, levtype=o2d/al, timespan?none + [ step, param ]] + [ type=4v, levtype=sfc, timespan?none + [ step, param, frequency?, direction? ]] + [ type=ssd, timespan?none + [ step, param, ident, instrument, channel ]] + [ type=gai + [ param ]] + [ type=ai/ob/ofb/mfb/tf/oai + [ obsgroup, reportype ]] +] + ######################################################## # The are the rules matching most of the fields # oper/dcda -[ class, expver, stream=oper/dcda/scda, date, time, domain? - +[ class, expver, stream=dcda/scda, date, time, domain?g [ type=im/sim [ step?, ident, instrument, channel ]] - [ type=ssd [ step, param, ident, instrument, channel ]] - [ type=4i, levtype [ step, iteration, levelist, param ]] - [ type=me, levtype [ step, number, levelist?, param ]] - [ type=ef, levtype [ step, levelist?, param, channel? ]] - [ type=ofb/mfb [ obsgroup, reportype ]] - + [ type=pf/em/es/efi, levtype + [ step, number?, levelist?, param ]] [ type, levtype [ step, levelist?, param ]] - ] # dcwv/scwv/wave [ class, expver, stream=dcwv/scwv/wave, date, time, domain [ type, levtype - [ step, param, frequency?, direction? ]]] + [ step, param, frequency?, direction? ]] +] # enfo [ class, expver, stream=enfo/efov/eefo, date, time, domain - [ type, levtype=dp, product?, section? - [ step, number?, levelist?, latitude?, longitude?, range?, param ]] - + [ step, number?, levelist?, latitude?, longitude?, range?, param ]] [ type=tu, levtype, reference [ step, number, levelist?, param ]] - [ type, levtype [ step, quantile?, number?, levelist?, param ]] - ] # waef/weov @@ -177,14 +447,10 @@ method: Integer; ######################################################## # enda [ class, expver, stream=enda, date, time, domain - [ type=ef/em/es/ses, levtype [ step, number?, levelist?, param, channel? ]] - [ type=ssd [ step, number, param, ident, instrument, channel ]] - - [ type, levtype [ step, number?, levelist?, param ]] ] @@ -198,42 +464,35 @@ method: Integer; ######################################################## # elda -[ class, expver, stream=elda, date, time, domain? - +[ class, expver, stream=elda, date, time, domain?g [ type=ofb/mfb [ obsgroup, reportype ]] - [ type, levtype, anoffset - [ step, number?, levelist?, iteration?, param, channel? ]] + [ step, number?, levelist?, iteration?, param, channel?, coeffindex? ]] ] -# ewda +# ewla [ class, expver, stream=ewla, date, time, domain [ type, levtype, anoffset [ step, number?, param, frequency?, direction? ]] ] ######################################################## -# elda -[ class, expver, stream=lwda, date, time, domain? - - [ type=ssd, anoffset - [ step, param, ident, instrument, channel ]] - - [type=me, levtype, anoffset - [ number, step, levelist?, param]] - - [ type=4i, levtype, anoffset - [ step, iteration, levelist, param ]] - - [ type=ofb/mfb - [ obsgroup, reportype ]] - - [ type, levtype, anoffset, timespan? - [ step, levelist?, param]] -] - -# ewda +# lwda +#[ class, expver, stream=lwda, date, time, domain?g +# [ type=ssd, anoffset +# [ step, param, ident, instrument, channel ]] +# [ type=me, levtype, anoffset +# [ number, step, levelist?, param]] +# [ type=4i, levtype, anoffset +# [ step, iteration, levelist, param ]] +# [ type=ofb/mfb/oai +# [ obsgroup, reportype ]] +# [ type, levtype, anoffset +# [ step, levelist?, param]] +#] + +# lwwv [ class, expver, stream=lwwv, date, time, domain [ type, levtype, anoffset [ step, param, frequency?, direction? ]] @@ -242,69 +501,78 @@ method: Integer; # amap [ class, expver, stream=amap, date, time, domain [ type, levtype, origin - [ step, levelist?, param ]]] + [ step, levelist?, param ]] +] # maed [ class, expver, stream=maed, date, time, domain [ type, levtype, origin - [ step, levelist?, param ]]] + [ step, levelist?, param ]] +] # mawv [ class, expver, stream=mawv, date, time, domain [ type, levtype, origin - [ step, param, frequency?, direction? ]]] + [ step, param, frequency?, direction? ]] +] # cher [ class, expver, stream=cher, date, time, domain [ type, levtype - [ step, levelist, param ]]] + [ step, levelist, param ]] +] # efhc [ class, expver, stream=efhc, refdate, time, domain [ type, levtype, date - [ step, number?, levelist?, param ]]] + [ step, number?, levelist?, param ]] +] # efho [ class, expver, stream=efho, date, time, domain [ type, levtype, hdate - [ step, number?, levelist?, param ]]] + [ step, number?, levelist?, param ]] +] # efhs [ class, expver, stream=efhs/eehs, date, time, domain [ type, levtype - [ step, quantile?, number?, levelist?, param ]]] + [ step, quantile?, number?, levelist?, param ]] +] # wehs [ class, expver, stream=wehs/wees, date, time, domain [ type, levtype - [ step, quantile?, number?, levelist?, param ]]] + [ step, quantile?, number?, levelist?, param ]] +] # kwbc [ class, expver, stream=kwbc, date, time, domain [ type, levtype - [ step, number?, levelist?, param ]]] + [ step, number?, levelist?, param ]] +] # ehmm [ class, expver, stream=ehmm, date, time, domain [ type, levtype, hdate - [ fcmonth, levelist?, param ]]] + [ fcmonth, levelist?, param ]] +] # ammc/cwao/edzw/egrr/lfpw/rjtd/toga [ class, expver, stream=ammc/cwao/edzw/egrr/lfpw/rjtd/toga/fgge, date, time, domain [ type, levtype - [ step, levelist?, param ]]] + [ step, levelist?, param ]] +] ######################################################################## # enfh [ class, expver, stream=enfh/eefh, date, time, domain - [ type, levtype=dp, hdate, product?, section? - [ step, number?, levelist?, latitude?, longitude?, range?, param ]] - + [ step, number?, levelist?, latitude?, longitude?, range?, param ]] [ type, levtype, hdate [ step, number?, levelist?, param ]] ] @@ -319,68 +587,73 @@ method: Integer; # sens [ class, expver, stream=sens, date, time, domain [ type, levtype - [ step, diagnostic, iteration, levelist?, param ]]] + [ step, diagnostic, iteration, levelist?, param ]] +] ######################################################################## # esmm [ class, expver, stream=esmm, date, time, domain [ type, levtype - [ fcmonth, levelist?, param ]]] + [ fcmonth, levelist?, param ]] +] + # ewhc [ class, expver, stream=ewhc, refdate, time, domain [ type, levtype, date - [ step, number?, param, frequency?, direction? ]]] + [ step, number?, param, frequency?, direction? ]] +] ######################################################################## # ewho [ class, expver, stream=ewho, date, time, domain [ type, levtype, hdate - [ step, number?, param, frequency?, direction? ]]] + [ step, number?, param, frequency?, direction? ]] +] # mfam [ class, expver, stream=mfam, date, time, domain - [ type=pb/pd, levtype, origin, system?, method [ fcperiod, quantile, levelist?, param ]] - [ type, levtype, origin, system?, method [ fcperiod, number?, levelist?, param ]] - ] # mfhm [ class, expver, stream=mfhm, refdate, time, domain [ type, levtype, origin, system?, method, date? - [ fcperiod, number?, levelist?, param ]]] + [ fcperiod, number?, levelist?, param ]] +] + # mfhw [ class, expver, stream=mfhw, refdate, time, domain [ type, levtype, origin, system?, method, date - [ step, number?, param ]]] + [ step, number?, param ]] +] + # mfwm [ class, expver, stream=mfwm, date, time, domain [ type, levtype, origin, system?, method - [ fcperiod, number, param ]]] + [ fcperiod, number, param ]] +] + # mhwm [ class, expver, stream=mhwm, refdate, time, domain [ type, levtype, origin, system?, method, date - [ fcperiod, number, param ]]] + [ fcperiod, number, param ]] +] # mmsf -[ class, expver, stream=mmsf, date, time, domain - +[ class=od/rd/te/c3/uk/nl/fr/es/ch/de/pt/be/gr/ie/tr/no/fi/se/it, expver, stream=mmsf, date, time, domain [ type, levtype=dp, origin, product, section, system?, method - [ step, number, levelist?, latitude?, longitude?, range?, param ]] - + [ step, number, levelist?, latitude?, longitude?, range?, param ]] [ type, levtype, origin, system?, method [ step, number, levelist?, param ]] ] # mnfc [ class, expver, stream=mnfc, date, time, domain - [ type, levtype=dp, origin, product, section, system?, method - [ step, number?, levelist?, latitude?, longitude?, range?, param ]] - + [ step, number?, levelist?, latitude?, longitude?, range?, param ]] [ type, levtype, origin, system?, method [ step, number?, levelist?, param ]] ] @@ -396,24 +669,28 @@ method: Integer; # mnfm [ class, expver, stream=mnfm, date, time, domain [ type, levtype, origin, system?, method - [ fcperiod, number?, levelist?, param ]]] + [ fcperiod, number?, levelist?, param ]] +] # mnfw [ class, expver, stream=mnfw, date, time, domain [ type, levtype, origin, system?, method - [ step, number?, param ]]] + [ step, number?, param ]] +] # ea/mnth [ class=ea, expver, stream=mnth, date, domain [ type, levtype - [ time, step?, levelist?, param ]]] + [ time, step?, levelist?, param ]] +] # mnth [ class, expver, stream=mnth, domain [ type=cl, levtype [ date: ClimateMonthly, time, levelist?, param ]] [ type, levtype - [ date , time, step?, levelist?, param ]]] + [ date , time, step?, levelist?, param ]] +] # mofc [ class, expver, stream=mofc, date, time, domain @@ -426,16 +703,19 @@ method: Integer; # mofm [ class, expver, stream=mofm, date, time, domain [ type, levtype, system?, method - [ fcperiod, number, levelist?, param ]]] + [ fcperiod, number, levelist?, param ]] +] # mmsa/msmm -[ class, expver, stream=mmsa, date, time, domain +[ class=od/rd/te/c3/uk/nl/fr/es/ch/de/pt/be/gr/ie/tr/no/fi/se/it, expver, stream=mmsa, date, time, domain [ type, levtype, origin, system?, method - [ fcmonth, number?, levelist?, param ]]] + [ fcmonth, number?, levelist?, param ]] +] -[ class, expver, stream=msmm, date, time, domain +[ class=od/rd/te/c3/uk/nl/fr/es/ch/de/pt/be/gr/ie/tr/no/fi/se/it, expver, stream=msmm, date, time, domain [ type, levtype, origin, system?, method - [ fcmonth, number?, levelist?, param ]]] + [ fcmonth, number?, levelist?, param ]] +] # ocea [ class, expver, stream=ocea, date, time, domain @@ -443,12 +723,30 @@ method: Integer; [ step, number, levelist?, latitude?, longitude?, range?, param ]] ] -#=# seas -[ class, expver, stream=seas, date, time, domain +# olda +[ class, expver, stream=olda, date, time, domain + [ type=tpa, levtype=o3d + [ number?, offsetdate, offsettime, step, levelist, param ]] + [ type=tpa, levtype=o2d + [ number?, offsetdate, offsettime, step, param ]] + [ type=an, levtype=o3d + [ number?, offsetdate, offsettime, levelist, param ]] + [ type=an, levtype=o2d + [ number?, offsetdate, offsettime, param ]] +] + +# ocda +[ class, expver, stream=ocda, date, domain + [ type=tpa, levtype=o2d/o3d, number? + [ time, step?,levelist?, param ]] + [ type=mfb + [ time, obsgroup, reportype ]] +] +# seas +[ class, expver, stream=seas, date, time, domain [ type, levtype=dp, product, section, system?, method [ step, number, levelist?, latitude?, longitude?, range?, param ]] - [ type, levtype, system?, method [ step, number, levelist?, param ]] ] @@ -456,96 +754,102 @@ method: Integer; # sfmm/smma [ class, expver, stream=sfmm/smma, date, time, domain [ type, levtype, system?, method - [ fcmonth, number?, levelist?, param ]]] + [ fcmonth, number?, levelist?, param ]] +] # supd [ class=od, expver, stream=supd, date, time, domain [ type, levtype, origin?, grid - [ step, levelist?, param ]]] + [ step, levelist?, param ]] +] # For era [ class, expver, stream=supd, date, time, domain [ type, levtype, grid- # The minus sign is here to consume 'grid', but don't index it - [ step, levelist?, param ]]] + [ step, levelist?, param ]] +] # swmm [ class, expver, stream=swmm, date, time, domain [ type, levtype, system?, method - [ fcmonth, number, param ]]] + [ fcmonth, number, param ]] +] # wamf [ class, expver, stream=wamf, date, time, domain [ type, levtype, system?, method - [ step, number?, param ]]] + [ step, number?, param ]] +] # ea/wamo [ class=ea, expver, stream=wamo, date, domain [ type, levtype - [ time, step?, param ]]] + [ time, step?, param ]] +] # wamo [ class, expver, stream=wamo, domain [ type=cl, levtype [ date: ClimateMonthly, time, param ]] [ type, levtype - [ date, time, step?, param ]]] + [ date, time, step?, param ]] +] # wamd [ class, expver, stream=wamd, date, domain [ type, levtype - [ param ]]] + [ param ]] +] # wasf [ class, expver, stream=wasf, date, time, domain [ type, levtype, system?, method - [ step, number, param ]]] + [ step, number, param ]] +] + # wmfm [ class, expver, stream=wmfm, date, time, domain [ type, levtype, system?, method - [ fcperiod, number, param ]]] + [ fcperiod, number, param ]] +] # moda [ class, expver, stream=moda, date, domain [ type, levtype - [ levelist?, param ]]] + [ levelist?, param ]] +] # msdc/mdfa/msda [ class, expver, stream=msdc/mdfa/msda, domain [ type, levtype - [ date, time?, step?, levelist?, param ]]] - - + [ date, time?, step?, levelist?, param ]] +] # seap [ class, expver, stream=seap, date, time, domain [ type=sv/svar, levtype, origin, method? [ step, leadtime, opttime, number, levelist?, param ]] - [ type=ef, levtype, origin [ step, levelist?, param, channel? ]] - [ type, levtype, origin [ step, levelist?, param ]] - - ] +] [ class, expver, stream=mmaf, date, time, domain [ type, levtype, origin, system?, method - [ step, number, levelist?, param ]] + [ step, number, levelist?, param ]] ] [ class, expver, stream=mmam, date, time, domain [ type, levtype, origin, system?, method - [ fcmonth, number, levelist?, param ]] + [ fcmonth, number, levelist?, param ]] ] - [ class, expver, stream=dacl, domain [ type=pb, levtype [ date: ClimateDaily, time, step, quantile, levelist?, param ]] [ type, levtype [ date: ClimateDaily, time, step, levelist?, param ]] - ] [ class, expver, stream=dacw, domain @@ -553,7 +857,6 @@ method: Integer; [ date: ClimateDaily, time, step, quantile, param ]] [ type, levtype [ date: ClimateDaily, time, step, param ]] - ] [ class, expver, stream=edmm/ewmm, date, time, domain @@ -572,19 +875,22 @@ method: Integer; [ class=mc/rd, expver, stream=gfas, date, time, domain [ type=ga, levtype [ step, param ]] - [ type=gsd [ param, ident, instrument ]] - ] # class is e2 [ class, expver, stream=espd, date, time, domain [ type, levtype, origin, grid - [ step, number, levelist?, param ]]] + [ step, number, levelist?, param ]] +] [ class=cs, expver, stream, date:Default, time, domain [ type, levtype - [ step, levelist?, param ]]] - + [ step, levelist?, param ]] +] +[ class=ce, expver, stream=efcl/wfcl, date, model, domain, hdate: Year + [ hdate: Month, type, levtype, origin + [ hdate: Date, levelist?, time, step, param ]] +] diff --git a/tests/fdb/test_service.cc b/tests/fdb/test_service.cc index 2c3c96d32..7eab110db 100644 --- a/tests/fdb/test_service.cc +++ b/tests/fdb/test_service.cc @@ -46,8 +46,7 @@ using namespace eckit::testing; using namespace fdb5; -namespace fdb { -namespace test { +namespace fdb::test { //---------------------------------------------------------------------------------------------------------------------- @@ -68,15 +67,14 @@ struct FixtureService { p["time"] = "0000"; p["type"] = "fc"; - modelParams_.push_back("130.128"); - modelParams_.push_back("138.128"); + modelParams_.push_back("130"); + modelParams_.push_back("138"); } void write_cycle(fdb5::Archiver& fdb, StringDict& p) { Translator str; - std::vector::iterator param = modelParams_.begin(); - for (; param != modelParams_.end(); ++param) { - p["param"] = *param; + for (const auto& param : modelParams_) { + p["param"] = param; p["levtype"] = "pl"; @@ -88,7 +86,7 @@ struct FixtureService { std::ostringstream data; data << "Raining cats and dogs -- " - << " param " << *param << " step " << step << " level " << level << std::endl; + << " param " << param << " step " << step << " level " << level << std::endl; std::string data_str = data.str(); fdb5::Key k{p}; @@ -131,7 +129,7 @@ CASE("test_fdb_stepunit_archive") { fdb5::ListIterator iter = fdb.list(r, true); fdb5::ListElement el; EXPECT(iter.next(el)); - EXPECT(el.combinedKey().get("step") == "60"); + EXPECT_EQUAL(el.combinedKey().get("step"), "60"); EXPECT(!iter.next(el)); } @@ -146,12 +144,12 @@ CASE("test_fdb_stepunit_archive") { fdb5::ListIterator iter = fdb.list(r, true); fdb5::ListElement el; EXPECT(iter.next(el)); - EXPECT(el.combinedKey().get("step") == "2"); + EXPECT_EQUAL(el.combinedKey().get("step"), "2"); EXPECT(!iter.next(el)); iter = fdb5::FDB{}.list(r, true); EXPECT(iter.next(el)); - EXPECT(el.combinedKey().get("step") == "2"); + EXPECT_EQUAL(el.combinedKey().get("step"), "2"); EXPECT(!iter.next(el)); } @@ -161,16 +159,16 @@ CASE("test_fdb_stepunit_archive") { fdb5::ListIterator iter = fdb.list(r, true); fdb5::ListElement el; EXPECT(iter.next(el)); - EXPECT(el.combinedKey().get("step") == "2"); + EXPECT_EQUAL(el.combinedKey().get("step"), "2"); EXPECT(iter.next(el)); - EXPECT(el.combinedKey().get("step") == "60"); + EXPECT_EQUAL(el.combinedKey().get("step"), "60"); EXPECT(!iter.next(el)); iter = fdb5::FDB{}.list(r, true); EXPECT(iter.next(el)); - EXPECT(el.combinedKey().get("step") == "2"); + EXPECT_EQUAL(el.combinedKey().get("step"), "2"); EXPECT(iter.next(el)); - EXPECT(el.combinedKey().get("step") == "60"); + EXPECT_EQUAL(el.combinedKey().get("step"), "60"); EXPECT(!iter.next(el)); } @@ -185,7 +183,7 @@ CASE("test_fdb_stepunit_archive") { fdb5::ListIterator iter = fdb.list(r, true); fdb5::ListElement el; EXPECT(iter.next(el)); - EXPECT(el.combinedKey().get("step") == "30m"); + EXPECT_EQUAL(el.combinedKey().get("step"), "30m"); EXPECT(!iter.next(el)); } @@ -199,9 +197,9 @@ CASE("test_fdb_stepunit_archive") { fdb5::ListIterator iter = fdb.list(r, true); fdb5::ListElement el; EXPECT(iter.next(el)); - EXPECT(el.combinedKey().get("step") == "30m"); + EXPECT_EQUAL(el.combinedKey().get("step"), "30m"); EXPECT(iter.next(el)); - EXPECT(el.combinedKey().get("step") == "2"); + EXPECT_EQUAL(el.combinedKey().get("step"), "2"); EXPECT(!iter.next(el)); } } @@ -251,9 +249,8 @@ CASE("test_fdb_service") { Buffer buffer(1_KiB); Translator str; - std::vector::iterator param = f.modelParams_.begin(); - for (; param != f.modelParams_.end(); ++param) { - f.p["param"] = *param; + for (const auto& param : f.modelParams_) { + f.p["param"] = param; f.p["levtype"] = "pl"; for (size_t step = 0; step < 2; ++step) { @@ -269,9 +266,9 @@ CASE("test_fdb_service") { auto it = fdb5::FDB{}.inspect(r); fdb5::ListElement el; EXPECT(it.next(el)); - EXPECT(el.combinedKey().get("param") == *param); - EXPECT(el.combinedKey().get("step") == str(step * 3)); - EXPECT(el.combinedKey().get("levelist") == str(level * 100)); + EXPECT_EQUAL(el.combinedKey().get("param"), param); + EXPECT_EQUAL(el.combinedKey().get("step"), str(step * 3)); + EXPECT_EQUAL(el.combinedKey().get("levelist"), str(level * 100)); EXPECT(!it.next(el)); std::unique_ptr dh(retriever.retrieve(r)); @@ -286,7 +283,7 @@ CASE("test_fdb_service") { std::ostringstream data; data << "Raining cats and dogs -- " - << " param " << *param << " step " << step << " level " << level << std::endl; + << " param " << param << " step " << step << " level " << level << std::endl; EXPECT(::memcmp(buffer, data.str().c_str(), data.str().size()) == 0); } @@ -299,9 +296,8 @@ CASE("test_fdb_service") { fdb5::FDB lister; Translator str; - std::vector::iterator param = f.modelParams_.begin(); - for (; param != f.modelParams_.end(); ++param) { - f.p["param"] = *param; + for (const auto& param : f.modelParams_) { + f.p["param"] = param; f.p["levtype"] = "pl"; f.p["step"] = str(0); f.p["levelist"] = str(0); @@ -431,9 +427,8 @@ CASE("test_fdb_service_subtoc") { f.p["expver"] = "0002"; Translator str; - std::vector::iterator param = f.modelParams_.begin(); - for (; param != f.modelParams_.end(); ++param) { - f.p["param"] = *param; + for (const auto& param : f.modelParams_) { + f.p["param"] = param; f.p["levtype"] = "pl"; for (size_t step = 0; step < 2; ++step) { @@ -457,7 +452,7 @@ CASE("test_fdb_service_subtoc") { std::ostringstream data; data << "Raining cats and dogs -- " - << " param " << *param << " step " << step << " level " << level << std::endl; + << " param " << param << " step " << step << " level " << level << std::endl; EXPECT(::memcmp(buffer, data.str().c_str(), data.str().size()) == 0); } @@ -472,10 +467,9 @@ CASE("test_fdb_service_subtoc") { f.p["expver"] = "0002"; Translator str; - std::vector::iterator param = f.modelParams_.begin(); - for (; param != f.modelParams_.end(); ++param) { + for (const auto& param : f.modelParams_) { - f.p["param"] = *param; + f.p["param"] = param; f.p["levtype"] = "pl"; f.p["step"] = str(0); f.p["levelist"] = str(0); @@ -584,7 +578,7 @@ CASE("schemaSerialisation") { std::ostringstream ss; clone->dump(ss); - EXPECT(original == ss.str()); + EXPECT_EQUAL(original, ss.str()); } if (filename.exists()) { filename.unlink(); @@ -593,8 +587,7 @@ CASE("schemaSerialisation") { //----------------------------------------------------------------------------- -} // namespace test -} // namespace fdb +} // namespace fdb::test int main(int argc, char** argv) { eckit::Main::initialise(argc, argv, "FDB_HOME"); diff --git a/tests/fdb/timespan/CMakeLists.txt b/tests/fdb/timespan/CMakeLists.txt new file mode 100644 index 000000000..9d8eaf8bf --- /dev/null +++ b/tests/fdb/timespan/CMakeLists.txt @@ -0,0 +1,7 @@ +ecbuild_configure_file( timespan.sh.in timespan.sh @ONLY ) +ecbuild_add_test( + TARGET fdb_test_timespan + LABELS mtg2 + TYPE SCRIPT + COMMAND timespan.sh + ENVIRONMENT "${test_environment}" ) diff --git a/tests/fdb/timespan/in.grib b/tests/fdb/timespan/in.grib new file mode 100644 index 0000000000000000000000000000000000000000..e22eff06021eff10ec19e97c4d3eb27813c89451 GIT binary patch literal 10872 zcmeI2J!ooY9LE2j=X$9vxfd^3kXBj?QXCw-tt}2xgloY;ih~q~P=sc1NWme4Lk0^O z95Og$5Sqau6o(8B85{z2$l#E{A%jB(hYSuG95M*$k8=V>j_2cj-~aRc z9^UtySKod6&Eq2pz22Tg@b3lF4@4>AC%4g$o)al!=QAOuG(9zb`Nhkxh=L;}db%kJ z_6CpdZa6Kuz2x>6|Nhrcx8Lb!e0lNHZ?o-AB0eUHQJfN##NE=Ap)BPnPX#JciON)= zD%Ge?4cet9?NN*NsZ9sep+oA@5%uVp`gB4AI;A0<(TL7zOcykvOPbOZ&FGrubVCce zr6t|bitcGm542%o;|NE2hhrS)1SdJgY0hw#bDZY_7rDe`u5guWT;~Swa+CMC#rxdm z1Mcu4cln5We9V15;Q^oWkk5F;=RD>Mp7144`HE+J&2zrt1>f?L?|8-cyygeq2#HBV zqOv0~iAzF~l9IG!Br7?|OF@cKlCo5!DmAG~Lw2Ppd(x79Y0H6h*0rI#+SEO5>Atr0Ks$Ps)Vip|`r!J6-9$uJu7TMrIbVsO?zH;+C+ar7Ue3%UaIzR+IChelk9gE~Jmzsvc+yjz_Kase=Xo!9(Mw+TidVhnb#M5tH+|1rzVB^6@QxpP z*N?pC$KLl7ANZ*c{me&x?qk33iC_BEuYBg$KKC16_^mJf&R2f#Yk%-fK!F93AR6oh zu^=8Kf@F{i(m^K32Du;~6oO(<3d%txsN%1JZzb$0;FlbZ$l%Bn&Pd?Q7_Jb-l`J6N z;L2;$FEQc^jQkuGn4uC= zRAhq6j8UNxDm6sK2B=&g73`ssT~xG#%C=GA7AoCD#T%%64GO402_-0^0A=K$kPMWP zf?^U-P7Df)LP=(%8z^fHg{`2pB^0-S^5#(B3`(3rkrOC$426!M)FBi*fO7j#a1ToE zLeU*4yA6f6p!6mb-+=OKa6ko4D8Ug0I3ov#WZ;w(9Fu@^VsKCtPBJCgz*%cJYz3z+ z;kX5yH-`gfaN-n>oWPl5ICKQ34&m4VoZE+kdvJ0Wj_$zOZ8*FIr#IpF2Ap350V*It z2}CG>3^@=Y15%_wj0DIL13{u7i2=?VkYx?RtU#J2h_e8B<{;1vB$|Rq6Od^PLXAMG zA&4~qx%wbj4E0A^x;x0hmIS4!hiKig)1Y{nA&?As~2x1RF?mh_K1IfE|2&x}|?)#wp z9%#P{>eoU4DpH_~G$~*w|JpO`I*+y0H<93g1LuMN@ z^r3Hqiay`&eY1U##0_y^u>IMee2MK({|FHPdSFdxHw44)f@&kgHgK8E@DFU-gH-p base.req < inst.req < 1h.req < content.inst < content.1h < expected.all < expected.inst < expected.1h < expected.all < expected.inst < expected.1h < expected.all < expected.inst < expected.1h < axes.out -echo '{"class":["rd"],"date":["20201102"],"domain":["g"],"expver":["xxxx"],"levelist":[""],"levtype":["sfc"],"param":["166"],"step":["6","9"],"stream":["oper"],"time":["0000"],"type":["an","fc"]}' > expected.out +echo '{"class":["rd"],"date":["20201102"],"domain":["g"],"expver":["xxxx"],"levtype":["sfc"],"param":["166"],"step":["6","9"],"stream":["oper"],"time":["0000"],"type":["an","fc"]}' > expected.out cat axes.out cat expected.out cmp axes.out expected.out fdb-axes class=rd,expver=xxxx,stream=oper,date=20201102,time=0000,domain=g > axes.out -echo 'IndexAxis[axis={class=(rd),date=(20201102),domain=(g),expver=(xxxx),levelist=(),levtype=(sfc),param=(166),step=(6,9),stream=(oper),time=(0000),type=(an,fc)}]' > expected.out +echo 'IndexAxis[axis={class=(rd),date=(20201102),domain=(g),expver=(xxxx),levtype=(sfc),param=(166),step=(6,9),stream=(oper),time=(0000),type=(an,fc)}]' > expected.out cat axes.out cat expected.out cmp axes.out expected.out @@ -62,7 +62,7 @@ cmp axes.out expected.out ####### Sub-selection by index fdb-axes class=rd,expver=xxxx,stream=oper,date=20201102,time=0000,domain=g,step=6 > axes.out -echo 'IndexAxis[axis={class=(rd),date=(20201102),domain=(g),expver=(xxxx),levelist=(),levtype=(sfc),param=(166),step=(6),stream=(oper),time=(0000),type=(an,fc)}]' > expected.out +echo 'IndexAxis[axis={class=(rd),date=(20201102),domain=(g),expver=(xxxx),levtype=(sfc),param=(166),step=(6),stream=(oper),time=(0000),type=(an,fc)}]' > expected.out cat axes.out cat expected.out cmp axes.out expected.out From 3c00e562769815380969f059d956d5876dbaa079 Mon Sep 17 00:00:00 2001 From: Emanuele Danovaro Date: Wed, 11 Mar 2026 14:34:57 +0000 Subject: [PATCH 2/3] fix schema --- tests/fdb/etc/fdb/schema | 2 +- tests/fdb/timespan/schema2 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/fdb/etc/fdb/schema b/tests/fdb/etc/fdb/schema index e2e6af20f..8b933cfdc 100755 --- a/tests/fdb/etc/fdb/schema +++ b/tests/fdb/etc/fdb/schema @@ -384,7 +384,7 @@ method: Integer; [ step, param, frequency?, direction? ]] [ type=me, levtype=ml, timespan?none [ step?, number-, levelist, param, coeffindex? ]] - [ type=4i, levtype=ml, tmespan? + [ type=4i, levtype=ml, timespan?none [ step, iteration, levelist, param ]] [ type=4v, levtype=ml/pl/sol/layer/o3d/pv/pt, timespan?none [ step, levelist, param ]] diff --git a/tests/fdb/timespan/schema2 b/tests/fdb/timespan/schema2 index e2e6af20f..8b933cfdc 100755 --- a/tests/fdb/timespan/schema2 +++ b/tests/fdb/timespan/schema2 @@ -384,7 +384,7 @@ method: Integer; [ step, param, frequency?, direction? ]] [ type=me, levtype=ml, timespan?none [ step?, number-, levelist, param, coeffindex? ]] - [ type=4i, levtype=ml, tmespan? + [ type=4i, levtype=ml, timespan?none [ step, iteration, levelist, param ]] [ type=4v, levtype=ml/pl/sol/layer/o3d/pv/pt, timespan?none [ step, levelist, param ]] From ab5ca3c609bebd87bd9ec977e156f47511ab7570 Mon Sep 17 00:00:00 2001 From: Emanuele Danovaro Date: Fri, 20 Mar 2026 07:27:08 +0000 Subject: [PATCH 3/3] FDB-649 schema - optional with defaults - improved behaviour (not injecting the default in the index) --- src/fdb5/api/FDB.cc | 18 +- src/fdb5/database/IndexAxis.cc | 16 +- src/fdb5/rules/MatchOptional.cc | 4 +- src/fdb5/rules/Rule.cc | 72 +- src/fdb5/tools/compare/fdb-compare.cc | 1 - src/fdb5/tools/compare/grib/CompareBitwise.cc | 1 - tests/fdb/CMakeLists.txt | 1 + tests/fdb/api/test_auxiliary.cc | 6 +- tests/fdb/api/test_callback.cc | 2 +- tests/fdb/api/test_dist.cc | 2 +- tests/fdb/api/test_fdb_c.cc | 9 +- tests/fdb/api/test_select.cc | 23 +- tests/fdb/daos/test_daos_catalogue.cc | 6 +- tests/fdb/etc/fdb/schema | 546 ++++++++--- tests/fdb/test_service.cc | 69 +- tests/fdb/timespan/CMakeLists.txt | 7 + tests/fdb/timespan/in.grib | Bin 0 -> 10872 bytes tests/fdb/timespan/local1.yaml | 7 + tests/fdb/timespan/local2.yaml | 7 + tests/fdb/timespan/local3.yaml | 7 + tests/fdb/timespan/req | 12 + tests/fdb/timespan/schema1 | 113 +++ tests/fdb/timespan/schema2 | 896 ++++++++++++++++++ tests/fdb/timespan/schema3 | 113 +++ tests/fdb/timespan/timespan.sh.in | 286 ++++++ tests/fdb/tools/fdb_axes.sh.in | 6 +- 26 files changed, 2014 insertions(+), 216 deletions(-) create mode 100644 tests/fdb/timespan/CMakeLists.txt create mode 100644 tests/fdb/timespan/in.grib create mode 100644 tests/fdb/timespan/local1.yaml create mode 100644 tests/fdb/timespan/local2.yaml create mode 100644 tests/fdb/timespan/local3.yaml create mode 100644 tests/fdb/timespan/req create mode 100755 tests/fdb/timespan/schema1 create mode 100755 tests/fdb/timespan/schema2 create mode 100755 tests/fdb/timespan/schema3 create mode 100755 tests/fdb/timespan/timespan.sh.in diff --git a/src/fdb5/api/FDB.cc b/src/fdb5/api/FDB.cc index 55e1f8e77..a3f777856 100644 --- a/src/fdb5/api/FDB.cc +++ b/src/fdb5/api/FDB.cc @@ -30,6 +30,10 @@ #include "eckit/message/Message.h" #include "eckit/message/Reader.h" +#include "metkit/hypercube/HyperCube.h" +#include "metkit/mars/MarsLanguage.h" +#include "metkit/mars/MarsRequest.h" + #include "fdb5/LibFdb5.h" #include "fdb5/api/FDBFactory.h" #include "fdb5/api/helpers/FDBToolRequest.h" @@ -237,7 +241,19 @@ eckit::DataHandle* FDB::retrieve(const metkit::mars::MarsRequest& request) { } ListIterator FDB::inspect(const metkit::mars::MarsRequest& request) { - return internal_->inspect(request); + + ASSERT(!request.empty()); + + metkit::mars::MarsRequest indexingRequest{request.verb()}; + metkit::mars::MarsLanguage language{request.verb()}; + // Only copy data parameters, as these are the only ones relevant for the indexing + for (const auto& p : request.parameters()) { + if (!language.isPostProc(p.name()) && !language.isSink(p.name())) { + indexingRequest.setValuesTyped(&p.type(), p.values()); + } + } + + return internal_->inspect(indexingRequest); } ListIterator FDB::list(const FDBToolRequest& request, const ListMode mode, const int level) { diff --git a/src/fdb5/database/IndexAxis.cc b/src/fdb5/database/IndexAxis.cc index 9e089b290..67939d4fb 100644 --- a/src/fdb5/database/IndexAxis.cc +++ b/src/fdb5/database/IndexAxis.cc @@ -399,10 +399,13 @@ void IndexAxis::print(std::ostream& out) const { const char* sep = ""; out << "{"; - for (const auto& kv : axis_) { - out << sep << kv.first << "=("; + for (const auto& [k, vv] : axis_) { + if (vv->size() == 1 && vv->at(0).empty()) { + continue; + } + out << sep << k << "=("; const char* sep2 = ""; - for (const auto& v : *kv.second) { + for (const auto& v : *vv) { out << sep2 << v; sep2 = ","; } @@ -415,8 +418,11 @@ void IndexAxis::print(std::ostream& out) const { void IndexAxis::json(eckit::JSON& json) const { json.startObject(); - for (const auto& kv : axis_) { - json << kv.first << *kv.second; + for (const auto& [k, vv] : axis_) { + if (vv->size() == 1 && vv->at(0).empty()) { + continue; + } + json << k << *vv; } json.endObject(); } diff --git a/src/fdb5/rules/MatchOptional.cc b/src/fdb5/rules/MatchOptional.cc index f9a7385fd..ced0c1eb5 100644 --- a/src/fdb5/rules/MatchOptional.cc +++ b/src/fdb5/rules/MatchOptional.cc @@ -71,11 +71,13 @@ void MatchOptional::fill(Key& key, const std::string& keyword, const std::string const std::string& MatchOptional::value(const Key& key, const std::string& keyword) const { + static std::string empty{}; + if (const auto [iter, found] = key.find(keyword); found) { return iter->second; } - return default_[0]; + return empty; } const std::vector& MatchOptional::values(const metkit::mars::MarsRequest& rq, diff --git a/src/fdb5/rules/Rule.cc b/src/fdb5/rules/Rule.cc index 68f4f9521..f32133294 100644 --- a/src/fdb5/rules/Rule.cc +++ b/src/fdb5/rules/Rule.cc @@ -208,7 +208,13 @@ std::optional Rule::findMatchingKey(const eckit::StringList& values) const return {}; } - ASSERT(values.size() >= predicates_.size()); + size_t numPred = predicates_.size(); + for (const auto& p : predicates_) { + if (p->optional()) { + numPred--; + } + } + ASSERT(values.size() >= numPred); TypedKey key(registry_); @@ -282,7 +288,6 @@ std::vector Rule::findMatchingKeys(const metkit::mars::MarsRequest& request } } - /// @todo activate this graph.canonicalise(registry_); return graph.makeKeys(); @@ -295,13 +300,12 @@ std::vector Rule::findMatchingKeys(const metkit::mars::MarsRequest& request for (const auto& pred : predicates_) { const auto& keyword = pred->keyword(); - const auto& type = registry_.lookupType(keyword); - - - const auto& values = pred->values(request); + auto values = pred->values(request); - /// @note do we want to allow empty values? - // if (values.empty() && pred->optional()) { values.push_back(pred->defaultValue()); } + /// if the request does not have the keyword, but the predicate is optional, then use the default value + if (values.empty() && pred->optional()) { + values.push_back(pred->defaultValue()); + } auto& node = graph.push(keyword); @@ -311,6 +315,7 @@ std::vector Rule::findMatchingKeys(const metkit::mars::MarsRequest& request } } + /// if there are no matching values for this predicate, then there are no matching keys for the rule if (node.empty()) { return {}; } @@ -328,22 +333,25 @@ std::vector Rule::findMatchingKeys(const metkit::mars::MarsRequest& request for (const auto& pred : predicates_) { const auto& keyword = pred->keyword(); - const auto& type = registry_.lookupType(keyword); // performance optimization to avoid calling values() on visitor - if (!pred->optional() && request.countValues(keyword) == 0) { - return {}; - } - eckit::StringList values; - visitor.values(request, keyword, registry_, values); - - if (values.empty() && pred->optional()) { - values.push_back(pred->defaultValue()); + if (request.countValues(keyword) == 0) { + if (pred->optional()) { + values.push_back(pred->defaultValue()); + if (!pred->defaultValue().empty()) { + values.push_back(""); + } + } + else { + return {}; + } + } + else { + visitor.values(request, keyword, registry_, values); } auto& node = graph.push(keyword); - for (const auto& value : values) { if (pred->match(value)) { node.emplace_back(value); @@ -351,23 +359,17 @@ std::vector Rule::findMatchingKeys(const metkit::mars::MarsRequest& request } if (node.empty()) { - return {}; + if (pred->optional()) { + node.emplace_back(""); + } + else { + return {}; + } } } graph.canonicalise(registry_); - - auto out = graph.makeKeys(); - - LOG_DEBUG_LIB(LibFdb5) << "findMatchingKeys " << request << " ==> "; - std::string sep; - for (const auto& k : out) { - LOG_DEBUG_LIB(LibFdb5) << sep << k; - sep = " | "; - } - LOG_DEBUG_LIB(LibFdb5) << std::endl; - - return out; + return graph.makeKeys(); } //---------------------------------------------------------------------------------------------------------------------- @@ -399,7 +401,13 @@ bool Rule::tryFill(Key& key, const eckit::StringList& values) const { // --> HACK. // --> Stick a plaster over the symptom. - ASSERT(values.size() >= predicates_.size()); // Should be equal, except for quantile (FDB-103) + size_t numPred = predicates_.size(); + for (const auto& p : predicates_) { + if (p->optional()) { + numPred--; + } + } + ASSERT(values.size() >= numPred); // Should be equal, except for quantile (FDB-103) ASSERT(values.size() <= predicates_.size() + 1); auto it_value = values.begin(); diff --git a/src/fdb5/tools/compare/fdb-compare.cc b/src/fdb5/tools/compare/fdb-compare.cc index 43dd65867..62fdb29a0 100644 --- a/src/fdb5/tools/compare/fdb-compare.cc +++ b/src/fdb5/tools/compare/fdb-compare.cc @@ -62,7 +62,6 @@ class FDBCompare : public eckit::Tool { std::optional config2_; std::optional req1String_; std::optional req2String_; - bool singleFDB_ = false; }; //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/fdb5/tools/compare/grib/CompareBitwise.cc b/src/fdb5/tools/compare/grib/CompareBitwise.cc index a1c4dcf9b..c91b9a354 100644 --- a/src/fdb5/tools/compare/grib/CompareBitwise.cc +++ b/src/fdb5/tools/compare/grib/CompareBitwise.cc @@ -190,7 +190,6 @@ CompareResult bitComparison(const uint8_t* buffer1, const uint8_t* buffer2, size // Process sections based on edition for (int i = 0; i < numSections; ++i) { - // std::cout<<"offset " << offset< setup(FDB& fdb, std::set auxExtensions = {"foo", "bar"}, const std::vector& dates = {"20101010", "20111213"}, - const std::vector& types = {"fc", "pf"}, + const std::vector& types = {"fc", "an"}, const std::vector& steps = {"1", "2"} ) { @@ -126,7 +126,7 @@ CASE("Wipe with extensions") { EXPECT_EQUAL(element_counts[WipeElementType::STORE_AUX], 8); // over specified wipe: returns nothing - request = FDBToolRequest::requestsFromString("class=od,expver=xxxx,type=pf,step=1")[0]; + request = FDBToolRequest::requestsFromString("class=od,expver=xxxx,type=an,step=1")[0]; doit = true; iter = fdb.wipe(request, doit); element_counts.clear(); @@ -140,7 +140,7 @@ CASE("Wipe with extensions") { // partial wipe on the second level. Hits half the data files - request = FDBToolRequest::requestsFromString("class=od,expver=xxxx,type=pf")[0]; + request = FDBToolRequest::requestsFromString("class=od,expver=xxxx,type=an")[0]; doit = true; iter = fdb.wipe(request, doit); element_counts.clear(); diff --git a/tests/fdb/api/test_callback.cc b/tests/fdb/api/test_callback.cc index afbed70c4..be375f9f0 100644 --- a/tests/fdb/api/test_callback.cc +++ b/tests/fdb/api/test_callback.cc @@ -48,7 +48,7 @@ CASE("Archive and flush callback") { keys.push_back(key); fdb.archive(key, data, length); - key.set("type", "pf"); + key.set("type", "an"); keys.push_back(key); fdb.archive(key, data, length); diff --git a/tests/fdb/api/test_dist.cc b/tests/fdb/api/test_dist.cc index 102ac8989..89312c860 100644 --- a/tests/fdb/api/test_dist.cc +++ b/tests/fdb/api/test_dist.cc @@ -142,7 +142,7 @@ CASE("retrieves_distributed_according_to_dist") { // Do some archiving - metkit::mars::MarsRequest req; + metkit::mars::MarsRequest req{"retrieve"}; req.setValuesTyped(new metkit::mars::TypeAny("class"), std::vector{"od"}); req.setValuesTyped(new metkit::mars::TypeAny("expver"), std::vector{"xxxx"}); fdb.inspect(req); diff --git a/tests/fdb/api/test_fdb_c.cc b/tests/fdb/api/test_fdb_c.cc index ba4a43443..62d0f1979 100644 --- a/tests/fdb/api/test_fdb_c.cc +++ b/tests/fdb/api/test_fdb_c.cc @@ -35,7 +35,7 @@ int fdb_request_add1(fdb_request_t* req, const char* param, const char* value) { void key_compare(const std::vector& keys, fdb_listiterator_t* it, bool checkLevel = true) { const char* k; - const char* v; + const char* v = nullptr; size_t l; int err; @@ -47,7 +47,12 @@ void key_compare(const std::vector& keys, fdb_listiterator_t* it, boo size_t level = 0; for (const auto& key : keys) { for (const auto& k1 : key) { - int err = fdb_splitkey_next_metadata(sk, &k, &v, checkLevel ? &l : nullptr); + int err; + v = nullptr; + // skip empty values (optional metadata) + while (v == nullptr || strlen(v) == 0) { + err = fdb_splitkey_next_metadata(sk, &k, &v, checkLevel ? &l : nullptr); + } std::cerr << "k=" << k << " v=" << v << " l=" << l << std::endl; EXPECT(err == FDB_SUCCESS); EXPECT(k1.first == k); diff --git a/tests/fdb/api/test_select.cc b/tests/fdb/api/test_select.cc index 9d02de31e..d5e37ecc7 100644 --- a/tests/fdb/api/test_select.cc +++ b/tests/fdb/api/test_select.cc @@ -17,10 +17,13 @@ #include "eckit/testing/Test.h" -#include "fdb5/api/helpers/WipeIterator.h" +#include "metkit/mars/MarsLanguage.h" +#include "metkit/mars/MarsParser.h" +#include "metkit/mars/MarsRequest.h" #include "metkit/mars/TypeAny.h" #include "fdb5/api/helpers/FDBToolRequest.h" +#include "fdb5/api/helpers/WipeIterator.h" #include "fdb5/config/Config.h" #include "ApiSpy.h" @@ -153,8 +156,20 @@ CASE("retrieves_distributed_according_to_select") { // Build FDB from default config fdb5::FDB fdb(defaultConfig()); - fdb.list(metkit::mars::MarsRequest{"class=od"}); - fdb.list(metkit::mars::MarsRequest{"class=rd"}); + { + std::istringstream in("retrieve,class=od"); + metkit::mars::MarsParser parser(in); + auto reqs = parser.parse(); + ASSERT(reqs.size() == 1); + fdb.list(reqs[0]); + } + { + std::istringstream in("retrieve,class=rd"); + metkit::mars::MarsParser parser(in); + auto reqs = parser.parse(); + ASSERT(reqs.size() == 1); + fdb.list(reqs[0]); + } EXPECT(ApiSpy::knownSpies().size() == 3); ApiSpy& spy_od(*ApiSpy::knownSpies()[0]); @@ -163,7 +178,7 @@ CASE("retrieves_distributed_according_to_select") { // Do some archiving - metkit::mars::MarsRequest req; + metkit::mars::MarsRequest req{"retrieve"}; req.setValuesTyped(new metkit::mars::TypeAny("class"), std::vector{"od"}); req.setValuesTyped(new metkit::mars::TypeAny("expver"), std::vector{"xxxx"}); fdb.inspect(req); diff --git a/tests/fdb/daos/test_daos_catalogue.cc b/tests/fdb/daos/test_daos_catalogue.cc index 12b752744..cc4f58bfe 100644 --- a/tests/fdb/daos/test_daos_catalogue.cc +++ b/tests/fdb/daos/test_daos_catalogue.cc @@ -527,9 +527,9 @@ CASE("DaosCatalogue tests") { fdb5::Key db_key({{"a", "11"}, {"b", "22"}}); fdb5::Key index_key({{"a", "11"}, {"b", "22"}, {"c", "3"}, {"d", "4"}}); - fdb5::FDBToolRequest full_req{request_key.request("retrieve"), false, std::vector{"a", "b"}}; - fdb5::FDBToolRequest index_req{index_key.request("retrieve"), false, std::vector{"a", "b"}}; - fdb5::FDBToolRequest db_req{db_key.request("retrieve"), false, std::vector{"a", "b"}}; + fdb5::FDBToolRequest full_req{request_key.request(), false, std::vector{"a", "b"}}; + fdb5::FDBToolRequest index_req{index_key.request(), false, std::vector{"a", "b"}}; + fdb5::FDBToolRequest db_req{db_key.request(), false, std::vector{"a", "b"}}; fdb5::FDBToolRequest all_req{metkit::mars::MarsRequest{}, true, std::vector{}}; // initialise FDB diff --git a/tests/fdb/etc/fdb/schema b/tests/fdb/etc/fdb/schema index bceac97f4..8b933cfdc 100755 --- a/tests/fdb/etc/fdb/schema +++ b/tests/fdb/etc/fdb/schema @@ -19,7 +19,7 @@ # This will be used when matching rules. # * Attributes can be typed -# Globally, at the beginning of this file: +# Globally, at the begining of this file: # refdate: Date; @@ -30,7 +30,7 @@ # * Attributes can be optional # [ step, levelist?, param ] -# They will be replaced internally by an empty value. It is also possible to provide a default substitution value: e.g. [domain?g] will consider the domain to be 'g' if missing. +# They will be replaced internally by an empty value. It is also posiible to provide a default subtitution value: e.g. [domain?g] will consider the domain to be 'g' if missing. # * Attributes can be removed: # [grid-] @@ -61,6 +61,7 @@ step: Step; date: Date; hdate: Date; refdate: Date; +offsetdate: Date; latitude: Double; longitude: Double; levelist: Double; @@ -68,12 +69,15 @@ grid: Grid; expver: Expver; time: Time; +offsettime: Time; fcmonth: Integer; number: Integer; frequency: Integer; direction: Integer; channel: Integer; +chem: Integer; +coeffindex: Integer; instrument: Integer; ident: Integer; @@ -100,6 +104,7 @@ method: Integer; ######################################################## # These rules must be first, otherwise fields of These # classes will be index with the default rule for oper + [ class=ti/s2, expver, stream, date, time, model [ origin, type, levtype, hdate? [ step, number?, levelist?, param ]] @@ -112,8 +117,7 @@ method: Integer; [ class=ms, expver, stream, date, time, country=it [ domain, type, levtype, model, bcmodel, icmodel:First3 - [ step, levelist?, param ] - ] + [ step, levelist?, param ]] ] [ class=el, expver, stream, date, time, domain @@ -121,51 +125,317 @@ method: Integer; [ step, levelist?, param ]] ] +######################################################## +# These are the rules for class Cerise (mmsf/mmsa/msmm) +[ class=ci, expver, stream=mmsf, date, time, domain + [ type, levtype, origin, system? + [ step, number, levelist?, param ]] +] + +[ class=ci, expver, stream=mmsa/msmm, date, time, domain + [ type, levtype, origin, system? + [ fcmonth, number?, levelist?, param ]] +] + +######################################################## +# These are the rules for class=ai +[ class=ai, expver, stream, model?, date, time, domain + [ type, levtype, timespan?none + [ step, quantile?, number?, levelist?, param ]] +] + +######################################################## +# These are the rules for the Extremes DT +# oper/wave +[ class=d1, dataset=extremes-dt, expver, stream=oper/wave, date, time + [ type, levtype, timespan?none + [ step, levelist?, param, frequency?, direction? ]] +] +# enfo/waef +[ class=d1, dataset=extremes-dt, expver, stream=enfo/waef, date, time + [ type, levtype, timespan?none + [ step, number?, levelist?, param, frequency?, direction? ]] +] +# lwda/lwwv +[ class=d1, dataset=extremes-dt, expver, stream=lwda/lwwv, date, time + [ type, levtype, anoffset, timespan?none + [ step, levelist?, param, frequency?, direction? ]] +] + +######################################################## +# These are the rules for the On-Demand Extremes DT +# oper +[ class=d1, dataset=on-demand-extremes-dt, expver, stream=oper, date, time + [ type=ssd, georef, timespan?none + [ step, param, ident, instrument, channel ]] + [ type, levtype, georef, timespan?none + [ step, levelist?, param ]] +] + +# enfo +[ class=d1, dataset=on-demand-extremes-dt, expver, stream=enfo, date, time + [ type, levtype, georef, timespan?none + [ step, number?, levelist?, param ]] +] + +######################################################## +# These are the rules for class=e6 ERA6 + +# stream elda +[ class=e6, expver, stream=elda, date, domain?g + [ type=an, levtype=al/sfc, anoffset, timespan?none + [ number, time, step?0, levelist-, param, frequency?, direction?, wavelength?]] + [ type=an, levtype=ml/pl/sol/hl/pv/pt, anoffset, timespan?none + [ number, time, step?0, levelist, param, frequency?, direction?, wavelength?]] + [ type=eme, levtype, anoffset, timespan?none + [ number, time, step?0, levelist?, param, frequency?, direction?, wavelength?]] + [ type=fc, levtype=al/sfc/o2d, anoffset, timespan?none + [ number, time, step, levelist-, param, frequency?, direction?, wavelength?]] + [ type=fc, levtype=ml/pl/sol/hl/pv/pt/o3d, anoffset, timespan?none + [ number, time, step, levelist, param, frequency?, direction?, wavelength?]] + [ type=4i, levtype, anoffset, timespan?none + [ number?, time, step, iteration, levelist, param ]] + [ type=4v, levtype, anoffset, timespan?none + [ number, time, step, levelist?, param, frequency?, direction?, wavelength? ]] + [ type=est, levtype, anoffset, timespan?none + [ number?, time, step, levelist?, param, frequency?, direction?, wavelength? ]] + [ type=es/em, levtype, anoffset, timespan?none + [ number?, time, step, levelist?, param, channel?, wavelength? ]] + [ type=ses, levtype, anoffset, timespan?none + [ number?, time, step, levelist?, param, channel? ]] +] + +# stream lwda +[ class=e6, expver, stream=lwda, date, domain?g + [ type=an, levtype, anoffset, timespan?none + [ time, step?0, levelist?, param, frequency?, direction?, wavelength?]] + [ type=me, levtype, anoffset, timespan?none + [ number?, time, step?0, levelist?, param, frequency?, direction?, wavelength?]] + [ type=fc, levtype, anoffset, timespan?none + [ time, step, levelist?, param, frequency?, direction?, wavelength?]] + [ type=4i, levtype, anoffset, timespan?none + [ time, step, iteration, levelist, param ]] + [ type=4v, levtype, anoffset, timespan?none + [ time, step, levelist?, param, frequency?, direction?, wavelength? ]] +] + +# stream enda +[ class=e6, expver, stream=enda, date, domain?g + [ type, levtype, timespan?none + [ number, time, step?0, levelist?, param, channel?, frequency?, direction?, wavelength?]] +] + +# stream oper +[ class=e6, expver, stream=oper, date, domain?g + [ type=me, levtype, timespan?none + [ number?, time, step?0, levelist?, param, frequency?, direction?, wavelength?]] + [ type, levtype, timespan?none + [ time, step, levelist?, param, frequency?, direction?, wavelength?]] +] + +######################################################## +# Monthly and daily statistics for ERA6 + +[ class=e6, expver, stream=sttd, date, domain?g + [ stattype=moav/momn/momx/mosd/daac/daav/damn/damx/dasd/moav_daav/moav_damn/moav_damx/moav_dasd/momn_daav/momn_damn/momn_damx/momn_dasd/momx_daav/momx_damn/momx_damx/momx_dasd/mosd_daav/mosd_damn/mosd_damx/mosd_dasd, type, levtype, timespan?none + [ levelist?, param, frequency?, direction?, wavelength?]] +] + +[ class=e6, expver, stream=stte, date, domain?g + [ stattype=moav/momn/momx/mosd/daac/daav/damn/damx/dasd/moav_daav/moav_damn/moav_damx/moav_dasd/momn_daav/momn_damn/momn_damx/momn_dasd/momx_daav/momx_damn/momx_damx/momx_dasd/mosd_daav/mosd_damn/mosd_damx/mosd_dasd, type=em/es, levtype, timespan?none + [ levelist?, param, frequency?, direction?, wavelength?]] + [ stattype=moav/momn/momx/mosd/daac/daav/damn/damx/dasd/moav_daav/moav_damn/moav_damx/moav_dasd/momn_daav/momn_damn/momn_damx/momn_dasd/momx_daav/momx_damn/momx_damx/momx_dasd/mosd_daav/mosd_damn/mosd_damx/mosd_dasd, type, levtype, timespan?none + [ number, levelist?, param, frequency?, direction?, wavelength?]] +] + +######################################################## +######################################################## +## These are the rules for CAMS - classes cr/a5 +# stream oper +[ class=cr, expver, stream=oper, date, domain? + [ type=an, levtype, timespan?none + [ time, step?0, levelist?, param, chem, frequency?, direction?, wavelength?]] + [ type=me, levtype, timespan?none + [ number?, time, step?0, levelist?, param, chem?, frequency?, direction?, wavelength?]] + [ type=fc, levtype, timespan?none + [ time, step, levelist?, param, chem?, frequency?, direction?, wavelength?]] + [ type=4i, levtype, timespan?none + [ time, step, iteration, levelist, param, chem? ]] + [ type=4v, levtype, timespan?none + [ time, step, levelist?, param, chem?, frequency?, direction?, wavelength?]] +] + +[ class=cr, expver, stream=lwda, date, domain? + [ type=an, levtype, anoffset, timespan?none + [ time, step?0, levelist?, param, chem?, frequency?, direction?, wavelength?]] + [ type=me, levtype, anoffset, timespan?none + [ number, time, step?0, levelist?, param, chem?, frequency?, direction?, wavelength?]] + [ type=fc, levtype, anoffset, timespan?none + [ time, step, levelist?, param, chem?, frequency?, direction?, wavelength?]] + [ type=4i, levtype, anoffset, timespan?none + [ time, step, iteration, levelist, param, chem? ]] + [ type=4v, levtype, anoffset, timespan?none + [ time, step, levelist?, param, chem?, frequency?, direction?, wavelength?]] +] + +[ class=a5, expver, stream=oper, date, domain? + [ type=an, levtype, timespan?none + [ time, step?0, levelist?, param, chem?, frequency?, direction?, wavelength?]] + [ type=me, levtype, timespan?none + [ number?, time, step?0, levelist?, param, chem?, frequency?, direction?, wavelength?]] + [ type=fc, levtype, timespan?none + [ time, step, levelist?, param, chem?, frequency?, direction?, wavelength?]] + [ type=4i, levtype, timespan?none + [ time, step, iteration, levelist, param, chem? ]] + [ type=4v, levtype, timespan?none + [ time, step, levelist?, param, chem?, frequency?, direction?, wavelength?]] +] + +[ class=a5, expver, stream=lwda, date, domain? + [ type=an, levtype, anoffset, timespan?none + [ time, step?0, levelist?, param, chem?, frequency?, direction?, wavelength?]] + [ type=me, levtype, anoffset, timespan?none + [ number, time, step?0, levelist?, param, chem?, frequency?, direction?, wavelength?]] + [ type=fc, levtype, anoffset, timespan?none + [ time, step, levelist?, param, chem?, frequency?, direction?, wavelength?]] + [ type=4i, levtype, anoffset, timespan?none + [ time, step, iteration, levelist, param, chem? ]] + [ type=4v, levtype, anoffset, timespan?none + [ time, step, levelist?, param, chem?, frequency?, direction?, wavelength?]] +] + +######################################################## +# Monthly and daily statistics for EAC5 and CAMS research + +[ class=a5, expver, stream=sttd, date, domain? + [ stattype=moav/momn/momx/mosd/daac/daav/damn/damx/dasd/moav_daav/moav_damn/moav_damx/moav_dasd/momn_daav/momn_damn/momn_damx/momn_dasd/momx_daav/momx_damn/momx_damx/momx_dasd/mosd_daav/mosd_damn/mosd_damx/mosd_dasd, type, levtype, timespan?none + [ levelist?, param, chem?, frequency?, direction?, wavelength?]] +] + +[ class=a5, expver, stream=stte, date, domain? + [ stattype=moav/momn/momx/mosd/daac/daav/damn/damx/dasd/moav_daav/moav_damn/moav_damx/moav_dasd/momn_daav/momn_damn/momn_damx/momn_dasd/momx_daav/momx_damn/momx_damx/momx_dasd/mosd_daav/mosd_damn/mosd_damx/mosd_dasd, type, levtype, timespan?none + [ number, levelist?, param, chem?, frequency?, direction?, wavelength?]] +] + +[ class=cr, expver, stream=sttd, date, domain? + [ stattype=moav/momn/momx/mosd/daac/daav/damn/damx/dasd/moav_daav/moav_damn/moav_damx/moav_dasd/momn_daav/momn_damn/momn_damx/momn_dasd/momx_daav/momx_damn/momx_damx/momx_dasd/mosd_daav/mosd_damn/mosd_damx/mosd_dasd, type, levtype, timespan?none + [ levelist?, param, chem?, frequency?, direction?, wavelength?]] +] + +[ class=cr, expver, stream=stte, date, domain? + [ stattype=moav/momn/momx/mosd/daac/daav/damn/damx/dasd/moav_daav/moav_damn/moav_damx/moav_dasd/momn_daav/momn_damn/momn_damx/momn_dasd/momx_daav/momx_damn/momx_damx/momx_dasd/mosd_daav/mosd_damn/mosd_damx/mosd_dasd, type, levtype, timespan?none + [ number, levelist?, param, chem?, frequency?, direction?, wavelength?]] +] + +######################################################## +# rules for class RD +# rd/lwda +[ class, expver, stream=lwda, date, time, domain?g + [ type=an, levtype=pl/ml/sol/layer/o3d/pv/pt, anoffset, timespan?none + [ step?0, levelist, param ]] + [ type=an, levtype=o2d/al, anoffset, timespan?none + [ step?0, param ]] + [ type=an, levtype=sfc, anoffset, timespan?none + [ step?0, param, frequency?, direction? ]] + [ type=fc, levtype=pl/ml/sol/layer/o3d/pv/pt, anoffset, timespan?none + [ step, levelist, param ]] + [ type=fc, levtype=o2d/al, anoffset, timespan?none + [ step, param ]] + [ type=fc, levtype=sfc, anoffset, timespan?none + [ step, param, frequency?, direction? ]] + [ type=me, levtype=ml, anoffset, timespan?none + [ step?, number-, levelist, param, coeffindex? ]] + [ type=4i, levtype=ml, anoffset, timespan?none + [ step, iteration, levelist, param ]] + [ type=4v, levtype=pl/ml/sol/layer/o3d/pv/pt, anoffset, timespan?none + [ step, levelist, param ]] + [ type=4v, levtype=o2d/al, anoffset, timespan?none + [ step, param ]] + [ type=4v, levtype=sfc, anoffset, timespan?none + [ step, param, frequency?, direction? ]] + [ type=ssd, anoffset, timespan?none + [ step, param, ident, instrument, channel ]] + [ type=gai + [ param ]] + [ type=ai/ob/ofb/mfb/tf/oai + [ obsgroup, reportype ]] +] + +# MTG2 OD +[ class=od, expver=2249/2250, stream=oper, date, domain? + [ type=me, levtype, timespan?none + [ number?, time, step?0, levelist?, param, frequency?, direction?, wavelength?]] + [ type, levtype, timespan?none + [ time, step, levelist?, param, frequency?, direction?, wavelength?]] +] + +[ class, expver, stream=oper, date, time, domain?g + [ type=an, levtype=pl/ml/sol/layer/o3d/pt/pv, timespan?none + [ step?0, levelist, param ]] + [ type=an, levtype=o2d/al, timespan?none + [ step?0, param ]] + [ type=an, levtype=sfc, timespan?none + [ step?0, param, frequency?, direction? ]] + [ type=fc, levtype=ml/pl/sol/layer/o3d/pt/pv, timespan?none + [ step, levelist, param ]] + [ type=fc, levtype=o2d/al, timespan?none + [ step, param ]] + [ type=fc, levtype=sfc, timespan?none + [ step, param, frequency?, direction? ]] + [ type=me, levtype=ml, timespan?none + [ step?, number-, levelist, param, coeffindex? ]] + [ type=4i, levtype=ml, timespan?none + [ step, iteration, levelist, param ]] + [ type=4v, levtype=ml/pl/sol/layer/o3d/pv/pt, timespan?none + [ step, levelist, param ]] + [ type=4v, levtype=o2d/al, timespan?none + [ step, param ]] + [ type=4v, levtype=sfc, timespan?none + [ step, param, frequency?, direction? ]] + [ type=ssd, timespan?none + [ step, param, ident, instrument, channel ]] + [ type=gai + [ param ]] + [ type=ai/ob/ofb/mfb/tf/oai + [ obsgroup, reportype ]] +] + ######################################################## # The are the rules matching most of the fields # oper/dcda -[ class, expver, stream=oper/dcda/scda, date, time, domain? - +[ class, expver, stream=dcda/scda, date, time, domain?g [ type=im/sim [ step?, ident, instrument, channel ]] - [ type=ssd [ step, param, ident, instrument, channel ]] - [ type=4i, levtype [ step, iteration, levelist, param ]] - [ type=me, levtype [ step, number, levelist?, param ]] - [ type=ef, levtype [ step, levelist?, param, channel? ]] - [ type=ofb/mfb [ obsgroup, reportype ]] - + [ type=pf/em/es/efi, levtype + [ step, number?, levelist?, param ]] [ type, levtype [ step, levelist?, param ]] - ] # dcwv/scwv/wave [ class, expver, stream=dcwv/scwv/wave, date, time, domain [ type, levtype - [ step, param, frequency?, direction? ]]] + [ step, param, frequency?, direction? ]] +] # enfo [ class, expver, stream=enfo/efov/eefo, date, time, domain - [ type, levtype=dp, product?, section? - [ step, number?, levelist?, latitude?, longitude?, range?, param ]] - + [ step, number?, levelist?, latitude?, longitude?, range?, param ]] [ type=tu, levtype, reference [ step, number, levelist?, param ]] - [ type, levtype [ step, quantile?, number?, levelist?, param ]] - ] # waef/weov @@ -177,14 +447,10 @@ method: Integer; ######################################################## # enda [ class, expver, stream=enda, date, time, domain - [ type=ef/em/es/ses, levtype [ step, number?, levelist?, param, channel? ]] - [ type=ssd [ step, number, param, ident, instrument, channel ]] - - [ type, levtype [ step, number?, levelist?, param ]] ] @@ -198,42 +464,35 @@ method: Integer; ######################################################## # elda -[ class, expver, stream=elda, date, time, domain? - +[ class, expver, stream=elda, date, time, domain?g [ type=ofb/mfb [ obsgroup, reportype ]] - [ type, levtype, anoffset - [ step, number?, levelist?, iteration?, param, channel? ]] + [ step, number?, levelist?, iteration?, param, channel?, coeffindex? ]] ] -# ewda +# ewla [ class, expver, stream=ewla, date, time, domain [ type, levtype, anoffset [ step, number?, param, frequency?, direction? ]] ] ######################################################## -# elda -[ class, expver, stream=lwda, date, time, domain? - - [ type=ssd, anoffset - [ step, param, ident, instrument, channel ]] - - [type=me, levtype, anoffset - [ number, step, levelist?, param]] - - [ type=4i, levtype, anoffset - [ step, iteration, levelist, param ]] - - [ type=ofb/mfb - [ obsgroup, reportype ]] - - [ type, levtype, anoffset, timespan? - [ step, levelist?, param]] -] - -# ewda +# lwda +#[ class, expver, stream=lwda, date, time, domain?g +# [ type=ssd, anoffset +# [ step, param, ident, instrument, channel ]] +# [ type=me, levtype, anoffset +# [ number, step, levelist?, param]] +# [ type=4i, levtype, anoffset +# [ step, iteration, levelist, param ]] +# [ type=ofb/mfb/oai +# [ obsgroup, reportype ]] +# [ type, levtype, anoffset +# [ step, levelist?, param]] +#] + +# lwwv [ class, expver, stream=lwwv, date, time, domain [ type, levtype, anoffset [ step, param, frequency?, direction? ]] @@ -242,69 +501,78 @@ method: Integer; # amap [ class, expver, stream=amap, date, time, domain [ type, levtype, origin - [ step, levelist?, param ]]] + [ step, levelist?, param ]] +] # maed [ class, expver, stream=maed, date, time, domain [ type, levtype, origin - [ step, levelist?, param ]]] + [ step, levelist?, param ]] +] # mawv [ class, expver, stream=mawv, date, time, domain [ type, levtype, origin - [ step, param, frequency?, direction? ]]] + [ step, param, frequency?, direction? ]] +] # cher [ class, expver, stream=cher, date, time, domain [ type, levtype - [ step, levelist, param ]]] + [ step, levelist, param ]] +] # efhc [ class, expver, stream=efhc, refdate, time, domain [ type, levtype, date - [ step, number?, levelist?, param ]]] + [ step, number?, levelist?, param ]] +] # efho [ class, expver, stream=efho, date, time, domain [ type, levtype, hdate - [ step, number?, levelist?, param ]]] + [ step, number?, levelist?, param ]] +] # efhs [ class, expver, stream=efhs/eehs, date, time, domain [ type, levtype - [ step, quantile?, number?, levelist?, param ]]] + [ step, quantile?, number?, levelist?, param ]] +] # wehs [ class, expver, stream=wehs/wees, date, time, domain [ type, levtype - [ step, quantile?, number?, levelist?, param ]]] + [ step, quantile?, number?, levelist?, param ]] +] # kwbc [ class, expver, stream=kwbc, date, time, domain [ type, levtype - [ step, number?, levelist?, param ]]] + [ step, number?, levelist?, param ]] +] # ehmm [ class, expver, stream=ehmm, date, time, domain [ type, levtype, hdate - [ fcmonth, levelist?, param ]]] + [ fcmonth, levelist?, param ]] +] # ammc/cwao/edzw/egrr/lfpw/rjtd/toga [ class, expver, stream=ammc/cwao/edzw/egrr/lfpw/rjtd/toga/fgge, date, time, domain [ type, levtype - [ step, levelist?, param ]]] + [ step, levelist?, param ]] +] ######################################################################## # enfh [ class, expver, stream=enfh/eefh, date, time, domain - [ type, levtype=dp, hdate, product?, section? - [ step, number?, levelist?, latitude?, longitude?, range?, param ]] - + [ step, number?, levelist?, latitude?, longitude?, range?, param ]] [ type, levtype, hdate [ step, number?, levelist?, param ]] ] @@ -319,68 +587,73 @@ method: Integer; # sens [ class, expver, stream=sens, date, time, domain [ type, levtype - [ step, diagnostic, iteration, levelist?, param ]]] + [ step, diagnostic, iteration, levelist?, param ]] +] ######################################################################## # esmm [ class, expver, stream=esmm, date, time, domain [ type, levtype - [ fcmonth, levelist?, param ]]] + [ fcmonth, levelist?, param ]] +] + # ewhc [ class, expver, stream=ewhc, refdate, time, domain [ type, levtype, date - [ step, number?, param, frequency?, direction? ]]] + [ step, number?, param, frequency?, direction? ]] +] ######################################################################## # ewho [ class, expver, stream=ewho, date, time, domain [ type, levtype, hdate - [ step, number?, param, frequency?, direction? ]]] + [ step, number?, param, frequency?, direction? ]] +] # mfam [ class, expver, stream=mfam, date, time, domain - [ type=pb/pd, levtype, origin, system?, method [ fcperiod, quantile, levelist?, param ]] - [ type, levtype, origin, system?, method [ fcperiod, number?, levelist?, param ]] - ] # mfhm [ class, expver, stream=mfhm, refdate, time, domain [ type, levtype, origin, system?, method, date? - [ fcperiod, number?, levelist?, param ]]] + [ fcperiod, number?, levelist?, param ]] +] + # mfhw [ class, expver, stream=mfhw, refdate, time, domain [ type, levtype, origin, system?, method, date - [ step, number?, param ]]] + [ step, number?, param ]] +] + # mfwm [ class, expver, stream=mfwm, date, time, domain [ type, levtype, origin, system?, method - [ fcperiod, number, param ]]] + [ fcperiod, number, param ]] +] + # mhwm [ class, expver, stream=mhwm, refdate, time, domain [ type, levtype, origin, system?, method, date - [ fcperiod, number, param ]]] + [ fcperiod, number, param ]] +] # mmsf -[ class, expver, stream=mmsf, date, time, domain - +[ class=od/rd/te/c3/uk/nl/fr/es/ch/de/pt/be/gr/ie/tr/no/fi/se/it, expver, stream=mmsf, date, time, domain [ type, levtype=dp, origin, product, section, system?, method - [ step, number, levelist?, latitude?, longitude?, range?, param ]] - + [ step, number, levelist?, latitude?, longitude?, range?, param ]] [ type, levtype, origin, system?, method [ step, number, levelist?, param ]] ] # mnfc [ class, expver, stream=mnfc, date, time, domain - [ type, levtype=dp, origin, product, section, system?, method - [ step, number?, levelist?, latitude?, longitude?, range?, param ]] - + [ step, number?, levelist?, latitude?, longitude?, range?, param ]] [ type, levtype, origin, system?, method [ step, number?, levelist?, param ]] ] @@ -396,24 +669,28 @@ method: Integer; # mnfm [ class, expver, stream=mnfm, date, time, domain [ type, levtype, origin, system?, method - [ fcperiod, number?, levelist?, param ]]] + [ fcperiod, number?, levelist?, param ]] +] # mnfw [ class, expver, stream=mnfw, date, time, domain [ type, levtype, origin, system?, method - [ step, number?, param ]]] + [ step, number?, param ]] +] # ea/mnth [ class=ea, expver, stream=mnth, date, domain [ type, levtype - [ time, step?, levelist?, param ]]] + [ time, step?, levelist?, param ]] +] # mnth [ class, expver, stream=mnth, domain [ type=cl, levtype [ date: ClimateMonthly, time, levelist?, param ]] [ type, levtype - [ date , time, step?, levelist?, param ]]] + [ date , time, step?, levelist?, param ]] +] # mofc [ class, expver, stream=mofc, date, time, domain @@ -426,16 +703,19 @@ method: Integer; # mofm [ class, expver, stream=mofm, date, time, domain [ type, levtype, system?, method - [ fcperiod, number, levelist?, param ]]] + [ fcperiod, number, levelist?, param ]] +] # mmsa/msmm -[ class, expver, stream=mmsa, date, time, domain +[ class=od/rd/te/c3/uk/nl/fr/es/ch/de/pt/be/gr/ie/tr/no/fi/se/it, expver, stream=mmsa, date, time, domain [ type, levtype, origin, system?, method - [ fcmonth, number?, levelist?, param ]]] + [ fcmonth, number?, levelist?, param ]] +] -[ class, expver, stream=msmm, date, time, domain +[ class=od/rd/te/c3/uk/nl/fr/es/ch/de/pt/be/gr/ie/tr/no/fi/se/it, expver, stream=msmm, date, time, domain [ type, levtype, origin, system?, method - [ fcmonth, number?, levelist?, param ]]] + [ fcmonth, number?, levelist?, param ]] +] # ocea [ class, expver, stream=ocea, date, time, domain @@ -443,12 +723,30 @@ method: Integer; [ step, number, levelist?, latitude?, longitude?, range?, param ]] ] -#=# seas -[ class, expver, stream=seas, date, time, domain +# olda +[ class, expver, stream=olda, date, time, domain + [ type=tpa, levtype=o3d + [ number?, offsetdate, offsettime, step, levelist, param ]] + [ type=tpa, levtype=o2d + [ number?, offsetdate, offsettime, step, param ]] + [ type=an, levtype=o3d + [ number?, offsetdate, offsettime, levelist, param ]] + [ type=an, levtype=o2d + [ number?, offsetdate, offsettime, param ]] +] + +# ocda +[ class, expver, stream=ocda, date, domain + [ type=tpa, levtype=o2d/o3d, number? + [ time, step?,levelist?, param ]] + [ type=mfb + [ time, obsgroup, reportype ]] +] +# seas +[ class, expver, stream=seas, date, time, domain [ type, levtype=dp, product, section, system?, method [ step, number, levelist?, latitude?, longitude?, range?, param ]] - [ type, levtype, system?, method [ step, number, levelist?, param ]] ] @@ -456,96 +754,102 @@ method: Integer; # sfmm/smma [ class, expver, stream=sfmm/smma, date, time, domain [ type, levtype, system?, method - [ fcmonth, number?, levelist?, param ]]] + [ fcmonth, number?, levelist?, param ]] +] # supd [ class=od, expver, stream=supd, date, time, domain [ type, levtype, origin?, grid - [ step, levelist?, param ]]] + [ step, levelist?, param ]] +] # For era [ class, expver, stream=supd, date, time, domain [ type, levtype, grid- # The minus sign is here to consume 'grid', but don't index it - [ step, levelist?, param ]]] + [ step, levelist?, param ]] +] # swmm [ class, expver, stream=swmm, date, time, domain [ type, levtype, system?, method - [ fcmonth, number, param ]]] + [ fcmonth, number, param ]] +] # wamf [ class, expver, stream=wamf, date, time, domain [ type, levtype, system?, method - [ step, number?, param ]]] + [ step, number?, param ]] +] # ea/wamo [ class=ea, expver, stream=wamo, date, domain [ type, levtype - [ time, step?, param ]]] + [ time, step?, param ]] +] # wamo [ class, expver, stream=wamo, domain [ type=cl, levtype [ date: ClimateMonthly, time, param ]] [ type, levtype - [ date, time, step?, param ]]] + [ date, time, step?, param ]] +] # wamd [ class, expver, stream=wamd, date, domain [ type, levtype - [ param ]]] + [ param ]] +] # wasf [ class, expver, stream=wasf, date, time, domain [ type, levtype, system?, method - [ step, number, param ]]] + [ step, number, param ]] +] + # wmfm [ class, expver, stream=wmfm, date, time, domain [ type, levtype, system?, method - [ fcperiod, number, param ]]] + [ fcperiod, number, param ]] +] # moda [ class, expver, stream=moda, date, domain [ type, levtype - [ levelist?, param ]]] + [ levelist?, param ]] +] # msdc/mdfa/msda [ class, expver, stream=msdc/mdfa/msda, domain [ type, levtype - [ date, time?, step?, levelist?, param ]]] - - + [ date, time?, step?, levelist?, param ]] +] # seap [ class, expver, stream=seap, date, time, domain [ type=sv/svar, levtype, origin, method? [ step, leadtime, opttime, number, levelist?, param ]] - [ type=ef, levtype, origin [ step, levelist?, param, channel? ]] - [ type, levtype, origin [ step, levelist?, param ]] - - ] +] [ class, expver, stream=mmaf, date, time, domain [ type, levtype, origin, system?, method - [ step, number, levelist?, param ]] + [ step, number, levelist?, param ]] ] [ class, expver, stream=mmam, date, time, domain [ type, levtype, origin, system?, method - [ fcmonth, number, levelist?, param ]] + [ fcmonth, number, levelist?, param ]] ] - [ class, expver, stream=dacl, domain [ type=pb, levtype [ date: ClimateDaily, time, step, quantile, levelist?, param ]] [ type, levtype [ date: ClimateDaily, time, step, levelist?, param ]] - ] [ class, expver, stream=dacw, domain @@ -553,7 +857,6 @@ method: Integer; [ date: ClimateDaily, time, step, quantile, param ]] [ type, levtype [ date: ClimateDaily, time, step, param ]] - ] [ class, expver, stream=edmm/ewmm, date, time, domain @@ -572,19 +875,22 @@ method: Integer; [ class=mc/rd, expver, stream=gfas, date, time, domain [ type=ga, levtype [ step, param ]] - [ type=gsd [ param, ident, instrument ]] - ] # class is e2 [ class, expver, stream=espd, date, time, domain [ type, levtype, origin, grid - [ step, number, levelist?, param ]]] + [ step, number, levelist?, param ]] +] [ class=cs, expver, stream, date:Default, time, domain [ type, levtype - [ step, levelist?, param ]]] - + [ step, levelist?, param ]] +] +[ class=ce, expver, stream=efcl/wfcl, date, model, domain, hdate: Year + [ hdate: Month, type, levtype, origin + [ hdate: Date, levelist?, time, step, param ]] +] diff --git a/tests/fdb/test_service.cc b/tests/fdb/test_service.cc index 2c3c96d32..7eab110db 100644 --- a/tests/fdb/test_service.cc +++ b/tests/fdb/test_service.cc @@ -46,8 +46,7 @@ using namespace eckit::testing; using namespace fdb5; -namespace fdb { -namespace test { +namespace fdb::test { //---------------------------------------------------------------------------------------------------------------------- @@ -68,15 +67,14 @@ struct FixtureService { p["time"] = "0000"; p["type"] = "fc"; - modelParams_.push_back("130.128"); - modelParams_.push_back("138.128"); + modelParams_.push_back("130"); + modelParams_.push_back("138"); } void write_cycle(fdb5::Archiver& fdb, StringDict& p) { Translator str; - std::vector::iterator param = modelParams_.begin(); - for (; param != modelParams_.end(); ++param) { - p["param"] = *param; + for (const auto& param : modelParams_) { + p["param"] = param; p["levtype"] = "pl"; @@ -88,7 +86,7 @@ struct FixtureService { std::ostringstream data; data << "Raining cats and dogs -- " - << " param " << *param << " step " << step << " level " << level << std::endl; + << " param " << param << " step " << step << " level " << level << std::endl; std::string data_str = data.str(); fdb5::Key k{p}; @@ -131,7 +129,7 @@ CASE("test_fdb_stepunit_archive") { fdb5::ListIterator iter = fdb.list(r, true); fdb5::ListElement el; EXPECT(iter.next(el)); - EXPECT(el.combinedKey().get("step") == "60"); + EXPECT_EQUAL(el.combinedKey().get("step"), "60"); EXPECT(!iter.next(el)); } @@ -146,12 +144,12 @@ CASE("test_fdb_stepunit_archive") { fdb5::ListIterator iter = fdb.list(r, true); fdb5::ListElement el; EXPECT(iter.next(el)); - EXPECT(el.combinedKey().get("step") == "2"); + EXPECT_EQUAL(el.combinedKey().get("step"), "2"); EXPECT(!iter.next(el)); iter = fdb5::FDB{}.list(r, true); EXPECT(iter.next(el)); - EXPECT(el.combinedKey().get("step") == "2"); + EXPECT_EQUAL(el.combinedKey().get("step"), "2"); EXPECT(!iter.next(el)); } @@ -161,16 +159,16 @@ CASE("test_fdb_stepunit_archive") { fdb5::ListIterator iter = fdb.list(r, true); fdb5::ListElement el; EXPECT(iter.next(el)); - EXPECT(el.combinedKey().get("step") == "2"); + EXPECT_EQUAL(el.combinedKey().get("step"), "2"); EXPECT(iter.next(el)); - EXPECT(el.combinedKey().get("step") == "60"); + EXPECT_EQUAL(el.combinedKey().get("step"), "60"); EXPECT(!iter.next(el)); iter = fdb5::FDB{}.list(r, true); EXPECT(iter.next(el)); - EXPECT(el.combinedKey().get("step") == "2"); + EXPECT_EQUAL(el.combinedKey().get("step"), "2"); EXPECT(iter.next(el)); - EXPECT(el.combinedKey().get("step") == "60"); + EXPECT_EQUAL(el.combinedKey().get("step"), "60"); EXPECT(!iter.next(el)); } @@ -185,7 +183,7 @@ CASE("test_fdb_stepunit_archive") { fdb5::ListIterator iter = fdb.list(r, true); fdb5::ListElement el; EXPECT(iter.next(el)); - EXPECT(el.combinedKey().get("step") == "30m"); + EXPECT_EQUAL(el.combinedKey().get("step"), "30m"); EXPECT(!iter.next(el)); } @@ -199,9 +197,9 @@ CASE("test_fdb_stepunit_archive") { fdb5::ListIterator iter = fdb.list(r, true); fdb5::ListElement el; EXPECT(iter.next(el)); - EXPECT(el.combinedKey().get("step") == "30m"); + EXPECT_EQUAL(el.combinedKey().get("step"), "30m"); EXPECT(iter.next(el)); - EXPECT(el.combinedKey().get("step") == "2"); + EXPECT_EQUAL(el.combinedKey().get("step"), "2"); EXPECT(!iter.next(el)); } } @@ -251,9 +249,8 @@ CASE("test_fdb_service") { Buffer buffer(1_KiB); Translator str; - std::vector::iterator param = f.modelParams_.begin(); - for (; param != f.modelParams_.end(); ++param) { - f.p["param"] = *param; + for (const auto& param : f.modelParams_) { + f.p["param"] = param; f.p["levtype"] = "pl"; for (size_t step = 0; step < 2; ++step) { @@ -269,9 +266,9 @@ CASE("test_fdb_service") { auto it = fdb5::FDB{}.inspect(r); fdb5::ListElement el; EXPECT(it.next(el)); - EXPECT(el.combinedKey().get("param") == *param); - EXPECT(el.combinedKey().get("step") == str(step * 3)); - EXPECT(el.combinedKey().get("levelist") == str(level * 100)); + EXPECT_EQUAL(el.combinedKey().get("param"), param); + EXPECT_EQUAL(el.combinedKey().get("step"), str(step * 3)); + EXPECT_EQUAL(el.combinedKey().get("levelist"), str(level * 100)); EXPECT(!it.next(el)); std::unique_ptr dh(retriever.retrieve(r)); @@ -286,7 +283,7 @@ CASE("test_fdb_service") { std::ostringstream data; data << "Raining cats and dogs -- " - << " param " << *param << " step " << step << " level " << level << std::endl; + << " param " << param << " step " << step << " level " << level << std::endl; EXPECT(::memcmp(buffer, data.str().c_str(), data.str().size()) == 0); } @@ -299,9 +296,8 @@ CASE("test_fdb_service") { fdb5::FDB lister; Translator str; - std::vector::iterator param = f.modelParams_.begin(); - for (; param != f.modelParams_.end(); ++param) { - f.p["param"] = *param; + for (const auto& param : f.modelParams_) { + f.p["param"] = param; f.p["levtype"] = "pl"; f.p["step"] = str(0); f.p["levelist"] = str(0); @@ -431,9 +427,8 @@ CASE("test_fdb_service_subtoc") { f.p["expver"] = "0002"; Translator str; - std::vector::iterator param = f.modelParams_.begin(); - for (; param != f.modelParams_.end(); ++param) { - f.p["param"] = *param; + for (const auto& param : f.modelParams_) { + f.p["param"] = param; f.p["levtype"] = "pl"; for (size_t step = 0; step < 2; ++step) { @@ -457,7 +452,7 @@ CASE("test_fdb_service_subtoc") { std::ostringstream data; data << "Raining cats and dogs -- " - << " param " << *param << " step " << step << " level " << level << std::endl; + << " param " << param << " step " << step << " level " << level << std::endl; EXPECT(::memcmp(buffer, data.str().c_str(), data.str().size()) == 0); } @@ -472,10 +467,9 @@ CASE("test_fdb_service_subtoc") { f.p["expver"] = "0002"; Translator str; - std::vector::iterator param = f.modelParams_.begin(); - for (; param != f.modelParams_.end(); ++param) { + for (const auto& param : f.modelParams_) { - f.p["param"] = *param; + f.p["param"] = param; f.p["levtype"] = "pl"; f.p["step"] = str(0); f.p["levelist"] = str(0); @@ -584,7 +578,7 @@ CASE("schemaSerialisation") { std::ostringstream ss; clone->dump(ss); - EXPECT(original == ss.str()); + EXPECT_EQUAL(original, ss.str()); } if (filename.exists()) { filename.unlink(); @@ -593,8 +587,7 @@ CASE("schemaSerialisation") { //----------------------------------------------------------------------------- -} // namespace test -} // namespace fdb +} // namespace fdb::test int main(int argc, char** argv) { eckit::Main::initialise(argc, argv, "FDB_HOME"); diff --git a/tests/fdb/timespan/CMakeLists.txt b/tests/fdb/timespan/CMakeLists.txt new file mode 100644 index 000000000..9d8eaf8bf --- /dev/null +++ b/tests/fdb/timespan/CMakeLists.txt @@ -0,0 +1,7 @@ +ecbuild_configure_file( timespan.sh.in timespan.sh @ONLY ) +ecbuild_add_test( + TARGET fdb_test_timespan + LABELS mtg2 + TYPE SCRIPT + COMMAND timespan.sh + ENVIRONMENT "${test_environment}" ) diff --git a/tests/fdb/timespan/in.grib b/tests/fdb/timespan/in.grib new file mode 100644 index 0000000000000000000000000000000000000000..e22eff06021eff10ec19e97c4d3eb27813c89451 GIT binary patch literal 10872 zcmeI2J!ooY9LE2j=X$9vxfd^3kXBj?QXCw-tt}2xgloY;ih~q~P=sc1NWme4Lk0^O z95Og$5Sqau6o(8B85{z2$l#E{A%jB(hYSuG95M*$k8=V>j_2cj-~aRc z9^UtySKod6&Eq2pz22Tg@b3lF4@4>AC%4g$o)al!=QAOuG(9zb`Nhkxh=L;}db%kJ z_6CpdZa6Kuz2x>6|Nhrcx8Lb!e0lNHZ?o-AB0eUHQJfN##NE=Ap)BPnPX#JciON)= zD%Ge?4cet9?NN*NsZ9sep+oA@5%uVp`gB4AI;A0<(TL7zOcykvOPbOZ&FGrubVCce zr6t|bitcGm542%o;|NE2hhrS)1SdJgY0hw#bDZY_7rDe`u5guWT;~Swa+CMC#rxdm z1Mcu4cln5We9V15;Q^oWkk5F;=RD>Mp7144`HE+J&2zrt1>f?L?|8-cyygeq2#HBV zqOv0~iAzF~l9IG!Br7?|OF@cKlCo5!DmAG~Lw2Ppd(x79Y0H6h*0rI#+SEO5>Atr0Ks$Ps)Vip|`r!J6-9$uJu7TMrIbVsO?zH;+C+ar7Ue3%UaIzR+IChelk9gE~Jmzsvc+yjz_Kase=Xo!9(Mw+TidVhnb#M5tH+|1rzVB^6@QxpP z*N?pC$KLl7ANZ*c{me&x?qk33iC_BEuYBg$KKC16_^mJf&R2f#Yk%-fK!F93AR6oh zu^=8Kf@F{i(m^K32Du;~6oO(<3d%txsN%1JZzb$0;FlbZ$l%Bn&Pd?Q7_Jb-l`J6N z;L2;$FEQc^jQkuGn4uC= zRAhq6j8UNxDm6sK2B=&g73`ssT~xG#%C=GA7AoCD#T%%64GO402_-0^0A=K$kPMWP zf?^U-P7Df)LP=(%8z^fHg{`2pB^0-S^5#(B3`(3rkrOC$426!M)FBi*fO7j#a1ToE zLeU*4yA6f6p!6mb-+=OKa6ko4D8Ug0I3ov#WZ;w(9Fu@^VsKCtPBJCgz*%cJYz3z+ z;kX5yH-`gfaN-n>oWPl5ICKQ34&m4VoZE+kdvJ0Wj_$zOZ8*FIr#IpF2Ap350V*It z2}CG>3^@=Y15%_wj0DIL13{u7i2=?VkYx?RtU#J2h_e8B<{;1vB$|Rq6Od^PLXAMG zA&4~qx%wbj4E0A^x;x0hmIS4!hiKig)1Y{nA&?As~2x1RF?mh_K1IfE|2&x}|?)#wp z9%#P{>eoU4DpH_~G$~*w|JpO`I*+y0H<93g1LuMN@ z^r3Hqiay`&eY1U##0_y^u>IMee2MK({|FHPdSFdxHw44)f@&kgHgK8E@DFU-gH-p base.req < inst.req < 1h.req < content.inst < content.1h < expected.all < expected.inst < expected.1h < expected.all < expected.inst < expected.1h < expected.all < expected.inst < expected.1h < axes.out -echo '{"class":["rd"],"date":["20201102"],"domain":["g"],"expver":["xxxx"],"levelist":[""],"levtype":["sfc"],"param":["166"],"step":["6","9"],"stream":["oper"],"time":["0000"],"type":["an","fc"]}' > expected.out +echo '{"class":["rd"],"date":["20201102"],"domain":["g"],"expver":["xxxx"],"levtype":["sfc"],"param":["166"],"step":["6","9"],"stream":["oper"],"time":["0000"],"type":["an","fc"]}' > expected.out cat axes.out cat expected.out cmp axes.out expected.out fdb-axes class=rd,expver=xxxx,stream=oper,date=20201102,time=0000,domain=g > axes.out -echo 'IndexAxis[axis={class=(rd),date=(20201102),domain=(g),expver=(xxxx),levelist=(),levtype=(sfc),param=(166),step=(6,9),stream=(oper),time=(0000),type=(an,fc)}]' > expected.out +echo 'IndexAxis[axis={class=(rd),date=(20201102),domain=(g),expver=(xxxx),levtype=(sfc),param=(166),step=(6,9),stream=(oper),time=(0000),type=(an,fc)}]' > expected.out cat axes.out cat expected.out cmp axes.out expected.out @@ -62,7 +62,7 @@ cmp axes.out expected.out ####### Sub-selection by index fdb-axes class=rd,expver=xxxx,stream=oper,date=20201102,time=0000,domain=g,step=6 > axes.out -echo 'IndexAxis[axis={class=(rd),date=(20201102),domain=(g),expver=(xxxx),levelist=(),levtype=(sfc),param=(166),step=(6),stream=(oper),time=(0000),type=(an,fc)}]' > expected.out +echo 'IndexAxis[axis={class=(rd),date=(20201102),domain=(g),expver=(xxxx),levtype=(sfc),param=(166),step=(6),stream=(oper),time=(0000),type=(an,fc)}]' > expected.out cat axes.out cat expected.out cmp axes.out expected.out