您的位置:首页 > 移动开发 > Objective-C

node-haystack Episode 11: node object of Volume

2016-09-11 16:36 369 查看
With the template, the representation of Volume now is simple and neat.

List of VolumeObject:

#define NODE_CLS_NAME_VOL   "Volume"
/*!
\brief The node object of Volume.
*/
class VolumeObject : public NodeObjectTemplate<Volume> {
public:
using self_t = VolumeObject;
using vol_t = shared_t<wrapped_t>;
public:
explicit VolumeObject(Volume* vol):Base(vol) {
}

IMPL_INIT_FUNC(NODE_CLS_NAME_VOL, {
{ "load", LoadVolume },
{ "close", CloseVolume },
{ "find", FindBlock },
{ "addBlock", AddBlock },
{ "rmBlock", RemoveBlock },
{ "readData", ReadData },
{ "recover", Recover },
{ "verify", Verify },
}, {
{ "numOfBlock", BlockNum },
{ "sizeOfVol", VolumeSize },
})

IMPL_NEW_FUNC(DEFAULT_NEW_FUNC())

private:
/*!
\brief Load volume from a file.
*/
static void LoadVolume(const js_arg_t& args) {
PREPARE_FUNC(args, 3, vol)

std::string path = help::to_string(args[0]);
bool createNew = help::to_bool(args[1]);
bool loadIndex = help::to_bool(args[2]);

INIT_MT_CALLBACK(args, 3);

vol->Load(path, createNew, loadIndex, [&, __CALLBACK_INFO__](int err) {
MT_SCOPE()

if (err) {
MT_FIRE_CB_ERR(err)
return ;
}

MT_FIRE_CB(help::mk_null(iso));
});
}

/*!
\brief Close volume.
*/
static void CloseVolume(const js_arg_t& args) {
PREPARE_FUNC(args, 0, vol)
INIT_MT_CALLBACK(args, 0)

vol->Close([&, __CALLBACK_INFO__](int err) {
MT_SCOPE()

if (err) {
MT_FIRE_CB_ERR(err);
return ;
}

MT_FIRE_CB(help::mk_null(iso));
});
}

/*!
\brief Find specified block
*/
static void FindBlock(const js_arg_t& args) {
PREPARE_FUNC(args, 1, vol)

std::string key = help::to_string(args[0]);
blk_idx_val_t idx;

if (vol->FindBlock(key, &idx)) {
FIRE_CB_ERR_MSG(args, 1, "NOT_FOUND");
return ;
}

FIRE_CB(args, 1,
js::Null(iso),
js_int::New(iso, idx.cookie),
js_int::New(iso, idx.tag),
js_int::New(iso, idx.size)
);
}

/*!
\brief Add a new lbock.
*/
static void AddBlock(const js_arg_t& args) {
PREPARE_FUNC(args, 6, vol)

std::string key = help::to_string(args[0]);
u32 cookie = args[1]->Int32Value();
u16 tag = args[2]->Int32Value();
u16 flag = args[3]->Int32Value();

if (!js_buf::HasInstance(args[4])) {
THROW_JS_EXCEPTION(iso, "INVALID_BUFFER");
return ;
}

js_obj_t obj = args[4].As<js_obj>();
const char* buf = js_buf::Data(obj);
size_t buf_len = js_buf::Length(obj);
size_t len = args[5]->Uint32Value();

if (len > buf_len) {
THROW_JS_EXCEPTION(iso, "LENGTH_OUT_OF_BOUNDS");
return ;
}

shared_t<vec_t<char>> data = mk_shared<vec_t<char>>({buf, buf + len});

INIT_MT_CALLBACK(args, 6)

vol->AppendBlock(key, cookie, tag, flag, data, [&, __CALLBACK_INFO__](int err) mutable {
MT_SCOPE()

if (err) {
MT_FIRE_CB_ERR(err);
return ;
}

MT_FIRE_CB(js::Null(iso));
});
}

/*!
\brief Remove specified block.
*/
static void RemoveBlock(const js_arg_t& args) {
PREPARE_FUNC(args, 2, vol)

std::string key = help::to_string(args[0]);
u32 cookie = args[1]->Uint32Value();

INIT_MT_CALLBACK(args, 2)

vol->RemoveBlock(key, cookie, [&, __CALLBACK_INFO__](int err) {
MT_SCOPE()

if (err) {
MT_FIRE_CB_ERR(err);
return ;
}

MT_FIRE_CB(js::Null(iso));
});
}

/*!
\brief Read block data.
*/
static void ReadData(const js_arg_t& args) {
PREPARE_FUNC(args, 1, vol)

std::string key = help::to_string(args[0]);

INIT_MT_CALLBACK(args, 1)

vol->ReadBlockData(key, [&, __CALLBACK_INFO__](int err, shared_t<vec_t<char>>& data) {
MT_SCOPE()

if (err) {
MT_FIRE_CB_ERR(err);
return ;
}

size_t size = data->size();
char* buf = (char *)malloc(size);

if (!buf) {
MT_FIRE_CB_ERR_MSG("FAIL_TO_ALLOC_MEM");
return ;
}

MT_FIRE_CB(
js::Null(iso),
js_buf::New(iso, buf, size).ToLocalChecked(),
js_int::New(iso, size)
);
});
}

/*!
\brief Recover a volume.
*/
static void Recover(const js_arg_t& args) {
PREPARE_FUNC(args, 2, vol)

std::string src = help::to_string(args[0]);
std::string dst = help::to_string(args[1]);

INIT_MT_CALLBACK(args, 2)

vol->Recover(src, dst, [&, __CALLBACK_INFO__](int err, const std::string& stat, u32 prog) {
MT_SCOPE()

if (err) {
MT_FIRE_CB_ERR(err);
return ;
}

MT_FIRE_CB({
help::mk_null(iso),
help::mk_str(iso, stat),
js_int::New(iso, prog)
});
});
}

/*!
\brief Verify a volume.
*/
static void Verify(const js_arg_t& args) {
PREPARE_FUNC(args, 2, vol)

std::string src = help::to_string(args[0]);
std::string dst = help::to_string(args[1]);

INIT_MT_CALLBACK(args, 2)

vol->Verify(src, dst, [&, __CALLBACK_INFO__](int err, const std::string& stat, u32 prog) {
MT_SCOPE()

if (err) {
MT_FIRE_CB_ERR(err);
return ;
}

MT_FIRE_CB({
help::mk_null(iso),
help::mk_str(iso, stat),
js_int::New(iso, prog)
});
});
}

/*!
\brief Get the number of blocks.
*/
static void BlockNum(js_str_t prop_name, const js_prop_t& prop) {
PREPARE_PROP(prop, vol, [&](vol_t vol) {
return static_cast<u32>(vol == nullptr ? 0 : vol->BlockNum());
});
}

/*!
\brief Get file size of volume.
*/
static void VolumeSize(js_str_t prop_name, const js_prop_t& prop) {
PREPARE_PROP(prop, vol, [&](vol_t vol ) {
return js_num::New(iso, vol == nullptr ? (u64)0 : vol->FileSize());
});
}

private:
DECL_CTOR()
}; // class


Project

Sorry, I omit this part.

Test

A test code looks like this:

var volume = require('../node-volume');
var random = require('../node-random');
var vol = new volume();
var vol_path = '/storage/node-volume-test.vol';

vol.load(vol_path, true, true, function(err) {
if (err) {
console.log('Failed to load volume:', err);
return ;
}

var num = 1024;
var buf = Buffer.allocUnsafe(1024).fill(0xAF);

function add_more_blocks() {
if (num == 0) {
return vol.close(function(err) {

if (err) {
console.log('Failed to close volume:', err);
return ;
}

console.log('Volume closed');
});
}

num--;

var key = random.nextUuid();
var cookie = random.next();
var tag = 0x1;
var flag = 0;

console.log('Add block:', 1024 - num);
vol.addBlock(key, cookie, tag, flag, buf, buf.length, function(err) {
if (err) {
console.log('Failed to add block:', err);
return ;
}

add_more_blocks();
});
} // fn add_more_blocks

add_more_blocks();
});
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  node-js haystack c++