From 4d3c5ed5d54b4378a6de69fee5a5890e566f516e Mon Sep 17 00:00:00 2001 From: Arsentiy Milchakov Date: Mon, 11 Dec 2017 15:58:40 +0300 Subject: [PATCH] [booking] filter availability. Check from cache before show usermark --- map/booking_filter.cpp | 34 +++++++++++++++++++++++++--------- map/booking_filter.hpp | 11 +++++++++++ map/booking_filter_cache.cpp | 10 ++++++++++ map/booking_filter_cache.hpp | 4 ++++ map/framework.cpp | 27 ++++++++++++++++++++++++++- map/framework.hpp | 2 ++ map/search_api.cpp | 3 +++ map/search_api.hpp | 5 +++++ 8 files changed, 86 insertions(+), 10 deletions(-) diff --git a/map/booking_filter.cpp b/map/booking_filter.cpp index 5743be63fd..dcec491040 100644 --- a/map/booking_filter.cpp +++ b/map/booking_filter.cpp @@ -158,9 +158,12 @@ void Filter::FilterAvailability(search::Results const & results, { GetPlatform().RunTask(Platform::Thread::File, [this, results, params]() { + std::lock_guard lock(m_mutex); + auto const & cb = params.m_callback; ASSERT(params.m_params.m_hotelIds.empty(), ()); + m_currentParams.m_hotelIds.clear(); if (m_currentParams != params.m_params) { @@ -185,20 +188,33 @@ void Filter::FilterAvailability(search::Results const & results, auto const apiCallback = [cb, hotelToResults, availabilityCache](std::vector hotelIds) mutable { - GetPlatform().RunTask(Platform::Thread::File, - [cb, hotelToResults, availabilityCache, hotelIds]() mutable - { - search::Results results; - std::sort(hotelIds.begin(), hotelIds.end()); - UpdateCache(hotelToResults, hotelIds, *availabilityCache); - FillResults(std::move(hotelToResults), hotelIds, *availabilityCache, results); - cb(results); - }); + search::Results results; + std::sort(hotelIds.begin(), hotelIds.end()); + UpdateCache(hotelToResults, hotelIds, *availabilityCache); + FillResults(std::move(hotelToResults), hotelIds, *availabilityCache, results); + cb(results); }; m_api.GetHotelAvailability(m_currentParams, apiCallback); m_availabilityCache->RemoveOutdated(); }); } + +availability::Cache::HotelStatus Filter::GetHotelAvailabilityStatus(std::string const & hotelId) +{ + // Cache is thread-safe, no need to lock mutex. + return m_availabilityCache->Get(hotelId); +} + +void Filter::OnParamsUpdated(AvailabilityParams const & params) +{ + std::lock_guard lock(m_mutex); + + if (m_currentParams != params) + { + m_currentParams = params; + m_availabilityCache = std::make_shared(); + } +} } // namespace filter } // namespace booking diff --git a/map/booking_filter.hpp b/map/booking_filter.hpp index 0288405bae..5e475f5249 100644 --- a/map/booking_filter.hpp +++ b/map/booking_filter.hpp @@ -3,7 +3,10 @@ #include "map/booking_filter_availability_params.hpp" #include "map/booking_filter_cache.hpp" +#include "base/macros.hpp" + #include +#include class Index; @@ -18,6 +21,7 @@ class Api; namespace filter { +// NOTE: this class IS thread-safe. class Filter { public: @@ -26,6 +30,10 @@ public: void FilterAvailability(search::Results const & results, availability::internal::Params const & params); + void OnParamsUpdated(AvailabilityParams const & params); + + availability::Cache::HotelStatus GetHotelAvailabilityStatus(std::string const & hotelId); + private: Index const & m_index; Api const & m_api; @@ -35,6 +43,9 @@ private: CachePtr m_availabilityCache = std::make_shared(); AvailabilityParams m_currentParams; + std::mutex m_mutex; + + DISALLOW_COPY_AND_MOVE(Filter); }; } // namespace filter } // namespace booking diff --git a/map/booking_filter_cache.cpp b/map/booking_filter_cache.cpp index 32dc68d6ae..6af551f226 100644 --- a/map/booking_filter_cache.cpp +++ b/map/booking_filter_cache.cpp @@ -15,6 +15,8 @@ Cache::Cache(size_t maxCount, size_t expiryPeriodSeconds) Cache::HotelStatus Cache::Get(std::string const & hotelId) { + std::lock_guard lock(m_mutex); + HotelStatus result = Get(m_notReadyHotels, hotelId); if (result == HotelStatus::Absent) @@ -25,6 +27,8 @@ Cache::HotelStatus Cache::Get(std::string const & hotelId) void Cache::Reserve(std::string const & hotelId) { + std::lock_guard lock(m_mutex); + ASSERT(m_hotelToStatus.find(hotelId) == m_hotelToStatus.end(), ()); m_notReadyHotels.emplace(hotelId, Item()); @@ -32,6 +36,8 @@ void Cache::Reserve(std::string const & hotelId) void Cache::Insert(std::string const & hotelId, HotelStatus const s) { + std::lock_guard lock(m_mutex); + ASSERT_NOT_EQUAL(s, HotelStatus::NotReady, ("Please, use Cache::Reserve method for HotelStatus::NotReady")); @@ -44,6 +50,8 @@ void Cache::Insert(std::string const & hotelId, HotelStatus const s) void Cache::RemoveOutdated() { + std::lock_guard lock(m_mutex); + if (m_expiryPeriodSeconds == 0) return; @@ -53,6 +61,8 @@ void Cache::RemoveOutdated() void Cache::Clear() { + std::lock_guard lock(m_mutex); + m_hotelToStatus.clear(); m_notReadyHotels.clear(); } diff --git a/map/booking_filter_cache.hpp b/map/booking_filter_cache.hpp index 9e91dbddfb..3c1045e36c 100644 --- a/map/booking_filter_cache.hpp +++ b/map/booking_filter_cache.hpp @@ -4,6 +4,7 @@ #include #include +#include namespace booking { @@ -11,6 +12,7 @@ namespace filter { namespace availability { +// NOTE: this class IS thread-safe. class Cache { public: @@ -65,6 +67,8 @@ private: // Do not use aging when |m_expiryPeriodSeconds| is equal to zero. size_t const m_expiryPeriodSeconds = 60; + std::mutex m_mutex; + DISALLOW_COPY_AND_MOVE(Cache); }; diff --git a/map/framework.cpp b/map/framework.cpp index e92eb34e1a..4c5ae91420 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -1639,7 +1639,7 @@ void Framework::FillSearchResultsMarks(bool clear, search::Results::ConstIter be mark->SetMarkType(SearchMarkType::Booking); if (GetSearchAPI().GetSponsoredMode() == SearchAPI::SponsoredMode::Booking) - mark->SetPreparing(true /* isPreparing */); + SetPreparingStateForBookingHotel(r.GetFeatureID(), mark); } } @@ -3451,3 +3451,28 @@ void Framework::FilterSearchResultsOnBooking(booking::filter::availability::Para m_bookingFilter.FilterAvailability(results, paramsInternal); } + +void Framework::OnBookingFilterParamsUpdate(booking::AvailabilityParams const & params) +{ + m_bookingFilter.OnParamsUpdated(params); +} + +void Framework::SetPreparingStateForBookingHotel(FeatureID const & id, SearchMarkPoint * mark) +{ + using booking::filter::availability::Cache; + Index::FeaturesLoaderGuard guard(m_model.GetIndex(), id.m_mwmId); + + FeatureType ft; + if (!guard.GetFeatureByIndex(id.m_index, ft)) + { + LOG(LERROR, ("Feature can't be loaded:", id)); + return; + } + + auto const & hotelId = ft.GetMetadata().Get(feature::Metadata::FMD_SPONSORED_ID); + + if (m_bookingFilter.GetHotelAvailabilityStatus(hotelId) == Cache::HotelStatus::Available) + mark->SetPreparing(false /* isPreparing */); + else + mark->SetPreparing(true /* isPreparing */); +} diff --git a/map/framework.hpp b/map/framework.hpp index 3108d95f08..f7933a47b6 100644 --- a/map/framework.hpp +++ b/map/framework.hpp @@ -850,8 +850,10 @@ private: public: void FilterSearchResultsOnBooking(booking::filter::availability::Params const & params, search::Results const & results, bool inViewport) override; + void OnBookingFilterParamsUpdate(booking::AvailabilityParams const & params) override; private: + void SetPreparingStateForBookingHotel(FeatureID const & id, SearchMarkPoint * mark); // m_discoveryManager must be bellow m_searchApi, m_viatorApi, m_localsApi unique_ptr m_discoveryManager; }; diff --git a/map/search_api.cpp b/map/search_api.cpp index 6938c6ba4c..6611decf99 100644 --- a/map/search_api.cpp +++ b/map/search_api.cpp @@ -142,6 +142,9 @@ bool SearchAPI::SearchInViewport(ViewportSearchParams const & params) } }); + if (m_sponsoredMode == SponsoredMode::Booking) + m_delegate.OnBookingFilterParamsUpdate(params.m_bookingFilterParams.m_params); + return Search(p, false /* forceSearch */); } diff --git a/map/search_api.hpp b/map/search_api.hpp index e44d1b203d..fd334196c6 100644 --- a/map/search_api.hpp +++ b/map/search_api.hpp @@ -33,6 +33,7 @@ struct DownloaderSearchParams; namespace booking { +struct AvailabilityParams; namespace filter { namespace availability @@ -85,6 +86,10 @@ public: search::Results const & results, bool inViewport) { } + + virtual void OnBookingFilterParamsUpdate(booking::AvailabilityParams const & params) + { + } }; SearchAPI(Index & index, storage::Storage const & storage,