readme. bitcoindjs.stop. building.

This commit is contained in:
Christopher Jeffrey 2014-09-11 17:18:36 -07:00
parent ea706e329b
commit 2de298bbc3
5 changed files with 199 additions and 29 deletions

View File

@ -4,39 +4,58 @@ Bitcoind as a node.js module.
## Building
### bitcoind:
### bitcoind
- NOTE (to self): Arch is using bitcoin-daemon 0.9.2.1, the latest boost headers
in Arch should be correct.
Cloning libbitcoind:
``` bash
$ cd ~/bitcoin
$ git clean -xdf
$ cd ~
$ git clone git@github.com:bitpay/libbitcoind.git bitcoin
$ cd bitcoin
```
...
This is a fork of bitcoin v0.9.0 right now, but it has the ability to compile
bitcoind as a shared object. This may not be ideal yet.
$ git checkout v0.9.2.1
OR:
$ git checkout v0.9.0
#### Compiling bticoind as a library
...
``` bash
# ensure clean up
$ make clean
$ find ~/bitcoin -type f -name '*.o' -or -name '*.so' -print0 | xargs -0 rm -f
# create configure file
$ ./autogen.sh
...
# configure as a library with -fPIC on all object files
# use --with-incompatible-bdb if necessary
# use --prefix=/usr if necessary
$ ./configure --enable-library --with-incompatible-bdb
$ ./configure --with-incompatible-bdb --prefix=/usr
OR:
$ ./configure --prefix=/usr
...
$ time make
# build libbitcoind.so
$ time make library
real 31m33.128s
user 16m23.930s
sys 2m52.310s
```
`--enable-library` will compile all object files with `-fPIC` (Position
Independent Code - needed to create a shared object).
`make library` will then compile `./src/libbitcoind.so` (with `-shared -fPIC`),
linking to all the freshly compiled PIC object files.
Without `--enable-library`, the Makefile with compile bitcoind with -fPIE
(Position Independent for Executable), this allows compiling of bitcoind.
#### Todo
- Find a way to compile bitcoind and libbitcoind.so at the same time without
recompiling object files each time?
### bitcoind.js:
- NOTE: This will eventually try to include our included version of boost.
@ -47,6 +66,30 @@ $ cd ~/work/node_modules/bitcoind.js
$ PYTHON=/usr/bin/python2.7 make gyp
```
#### Running bitcoind.js
You can run bitcoind.js to start downloading the blockchain by doing:
``` bash
$ node example/ &
bitcoind: log pipe opened: 12
bitcoind: status="start_node(): bitcoind opened."
```
However, if you look at the bitcoind log files:
``` bash
$ tail -f ~/.bitcoin/debug.log
connect() to [2001:470:c1f2:3::201]:8333 failed: 101
connect() to [2001:470:6c:778::2]:8333 failed: 101
connect() to [2001:470:c1f2:3::201]:8333 failed: 101
```
Right now, the `connect(3)` call is failing due to some conflict with node or
libuv I'm guessing. This is being investigated.
^C (SIGINT) will call `StartShutdown()` in bitcoind on the node thread pool.
## Contribution and License Agreement
If you contribute code to this project, you are implicitly allowing your code

View File

@ -15,6 +15,7 @@
'defines': [
'HAVE_WORKING_BOOST_SLEEP',
#'HAVE_WORKING_BOOST_SLEEP_FOR',
'ENABLE_WALLET',
],
'cflags_cc': [
'-fexceptions',

View File

@ -2,10 +2,18 @@
var bitcoind = require('../')();
bitcoind.on('error', function(err) {
console.log('bitcoind: error="%s"', err.message);
bitcoind.start(function(err) {
bitcoind.on('error', function(err) {
console.log('bitcoind: error="%s"', err.message);
});
bitcoind.on('open', function(status) {
console.log('bitcoind: status="%s"', status);
});
});
bitcoind.on('open', function(status) {
console.log('bitcoind: status="%s"', status);
process.on('SIGINT', function() {
return bitcoind.stop(function(err) {
if (err) throw err;
return process.exit(0);
});
});

View File

@ -23,13 +23,23 @@ function Bitcoin(options) {
EventEmitter.call(this);
this.options = options;
}
Bitcoin.prototype.__proto__ = EventEmitter.prototype;
Bitcoin.prototype.start = function(callback) {
var self = this;
this.log_pipe = bitcoindjs.start(function(err, status) {
if (callback) {
callback(err);
callback = null;
}
if (err) {
self.emit('error', err);
return;
} else {
self.emit('open', status);
}
self.emit('open', status);
});
// bitcoind's boost threads aren't in the thread pool
@ -38,10 +48,8 @@ function Bitcoin(options) {
;
}, 10000);
this.log('log pipe opened: %d', this.log_pipe);
}
Bitcoin.prototype.__proto__ = EventEmitter.prototype;
return this.log('log pipe opened: %d', this.log_pipe);
};
Bitcoin.prototype.log =
Bitcoin.prototype.info = function() {
@ -62,10 +70,20 @@ Bitcoin.prototype.error = function() {
return process.stderr.write('bitcoind: ' + out + '\n');
};
Bitcoin.prototype.close = function() {
Bitcoin.prototype.stop =
Bitcoin.prototype.close = function(callback) {
var self = this;
clearInterval(this._interval);
delete this._interval;
// XXX Call bitcoind's shutdown here
return bitcoindjs.stop(function(err, status) {
if (err) {
self.error(err.message);
} else {
self.log(status);
}
if (!callback) return;
return callback(err, status);
});
};
/**

View File

@ -78,8 +78,8 @@ extern void (ThreadImport)(std::vector<boost::filesystem::path>);
extern void (DetectShutdownThread)(boost::thread_group*);
extern void (StartNode)(boost::thread_group&);
extern void (ThreadScriptCheck)();
extern void (StartShutdown)();
extern int nScriptCheckThreads;
// extern const int DEFAULT_SCRIPTCHECK_THREADS; // static!!
#ifdef ENABLE_WALLET
extern std::string strWalletFile;
extern CWallet *pwalletMain;
@ -108,6 +108,12 @@ async_start_node_work(uv_work_t *req);
static void
async_start_node_after(uv_work_t *req);
static void
async_stop_node_work(uv_work_t *req);
static void
async_stop_node_after(uv_work_t *req);
static int
start_node(void);
@ -275,6 +281,8 @@ async_start_node_after(uv_work_t *req) {
static int
start_node(void) {
boost::thread_group threadGroup;
// XXX Run this in a node thread instead to keep the event loop open:
boost::thread *detectShutdownThread = NULL;
detectShutdownThread = new boost::thread(
boost::bind(&DetectShutdownThread, &threadGroup));
@ -451,6 +459,97 @@ async_parse_logs_after(uv_work_t *req) {
delete req;
}
/**
* StopBitcoind
* bitcoind.stop(callback)
*/
NAN_METHOD(StopBitcoind) {
NanScope();
if (args.Length() < 1 || !args[0]->IsFunction()) {
return NanThrowError(
"Usage: bitcoind.stop(callback)");
}
Local<Function> callback = Local<Function>::Cast(args[0]);
//
// Run bitcoind's StartShutdown() on a separate thread.
//
async_node_data* data_stop_node = new async_node_data();
data_stop_node->err_msg = NULL;
data_stop_node->result = NULL;
data_stop_node->callback = Persistent<Function>::New(callback);
uv_work_t *req_stop_node = new uv_work_t();
req_stop_node->data = data_stop_node;
int status_stop_node = uv_queue_work(uv_default_loop(),
req_stop_node, async_stop_node_work,
(uv_after_work_cb)async_stop_node_after);
assert(status_stop_node == 0);
NanReturnValue(Undefined());
}
/**
* async_stop_node_work()
* Call StartShutdown() to join the boost threads, which will call Shutdown().
*/
static void
async_stop_node_work(uv_work_t *req) {
async_node_data* node_data = static_cast<async_node_data*>(req->data);
StartShutdown();
node_data->result = (char *)strdup("stop_node(): bitcoind shutdown.");
}
/**
* async_stop_node_after()
* Execute our callback.
*/
static void
async_stop_node_after(uv_work_t *req) {
NanScope();
async_node_data* node_data = static_cast<async_node_data*>(req->data);
if (node_data->err_msg != NULL) {
Local<Value> err = Exception::Error(String::New(node_data->err_msg));
free(node_data->err_msg);
const unsigned argc = 1;
Local<Value> argv[argc] = { err };
TryCatch try_catch;
node_data->callback->Call(Context::GetCurrent()->Global(), argc, argv);
if (try_catch.HasCaught()) {
node::FatalException(try_catch);
}
} else {
const unsigned argc = 2;
Local<Value> argv[argc] = {
Local<Value>::New(Null()),
Local<Value>::New(String::New(node_data->result))
};
TryCatch try_catch;
node_data->callback->Call(Context::GetCurrent()->Global(), argc, argv);
if (try_catch.HasCaught()) {
node::FatalException(try_catch);
}
}
node_data->callback.Dispose();
if (node_data->result != NULL) {
free(node_data->result);
}
delete node_data;
delete req;
}
/**
* Init
*/
@ -459,6 +558,7 @@ extern "C" void
init(Handle<Object> target) {
NanScope();
NODE_SET_METHOD(target, "start", StartBitcoind);
NODE_SET_METHOD(target, "stop", StopBitcoind);
}
NODE_MODULE(bitcoindjs, init)