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

osmcache - Fix concurrent access.

parent e330a242
......@@ -6,8 +6,8 @@
"pkgfiles": "2.3.0"
},
"dependencies": {
"loglevel": "",
"node-getopt": ""
"loglevel": "1.4.0",
"node-getopt": "0.2.3"
},
"main": "./server.js",
"scripts": {
......
......@@ -41,6 +41,8 @@ if (opt.options.debug) {
log.setLevel("debug");
}
var activeRequests = {};
var server = http.createServer(function(request, response) {
var page = url.parse(request.url).pathname;
log.debug("page:" + page);
......@@ -64,58 +66,142 @@ var server = http.createServer(function(request, response) {
var ytile = tile[2];
var cacheFile = cacheDir + "/" + zoom + "/" + xtile + "/" + ytile + ".xml";
fs.stat(
cacheFile,
function(err, stats) {
if (err !== null && err.code === 'ENOENT') {
// || !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("myPath: " + myPath);
var osmRequest = 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', () => {
response.writeHead(200, {
var cacheFileLock = cacheFile + ".lock";
var tileId = 'tile_' + zoom + '_' + xtile + '_' + ytile;
if (!fileExists(cacheFile) && !fileExists(cacheFileLock)) {
fs.mkdirParentSync(path.dirname(cacheFileLock));
fs.closeSync(fs.openSync(cacheFileLock, 'w'));
console.log('Lock file (', cacheFileLock, ')');
log.debug('Can not access file ' + cacheFile);
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);
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)
osmReadStream.pipe(fs.createWriteStream(cacheFile), {
end: true
});
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'
});
fs.createReadStream(cacheFile).pipe(response, {
fs.createReadStream(cacheFile).pipe(response_, {
end: true
});
});
});
osmRequest.on('error', function(e) {
log.debug('problem with request: ' + e.message);
}
// delete activeRequests[tileId];
});
osmRequest.end();
} else {
response.writeHead(200, {
'Content-Type': 'text/xml',
'Content-Length': stats.size
});
fs.createReadStream(cacheFile).pipe(response, {
end: true
});
}
// Return osm data
});
activeRequests[tileId].request.on('error', function(e) {
log.debug('problem with request: ' + e.message);
});
activeRequests[tileId].request.end();
}
);
} 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 {
// fallback;
response.writeHead(404, {
......@@ -126,6 +212,14 @@ var server = http.createServer(function(request, response) {
});
server.listen(8082);
function fileExists(filePath) {
try {
return fs.statSync(filePath).isFile();
} catch (err) {
return false;
}
}
function tile2long(x, z) {
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