Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 36 additions & 5 deletions libs/http-service/src/tiles-ws-controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -823,6 +823,36 @@
}
}

/// Match one backend-produced tile key against the currently desired request set.
[[nodiscard]] std::optional<MapTileKey> matchDesiredTileKeyLocked(
MapTileKey key,
uint32_t advertisedStages) const
{
auto requestedTileKey = makeCanonicalRequestedTileKey(std::move(key));
if (desiredTileKeys_.find(requestedTileKey) != desiredTileKeys_.end()) {

Check warning on line 832 in libs/http-service/src/tiles-ws-controller.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use "contains" member function.

See more on https://sonarcloud.io/project/issues?id=ndsev_mapget&issues=AZ0_DmCrTlNjRCqKlWBA&open=AZ0_DmCrTlNjRCqKlWBA&pullRequest=153
return requestedTileKey;
}

// Single-stage datasources legitimately return stage-less tiles even when
// the client used staged bucket requests. Treat stage 0 and "unspecified"
// as equivalent only for those layers.
if (advertisedStages <= 1U) {
if (requestedTileKey.stage_ == UnspecifiedStage) {
requestedTileKey.stage_ = 0;
if (desiredTileKeys_.find(requestedTileKey) != desiredTileKeys_.end()) {

Check warning on line 842 in libs/http-service/src/tiles-ws-controller.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use "contains" member function.

See more on https://sonarcloud.io/project/issues?id=ndsev_mapget&issues=AZ0_DmCrTlNjRCqKlWBB&open=AZ0_DmCrTlNjRCqKlWBB&pullRequest=153
return requestedTileKey;
}
} else if (requestedTileKey.stage_ == 0) {
requestedTileKey.stage_ = UnspecifiedStage;
if (desiredTileKeys_.find(requestedTileKey) != desiredTileKeys_.end()) {

Check warning on line 847 in libs/http-service/src/tiles-ws-controller.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use "contains" member function.

See more on https://sonarcloud.io/project/issues?id=ndsev_mapget&issues=AZ0_DmCrTlNjRCqKlWBC&open=AZ0_DmCrTlNjRCqKlWBC&pullRequest=153
return requestedTileKey;
}
}
}

return std::nullopt;
}

