Skip to content

Commit

Permalink
Async queryMany.
Browse files Browse the repository at this point in the history
  • Loading branch information
yhahn committed Sep 12, 2014
1 parent f5494a0 commit ecf1d75
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 48 deletions.
70 changes: 65 additions & 5 deletions src/mapnik_vector_tile.cpp
Expand Up @@ -1065,10 +1065,10 @@ typedef struct {
uv_work_t request;
VectorTile* d;
std::vector<query_lonlat> query;
std::string layer_name;
double tolerance;
std::string layer_name;
std::vector<std::string> fields;
std::vector<query_result> result;
queryMany_result result;
bool error;
std::string error_name;
Persistent<Function> cb;
Expand Down Expand Up @@ -1169,9 +1169,34 @@ NAN_METHOD(VectorTile::queryMany)
}

VectorTile* d = node::ObjectWrap::Unwrap<VectorTile>(args.This());
queryMany_result result = _queryMany(d, query, tolerance, layer_name, fields);
Local<Object> result_obj = _queryManyResultToV8(result);
NanReturnValue(result_obj);

// If last argument is not a function go with sync call.
if (!args[args.Length()-1]->IsFunction()) {
try {
queryMany_result result = _queryMany(d, query, tolerance, layer_name, fields);
Local<Object> result_obj = _queryManyResultToV8(result);
NanReturnValue(result_obj);
}
catch (std::exception const& ex)
{
NanThrowError(ex.what());
NanReturnUndefined();
}
} else {
Local<Value> callback = args[args.Length()-1];
vector_tile_queryMany_baton_t *closure = new vector_tile_queryMany_baton_t();
closure->d = d;
closure->query = query;
closure->tolerance = tolerance;
closure->layer_name = layer_name;
closure->fields = fields;
closure->error = false;
closure->request.data = closure;
NanAssignPersistent(closure->cb, callback.As<Function>());
uv_queue_work(uv_default_loop(), &closure->request, EIO_QueryMany, (uv_after_work_cb)EIO_AfterQueryMany);
d->Ref();
NanReturnUndefined();
}
}

queryMany_result VectorTile::_queryMany(VectorTile* d, std::vector<query_lonlat> query, double tolerance, std::string layer_name, std::vector<std::string> fields) {
Expand Down Expand Up @@ -1361,6 +1386,41 @@ Local<Object> VectorTile::_queryManyResultToV8(queryMany_result result) {
return results;
}

void VectorTile::EIO_QueryMany(uv_work_t* req)
{
vector_tile_queryMany_baton_t *closure = static_cast<vector_tile_queryMany_baton_t *>(req->data);
try
{
closure->result = _queryMany(closure->d, closure->query, closure->tolerance, closure->layer_name, closure->fields);
}
catch (std::exception const& ex)
{
closure->error = true;
closure->error_name = ex.what();
}
}

void VectorTile::EIO_AfterQueryMany(uv_work_t* req)
{
NanScope();
vector_tile_queryMany_baton_t *closure = static_cast<vector_tile_queryMany_baton_t *>(req->data);
if (closure->error) {
Local<Value> argv[1] = { NanError(closure->error_name.c_str()) };
NanMakeCallback(NanGetCurrentContext()->Global(), NanNew(closure->cb), 1, argv);
}
else
{
queryMany_result result = closure->result;
Local<Object> obj = _queryManyResultToV8(result);
Local<Value> argv[2] = { NanNull(), obj };
NanMakeCallback(NanGetCurrentContext()->Global(), NanNew(closure->cb), 2, argv);
}

closure->d->Unref();
NanDisposePersistent(closure->cb);
delete closure;
}

NAN_METHOD(VectorTile::toJSON)
{
NanScope();
Expand Down
2 changes: 2 additions & 0 deletions src/mapnik_vector_tile.hpp
Expand Up @@ -54,6 +54,8 @@ class VectorTile: public node::ObjectWrap {
static NAN_METHOD(queryMany);
static queryMany_result _queryMany(VectorTile* d, std::vector<query_lonlat> query, double tolerance, std::string layer_name, std::vector<std::string> fields);
static Local<Object> _queryManyResultToV8(queryMany_result result);
static void EIO_QueryMany(uv_work_t* req);
static void EIO_AfterQueryMany(uv_work_t* req);
static NAN_METHOD(names);
static NAN_METHOD(toGeoJSON);
static NAN_METHOD(addGeoJSON);
Expand Down
115 changes: 72 additions & 43 deletions test/vector-tile.queryMany.test.js
Expand Up @@ -3,47 +3,79 @@ var assert = require('assert');
var path = require('path');

describe('mapnik.VectorTile queryMany', function() {
mapnik.register_datasource(path.join(mapnik.settings.paths.input_plugins,'ogr.input'));
var geojson = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[0,0],
[0.1,0.1],
[20,20],
[20.1,20.1]
]
},
"properties": {
"name": "A"
}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[-40,-40],
[-40.1,-40.1],
[-60,-60],
[-60.1,-60.1]
]
},
"properties": {
"name": "B"
}
}
]
};

it('vtile.queryMany', function(done) {
mapnik.register_datasource(path.join(mapnik.settings.paths.input_plugins,'ogr.input'));
var vtile2 = new mapnik.VectorTile(0,0,0);
var geojson2 = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[0,0],
[0.1,0.1],
[20,20],
[20.1,20.1]
]
},
"properties": {
"name": "A"
}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[-40,-40],
[-40.1,-40.1],
[-60,-60],
[-60.1,-60.1]
]
},
"properties": {
"name": "B"
}
}
]
};
vtile2.addGeoJSON(JSON.stringify(geojson2),"layer-name");
var manyResults = vtile2.queryMany([[0,0],[0,0],[-40,-40]],{tolerance:1,fields:['name'],layer:'layer-name'});
var vtile = new mapnik.VectorTile(0,0,0);
vtile.addGeoJSON(JSON.stringify(geojson),"layer-name");
var manyResults = vtile.queryMany([[0,0],[0,0],[-40,-40]],{tolerance:1,fields:['name'],layer:'layer-name'});
check(manyResults);
done();
});

it('vtile.queryMany async', function(done) {
var vtile = new mapnik.VectorTile(0,0,0);
vtile.addGeoJSON(JSON.stringify(geojson),"layer-name");
vtile.queryMany([[0,0],[0,0],[-40,-40]],{tolerance:1,fields:['name'],layer:'layer-name'}, function(err, manyResults) {
assert.ifError(err);
check(manyResults);
done();
});
});

it('vtile.queryMany concurrent x4', function(done) {
var remaining = 4;
function run() {
var vtile = new mapnik.VectorTile(0,0,0);
vtile.addGeoJSON(JSON.stringify(geojson),"layer-name");
vtile.queryMany([[0,0],[0,0],[-40,-40]],{tolerance:1,fields:['name'],layer:'layer-name'}, function(err, manyResults) {
assert.ifError(err);
check(manyResults);
if (!--remaining) done();
});
}
run();
run();
run();
run();
});

function check(manyResults) {
assert.equal(Object.keys(manyResults.hits).length, 3);

assert.equal(manyResults.hits[0].length, 2);
Expand Down Expand Up @@ -76,8 +108,5 @@ describe('mapnik.VectorTile queryMany', function() {
assert.equal(manyResults.features[1].id(),2);
assert.equal(manyResults.features[1].layer, 'layer-name');
assert.deepEqual(manyResults.features[1].attributes(), { name: 'B' });

done();
});

}
});

0 comments on commit ecf1d75

Please sign in to comment.