From e1a0e89a6bc26fbe0f70c2feccb16e9fb0e967d0 Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Sat, 3 Aug 2024 02:26:04 +0300 Subject: [PATCH] node.js binding fixes --- node-binding/addon.cc | 4 +- node-binding/binding.gyp | 5 +- node-binding/client.cc | 259 ++++++++++++++++++++++++++------------- node-binding/client.h | 18 +-- node-binding/index.js | 1 + 5 files changed, 192 insertions(+), 95 deletions(-) create mode 100644 node-binding/index.js diff --git a/node-binding/addon.cc b/node-binding/addon.cc index e5a30c0d..3cbc32c2 100644 --- a/node-binding/addon.cc +++ b/node-binding/addon.cc @@ -24,7 +24,7 @@ NAN_MODULE_INIT(InitAddon) tpl = Nan::New(NodeVitastorImage::Create); tpl->SetClassName(Nan::New("Image").ToLocalChecked()); - tpl->InstanceTemplate()->SetInternalFieldCount(2); + tpl->InstanceTemplate()->SetInternalFieldCount(1); Nan::SetPrototypeMethod(tpl, "read", NodeVitastorImage::Read); Nan::SetPrototypeMethod(tpl, "write", NodeVitastorImage::Write); @@ -67,7 +67,7 @@ NAN_MODULE_INIT(InitAddon) tpl = Nan::New(NodeVitastorKVListing::Create); tpl->SetClassName(Nan::New("KVListing").ToLocalChecked()); - tpl->InstanceTemplate()->SetInternalFieldCount(2); + tpl->InstanceTemplate()->SetInternalFieldCount(1); Nan::SetPrototypeMethod(tpl, "next", NodeVitastorKVListing::Next); Nan::SetPrototypeMethod(tpl, "close", NodeVitastorKVListing::Close); diff --git a/node-binding/binding.gyp b/node-binding/binding.gyp index 4bbdb7d6..cf3e881a 100644 --- a/node-binding/binding.gyp +++ b/node-binding/binding.gyp @@ -10,10 +10,11 @@ ' cb): Nan::AsyncResource("NodeVitastorRequest") + NodeVitastorRequest(NodeVitastor *cli, v8::Local cb): Nan::AsyncResource("NodeVitastorRequest") { + this->cli = cli; callback.Reset(cb); } iovec iov; std::vector iov_list; + NodeVitastor *cli = NULL; NodeVitastorImage *img = NULL; int op = 0; uint64_t offset = 0, len = 0, version = 0; @@ -44,6 +46,7 @@ NodeVitastor::NodeVitastor(): Nan::ObjectWrap() NodeVitastor::~NodeVitastor() { + TRACE("NodeVitastor: destructor"); uv_poll_stop(&poll_watcher); vitastor_c_destroy(c); c = NULL; @@ -75,9 +78,10 @@ NAN_METHOD(NodeVitastor::Create) if (res >= 0) { cli->eventfd = res; - res = uv_poll_init_socket(uv_default_loop(), &cli->poll_watcher, cli->eventfd); + res = uv_poll_init(uv_default_loop(), &cli->poll_watcher, cli->eventfd); if (res >= 0) res = uv_poll_start(&cli->poll_watcher, UV_READABLE, on_io_readable); + on_io_readable(&cli->poll_watcher, 0, UV_READABLE); } if (res < 0) { @@ -98,12 +102,28 @@ void NodeVitastor::on_io_readable(uv_poll_t* handle, int status, int revents) if (revents & UV_READABLE) { NodeVitastor* self = (NodeVitastor*)handle->data; - std::unique_lock lock(self->mu); - vitastor_c_uring_handle_events(self->c); + { + std::unique_lock lock(self->mu); + vitastor_c_uring_handle_events(self->c); + } + self->run_postponed(); } } -static NodeVitastorRequest* getReadRequest(const Nan::FunctionCallbackInfo & info, int argpos) +void NodeVitastor::run_postponed() +{ + std::vector> callbacks; + { + std::unique_lock lock(mu); + callbacks.swap(postponed); + } + for (auto & cb: callbacks) + { + cb(); + } +} + +NodeVitastorRequest* NodeVitastor::get_read_request(const Nan::FunctionCallbackInfo & info, int argpos) { uint64_t offset = Nan::To(info[argpos+0]).FromJust(); uint64_t len = Nan::To(info[argpos+1]).FromJust(); @@ -114,7 +134,7 @@ static NodeVitastorRequest* getReadRequest(const Nan::FunctionCallbackInfo callback = info[argpos+2].As(); - auto req = new NodeVitastorRequest(callback); + auto req = new NodeVitastorRequest(this, callback); req->offset = offset; req->len = len; @@ -133,13 +153,17 @@ NAN_METHOD(NodeVitastor::Read) uint64_t pool = Nan::To(info[0]).FromJust(); uint64_t inode = Nan::To(info[1]).FromJust(); - auto req = getReadRequest(info, 2); + auto req = self->get_read_request(info, 2); - std::unique_lock lock(self->mu); - vitastor_c_read(self->c, ((pool << (64-POOL_ID_BITS)) | inode), req->offset, req->len, &req->iov, 1, on_read_finish, req); + self->Ref(); + { + std::unique_lock lock(self->mu); + vitastor_c_read(self->c, ((pool << (64-POOL_ID_BITS)) | inode), req->offset, req->len, &req->iov, 1, postpone_read_finish, req); + } + self->run_postponed(); } -static NodeVitastorRequest* getWriteRequest(const Nan::FunctionCallbackInfo & info, int argpos) +NodeVitastorRequest* NodeVitastor::get_write_request(const Nan::FunctionCallbackInfo & info, int argpos) { uint64_t offset = Nan::To(info[argpos+0]).FromJust(); const auto & bufarg = info[argpos+1]; @@ -155,7 +179,7 @@ static NodeVitastorRequest* getWriteRequest(const Nan::FunctionCallbackInfo callback = info[argpos+2].As(); - auto req = new NodeVitastorRequest(callback); + auto req = new NodeVitastorRequest(this, callback); req->offset = offset; req->version = version; @@ -177,7 +201,7 @@ static NodeVitastorRequest* getWriteRequest(const Nan::FunctionCallbackInfoiov = { .iov_base = buf, .iov_len = req->len }; + req->iov = { .iov_base = buf, .iov_len = len }; req->len = len; } @@ -194,13 +218,17 @@ NAN_METHOD(NodeVitastor::Write) uint64_t pool = Nan::To(info[0]).FromJust(); uint64_t inode = Nan::To(info[1]).FromJust(); - auto req = getWriteRequest(info, 2); + auto req = self->get_write_request(info, 2); - std::unique_lock lock(self->mu); - vitastor_c_write(self->c, ((pool << (64-POOL_ID_BITS)) | inode), req->offset, req->len, req->version, - req->iov_list.size() ? req->iov_list.data() : &req->iov, - req->iov_list.size() ? req->iov_list.size() : 1, - on_write_finish, req); + self->Ref(); + { + std::unique_lock lock(self->mu); + vitastor_c_write(self->c, ((pool << (64-POOL_ID_BITS)) | inode), req->offset, req->len, req->version, + req->iov_list.size() ? req->iov_list.data() : &req->iov, + req->iov_list.size() ? req->iov_list.size() : 1, + postpone_write_finish, req); + } + self->run_postponed(); } // sync(callback(err)) @@ -211,10 +239,14 @@ NAN_METHOD(NodeVitastor::Sync) NodeVitastor* self = Nan::ObjectWrap::Unwrap(info.This()); v8::Local callback = info[0].As(); - auto req = new NodeVitastorRequest(callback); + auto req = new NodeVitastorRequest(self, callback); - std::unique_lock lock(self->mu); - vitastor_c_sync(self->c, on_write_finish, req); + self->Ref(); + { + std::unique_lock lock(self->mu); + vitastor_c_sync(self->c, postpone_write_finish, req); + } + self->run_postponed(); } // read_bitmap(pool, inode, offset, len, with_parents, callback(err, bitmap_buffer)) @@ -230,9 +262,14 @@ NAN_METHOD(NodeVitastor::ReadBitmap) uint64_t len = Nan::To(info[3]).FromJust(); bool with_parents = Nan::To(info[4]).FromJust(); v8::Local callback = info[5].As(); + auto req = new NodeVitastorRequest(self, callback); - auto req = new NodeVitastorRequest(callback); - vitastor_c_read_bitmap(self->c, ((pool << (64-POOL_ID_BITS)) | inode), offset, len, with_parents, on_read_bitmap_finish, req); + self->Ref(); + { + std::unique_lock lock(self->mu); + vitastor_c_read_bitmap(self->c, ((pool << (64-POOL_ID_BITS)) | inode), offset, len, with_parents, postpone_read_bitmap_finish, req); + } + self->run_postponed(); } static void on_error(NodeVitastorRequest *req, Nan::Callback & nanCallback, long retval) @@ -248,6 +285,7 @@ static void on_error(NodeVitastorRequest *req, Nan::Callback & nanCallback, long void NodeVitastor::on_read_finish(void *opaque, long retval, uint64_t version) { + TRACE("NodeVitastor::on_read_finish"); Nan::HandleScope scope; NodeVitastorRequest *req = (NodeVitastorRequest *)opaque; Nan::Callback nanCallback(Nan::New(req->callback)); @@ -269,20 +307,24 @@ void NodeVitastor::on_read_finish(void *opaque, long retval, uint64_t version) args[2] = v8::BigInt::NewFromUnsigned(v8::Isolate::GetCurrent(), version); nanCallback.Call(3, args, req); } + req->cli->Unref(); delete req; } void NodeVitastor::on_write_finish(void *opaque, long retval) { + TRACE("NodeVitastor::on_write_finish"); Nan::HandleScope scope; NodeVitastorRequest *req = (NodeVitastorRequest *)opaque; Nan::Callback nanCallback(Nan::New(req->callback)); on_error(req, nanCallback, retval); + req->cli->Unref(); delete req; } void NodeVitastor::on_read_bitmap_finish(void *opaque, long retval, uint8_t *bitmap) { + TRACE("NodeVitastor::on_read_bitmap_finish"); Nan::HandleScope scope; NodeVitastorRequest *req = (NodeVitastorRequest *)opaque; Nan::Callback nanCallback(Nan::New(req->callback)); @@ -297,9 +339,28 @@ void NodeVitastor::on_read_bitmap_finish(void *opaque, long retval, uint8_t *bit args[1] = Nan::NewBuffer((char*)bitmap, (retval+7)/8).ToLocalChecked(); nanCallback.Call(2, args, req); } + req->cli->Unref(); delete req; } +void NodeVitastor::postpone_read_finish(void *opaque, long retval, uint64_t version) +{ + NodeVitastorRequest *req = (NodeVitastorRequest *)opaque; + req->cli->postponed.push_back([=]() { on_read_finish(opaque, retval, version); }); +} + +void NodeVitastor::postpone_write_finish(void *opaque, long retval) +{ + NodeVitastorRequest *req = (NodeVitastorRequest *)opaque; + req->cli->postponed.push_back([=]() { on_write_finish(opaque, retval); }); +} + +void NodeVitastor::postpone_read_bitmap_finish(void *opaque, long retval, uint8_t *bitmap) +{ + NodeVitastorRequest *req = (NodeVitastorRequest *)opaque; + req->cli->postponed.push_back([=]() { on_read_bitmap_finish(opaque, retval, bitmap); }); +} + //NAN_METHOD(NodeVitastor::Destroy) //{ // TRACE("NodeVitastor::Destroy"); @@ -318,6 +379,8 @@ NAN_METHOD(NodeVitastorImage::Create) NodeVitastor *cli = Nan::ObjectWrap::Unwrap(parent); NodeVitastorImage *img = new NodeVitastorImage(); + img->Wrap(info.This()); + img->cli = cli; img->name = name; @@ -326,7 +389,6 @@ NAN_METHOD(NodeVitastorImage::Create) std::unique_lock lock(cli->mu); vitastor_c_watch_inode(cli->c, (char*)img->name.c_str(), on_watch_start, img); - img->Wrap(info.This()); info.GetReturnValue().Set(info.This()); } @@ -347,7 +409,7 @@ NAN_METHOD(NodeVitastorImage::Read) NodeVitastorImage* img = Nan::ObjectWrap::Unwrap(info.This()); - auto req = getReadRequest(info, 0); + auto req = img->cli->get_read_request(info, 0); req->img = img; req->op = NODE_VITASTOR_READ; @@ -361,7 +423,7 @@ NAN_METHOD(NodeVitastorImage::Write) NodeVitastorImage* img = Nan::ObjectWrap::Unwrap(info.This()); - auto req = getWriteRequest(info, 0); + auto req = img->cli->get_write_request(info, 0); req->img = img; req->op = NODE_VITASTOR_WRITE; @@ -375,7 +437,7 @@ NAN_METHOD(NodeVitastorImage::Sync) NodeVitastorImage* img = Nan::ObjectWrap::Unwrap(info.This()); v8::Local callback = info[0].As(); - auto req = new NodeVitastorRequest(callback); + auto req = new NodeVitastorRequest(img->cli, callback); req->img = img; req->op = NODE_VITASTOR_SYNC; @@ -394,7 +456,7 @@ NAN_METHOD(NodeVitastorImage::ReadBitmap) bool with_parents = Nan::To(info[2]).FromJust(); v8::Local callback = info[3].As(); - auto req = new NodeVitastorRequest(callback); + auto req = new NodeVitastorRequest(img->cli, callback); req->img = img; req->op = NODE_VITASTOR_READ_BITMAP; req->offset = offset; @@ -406,12 +468,12 @@ NAN_METHOD(NodeVitastorImage::ReadBitmap) NAN_METHOD(NodeVitastorImage::GetInfo) { - TRACE("NodeVitastorImage::Sync"); + TRACE("NodeVitastorImage::GetInfo"); NodeVitastorImage* img = Nan::ObjectWrap::Unwrap(info.This()); v8::Local callback = info[0].As(); - auto req = new NodeVitastorRequest(callback); + auto req = new NodeVitastorRequest(img->cli, callback); req->img = img; req->op = NODE_VITASTOR_GET_INFO; @@ -433,78 +495,52 @@ void NodeVitastorImage::exec_or_wait(NodeVitastorRequest *req) void NodeVitastorImage::exec_request(NodeVitastorRequest *req) { - std::unique_lock lock(cli->mu); if (req->op == NODE_VITASTOR_READ) { + cli->Ref(); + std::unique_lock lock(cli->mu); uint64_t ino = vitastor_c_inode_get_num(watch); - vitastor_c_read(cli->c, ino, req->offset, req->len, &req->iov, 1, NodeVitastor::on_read_finish, req); + vitastor_c_read(cli->c, ino, req->offset, req->len, &req->iov, 1, NodeVitastor::postpone_read_finish, req); } else if (req->op == NODE_VITASTOR_WRITE) { + cli->Ref(); + std::unique_lock lock(cli->mu); uint64_t ino = vitastor_c_inode_get_num(watch); vitastor_c_write(cli->c, ino, req->offset, req->len, req->version, req->iov_list.size() ? req->iov_list.data() : &req->iov, req->iov_list.size() ? req->iov_list.size() : 1, - NodeVitastor::on_write_finish, req); + NodeVitastor::postpone_write_finish, req); } else if (req->op == NODE_VITASTOR_SYNC) { + cli->Ref(); + std::unique_lock lock(cli->mu); uint64_t ino = vitastor_c_inode_get_num(watch); uint32_t imm = vitastor_c_inode_get_immediate_commit(cli->c, ino); if (imm != IMMEDIATE_ALL) { - vitastor_c_sync(cli->c, NodeVitastor::on_write_finish, req); + vitastor_c_sync(cli->c, NodeVitastor::postpone_write_finish, req); } else { - NodeVitastor::on_write_finish(req, 0); + NodeVitastor::postpone_write_finish(req, 0); } } else if (req->op == NODE_VITASTOR_READ_BITMAP) { + cli->Ref(); + std::unique_lock lock(cli->mu); uint64_t ino = vitastor_c_inode_get_num(watch); - vitastor_c_read_bitmap(cli->c, ino, req->offset, req->len, req->with_parents, NodeVitastor::on_read_bitmap_finish, req); + vitastor_c_read_bitmap(cli->c, ino, req->offset, req->len, req->with_parents, NodeVitastor::postpone_read_bitmap_finish, req); } else if (req->op == NODE_VITASTOR_GET_INFO) { - uint64_t size = vitastor_c_inode_get_size(watch); - uint64_t num = vitastor_c_inode_get_num(watch); - uint32_t block_size = vitastor_c_inode_get_block_size(cli->c, num); - uint32_t bitmap_granularity = vitastor_c_inode_get_bitmap_granularity(cli->c, num); - int readonly = vitastor_c_inode_get_readonly(watch); - uint32_t immediate_commit = vitastor_c_inode_get_immediate_commit(cli->c, num); - uint64_t parent_id = vitastor_c_inode_get_parent_id(watch); - char *meta = vitastor_c_inode_get_meta(watch); - uint64_t mod_revision = vitastor_c_inode_get_mod_revision(watch); + v8::Local res = Nan::New(); + + fill_info(res); Nan::HandleScope scope; - - v8::Local res = Nan::New(); - Nan::Set(res, Nan::New("pool_id").ToLocalChecked(), Nan::New(INODE_POOL(num))); - Nan::Set(res, Nan::New("inode_num").ToLocalChecked(), Nan::New(INODE_NO_POOL(num))); - if (size < ((uint64_t)1<<53)) - Nan::Set(res, Nan::New("size").ToLocalChecked(), Nan::New(size)); - else - Nan::Set(res, Nan::New("size").ToLocalChecked(), v8::BigInt::NewFromUnsigned(v8::Isolate::GetCurrent(), size)); - if (parent_id) - { - Nan::Set(res, Nan::New("parent_pool_id").ToLocalChecked(), Nan::New(INODE_POOL(parent_id))); - Nan::Set(res, Nan::New("parent_inode_num").ToLocalChecked(), Nan::New(INODE_NO_POOL(parent_id))); - } - Nan::Set(res, Nan::New("readonly").ToLocalChecked(), Nan::New((bool)readonly)); - if (meta) - { - Nan::JSON nanJSON; - Nan::Set(res, Nan::New("meta").ToLocalChecked(), nanJSON.Parse(Nan::New(meta).ToLocalChecked()).ToLocalChecked()); - } - if (mod_revision < ((uint64_t)1<<53)) - Nan::Set(res, Nan::New("mod_revision").ToLocalChecked(), Nan::New(mod_revision)); - else - Nan::Set(res, Nan::New("mod_revision").ToLocalChecked(), v8::BigInt::NewFromUnsigned(v8::Isolate::GetCurrent(), mod_revision)); - Nan::Set(res, Nan::New("block_size").ToLocalChecked(), Nan::New(block_size)); - Nan::Set(res, Nan::New("bitmap_granularity").ToLocalChecked(), Nan::New(bitmap_granularity)); - Nan::Set(res, Nan::New("immediate_commit").ToLocalChecked(), Nan::New(immediate_commit)); - Nan::Callback nanCallback(Nan::New(req->callback)); v8::Local args[1]; args[0] = res; @@ -512,6 +548,46 @@ void NodeVitastorImage::exec_request(NodeVitastorRequest *req) delete req; } + cli->run_postponed(); +} + +void NodeVitastorImage::fill_info(v8::Local & res) +{ + std::unique_lock lock(cli->mu); + uint64_t size = vitastor_c_inode_get_size(watch); + uint64_t num = vitastor_c_inode_get_num(watch); + uint32_t block_size = vitastor_c_inode_get_block_size(cli->c, num); + uint32_t bitmap_granularity = vitastor_c_inode_get_bitmap_granularity(cli->c, num); + int readonly = vitastor_c_inode_get_readonly(watch); + uint32_t immediate_commit = vitastor_c_inode_get_immediate_commit(cli->c, num); + uint64_t parent_id = vitastor_c_inode_get_parent_id(watch); + char *meta = vitastor_c_inode_get_meta(watch); + uint64_t mod_revision = vitastor_c_inode_get_mod_revision(watch); + + Nan::Set(res, Nan::New("pool_id").ToLocalChecked(), Nan::New(INODE_POOL(num))); + Nan::Set(res, Nan::New("inode_num").ToLocalChecked(), Nan::New(INODE_NO_POOL(num))); + if (size < ((uint64_t)1<<53)) + Nan::Set(res, Nan::New("size").ToLocalChecked(), Nan::New(size)); + else + Nan::Set(res, Nan::New("size").ToLocalChecked(), v8::BigInt::NewFromUnsigned(v8::Isolate::GetCurrent(), size)); + if (parent_id) + { + Nan::Set(res, Nan::New("parent_pool_id").ToLocalChecked(), Nan::New(INODE_POOL(parent_id))); + Nan::Set(res, Nan::New("parent_inode_num").ToLocalChecked(), Nan::New(INODE_NO_POOL(parent_id))); + } + Nan::Set(res, Nan::New("readonly").ToLocalChecked(), Nan::New((bool)readonly)); + if (meta) + { + Nan::JSON nanJSON; + Nan::Set(res, Nan::New("meta").ToLocalChecked(), nanJSON.Parse(Nan::New(meta).ToLocalChecked()).ToLocalChecked()); + } + if (mod_revision < ((uint64_t)1<<53)) + Nan::Set(res, Nan::New("mod_revision").ToLocalChecked(), Nan::New(mod_revision)); + else + Nan::Set(res, Nan::New("mod_revision").ToLocalChecked(), v8::BigInt::NewFromUnsigned(v8::Isolate::GetCurrent(), mod_revision)); + Nan::Set(res, Nan::New("block_size").ToLocalChecked(), Nan::New(block_size)); + Nan::Set(res, Nan::New("bitmap_granularity").ToLocalChecked(), Nan::New(bitmap_granularity)); + Nan::Set(res, Nan::New("immediate_commit").ToLocalChecked(), Nan::New(immediate_commit)); } void NodeVitastorImage::on_watch_start(void *opaque, long retval) @@ -532,6 +608,8 @@ void NodeVitastorImage::on_watch_start(void *opaque, long retval) // NodeVitastorKV ////////////////////////////////////////////////// +Nan::Persistent NodeVitastorKV::listing_class; + // constructor(node_vitastor) NAN_METHOD(NodeVitastorKV::Create) { @@ -548,24 +626,26 @@ NAN_METHOD(NodeVitastorKV::Create) } kv->Wrap(info.This()); + cli->Ref(); info.GetReturnValue().Set(info.This()); } NodeVitastorKV::~NodeVitastorKV() { delete dbw; + cli->Unref(); } -// open(inode_id, { ...config }, callback(err)) +// open(pool_id, inode_num, { ...config }, callback(err)) NAN_METHOD(NodeVitastorKV::Open) { TRACE("NodeVitastorKV::Open"); NodeVitastorKV* kv = Nan::ObjectWrap::Unwrap(info.This()); - uint64_t inode_id = Nan::To(info[0]).FromJust(); + uint64_t inode_id = INODE_WITH_POOL(Nan::To(info[0]).FromJust(), Nan::To(info[1]).FromJust()); - v8::Local jsParams = info[1].As(); + v8::Local jsParams = info[2].As(); v8::Local keys = Nan::GetOwnPropertyNames(jsParams).ToLocalChecked(); std::map cfg; for (uint32_t i = 0; i < keys->Length(); i++) @@ -574,8 +654,8 @@ NAN_METHOD(NodeVitastorKV::Open) cfg[std::string(*Nan::Utf8String(key))] = std::string(*Nan::Utf8String(Nan::Get(jsParams, key).ToLocalChecked())); } - v8::Local callback = info[2].As(); - auto req = new NodeVitastorRequest(callback); + v8::Local callback = info[3].As(); + auto req = new NodeVitastorRequest(kv->cli, callback); kv->Ref(); kv->dbw->open(inode_id, cfg, [kv, req](int res) @@ -598,7 +678,7 @@ NAN_METHOD(NodeVitastorKV::Close) NodeVitastorKV* kv = Nan::ObjectWrap::Unwrap(info.This()); v8::Local callback = info[0].As(); - auto req = new NodeVitastorRequest(callback); + auto req = new NodeVitastorRequest(kv->cli, callback); kv->Ref(); kv->dbw->close([kv, req]() @@ -651,7 +731,7 @@ void NodeVitastorKV::get_impl(const Nan::FunctionCallbackInfo & info, std::string key(*Nan::Utf8String(info[0].As())); v8::Local callback = info[1].As(); - auto req = new NodeVitastorRequest(callback); + auto req = new NodeVitastorRequest(kv->cli, callback); kv->Ref(); kv->dbw->get(key, [kv, req](int res, const std::string & value) @@ -708,13 +788,13 @@ NAN_METHOD(NodeVitastorKV::Set) std::string value(*Nan::Utf8String(info[1].As())); v8::Local callback = info[2].As(); - NodeVitastorRequest *req = new NodeVitastorRequest(callback), *cas_req = NULL; + NodeVitastorRequest *req = new NodeVitastorRequest(kv->cli, callback), *cas_req = NULL; std::function cas_cb; if (info.Length() > 3 && info[3]->IsObject()) { v8::Local cas_callback = info[3].As(); - cas_req = new NodeVitastorRequest(cas_callback); + cas_req = new NodeVitastorRequest(kv->cli, cas_callback); cas_cb = make_cas_callback(cas_req); } @@ -744,13 +824,13 @@ NAN_METHOD(NodeVitastorKV::Del) std::string key(*Nan::Utf8String(info[0].As())); v8::Local callback = info[1].As(); - NodeVitastorRequest *req = new NodeVitastorRequest(callback), *cas_req = NULL; + NodeVitastorRequest *req = new NodeVitastorRequest(kv->cli, callback), *cas_req = NULL; std::function cas_cb; if (info.Length() > 2 && info[2]->IsObject()) { v8::Local cas_callback = info[2].As(); - cas_req = new NodeVitastorRequest(cas_callback); + cas_req = new NodeVitastorRequest(kv->cli, cas_callback); cas_cb = make_cas_callback(cas_req); } @@ -786,6 +866,15 @@ NAN_METHOD(NodeVitastorKV::List) info.GetReturnValue().Set(Nan::NewInstance(cons, narg, args).ToLocalChecked()); } +/*NAN_METHOD(NodeVitastorKV::Destroy) +{ + TRACE("NodeVitastorKV::Destroy"); + NodeVitastorKV* kv = Nan::ObjectWrap::Unwrap(info.This()); + std::unique_lock lock(self->mu); + if (!kv->dead) + kv->Unref(); +}*/ + ////////////////////////////////////////////////// // NodeVitastorKVListing ////////////////////////////////////////////////// @@ -813,6 +902,7 @@ NAN_METHOD(NodeVitastorKVListing::Create) } list->Wrap(info.This()); + kv->Ref(); info.GetReturnValue().Set(info.This()); } @@ -824,6 +914,7 @@ NodeVitastorKVListing::~NodeVitastorKVListing() kv->dbw->list_close(handle); handle = NULL; } + kv->Unref(); } // next(callback(err, value)) @@ -834,7 +925,7 @@ NAN_METHOD(NodeVitastorKVListing::Next) NodeVitastorKVListing* list = Nan::ObjectWrap::Unwrap(info.This()); v8::Local callback = info[0].As(); - auto req = new NodeVitastorRequest(callback); + auto req = new NodeVitastorRequest(list->kv->cli, callback); if (!list->handle) { // Already closed diff --git a/node-binding/client.h b/node-binding/client.h index a8f547b7..f14f9d51 100644 --- a/node-binding/client.h +++ b/node-binding/client.h @@ -36,6 +36,7 @@ private: uv_poll_t poll_watcher; // FIXME: Is it really needed? std::mutex mu; + std::vector> postponed; NodeVitastor(); @@ -44,6 +45,14 @@ private: static void on_write_finish(void *opaque, long retval); static void on_read_bitmap_finish(void *opaque, long retval, uint8_t *bitmap); + void run_postponed(); + static void postpone_read_finish(void *opaque, long retval, uint64_t version); + static void postpone_write_finish(void *opaque, long retval); + static void postpone_read_bitmap_finish(void *opaque, long retval, uint8_t *bitmap); + + NodeVitastorRequest* get_read_request(const Nan::FunctionCallbackInfo & info, int argpos); + NodeVitastorRequest* get_write_request(const Nan::FunctionCallbackInfo & info, int argpos); + friend class NodeVitastorImage; friend class NodeVitastorKV; friend class NodeVitastorKVListing; @@ -74,11 +83,10 @@ private: std::vector on_init; Nan::Persistent cliObj; - NodeVitastorImage(); - static void on_watch_start(void *opaque, long retval); void exec_request(NodeVitastorRequest *req); void exec_or_wait(NodeVitastorRequest *req); + void fill_info(v8::Local & res); }; class NodeVitastorKV: public Nan::ObjectWrap @@ -86,7 +94,7 @@ class NodeVitastorKV: public Nan::ObjectWrap public: // constructor(node_vitastor) static NAN_METHOD(Create); - // open(inode_id, { ...config }, callback(err)) + // open(pool_id, inode_num, { ...config }, callback(err)) static NAN_METHOD(Open); // set_config({ ...config }) static NAN_METHOD(SetConfig); @@ -113,8 +121,6 @@ private: NodeVitastor *cli = NULL; vitastorkv_dbw_t *dbw = NULL; - NodeVitastorKV(); - static void get_impl(const Nan::FunctionCallbackInfo & info, bool allow_cache); friend class NodeVitastorKVListing; @@ -135,8 +141,6 @@ public: private: NodeVitastorKV *kv = NULL; void *handle = NULL; - - NodeVitastorKVListing(); }; #endif diff --git a/node-binding/index.js b/node-binding/index.js new file mode 100644 index 00000000..ff9a0457 --- /dev/null +++ b/node-binding/index.js @@ -0,0 +1 @@ +module.exports = require('bindings')('addon.node');