/// Complete all currently pending pull waiters with one terminal status.
void collectAllPullWaitersLocked(PullFrameResult::Status status, std::vector<PullDispatch>& dispatches)
{
Expand Down Expand Up @@ -1065,17 +1095,18 @@
return;
if (!layer)
return;

const auto requestedTileKey = makeCanonicalRequestedTileKey(layer->id());
std::optional<std::pair<std::string, simfil::StringId>> stringPoolCommit;
std::vector<PullDispatch> pullDispatches;

{
std::lock_guard lock(mutex_);
if (cancelled_)
return;
auto requestedTileKey = matchDesiredTileKeyLocked(
layer->id(),
layer->layerInfo() ? std::max<uint32_t>(1U, layer->layerInfo()->stages_) : 1U);
// Late-arriving tile for an outdated request: drop before serialization work.
if (desiredTileKeys_.find(requestedTileKey) == desiredTileKeys_.end()) {
if (!requestedTileKey.has_value()) {
return;
}

Expand Down Expand Up @@ -1107,11 +1138,11 @@
frame.type = m.type;
if (m.type == TileLayerStream::MessageType::StringPool) {
frame.stringPoolCommit = stringPoolCommit;
frame.requestedTileKey = requestedTileKey;
frame.requestedTileKey = *requestedTileKey;
}
if (m.type == TileLayerStream::MessageType::TileFeatureLayer
|| m.type == TileLayerStream::MessageType::TileSourceDataLayer) {
frame.requestedTileKey = requestedTileKey;
frame.requestedTileKey = *requestedTileKey;
}
enqueueOutgoingLocked(std::move(frame));
}
Expand Down
18 changes: 12 additions & 6 deletions libs/model/src/featureid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
#include "featurelayer.h"

#include <algorithm>
#include <sstream>
#include <string>

#include <fmt/format.h>

#include "mapget/log.h"

Expand Down Expand Up @@ -143,7 +145,7 @@ void appendTypedKeyValue(
valueNode->value());
}

void appendNodeValueToString(std::stringstream& out, simfil::ModelNode::Ptr const& node)
void appendNodeValueToString(std::string& out, simfil::ModelNode::Ptr const& node)
{
if (!node) {
return;
Expand All @@ -157,7 +159,12 @@ void appendNodeValueToString(std::stringstream& out, simfil::ModelNode::Ptr cons
raiseFmt("FeatureId part value 'b\"{}\"' cannot be a ByteArray.", v.toHex());
}
else if constexpr (!std::is_same_v<T, std::monostate>) {
out << "." << v;
if constexpr (std::is_same_v<T, bool>) {
fmt::format_to(std::back_inserter(out), FMT_STRING(".{:d}"), v);
}
else {
fmt::format_to(std::back_inserter(out), FMT_STRING(".{}"), v);
}
}
},
node->value());
Expand Down Expand Up @@ -208,8 +215,7 @@ std::string_view FeatureId::typeId() const

std::string FeatureId::toString() const
{
std::stringstream result;
result << typeId();
std::string result(typeId());

if (data_.useCommonTilePrefix_) {
if (auto idPrefix = model().getIdPrefix()) {
Expand All @@ -225,7 +231,7 @@ std::string FeatureId::toString() const
}
}

return result.str();
return result;
}

simfil::ValueType FeatureId::type() const
Expand Down
24 changes: 15 additions & 9 deletions libs/model/src/featurelayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -501,18 +501,24 @@
* Create a string representation of the given id parts.
*/
std::string idPartsToString(KeyValueViewPairs const& idParts) {
std::stringstream result;
result << "{";
fmt::memory_buffer result;
fmt::format_to(std::back_inserter(result), FMT_STRING("{{"));
for (auto i = 0; i < idParts.size(); ++i) {
if (i > 0)
result << ", ";
result << idParts[i].first << ": ";
std::visit([&result](auto&& value){
result << value;
if (i > 0) {
fmt::format_to(std::back_inserter(result), FMT_STRING(", "));
}
std::visit([&result, key = idParts[i].first](auto&& value){

Check warning on line 510 in libs/model/src/featurelayer.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace "auto" with an explicit template parameter.

See more on https://sonarcloud.io/project/issues?id=ndsev_mapget&issues=AZ0_daqL1q7FpChCK6hT&open=AZ0_daqL1q7FpChCK6hT&pullRequest=153
using T = std::decay_t<decltype(value)>;
if constexpr (std::is_same_v<T, bool>) {
fmt::format_to(std::back_inserter(result), FMT_STRING("{}: {:d}"), key, value);
}
else {
fmt::format_to(std::back_inserter(result), FMT_STRING("{}: {}"), key, value);
}
}, idParts[i].second);
}
result << "}";
return result.str();
fmt::format_to(std::back_inserter(result), FMT_STRING("}}"));
return fmt::to_string(result);
}

/**
Expand Down
19 changes: 19 additions & 0 deletions test/unit/test-http-datasource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,25 @@ TEST_CASE("HttpDataSource", "[HttpDataSource]")

wsClient.stop();
}

// WebSocket tiles: single-stage layers must also work through staged bucket requests.
{
auto req = nlohmann::json::object({
{"requests", nlohmann::json::array({nlohmann::json::object({
{"mapId", "Tropico"},
{"layerId", "WayLayer"},
{"tileIdsByNextStage", nlohmann::json::array({
nlohmann::json::array({1234}),
})},
})})},
}).dump();

auto [status, wsTileCount] = runWsTilesRequest(true, req);
REQUIRE(wsTileCount == 1);
REQUIRE(status["requests"].size() == 1);
REQUIRE(status["requests"][0]["status"].get<int>() ==
static_cast<int>(RequestStatus::Success));
}
}

service.remove(remoteDataSource);
Expand Down
Loading