|
|
|
@@ -34,6 +34,13 @@ public:
|
|
|
|
|
Nan::Persistent<v8::Function> callback;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static uint64_t get_ui64(const v8::Local<v8::Value> & val)
|
|
|
|
|
{
|
|
|
|
|
if (val->IsBigInt())
|
|
|
|
|
return val->ToBigInt(Nan::GetCurrentContext()).ToLocalChecked()->Uint64Value();
|
|
|
|
|
return Nan::To<int64_t>(val).FromJust();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////
|
|
|
|
|
// NodeVitastor
|
|
|
|
|
//////////////////////////////////////////////////
|
|
|
|
@@ -102,31 +109,14 @@ 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<std::mutex> lock(self->mu);
|
|
|
|
|
vitastor_c_uring_handle_events(self->c);
|
|
|
|
|
}
|
|
|
|
|
self->run_postponed();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NodeVitastor::run_postponed()
|
|
|
|
|
{
|
|
|
|
|
std::vector<std::function<void()>> callbacks;
|
|
|
|
|
{
|
|
|
|
|
std::unique_lock<std::mutex> lock(mu);
|
|
|
|
|
callbacks.swap(postponed);
|
|
|
|
|
}
|
|
|
|
|
for (auto & cb: callbacks)
|
|
|
|
|
{
|
|
|
|
|
cb();
|
|
|
|
|
vitastor_c_uring_handle_events(self->c);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NodeVitastorRequest* NodeVitastor::get_read_request(const Nan::FunctionCallbackInfo<v8::Value> & info, int argpos)
|
|
|
|
|
{
|
|
|
|
|
uint64_t offset = Nan::To<int64_t>(info[argpos+0]).FromJust();
|
|
|
|
|
uint64_t len = Nan::To<int64_t>(info[argpos+1]).FromJust();
|
|
|
|
|
uint64_t offset = get_ui64(info[argpos+0]);
|
|
|
|
|
uint64_t len = get_ui64(info[argpos+1]);
|
|
|
|
|
uint8_t *buf = (uint8_t*)malloc(len);
|
|
|
|
|
if (!buf)
|
|
|
|
|
{
|
|
|
|
@@ -147,34 +137,34 @@ NodeVitastorRequest* NodeVitastor::get_read_request(const Nan::FunctionCallbackI
|
|
|
|
|
NAN_METHOD(NodeVitastor::Read)
|
|
|
|
|
{
|
|
|
|
|
TRACE("NodeVitastor::Read");
|
|
|
|
|
if (info.Length() < 5)
|
|
|
|
|
Nan::ThrowError("Not enough arguments to read(pool, inode, offset, len, callback(err, buffer, version))");
|
|
|
|
|
|
|
|
|
|
NodeVitastor* self = Nan::ObjectWrap::Unwrap<NodeVitastor>(info.This());
|
|
|
|
|
|
|
|
|
|
uint64_t pool = Nan::To<int64_t>(info[0]).FromJust();
|
|
|
|
|
uint64_t inode = Nan::To<int64_t>(info[1]).FromJust();
|
|
|
|
|
uint64_t pool = get_ui64(info[0]);
|
|
|
|
|
uint64_t inode = get_ui64(info[1]);
|
|
|
|
|
|
|
|
|
|
auto req = self->get_read_request(info, 2);
|
|
|
|
|
|
|
|
|
|
self->Ref();
|
|
|
|
|
{
|
|
|
|
|
std::unique_lock<std::mutex> 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();
|
|
|
|
|
vitastor_c_read(self->c, ((pool << (64-POOL_ID_BITS)) | inode), req->offset, req->len, &req->iov, 1, on_read_finish, req);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NodeVitastorRequest* NodeVitastor::get_write_request(const Nan::FunctionCallbackInfo<v8::Value> & info, int argpos)
|
|
|
|
|
{
|
|
|
|
|
uint64_t offset = Nan::To<int64_t>(info[argpos+0]).FromJust();
|
|
|
|
|
uint64_t offset = get_ui64(info[argpos+0]);
|
|
|
|
|
const auto & bufarg = info[argpos+1];
|
|
|
|
|
uint64_t version = 0;
|
|
|
|
|
if (!info[argpos+2].IsEmpty() && info[argpos+2]->IsObject())
|
|
|
|
|
if (!info[argpos+2].IsEmpty() &&
|
|
|
|
|
!info[argpos+2]->IsFunction() &&
|
|
|
|
|
info[argpos+2]->IsObject())
|
|
|
|
|
{
|
|
|
|
|
auto key = Nan::New<v8::String>("version").ToLocalChecked();
|
|
|
|
|
auto params = info[argpos+2].As<v8::Object>();
|
|
|
|
|
auto versionObj = Nan::Get(params, key).ToLocalChecked();
|
|
|
|
|
if (!versionObj.IsEmpty())
|
|
|
|
|
version = Nan::To<int64_t>(versionObj).FromJust();
|
|
|
|
|
version = get_ui64(versionObj);
|
|
|
|
|
argpos++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -212,29 +202,29 @@ NodeVitastorRequest* NodeVitastor::get_write_request(const Nan::FunctionCallback
|
|
|
|
|
NAN_METHOD(NodeVitastor::Write)
|
|
|
|
|
{
|
|
|
|
|
TRACE("NodeVitastor::Write");
|
|
|
|
|
if (info.Length() < 5)
|
|
|
|
|
Nan::ThrowError("Not enough arguments to write(pool, inode, offset, buf: Buffer | Buffer[], { version }?, callback(err))");
|
|
|
|
|
|
|
|
|
|
NodeVitastor* self = Nan::ObjectWrap::Unwrap<NodeVitastor>(info.This());
|
|
|
|
|
|
|
|
|
|
uint64_t pool = Nan::To<int64_t>(info[0]).FromJust();
|
|
|
|
|
uint64_t inode = Nan::To<int64_t>(info[1]).FromJust();
|
|
|
|
|
uint64_t pool = get_ui64(info[0]);
|
|
|
|
|
uint64_t inode = get_ui64(info[1]);
|
|
|
|
|
|
|
|
|
|
auto req = self->get_write_request(info, 2);
|
|
|
|
|
|
|
|
|
|
self->Ref();
|
|
|
|
|
{
|
|
|
|
|
std::unique_lock<std::mutex> 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();
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// sync(callback(err))
|
|
|
|
|
NAN_METHOD(NodeVitastor::Sync)
|
|
|
|
|
{
|
|
|
|
|
TRACE("NodeVitastor::Sync");
|
|
|
|
|
if (info.Length() < 1)
|
|
|
|
|
Nan::ThrowError("Not enough arguments to sync(callback(err))");
|
|
|
|
|
|
|
|
|
|
NodeVitastor* self = Nan::ObjectWrap::Unwrap<NodeVitastor>(info.This());
|
|
|
|
|
|
|
|
|
@@ -242,34 +232,28 @@ NAN_METHOD(NodeVitastor::Sync)
|
|
|
|
|
auto req = new NodeVitastorRequest(self, callback);
|
|
|
|
|
|
|
|
|
|
self->Ref();
|
|
|
|
|
{
|
|
|
|
|
std::unique_lock<std::mutex> lock(self->mu);
|
|
|
|
|
vitastor_c_sync(self->c, postpone_write_finish, req);
|
|
|
|
|
}
|
|
|
|
|
self->run_postponed();
|
|
|
|
|
vitastor_c_sync(self->c, on_write_finish, req);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// read_bitmap(pool, inode, offset, len, with_parents, callback(err, bitmap_buffer))
|
|
|
|
|
NAN_METHOD(NodeVitastor::ReadBitmap)
|
|
|
|
|
{
|
|
|
|
|
TRACE("NodeVitastor::ReadBitmap");
|
|
|
|
|
if (info.Length() < 6)
|
|
|
|
|
Nan::ThrowError("Not enough arguments to read_bitmap(pool, inode, offset, len, with_parents, callback(err, bitmap_buffer))");
|
|
|
|
|
|
|
|
|
|
NodeVitastor* self = Nan::ObjectWrap::Unwrap<NodeVitastor>(info.This());
|
|
|
|
|
|
|
|
|
|
uint64_t pool = Nan::To<int64_t>(info[0]).FromJust();
|
|
|
|
|
uint64_t inode = Nan::To<int64_t>(info[1]).FromJust();
|
|
|
|
|
uint64_t offset = Nan::To<int64_t>(info[2]).FromJust();
|
|
|
|
|
uint64_t len = Nan::To<int64_t>(info[3]).FromJust();
|
|
|
|
|
uint64_t pool = get_ui64(info[0]);
|
|
|
|
|
uint64_t inode = get_ui64(info[1]);
|
|
|
|
|
uint64_t offset = get_ui64(info[2]);
|
|
|
|
|
uint64_t len = get_ui64(info[3]);
|
|
|
|
|
bool with_parents = Nan::To<bool>(info[4]).FromJust();
|
|
|
|
|
v8::Local<v8::Function> callback = info[5].As<v8::Function>();
|
|
|
|
|
auto req = new NodeVitastorRequest(self, callback);
|
|
|
|
|
|
|
|
|
|
auto req = new NodeVitastorRequest(self, callback);
|
|
|
|
|
self->Ref();
|
|
|
|
|
{
|
|
|
|
|
std::unique_lock<std::mutex> 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();
|
|
|
|
|
vitastor_c_read_bitmap(self->c, ((pool << (64-POOL_ID_BITS)) | inode), offset, len, with_parents, on_read_bitmap_finish, req);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void on_error(NodeVitastorRequest *req, Nan::Callback & nanCallback, long retval)
|
|
|
|
@@ -294,7 +278,7 @@ void NodeVitastor::on_read_finish(void *opaque, long retval, uint64_t version)
|
|
|
|
|
free(req->iov.iov_base);
|
|
|
|
|
nanCallback.Call(0, NULL, req);
|
|
|
|
|
}
|
|
|
|
|
else if (retval < 0)
|
|
|
|
|
else if (retval < 0 || (uint64_t)retval != req->len)
|
|
|
|
|
{
|
|
|
|
|
free(req->iov.iov_base);
|
|
|
|
|
on_error(req, nanCallback, retval);
|
|
|
|
@@ -317,7 +301,16 @@ void NodeVitastor::on_write_finish(void *opaque, long retval)
|
|
|
|
|
Nan::HandleScope scope;
|
|
|
|
|
NodeVitastorRequest *req = (NodeVitastorRequest *)opaque;
|
|
|
|
|
Nan::Callback nanCallback(Nan::New(req->callback));
|
|
|
|
|
on_error(req, nanCallback, retval);
|
|
|
|
|
if (retval < 0 || (uint64_t)retval != req->len)
|
|
|
|
|
{
|
|
|
|
|
on_error(req, nanCallback, retval);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
v8::Local<v8::Value> args[1];
|
|
|
|
|
args[0] = Nan::Null();
|
|
|
|
|
nanCallback.Call(1, args, req);
|
|
|
|
|
}
|
|
|
|
|
req->cli->Unref();
|
|
|
|
|
delete req;
|
|
|
|
|
}
|
|
|
|
@@ -343,24 +336,6 @@ void NodeVitastor::on_read_bitmap_finish(void *opaque, long retval, uint8_t *bit
|
|
|
|
|
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");
|
|
|
|
@@ -373,6 +348,8 @@ void NodeVitastor::postpone_read_bitmap_finish(void *opaque, long retval, uint8_
|
|
|
|
|
NAN_METHOD(NodeVitastorImage::Create)
|
|
|
|
|
{
|
|
|
|
|
TRACE("NodeVitastorImage::Create");
|
|
|
|
|
if (info.Length() < 2)
|
|
|
|
|
Nan::ThrowError("Not enough arguments to Image(client, name)");
|
|
|
|
|
|
|
|
|
|
v8::Local<v8::Object> parent = info[0].As<v8::Object>();
|
|
|
|
|
std::string name = std::string(*Nan::Utf8String(info[1].As<v8::String>()));
|
|
|
|
@@ -386,7 +363,6 @@ NAN_METHOD(NodeVitastorImage::Create)
|
|
|
|
|
|
|
|
|
|
img->Ref();
|
|
|
|
|
cli->Ref();
|
|
|
|
|
std::unique_lock<std::mutex> lock(cli->mu);
|
|
|
|
|
vitastor_c_watch_inode(cli->c, (char*)img->name.c_str(), on_watch_start, img);
|
|
|
|
|
|
|
|
|
|
info.GetReturnValue().Set(info.This());
|
|
|
|
@@ -406,6 +382,8 @@ NodeVitastorImage::~NodeVitastorImage()
|
|
|
|
|
NAN_METHOD(NodeVitastorImage::Read)
|
|
|
|
|
{
|
|
|
|
|
TRACE("NodeVitastorImage::Read");
|
|
|
|
|
if (info.Length() < 3)
|
|
|
|
|
Nan::ThrowError("Not enough arguments to read(offset, len, callback(err, buffer, version))");
|
|
|
|
|
|
|
|
|
|
NodeVitastorImage* img = Nan::ObjectWrap::Unwrap<NodeVitastorImage>(info.This());
|
|
|
|
|
|
|
|
|
@@ -420,6 +398,8 @@ NAN_METHOD(NodeVitastorImage::Read)
|
|
|
|
|
NAN_METHOD(NodeVitastorImage::Write)
|
|
|
|
|
{
|
|
|
|
|
TRACE("NodeVitastorImage::Write");
|
|
|
|
|
if (info.Length() < 3)
|
|
|
|
|
Nan::ThrowError("Not enough arguments to write(offset, buffer, { version }?, callback(err))");
|
|
|
|
|
|
|
|
|
|
NodeVitastorImage* img = Nan::ObjectWrap::Unwrap<NodeVitastorImage>(info.This());
|
|
|
|
|
|
|
|
|
@@ -430,9 +410,12 @@ NAN_METHOD(NodeVitastorImage::Write)
|
|
|
|
|
img->exec_or_wait(req);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// sync(callback(err))
|
|
|
|
|
NAN_METHOD(NodeVitastorImage::Sync)
|
|
|
|
|
{
|
|
|
|
|
TRACE("NodeVitastorImage::Sync");
|
|
|
|
|
if (info.Length() < 1)
|
|
|
|
|
Nan::ThrowError("Not enough arguments to sync(callback(err))");
|
|
|
|
|
|
|
|
|
|
NodeVitastorImage* img = Nan::ObjectWrap::Unwrap<NodeVitastorImage>(info.This());
|
|
|
|
|
|
|
|
|
@@ -448,11 +431,13 @@ NAN_METHOD(NodeVitastorImage::Sync)
|
|
|
|
|
NAN_METHOD(NodeVitastorImage::ReadBitmap)
|
|
|
|
|
{
|
|
|
|
|
TRACE("NodeVitastorImage::ReadBitmap");
|
|
|
|
|
if (info.Length() < 4)
|
|
|
|
|
Nan::ThrowError("Not enough arguments to read_bitmap(offset, len, with_parents, callback(err, bitmap_buffer))");
|
|
|
|
|
|
|
|
|
|
NodeVitastorImage* img = Nan::ObjectWrap::Unwrap<NodeVitastorImage>(info.This());
|
|
|
|
|
|
|
|
|
|
uint64_t offset = Nan::To<int64_t>(info[0]).FromJust();
|
|
|
|
|
uint64_t len = Nan::To<int64_t>(info[1]).FromJust();
|
|
|
|
|
uint64_t offset = get_ui64(info[0]);
|
|
|
|
|
uint64_t len = get_ui64(info[1]);
|
|
|
|
|
bool with_parents = Nan::To<bool>(info[2]).FromJust();
|
|
|
|
|
v8::Local<v8::Function> callback = info[3].As<v8::Function>();
|
|
|
|
|
|
|
|
|
@@ -466,9 +451,12 @@ NAN_METHOD(NodeVitastorImage::ReadBitmap)
|
|
|
|
|
img->exec_or_wait(req);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// get_info(callback({ num, name, size, parent_id?, readonly?, meta?, mod_revision, block_size, bitmap_granularity, immediate_commit }))
|
|
|
|
|
NAN_METHOD(NodeVitastorImage::GetInfo)
|
|
|
|
|
{
|
|
|
|
|
TRACE("NodeVitastorImage::GetInfo");
|
|
|
|
|
if (info.Length() < 1)
|
|
|
|
|
Nan::ThrowError("Not enough arguments to get_info(callback({ num, name, size, parent_id?, readonly?, meta?, mod_revision, block_size, bitmap_granularity, immediate_commit }))");
|
|
|
|
|
|
|
|
|
|
NodeVitastorImage* img = Nan::ObjectWrap::Unwrap<NodeVitastorImage>(info.This());
|
|
|
|
|
|
|
|
|
@@ -497,50 +485,79 @@ void NodeVitastorImage::exec_request(NodeVitastorRequest *req)
|
|
|
|
|
{
|
|
|
|
|
if (req->op == NODE_VITASTOR_READ)
|
|
|
|
|
{
|
|
|
|
|
cli->Ref();
|
|
|
|
|
std::unique_lock<std::mutex> 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::postpone_read_finish, req);
|
|
|
|
|
cli->Ref();
|
|
|
|
|
vitastor_c_read(cli->c, ino, req->offset, req->len, &req->iov, 1, NodeVitastor::on_read_finish, req);
|
|
|
|
|
}
|
|
|
|
|
else if (req->op == NODE_VITASTOR_WRITE)
|
|
|
|
|
{
|
|
|
|
|
cli->Ref();
|
|
|
|
|
std::unique_lock<std::mutex> lock(cli->mu);
|
|
|
|
|
uint64_t ino = vitastor_c_inode_get_num(watch);
|
|
|
|
|
cli->Ref();
|
|
|
|
|
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::postpone_write_finish, req);
|
|
|
|
|
NodeVitastor::on_write_finish, req);
|
|
|
|
|
}
|
|
|
|
|
else if (req->op == NODE_VITASTOR_SYNC)
|
|
|
|
|
{
|
|
|
|
|
cli->Ref();
|
|
|
|
|
std::unique_lock<std::mutex> lock(cli->mu);
|
|
|
|
|
uint64_t ino = vitastor_c_inode_get_num(watch);
|
|
|
|
|
uint32_t imm = vitastor_c_inode_get_immediate_commit(cli->c, ino);
|
|
|
|
|
cli->Ref();
|
|
|
|
|
if (imm != IMMEDIATE_ALL)
|
|
|
|
|
{
|
|
|
|
|
vitastor_c_sync(cli->c, NodeVitastor::postpone_write_finish, req);
|
|
|
|
|
vitastor_c_sync(cli->c, NodeVitastor::on_write_finish, req);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
NodeVitastor::postpone_write_finish(req, 0);
|
|
|
|
|
NodeVitastor::on_write_finish(req, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (req->op == NODE_VITASTOR_READ_BITMAP)
|
|
|
|
|
{
|
|
|
|
|
cli->Ref();
|
|
|
|
|
std::unique_lock<std::mutex> 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::postpone_read_bitmap_finish, req);
|
|
|
|
|
cli->Ref();
|
|
|
|
|
vitastor_c_read_bitmap(cli->c, ino, req->offset, req->len, req->with_parents, NodeVitastor::on_read_bitmap_finish, req);
|
|
|
|
|
}
|
|
|
|
|
else if (req->op == NODE_VITASTOR_GET_INFO)
|
|
|
|
|
{
|
|
|
|
|
v8::Local<v8::Object> res = Nan::New<v8::Object>();
|
|
|
|
|
|
|
|
|
|
fill_info(res);
|
|
|
|
|
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::HandleScope scope;
|
|
|
|
|
|
|
|
|
|
v8::Local<v8::Object> res = Nan::New<v8::Object>();
|
|
|
|
|
Nan::Set(res, Nan::New<v8::String>("pool_id").ToLocalChecked(), Nan::New<v8::Number>(INODE_POOL(num)));
|
|
|
|
|
Nan::Set(res, Nan::New<v8::String>("inode_num").ToLocalChecked(), Nan::New<v8::Number>(INODE_NO_POOL(num)));
|
|
|
|
|
if (size < ((uint64_t)1<<53))
|
|
|
|
|
Nan::Set(res, Nan::New<v8::String>("size").ToLocalChecked(), Nan::New<v8::Number>(size));
|
|
|
|
|
else
|
|
|
|
|
Nan::Set(res, Nan::New<v8::String>("size").ToLocalChecked(), v8::BigInt::NewFromUnsigned(v8::Isolate::GetCurrent(), size));
|
|
|
|
|
if (parent_id)
|
|
|
|
|
{
|
|
|
|
|
Nan::Set(res, Nan::New<v8::String>("parent_pool_id").ToLocalChecked(), Nan::New<v8::Number>(INODE_POOL(parent_id)));
|
|
|
|
|
Nan::Set(res, Nan::New<v8::String>("parent_inode_num").ToLocalChecked(), Nan::New<v8::Number>(INODE_NO_POOL(parent_id)));
|
|
|
|
|
}
|
|
|
|
|
Nan::Set(res, Nan::New<v8::String>("readonly").ToLocalChecked(), Nan::New((bool)readonly));
|
|
|
|
|
if (meta)
|
|
|
|
|
{
|
|
|
|
|
Nan::JSON nanJSON;
|
|
|
|
|
Nan::Set(res, Nan::New<v8::String>("meta").ToLocalChecked(), nanJSON.Parse(Nan::New<v8::String>(meta).ToLocalChecked()).ToLocalChecked());
|
|
|
|
|
}
|
|
|
|
|
if (mod_revision < ((uint64_t)1<<53))
|
|
|
|
|
Nan::Set(res, Nan::New<v8::String>("mod_revision").ToLocalChecked(), Nan::New<v8::Number>(mod_revision));
|
|
|
|
|
else
|
|
|
|
|
Nan::Set(res, Nan::New<v8::String>("mod_revision").ToLocalChecked(), v8::BigInt::NewFromUnsigned(v8::Isolate::GetCurrent(), mod_revision));
|
|
|
|
|
Nan::Set(res, Nan::New<v8::String>("block_size").ToLocalChecked(), Nan::New(block_size));
|
|
|
|
|
Nan::Set(res, Nan::New<v8::String>("bitmap_granularity").ToLocalChecked(), Nan::New(bitmap_granularity));
|
|
|
|
|
Nan::Set(res, Nan::New<v8::String>("immediate_commit").ToLocalChecked(), Nan::New(immediate_commit));
|
|
|
|
|
|
|
|
|
|
Nan::Callback nanCallback(Nan::New(req->callback));
|
|
|
|
|
v8::Local<v8::Value> args[1];
|
|
|
|
|
args[0] = res;
|
|
|
|
@@ -548,46 +565,6 @@ void NodeVitastorImage::exec_request(NodeVitastorRequest *req)
|
|
|
|
|
|
|
|
|
|
delete req;
|
|
|
|
|
}
|
|
|
|
|
cli->run_postponed();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NodeVitastorImage::fill_info(v8::Local<v8::Object> & res)
|
|
|
|
|
{
|
|
|
|
|
std::unique_lock<std::mutex> 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<v8::String>("pool_id").ToLocalChecked(), Nan::New<v8::Number>(INODE_POOL(num)));
|
|
|
|
|
Nan::Set(res, Nan::New<v8::String>("inode_num").ToLocalChecked(), Nan::New<v8::Number>(INODE_NO_POOL(num)));
|
|
|
|
|
if (size < ((uint64_t)1<<53))
|
|
|
|
|
Nan::Set(res, Nan::New<v8::String>("size").ToLocalChecked(), Nan::New<v8::Number>(size));
|
|
|
|
|
else
|
|
|
|
|
Nan::Set(res, Nan::New<v8::String>("size").ToLocalChecked(), v8::BigInt::NewFromUnsigned(v8::Isolate::GetCurrent(), size));
|
|
|
|
|
if (parent_id)
|
|
|
|
|
{
|
|
|
|
|
Nan::Set(res, Nan::New<v8::String>("parent_pool_id").ToLocalChecked(), Nan::New<v8::Number>(INODE_POOL(parent_id)));
|
|
|
|
|
Nan::Set(res, Nan::New<v8::String>("parent_inode_num").ToLocalChecked(), Nan::New<v8::Number>(INODE_NO_POOL(parent_id)));
|
|
|
|
|
}
|
|
|
|
|
Nan::Set(res, Nan::New<v8::String>("readonly").ToLocalChecked(), Nan::New((bool)readonly));
|
|
|
|
|
if (meta)
|
|
|
|
|
{
|
|
|
|
|
Nan::JSON nanJSON;
|
|
|
|
|
Nan::Set(res, Nan::New<v8::String>("meta").ToLocalChecked(), nanJSON.Parse(Nan::New<v8::String>(meta).ToLocalChecked()).ToLocalChecked());
|
|
|
|
|
}
|
|
|
|
|
if (mod_revision < ((uint64_t)1<<53))
|
|
|
|
|
Nan::Set(res, Nan::New<v8::String>("mod_revision").ToLocalChecked(), Nan::New<v8::Number>(mod_revision));
|
|
|
|
|
else
|
|
|
|
|
Nan::Set(res, Nan::New<v8::String>("mod_revision").ToLocalChecked(), v8::BigInt::NewFromUnsigned(v8::Isolate::GetCurrent(), mod_revision));
|
|
|
|
|
Nan::Set(res, Nan::New<v8::String>("block_size").ToLocalChecked(), Nan::New(block_size));
|
|
|
|
|
Nan::Set(res, Nan::New<v8::String>("bitmap_granularity").ToLocalChecked(), Nan::New(bitmap_granularity));
|
|
|
|
|
Nan::Set(res, Nan::New<v8::String>("immediate_commit").ToLocalChecked(), Nan::New(immediate_commit));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NodeVitastorImage::on_watch_start(void *opaque, long retval)
|
|
|
|
@@ -614,6 +591,8 @@ Nan::Persistent<v8::Function> NodeVitastorKV::listing_class;
|
|
|
|
|
NAN_METHOD(NodeVitastorKV::Create)
|
|
|
|
|
{
|
|
|
|
|
TRACE("NodeVitastorKV::Create");
|
|
|
|
|
if (info.Length() < 1)
|
|
|
|
|
Nan::ThrowError("Not enough arguments to new KV(client)");
|
|
|
|
|
|
|
|
|
|
v8::Local<v8::Object> parent = info[0].As<v8::Object>();
|
|
|
|
|
NodeVitastor *cli = Nan::ObjectWrap::Unwrap<NodeVitastor>(parent);
|
|
|
|
@@ -621,7 +600,6 @@ NAN_METHOD(NodeVitastorKV::Create)
|
|
|
|
|
NodeVitastorKV *kv = new NodeVitastorKV();
|
|
|
|
|
kv->cli = cli;
|
|
|
|
|
{
|
|
|
|
|
std::unique_lock<std::mutex> lock(cli->mu);
|
|
|
|
|
kv->dbw = new vitastorkv_dbw_t((cluster_client_t*)vitastor_c_get_internal_client(cli->c));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -640,10 +618,12 @@ NodeVitastorKV::~NodeVitastorKV()
|
|
|
|
|
NAN_METHOD(NodeVitastorKV::Open)
|
|
|
|
|
{
|
|
|
|
|
TRACE("NodeVitastorKV::Open");
|
|
|
|
|
if (info.Length() < 4)
|
|
|
|
|
Nan::ThrowError("Not enough arguments to open(pool_id, inode_num, { ...config }, callback(err))");
|
|
|
|
|
|
|
|
|
|
NodeVitastorKV* kv = Nan::ObjectWrap::Unwrap<NodeVitastorKV>(info.This());
|
|
|
|
|
|
|
|
|
|
uint64_t inode_id = INODE_WITH_POOL(Nan::To<int64_t>(info[0]).FromJust(), Nan::To<int64_t>(info[1]).FromJust());
|
|
|
|
|
uint64_t inode_id = INODE_WITH_POOL(get_ui64(info[0]), get_ui64(info[1]));
|
|
|
|
|
|
|
|
|
|
v8::Local<v8::Object> jsParams = info[2].As<v8::Object>();
|
|
|
|
|
v8::Local<v8::Array> keys = Nan::GetOwnPropertyNames(jsParams).ToLocalChecked();
|
|
|
|
@@ -674,6 +654,8 @@ NAN_METHOD(NodeVitastorKV::Open)
|
|
|
|
|
NAN_METHOD(NodeVitastorKV::Close)
|
|
|
|
|
{
|
|
|
|
|
TRACE("NodeVitastorKV::Close");
|
|
|
|
|
if (info.Length() < 1)
|
|
|
|
|
Nan::ThrowError("Not enough arguments to close(callback(err))");
|
|
|
|
|
|
|
|
|
|
NodeVitastorKV* kv = Nan::ObjectWrap::Unwrap<NodeVitastorKV>(info.This());
|
|
|
|
|
|
|
|
|
@@ -695,6 +677,8 @@ NAN_METHOD(NodeVitastorKV::Close)
|
|
|
|
|
NAN_METHOD(NodeVitastorKV::SetConfig)
|
|
|
|
|
{
|
|
|
|
|
TRACE("NodeVitastorKV::SetConfig");
|
|
|
|
|
if (info.Length() < 1)
|
|
|
|
|
Nan::ThrowError("Not enough arguments to set_config({ ...config })");
|
|
|
|
|
|
|
|
|
|
NodeVitastorKV* kv = Nan::ObjectWrap::Unwrap<NodeVitastorKV>(info.This());
|
|
|
|
|
|
|
|
|
@@ -751,6 +735,8 @@ void NodeVitastorKV::get_impl(const Nan::FunctionCallbackInfo<v8::Value> & info,
|
|
|
|
|
NAN_METHOD(NodeVitastorKV::Get)
|
|
|
|
|
{
|
|
|
|
|
TRACE("NodeVitastorKV::Get");
|
|
|
|
|
if (info.Length() < 2)
|
|
|
|
|
Nan::ThrowError("Not enough arguments to get(key, callback(err, value))");
|
|
|
|
|
get_impl(info, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -758,6 +744,8 @@ NAN_METHOD(NodeVitastorKV::Get)
|
|
|
|
|
NAN_METHOD(NodeVitastorKV::GetCached)
|
|
|
|
|
{
|
|
|
|
|
TRACE("NodeVitastorKV::GetCached");
|
|
|
|
|
if (info.Length() < 2)
|
|
|
|
|
Nan::ThrowError("Not enough arguments to get_cached(key, callback(err, value))");
|
|
|
|
|
get_impl(info, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -776,10 +764,12 @@ static std::function<bool(int, const std::string &)> make_cas_callback(NodeVitas
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// set(key, value, callback(err), cas_compare(old_value))
|
|
|
|
|
// set(key, value, callback(err), cas_compare(old_value)?)
|
|
|
|
|
NAN_METHOD(NodeVitastorKV::Set)
|
|
|
|
|
{
|
|
|
|
|
TRACE("NodeVitastorKV::Set");
|
|
|
|
|
if (info.Length() < 3)
|
|
|
|
|
Nan::ThrowError("Not enough arguments to set(key, value, callback(err), cas_compare(old_value)?)");
|
|
|
|
|
|
|
|
|
|
NodeVitastorKV* kv = Nan::ObjectWrap::Unwrap<NodeVitastorKV>(info.This());
|
|
|
|
|
|
|
|
|
@@ -813,10 +803,12 @@ NAN_METHOD(NodeVitastorKV::Set)
|
|
|
|
|
}, cas_cb);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// del(key, callback(err), cas_compare(old_value))
|
|
|
|
|
// del(key, callback(err), cas_compare(old_value)?)
|
|
|
|
|
NAN_METHOD(NodeVitastorKV::Del)
|
|
|
|
|
{
|
|
|
|
|
TRACE("NodeVitastorKV::Del");
|
|
|
|
|
if (info.Length() < 2)
|
|
|
|
|
Nan::ThrowError("Not enough arguments to del(key, callback(err), cas_compare(old_value)?)");
|
|
|
|
|
|
|
|
|
|
NodeVitastorKV* kv = Nan::ObjectWrap::Unwrap<NodeVitastorKV>(info.This());
|
|
|
|
|
|
|
|
|
@@ -870,7 +862,6 @@ NAN_METHOD(NodeVitastorKV::List)
|
|
|
|
|
{
|
|
|
|
|
TRACE("NodeVitastorKV::Destroy");
|
|
|
|
|
NodeVitastorKV* kv = Nan::ObjectWrap::Unwrap<NodeVitastorKV>(info.This());
|
|
|
|
|
std::unique_lock<std::mutex> lock(self->mu);
|
|
|
|
|
if (!kv->dead)
|
|
|
|
|
kv->Unref();
|
|
|
|
|
}*/
|
|
|
|
@@ -896,10 +887,7 @@ NAN_METHOD(NodeVitastorKVListing::Create)
|
|
|
|
|
|
|
|
|
|
NodeVitastorKVListing *list = new NodeVitastorKVListing();
|
|
|
|
|
list->kv = kv;
|
|
|
|
|
{
|
|
|
|
|
std::unique_lock<std::mutex> lock(kv->cli->mu);
|
|
|
|
|
list->handle = list->kv->dbw->list_start(start_key);
|
|
|
|
|
}
|
|
|
|
|
list->handle = list->kv->dbw->list_start(start_key);
|
|
|
|
|
|
|
|
|
|
list->Wrap(info.This());
|
|
|
|
|
kv->Ref();
|
|
|
|
@@ -910,36 +898,54 @@ NodeVitastorKVListing::~NodeVitastorKVListing()
|
|
|
|
|
{
|
|
|
|
|
if (handle)
|
|
|
|
|
{
|
|
|
|
|
std::unique_lock<std::mutex> lock(kv->cli->mu);
|
|
|
|
|
kv->dbw->list_close(handle);
|
|
|
|
|
handle = NULL;
|
|
|
|
|
}
|
|
|
|
|
if (iter)
|
|
|
|
|
{
|
|
|
|
|
delete iter;
|
|
|
|
|
iter = NULL;
|
|
|
|
|
}
|
|
|
|
|
kv->Unref();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// next(callback(err, value))
|
|
|
|
|
// next(callback(err, value)?)
|
|
|
|
|
NAN_METHOD(NodeVitastorKVListing::Next)
|
|
|
|
|
{
|
|
|
|
|
TRACE("NodeVitastorKVListing::Next");
|
|
|
|
|
|
|
|
|
|
NodeVitastorKVListing* list = Nan::ObjectWrap::Unwrap<NodeVitastorKVListing>(info.This());
|
|
|
|
|
|
|
|
|
|
v8::Local<v8::Function> callback = info[0].As<v8::Function>();
|
|
|
|
|
auto req = new NodeVitastorRequest(list->kv->cli, callback);
|
|
|
|
|
if (info.Length() > 0)
|
|
|
|
|
{
|
|
|
|
|
v8::Local<v8::Function> callback = info[0].As<v8::Function>();
|
|
|
|
|
if (list->iter)
|
|
|
|
|
{
|
|
|
|
|
delete list->iter;
|
|
|
|
|
}
|
|
|
|
|
list->iter = new NodeVitastorRequest(list->kv->cli, callback);
|
|
|
|
|
}
|
|
|
|
|
if (!list->handle)
|
|
|
|
|
{
|
|
|
|
|
// Already closed
|
|
|
|
|
Nan::Callback nanCallback(Nan::New(req->callback));
|
|
|
|
|
v8::Local<v8::Value> args[1];
|
|
|
|
|
args[0] = Nan::New<v8::Int32>(-EINVAL);
|
|
|
|
|
nanCallback.Call(1, args, req);
|
|
|
|
|
delete req;
|
|
|
|
|
if (list->iter)
|
|
|
|
|
{
|
|
|
|
|
auto req = list->iter;
|
|
|
|
|
list->iter = NULL;
|
|
|
|
|
Nan::Callback nanCallback(Nan::New(req->callback));
|
|
|
|
|
v8::Local<v8::Value> args[1];
|
|
|
|
|
args[0] = Nan::New<v8::Int32>(-EINVAL);
|
|
|
|
|
nanCallback.Call(1, args, req);
|
|
|
|
|
delete req;
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
list->kv->Ref();
|
|
|
|
|
list->kv->dbw->list_next(list->handle, [list, req](int res, const std::string & key, const std::string & value)
|
|
|
|
|
list->kv->dbw->list_next(list->handle, [list](int res, const std::string & key, const std::string & value)
|
|
|
|
|
{
|
|
|
|
|
auto req = list->iter;
|
|
|
|
|
list->iter = NULL;
|
|
|
|
|
Nan::HandleScope scope;
|
|
|
|
|
Nan::Callback nanCallback(Nan::New(req->callback));
|
|
|
|
|
v8::Local<v8::Value> args[3];
|
|
|
|
@@ -947,7 +953,10 @@ NAN_METHOD(NodeVitastorKVListing::Next)
|
|
|
|
|
args[1] = !res ? v8::Local<v8::Value>(Nan::New<v8::String>(key).ToLocalChecked()) : v8::Local<v8::Value>(Nan::Null());
|
|
|
|
|
args[2] = !res ? v8::Local<v8::Value>(Nan::New<v8::String>(value).ToLocalChecked()) : v8::Local<v8::Value>(Nan::Null());
|
|
|
|
|
nanCallback.Call(3, args, req);
|
|
|
|
|
delete req;
|
|
|
|
|
if (list->iter)
|
|
|
|
|
delete req;
|
|
|
|
|
else
|
|
|
|
|
list->iter = req;
|
|
|
|
|
list->kv->Unref();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
@@ -961,8 +970,12 @@ NAN_METHOD(NodeVitastorKVListing::Close)
|
|
|
|
|
|
|
|
|
|
if (list->handle)
|
|
|
|
|
{
|
|
|
|
|
std::unique_lock<std::mutex> lock(list->kv->cli->mu);
|
|
|
|
|
list->kv->dbw->list_close(list->handle);
|
|
|
|
|
list->handle = NULL;
|
|
|
|
|
}
|
|
|
|
|
if (list->iter)
|
|
|
|
|
{
|
|
|
|
|
delete list->iter;
|
|
|
|
|
list->iter = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|