Skip to content

Commit b1352e4

Browse files
Enable the prefetching of aggregated tiles (#1026)
Enable the user to prefetch a list of aggregated tiles. When the tile does not exists, the prefetch algorithm scans the tree to find the nearest parent. Resolves: OLPEDGE-2245 Signed-off-by: Mykhailo Kuchma <ext-mykhailo.kuchma@here.com>
1 parent 1f1767b commit b1352e4

File tree

6 files changed

+176
-35
lines changed

6 files changed

+176
-35
lines changed

olp-cpp-sdk-dataservice-read/include/olp/dataservice/read/PrefetchTilesRequest.h

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,36 @@ class DATASERVICE_READ_API PrefetchTilesRequest final {
149149
return *this;
150150
}
151151

152+
/**
153+
* @brief Changes the prefetch behavior when prefetching a list of tiles.
154+
*
155+
* In case a tile does not exist, the prefetch algorithm searches for the
156+
* nearest parent and prefetches it.
157+
*
158+
* @param data_aggregation_enabled The boolean parameter that enables or
159+
* disables the aggregation.
160+
*
161+
* @note Experimental. API may change.
162+
*
163+
* @return A reference to the updated `PrefetchTilesRequest` instance.
164+
*/
165+
inline PrefetchTilesRequest& WithDataAggregationEnabled(
166+
bool data_aggregation_enabled) {
167+
data_aggregation_enabled_ = data_aggregation_enabled;
168+
return *this;
169+
}
170+
171+
/**
172+
* @brief Gets the data aggregation flag.
173+
*
174+
* @note Experimental. API may change.
175+
*
176+
* @return The data aggregation flag as a boolean value.
177+
*/
178+
inline bool GetDataAggregationEnabled() const {
179+
return data_aggregation_enabled_;
180+
}
181+
152182
/**
153183
* @brief Creates a readable format for the request.
154184
*
@@ -160,9 +190,6 @@ class DATASERVICE_READ_API PrefetchTilesRequest final {
160190
std::stringstream out;
161191
out << layer_id << "[" << GetMinLevel() << "/" << GetMaxLevel() << "]"
162192
<< "(" << GetTileKeys().size() << ")";
163-
if (catalog_version_) {
164-
out << "@" << catalog_version_.get();
165-
}
166193
if (GetBillingTag()) {
167194
out << "$" << GetBillingTag().get();
168195
}
@@ -174,8 +201,8 @@ class DATASERVICE_READ_API PrefetchTilesRequest final {
174201
std::vector<geo::TileKey> tile_keys_;
175202
unsigned int min_level_{geo::TileKey::LevelCount};
176203
unsigned int max_level_{geo::TileKey::LevelCount};
177-
boost::optional<int64_t> catalog_version_;
178204
boost::optional<std::string> billing_tag_;
205+
bool data_aggregation_enabled_{false};
179206
};
180207

181208
} // namespace read

olp-cpp-sdk-dataservice-read/src/VersionedLayerClientImpl.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -270,8 +270,11 @@ client::CancellationToken VersionedLayerClientImpl::PrefetchTiles(
270270
};
271271

272272
auto filter = [=](QueryResult tiles) mutable {
273-
return repository.FilterSkippedTiles(
274-
request, request_only_input_tiles, std::move(tiles));
273+
if (request_only_input_tiles) {
274+
return repository.FilterTilesByList(request, std::move(tiles));
275+
} else {
276+
return repository.FilterTilesByLevel(request, std::move(tiles));
277+
}
275278
};
276279

277280
auto billing_tag = request.GetBillingTag();

olp-cpp-sdk-dataservice-read/src/VolatileLayerClientImpl.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,8 +230,11 @@ client::CancellationToken VolatileLayerClientImpl::PrefetchTiles(
230230
};
231231

232232
auto filter = [=](QueryResult tiles) mutable {
233-
return repository.FilterSkippedTiles(
234-
request, request_only_input_tiles, std::move(tiles));
233+
if (request_only_input_tiles) {
234+
return repository.FilterTilesByList(request, std::move(tiles));
235+
} else {
236+
return repository.FilterTilesByLevel(request, std::move(tiles));
237+
}
235238
};
236239

237240
auto billing_tag = request.GetBillingTag();

olp-cpp-sdk-dataservice-read/src/repositories/PrefetchTilesRepository.cpp

Lines changed: 68 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -283,45 +283,89 @@ SubQuadsResponse PrefetchTilesRepository::GetVolatileSubQuads(
283283
return result;
284284
}
285285

286-
SubQuadsResult PrefetchTilesRepository::FilterSkippedTiles(
287-
const PrefetchTilesRequest& request, bool request_only_input_tiles,
288-
SubQuadsResult sub_tiles) {
286+
SubQuadsResult PrefetchTilesRepository::FilterTilesByLevel(
287+
const PrefetchTilesRequest& request, SubQuadsResult tiles) {
289288
const auto& tile_keys = request.GetTileKeys();
289+
290290
auto skip_tile = [&](const geo::TileKey& tile_key) {
291-
if (request_only_input_tiles) {
292-
return std::find(tile_keys.begin(), tile_keys.end(), tile_key) ==
293-
tile_keys.end();
294-
} else if (tile_key.Level() < request.GetMinLevel() ||
295-
tile_key.Level() > request.GetMaxLevel()) {
296-
// tile outside min/max segment, skip this tile
291+
if (tile_key.Level() < request.GetMinLevel()) {
292+
return true;
293+
}
294+
295+
if (tile_key.Level() > request.GetMaxLevel()) {
297296
return true;
298-
} else {
299-
// tile is not a parent or child for any of requested tiles, skip
300-
// this tile
301-
return std::find_if(tile_keys.begin(), tile_keys.end(),
302-
[&tile_key](const geo::TileKey& root_key) {
303-
return (root_key.IsParentOf(tile_key) ||
304-
tile_key.IsParentOf(root_key) ||
305-
root_key == tile_key);
306-
}) == tile_keys.end();
307297
}
298+
299+
return std::find_if(tile_keys.begin(), tile_keys.end(),
300+
[&tile_key](const geo::TileKey& root_key) {
301+
return (root_key.IsParentOf(tile_key) ||
302+
tile_key.IsParentOf(root_key) ||
303+
root_key == tile_key);
304+
}) == tile_keys.end();
308305
};
309306

310-
for (auto sub_quad_it = sub_tiles.begin(); sub_quad_it != sub_tiles.end();) {
307+
for (auto sub_quad_it = tiles.begin(); sub_quad_it != tiles.end();) {
311308
if (skip_tile(sub_quad_it->first)) {
312-
sub_quad_it = sub_tiles.erase(sub_quad_it);
309+
sub_quad_it = tiles.erase(sub_quad_it);
313310
} else {
314311
++sub_quad_it;
315312
}
316313
}
317-
if (request_only_input_tiles) {
314+
315+
return tiles;
316+
}
317+
318+
SubQuadsResult PrefetchTilesRepository::FilterTilesByList(
319+
const PrefetchTilesRequest& request, SubQuadsResult tiles) {
320+
const bool aggregation_enabled = request.GetDataAggregationEnabled();
321+
322+
const auto& tile_keys = request.GetTileKeys();
323+
324+
if (!aggregation_enabled) {
325+
for (auto it = tiles.begin(); it != tiles.end();) {
326+
if (std::find(tile_keys.begin(), tile_keys.end(), it->first) ==
327+
tile_keys.end()) {
328+
it = tiles.erase(it);
329+
} else {
330+
++it;
331+
}
332+
}
333+
318334
for (const auto& tile : tile_keys) {
319-
if (sub_tiles.find(tile) == sub_tiles.end()) {
320-
sub_tiles[tile] = "";
335+
if (tiles.find(tile) == tiles.end()) {
336+
tiles[tile] = "";
321337
}
322338
}
339+
340+
} else {
341+
SubQuadsResult result;
342+
343+
auto append_tile = [&](const geo::TileKey& key) {
344+
auto tile_it = tiles.find(key);
345+
if (tile_it != tiles.end()) {
346+
result[tile_it->first] = tile_it->second;
347+
return true;
348+
} else {
349+
return false;
350+
}
351+
};
352+
353+
for (const auto& tile : tile_keys) {
354+
auto aggregated_tile = tile;
355+
356+
while (aggregated_tile.IsValid() && !append_tile(aggregated_tile)) {
357+
aggregated_tile = aggregated_tile.Parent();
358+
}
359+
360+
if (!aggregated_tile.IsValid()) {
361+
result[tile] = ""; // To generate Not Found error
362+
}
363+
}
364+
365+
tiles.swap(result);
323366
}
324-
return sub_tiles;
367+
368+
return tiles;
325369
}
326370

327371
} // namespace repository

olp-cpp-sdk-dataservice-read/src/repositories/PrefetchTilesRepository.h

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,34 @@ class PrefetchTilesRepository {
6969
RootTilesForRequest GetSlicedTiles(const std::vector<geo::TileKey>& tile_keys,
7070
std::uint32_t min, std::uint32_t max);
7171

72+
/**
73+
* @brief Filters the input tiles according to the request.
74+
*
75+
* Removes tiles that do not belong to the minimum and maximum levels.
76+
* Removes tiles that are not a child or a parent of the requested tiles.
77+
*
78+
* @param request Your request.
79+
* @param tiles The input tiles.
80+
*
81+
* @returns The modified tiles.
82+
*/
83+
SubQuadsResult FilterTilesByLevel(const PrefetchTilesRequest& request,
84+
SubQuadsResult tiles);
7285

73-
SubQuadsResult FilterSkippedTiles(const PrefetchTilesRequest& request,
74-
bool request_only_input_tiles,
75-
SubQuadsResult sub_tiles);
86+
/**
87+
* @brief Filters the input tiles according to the request.
88+
*
89+
* Removes tiles that are not requested.
90+
* Adds tiles that are missing (to notify you that they are not found).
91+
* If you requested aggregated tiles, `FilterTilesByList` scans for parents.
92+
*
93+
* @param request Your request.
94+
* @param tiles The input tiles.
95+
*
96+
* @returns The modified tiles.
97+
*/
98+
SubQuadsResult FilterTilesByList(const PrefetchTilesRequest& request,
99+
SubQuadsResult tiles);
76100

77101
SubQuadsResponse GetVersionedSubQuads(geo::TileKey tile, int32_t depth,
78102
std::int64_t version,

tests/integration/olp-cpp-sdk-dataservice-read/VersionedLayerClientTest.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1519,6 +1519,46 @@ TEST_F(DataserviceReadVersionedLayerClientTest,
15191519
}
15201520
}
15211521

1522+
TEST_F(DataserviceReadVersionedLayerClientTest, PrefetchAggregatedTile) {
1523+
constexpr auto kLayerId = "hype-test-prefetch";
1524+
1525+
auto client = std::make_shared<read::VersionedLayerClient>(
1526+
kCatalog, kLayerId, boost::none, settings_);
1527+
1528+
{
1529+
SCOPED_TRACE("Prefetch aggregated tile");
1530+
const auto requested_tile = geo::TileKey::FromHereTile("23618365");
1531+
1532+
EXPECT_CALL(*network_mock_,
1533+
Send(IsGetRequest(URL_QUADKEYS_92259), _, _, _, _))
1534+
.WillOnce(ReturnHttpResponse(GetResponse(http::HttpStatusCode::OK),
1535+
HTTP_RESPONSE_QUADKEYS_92259_ROOT_ONLY));
1536+
1537+
auto request = read::PrefetchTilesRequest()
1538+
.WithTileKeys({requested_tile})
1539+
.WithDataAggregationEnabled(true);
1540+
1541+
auto promise = std::make_shared<std::promise<PrefetchTilesResponse>>();
1542+
auto future = promise->get_future();
1543+
auto token = client->PrefetchTiles(
1544+
request, [promise](PrefetchTilesResponse response) {
1545+
promise->set_value(std::move(response));
1546+
});
1547+
1548+
ASSERT_NE(future.wait_for(kWaitTimeout), std::future_status::timeout);
1549+
PrefetchTilesResponse response = future.get();
1550+
ASSERT_TRUE(response.IsSuccessful()) << response.GetError().GetMessage();
1551+
ASSERT_FALSE(response.GetResult().empty());
1552+
1553+
const auto& result = response.GetResult();
1554+
ASSERT_EQ(result.size(), 1);
1555+
1556+
const auto& tile_response = result[0];
1557+
ASSERT_TRUE(tile_response->IsSuccessful());
1558+
ASSERT_TRUE(tile_response->tile_key_.IsParentOf(requested_tile));
1559+
}
1560+
}
1561+
15221562
TEST_F(DataserviceReadVersionedLayerClientTest, PrefetchTilesWrongLevels) {
15231563
constexpr auto kLayerId = "hype-test-prefetch";
15241564

0 commit comments

Comments
 (0)