-
Notifications
You must be signed in to change notification settings - Fork 13
Feature/fdb 327 fdb compare #165
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
0cf5628
f48b74f
a7baa4d
bbfaf0a
4f8952f
20fbf3c
d881e5b
86f64ff
d36ba97
b8b8491
8a63c45
7b7de8e
36f7f31
81d0033
80e58d7
9eaf3aa
9bafd3b
a1533d2
0bbd8ab
b15b50c
41ab0fb
74d19cb
c52b2bf
e42976e
9b6e1f6
b94f174
9d3c367
b59ff8e
eaeadf2
78721dc
09e5647
b643bc8
1b031b4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| /* | ||
| * (C) Copyright 2025- ECMWF. | ||
| * | ||
| * This software is licensed under the terms of the Apache Licence Version 2.0 | ||
| * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. | ||
| * In applying this licence, ECMWF does not waive the privileges and immunities | ||
| * granted to it by virtue of its status as an intergovernmental organisation nor | ||
| * does it submit to any jurisdiction. | ||
| */ | ||
| #include "common/ComparisonMap.h" | ||
|
|
||
|
|
||
| namespace compare { | ||
|
|
||
| bool isSubset(const KeyValueMap& a, const KeyValueMap& b) { | ||
| for (const auto& kv : a) { | ||
| auto it = b.find(kv.first); | ||
| if (it == b.end() || it->second != kv.second) | ||
| return false; | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
|
|
||
| DataIndex assembleCompareMap(fdb5::FDB& fdb, const fdb5::FDBToolRequest& req, const KeyValueMap& ignore) { | ||
| DataIndex out; | ||
|
|
||
| auto list = fdb.list(req); | ||
| fdb5::ListElement elem; | ||
|
|
||
| std::cout << req << std::endl; | ||
| std::cout << ignore << std::endl; | ||
| while (list.next(elem)) { | ||
| KeyValueMap km; | ||
| for (const auto& bit : elem.keys()) { | ||
| auto d = bit.keyDict(); | ||
| km.insert(d.begin(), d.end()); | ||
| } | ||
| if (ignore.empty() || !isSubset(ignore, km)) { | ||
| out.emplace(km, DataLocation{elem.location().uri().path(), static_cast<long long>(elem.location().offset()), | ||
| static_cast<long long>(elem.location().length())}); | ||
| } | ||
| } | ||
| std::cout << "[LOG] FDB request: " << req << " resulted in " << out.size() << " entries.\n"; | ||
| return out; | ||
| } | ||
| } // namespace compare |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| /* | ||
| * (C) Copyright 2025- ECMWF. | ||
| * | ||
| * This software is licensed under the terms of the Apache Licence Version 2.0 | ||
| * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. | ||
| * In applying this licence, ECMWF does not waive the privileges and immunities | ||
| * granted to it by virtue of its status as an intergovernmental organisation nor | ||
| * does it submit to any jurisdiction. | ||
| */ | ||
| #pragma once | ||
| #include <fdb5/api/FDB.h> | ||
| #include <fdb5/api/helpers/FDBToolRequest.h> | ||
| #include "DataMap.h" | ||
|
|
||
| namespace compare { | ||
|
|
||
| /// Runs a request on a fdb to create a list of filtered entries to compared on. | ||
| /// | ||
| /// @param fdb FDB on which to operate on | ||
| /// @param req Request which performs a selection on the fdb | ||
| /// @param ignore Map of key-value pairs to ignore | ||
| /// @return filtered DataIndex | ||
| DataIndex assembleCompareMap(fdb5::FDB& fdb, const fdb5::FDBToolRequest& req, const KeyValueMap& ignore); | ||
|
|
||
| } // namespace compare |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,137 @@ | ||
| /* | ||
| * (C) Copyright 2025- ECMWF. | ||
| * | ||
| * This software is licensed under the terms of the Apache Licence Version 2.0 | ||
| * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. | ||
| * In applying this licence, ECMWF does not waive the privileges and immunities | ||
| * granted to it by virtue of its status as an intergovernmental organisation nor | ||
| * does it submit to any jurisdiction. | ||
| */ | ||
| #include "DataMap.h" | ||
|
|
||
| #include <sstream> | ||
|
|
||
| namespace compare { | ||
|
|
||
| std::ostream& operator<<(std::ostream& os, const KeyValueMap& km) { | ||
| os << "{"; | ||
| for (const auto& [k, v] : km) { | ||
| os << k << "=" << v << ", "; | ||
| } | ||
| os << "}"; | ||
| return os; | ||
| } | ||
|
|
||
| std::ostream& operator<<(std::ostream& os, const KeyDiffMap& km) { | ||
| os << "{"; | ||
| for (const auto& [k, v] : km) { | ||
| os << k << "=" << "(" << (v.first ? *v.first : "<MISSING>") << ", " << (v.second ? *v.second : "<MISSING>") | ||
| << ")" << ", "; | ||
| } | ||
| os << "}"; | ||
| return os; | ||
| } | ||
|
|
||
| std::ostream& operator<<(std::ostream& os, const KeySet& km) { | ||
| os << "{"; | ||
| for (const auto& k : km) { | ||
| os << k << ", "; | ||
| } | ||
| os << "}"; | ||
| return os; | ||
| } | ||
|
|
||
| std::ostream& operator<<(std::ostream& os, const DataLocation& loc) { | ||
| return os << "(" << loc.path << ", " << loc.offset << ", " << loc.length << ")"; | ||
| } | ||
|
|
||
| std::ostream& operator<<(std::ostream& os, const DataIndex& idx) { | ||
| for (const auto& [km, loc] : idx) { | ||
| os << "Key: " << km << " -> Value: " << loc << "\n"; | ||
| } | ||
| return os; | ||
| } | ||
|
|
||
|
|
||
| void parseKeyValues(KeyValueMap& container, const std::string& keyValueStr) { | ||
| std::istringstream stream(keyValueStr); | ||
| std::string entry; | ||
|
|
||
| while (std::getline(stream, entry, ',')) { | ||
| std::istringstream pairStream(entry); | ||
| std::string key, value; | ||
| if (std::getline(pairStream, key, '=') && std::getline(pairStream, value)) { | ||
| container[key] = value; // Update or insert key-value pair | ||
| } | ||
| else { | ||
| std::cerr << "Invalid key-value pair: " << entry << std::endl; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| KeyValueMap parseKeyValues(const std::string& keyValueStr) { | ||
| KeyValueMap container; | ||
| parseKeyValues(container, keyValueStr); | ||
| return container; | ||
| } | ||
|
|
||
| void parseKeySet(KeySet& container, const std::string& keyStr) { | ||
| std::istringstream stream(keyStr); | ||
| std::string entry; | ||
|
|
||
| while (std::getline(stream, entry, ',')) { | ||
| container.insert(entry); // Insert the whole entry as a single string | ||
| } | ||
| } | ||
|
|
||
| KeySet parseKeySet(const std::string& keyStr) { | ||
| KeySet container; | ||
| parseKeySet(container, keyStr); | ||
| return container; | ||
| } | ||
|
|
||
| compare::KeyDiffMap requestDiff(const KeyValueMap& l, const KeyValueMap& r) { | ||
| compare::KeyDiffMap res; | ||
| for (const auto& [lk, lv] : l) { | ||
| auto search = r.find(lk); | ||
| if (search != r.end()) { | ||
| if (search->second != lv) { | ||
| res.insert({lk, {lv, search->second}}); | ||
| } | ||
| } | ||
| else { | ||
| res.insert({lk, {lv, {}}}); | ||
| } | ||
| } | ||
|
|
||
| for (const auto& [rk, rv] : r) { | ||
| auto search = l.find(rk); | ||
| if (search == r.end()) { | ||
| res.insert({rk, {{}, rv}}); | ||
| } | ||
| } | ||
| return res; | ||
| } | ||
|
|
||
|
|
||
| KeyValueMap applyKeyDiff(KeyValueMap k, const KeyDiffMap& diff, bool swapDiff) { | ||
| for (const auto& [field, val_pair] : diff) { | ||
| const auto& val = swapDiff ? val_pair.first : val_pair.second; | ||
| if (val) { | ||
| auto it = k.find(field); | ||
| if (it != k.end()) { | ||
| it->second = *val; // replace value | ||
| } | ||
| else { | ||
| k.insert({field, *val}); | ||
| } | ||
| } | ||
| else { | ||
| // Delete | ||
| k.erase(field); | ||
| } | ||
| } | ||
| return k; // return modified copy | ||
| }; | ||
|
|
||
| } // namespace compare | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| /* | ||
| * (C) Copyright 2025- ECMWF. | ||
| * | ||
| * This software is licensed under the terms of the Apache Licence Version 2.0 | ||
| * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. | ||
| * In applying this licence, ECMWF does not waive the privileges and immunities | ||
| * granted to it by virtue of its status as an intergovernmental organisation nor | ||
| * does it submit to any jurisdiction. | ||
| */ | ||
| #pragma once | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This file is called DataMap - but there is no class (nor anything else) called DataMap in it. |
||
| #include <functional> | ||
| #include <iostream> | ||
| #include <map> | ||
| #include <optional> | ||
| #include <string> | ||
| #include <unordered_map> | ||
| #include <unordered_set> | ||
|
|
||
| namespace compare { | ||
|
|
||
| struct DataLocation { | ||
| std::string path; | ||
| long long offset = 0; | ||
| long long length = 0; | ||
| }; | ||
|
|
||
| using KeyValueMap = std::map<std::string, std::string>; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For the namespace, I think that these names are too generic. They would be appropriate inside (say) a templated class. But here...
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is especially true given that you have both DataMap and ComparisonMap headers in the project. What does "MapHash" or "KeyValueMap" belong to in that context? |
||
| using ValueDiff = std::pair<std::optional<std::string>, std::optional<std::string>>; | ||
| using KeyDiffMap = std::map<std::string, ValueDiff>; | ||
|
|
||
| using KeySet = std::unordered_set<std::string>; | ||
|
|
||
| struct MapHash { | ||
| size_t operator()(const KeyValueMap& m) const noexcept { | ||
| size_t h = 0; | ||
| std::hash<std::string> hs; | ||
| for (const auto& kv : m) { | ||
| h ^= (hs(kv.first) * 1315423911u) ^ hs(kv.second); | ||
| } | ||
| return h; | ||
| } | ||
| }; | ||
|
|
||
| struct MapEqual { | ||
| bool operator()(const KeyValueMap& a, const KeyValueMap& b) const noexcept { return a == b; } | ||
| }; | ||
|
|
||
| using DataIndex = std::unordered_map<KeyValueMap, DataLocation, MapHash, MapEqual>; | ||
|
|
||
| /// Print a KeyValueMap | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unclear why these warrant a comment, when they are absolutely clear what they do, but there is no commentary/docs about what the purpose of these classes is. |
||
| std::ostream& operator<<(std::ostream& os, const KeyValueMap& km); | ||
|
|
||
| /// Print a KeyDiffMap | ||
| std::ostream& operator<<(std::ostream& os, const KeyDiffMap& km); | ||
|
|
||
| /// Print a KeySet | ||
| std::ostream& operator<<(std::ostream& os, const KeySet& km); | ||
|
|
||
| /// Print a DataLocation | ||
| std::ostream& operator<<(std::ostream& os, const DataLocation& loc); | ||
|
|
||
| /// Print a DataIndex | ||
| std::ostream& operator<<(std::ostream& os, const DataIndex& idx); | ||
|
|
||
|
|
||
| void parseKeyValues(KeyValueMap& container, const std::string& keyValueStr); | ||
| KeyValueMap parseKeyValues(const std::string& keyValueStr); | ||
|
|
||
| void parseKeySet(KeySet& container, const std::string& keyValueStr); | ||
| KeySet parseKeySet(const std::string& keyValueStr); | ||
|
|
||
| compare::KeyDiffMap requestDiff(const KeyValueMap& l, const KeyValueMap& r); | ||
|
|
||
| /// @param km Map of keys with values | ||
| /// @param diff Map of keys with differences | ||
| /// @param swapPair Optional - If false the second pair of the difference is put in the resulting request. | ||
| // If true the first one is used. | ||
| /// @return New KeyValueMap with differences applied | ||
| KeyValueMap applyKeyDiff(KeyValueMap km, const KeyDiffMap& diff, bool swapPair = false); | ||
|
|
||
| } // namespace compare | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug here.
searchcomes froml.findbut is being compared againstr.end. Iterators are not comparable between containers.