Add locking to mbtiles commits -- sqlite3 doesn't allow concurrent transactions.

This commit is contained in:
Young Hahn
2014-09-30 11:52:04 -04:00
parent 8a7c3da9f3
commit a375ae1df0
2 changed files with 54 additions and 6 deletions

View File

@@ -368,11 +368,23 @@ MBTiles.prototype.write = function(table, id, row, callback) {
// - @param {Function(err)} callback
MBTiles.prototype._commit = function(callback) {
var mbtiles = this;
// If no pending commits our work's done.
if (!mbtiles._pending) return callback();
// If already committing wait in line.
if (mbtiles._committing) return mbtiles.once('commit', function() {
mbtiles._commit(callback);
});
var writes = mbtiles._writes;
mbtiles._clearCaches();
mbtiles._committing = true;
mbtiles._db.serialize(function() {
mbtiles._db.run('BEGIN');
var statements = {};
Object.keys(mbtiles._writes).forEach(function(table) {
Object.keys(writes).forEach(function(table) {
switch (table) {
case 'map':
// Insert map table. This has to be so complicate due to a design flaw
@@ -384,8 +396,8 @@ MBTiles.prototype._commit = function(callback) {
COALESCE(?, (SELECT tile_id FROM map WHERE zoom_level = ? AND tile_column = ? AND tile_row = ?)),\
COALESCE(?, (SELECT grid_id FROM map WHERE zoom_level = ? AND tile_column = ? AND tile_row = ?)))';
statements['map'] = mbtiles._db.prepare(sql);
for (var id in mbtiles._writes[table]) {
var row = mbtiles._writes[table][id];
for (var id in writes[table]) {
var row = writes[table][id];
statements['map'].run(
row.zoom_level, row.tile_column, row.tile_row,
row.tile_id, row.zoom_level, row.tile_column, row.tile_row,
@@ -397,8 +409,8 @@ MBTiles.prototype._commit = function(callback) {
var rows = [];
var args = [];
var fields = [];
for (var id in mbtiles._writes[table]) {
var record = mbtiles._writes[table][id];
for (var id in writes[table]) {
var record = writes[table][id];
var row = [];
for (var field in record) {
row.push(record[field]);
@@ -417,7 +429,11 @@ MBTiles.prototype._commit = function(callback) {
}
});
mbtiles._db.run('COMMIT', callback);
mbtiles._db.run('COMMIT', function(err) {
mbtiles._committing = false;
mbtiles.emit('commit');
callback(err);
});
mbtiles._clearCaches();
});
};