diff options
author | VladiMihaylenko <vxmihaylenko@gmail.com> | 2017-08-07 11:06:47 +0300 |
---|---|---|
committer | Arsentiy Milchakov <milcars@mapswithme.com> | 2017-08-08 14:36:03 +0300 |
commit | 5ef2109e8ebc7fb5afc61d5d6478cdb754fcdae3 (patch) | |
tree | 1c4cb8fa24bb9b8485c230543c333866622433d5 /storage | |
parent | 4e270ecaf9c49ad9c03201dc776c53333ce81744 (diff) |
Added diff scheme checker.
Diffstat (limited to 'storage')
-rw-r--r-- | storage/CMakeLists.txt | 3 | ||||
-rw-r--r-- | storage/diff_scheme_checker.cpp | 131 | ||||
-rw-r--r-- | storage/diff_scheme_checker.hpp | 27 | ||||
-rw-r--r-- | storage/diff_types.hpp | 24 | ||||
-rw-r--r-- | storage/storage.pro | 3 |
5 files changed, 188 insertions, 0 deletions
diff --git a/storage/CMakeLists.txt b/storage/CMakeLists.txt index 1048cd0ff3..d8799ac5a0 100644 --- a/storage/CMakeLists.txt +++ b/storage/CMakeLists.txt @@ -15,6 +15,9 @@ set( country_name_getter.hpp country_polygon.hpp country_tree.hpp + diff_scheme_checker.cpp + diff_scheme_checker.hpp + diff_types.hpp downloader_search_params.hpp downloading_policy.cpp downloading_policy.hpp diff --git a/storage/diff_scheme_checker.cpp b/storage/diff_scheme_checker.cpp new file mode 100644 index 0000000000..d5b16ac909 --- /dev/null +++ b/storage/diff_scheme_checker.cpp @@ -0,0 +1,131 @@ +#include "storage/diff_scheme_checker.hpp" + +#include "platform/http_client.hpp" +#include "platform/platform.hpp" + +#include "base/logging.hpp" +#include "base/thread.hpp" + +#include <memory> +#include <utility> + +#include "3party/jansson/myjansson.hpp" + +#include "private.h" + +using namespace std; + +namespace +{ +using namespace diff_scheme; + +char const * const kMaxVersionKey = "max_version"; +char const * const kMwmsKey = "mwms"; +char const * const kNameKey = "name"; +char const * const kSizeKey = "size"; +char const * const kVersionKey = "version"; + +string SerializeCheckerData(Checker::LocalMapsInfo const & info) +{ + auto mwmsArrayNode = my::NewJSONArray(); + for (auto const & nameAndVersion : info.m_localMaps) + { + auto node = my::NewJSONObject(); + ToJSONObject(*node, kNameKey, nameAndVersion.first); + ToJSONObject(*node, kVersionKey, nameAndVersion.second); + json_array_append_new(mwmsArrayNode.get(), node.release()); + } + + auto const root = my::NewJSONObject(); + json_object_set_new(root.get(), kMwmsKey, mwmsArrayNode.release()); + ToJSONObject(*root, kMaxVersionKey, info.m_currentDataVersion); + unique_ptr<char, JSONFreeDeleter> buffer(json_dumps(root.get(), JSON_COMPACT | JSON_ENSURE_ASCII)); + return buffer.get(); +} + +NameFileMap DeserializeResponse(string const & response, Checker::NameVersionMap const & nameVersionMap) +{ + if (response.empty()) + { + LOG(LERROR, ("Diff responce shouldn't be empty.")); + return {}; + } + + my::Json const json(response.c_str()); + if (json.get() == nullptr) + return {}; + + auto const root = json_object_get(json.get(), kMwmsKey); + if (root == nullptr || !json_is_array(root)) + return {}; + + auto const size = json_array_size(root); + if (size == 0 || size != nameVersionMap.size()) + { + LOG(LERROR, ("Diff list size in response must be equal to mwm list size in request.")); + return {}; + } + + NameFileMap diffs; + + for (size_t i = 0; i < size; ++i) + { + auto const node = json_array_get(root, i); + + if (!node) + { + LOG(LERROR, ("Incorrect server response.")); + return diffs; + } + + string name; + FromJSONObject(node, kNameKey, name); + int64_t size; + FromJSONObject(node, kSizeKey, size); + // Invalid size. The diff is not available. + if (size == -1) + continue; + + if (nameVersionMap.find(name) == nameVersionMap.end()) + { + LOG(LERROR, ("Incorrect country name in response:", name)); + return {}; + } + + FileInfo info(size, nameVersionMap.at(name)); + diffs.emplace(move(name), move(info)); + } + + return diffs; +} +} // namespace + +namespace diff_scheme +{ +// static +void Checker::Check(LocalMapsInfo const & info, Callback const & fn) +{ + // TODO(Vlad): Log falling back to old scheme. + if (info.m_localMaps.empty()) + { + fn({}); + return; + } + + threads::SimpleThread thread([info, fn] { + platform::HttpClient request(DIFF_LIST_URL); + // TODO(Vlad): Check request's time. + string const body = SerializeCheckerData(info); + ASSERT(!body.empty(), ()); + request.SetBodyData(body, "application/json"); + NameFileMap diffs; + if (request.RunHttpRequest() && !request.WasRedirected() && request.ErrorCode() == 200) + diffs = DeserializeResponse(request.ServerResponse(), info.m_localMaps); + + GetPlatform().RunOnGuiThread([fn, diffs] { + fn(diffs); + }); + }); + thread.detach(); +} +} // namespace diff_scheme diff --git a/storage/diff_scheme_checker.hpp b/storage/diff_scheme_checker.hpp new file mode 100644 index 0000000000..c338604769 --- /dev/null +++ b/storage/diff_scheme_checker.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include "storage/diff_types.hpp" + +#include <cstdint> +#include <functional> +#include <string> +#include <unordered_map> + +namespace diff_scheme +{ +class Checker final +{ +public: + using NameVersionMap = std::unordered_map<std::string, uint64_t>; + + struct LocalMapsInfo final + { + uint64_t m_currentDataVersion = 0; + NameVersionMap m_localMaps; + }; + + using Callback = std::function<void(NameFileMap const & diffs)>; + + static void Check(LocalMapsInfo const & info, Callback const & fn); +}; +} // namespace diff_scheme diff --git a/storage/diff_types.hpp b/storage/diff_types.hpp new file mode 100644 index 0000000000..9f01d8f079 --- /dev/null +++ b/storage/diff_types.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include <cstdint> +#include <string> +#include <unordered_map> + +namespace diff_scheme +{ +enum class Status +{ + Undefined, + NotAvailable, + Available +}; + +struct FileInfo final +{ + FileInfo(uint64_t size, uint64_t version) : m_size(size), m_version(version) {} + uint64_t m_size; + uint64_t m_version; +}; + +using NameFileMap = std::unordered_map<std::string, FileInfo>; +} // namespace diff_scheme diff --git a/storage/storage.pro b/storage/storage.pro index e0ac68c67f..818b511ab5 100644 --- a/storage/storage.pro +++ b/storage/storage.pro @@ -17,6 +17,8 @@ HEADERS += \ country_name_getter.hpp \ country_polygon.hpp \ country_tree.hpp \ + diff_scheme_checker.hpp \ + diff_types.hpp \ downloader_search_params.hpp \ downloading_policy.hpp \ http_map_files_downloader.hpp \ @@ -32,6 +34,7 @@ SOURCES += \ country_decl.cpp \ country_info_getter.cpp \ country_name_getter.cpp \ + diff_scheme_checker.cpp \ downloading_policy.cpp \ http_map_files_downloader.cpp \ index.cpp \ |