Skip to content
Browse files

Introduce NIFs for most file ops in bitcask_fileops

  • Loading branch information...
1 parent 08c765d commit 79d5eb3470db7691f4584004563c1b2f19eb0ad4 @dizzyd dizzyd committed Dec 7, 2011
Showing with 401 additions and 54 deletions.
  1. +334 −1 c_src/bitcask_nifs.c
  2. +33 −52 src/bitcask_fileops.erl
  3. +34 −1 src/bitcask_nifs.erl
View
335 c_src/bitcask_nifs.c
@@ -53,6 +53,13 @@ static ErlNifResourceType* bitcask_keydir_RESOURCE;
static ErlNifResourceType* bitcask_lock_RESOURCE;
+static ErlNifResourceType* bitcask_file_RESOURCE;
+
+typedef struct
+{
+ int fd;
+} bitcask_file_handle;
+
typedef struct
{
uint32_t file_id;
@@ -167,6 +174,7 @@ static ERL_NIF_TERM ATOM_PWRITE_ERROR;
static ERL_NIF_TERM ATOM_READY;
static ERL_NIF_TERM ATOM_SETFL_ERROR;
static ERL_NIF_TERM ATOM_TRUE;
+static ERL_NIF_TERM ATOM_EOF;
// Prototypes
ERL_NIF_TERM bitcask_nifs_keydir_new0(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -192,13 +200,23 @@ ERL_NIF_TERM bitcask_nifs_lock_release(ErlNifEnv* env, int argc, const ERL_NIF_T
ERL_NIF_TERM bitcask_nifs_lock_readdata(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
ERL_NIF_TERM bitcask_nifs_lock_writedata(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+ERL_NIF_TERM bitcask_nifs_file_open(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+ERL_NIF_TERM bitcask_nifs_file_close(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+ERL_NIF_TERM bitcask_nifs_file_sync(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+ERL_NIF_TERM bitcask_nifs_file_pread(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+ERL_NIF_TERM bitcask_nifs_file_pwrite(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+ERL_NIF_TERM bitcask_nifs_file_read(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+ERL_NIF_TERM bitcask_nifs_file_write(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+ERL_NIF_TERM bitcask_nifs_file_seekbof(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+
ERL_NIF_TERM errno_atom(ErlNifEnv* env, int error);
ERL_NIF_TERM errno_error_tuple(ErlNifEnv* env, ERL_NIF_TERM key, int error);
static void merge_pending_entries(ErlNifEnv* env, bitcask_keydir* keydir);
static void lock_release(bitcask_lock_handle* handle);
static void bitcask_nifs_keydir_resource_cleanup(ErlNifEnv* env, void* arg);
+static void bitcask_nifs_file_resource_cleanup(ErlNifEnv* env, void* arg);
static ErlNifFunc nif_funcs[] =
{
@@ -223,7 +241,16 @@ static ErlNifFunc nif_funcs[] =
{"lock_acquire", 2, bitcask_nifs_lock_acquire},
{"lock_release", 1, bitcask_nifs_lock_release},
{"lock_readdata", 1, bitcask_nifs_lock_readdata},
- {"lock_writedata", 2, bitcask_nifs_lock_writedata}
+ {"lock_writedata", 2, bitcask_nifs_lock_writedata},
+
+ {"file_open", 1, bitcask_nifs_file_open},
+ {"file_close", 1, bitcask_nifs_file_close},
+ {"file_sync", 1, bitcask_nifs_file_sync},
+ {"file_pread", 3, bitcask_nifs_file_pread},
+ {"file_pwrite", 3, bitcask_nifs_file_pwrite},
+ {"file_read", 2, bitcask_nifs_file_read},
+ {"file_write", 2, bitcask_nifs_file_write},
+ {"file_seekbof", 1, bitcask_nifs_file_seekbof}
};
ERL_NIF_TERM bitcask_nifs_keydir_new0(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -1281,6 +1308,295 @@ ERL_NIF_TERM bitcask_nifs_lock_writedata(ErlNifEnv* env, int argc, const ERL_NIF
}
}
+
+ERL_NIF_TERM bitcask_nifs_file_open(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+ char filename[4096];
+ if (enif_get_string(env, argv[0], filename, sizeof(filename), ERL_NIF_LATIN1) > 0)
+ {
+ // Try to open the provided filename exclusively.
+ int fd = open(filename, O_CREAT | O_RDWR, S_IREAD | S_IWRITE);
+ if (fd > -1)
+ {
+ // Setup a resource for our handle
+ bitcask_file_handle* handle = enif_alloc_resource_compat(env,
+ bitcask_file_RESOURCE,
+ sizeof(bitcask_file_handle));
+ memset(handle, '\0', sizeof(bitcask_file_handle));
+ handle->fd = fd;
+
+ ERL_NIF_TERM result = enif_make_resource(env, handle);
+ enif_release_resource_compat(env, handle);
+ return enif_make_tuple2(env, ATOM_OK, result);
+ }
+ else
+ {
+ ERL_NIF_TERM error = enif_make_tuple2(env, ATOM_ERROR,
+ enif_make_atom(env, erl_errno_id(errno)));
+ return enif_make_tuple2(env, ATOM_ERROR, error);
+ }
+ }
+ else
+ {
+ return enif_make_badarg(env);
+ }
+}
+
+ERL_NIF_TERM bitcask_nifs_file_close(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+ bitcask_file_handle* handle;
+ if (enif_get_resource(env, argv[0], bitcask_file_RESOURCE, (void**)&handle))
+ {
+ if (handle->fd > 0)
+ {
+ /* TODO: Check for EIO */
+ close(handle->fd);
+ handle->fd = -1;
+ }
+ return ATOM_OK;
+ }
+ else
+ {
+ return enif_make_badarg(env);
+ }
+}
+
+ERL_NIF_TERM bitcask_nifs_file_sync(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+ bitcask_file_handle* handle;
+ if (enif_get_resource(env, argv[0], bitcask_file_RESOURCE, (void**)&handle))
+ {
+ int rc = fsync(handle->fd);
+ if (rc != -1)
+ {
+ return ATOM_OK;
+ }
+ else
+ {
+ ERL_NIF_TERM error = enif_make_tuple2(env, ATOM_ERROR,
+ enif_make_atom(env, erl_errno_id(errno)));
+ return enif_make_tuple2(env, ATOM_ERROR, error);
+ }
+ }
+ else
+ {
+ return enif_make_badarg(env);
+ }
+}
+
+ERL_NIF_TERM bitcask_nifs_file_pread(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+ bitcask_file_handle* handle;
+ off_t offset;
+ size_t count;
+
+ if (enif_get_resource(env, argv[0], bitcask_file_RESOURCE, (void**)&handle) &&
+ enif_get_ulong(env, argv[1], (unsigned long*)&offset) && /* Offset */
+ enif_get_ulong(env, argv[2], (unsigned long*)&count)) /* Count */
+ {
+ ErlNifBinary bin;
+ if (!enif_alloc_binary(count, &bin))
+ {
+ return enif_make_tuple2(env, ATOM_ERROR, ATOM_ALLOCATION_ERROR);
+ }
+
+ ssize_t bytes_read = pread(handle->fd, bin.data, count, offset);
+ if (bytes_read == count)
+ {
+ /* Good read; return {ok, Bin} */
+ return enif_make_tuple2(env, ATOM_OK, enif_make_binary(env, &bin));
+ }
+ else if (bytes_read > 0)
+ {
+ /* Partial read; need to resize our binary (bleh) and return {ok, Bin} */
+ if (enif_realloc_binary(&bin, bytes_read))
+ {
+ return enif_make_tuple2(env, ATOM_OK, enif_make_binary(env, &bin));
+ }
+ else
+ {
+ /* Realloc failed; cleanup and bail */
+ enif_release_binary(&bin);
+ return enif_make_tuple2(env, ATOM_ERROR, ATOM_ALLOCATION_ERROR);
+ }
+ }
+ else if (bytes_read == 0)
+ {
+ /* EOF */
+ enif_release_binary(&bin);
+ return ATOM_EOF;
+ }
+ else
+ {
+ /* Read failed altogether */
+ ERL_NIF_TERM error = enif_make_tuple2(env, ATOM_ERROR,
+ enif_make_atom(env, erl_errno_id(errno)));
+ return enif_make_tuple2(env, ATOM_ERROR, error);
+ }
+ }
+ else
+ {
+ return enif_make_badarg(env);
+ }
+}
+
+ERL_NIF_TERM bitcask_nifs_file_pwrite(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+ bitcask_file_handle* handle;
+ off_t offset;
+ ErlNifBinary bin;
+
+ if (enif_get_resource(env, argv[0], bitcask_file_RESOURCE, (void**)&handle) &&
+ enif_get_ulong(env, argv[1], (unsigned long*)&offset) && /* Offset */
+ enif_inspect_iolist_as_binary(env, argv[2], &bin)) /* Bytes to write */
+ {
+ unsigned char* buf = bin.data;
+ ssize_t bytes_written = 0;
+ ssize_t count = bin.size;
+ while (count > 0)
+ {
+ bytes_written = pwrite(handle->fd, buf, count, offset);
+ if (bytes_written > 0)
+ {
+ count -= bytes_written;
+ offset += bytes_written;
+ buf += bytes_written;
+ }
+ else
+ {
+ /* Write failed altogether */
+ ERL_NIF_TERM error = enif_make_tuple2(env, ATOM_ERROR,
+ enif_make_atom(env, erl_errno_id(errno)));
+ return enif_make_tuple2(env, ATOM_ERROR, error);
+ }
+ }
+
+ /* Write done */
+ return ATOM_OK;
+ }
+ else
+ {
+ return enif_make_badarg(env);
+ }
+}
+
+ERL_NIF_TERM bitcask_nifs_file_read(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+ bitcask_file_handle* handle;
+ size_t count;
+
+ if (enif_get_resource(env, argv[0], bitcask_file_RESOURCE, (void**)&handle) &&
+ enif_get_ulong(env, argv[1], &count)) /* Count */
+ {
+ ErlNifBinary bin;
+ if (!enif_alloc_binary(count, &bin))
+ {
+ return enif_make_tuple2(env, ATOM_ERROR, ATOM_ALLOCATION_ERROR);
+ }
+
+ ssize_t bytes_read = read(handle->fd, bin.data, count);
+ if (bytes_read == count)
+ {
+ /* Good read; return {ok, Bin} */
+ return enif_make_tuple2(env, ATOM_OK, enif_make_binary(env, &bin));
+ }
+ else if (bytes_read > 0)
+ {
+ /* Partial read; need to resize our binary (bleh) and return {ok, Bin} */
+ if (enif_realloc_binary(&bin, bytes_read))
+ {
+ return enif_make_tuple2(env, ATOM_OK, enif_make_binary(env, &bin));
+ }
+ else
+ {
+ /* Realloc failed; cleanup and bail */
+ enif_release_binary(&bin);
+ return enif_make_tuple2(env, ATOM_ERROR, ATOM_ALLOCATION_ERROR);
+ }
+ }
+ else if (bytes_read == 0)
+ {
+ /* EOF */
+ enif_release_binary(&bin);
+ return ATOM_EOF;
+ }
+ else
+ {
+ /* Read failed altogether */
+ ERL_NIF_TERM error = enif_make_tuple2(env, ATOM_ERROR,
+ enif_make_atom(env, erl_errno_id(errno)));
+ return enif_make_tuple2(env, ATOM_ERROR, error);
+ }
+ }
+ else
+ {
+ return enif_make_badarg(env);
+ }
+}
+
+ERL_NIF_TERM bitcask_nifs_file_write(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+ bitcask_file_handle* handle;
+ off_t offset;
+ ErlNifBinary bin;
+
+ if (enif_get_resource(env, argv[0], bitcask_file_RESOURCE, (void**)&handle) &&
+ enif_inspect_iolist_as_binary(env, argv[1], &bin)) /* Bytes to write */
+ {
+ unsigned char* buf = bin.data;
+ ssize_t bytes_written = 0;
+ ssize_t count = bin.size;
+ while (count > 0)
+ {
+ bytes_written = write(handle->fd, buf, count);
+ if (bytes_written > 0)
+ {
+ count -= bytes_written;
+ buf += bytes_written;
+ }
+ else
+ {
+ /* Write failed altogether */
+ ERL_NIF_TERM error = enif_make_tuple2(env, ATOM_ERROR,
+ enif_make_atom(env, erl_errno_id(errno)));
+ return enif_make_tuple2(env, ATOM_ERROR, error);
+ }
+ }
+
+ /* Write done */
+ return ATOM_OK;
+ }
+ else
+ {
+ return enif_make_badarg(env);
+ }
+}
+
+ERL_NIF_TERM bitcask_nifs_file_seekbof(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+ bitcask_file_handle* handle;
+
+ if (enif_get_resource(env, argv[0], bitcask_file_RESOURCE, (void**)&handle))
+ {
+ if (lseek(handle->fd, 0, SEEK_SET) != -1)
+ {
+ return ATOM_OK;
+ }
+ else
+ {
+ /* Write failed altogether */
+ ERL_NIF_TERM error = enif_make_tuple2(env, ATOM_ERROR,
+ enif_make_atom(env, erl_errno_id(errno)));
+ return enif_make_tuple2(env, ATOM_ERROR, error);
+ }
+ }
+ else
+ {
+ return enif_make_badarg(env);
+ }
+}
+
+
ERL_NIF_TERM errno_atom(ErlNifEnv* env, int error)
{
return enif_make_atom(env, erl_errno_id(error));
@@ -1503,6 +1819,16 @@ static void bitcask_nifs_lock_resource_cleanup(ErlNifEnv* env, void* arg)
lock_release(handle);
}
+static void bitcask_nifs_file_resource_cleanup(ErlNifEnv* env, void* arg)
+{
+ bitcask_file_handle* handle = (bitcask_file_handle*)arg;
+ if (handle->fd > -1)
+ {
+ close(handle->fd);
+ }
+}
+
+
#ifdef BITCASK_DEBUG
static void dump_fstats(bitcask_keydir* keydir)
{
@@ -1535,6 +1861,12 @@ static int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
&bitcask_nifs_lock_resource_cleanup,
ERL_NIF_RT_CREATE | ERL_NIF_RT_TAKEOVER,
0);
+
+ bitcask_file_RESOURCE = enif_open_resource_type_compat(env, "bitcask_file_resource",
+ &bitcask_nifs_file_resource_cleanup,
+ ERL_NIF_RT_CREATE | ERL_NIF_RT_TAKEOVER,
+ 0);
+
// Initialize shared keydir hashtable
bitcask_priv_data* priv = enif_alloc_compat(env, sizeof(bitcask_priv_data));
priv->global_keydirs = kh_init(global_keydirs);
@@ -1564,6 +1896,7 @@ static int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
ATOM_READY = enif_make_atom(env, "ready");
ATOM_SETFL_ERROR = enif_make_atom(env, "setfl_error");
ATOM_TRUE = enif_make_atom(env, "true");
+ ATOM_EOF = enif_make_atom(env, "eof");
return 0;
}
View
85 src/bitcask_fileops.erl
@@ -71,7 +71,7 @@ create_file(DirName, Opts) ->
%% Called with fully-qualified filename.
-spec open_file(Filename :: string()) -> {ok, #filestate{}} | {error, any()}.
open_file(Filename) ->
- case file:open(Filename, [read, raw, binary, read_ahead]) of
+ case bitcask_nifs:file_open(Filename) of
{ok, FD} ->
{ok, #filestate{mode = read_only,
filename = Filename, tstamp = file_tstamp(Filename),
@@ -85,12 +85,12 @@ open_file(Filename) ->
close(fresh) -> ok;
close(undefined) -> ok;
close(#filestate{ fd = FD, hintfd = HintFd }) ->
- file:close(FD),
+ bitcask_nifs:file_close(FD),
case HintFd of
undefined ->
ok;
_ ->
- file:close(HintFd)
+ bitcask_nifs:file_close(HintFd)
end,
ok.
@@ -100,9 +100,9 @@ close_for_writing(fresh) -> ok;
close_for_writing(undefined) -> ok;
close_for_writing(State =
#filestate{ mode = read_write, fd = Fd, hintfd = HintFd }) ->
- file:sync(Fd),
- file:sync(HintFd),
- file:close(HintFd),
+ bitcask_nifs:file_sync(Fd),
+ bitcask_nifs:file_sync(HintFd),
+ bitcask_nifs:file_close(HintFd),
State#filestate { mode = read_only, hintfd = undefined }.
%% Build a list of {tstamp, filename} for all files in the directory that
@@ -145,11 +145,11 @@ write(Filestate=#filestate{fd = FD, hintfd = HintFD, ofs = Offset},
<<ValueSz:?VALSIZEFIELD>>, Key, Value],
Bytes = [<<(erlang:crc32(Bytes0)):?CRCSIZEFIELD>> | Bytes0],
%% Store the full entry in the data file
- ok = file:pwrite(FD, Offset, Bytes),
+ ok = bitcask_nifs:file_pwrite(FD, Offset, Bytes),
%% Create and store the corresponding hint entry
TotalSz = KeySz + ValueSz + ?HEADER_SIZE,
Iolist = hintfile_entry(Key, Tstamp, {Offset, TotalSz}),
- ok = file:write(HintFD, Iolist),
+ ok = bitcask_nifs:file_write(HintFD, Iolist),
%% Record our final offset
TotalSz = iolist_size(Bytes),
{ok, Filestate#filestate{ofs = Offset + TotalSz}, Offset, TotalSz}.
@@ -168,7 +168,7 @@ read(Filename, Offset, Size) when is_list(Filename) ->
{error, Reason}
end;
read(#filestate { fd = FD }, Offset, Size) ->
- case file:pread(FD, Offset, Size) of
+ case bitcask_nifs:file_pread(FD, Offset, Size) of
{ok, <<Crc32:?CRCSIZEFIELD/unsigned, Bytes/binary>>} ->
%% Unpack the actual data
<<_Tstamp:?TSTAMPFIELD, KeySz:?KEYSIZEFIELD, ValueSz:?VALSIZEFIELD,
@@ -190,8 +190,8 @@ read(#filestate { fd = FD }, Offset, Size) ->
%% @doc Call the OS's fsync(2) system call on the cask and hint files.
-spec sync(#filestate{}) -> ok.
sync(#filestate { mode = read_write, fd = Fd, hintfd = HintFd }) ->
- ok = file:sync(Fd),
- ok = file:sync(HintFd).
+ ok = bitcask_nifs:file_sync(Fd),
+ ok = bitcask_nifs:file_sync(HintFd).
-spec fold(fresh | #filestate{},
fun((binary(), binary(), integer(),
@@ -201,8 +201,9 @@ sync(#filestate { mode = read_write, fd = Fd, hintfd = HintFd }) ->
fold(fresh, _Fun, Acc) -> Acc;
fold(#filestate { fd=Fd, filename=Filename, tstamp=FTStamp }, Fun, Acc) ->
%% TODO: Add some sort of check that this is a read-only file
- {ok, _} = file:position(Fd, bof),
- case file:read(Fd, ?HEADER_SIZE) of
+ %% TODO: Need to position+read?!
+ ok = bitcask_nifs:file_seekbof(Fd),
+ case bitcask_nifs:file_read(Fd, ?HEADER_SIZE) of
{ok, <<_Crc:?CRCSIZEFIELD, _Tstamp:?TSTAMPFIELD, _KeySz:?KEYSIZEFIELD,
_ValueSz:?VALSIZEFIELD>> = H} ->
fold_loop(Fd, Filename, FTStamp, H, 0, Fun, Acc);
@@ -256,7 +257,7 @@ create_hintfile(Filename) when is_list(Filename) ->
create_hintfile(State) when is_record(State, filestate) ->
F = fun(K, Tstamp, {Offset, TotalSz}, HintFd) ->
Iolist = hintfile_entry(K, Tstamp, {Offset, TotalSz}),
- case file:write(HintFd, Iolist) of
+ case bitcask_nifs:file_write(HintFd, Iolist) of
ok ->
HintFd;
{error, Reason} ->
@@ -321,7 +322,7 @@ fold_loop(Fd, Filename, FTStamp, Header, Offset, Fun, Acc0) ->
ValueSz:?VALSIZEFIELD>> = Header,
<<_:4/binary, HeaderMinusCRC/binary>> = Header,
TotalSz = KeySz + ValueSz + ?HEADER_SIZE,
- case file:read(Fd, TotalSz) of
+ case bitcask_nifs:file_read(Fd, TotalSz) of
{ok, <<Key:KeySz/bytes, Value:ValueSz/bytes, Rest/binary>>} ->
case erlang:crc32([HeaderMinusCRC, Key, Value]) of
Crc32 ->
@@ -346,15 +347,15 @@ fold_loop(Fd, Filename, FTStamp, Header, Offset, Fun, Acc0) ->
end.
fold_keys_loop(Fd, Offset, Fun, Acc0) ->
- case file:pread(Fd, Offset, ?HEADER_SIZE) of
+ case bitcask_nifs:file_pread(Fd, Offset, ?HEADER_SIZE) of
{ok, Header} when erlang:size(Header) =:= ?HEADER_SIZE ->
<<_Crc32:?CRCSIZEFIELD, Tstamp:?TSTAMPFIELD, KeySz:?KEYSIZEFIELD,
ValueSz:?VALSIZEFIELD>> = Header,
TotalSz = KeySz + ValueSz + ?HEADER_SIZE,
PosInfo = {Offset, TotalSz},
%% NOTE: We are intentionally *not* reading the value blob,
%% so we cannot check the checksum.
- case file:pread(Fd, Offset + ?HEADER_SIZE, KeySz) of
+ case bitcask_nifs:file_pread(Fd, Offset + ?HEADER_SIZE, KeySz) of
{ok, Key} when erlang:size(Key) =:= KeySz ->
Acc = Fun(Key, Tstamp, PosInfo, Acc0),
fold_keys_loop(Fd, Offset + TotalSz, Fun, Acc);
@@ -377,13 +378,12 @@ fold_keys_loop(Fd, Offset, Fun, Acc0) ->
fold_hintfile(State, Fun, Acc) ->
- case file:open(hintfile_name(State), [read, raw, binary, read_ahead]) of
+ case bitcask_nifs:file_open(hintfile_name(State)) of
{ok, HintFd} ->
try
{ok, DataI} = file:read_file_info(State#filestate.filename),
DataSize = DataI#file_info.size,
- {ok, _} = file:position(HintFd, bof),
- case file:read(HintFd, ?HINT_RECORD_SZ) of
+ case bitcask_nifs:file_read(HintFd, ?HINT_RECORD_SZ) of
{ok, <<H:?HINT_RECORD_SZ/bytes>>} ->
fold_hintfile_loop(DataSize, hintfile_name(State),
HintFd, H, Fun, Acc);
@@ -400,7 +400,7 @@ fold_hintfile(State, Fun, Acc) ->
{error, {fold_hintfile, Reason}}
end
after
- file:close(HintFd)
+ bitcask_nifs:file_close(HintFd)
end;
{error, Reason} ->
{error, {fold_hintfile, Reason}}
@@ -410,7 +410,7 @@ fold_hintfile_loop(DataSize, HintFile, Fd, HintRecord, Fun, Acc0) ->
<<Tstamp:?TSTAMPFIELD, KeySz:?KEYSIZEFIELD,
TotalSz:?TOTALSIZEFIELD, Offset:?OFFSETFIELD>> = HintRecord,
ReadSz = KeySz + ?HINT_RECORD_SZ,
- case file:read(Fd, ReadSz) of
+ case bitcask_nifs:file_read(Fd, ReadSz) of
{ok, <<Key:KeySz/bytes, Rest/binary>>} when
Offset + TotalSz =< DataSize ->
PosInfo = {Offset, TotalSz},
@@ -441,34 +441,15 @@ create_file_loop(DirName, Opts, Tstamp) ->
ok = filelib:ensure_dir(Filename),
case bitcask_nifs:create_file(Filename) of
true ->
- {ok, FD} = file:open(Filename, [read, write, raw, binary, read_ahead]),
- {ok, HintFD} = file:open(hintfile_name(Filename),
- [read, write, raw, binary, read_ahead]),
- %% If o_sync is specified in the options, try to set that
- %% flag on the underlying file descriptor
- case bitcask:get_opt(sync_strategy, Opts) of
- o_sync ->
- %% Make a hacky assumption here that if we open a
- %% raw file, we get back a specific tuple from the
- %% Erlang VM. The tradeoff is that we can set the
- %% O_SYNC flag on the fd, thus improving
- %% performance rather dramatically.
- {file_descriptor, prim_file, {_Port, RealFd}} = FD,
- case bitcask_nifs:set_osync(RealFd) of
- ok ->
- {ok, #filestate{mode = read_write,
- filename = Filename,
- tstamp = file_tstamp(Filename),
- hintfd = HintFD, fd = FD, ofs = 0}};
- {error, Reason} ->
- {error, Reason}
- end;
- _ ->
- {ok, #filestate{mode = read_write,
- filename = Filename,
- tstamp = file_tstamp(Filename),
- hintfd = HintFD, fd = FD, ofs = 0}}
- end;
+ {ok, FD} = bitcask_nifs:file_open(Filename),
+ {ok, HintFD} = bitcask_nifs:file_open(hintfile_name(Filename)),
+
+ %% TODO: Reinstate O_SYNC support
+ {ok, #filestate{mode = read_write,
+ filename = Filename,
+ tstamp = file_tstamp(Filename),
+ hintfd = HintFD, fd = FD, ofs = 0}};
+
false ->
%% Couldn't create a new file with the requested name,
%% check for the more recent timestamp and increment by
@@ -487,7 +468,7 @@ create_file_loop(DirName, Opts, Tstamp) ->
generate_hintfile(Filename, {FolderMod, FolderFn, FolderArgs}) ->
%% Create the temp file that we will write records out to.
TmpFilename = temp_filename(Filename ++ ".~w"),
- {ok, Fd} = file:open(TmpFilename, [read, write, raw, binary, read_ahead]),
+ {ok, Fd} = bitcask_nifs:file_open(TmpFilename),
%% Run the provided fold function over whatever the dataset is. The function
%% is passed the Fd as the accumulator argument, and must return the same
@@ -500,7 +481,7 @@ generate_hintfile(Filename, {FolderMod, FolderFn, FolderArgs}) ->
{error, Reason}
after
file:delete(TmpFilename),
- file:close(Fd)
+ bitcask_nifs:file_close(Fd)
end.
hintfile_entry(Key, Tstamp, {Offset, TotalSz}) ->
View
35 src/bitcask_nifs.erl
@@ -40,7 +40,15 @@
lock_acquire/2,
lock_release/1,
lock_readdata/1,
- lock_writedata/2]).
+ lock_writedata/2,
+ file_open/1,
+ file_close/1,
+ file_sync/1,
+ file_pread/3,
+ file_pwrite/3,
+ file_read/2,
+ file_write/2,
+ file_seekbof/1]).
-on_load(init/0).
@@ -343,6 +351,31 @@ lock_writedata(_Ref, _Data) ->
_ -> exit("NIF library not loaded")
end.
+file_open(_Filename) ->
+ erlang:nif_error({error, not_loaded}).
+
+file_close(_Ref) ->
+ erlang:nif_error({error, not_loaded}).
+
+file_sync(_Ref) ->
+ erlang:nif_error({error, not_loaded}).
+
+file_pread(_Ref, _Offset, _Size) ->
+ erlang:nif_error({error, not_loaded}).
+
+file_pwrite(_Ref, _Offset, _Bytes) ->
+ erlang:nif_error({error, not_loaded}).
+
+file_read(_Ref, _Size) ->
+ erlang:nif_error({error, not_loaded}).
+
+file_write(_Ref, _Bytes) ->
+ erlang:nif_error({error, not_loaded}).
+
+file_seekbof(_Ref) ->
+ erlang:nif_error({error, not_loaded}).
+
+
%% ===================================================================
%% Internal functions
%% ===================================================================

0 comments on commit 79d5eb3

Please sign in to comment.
Something went wrong with that request. Please try again.