lets/c_src/lets_nif_lib.cc
Joseph Wayne Norton 4a2b2d6ac3 Initial commit
2011-10-26 23:09:08 +09:00

300 lines
11 KiB
C++

// The MIT License
//
// Copyright (C) 2011 by Joseph Wayne Norton <norton@alum.mit.edu>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "lets_nif_lib.h"
#if 0
static bool
return_false(unsigned line) {
fprintf(stderr, "FALSE %s:%d\n", __FILE__, line);
return false;
}
#define FALSE return_false(__LINE__)
#else
#define FALSE false
#endif
ERL_NIF_TERM lets_atom_true = 0;
ERL_NIF_TERM lets_atom_false = 0;
ERL_NIF_TERM lets_atom_set = 0;
ERL_NIF_TERM lets_atom_ordered_set = 0;
ERL_NIF_TERM lets_atom_private = 0;
ERL_NIF_TERM lets_atom_protected = 0;
ERL_NIF_TERM lets_atom_public = 0;
ERL_NIF_TERM lets_atom_create_if_missing = 0;
ERL_NIF_TERM lets_atom_error_if_exists = 0;
ERL_NIF_TERM lets_atom_paranoid_checks = 0;
ERL_NIF_TERM lets_atom_write_buffer_size = 0;
ERL_NIF_TERM lets_atom_max_open_files = 0;
ERL_NIF_TERM lets_atom_block_cache_size = 0;
ERL_NIF_TERM lets_atom_block_size = 0;
ERL_NIF_TERM lets_atom_compression = 0;
ERL_NIF_TERM lets_atom_no = 0;
ERL_NIF_TERM lets_atom_snappy = 0;
ERL_NIF_TERM lets_atom_block_restart_interval = 0;
ERL_NIF_TERM lets_atom_verify_checksums = 0;
ERL_NIF_TERM lets_atom_fill_cache = 0;
ERL_NIF_TERM lets_atom_sync = 0;
ERL_NIF_TERM lets_atom_end_of_table = 0;
bool
lets_nif_lib_init(ErlNifEnv* env)
{
lets_atom_true = enif_make_atom(env, "true");
lets_atom_false = enif_make_atom(env, "false");
lets_atom_set = enif_make_atom(env, "set");
lets_atom_ordered_set = enif_make_atom(env, "ordered_set");
lets_atom_private = enif_make_atom(env, "private");
lets_atom_protected = enif_make_atom(env, "protected");
lets_atom_public = enif_make_atom(env, "public");
lets_atom_create_if_missing = enif_make_atom(env, "create_if_missing");
lets_atom_error_if_exists = enif_make_atom(env, "error_if_exists");
lets_atom_paranoid_checks = enif_make_atom(env, "paranoid_checks");
lets_atom_write_buffer_size = enif_make_atom(env, "write_buffer_size");
lets_atom_max_open_files = enif_make_atom(env, "max_open_files");
lets_atom_block_cache_size = enif_make_atom(env, "block_cache_size");
lets_atom_block_size = enif_make_atom(env, "block_size");
lets_atom_compression = enif_make_atom(env, "compression");
lets_atom_no = enif_make_atom(env, "no");
lets_atom_snappy = enif_make_atom(env, "snappy");
lets_atom_block_restart_interval = enif_make_atom(env, "block_restart_interval");
lets_atom_verify_checksums = enif_make_atom(env, "verify_checksums");
lets_atom_fill_cache = enif_make_atom(env, "fill_cache");
lets_atom_sync = enif_make_atom(env, "sync");
lets_atom_end_of_table = enif_make_atom(env, "$end_of_table");
return true;
}
bool
lets_init(lets_impl& impl,
const char type, const char privacy, const char* name, const size_t namelen)
{
impl.type = type;
impl.privacy = privacy;
impl.name = new std::string(name, namelen);
if (!impl.name) {
return FALSE;
}
impl.db_options = leveldb::Options();
impl.db_read_options = leveldb::ReadOptions();
impl.db_write_options = leveldb::WriteOptions();
return true;
}
bool
lets_create(lets_impl& impl,
const char op)
{
leveldb::Status status;
// db
switch (op) {
case OPEN:
status = leveldb::DB::Open(impl.db_options, impl.name->c_str(), &(impl.db));
if (!status.ok()) {
return FALSE;
} else {
// alive
impl.alive = 1;
}
break;
case DESTROY:
status = DestroyDB(impl.name->c_str(), impl.db_options);
if (!status.ok()) {
return FALSE;
}
break;
case REPAIR:
status = RepairDB(impl.name->c_str(), impl.db_options);
if (!status.ok()) {
return FALSE;
}
break;
default:
return FALSE;
}
return true;
}
bool
lets_parse_options(ErlNifEnv* env, lets_impl& impl,
ERL_NIF_TERM& options, const ERL_NIF_TERM& options_len)
{
ERL_NIF_TERM head, tail;
int arity;
const ERL_NIF_TERM* tuple;
while (enif_get_list_cell(env, options, &head, &tail)) {
if (enif_is_identical(head, lets_atom_create_if_missing)) {
impl.db_options.create_if_missing = true;
} else if (enif_is_identical(head, lets_atom_error_if_exists)) {
impl.db_options.error_if_exists = true;
} else if (enif_is_identical(head, lets_atom_paranoid_checks)) {
impl.db_options.paranoid_checks = true;
} else if (enif_get_tuple(env, head, &arity, &tuple) && arity == 2) {
unsigned int val;
if (enif_is_identical(tuple[0], lets_atom_create_if_missing)) {
if (enif_is_identical(tuple[1], lets_atom_true)) {
impl.db_options.create_if_missing = true;
} else if (enif_is_identical(tuple[1], lets_atom_false)) {
impl.db_options.create_if_missing = false;
} else {
return FALSE;
}
} else if (enif_is_identical(tuple[0], lets_atom_error_if_exists)) {
if (enif_is_identical(tuple[1], lets_atom_true)) {
impl.db_options.error_if_exists = true;
} else if (enif_is_identical(tuple[1], lets_atom_false)) {
impl.db_options.error_if_exists = false;
} else {
return FALSE;
}
} else if (enif_is_identical(tuple[0], lets_atom_paranoid_checks)) {
impl.db_options.paranoid_checks = true;
if (enif_is_identical(tuple[1], lets_atom_true)) {
impl.db_options.paranoid_checks = true;
} else if (enif_is_identical(tuple[1], lets_atom_false)) {
impl.db_options.paranoid_checks = false;
} else {
return FALSE;
}
} else if (enif_is_identical(tuple[0], lets_atom_write_buffer_size) &&
enif_get_uint(env, tuple[1], &val)) {
impl.db_options.write_buffer_size = val;
} else if (enif_is_identical(tuple[0], lets_atom_max_open_files) &&
enif_get_uint(env, tuple[1], &val)) {
impl.db_options.max_open_files = val;
} else if (enif_is_identical(tuple[0], lets_atom_block_cache_size) &&
enif_get_uint(env, tuple[1], &val)) {
impl.db_block_cache_size = val;
impl.db_block_cache = leveldb::NewLRUCache(impl.db_block_cache_size);
impl.db_options.block_cache = impl.db_block_cache;
if (!impl.db_options.block_cache) {
return FALSE;
}
} else if (enif_is_identical(tuple[0], lets_atom_block_size) &&
enif_get_uint(env, tuple[1], &val)) {
impl.db_options.block_size = val;
} else if (enif_is_identical(tuple[0], lets_atom_block_restart_interval) &&
enif_get_uint(env, tuple[1], &val)) {
impl.db_options.block_restart_interval = val;
} else if (enif_is_identical(tuple[0], lets_atom_compression)) {
if (enif_is_identical(tuple[1], lets_atom_no)) {
impl.db_options.compression = leveldb::kNoCompression;
} else if (enif_is_identical(tuple[1], lets_atom_snappy)) {
impl.db_options.compression = leveldb::kSnappyCompression;
} else {
return FALSE;
}
} else {
return FALSE;
}
} else {
return FALSE;
}
options = tail;
}
return true;
}
bool
lets_parse_read_options(ErlNifEnv* env, lets_impl& impl,
ERL_NIF_TERM& options, const ERL_NIF_TERM& options_len)
{
ERL_NIF_TERM head, tail;
int arity;
const ERL_NIF_TERM* tuple;
// TODO: snapshot
while (enif_get_list_cell(env, options, &head, &tail)) {
if (enif_is_identical(head, lets_atom_verify_checksums)) {
impl.db_read_options.verify_checksums = true;
} else if (enif_is_identical(head, lets_atom_fill_cache)) {
impl.db_read_options.fill_cache = true;
} else if (enif_get_tuple(env, head, &arity, &tuple) && arity == 2) {
if (enif_is_identical(tuple[0], lets_atom_verify_checksums)) {
if (enif_is_identical(tuple[1], lets_atom_true)) {
impl.db_read_options.verify_checksums = true;
} else if (enif_is_identical(tuple[1], lets_atom_false)) {
impl.db_read_options.verify_checksums = false;
} else {
return FALSE;
}
} else if (enif_is_identical(tuple[0], lets_atom_fill_cache)) {
if (enif_is_identical(tuple[1], lets_atom_true)) {
impl.db_read_options.fill_cache = true;
} else if (enif_is_identical(tuple[1], lets_atom_false)) {
impl.db_read_options.fill_cache = false;
} else {
return FALSE;
}
} else {
return FALSE;
}
} else {
return FALSE;
}
options = tail;
}
return true;
}
bool
lets_parse_write_options(ErlNifEnv* env, lets_impl& impl,
ERL_NIF_TERM& options, const ERL_NIF_TERM& options_len)
{
ERL_NIF_TERM head, tail;
int arity;
const ERL_NIF_TERM* tuple;
// TODO: snapshot
while (enif_get_list_cell(env, options, &head, &tail)) {
if (enif_is_identical(head, lets_atom_sync)) {
impl.db_write_options.sync = true;
} else if (enif_get_tuple(env, head, &arity, &tuple) && arity == 2) {
if (enif_is_identical(tuple[0], lets_atom_sync)) {
if (enif_is_identical(tuple[1], lets_atom_true)) {
impl.db_write_options.sync = true;
} else if (enif_is_identical(tuple[1], lets_atom_false)) {
impl.db_write_options.sync = false;
} else {
return FALSE;
}
} else {
return FALSE;
}
} else {
return FALSE;
}
options = tail;
}
return true;
}