diff --git a/lib/db/lowlevelup.js b/lib/db/lowlevelup.js index afebb8bb..63ee4373 100644 --- a/lib/db/lowlevelup.js +++ b/lib/db/lowlevelup.js @@ -106,6 +106,23 @@ LowlevelUp.prototype.repair = function repair(callback) { this.backend.repair(this.location, callback); }; +/** + * Backup the database. + * @param {String} path + * @param {Function} callback + */ + +LowlevelUp.prototype.backup = function backup(path, callback) { + assert(!this.loading); + assert(!this.closing); + assert(this.loaded); + + if (!this.binding.backup) + return this.clone(path, callback); + + this.binding.backup(path, callback); +}; + /** * Retrieve a record from the database. * @param {String} key @@ -379,6 +396,63 @@ LowlevelUp.prototype.checkVersion = function checkVersion(key, version, callback }); }; +/** + * Clone the database. + * @param {String} path + * @param {Function} callback + */ + +LowlevelUp.prototype.clone = function clone(path, callback) { + var self = this; + var options = { keys: true, values: true }; + var tmp, batch; + + assert(!this.loading); + assert(!this.closing); + assert(this.loaded); + + this.options.createIfMissing = true; + this.options.errorIfExists = true; + + tmp = new LowlevelUp(path, this.options); + + function done(err) { + tmp.close(function(e) { + if (e) + return callback(e); + callback(err); + }); + } + + tmp.open(function(err) { + if (err) + return callback(err); + + batch = tmp.batch(); + + self.each(options, function(key, value, next, i) { + batch.put(key, value); + + if (i % 1000 === 0) { + batch.write(function(err) { + if (err) + return next(err); + batch = tmp.batch(); + next(); + }); + return; + } + + next(); + }, function(err) { + if (err) + return done(err); + + batch.write(done); + }); + }); +}; + /* * Helpers */ diff --git a/lib/http/rpc.js b/lib/http/rpc.js index 33cf9efa..f68cb152 100644 --- a/lib/http/rpc.js +++ b/lib/http/rpc.js @@ -2574,10 +2574,14 @@ RPC.prototype.addwitnessaddress = function addwitnessaddress(args, callback) { }; RPC.prototype.backupwallet = function backupwallet(args, callback) { + var dest; + if (args.help || args.length !== 1) return callback(new RPCError('backupwallet "destination"')); - // Unlikely to be implemented. - callback(new Error('Not implemented.')); + + dest = toString(args[0]); + + this.walletdb.db.backup(dest, callback); }; RPC.prototype.dumpprivkey = function dumpprivkey(args, callback) {