Renamed get_lg_dir() to get_lg_dir_info and added get_data_dirs_info().
Both new calls return the filesystem id and the number of mbytes available on that filesystem.
This commit is contained in:
parent
2c6277bdf4
commit
1409096860
6 changed files with 266 additions and 2 deletions
|
@ -9,12 +9,15 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <time.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/statvfs.h>
|
||||
|
||||
#include "hive_hash.h"
|
||||
#include "bdberl_drv.h"
|
||||
|
@ -40,7 +43,9 @@ static void do_async_log_stat(void* arg);
|
|||
static void do_async_memp_stat(void* arg);
|
||||
static void do_async_mutex_stat(void* arg);
|
||||
static void do_async_txn_stat(void* arg);
|
||||
static void do_sync_data_dirs_info(PortData *p);
|
||||
|
||||
static int send_dir_info(ErlDrvPort port, ErlDrvTermData pid, const char *path);
|
||||
static void send_rc(ErlDrvPort port, ErlDrvTermData pid, int rc);
|
||||
|
||||
static int add_dbref(PortData* data, int dbref);
|
||||
|
@ -1039,6 +1044,44 @@ static int bdberl_drv_control(ErlDrvData handle, unsigned int cmd,
|
|||
int rc = G_DB_ENV->txn_stat_print(G_DB_ENV, flags);
|
||||
RETURN_INT(rc, outbuf);
|
||||
}
|
||||
case CMD_DATA_DIRS_INFO:
|
||||
{
|
||||
FAIL_IF_ASYNC_PENDING(d, outbuf);
|
||||
|
||||
do_sync_data_dirs_info(d);
|
||||
|
||||
// Let caller know that the operation is in progress
|
||||
// Outbuf is: <<0:32>>
|
||||
RETURN_INT(0, outbuf);
|
||||
}
|
||||
|
||||
case CMD_LOG_DIR_INFO:
|
||||
{
|
||||
FAIL_IF_ASYNC_PENDING(d, outbuf);
|
||||
|
||||
// Find the log dir or use DB_HOME - error if not present
|
||||
const char *lg_dir = NULL;
|
||||
int rc = G_DB_ENV->get_lg_dir(G_DB_ENV, &lg_dir);
|
||||
if (0 == rc && NULL == lg_dir)
|
||||
{
|
||||
rc = G_DB_ENV->get_home(G_DB_ENV, &lg_dir);
|
||||
}
|
||||
// Send info if we can get a dir, otherwise return the error
|
||||
if (0 == rc)
|
||||
{
|
||||
// send a dirinfo message - will send an error message on a NULL lg_dir
|
||||
send_dir_info(d->port, d->port_owner, lg_dir);
|
||||
}
|
||||
else
|
||||
{
|
||||
send_rc(d->port, d->port_owner, rc);
|
||||
}
|
||||
|
||||
// Let caller know that the operation is in progress
|
||||
// Outbuf is: <<0:32>>
|
||||
RETURN_INT(0, outbuf);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
*outbuf = 0;
|
||||
|
@ -1271,6 +1314,21 @@ static void get_info(int target, void* values, BinHelper* bh)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case SYSP_LOG_DIR_GET:
|
||||
{
|
||||
const char* dir = 0;
|
||||
// Get the log dir - according to BDB docs, if not set
|
||||
// the DB_HOME is used.
|
||||
int rc = G_DB_ENV->get_lg_dir(G_DB_ENV, &dir);
|
||||
if (NULL == dir)
|
||||
{
|
||||
dir = getenv("DB_HOME");
|
||||
}
|
||||
bin_helper_init(bh);
|
||||
bin_helper_push_int32(bh, rc);
|
||||
bin_helper_push_string(bh, dir);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1328,6 +1386,53 @@ static char *rc_to_atom_str(int rc)
|
|||
}
|
||||
|
||||
|
||||
// Send a {dirinfo, Path, FsId, MbyteAvail} message to pid given.
|
||||
// Send an {errno, Reason} on failure
|
||||
// returns 0 on success, errno on failure
|
||||
static int send_dir_info(ErlDrvPort port, ErlDrvTermData pid, const char *path)
|
||||
{
|
||||
struct statvfs svfs;
|
||||
int rc;
|
||||
|
||||
if (NULL == path)
|
||||
{
|
||||
rc = EINVAL;
|
||||
}
|
||||
else if (0 != statvfs(path, &svfs))
|
||||
{
|
||||
rc = errno;
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
if (0 != rc)
|
||||
{
|
||||
send_rc(port, pid, rc);
|
||||
}
|
||||
else
|
||||
{
|
||||
fsblkcnt_t blocks_per_mbyte = 1024 * 1024 / svfs.f_frsize;
|
||||
assert(blocks_per_mbyte > 0);
|
||||
unsigned int mbyte_avail = (unsigned int) (svfs.f_bavail / blocks_per_mbyte);
|
||||
int path_len = strlen(path);
|
||||
|
||||
ErlDrvTermData response[] = { ERL_DRV_ATOM, driver_mk_atom("dirinfo"),
|
||||
ERL_DRV_STRING, (ErlDrvTermData) path, path_len,
|
||||
// send fsid as a binary as will only be used
|
||||
// to compare which physical filesystem is on
|
||||
// and the definintion varies between platforms.
|
||||
ERL_DRV_BUF2BINARY, (ErlDrvTermData) &svfs.f_fsid,
|
||||
sizeof(svfs.f_fsid),
|
||||
ERL_DRV_UINT, mbyte_avail,
|
||||
ERL_DRV_TUPLE, 4};
|
||||
driver_send_term(port, pid, response, sizeof(response) / sizeof(response[0]));
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static void send_rc(ErlDrvPort port, ErlDrvTermData pid, int rc)
|
||||
{
|
||||
// TODO: May need to tag the messages a bit more explicitly so that if another async
|
||||
|
@ -2334,6 +2439,71 @@ static void do_async_txn_stat(void* arg)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static void do_sync_data_dirs_info(PortData *d)
|
||||
{
|
||||
// Get DB_HOME and find the real path
|
||||
const char *db_home = NULL;
|
||||
const char *data_dir = NULL;
|
||||
const char **data_dirs = NULL;
|
||||
char db_home_realpath[PATH_MAX+1];
|
||||
char data_dir_realpath[PATH_MAX+1];
|
||||
int got_db_home = 0;
|
||||
|
||||
// Lookup the environment and add it if not explicitly included in the data_dirs
|
||||
int rc = G_DB_ENV->get_home(G_DB_ENV, &db_home);
|
||||
if (rc != 0 || NULL == db_home)
|
||||
{
|
||||
// If no db_home we'll have to rely on whatever the global environment is configured with
|
||||
got_db_home = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (NULL == realpath(db_home, db_home_realpath))
|
||||
rc = errno;
|
||||
}
|
||||
|
||||
// Get the data first
|
||||
rc = G_DB_ENV->get_data_dirs(G_DB_ENV, &data_dirs);
|
||||
int i;
|
||||
for (i = 0; 0 == rc && NULL != data_dirs && NULL != data_dirs[i]; i++)
|
||||
{
|
||||
data_dir = data_dirs[i];
|
||||
|
||||
if (!got_db_home)
|
||||
{
|
||||
// Get the real path of the data dir
|
||||
if (NULL == realpath(data_dir, data_dir_realpath))
|
||||
{
|
||||
rc = errno;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set got_db_home if it matches
|
||||
if (0 == strcmp(data_dir_realpath, db_home_realpath))
|
||||
{
|
||||
got_db_home = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (0 == rc)
|
||||
{
|
||||
rc = send_dir_info(d->port, d->port_owner, data_dir);
|
||||
}
|
||||
}
|
||||
|
||||
// BDB always searches the environment home too so add it to the list
|
||||
if (!got_db_home && rc == 0)
|
||||
{
|
||||
rc = send_dir_info(d->port, d->port_owner, db_home);
|
||||
}
|
||||
|
||||
// Send the return code - will termiante the receive loop in bdberl.erl
|
||||
send_rc(d->port, d->port_owner, rc);
|
||||
}
|
||||
|
||||
|
||||
static void* zalloc(unsigned int size)
|
||||
{
|
||||
void* res = driver_alloc(size);
|
||||
|
|
|
@ -59,6 +59,8 @@ static int bdberl_drv_control(ErlDrvData handle, unsigned int cmd,
|
|||
#define CMD_MUTEX_STAT_PRINT 28
|
||||
#define CMD_TXN_STAT 29
|
||||
#define CMD_TXN_STAT_PRINT 30
|
||||
#define CMD_DATA_DIRS_INFO 31
|
||||
#define CMD_LOG_DIR_INFO 32
|
||||
|
||||
/**
|
||||
* Command status values
|
||||
|
@ -96,6 +98,7 @@ static int bdberl_drv_control(ErlDrvData handle, unsigned int cmd,
|
|||
#define SYSP_CACHESIZE_GET 1
|
||||
#define SYSP_TXN_TIMEOUT_GET 2
|
||||
#define SYSP_DATA_DIR_GET 3
|
||||
#define SYSP_LOG_DIR_GET 4
|
||||
|
||||
/**
|
||||
* Driver Entry
|
||||
|
|
|
@ -44,6 +44,10 @@ void bin_helper_push_int32(BinHelper* bh, int value)
|
|||
|
||||
void bin_helper_push_string(BinHelper* bh, const char* string)
|
||||
{
|
||||
if (NULL == string)
|
||||
{
|
||||
string = "<null>";
|
||||
}
|
||||
int sz = strlen(string);
|
||||
bin_helper_check_size(bh, sz+1);
|
||||
strncpy(bh->bin->orig_bytes+(bh->offset), string, sz+1);
|
||||
|
|
|
@ -36,6 +36,8 @@
|
|||
-define(CMD_MUTEX_STAT_PRINT,28).
|
||||
-define(CMD_TXN_STAT, 29).
|
||||
-define(CMD_TXN_STAT_PRINT, 30).
|
||||
-define(CMD_DATA_DIRS_INFO, 31).
|
||||
-define(CMD_LOG_DIR_INFO, 32).
|
||||
|
||||
-define(DB_TYPE_BTREE, 1).
|
||||
-define(DB_TYPE_HASH, 2).
|
||||
|
@ -44,6 +46,7 @@
|
|||
-define(SYSP_CACHESIZE_GET, 1).
|
||||
-define(SYSP_TXN_TIMEOUT_GET, 2).
|
||||
-define(SYSP_DATA_DIR_GET, 3).
|
||||
-define(SYSP_LOG_DIR_GET, 4).
|
||||
|
||||
-define(STATUS_OK, 0).
|
||||
-define(STATUS_ERROR, 1).
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
txn_commit/0, txn_commit/1, txn_abort/0,
|
||||
get_cache_size/0,
|
||||
get_data_dirs/0,
|
||||
get_data_dirs_info/0,
|
||||
get_lg_dir_info/0,
|
||||
get_txn_timeout/0,
|
||||
stat/1, stat/2,
|
||||
stat_print/1, stat_print/2,
|
||||
|
@ -48,10 +50,11 @@
|
|||
-type db_name() :: [byte(),...].
|
||||
-type db_type() :: btree | hash.
|
||||
-type db_flags() :: [atom()].
|
||||
-type db_fsid() :: binary().
|
||||
-type db_key() :: term().
|
||||
-type db_mbytes() :: non_neg_integer().
|
||||
-type db_value() :: term().
|
||||
-type db_ret_value() :: not_found | db_value().
|
||||
|
||||
-type db_error_reason() :: atom() | {unknown, integer()}.
|
||||
-type db_error() :: {error, db_error_reason()}.
|
||||
|
||||
|
@ -1267,6 +1270,63 @@ get_data_dirs() ->
|
|||
end.
|
||||
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% @doc
|
||||
%% Returns the list of directories that bdberl searches to find databases
|
||||
%% with the number of megabytes available for each dir
|
||||
%%
|
||||
%% @spec get_data_dirs_info() -> {ok, [DirName, Fsid, MbytesAvail]} | {error, Error}
|
||||
%% where
|
||||
%% DirName = string()
|
||||
%% Fsid = binary()
|
||||
%% MbytesAvail = integer()
|
||||
%%
|
||||
%% @end
|
||||
%%--------------------------------------------------------------------
|
||||
-spec get_data_dirs_info() -> {ok, [{string(), db_fsid(), db_mbytes()}]} | db_error().
|
||||
|
||||
get_data_dirs_info() ->
|
||||
% Call into the BDB library and get a list of configured data directories
|
||||
Cmd = <<>>,
|
||||
<<Result:32/signed-native>> = erlang:port_control(get_port(),?CMD_DATA_DIRS_INFO, Cmd),
|
||||
case decode_rc(Result) of
|
||||
ok ->
|
||||
recv_dirs_info([]);
|
||||
Reason ->
|
||||
{error, Reason}
|
||||
end.
|
||||
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% @doc
|
||||
%% Returns the log directory info (name and megabytes available)
|
||||
%%
|
||||
%% @spec get_lg_dir_info() -> {ok, DirName, Fsid, MbytesAvail} | {error, Error}
|
||||
%% where
|
||||
%% DirName = string()
|
||||
%% Fsid = binary()
|
||||
%% MbytesAvail = integer()
|
||||
%%
|
||||
%% @end
|
||||
%%--------------------------------------------------------------------
|
||||
-spec get_lg_dir_info() -> {ok, string(), db_fsid(), db_mbytes()} | db_error().
|
||||
get_lg_dir_info() ->
|
||||
% Call into the BDB library and get the log dir and filesystem info
|
||||
Cmd = <<>>,
|
||||
<<Result:32/signed-native>> = erlang:port_control(get_port(), ?CMD_LOG_DIR_INFO, Cmd),
|
||||
case decode_rc(Result) of
|
||||
ok ->
|
||||
receive
|
||||
{dirinfo, Path, FsId, MbytesAvail} ->
|
||||
{ok, Path, FsId, MbytesAvail};
|
||||
{error, Reason} ->
|
||||
{error, Reason}
|
||||
end;
|
||||
Reason ->
|
||||
{error, Reason}
|
||||
end.
|
||||
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% @doc
|
||||
%% Returns the size of the in-memory cache.
|
||||
|
@ -2196,3 +2256,17 @@ recv_txn_stat(Tstats) ->
|
|||
{ok, Stats} ->
|
||||
{ok, Stats, Tstats}
|
||||
end.
|
||||
|
||||
%%
|
||||
%% Receive directory info messages until ok
|
||||
%%
|
||||
recv_dirs_info(DirInfos) ->
|
||||
receive
|
||||
{dirinfo, Path, FsId, MbytesAvail} ->
|
||||
recv_dirs_info([{Path, FsId, MbytesAvail} | DirInfos]);
|
||||
{error, Reason} ->
|
||||
{error, Reason};
|
||||
ok ->
|
||||
{ok, DirInfos}
|
||||
end.
|
||||
|
||||
|
|
|
@ -39,7 +39,10 @@ all() ->
|
|||
log_stat_should_report_on_success,
|
||||
memp_stat_should_report_on_success,
|
||||
mutex_stat_should_report_on_success,
|
||||
txn_stat_should_report_on_success].
|
||||
txn_stat_should_report_on_success,
|
||||
data_dirs_info_should_report_on_success,
|
||||
lg_dir_info_should_report_on_success].
|
||||
|
||||
|
||||
|
||||
dbconfig(Config) ->
|
||||
|
@ -312,3 +315,10 @@ txn_stat_should_report_on_success(_Config) ->
|
|||
bdberl:txn_abort(),
|
||||
{ok, _GStat3, []} = bdberl:txn_stat([]),
|
||||
done.
|
||||
|
||||
data_dirs_info_should_report_on_success(_Config) ->
|
||||
{ok, _DataDirs} = bdberl:get_data_dirs_info().
|
||||
|
||||
lg_dir_info_should_report_on_success(_Config) ->
|
||||
{ok, _LgDir, _Fsid, _MBytesAvail} = bdberl:get_lg_dir_info().
|
||||
|
||||
|
|
Loading…
Reference in a new issue