Add mbcheck.
This commit is contained in:
162
bin/mbcheck
Executable file
162
bin/mbcheck
Executable file
@@ -0,0 +1,162 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
var options = argv = require('optimist').argv,
|
||||
_ = require('underscore'),
|
||||
Step = require('step'),
|
||||
utils = require('..').utils,
|
||||
MBTiles = require('..').MBTiles,
|
||||
mbtiles,
|
||||
tables = [],
|
||||
zooms = [],
|
||||
tiles = [];
|
||||
|
||||
// Show help.
|
||||
if (argv.help || argv._.length === 0) {
|
||||
console.warn('Usage: mbcheck [OPTIONS] [FILE]');
|
||||
utils.table([
|
||||
['--help', 'Show help.']
|
||||
]);
|
||||
process.exit();
|
||||
}
|
||||
|
||||
// Wishlist:
|
||||
// ---------
|
||||
// - check that tiles exist for specified bounds
|
||||
|
||||
Step(
|
||||
function() { mbtiles = new MBTiles(argv._[0], this); },
|
||||
function() { mbtiles.integrity(this); },
|
||||
function(err) {
|
||||
if (err) throw err;
|
||||
mbtiles.exists('tiles', function(err, exists) {
|
||||
if (!exists) throw new Error('`tiles` table does not exist.');
|
||||
this();
|
||||
}.bind(this));
|
||||
},
|
||||
function(err) {
|
||||
if (err) throw err;
|
||||
mbtiles.exists('metadata', function(err, exists) {
|
||||
if (!exists) throw new Error('`metadata` table does not exist.');
|
||||
this();
|
||||
}.bind(this));
|
||||
},
|
||||
function(err) {
|
||||
if (err) throw err;
|
||||
mbtiles.metadata('name', this.parallel());
|
||||
mbtiles.metadata('type', this.parallel());
|
||||
mbtiles.metadata('desciption', this.parallel());
|
||||
mbtiles.metadata('version', this.parallel());
|
||||
mbtiles.metadata('format', this.parallel());
|
||||
mbtiles.metadata('bounds', this.parallel());
|
||||
},
|
||||
function(err, name, type, description, version, format, bounds) {
|
||||
console.warn('');
|
||||
console.warn(' Metadata');
|
||||
utils.table([
|
||||
['name', name],
|
||||
['type', type],
|
||||
['description', description],
|
||||
['vesion', version],
|
||||
['format', format],
|
||||
['bounds', bounds]
|
||||
]);
|
||||
this();
|
||||
},
|
||||
function(err) {
|
||||
if (err) throw err;
|
||||
Step(
|
||||
function() {
|
||||
var group = this.group(),
|
||||
query = mbtiles.db.prepare(
|
||||
'SELECT zoom_level AS zoom, ' +
|
||||
'COUNT(zoom_level) AS count ' +
|
||||
'FROM tiles ' +
|
||||
'WHERE zoom_level = ?'
|
||||
);
|
||||
for (var i = 0; i < 30; i++) {
|
||||
query.get(i, group());
|
||||
}
|
||||
query.finalize();
|
||||
},
|
||||
function(err, rows) {
|
||||
if (err) throw err;
|
||||
zooms = rows;
|
||||
do {
|
||||
var last = zooms.pop();
|
||||
if (last.count) zooms.push(last);
|
||||
} while(!last.count);
|
||||
do {
|
||||
var first = zooms.shift();
|
||||
if (first.count) zooms.unshift(first);
|
||||
} while(!first.count);
|
||||
this();
|
||||
}.bind(this)
|
||||
);
|
||||
},
|
||||
function(err) {
|
||||
if (err) throw err;
|
||||
Step(
|
||||
function() {
|
||||
var group = this.group(),
|
||||
query = mbtiles.db.prepare(
|
||||
'SELECT MAX(tile_column) AS maxx, ' +
|
||||
'MIN(tile_column) AS minx, ' +
|
||||
'MAX(tile_row) AS maxy, ' +
|
||||
'MIN(tile_row) AS miny, ' +
|
||||
'zoom_level AS zoom ' +
|
||||
'FROM tiles ' +
|
||||
'WHERE zoom_level = ?'
|
||||
);
|
||||
for (var i = 0; i < zooms.length; i++) {
|
||||
query.get(zooms[i].zoom, group());
|
||||
}
|
||||
query.finalize();
|
||||
},
|
||||
function(err, rows) {
|
||||
if (err) throw err;
|
||||
|
||||
var group = this.group(),
|
||||
query = mbtiles.db.prepare(
|
||||
'SELECT zoom_level AS zoom, ' +
|
||||
'COUNT(zoom_level) AS count, ' +
|
||||
'? AS expected ' +
|
||||
'FROM tiles ' +
|
||||
'WHERE zoom_level = ? AND ' +
|
||||
'tile_column >= ? AND ' +
|
||||
'tile_column <= ? AND ' +
|
||||
'tile_row >= ? AND ' +
|
||||
'tile_row <= ?'
|
||||
);
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
var expected = (rows[i].maxx - rows[i].minx + 1) * (rows[i].maxy - rows[i].miny + 1);
|
||||
query.get(
|
||||
expected,
|
||||
rows[i].zoom,
|
||||
rows[i].minx,
|
||||
rows[i].maxx,
|
||||
rows[i].miny,
|
||||
rows[i].maxy,
|
||||
group()
|
||||
);
|
||||
}
|
||||
query.finalize();
|
||||
},
|
||||
function(err, rows) {
|
||||
if (err) throw err;
|
||||
console.warn('');
|
||||
var output = [];
|
||||
output.push(['Z', 'Tiles', 'Missing']);
|
||||
_(rows).each(function(row, index) {
|
||||
output.push([
|
||||
row.zoom,
|
||||
zooms[index].count,
|
||||
row.expected - row.count
|
||||
]);
|
||||
});
|
||||
utils.table(output);
|
||||
this();
|
||||
}.bind(this)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
2
index.js
2
index.js
@@ -1,8 +1,10 @@
|
||||
var MBTiles = require('./lib/mbtiles'),
|
||||
utils = require('./lib/utils'),
|
||||
Step = require('step');
|
||||
|
||||
module.exports = {
|
||||
MBTiles: MBTiles,
|
||||
utils: utils,
|
||||
pool: function(datasource) {
|
||||
return {
|
||||
create: function(callback) {
|
||||
|
||||
@@ -34,6 +34,17 @@ MBTiles.prototype.exists = function(table, callback) {
|
||||
}
|
||||
};
|
||||
|
||||
// DB integrity check.
|
||||
MBTiles.prototype.integrity = function(callback) {
|
||||
this.db.get('PRAGMA quick_check(1)', function(err, row) {
|
||||
if (!(row && row.integrity_check && row.integrity_check === 'ok')) {
|
||||
callback(new Error('Corrupted database.'));
|
||||
} else {
|
||||
callback(null, true);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Setup schema, indices, views for a new mbtiles database.
|
||||
// Sets the synchronous flag to OFF for (much) faster inserts.
|
||||
// See http://www.sqlite3.org/pragma.html#pragma_synchronous
|
||||
|
||||
21
lib/utils.js
Normal file
21
lib/utils.js
Normal file
@@ -0,0 +1,21 @@
|
||||
var utils = {};
|
||||
|
||||
utils.table = function(fields) {
|
||||
if (!fields[0]) return;
|
||||
var lengths = fields[0].map(function(val, i) {
|
||||
return Math.max.apply(Math, fields.map(function(field) {
|
||||
if (field[i] === undefined) field[i] = '';
|
||||
return field[i].toString().length;
|
||||
}));
|
||||
});
|
||||
fields.forEach(function(field) {
|
||||
console.warn(
|
||||
' ' + field.map(function(val, i) {
|
||||
if (i >= lengths.length - 1) return val;
|
||||
return val + Array(lengths[i] - val.toString().length + 1).join(' ');
|
||||
}).join(' ')
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = utils;
|
||||
@@ -17,6 +17,7 @@
|
||||
"Young Hahn <yhahn>"
|
||||
],
|
||||
"dependencies": {
|
||||
"optimist": "0.2.x",
|
||||
"sqlite3": "2.0.x",
|
||||
"step": "0.0.x",
|
||||
"underscore": "1.1.x",
|
||||
|
||||
Reference in New Issue
Block a user