Merge branch 'master' into android-mason

Conflicts:
	gyp/mbgl-ios.gypi
	gyp/mbgl-linux.gypi
	gyp/mbgl-osx.gypi
	platform/default/caching_http_file_source.cpp
This commit is contained in:
Mike Morris
2014-12-03 13:07:49 -05:00
12 changed files with 150 additions and 72 deletions

View File

@@ -4,12 +4,32 @@
'product_name': 'mbgl-headless',
'type': 'static_library',
'standalone_static_library': 1,
'variables': {
'cflags_cc': [
'<@(uv_cflags)',
],
'cflags': [
'<@(uv_cflags)',
],
},
'include_dirs': [
'../include',
],
'conditions': [
['OS == "mac"', {
'xcode_settings': {
'OTHER_CPLUSPLUSFLAGS': [ '<@(cflags_cc)' ],
'OTHER_CFLAGS': [ '<@(cflags)' ],
}
}, {
'cflags_cc': [ '<@(cflags_cc)' ],
'cflags': [ '<@(cflags)' ],
}]
],
'sources': [
'../platform/default/headless_view.cpp',
'../platform/default/headless_display.cpp',
'../platform/default/caching_http_file_source.cpp',
],
},
],

View File

@@ -36,6 +36,7 @@
'../platform/darwin/string_nsstring.mm',
'../platform/darwin/http_request_baton_cocoa.mm',
'../platform/darwin/image.mm',
'../platform/default/caching_http_file_source.cpp',
'../platform/default/asset_request_baton_noop.cpp',
],
'include_dirs': [

View File

@@ -35,6 +35,7 @@
'../platform/default/image_reader.cpp',
'../platform/default/png_reader.cpp',
'../platform/default/jpeg_reader.cpp',
'../platform/default/caching_http_file_source.cpp',
'../platform/default/asset_request_baton_noop.cpp',
],
'include_dirs': [

View File

@@ -11,6 +11,7 @@
'../platform/darwin/string_nsstring.mm',
'../platform/darwin/http_request_baton_cocoa.mm',
'../platform/darwin/image.mm',
'../platform/default/caching_http_file_source.cpp',
'../platform/default/asset_request_baton_noop.cpp',
],
'include_dirs': [

View File

@@ -34,7 +34,7 @@ class Map : private util::noncopyable {
typedef void (*stop_callback)(void *);
public:
explicit Map(View &view);
explicit Map(View&, FileSource&);
~Map();
// Start the map render thread. It is asynchronous.
@@ -197,7 +197,7 @@ private:
Transform transform;
TransformState state;
util::ptr<FileSource> fileSource;
FileSource& fileSource;
util::ptr<Style> style;
GlyphAtlas glyphAtlas;

View File

@@ -0,0 +1,52 @@
#ifndef MBGL_STORAGE_CACHING_HTTP_FILE_SOURCE
#define MBGL_STORAGE_CACHING_HTTP_FILE_SOURCE
#include <mbgl/storage/file_source.hpp>
#include <unordered_map>
typedef struct uv_messenger_s uv_messenger_t;
namespace mbgl {
class BaseRequest;
class SQLiteStore;
class CachingHTTPFileSource : public FileSource {
public:
CachingHTTPFileSource(uv_loop_t*, const std::string &path_);
CachingHTTPFileSource(const std::string &path_);
~CachingHTTPFileSource();
// Stores and checks the libuv loop for requests
void setLoop(uv_loop_t*);
bool hasLoop();
// Stores and retrieves the base path/URL for relative requests
void setBase(const std::string &value);
const std::string &getBase() const;
std::unique_ptr<Request> request(ResourceType type, const std::string &url);
void prepare(std::function<void()> fn);
void retryAllPending();
private:
unsigned long thread_id;
// Path to the cache database.
std::string path;
// Stores a URL that is used as a base for loading resources with relative path.
std::string base;
std::unordered_map<std::string, std::weak_ptr<BaseRequest>> pending;
util::ptr<SQLiteStore> store;
uv_loop_t *loop = nullptr;
uv_messenger_t *queue = nullptr;
};
}
#endif

View File

@@ -1,48 +1,25 @@
#ifndef MBGL_STORAGE_FILE_SOURCE
#define MBGL_STORAGE_FILE_SOURCE
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/storage/resource_type.hpp>
#include <mbgl/storage/request.hpp>
#include <mbgl/util/noncopyable.hpp>
#include <string>
#include <unordered_map>
#include <functional>
typedef struct uv_loop_s uv_loop_t;
typedef struct uv_messenger_s uv_messenger_t;
namespace mbgl {
class BaseRequest;
class SQLiteStore;
class FileSource : public util::noncopyable {
private:
public:
FileSource(uv_loop_t *loop, const std::string &path);
~FileSource();
// Stores and retrieves the base path/URL for relative requests
void setBase(const std::string &value);
const std::string &getBase() const;
std::unique_ptr<Request> request(ResourceType type, const std::string &url);
void prepare(std::function<void()> fn);
void retryAllPending();
private:
const unsigned long thread_id;
// Stores a URL that is used as a base for loading resources with relative path.
std::string base;
std::unordered_map<std::string, std::weak_ptr<BaseRequest>> pending;
util::ptr<SQLiteStore> store;
uv_loop_t *loop = nullptr;
uv_messenger_t *queue = nullptr;
virtual void setLoop(uv_loop_t*) = 0;
virtual bool hasLoop() = 0;
virtual void setBase(const std::string &value) = 0;
virtual std::unique_ptr<Request> request(ResourceType type, const std::string &url) = 0;
virtual void prepare(std::function<void()> fn) = 0;
virtual void retryAllPending() = 0;
};
}

View File

@@ -4,6 +4,7 @@
#include <mbgl/platform/default/settings_json.hpp>
#include <mbgl/platform/default/glfw_view.hpp>
#include <mbgl/platform/default/log_stderr.hpp>
#include <mbgl/platform/default/caching_http_file_source.hpp>
#include <signal.h>
#include <getopt.h>
@@ -63,7 +64,8 @@ int main(int argc, char *argv[]) {
sigaction(SIGINT, &sigIntHandler, NULL);
view = new GLFWView();
mbgl::Map map(*view);
mbgl::CachingHTTPFileSource fileSource(mbgl::platform::defaultCacheDatabase());
mbgl::Map map(*view, fileSource);
// Load settings
mbgl::Settings_JSON settings;

View File

@@ -2,6 +2,7 @@
#include <mbgl/platform/darwin/log_nslog.hpp>
#include <mbgl/platform/darwin/Reachability.h>
#include <mbgl/platform/default/glfw_view.hpp>
#include <mbgl/platform/default/caching_http_file_source.hpp>
#import <Foundation/Foundation.h>
@@ -72,7 +73,8 @@ int main() {
mbgl::Log::Set<mbgl::NSLogBackend>();
GLFWView view;
mbgl::Map map(view);
mbgl::CachingHTTPFileSource fileSource(mbgl::platform::defaultCacheDatabase());
mbgl::Map map(view, fileSource);
mbgl::Map *map_ptr = &map;
URLHandler *handler = [[URLHandler alloc] init];

View File

@@ -1,4 +1,4 @@
#include <mbgl/storage/file_source.hpp>
#include <mbgl/platform/default/caching_http_file_source.hpp>
#include <mbgl/storage/file_request.hpp>
#include <mbgl/storage/http_request.hpp>
#include <mbgl/storage/sqlite_store.hpp>
@@ -10,8 +10,9 @@
namespace mbgl {
FileSource::FileSource(uv_loop_t *loop_, const std::string &path)
CachingHTTPFileSource::CachingHTTPFileSource(uv_loop_t* loop_, const std::string &path_)
: thread_id(uv_thread_self()),
path(path_),
store(!path.empty() ? util::ptr<SQLiteStore>(new SQLiteStore(loop_, path)) : nullptr),
loop(loop_),
queue(new uv_messenger_t) {
@@ -23,34 +24,56 @@ FileSource::FileSource(uv_loop_t *loop_, const std::string &path)
uv_unref((uv_handle_t *)&queue->async);
}
FileSource::~FileSource() {
// FIXME temp fix for #608 crash
//assert(thread_id == uv_thread_self());
uv_messenger_stop(queue, [](uv_messenger_t *msgr) {
delete msgr;
});
CachingHTTPFileSource::CachingHTTPFileSource(const std::string &path_)
: path(path_) {}
util::ptr<BaseRequest> req;
CachingHTTPFileSource::~CachingHTTPFileSource() {
if (hasLoop()) {
// FIXME temp fix for #608 crash
// assert(thread_id == uv_thread_self());
uv_messenger_stop(queue, [](uv_messenger_t *msgr) {
delete msgr;
});
// Send a cancel() message to all requests that we are still holding.
for (const std::pair<std::string, std::weak_ptr<BaseRequest>> &pair : pending) {
if ((req = pair.second.lock())) {
req->cancel();
util::ptr<BaseRequest> req;
// Send a cancel() message to all requests that we are still holding.
for (const std::pair<std::string, std::weak_ptr<BaseRequest>> &pair : pending) {
if ((req = pair.second.lock())) {
req->cancel();
}
}
}
}
void FileSource::setBase(const std::string &value) {
void CachingHTTPFileSource::setLoop(uv_loop_t* loop_) {
thread_id = uv_thread_self();
store = !path.empty() ? util::ptr<SQLiteStore>(new SQLiteStore(loop_, path)) : nullptr;
loop = loop_;
queue = new uv_messenger_t;
uv_messenger_init(loop, queue, [](void *ptr) {
std::unique_ptr<std::function<void()>> fn { reinterpret_cast<std::function<void()> *>(ptr) };
(*fn)();
});
uv_unref((uv_handle_t *)&queue->async);
}
bool CachingHTTPFileSource::hasLoop() {
return loop;
}
void CachingHTTPFileSource::setBase(const std::string &value) {
assert(thread_id == uv_thread_self());
base = value;
}
const std::string &FileSource::getBase() const {
const std::string &CachingHTTPFileSource::getBase() const {
assert(thread_id == uv_thread_self());
return base;
}
std::unique_ptr<Request> FileSource::request(ResourceType type, const std::string &url) {
std::unique_ptr<Request> CachingHTTPFileSource::request(ResourceType type, const std::string &url) {
assert(thread_id == uv_thread_self());
// Make URL absolute.
@@ -87,7 +110,7 @@ std::unique_ptr<Request> FileSource::request(ResourceType type, const std::strin
return util::make_unique<Request>(req);
}
void FileSource::prepare(std::function<void()> fn) {
void CachingHTTPFileSource::prepare(std::function<void()> fn) {
if (thread_id == uv_thread_self()) {
fn();
} else {
@@ -95,7 +118,7 @@ void FileSource::prepare(std::function<void()> fn) {
}
}
void FileSource::retryAllPending() {
void CachingHTTPFileSource::retryAllPending() {
assert(thread_id == uv_thread_self());
util::ptr<BaseRequest> req;

View File

@@ -90,13 +90,14 @@ const static bool sqlite_version_check = []() {
using namespace mbgl;
Map::Map(View& view_)
Map::Map(View& view_, FileSource& fileSource_)
: loop(util::make_unique<uv::loop>()),
view(view_),
#ifndef NDEBUG
mainThread(uv_thread_self()),
#endif
transform(view_),
fileSource(fileSource_),
glyphAtlas(1024, 1024),
spriteAtlas(512, 512),
texturePool(std::make_shared<TexturePool>()),
@@ -120,7 +121,6 @@ Map::~Map() {
glyphStore.reset();
style.reset();
texturePool.reset();
fileSource.reset();
workers.reset();
uv_run(**loop, UV_RUN_DEFAULT);
@@ -150,7 +150,6 @@ void Map::start(bool startPaused) {
// Remove all of these to make sure they are destructed in the correct thread.
glyphStore.reset();
fileSource.reset();
style.reset();
workers.reset();
activeSources.clear();
@@ -371,11 +370,9 @@ void Map::terminate() {
void Map::setReachability(bool reachable) {
// Note: This function may be called from *any* thread.
if (reachable) {
if (fileSource) {
fileSource->prepare([&]() {
fileSource->retryAllPending();
});
}
fileSource.prepare([&]() {
fileSource.retryAllPending();
});
}
}
@@ -407,11 +404,11 @@ void Map::setStyleJSON(std::string newStyleJSON, const std::string &base) {
}
style->loadJSON((const uint8_t *)styleJSON.c_str());
if (!fileSource) {
fileSource = std::make_shared<FileSource>(**loop, platform::defaultCacheDatabase());
glyphStore = std::make_shared<GlyphStore>(*fileSource);
if (!fileSource.hasLoop()) {
fileSource.setLoop(**loop);
glyphStore = std::make_shared<GlyphStore>(fileSource);
}
fileSource->setBase(base);
fileSource.setBase(base);
glyphStore->setURL(util::mapbox::normalizeGlyphsURL(style->glyph_url, getAccessToken()));
style->setDefaultTransitionDuration(defaultTransitionDuration);
@@ -447,7 +444,7 @@ util::ptr<Sprite> Map::getSprite() {
const float pixelRatio = state.getPixelRatio();
const std::string &sprite_url = style->getSpriteURL();
if (!sprite || sprite->pixelRatio != pixelRatio) {
sprite = Sprite::Create(sprite_url, pixelRatio, *fileSource);
sprite = Sprite::Create(sprite_url, pixelRatio, fileSource);
}
return sprite;
@@ -671,7 +668,7 @@ void Map::updateSources() {
if (source->enabled) {
if (!source->source) {
source->source = std::make_shared<Source>(source->info);
source->source->load(*this, *fileSource);
source->source->load(*this, fileSource);
}
} else {
source->source.reset();
@@ -705,20 +702,20 @@ void Map::updateTiles() {
source->source->update(*this, getWorker(),
style, glyphAtlas, *glyphStore,
spriteAtlas, getSprite(),
*texturePool, *fileSource, [this](){ update(); });
*texturePool, fileSource, [this](){ update(); });
}
}
void Map::prepare() {
if (!fileSource) {
fileSource = std::make_shared<FileSource>(**loop, platform::defaultCacheDatabase());
glyphStore = std::make_shared<GlyphStore>(*fileSource);
if (!fileSource.hasLoop()) {
fileSource.setLoop(**loop);
glyphStore = std::make_shared<GlyphStore>(fileSource);
}
if (!style) {
style = std::make_shared<Style>();
fileSource->request(ResourceType::JSON, styleURL)->onload([&](const Response &res) {
fileSource.request(ResourceType::JSON, styleURL)->onload([&](const Response &res) {
if (res.code == 200) {
// Calculate the base
const size_t pos = styleURL.rfind('/');

View File

@@ -11,6 +11,7 @@
#include <mbgl/platform/default/headless_view.hpp>
#include <mbgl/platform/default/headless_display.hpp>
#include <mbgl/platform/default/caching_http_file_source.hpp>
#include "./fixtures/fixture_log.hpp"
@@ -184,7 +185,8 @@ TEST_P(HeadlessTest, render) {
}
HeadlessView view(env->display);
Map map(view);
CachingHTTPFileSource fileSource(platform::defaultCacheDatabase());
Map map(view, fileSource);
map.setStyleJSON(style, base_directory);
map.setAppliedClasses(classes);