diff options
author | Sergey Yershov <syershov@maps.me> | 2016-12-07 17:38:47 +0300 |
---|---|---|
committer | Sergey Yershov <syershov@maps.me> | 2016-12-09 13:39:57 +0300 |
commit | d67c82407eee4f8b5f7ad1c493497476d83c4529 (patch) | |
tree | bab0d31bce50df147b56fdf96d77fb40b08a648b /traffic | |
parent | fc8189106a38692a746597ebb9548bbcd218068e (diff) |
HEAD request for check traffic update
Diffstat (limited to 'traffic')
-rw-r--r-- | traffic/traffic_info.cpp | 88 | ||||
-rw-r--r-- | traffic/traffic_info.hpp | 16 | ||||
-rw-r--r-- | traffic/traffic_tests/traffic_info_test.cpp | 9 |
3 files changed, 73 insertions, 40 deletions
diff --git a/traffic/traffic_info.cpp b/traffic/traffic_info.cpp index d3346adb99..23138ba085 100644 --- a/traffic/traffic_info.cpp +++ b/traffic/traffic_info.cpp @@ -75,6 +75,8 @@ string MakeRemoteURL(string const & name, uint64_t version) ss << UrlEncode(name) << TRAFFIC_FILE_EXTENSION; return ss.str(); } + +char const kETag[] = "Etag"; } // namespace // TrafficInfo::RoadSegmentId ----------------------------------------------------------------- @@ -133,10 +135,10 @@ void TrafficInfo::SetTrafficKeysForTesting(vector<RoadSegmentId> const & keys) m_availability = Availability::IsAvailable; } -bool TrafficInfo::ReceiveTrafficData() +bool TrafficInfo::ReceiveTrafficData(string & etag) { vector<SpeedGroup> values; - if (!ReceiveTrafficValues(values)) + if (!ReceiveTrafficValues(etag, values)) return false; return UpdateTrafficData(values); @@ -396,48 +398,28 @@ bool TrafficInfo::ReceiveTrafficKeys() return true; } -bool TrafficInfo::ReceiveTrafficValues(vector<SpeedGroup> & values) +bool TrafficInfo::ReceiveTrafficValues(string & etag, vector<SpeedGroup> & values) { auto const & info = m_mwmId.GetInfo(); if (!info) return false; - string const url = MakeRemoteURL(info->GetCountryName(), info->GetVersion()); + uint64_t const version = info->GetVersion(); + string const url = MakeRemoteURL(info->GetCountryName(), version); if (url.empty()) return false; - vector<uint8_t> contents; - int errorCode; - if (!ReadRemoteFile(url, contents, errorCode)) - { - if (errorCode == 404) - { - string const result(reinterpret_cast<char*>(contents.data()), contents.size()); - - int64_t version = 0; - strings::to_int64(result.c_str(), version); - - if (version > info->GetVersion() && version <= m_currentDataVersion) - m_availability = Availability::ExpiredData; - else if (version > m_currentDataVersion) - m_availability = Availability::ExpiredApp; - else - m_availability = Availability::NoData; - } - else - { - m_availability = Availability::Unknown; - - alohalytics::LogEvent( - "$TrafficNetworkError", - alohalytics::TStringMap({{"code", strings::to_string(errorCode)}})); - } - return false; - } + platform::HttpClient request(url); + request.LoadHeaders(true); + request.SetRawHeader("If-None-Match", etag); + if (!request.RunHttpRequest() || request.ErrorCode() != 200) + return ProcessFailure(request, version); try { + string const & response = request.ServerResponse(); + vector<uint8_t> contents(response.cbegin(), response.cend()); DeserializeTrafficValues(contents, values); } catch (Reader::Exception const & e) @@ -453,6 +435,12 @@ bool TrafficInfo::ReceiveTrafficValues(vector<SpeedGroup> & values) return false; } + // Update ETag for this MWM. + auto const & headers = request.GetHeaders(); + auto const it = headers.find(kETag); + if (it != headers.end()) + etag = it->second; + m_availability = Availability::IsAvailable; return true; } @@ -480,13 +468,45 @@ bool TrafficInfo::UpdateTrafficData(vector<SpeedGroup> const & values) return true; } +bool TrafficInfo::ProcessFailure(platform::HttpClient const & request, uint64_t const mwmVersion) +{ + switch (request.ErrorCode()) + { + case 404: /* Not Found */ + { + int64_t version = 0; + strings::to_int64(request.ServerResponse().c_str(), version); + + if (version > mwmVersion && version <= m_currentDataVersion) + m_availability = Availability::ExpiredData; + else if (version > m_currentDataVersion) + m_availability = Availability::ExpiredApp; + else + m_availability = Availability::NoData; + return false; + } + case 304: /* Not Modified */ + { + m_availability = Availability::IsAvailable; + return true; + } + } + + m_availability = Availability::Unknown; + alohalytics::LogEvent( + "$TrafficNetworkError", + alohalytics::TStringMap({{"code", strings::to_string(request.ErrorCode())}})); + + return false; +} + string DebugPrint(TrafficInfo::RoadSegmentId const & id) { string const dir = - id.m_dir == TrafficInfo::RoadSegmentId::kForwardDirection ? "Forward" : "Backward"; + id.m_dir == TrafficInfo::RoadSegmentId::kForwardDirection ? "Forward" : "Backward"; ostringstream oss; oss << "RoadSegmentId [" - << " fid = " << id.m_fid << " idx = " << id.m_idx << " dir = " << dir << " ]"; + << " fid = " << id.m_fid << " idx = " << id.m_idx << " dir = " << dir << " ]"; return oss.str(); } } // namespace traffic diff --git a/traffic/traffic_info.hpp b/traffic/traffic_info.hpp index 4c0ace5d21..23cbb268f0 100644 --- a/traffic/traffic_info.hpp +++ b/traffic/traffic_info.hpp @@ -9,6 +9,11 @@ #include "std/shared_ptr.hpp" #include "std/vector.hpp" +namespace platform +{ +class HttpClient; +} + namespace traffic { // This class is responsible for providing the real-time @@ -74,10 +79,13 @@ public: static TrafficInfo BuildForTesting(Coloring && coloring); void SetTrafficKeysForTesting(vector<RoadSegmentId> const & keys); - // Fetches the latest traffic data from the server and updates the coloring. + // Fetches the latest traffic data from the server and updates the coloring and ETag. // Construct the url by passing an MwmId. + // The ETag or entity tag is part of HTTP, the protocol for the World Wide Web. + // It is one of several mechanisms that HTTP provides for web cache validation, + // which allows a client to make conditional requests. // *NOTE* This method must not be called on the UI thread. - bool ReceiveTrafficData(); + bool ReceiveTrafficData(string & etag); // Returns the latest known speed group by a feature segment's id // or SpeedGroup::Unknown if there is no information about the segment. @@ -119,11 +127,13 @@ private: // Returns true and updates m_coloring if the values are read successfully and // their number is equal to the number of keys. // Otherwise, returns false and does not change m_coloring. - bool ReceiveTrafficValues(vector<SpeedGroup> & values); + bool ReceiveTrafficValues(string & etag, vector<SpeedGroup> & values); // Updates the coloring and changes the availability status if needed. bool UpdateTrafficData(vector<SpeedGroup> const & values); + bool ProcessFailure(platform::HttpClient const & request, uint64_t const mwmVersion); + // The mapping from feature segments to speed groups (see speed_groups.hpp). Coloring m_coloring; diff --git a/traffic/traffic_tests/traffic_info_test.cpp b/traffic/traffic_tests/traffic_info_test.cpp index 45f962c65a..d804824580 100644 --- a/traffic/traffic_tests/traffic_info_test.cpp +++ b/traffic/traffic_tests/traffic_info_test.cpp @@ -44,21 +44,24 @@ UNIT_TEST(TrafficInfo_RemoteFile) auto const & r = mwmSet.Register(platform::LocalCountryFile::MakeForTesting("traffic_data_test")); TrafficInfo trafficInfo(r.first, r.first.GetInfo()->GetVersion()); - TEST(trafficInfo.ReceiveTrafficData(), ()); + string etag; + TEST(trafficInfo.ReceiveTrafficData(etag), ()); } { TestMwmSet mwmSet; auto const & r = mwmSet.Register(platform::LocalCountryFile::MakeForTesting("traffic_data_test2")); TrafficInfo trafficInfo(r.first, r.first.GetInfo()->GetVersion()); - TEST(!trafficInfo.ReceiveTrafficData(), ()); + string etag; + TEST(!trafficInfo.ReceiveTrafficData(etag), ()); } { TestMwmSet mwmSet; auto const & r = mwmSet.Register(platform::LocalCountryFile::MakeForTesting("traffic_data_test", 101010)); TrafficInfo trafficInfo(r.first, r.first.GetInfo()->GetVersion()); - TEST(trafficInfo.ReceiveTrafficData(), ()); + string etag; + TEST(trafficInfo.ReceiveTrafficData(etag), ()); } } |