cpuminer: improve start/stop handling.
This commit is contained in:
parent
aa7e550f91
commit
b104e664a7
@ -13,6 +13,7 @@ var co = require('../utils/co');
|
|||||||
var AsyncObject = require('../utils/asyncobject');
|
var AsyncObject = require('../utils/asyncobject');
|
||||||
var workerPool = require('../workers/workerpool').pool;
|
var workerPool = require('../workers/workerpool').pool;
|
||||||
var mine = require('./mine');
|
var mine = require('./mine');
|
||||||
|
var Lock = require('../utils/lock');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CPU miner.
|
* CPU miner.
|
||||||
@ -33,11 +34,13 @@ function CPUMiner(miner) {
|
|||||||
this.network = this.miner.network;
|
this.network = this.miner.network;
|
||||||
this.logger = this.miner.logger;
|
this.logger = this.miner.logger;
|
||||||
this.chain = this.miner.chain;
|
this.chain = this.miner.chain;
|
||||||
|
this.locker = new Lock();
|
||||||
|
|
||||||
this.running = false;
|
this.running = false;
|
||||||
this.stopping = false;
|
this.stopping = false;
|
||||||
this.job = null;
|
this.job = null;
|
||||||
this.since = 0;
|
this.since = 0;
|
||||||
|
this.stopJob = null;
|
||||||
|
|
||||||
this._init();
|
this._init();
|
||||||
}
|
}
|
||||||
@ -67,25 +70,6 @@ CPUMiner.prototype._init = function _init() {
|
|||||||
if (self.job.attempt.prevBlock === tip.prevBlock)
|
if (self.job.attempt.prevBlock === tip.prevBlock)
|
||||||
self.job.destroy();
|
self.job.destroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.on('block', function(block, entry) {
|
|
||||||
// Emit the block hex as a failsafe (in case we can't send it)
|
|
||||||
self.logger.info('Found block: %d (%s).', entry.height, entry.rhash());
|
|
||||||
self.logger.debug('Raw: %s', block.toRaw().toString('hex'));
|
|
||||||
});
|
|
||||||
|
|
||||||
this.on('status', function(job, hashes, hashrate) {
|
|
||||||
var attempt = job.attempt;
|
|
||||||
var tip = util.revHex(attempt.prevBlock);
|
|
||||||
|
|
||||||
self.logger.info(
|
|
||||||
'Miner: hashrate=%dkhs hashes=%d target=%d height=%d best=%s',
|
|
||||||
Math.floor(hashrate / 1000),
|
|
||||||
hashes,
|
|
||||||
attempt.bits,
|
|
||||||
attempt.height,
|
|
||||||
tip);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -106,14 +90,6 @@ CPUMiner.prototype._open = co(function* open() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
CPUMiner.prototype._close = co(function* close() {
|
CPUMiner.prototype._close = co(function* close() {
|
||||||
if (!this.running)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (this.stopping) {
|
|
||||||
yield this._onStop();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
yield this.stop();
|
yield this.stop();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -124,7 +100,7 @@ CPUMiner.prototype._close = co(function* close() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
CPUMiner.prototype.start = co(function* start() {
|
CPUMiner.prototype.start = co(function* start() {
|
||||||
var block, entry;
|
var block, entry, job;
|
||||||
|
|
||||||
assert(!this.running, 'Miner is already running.');
|
assert(!this.running, 'Miner is already running.');
|
||||||
|
|
||||||
@ -140,7 +116,7 @@ CPUMiner.prototype.start = co(function* start() {
|
|||||||
if (this.stopping)
|
if (this.stopping)
|
||||||
break;
|
break;
|
||||||
this.emit('error', e);
|
this.emit('error', e);
|
||||||
continue;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.stopping)
|
if (this.stopping)
|
||||||
@ -152,7 +128,7 @@ CPUMiner.prototype.start = co(function* start() {
|
|||||||
if (this.stopping)
|
if (this.stopping)
|
||||||
break;
|
break;
|
||||||
this.emit('error', e);
|
this.emit('error', e);
|
||||||
continue;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.stopping)
|
if (this.stopping)
|
||||||
@ -166,22 +142,38 @@ CPUMiner.prototype.start = co(function* start() {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (this.stopping)
|
if (this.stopping)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if (e.type === 'VerifyError') {
|
||||||
|
this.logger.warning('Mined an invalid block!');
|
||||||
|
this.logger.error(e);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
this.emit('error', e);
|
this.emit('error', e);
|
||||||
continue;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
this.logger.warning('Mined a bad-prevblk (race condition?)');
|
this.logger.warning('Mined a bad-prevblk (race condition?)');
|
||||||
continue;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.stopping)
|
if (this.stopping)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// Log the block hex as a failsafe (in case we can't send it).
|
||||||
|
this.logger.info('Found block: %d (%s).', entry.height, entry.rhash());
|
||||||
|
this.logger.debug('Raw: %s', block.toRaw().toString('hex'));
|
||||||
|
|
||||||
this.emit('block', block, entry);
|
this.emit('block', block, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.emit('done');
|
job = this.stopJob;
|
||||||
|
|
||||||
|
if (job) {
|
||||||
|
this.stopJob = null;
|
||||||
|
job.resolve();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -191,18 +183,34 @@ CPUMiner.prototype.start = co(function* start() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
CPUMiner.prototype.stop = co(function* stop() {
|
CPUMiner.prototype.stop = co(function* stop() {
|
||||||
|
var unlock = yield this.locker.lock();
|
||||||
|
try {
|
||||||
|
return yield this._stop();
|
||||||
|
} finally {
|
||||||
|
unlock();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop mining (without a lock).
|
||||||
|
* @method
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
|
||||||
|
CPUMiner.prototype.stop = co(function* stop() {
|
||||||
|
if (!this.running)
|
||||||
|
return;
|
||||||
|
|
||||||
assert(this.running, 'Miner is not running.');
|
assert(this.running, 'Miner is not running.');
|
||||||
assert(!this.stopping, 'Miner is already stopping.');
|
assert(!this.stopping, 'Miner is already stopping.');
|
||||||
|
|
||||||
this.stopping = true;
|
this.stopping = true;
|
||||||
|
|
||||||
yield this._onDone();
|
yield this.wait();
|
||||||
|
|
||||||
this.running = false;
|
this.running = false;
|
||||||
this.stopping = false;
|
this.stopping = false;
|
||||||
this.job = null;
|
this.job = null;
|
||||||
|
|
||||||
this.emit('stop');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -211,23 +219,11 @@ CPUMiner.prototype.stop = co(function* stop() {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CPUMiner.prototype._onDone = function _onDone() {
|
CPUMiner.prototype.wait = function wait() {
|
||||||
var self = this;
|
var self = this;
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
self.once('done', resolve);
|
assert(!self.stopJob);
|
||||||
});
|
self.stopJob = co.job(resolve, reject);
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wait for `stop` event.
|
|
||||||
* @private
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
|
|
||||||
CPUMiner.prototype._onStop = function _onStop() {
|
|
||||||
var self = this;
|
|
||||||
return new Promise(function(resolve, reject) {
|
|
||||||
self.once('stop', resolve);
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -407,7 +403,20 @@ CPUMiner.prototype.iterate = function iterate(job) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
CPUMiner.prototype.sendStatus = function sendStatus(job, nonce) {
|
CPUMiner.prototype.sendStatus = function sendStatus(job, nonce) {
|
||||||
this.emit('status', job, job.getHashes(nonce), job.getRate(nonce));
|
var attempt = job.attempt;
|
||||||
|
var tip = util.revHex(attempt.prevBlock);
|
||||||
|
var hashes = job.getHashes(nonce);
|
||||||
|
var hashrate = job.getRate(nonce);
|
||||||
|
|
||||||
|
this.logger.info(
|
||||||
|
'Status: hashrate=%dkhs hashes=%d target=%d height=%d best=%s',
|
||||||
|
Math.floor(hashrate / 1000),
|
||||||
|
hashes,
|
||||||
|
attempt.bits,
|
||||||
|
attempt.height,
|
||||||
|
tip);
|
||||||
|
|
||||||
|
this.emit('status', job, hash, hashrate);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -498,8 +507,7 @@ CPUJob.prototype.refresh = function refresh() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
CPUJob.prototype.updateNonce = function updateNonce() {
|
CPUJob.prototype.updateNonce = function updateNonce() {
|
||||||
this.nonce2++;
|
if (++this.nonce2 === 0x100000000) {
|
||||||
if (this.nonce2 === 0x100000000) {
|
|
||||||
this.nonce2 = 0;
|
this.nonce2 = 0;
|
||||||
this.nonce1++;
|
this.nonce1++;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,10 +42,27 @@ function Miner(options) {
|
|||||||
this.addresses = this.options.addresses;
|
this.addresses = this.options.addresses;
|
||||||
this.locker = this.chain.locker;
|
this.locker = this.chain.locker;
|
||||||
this.cpu = new CPUMiner(this);
|
this.cpu = new CPUMiner(this);
|
||||||
|
|
||||||
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
util.inherits(Miner, AsyncObject);
|
util.inherits(Miner, AsyncObject);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open the miner, wait for the chain and mempool to load.
|
||||||
|
* @method
|
||||||
|
* @alias module:mining.Miner#open
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
|
||||||
|
Miner.prototype.init = function init() {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
this.cpu.on('error', function(err) {
|
||||||
|
self.emit('error', err);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open the miner, wait for the chain and mempool to load.
|
* Open the miner, wait for the chain and mempool to load.
|
||||||
* @method
|
* @method
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user