Commit 755a5574 authored by Clément Igonet's avatar Clément Igonet

osmcache - Fix concurrent access.

parent e330a242
...@@ -6,8 +6,8 @@ ...@@ -6,8 +6,8 @@
"pkgfiles": "2.3.0" "pkgfiles": "2.3.0"
}, },
"dependencies": { "dependencies": {
"loglevel": "", "loglevel": "1.4.0",
"node-getopt": "" "node-getopt": "0.2.3"
}, },
"main": "./server.js", "main": "./server.js",
"scripts": { "scripts": {
......
...@@ -41,6 +41,8 @@ if (opt.options.debug) { ...@@ -41,6 +41,8 @@ if (opt.options.debug) {
log.setLevel("debug"); log.setLevel("debug");
} }
var activeRequests = {};
var server = http.createServer(function(request, response) { var server = http.createServer(function(request, response) {
var page = url.parse(request.url).pathname; var page = url.parse(request.url).pathname;
log.debug("page:" + page); log.debug("page:" + page);
...@@ -64,58 +66,142 @@ var server = http.createServer(function(request, response) { ...@@ -64,58 +66,142 @@ var server = http.createServer(function(request, response) {
var ytile = tile[2]; var ytile = tile[2];
var cacheFile = cacheDir + "/" + zoom + "/" + xtile + "/" + ytile + ".xml"; var cacheFile = cacheDir + "/" + zoom + "/" + xtile + "/" + ytile + ".xml";
fs.stat( var cacheFileLock = cacheFile + ".lock";
cacheFile, var tileId = 'tile_' + zoom + '_' + xtile + '_' + ytile;
function(err, stats) {
if (err !== null && err.code === 'ENOENT') { if (!fileExists(cacheFile) && !fileExists(cacheFileLock)) {
// || !stats.isFile() fs.mkdirParentSync(path.dirname(cacheFileLock));
// TODO: reset file fs.closeSync(fs.openSync(cacheFileLock, 'w'));
log.debug('Can not access file ' + cacheFile); console.log('Lock file (', cacheFileLock, ')');
log.debug('err: ' + err); log.debug('Can not access file ' + cacheFile);
// Get data from external overpass API var myPath = "/api/0.6/map?bbox=" +
// and write it to cache file tile2long(+xtile, zoom) + "," +
var myPath = "/api/0.6/map?bbox=" + tile2lat(+ytile + 1, zoom) + "," +
tile2long(+xtile, zoom) + "," + tile2long(+xtile + 1, zoom) + "," +
tile2lat(+ytile + 1, zoom) + "," + tile2lat(+ytile, zoom);
tile2long(+xtile + 1, zoom) + "," + console.log('cacheFile:', cacheFile);
tile2lat(+ytile, zoom); console.log("myPath: " + myPath);
console.log("myPath: " + myPath); if (!activeRequests.hasOwnProperty(tileId)) {
var osmRequest = http.request({ activeRequests[tileId] = {};
hostname: 'www.openstreetmap.org', activeRequests[tileId].responses = [];
port: 80, activeRequests[tileId].request = http.request({
path: myPath, hostname: 'www.openstreetmap.org',
method: 'GET' port: 80,
}, function(osmReadStream) { path: myPath,
console.log("pipe to :" + cacheFile) method: 'GET'
fs.mkdirParentSync(path.dirname(cacheFile)); }, function(osmReadStream) {
osmReadStream.pipe(fs.createWriteStream(cacheFile), { console.log("pipe to :" + cacheFile)
end: true osmReadStream.pipe(fs.createWriteStream(cacheFile), {
}); end: true
osmReadStream.on('end', () => { });
response.writeHead(200, { osmReadStream.on('end', () => {
fs.unlinkSync(cacheFileLock);
console.log('Unlock file');
while (activeRequests[tileId].responses.length > 0) {
console.log('Give response (', tileId, ')');
var response_ = activeRequests[tileId].responses.pop();
response_.writeHead(200, {
'Content-Type': 'text/xml' 'Content-Type': 'text/xml'
}); });
fs.createReadStream(cacheFile).pipe(response, { fs.createReadStream(cacheFile).pipe(response_, {
end: true end: true
}); });
}); }
}); // delete activeRequests[tileId];
osmRequest.on('error', function(e) {
log.debug('problem with request: ' + e.message);
}); });
osmRequest.end(); });
} else { activeRequests[tileId].request.on('error', function(e) {
response.writeHead(200, { log.debug('problem with request: ' + e.message);
'Content-Type': 'text/xml', });
'Content-Length': stats.size activeRequests[tileId].request.end();
});
fs.createReadStream(cacheFile).pipe(response, {
end: true
});
}
// Return osm data
} }
); } else if (fileExists(cacheFileLock)) {
console.log('File locked, waiting for end (', tileId, ')');
// console.log('activeRequests:', JSON.stringify(activeRequests));
activeRequests[tileId].responses.push(response);
} else {
console.log('No blockers, give response (', tileId, ')');
response.writeHead(200, {
'Content-Type': 'text/xml'
});
fs.createReadStream(cacheFile).pipe(response, {
end: true
});
}
// fs.stat(
// cacheFile,
// function(err, stats) {
// if (err !== null && err.code === 'ENOENT') {
// fs.closeSync(fs.openSync(cacheFile + '.lock', 'w'));
// // || !stats.isFile()
// // TODO: reset file
// log.debug('Can not access file ' + cacheFile);
// log.debug('err: ' + err);
// // Get data from external overpass API
// // and write it to cache file
// var myPath = "/api/0.6/map?bbox=" +
// tile2long(+xtile, zoom) + "," +
// tile2lat(+ytile + 1, zoom) + "," +
// tile2long(+xtile + 1, zoom) + "," +
// tile2lat(+ytile, zoom);
// console.log('cacheFile:', cacheFile);
// console.log("myPath: " + myPath);
// var tileId = 'tile_' + zoom + '_' + xtile + '_' + ytile;
// // var osmRequest = http.request({
// if (!activeRequests.hasOwnProperty(tileId)) {
// activeRequests[tileId] = {};
// activeRequests[tileId].responses = [];
// activeRequests[tileId].request = http.request({
// hostname: 'www.openstreetmap.org',
// port: 80,
// path: myPath,
// method: 'GET'
// }, function(osmReadStream) {
// console.log("pipe to :" + cacheFile)
// fs.mkdirParentSync(path.dirname(cacheFile));
// osmReadStream.pipe(fs.createWriteStream(cacheFile), {
// end: true
// });
// osmReadStream.on('end', () => {
// // activeRequests[myPath].responses
// while (activeRequests[tileId].responses.length > 0) {
// var response_ = activeRequests[tileId].responses.pop();
// // activeRequests[tileId].responses.splice(0, 1);
// response_.writeHead(200, {
// 'Content-Type': 'text/xml'
// });
// fs.createReadStream(cacheFile).pipe(response_, {
// end: true
// });
// }
// // delete activeRequests[tileId];
// });
// });
// // responses: []
// // };
// }
// activeRequests[tileId].responses.push(response);
// // else {
// // }
// activeRequests[tileId].request.on('error', function(e) {
// log.debug('problem with request: ' + e.message);
// });
// activeRequests[tileId].request.end();
// } else {
// response.writeHead(200, {
// 'Content-Type': 'text/xml',
// 'Content-Length': stats.size
// });
// fs.createReadStream(cacheFile).pipe(response, {
// end: true
// });
// }
// // Return osm data
// }
// );
} else { } else {
// fallback; // fallback;
response.writeHead(404, { response.writeHead(404, {
...@@ -126,6 +212,14 @@ var server = http.createServer(function(request, response) { ...@@ -126,6 +212,14 @@ var server = http.createServer(function(request, response) {
}); });
server.listen(8082); server.listen(8082);
function fileExists(filePath) {
try {
return fs.statSync(filePath).isFile();
} catch (err) {
return false;
}
}
function tile2long(x, z) { function tile2long(x, z) {
return (x / Math.pow(2, z) * 360) % 360 - 180; return (x / Math.pow(2, z) * 360) % 360 - 180;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment