| 3067 | // [([a, b1), locationInfo), ([b1, c), locationInfo), ([c, d1), locationInfo)]. |
| 3068 | template <class F> |
| 3069 | Future<std::vector<KeyRangeLocationInfo>> getKeyRangeLocations(Database const& cx, |
| 3070 | TenantInfo const& tenant, |
| 3071 | KeyRange const& keys, |
| 3072 | int limit, |
| 3073 | Reverse reverse, |
| 3074 | F StorageServerInterface::*member, |
| 3075 | SpanContext const& spanContext, |
| 3076 | Optional<UID> const& debugID, |
| 3077 | UseProvisionalProxies useProvisionalProxies, |
| 3078 | Version version) { |
| 3079 | |
| 3080 | ASSERT(!keys.empty()); |
| 3081 | |
| 3082 | std::vector<KeyRangeLocationInfo> locations; |
| 3083 | if (!cx->getCachedLocations(tenant.name, keys, locations, limit, reverse)) { |
| 3084 | return getKeyRangeLocations_internal( |
| 3085 | cx, tenant, keys, limit, reverse, spanContext, debugID, useProvisionalProxies, version); |
| 3086 | } |
| 3087 | |
| 3088 | bool foundFailed = false; |
| 3089 | for (const auto& locationInfo : locations) { |
| 3090 | bool onlyEndpointFailedAndNeedRefresh = false; |
| 3091 | for (int i = 0; i < locationInfo.locations->size(); i++) { |
| 3092 | if (checkOnlyEndpointFailed(cx, locationInfo.locations->get(i, member).getEndpoint())) { |
| 3093 | onlyEndpointFailedAndNeedRefresh = true; |
| 3094 | } |
| 3095 | } |
| 3096 | |
| 3097 | if (onlyEndpointFailedAndNeedRefresh) { |
| 3098 | cx->invalidateCache(locationInfo.tenantEntry.prefix, locationInfo.range.begin); |
| 3099 | foundFailed = true; |
| 3100 | } |
| 3101 | } |
| 3102 | |
| 3103 | if (foundFailed) { |
| 3104 | // Refresh the cache with a new getKeyRangeLocations made to proxies. |
| 3105 | return getKeyRangeLocations_internal( |
| 3106 | cx, tenant, keys, limit, reverse, spanContext, debugID, useProvisionalProxies, version); |
| 3107 | } |
| 3108 | |
| 3109 | return locations; |
| 3110 | } |
| 3111 | |
| 3112 | template <class F> |
| 3113 | Future<std::vector<KeyRangeLocationInfo>> getKeyRangeLocations(Reference<TransactionState> trState, |
no test coverage detected