wterl/c_src/wterl.c
2012-02-20 13:30:09 -05:00

753 lines
26 KiB
C

// -------------------------------------------------------------------
//
// wterl: Erlang Wrapper for WiredTiger
//
// Copyright (c) 2011 Basho Technologies, Inc. All Rights Reserved.
//
// This file is provided to you under the Apache License,
// Version 2.0 (the "License"); you may not use this file
// except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// -------------------------------------------------------------------
#include "erl_nif.h"
#include "erl_driver.h"
#include <stdio.h>
#include <string.h>
#include "wiredtiger.h"
static ErlNifResourceType* wterl_conn_RESOURCE;
static ErlNifResourceType* wterl_session_RESOURCE;
static ErlNifResourceType* wterl_cursor_RESOURCE;
typedef struct
{
WT_CONNECTION* conn;
} wterl_conn_handle;
typedef struct
{
WT_SESSION* session;
} wterl_session_handle;
typedef struct
{
WT_CURSOR* cursor;
} wterl_cursor_handle;
typedef char Uri[128]; // object names
// Atoms (initialized in on_load)
static ERL_NIF_TERM ATOM_ERROR;
static ERL_NIF_TERM ATOM_OK;
typedef ERL_NIF_TERM (*CursorRetFun)(ErlNifEnv* env, WT_CURSOR* cursor, int rc);
// Prototypes
static ERL_NIF_TERM wterl_conn_close(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM wterl_conn_open(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM wterl_cursor_close(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM wterl_cursor_insert(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM wterl_cursor_key_ret(ErlNifEnv* env, WT_CURSOR *cursor, int rc);
static ERL_NIF_TERM wterl_cursor_kv_ret(ErlNifEnv* env, WT_CURSOR *cursor, int rc);
static ERL_NIF_TERM wterl_cursor_next(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM wterl_cursor_next_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM wterl_cursor_next_value(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM wterl_cursor_np_worker(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[],
CursorRetFun cursor_ret_fun, int next);
static ERL_NIF_TERM wterl_cursor_open(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM wterl_cursor_prev(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM wterl_cursor_prev_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM wterl_cursor_prev_value(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM wterl_cursor_remove(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM wterl_cursor_reset(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM wterl_cursor_search(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM wterl_cursor_search_near(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM wterl_cursor_search_worker(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[], int near);
static ERL_NIF_TERM wterl_cursor_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM wterl_cursor_value_ret(ErlNifEnv* env, WT_CURSOR *cursor, int rc);
static ERL_NIF_TERM wterl_session_close(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM wterl_session_create(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM wterl_session_delete(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM wterl_session_drop(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM wterl_session_get(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM wterl_session_open(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM wterl_session_put(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM wterl_session_rename(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM wterl_session_salvage(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM wterl_session_sync(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM wterl_session_truncate(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM wterl_session_upgrade(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM wterl_session_verify(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ErlNifFunc nif_funcs[] =
{
{"conn_close", 1, wterl_conn_close},
{"conn_open", 2, wterl_conn_open},
{"cursor_close", 1, wterl_cursor_close},
{"cursor_insert", 3, wterl_cursor_insert},
{"cursor_next", 1, wterl_cursor_next},
{"cursor_next_key", 1, wterl_cursor_next_key},
{"cursor_next_value", 1, wterl_cursor_next_value},
{"cursor_open", 2, wterl_cursor_open},
{"cursor_prev", 1, wterl_cursor_prev},
{"cursor_prev_key", 1, wterl_cursor_prev_key},
{"cursor_prev_value", 1, wterl_cursor_prev_value},
{"cursor_remove", 3, wterl_cursor_remove},
{"cursor_reset", 1, wterl_cursor_reset},
{"cursor_search", 2, wterl_cursor_search},
{"cursor_search_near", 2, wterl_cursor_search_near},
{"cursor_update", 3, wterl_cursor_update},
{"session_close", 1, wterl_session_close},
{"session_create", 3, wterl_session_create},
{"session_delete", 3, wterl_session_delete},
{"session_drop", 3, wterl_session_drop},
{"session_get", 3, wterl_session_get},
{"session_open", 1, wterl_session_open},
{"session_put", 4, wterl_session_put},
{"session_rename", 4, wterl_session_rename},
{"session_salvage", 3, wterl_session_salvage},
{"session_sync", 3, wterl_session_sync},
{"session_truncate", 3, wterl_session_truncate},
{"session_upgrade", 3, wterl_session_upgrade},
{"session_verify", 3, wterl_session_verify},
};
static inline ERL_NIF_TERM wterl_strerror(ErlNifEnv* env, int rc)
{
if (rc == WT_NOTFOUND)
return enif_make_atom(env, "not_found");
else
return enif_make_tuple2(env, ATOM_ERROR,
enif_make_string(env, wiredtiger_strerror(rc), ERL_NIF_LATIN1));
}
static ERL_NIF_TERM wterl_conn_open(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary config;
char homedir[4096];
if (enif_get_string(env, argv[0], homedir, sizeof homedir, ERL_NIF_LATIN1) &&
enif_inspect_binary(env, argv[1], &config))
{
WT_CONNECTION* conn;
int rc = wiredtiger_open(homedir, NULL, (const char*)config.data, &conn);
if (rc == 0)
{
wterl_conn_handle* conn_handle =
enif_alloc_resource(wterl_conn_RESOURCE, sizeof(wterl_conn_handle));
conn_handle->conn = conn;
ERL_NIF_TERM result = enif_make_resource(env, conn_handle);
enif_release_resource(conn_handle);
return enif_make_tuple2(env, ATOM_OK, result);
}
else
{
return wterl_strerror(env, rc);
}
}
return enif_make_badarg(env);
}
static ERL_NIF_TERM wterl_conn_close(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
wterl_conn_handle* conn_handle;
if (enif_get_resource(env, argv[0], wterl_conn_RESOURCE, (void**)&conn_handle))
{
WT_CONNECTION* conn = conn_handle->conn;
int rc = conn->close(conn, NULL);
if (rc != 0)
{
return wterl_strerror(env, rc);
}
else {
return ATOM_OK;
}
}
return enif_make_badarg(env);
}
#define WTERL_OP_CREATE 1
#define WTERL_OP_DROP 2
#define WTERL_OP_SALVAGE 3
#define WTERL_OP_SYNC 4
#define WTERL_OP_TRUNCATE 5
#define WTERL_OP_UPGRADE 6
#define WTERL_OP_VERIFY 7
static inline ERL_NIF_TERM wterl_session_worker(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[], int op)
{
wterl_session_handle* session_handle;
if (enif_get_resource(env, argv[0], wterl_session_RESOURCE, (void**)&session_handle))
{
WT_SESSION* session = session_handle->session;
ErlNifBinary config;
Uri uri;
if (enif_get_string(env, argv[1], uri, sizeof uri, ERL_NIF_LATIN1) &&
enif_inspect_binary(env, argv[2], &config))
{
int rc;
switch (op) {
case WTERL_OP_CREATE:
rc = session->create(session, uri, (const char*)config.data);
break;
case WTERL_OP_DROP:
rc = session->drop(session, uri, (const char*)config.data);
break;
case WTERL_OP_SALVAGE:
rc = session->salvage(session, uri, (const char*)config.data);
break;
case WTERL_OP_SYNC:
rc = session->sync(session, uri, (const char*)config.data);
break;
case WTERL_OP_TRUNCATE:
// Ignore the cursor start/stop form of truncation for now,
// support only the full file truncation.
rc = session->truncate(session, uri, NULL, NULL, (const char*)config.data);
break;
case WTERL_OP_UPGRADE:
rc = session->upgrade(session, uri, (const char*)config.data);
break;
default:
case WTERL_OP_VERIFY:
rc = session->verify(session, uri, (const char*)config.data);
break;
}
if (rc != 0)
{
return wterl_strerror(env, rc);
}
else
{
return ATOM_OK;
}
}
}
return enif_make_badarg(env);
}
static ERL_NIF_TERM wterl_session_open(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
wterl_conn_handle* conn_handle;
if (enif_get_resource(env, argv[0], wterl_conn_RESOURCE, (void**)&conn_handle))
{
WT_CONNECTION* conn = conn_handle->conn;
WT_SESSION* session;
int rc = conn->open_session(conn, NULL, NULL, &session);
if (rc == 0)
{
wterl_session_handle* session_handle =
enif_alloc_resource(wterl_session_RESOURCE, sizeof(wterl_session_handle));
session_handle->session = session;
ERL_NIF_TERM result = enif_make_resource(env, session_handle);
enif_keep_resource(conn_handle);
enif_release_resource(session_handle);
return enif_make_tuple2(env, ATOM_OK, result);
}
else
{
return wterl_strerror(env, rc);
}
}
return enif_make_badarg(env);
}
static ERL_NIF_TERM wterl_session_close(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
wterl_session_handle* session_handle;
if (enif_get_resource(env, argv[0], wterl_session_RESOURCE, (void**)&session_handle))
{
WT_SESSION* session = session_handle->session;
int rc = session->close(session, NULL);
if (rc != 0)
{
return wterl_strerror(env, rc);
}
else
{
return ATOM_OK;
}
}
return enif_make_badarg(env);
}
static ERL_NIF_TERM wterl_session_create(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
return wterl_session_worker(env, argc, argv, WTERL_OP_CREATE);
}
static ERL_NIF_TERM wterl_session_drop(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
return wterl_session_worker(env, argc, argv, WTERL_OP_DROP);
}
static ERL_NIF_TERM wterl_session_rename(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
wterl_session_handle* session_handle;
if (enif_get_resource(env, argv[0], wterl_session_RESOURCE, (void**)&session_handle))
{
WT_SESSION* session = session_handle->session;
ErlNifBinary config;
Uri oldname, newname;
if (enif_get_string(env, argv[1], oldname, sizeof oldname, ERL_NIF_LATIN1) &&
enif_get_string(env, argv[2], newname, sizeof newname, ERL_NIF_LATIN1) &&
enif_inspect_binary(env, argv[3], &config))
{
int rc = session->rename(session, oldname, newname, (const char*)config.data);
if (rc != 0)
{
return wterl_strerror(env, rc);
}
else
{
return ATOM_OK;
}
}
}
return enif_make_badarg(env);
}
static ERL_NIF_TERM wterl_session_salvage(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
return wterl_session_worker(env, argc, argv, WTERL_OP_SALVAGE);
}
static ERL_NIF_TERM wterl_session_sync(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
return wterl_session_worker(env, argc, argv, WTERL_OP_SYNC);
}
static ERL_NIF_TERM wterl_session_truncate(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
return wterl_session_worker(env, argc, argv, WTERL_OP_TRUNCATE);
}
static ERL_NIF_TERM wterl_session_upgrade(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
return wterl_session_worker(env, argc, argv, WTERL_OP_UPGRADE);
}
static ERL_NIF_TERM wterl_session_verify(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
return wterl_session_worker(env, argc, argv, WTERL_OP_VERIFY);
}
static ERL_NIF_TERM wterl_session_delete(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
wterl_session_handle* session_handle;
if (enif_get_resource(env, argv[0], wterl_session_RESOURCE, (void**)&session_handle))
{
WT_SESSION* session = session_handle->session;
Uri uri;
ErlNifBinary key;
if (enif_get_string(env, argv[1], uri, sizeof uri, ERL_NIF_LATIN1) &&
enif_inspect_binary(env, argv[2], &key))
{
WT_CURSOR* cursor;
int rc = session->open_cursor(session, uri, NULL, "raw", &cursor);
if (rc != 0)
{
return wterl_strerror(env, rc);
}
WT_ITEM raw_key;
raw_key.data = key.data;
raw_key.size = key.size;
cursor->set_key(cursor, &raw_key);
rc = cursor->remove(cursor);
(void)cursor->close(cursor);
if (rc != 0)
{
return wterl_strerror(env, rc);
}
else
{
return ATOM_OK;
}
}
}
return enif_make_badarg(env);
}
static ERL_NIF_TERM wterl_session_get(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
wterl_session_handle* session_handle;
if (enif_get_resource(env, argv[0], wterl_session_RESOURCE, (void**)&session_handle))
{
WT_SESSION* session = session_handle->session;
Uri uri;
ErlNifBinary key;
if (enif_get_string(env, argv[1], uri, sizeof uri, ERL_NIF_LATIN1) &&
enif_inspect_binary(env, argv[2], &key))
{
WT_CURSOR* cursor;
int rc = session->open_cursor(session, uri, NULL, "overwrite,raw", &cursor);
if (rc != 0)
{
return wterl_strerror(env, rc);
}
WT_ITEM raw_key, raw_value;
raw_key.data = key.data;
raw_key.size = key.size;
cursor->set_key(cursor, &raw_key);
rc = cursor->search(cursor);
if (rc == 0)
rc = cursor->get_value(cursor, &raw_value);
(void)cursor->close(cursor);
if (rc == 0)
{
ERL_NIF_TERM value;
memcpy(enif_make_new_binary(env, raw_value.size, &value), raw_value.data, raw_value.size);
return enif_make_tuple2(env, ATOM_OK, value);
}
else
{
return wterl_strerror(env, rc);
}
}
}
return enif_make_badarg(env);
}
static ERL_NIF_TERM wterl_session_put(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
wterl_session_handle* session_handle;
if (enif_get_resource(env, argv[0], wterl_session_RESOURCE, (void**)&session_handle))
{
WT_SESSION* session = session_handle->session;
Uri uri;
ErlNifBinary key, value;
if (enif_get_string(env, argv[1], uri, sizeof uri, ERL_NIF_LATIN1) &&
enif_inspect_binary(env, argv[2], &key) &&
enif_inspect_binary(env, argv[3], &value))
{
WT_CURSOR* cursor;
int rc = session->open_cursor(session, uri, NULL, "overwrite,raw", &cursor);
if (rc != 0)
{
return wterl_strerror(env, rc);
}
WT_ITEM raw_key, raw_value;
raw_key.data = key.data;
raw_key.size = key.size;
cursor->set_key(cursor, &raw_key);
raw_value.data = value.data;
raw_value.size = value.size;
cursor->set_value(cursor, &raw_value);
rc = cursor->insert(cursor);
(void)cursor->close(cursor);
if (rc != 0)
{
return wterl_strerror(env, rc);
}
return ATOM_OK;
}
}
return enif_make_badarg(env);
}
static ERL_NIF_TERM wterl_cursor_open(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
wterl_session_handle* session_handle;
if (enif_get_resource(env, argv[0], wterl_session_RESOURCE, (void**)&session_handle))
{
WT_SESSION* session = session_handle->session;
WT_CURSOR* cursor;
Uri uri;
if (enif_get_string(env, argv[1], uri, sizeof uri, ERL_NIF_LATIN1))
{
int rc = session->open_cursor(session, uri, NULL, "overwrite,raw", &cursor);
if (rc == 0)
{
wterl_cursor_handle* cursor_handle =
enif_alloc_resource(wterl_cursor_RESOURCE, sizeof(wterl_cursor_handle));
cursor_handle->cursor = cursor;
ERL_NIF_TERM result = enif_make_resource(env, cursor_handle);
enif_keep_resource(session_handle);
enif_release_resource(cursor_handle);
return enif_make_tuple2(env, ATOM_OK, result);
}
else
{
return wterl_strerror(env, rc);
}
}
}
return enif_make_badarg(env);
}
static ERL_NIF_TERM wterl_cursor_close(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
wterl_cursor_handle *cursor_handle;
if (enif_get_resource(env, argv[0], wterl_cursor_RESOURCE, (void**)&cursor_handle))
{
WT_CURSOR* cursor = cursor_handle->cursor;
int rc = cursor->close(cursor);
if (rc == 0)
{
return ATOM_OK;
}
else
{
return wterl_strerror(env, rc);
}
}
return enif_make_badarg(env);
}
static ERL_NIF_TERM wterl_cursor_key_ret(ErlNifEnv* env, WT_CURSOR *cursor, int rc)
{
if (rc == 0)
{
WT_ITEM raw_key;
rc = cursor->get_key(cursor, &raw_key);
if (rc == 0)
{
ERL_NIF_TERM key;
memcpy(enif_make_new_binary(env, raw_key.size, &key), raw_key.data, raw_key.size);
return enif_make_tuple2(env, ATOM_OK, key);
}
}
return wterl_strerror(env, rc);
}
static ERL_NIF_TERM wterl_cursor_kv_ret(ErlNifEnv* env, WT_CURSOR *cursor, int rc)
{
if (rc == 0)
{
WT_ITEM raw_key, raw_value;
rc = cursor->get_key(cursor, &raw_key);
if (rc == 0)
{
rc = cursor->get_value(cursor, &raw_value);
if (rc == 0)
{
ERL_NIF_TERM key, value;
memcpy(enif_make_new_binary(env, raw_key.size, &key), raw_key.data, raw_key.size);
memcpy(enif_make_new_binary(env, raw_value.size, &value), raw_value.data, raw_value.size);
return enif_make_tuple3(env, ATOM_OK, key, value);
}
}
}
return wterl_strerror(env, rc);
}
static ERL_NIF_TERM wterl_cursor_value_ret(ErlNifEnv* env, WT_CURSOR *cursor, int rc)
{
if (rc == 0)
{
WT_ITEM raw_value;
rc = cursor->get_value(cursor, &raw_value);
if (rc == 0)
{
ERL_NIF_TERM value;
memcpy(enif_make_new_binary(env, raw_value.size, &value), raw_value.data, raw_value.size);
return enif_make_tuple2(env, ATOM_OK, value);
}
}
return wterl_strerror(env, rc);
}
static ERL_NIF_TERM wterl_cursor_np_worker(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[],
CursorRetFun cursor_ret, int prev)
{
wterl_cursor_handle *cursor_handle;
if (enif_get_resource(env, argv[0], wterl_cursor_RESOURCE, (void**)&cursor_handle))
{
WT_CURSOR* cursor = cursor_handle->cursor;
return cursor_ret(env, cursor, prev == 0 ? cursor->next(cursor) : cursor->prev(cursor));
}
return enif_make_badarg(env);
}
static ERL_NIF_TERM wterl_cursor_next(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
return wterl_cursor_np_worker(env, argc, argv, wterl_cursor_kv_ret, 0);
}
static ERL_NIF_TERM wterl_cursor_next_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
return wterl_cursor_np_worker(env, argc, argv, wterl_cursor_key_ret, 0);
}
static ERL_NIF_TERM wterl_cursor_next_value(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
return wterl_cursor_np_worker(env, argc, argv, wterl_cursor_value_ret, 0);
}
static ERL_NIF_TERM wterl_cursor_prev(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
return wterl_cursor_np_worker(env, argc, argv, wterl_cursor_kv_ret, 1);
}
static ERL_NIF_TERM wterl_cursor_prev_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
return wterl_cursor_np_worker(env, argc, argv, wterl_cursor_key_ret, 1);
}
static ERL_NIF_TERM wterl_cursor_prev_value(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
return wterl_cursor_np_worker(env, argc, argv, wterl_cursor_value_ret, 1);
}
static ERL_NIF_TERM wterl_cursor_search_worker(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[], int near)
{
wterl_cursor_handle *cursor_handle;
ErlNifBinary key;
if (enif_get_resource(env, argv[0], wterl_cursor_RESOURCE, (void**)&cursor_handle) &&
enif_inspect_binary(env, argv[1], &key))
{
WT_CURSOR* cursor = cursor_handle->cursor;
WT_ITEM raw_key;
int exact;
raw_key.data = key.data;
raw_key.size = key.size;
cursor->set_key(cursor, &raw_key);
// We currently ignore the less-than, greater-than or equals-to return information
// from the cursor.search_near method.
return wterl_cursor_value_ret(env, cursor,
near == 1 ?
cursor->search_near(cursor, &exact) : cursor->search(cursor));
}
return enif_make_badarg(env);
}
static ERL_NIF_TERM wterl_cursor_search(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
return wterl_cursor_search_worker(env, argc, argv, 0);
}
static ERL_NIF_TERM wterl_cursor_search_near(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
return wterl_cursor_search_worker(env, argc, argv, 1);
}
static ERL_NIF_TERM wterl_cursor_reset(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
wterl_cursor_handle *cursor_handle;
if (enif_get_resource(env, argv[0], wterl_cursor_RESOURCE, (void**)&cursor_handle))
{
WT_CURSOR* cursor = cursor_handle->cursor;
int rc = cursor->reset(cursor);
if (rc == 0)
{
return ATOM_OK;
}
else
{
return wterl_strerror(env, rc);
}
}
return enif_make_badarg(env);
}
#define WTERL_OP_CURSOR_INSERT 1
#define WTERL_OP_CURSOR_UPDATE 2
#define WTERL_OP_CURSOR_REMOVE 3
static inline ERL_NIF_TERM wterl_cursor_data_op(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[], int op)
{
wterl_cursor_handle *cursor_handle;
if (enif_get_resource(env, argv[0], wterl_cursor_RESOURCE, (void**)&cursor_handle))
{
ErlNifBinary key, value;
int rc;
if (enif_inspect_binary(env, argv[1], &key) &&
enif_inspect_binary(env, argv[2], &value)) {
WT_CURSOR* cursor = cursor_handle->cursor;
WT_ITEM raw_key, raw_value;
raw_key.data = key.data;
raw_key.size = key.size;
cursor->set_key(cursor, &raw_key);
raw_value.data = value.data;
raw_value.size = value.size;
cursor->set_value(cursor, &raw_value);
switch (op) {
case WTERL_OP_CURSOR_INSERT:
rc = cursor->insert(cursor);
break;
case WTERL_OP_CURSOR_UPDATE:
rc = cursor->update(cursor);
break;
default:
case WTERL_OP_CURSOR_REMOVE:
rc = cursor->remove(cursor);
break;
}
if (rc == 0)
{
return ATOM_OK;
}
else
{
return wterl_strerror(env, rc);
}
}
}
return enif_make_badarg(env);
}
static ERL_NIF_TERM wterl_cursor_insert(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
return wterl_cursor_data_op(env, argc, argv, WTERL_OP_CURSOR_INSERT);
}
static ERL_NIF_TERM wterl_cursor_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
return wterl_cursor_data_op(env, argc, argv, WTERL_OP_CURSOR_UPDATE);
}
static ERL_NIF_TERM wterl_cursor_remove(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
return wterl_cursor_data_op(env, argc, argv, WTERL_OP_CURSOR_REMOVE);
}
static void wterl_conn_resource_cleanup(ErlNifEnv* env, void* arg)
{
/* Delete any dynamically allocated memory stored in wterl_handle */
/* wterl_handle* handle = (wterl_handle*)arg; */
}
static void wterl_session_resource_cleanup(ErlNifEnv* env, void* arg)
{
/* Delete any dynamically allocated memory stored in wterl_handle */
/* wterl_handle* handle = (wterl_handle*)arg; */
}
static void wterl_cursor_resource_cleanup(ErlNifEnv* env, void* arg)
{
/* Delete any dynamically allocated memory stored in wterl_handle */
/* wterl_handle* handle = (wterl_handle*)arg; */
}
static int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
{
ErlNifResourceFlags flags = ERL_NIF_RT_CREATE | ERL_NIF_RT_TAKEOVER;
wterl_conn_RESOURCE = enif_open_resource_type(env, NULL,
"wterl_conn_resource",
&wterl_conn_resource_cleanup,
flags, NULL);
wterl_session_RESOURCE = enif_open_resource_type(env, NULL,
"wterl_session_resource",
&wterl_session_resource_cleanup,
flags, NULL);
wterl_cursor_RESOURCE = enif_open_resource_type(env, NULL,
"wterl_cursor_resource",
&wterl_cursor_resource_cleanup,
flags, NULL);
ATOM_ERROR = enif_make_atom(env, "error");
ATOM_OK = enif_make_atom(env, "ok");
return 0;
}
ERL_NIF_INIT(wterl, nif_funcs, &on_load, NULL, NULL, NULL);