Skip to content
This repository was archived by the owner on Aug 8, 2023. It is now read-only.
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
8 changes: 4 additions & 4 deletions include/mbgl/storage/request.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ class Request : private util::noncopyable {

private:
~Request();
void invoke();
void notifyCallback();

private:
std::unique_ptr<uv::async> async;
struct Canceled;
std::unique_ptr<Canceled> canceled;
std::mutex mtx;
bool canceled = false;
bool confirmed = false;
const std::unique_ptr<uv::async> async;
Callback callback;
std::shared_ptr<const Response> response;

Expand Down
7 changes: 6 additions & 1 deletion include/mbgl/storage/response.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,24 @@
#define MBGL_STORAGE_RESPONSE

#include <string>
#include <memory>

namespace mbgl {

class Response {
public:
bool isExpired() const;

public:
enum Status { Error, Successful, NotFound };

Status status = Error;
bool stale = false;
std::string message;
int64_t modified = 0;
int64_t expires = 0;
std::string etag;
std::string data;
std::shared_ptr<const std::string> data;
};

}
Expand Down
5 changes: 4 additions & 1 deletion platform/darwin/http_request_nsurl.mm
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,9 @@ int64_t parseCacheControl(const char *value) {
// TODO: Use different codes for host not found, timeout, invalid URL etc.
// These can be categorized in temporary and permanent errors.
response = std::make_unique<Response>();
if (data) {
response->data = std::make_shared<std::string>((const char *)[data bytes], [data length]);
}
response->status = Response::Error;
response->message = [[error localizedDescription] UTF8String];

Expand Down Expand Up @@ -253,7 +256,7 @@ int64_t parseCacheControl(const char *value) {
const long responseCode = [(NSHTTPURLResponse *)res statusCode];

response = std::make_unique<Response>();
response->data = {(const char *)[data bytes], [data length]};
response->data = std::make_shared<std::string>((const char *)[data bytes], [data length]);

NSDictionary *headers = [(NSHTTPURLResponse *)res allHeaderFields];
NSString *cache_control = [headers objectForKey:@"Cache-Control"];
Expand Down
6 changes: 4 additions & 2 deletions platform/default/asset_request_fs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,10 @@ void AssetRequest::fileStated(uv_fs_t *req) {
#endif
self->response->etag = util::toString(stat->st_ino);
const auto size = (unsigned int)(stat->st_size);
self->response->data.resize(size);
self->buffer = uv_buf_init(const_cast<char *>(self->response->data.data()), size);
auto data = std::make_shared<std::string>();
self->response->data = data;
data->resize(size);
self->buffer = uv_buf_init(const_cast<char *>(data->data()), size);
uv_fs_req_cleanup(req);
#if UV_VERSION_MAJOR == 0 && UV_VERSION_MINOR <= 10
uv_fs_read(req->loop, req, self->fd, self->buffer.base, self->buffer.len, -1, fileRead);
Expand Down
6 changes: 4 additions & 2 deletions platform/default/asset_request_zip.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,10 @@ void AssetRequest::fileStated(uv_zip_t *zip) {
response = std::make_unique<Response>();

// Allocate the space for reading the data.
response->data.resize(zip->stat->size);
buffer = uv_buf_init(const_cast<char *>(response->data.data()), zip->stat->size);
auto data = std::make_shared<std::string>();
data->resize(zip->stat->size);
buffer = uv_buf_init(const_cast<char *>(data->data()), zip->stat->size);
response->data = data;

// Get the modification time in case we have one.
if (zip->stat->valid & ZIP_STAT_MTIME) {
Expand Down
2 changes: 1 addition & 1 deletion platform/default/glfw_view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ void GLFWView::addRandomPointAnnotations(int count) {
std::vector<mbgl::PointAnnotation> points;

for (int i = 0; i < count; i++) {
points.emplace_back(makeRandomPoint(), "default_marker");
points.emplace_back(makeRandomPoint(), "marker-15");
}

auto newIDs = map->addPointAnnotations(points);
Expand Down
12 changes: 9 additions & 3 deletions platform/default/http_request_curl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ class HTTPCURLRequest : public HTTPRequestBase {
HTTPCURLContext *context = nullptr;

// Will store the current response.
std::shared_ptr<std::string> data;
std::unique_ptr<Response> response;

// In case of revalidation requests, this will store the old response.
Expand Down Expand Up @@ -516,11 +517,11 @@ size_t HTTPCURLRequest::writeCallback(void *const contents, const size_t size, c
auto impl = reinterpret_cast<HTTPCURLRequest *>(userp);
MBGL_VERIFY_THREAD(impl->tid);

if (!impl->response) {
impl->response = std::make_unique<Response>();
if (!impl->data) {
impl->data = std::make_shared<std::string>();
}

impl->response->data.append((char *)contents, size * nmemb);
impl->data->append((char *)contents, size * nmemb);
return size * nmemb;
}

Expand Down Expand Up @@ -688,22 +689,27 @@ void HTTPCURLRequest::handleResult(CURLcode code) {
// This is an unsolicited 304 response and should only happen on malfunctioning
// HTTP servers. It likely doesn't include any data, but we don't have much options.
response->status = Response::Successful;
response->data = std::move(data);
return finish(ResponseStatus::Successful);
}
} else if (responseCode == 200) {
response->status = Response::Successful;
response->data = std::move(data);
return finish(ResponseStatus::Successful);
} else if (responseCode == 404) {
response->status = Response::NotFound;
response->data = std::move(data);
return finish(ResponseStatus::Successful);
} else if (responseCode >= 500 && responseCode < 600) {
// Server errors may be temporary, so back off exponentially.
response->status = Response::Error;
response->data = std::move(data);
response->message = "HTTP status code " + util::toString(responseCode);
return finish(ResponseStatus::TemporaryError);
} else {
// We don't know how to handle any other errors, so declare them as permanently failing.
response->status = Response::Error;
response->data = std::move(data);
response->message = "HTTP status code " + util::toString(responseCode);
return finish(ResponseStatus::PermanentError);
}
Expand Down
15 changes: 9 additions & 6 deletions platform/default/sqlite_cache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,9 @@ void SQLiteCache::Impl::get(const Resource &resource, Callback callback) {
response->modified = getStmt->get<int64_t>(1);
response->etag = getStmt->get<std::string>(2);
response->expires = getStmt->get<int64_t>(3);
response->data = getStmt->get<std::string>(4);
response->data = std::make_shared<std::string>(std::move(getStmt->get<std::string>(4)));
if (getStmt->get<int>(5)) { // == compressed
response->data = util::decompress(response->data);
response->data = std::make_shared<std::string>(std::move(util::decompress(*response->data)));
}
callback(std::move(response));
} else {
Expand Down Expand Up @@ -171,18 +171,21 @@ void SQLiteCache::Impl::put(const Resource& resource, std::shared_ptr<const Resp
putStmt->bind(6 /* expires */, response->expires);

std::string data;
if (resource.kind != Resource::SpriteImage) {
if (resource.kind != Resource::SpriteImage && response->data) {
// Do not compress images, since they are typically compressed already.
data = util::compress(response->data);
data = util::compress(*response->data);
}

if (!data.empty() && data.size() < response->data.size()) {
if (!data.empty() && data.size() < response->data->size()) {
// Store the compressed data when it is smaller than the original
// uncompressed data.
putStmt->bind(7 /* data */, data, false); // do not retain the string internally.
putStmt->bind(8 /* compressed */, true);
} else if (response->data) {
putStmt->bind(7 /* data */, *response->data, false); // do not retain the string internally.
putStmt->bind(8 /* compressed */, false);
} else {
putStmt->bind(7 /* data */, response->data, false); // do not retain the string internally.
putStmt->bind(7 /* data */, "", false);
putStmt->bind(8 /* compressed */, false);
}

Expand Down
1 change: 0 additions & 1 deletion platform/node/src/node_file_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,6 @@ void NodeFileSource::notify(const mbgl::Resource& resource, const std::shared_pt
}

observersIt->second->notify(response);
observers.erase(observersIt);
}

}
4 changes: 2 additions & 2 deletions platform/node/src/node_request.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,10 @@ NAN_METHOD(NodeRequest::Respond) {
if (Nan::Has(res, Nan::New("data").ToLocalChecked()).FromJust()) {
auto dataHandle = Nan::Get(res, Nan::New("data").ToLocalChecked()).ToLocalChecked();
if (node::Buffer::HasInstance(dataHandle)) {
response->data = std::string {
response->data = std::make_shared<std::string>(
node::Buffer::Data(dataHandle),
node::Buffer::Length(dataHandle)
};
);
} else {
return Nan::ThrowTypeError("Response data must be a Buffer");
}
Expand Down
93 changes: 75 additions & 18 deletions src/mbgl/map/live_tile_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,20 @@
#include <mbgl/util/worker.hpp>
#include <mbgl/util/work_request.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/style/style_bucket.hpp>

#include <sstream>

using namespace mbgl;

LiveTileData::LiveTileData(const TileID& id_,
std::unique_ptr<AnnotationTile> tile_,
Style& style_,
const SourceInfo& source_,
Style& style,
const SourceInfo& source,
std::function<void()> callback)
: TileData(id_),
worker(style_.workers),
tileWorker(id_,
source_.source_id,
style_,
style_.layers,
state,
std::make_unique<CollisionTile>(0, 0, false)),
worker(style.workers),
tileWorker(id, source.source_id, style, style.layers, state),
tile(std::move(tile_)) {
state = State::loaded;

Expand All @@ -32,27 +28,49 @@ LiveTileData::LiveTileData(const TileID& id_,
return;
}

reparse(callback);
parsePending(callback);
}

bool LiveTileData::reparse(std::function<void()> callback) {
if (parsing || (state != State::loaded && state != State::partial)) {
bool LiveTileData::parsePending(std::function<void()> callback) {
if (workRequest || (state != State::loaded && state != State::partial)) {
return false;
}

parsing = true;
workRequest.reset();
workRequest = worker.parseLiveTile(tileWorker, *tile, targetConfig, [this, callback, config = targetConfig] (TileParseResult result) {
workRequest.reset();

if (result.is<TileParseResultBuckets>()) {
auto& resultBuckets = result.get<TileParseResultBuckets>();
state = resultBuckets.state;

// Persist the configuration we just placed so that we can later check whether we need
// to place again in case the configuration has changed.
placedConfig = config;

workRequest = worker.parseLiveTile(tileWorker, *tile, [this, callback] (TileParseResult result) {
parsing = false;
// Move over all buckets we received in this parse request, potentially overwriting
// existing buckets in case we got a refresh parse.
for (auto& bucket : resultBuckets.buckets) {
buckets[bucket.first] = std::move(bucket.second);
}

if (result.is<State>()) {
state = result.get<State>();
// The target configuration could have changed since we started placement. In this case,
// we're starting another placement run.
if (placedConfig != targetConfig) {
redoPlacement();
}
} else {
error = result.get<std::string>();
state = State::obsolete;
}

callback();

// The target configuration could have changed since we started placement. In this case,
// we're starting another placement run.
if (!workRequest && placedConfig != targetConfig) {
redoPlacement();
}
});

return true;
Expand All @@ -67,10 +85,49 @@ Bucket* LiveTileData::getBucket(const StyleLayer& layer) {
return nullptr;
}

return tileWorker.getBucket(layer);
const auto it = buckets.find(layer.bucket->name);
if (it == buckets.end()) {
return nullptr;
}

assert(it->second);
return it->second.get();
}

void LiveTileData::cancel() {
state = State::obsolete;
workRequest.reset();
}

void LiveTileData::redoPlacement(const PlacementConfig newConfig) {
if (newConfig != placedConfig) {
targetConfig = newConfig;

if (!workRequest) {
// Don't start a new placement request when the current one hasn't completed yet, or
// when we are parsing buckets.
redoPlacement();
}
}
}

void LiveTileData::redoPlacement() {
workRequest.reset();
workRequest = worker.redoPlacement(tileWorker, buckets, targetConfig, [this, config = targetConfig] {
workRequest.reset();

// Persist the configuration we just placed so that we can later check whether we need to
// place again in case the configuration has changed.
placedConfig = config;

for (auto& bucket : buckets) {
bucket.second->swapRenderData();
}

// The target configuration could have changed since we started placement. In this case,
// we're starting another placement run.
if (placedConfig != targetConfig) {
redoPlacement();
}
});
}
17 changes: 15 additions & 2 deletions src/mbgl/map/live_tile_data.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ class LiveTileData : public TileData {
std::function<void ()> callback);
~LiveTileData();

bool reparse(std::function<void ()> callback) override;
bool parsePending(std::function<void ()> callback) override;

void redoPlacement(PlacementConfig config) override;
void redoPlacement();

void cancel() override;
Bucket* getBucket(const StyleLayer&) override;
Expand All @@ -29,8 +32,18 @@ class LiveTileData : public TileData {
Worker& worker;
TileWorker tileWorker;
std::unique_ptr<WorkRequest> workRequest;
bool parsing = false;
std::unique_ptr<AnnotationTile> tile;

// Contains all the Bucket objects for the tile. Buckets are render
// objects and they get added by tile parsing operations.
std::unordered_map<std::string, std::unique_ptr<Bucket>> buckets;

// Stores the placement configuration of the text that is currently placed on the screen.
PlacementConfig placedConfig;

// Stores the placement configuration of how the text should be placed. This isn't necessarily
// the one that is being displayed.
PlacementConfig targetConfig;
};

}
Expand Down
Loading