Land part 2 of clang-format changes
Change-Id: Ia84cc24c8924e6d22d02ac15f611c10e26db99b4 Signed-off-by: Nigel Babu <nigelb@redhat.com>
This commit is contained in:
parent
45a71c0548
commit
e16868dede
File diff suppressed because it is too large
Load Diff
7788
api/src/glfs-fops.c
7788
api/src/glfs-fops.c
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -22,166 +22,153 @@
|
||||
#include "glfs-mem-types.h"
|
||||
#include "gfapi-messages.h"
|
||||
|
||||
|
||||
int
|
||||
graph_setup (struct glfs *fs, glusterfs_graph_t *graph)
|
||||
graph_setup(struct glfs *fs, glusterfs_graph_t *graph)
|
||||
{
|
||||
xlator_t *new_subvol = NULL;
|
||||
xlator_t *old_subvol = NULL;
|
||||
inode_table_t *itable = NULL;
|
||||
int ret = -1;
|
||||
xlator_t *new_subvol = NULL;
|
||||
xlator_t *old_subvol = NULL;
|
||||
inode_table_t *itable = NULL;
|
||||
int ret = -1;
|
||||
|
||||
new_subvol = graph->top;
|
||||
new_subvol = graph->top;
|
||||
|
||||
/* This is called in a bottom-up context, it should specifically
|
||||
NOT be glfs_lock()
|
||||
*/
|
||||
pthread_mutex_lock (&fs->mutex);
|
||||
{
|
||||
if (new_subvol->switched ||
|
||||
new_subvol == fs->active_subvol ||
|
||||
new_subvol == fs->next_subvol ||
|
||||
new_subvol == fs->mip_subvol) {
|
||||
/* Spurious CHILD_UP event on old graph */
|
||||
ret = 0;
|
||||
goto unlock;
|
||||
}
|
||||
/* This is called in a bottom-up context, it should specifically
|
||||
NOT be glfs_lock()
|
||||
*/
|
||||
pthread_mutex_lock(&fs->mutex);
|
||||
{
|
||||
if (new_subvol->switched || new_subvol == fs->active_subvol ||
|
||||
new_subvol == fs->next_subvol || new_subvol == fs->mip_subvol) {
|
||||
/* Spurious CHILD_UP event on old graph */
|
||||
ret = 0;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (!new_subvol->itable) {
|
||||
itable = inode_table_new (131072, new_subvol);
|
||||
if (!itable) {
|
||||
errno = ENOMEM;
|
||||
ret = -1;
|
||||
goto unlock;
|
||||
}
|
||||
if (!new_subvol->itable) {
|
||||
itable = inode_table_new(131072, new_subvol);
|
||||
if (!itable) {
|
||||
errno = ENOMEM;
|
||||
ret = -1;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
new_subvol->itable = itable;
|
||||
}
|
||||
new_subvol->itable = itable;
|
||||
}
|
||||
|
||||
old_subvol = fs->next_subvol;
|
||||
fs->next_subvol = new_subvol;
|
||||
fs->next_subvol->winds++; /* first ref */
|
||||
ret = 0;
|
||||
}
|
||||
old_subvol = fs->next_subvol;
|
||||
fs->next_subvol = new_subvol;
|
||||
fs->next_subvol->winds++; /* first ref */
|
||||
ret = 0;
|
||||
}
|
||||
unlock:
|
||||
pthread_mutex_unlock (&fs->mutex);
|
||||
pthread_mutex_unlock(&fs->mutex);
|
||||
|
||||
if (old_subvol)
|
||||
/* wasn't picked up so far, skip */
|
||||
glfs_subvol_done (fs, old_subvol);
|
||||
if (old_subvol)
|
||||
/* wasn't picked up so far, skip */
|
||||
glfs_subvol_done(fs, old_subvol);
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
notify (xlator_t *this, int event, void *data, ...)
|
||||
notify(xlator_t *this, int event, void *data, ...)
|
||||
{
|
||||
glusterfs_graph_t *graph = NULL;
|
||||
struct glfs *fs = NULL;
|
||||
glusterfs_graph_t *graph = NULL;
|
||||
struct glfs *fs = NULL;
|
||||
|
||||
graph = data;
|
||||
fs = this->private;
|
||||
graph = data;
|
||||
fs = this->private;
|
||||
|
||||
switch (event) {
|
||||
case GF_EVENT_GRAPH_NEW:
|
||||
gf_msg (this->name, GF_LOG_INFO, 0, API_MSG_NEW_GRAPH,
|
||||
"New graph %s (%d) coming up",
|
||||
uuid_utoa ((unsigned char *)graph->graph_uuid),
|
||||
graph->id);
|
||||
break;
|
||||
case GF_EVENT_CHILD_UP:
|
||||
pthread_mutex_lock (&fs->mutex);
|
||||
{
|
||||
graph->used = 1;
|
||||
}
|
||||
pthread_mutex_unlock (&fs->mutex);
|
||||
graph_setup (fs, graph);
|
||||
glfs_init_done (fs, 0);
|
||||
break;
|
||||
case GF_EVENT_CHILD_DOWN:
|
||||
pthread_mutex_lock (&fs->mutex);
|
||||
{
|
||||
graph->used = 0;
|
||||
pthread_cond_broadcast (&fs->child_down_cond);
|
||||
}
|
||||
pthread_mutex_unlock (&fs->mutex);
|
||||
glfs_init_done (fs, 1);
|
||||
break;
|
||||
case GF_EVENT_CHILD_CONNECTING:
|
||||
break;
|
||||
switch (event) {
|
||||
case GF_EVENT_GRAPH_NEW:
|
||||
gf_msg(this->name, GF_LOG_INFO, 0, API_MSG_NEW_GRAPH,
|
||||
"New graph %s (%d) coming up",
|
||||
uuid_utoa((unsigned char *)graph->graph_uuid), graph->id);
|
||||
break;
|
||||
case GF_EVENT_CHILD_UP:
|
||||
pthread_mutex_lock(&fs->mutex);
|
||||
{
|
||||
graph->used = 1;
|
||||
}
|
||||
pthread_mutex_unlock(&fs->mutex);
|
||||
graph_setup(fs, graph);
|
||||
glfs_init_done(fs, 0);
|
||||
break;
|
||||
case GF_EVENT_CHILD_DOWN:
|
||||
pthread_mutex_lock(&fs->mutex);
|
||||
{
|
||||
graph->used = 0;
|
||||
pthread_cond_broadcast(&fs->child_down_cond);
|
||||
}
|
||||
pthread_mutex_unlock(&fs->mutex);
|
||||
glfs_init_done(fs, 1);
|
||||
break;
|
||||
case GF_EVENT_CHILD_CONNECTING:
|
||||
break;
|
||||
case GF_EVENT_UPCALL:
|
||||
glfs_process_upcall_event (fs, data);
|
||||
break;
|
||||
default:
|
||||
gf_msg_debug (this->name, 0, "got notify event %d", event);
|
||||
break;
|
||||
}
|
||||
glfs_process_upcall_event(fs, data);
|
||||
break;
|
||||
default:
|
||||
gf_msg_debug(this->name, 0, "got notify event %d", event);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
mem_acct_init (xlator_t *this)
|
||||
mem_acct_init(xlator_t *this)
|
||||
{
|
||||
int ret = -1;
|
||||
int ret = -1;
|
||||
|
||||
if (!this)
|
||||
return ret;
|
||||
if (!this)
|
||||
return ret;
|
||||
|
||||
ret = xlator_mem_acct_init (this, glfs_mt_end + 1);
|
||||
if (ret) {
|
||||
gf_msg (this->name, GF_LOG_ERROR, ENOMEM,
|
||||
API_MSG_MEM_ACCT_INIT_FAILED, "Failed to initialise "
|
||||
"memory accounting");
|
||||
return ret;
|
||||
}
|
||||
ret = xlator_mem_acct_init(this, glfs_mt_end + 1);
|
||||
if (ret) {
|
||||
gf_msg(this->name, GF_LOG_ERROR, ENOMEM, API_MSG_MEM_ACCT_INIT_FAILED,
|
||||
"Failed to initialise "
|
||||
"memory accounting");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
init (xlator_t *this)
|
||||
init(xlator_t *this)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
fini (xlator_t *this)
|
||||
fini(xlator_t *this)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/* place-holder fops */
|
||||
int
|
||||
glfs_forget (xlator_t *this, inode_t *inode)
|
||||
glfs_forget(xlator_t *this, inode_t *inode)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
glfs_release (xlator_t *this, fd_t *fd)
|
||||
glfs_release(xlator_t *this, fd_t *fd)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
glfs_releasedir (xlator_t *this, fd_t *fd)
|
||||
glfs_releasedir(xlator_t *this, fd_t *fd)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct xlator_dumpops dumpops;
|
||||
|
||||
|
||||
struct xlator_fops fops;
|
||||
|
||||
|
||||
struct xlator_cbks cbks = {
|
||||
.forget = glfs_forget,
|
||||
.release = glfs_release,
|
||||
.releasedir = glfs_releasedir
|
||||
};
|
||||
struct xlator_cbks cbks = {.forget = glfs_forget,
|
||||
.release = glfs_release,
|
||||
.releasedir = glfs_releasedir};
|
||||
|
1626
api/src/glfs-mgmt.c
1626
api/src/glfs-mgmt.c
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
2242
api/src/glfs.c
2242
api/src/glfs.c
File diff suppressed because it is too large
Load Diff
@ -30,111 +30,109 @@
|
||||
extern rpc_clnt_prog_t *cli_rpc_prog;
|
||||
|
||||
int
|
||||
cli_cmd_global_help_cbk (struct cli_state *state, struct cli_cmd_word *in_word,
|
||||
const char **words, int wordcount);
|
||||
cli_cmd_global_help_cbk(struct cli_state *state, struct cli_cmd_word *in_word,
|
||||
const char **words, int wordcount);
|
||||
int
|
||||
cli_cmd_get_state_cbk (struct cli_state *state, struct cli_cmd_word *word,
|
||||
const char **words, int wordcount);
|
||||
cli_cmd_get_state_cbk(struct cli_state *state, struct cli_cmd_word *word,
|
||||
const char **words, int wordcount);
|
||||
|
||||
struct cli_cmd global_cmds[] = {
|
||||
{ "global help",
|
||||
cli_cmd_global_help_cbk,
|
||||
"list global commands",
|
||||
},
|
||||
{ "get-state [<daemon>] [[odir </path/to/output/dir/>] "
|
||||
"[file <filename>]] [detail|volumeoptions]",
|
||||
cli_cmd_get_state_cbk,
|
||||
"Get local state representation of mentioned daemon",
|
||||
},
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
{
|
||||
"global help",
|
||||
cli_cmd_global_help_cbk,
|
||||
"list global commands",
|
||||
},
|
||||
{
|
||||
"get-state [<daemon>] [[odir </path/to/output/dir/>] "
|
||||
"[file <filename>]] [detail|volumeoptions]",
|
||||
cli_cmd_get_state_cbk,
|
||||
"Get local state representation of mentioned daemon",
|
||||
},
|
||||
{NULL, NULL, NULL}};
|
||||
|
||||
int
|
||||
cli_cmd_global_help_cbk (struct cli_state *state, struct cli_cmd_word *in_word,
|
||||
cli_cmd_global_help_cbk(struct cli_state *state, struct cli_cmd_word *in_word,
|
||||
const char **words, int wordcount)
|
||||
{
|
||||
struct cli_cmd *cmd = NULL;
|
||||
struct cli_cmd *global_cmd = NULL;
|
||||
int count = 0;
|
||||
|
||||
cmd = GF_MALLOC(sizeof(global_cmds), cli_mt_cli_cmd);
|
||||
memcpy(cmd, global_cmds, sizeof(global_cmds));
|
||||
count = (sizeof(global_cmds) / sizeof(struct cli_cmd));
|
||||
cli_cmd_sort(cmd, count);
|
||||
|
||||
cli_out("\ngluster global commands");
|
||||
cli_out("========================\n");
|
||||
for (global_cmd = cmd; global_cmd->pattern; global_cmd++)
|
||||
if (_gf_false == global_cmd->disable)
|
||||
cli_out("%s - %s", global_cmd->pattern, global_cmd->desc);
|
||||
|
||||
cli_out("\n");
|
||||
GF_FREE(cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
cli_cmd_global_register(struct cli_state *state)
|
||||
{
|
||||
int ret = 0;
|
||||
struct cli_cmd *cmd = NULL;
|
||||
for (cmd = global_cmds; cmd->pattern; cmd++) {
|
||||
ret = cli_cmd_register(&state->tree, cmd);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
cli_cmd_get_state_cbk(struct cli_state *state, struct cli_cmd_word *word,
|
||||
const char **words, int wordcount)
|
||||
{
|
||||
struct cli_cmd *cmd = NULL;
|
||||
struct cli_cmd *global_cmd = NULL;
|
||||
int count = 0;
|
||||
int sent = 0;
|
||||
int parse_error = 0;
|
||||
int ret = -1;
|
||||
rpc_clnt_procedure_t *proc = NULL;
|
||||
call_frame_t *frame = NULL;
|
||||
dict_t *options = NULL;
|
||||
cli_local_t *local = NULL;
|
||||
char *op_errstr = NULL;
|
||||
|
||||
cmd = GF_MALLOC (sizeof (global_cmds), cli_mt_cli_cmd);
|
||||
memcpy (cmd, global_cmds, sizeof (global_cmds));
|
||||
count = (sizeof (global_cmds) / sizeof (struct cli_cmd));
|
||||
cli_cmd_sort (cmd, count);
|
||||
frame = create_frame(THIS, THIS->ctx->pool);
|
||||
if (!frame)
|
||||
goto out;
|
||||
|
||||
cli_out ("\ngluster global commands");
|
||||
cli_out ("========================\n");
|
||||
for (global_cmd = cmd; global_cmd->pattern; global_cmd++)
|
||||
if (_gf_false == global_cmd->disable)
|
||||
cli_out ("%s - %s", global_cmd->pattern,
|
||||
global_cmd->desc);
|
||||
ret = cli_cmd_get_state_parse(state, words, wordcount, &options,
|
||||
&op_errstr);
|
||||
|
||||
cli_out ("\n");
|
||||
GF_FREE (cmd);
|
||||
return 0;
|
||||
}
|
||||
if (ret) {
|
||||
if (op_errstr) {
|
||||
cli_err("%s", op_errstr);
|
||||
cli_usage_out(word->pattern);
|
||||
GF_FREE(op_errstr);
|
||||
} else
|
||||
cli_usage_out(word->pattern);
|
||||
|
||||
int
|
||||
cli_cmd_global_register (struct cli_state *state)
|
||||
{
|
||||
int ret = 0;
|
||||
struct cli_cmd *cmd = NULL;
|
||||
for (cmd = global_cmds; cmd->pattern; cmd++) {
|
||||
ret = cli_cmd_register (&state->tree, cmd);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
parse_error = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
CLI_LOCAL_INIT(local, words, frame, options);
|
||||
|
||||
proc = &cli_rpc_prog->proctable[GLUSTER_CLI_GET_STATE];
|
||||
if (proc->fn)
|
||||
ret = proc->fn(frame, THIS, options);
|
||||
out:
|
||||
return ret;
|
||||
if (ret) {
|
||||
cli_cmd_sent_status_get(&sent);
|
||||
if ((sent == 0) && (parse_error == 0))
|
||||
cli_out("Getting daemon state failed");
|
||||
}
|
||||
|
||||
CLI_STACK_DESTROY(frame);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
cli_cmd_get_state_cbk (struct cli_state *state, struct cli_cmd_word *word,
|
||||
const char **words, int wordcount)
|
||||
{
|
||||
int sent = 0;
|
||||
int parse_error = 0;
|
||||
int ret = -1;
|
||||
rpc_clnt_procedure_t *proc = NULL;
|
||||
call_frame_t *frame = NULL;
|
||||
dict_t *options = NULL;
|
||||
cli_local_t *local = NULL;
|
||||
char *op_errstr = NULL;
|
||||
|
||||
frame = create_frame (THIS, THIS->ctx->pool);
|
||||
if (!frame)
|
||||
goto out;
|
||||
|
||||
ret = cli_cmd_get_state_parse (state, words, wordcount, &options,
|
||||
&op_errstr);
|
||||
|
||||
if (ret) {
|
||||
if (op_errstr) {
|
||||
cli_err ("%s", op_errstr);
|
||||
cli_usage_out (word->pattern);
|
||||
GF_FREE (op_errstr);
|
||||
} else
|
||||
cli_usage_out (word->pattern);
|
||||
|
||||
parse_error = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
CLI_LOCAL_INIT (local, words, frame, options);
|
||||
|
||||
proc = &cli_rpc_prog->proctable[GLUSTER_CLI_GET_STATE];
|
||||
if (proc->fn)
|
||||
ret = proc->fn (frame, THIS, options);
|
||||
out:
|
||||
if (ret) {
|
||||
cli_cmd_sent_status_get (&sent);
|
||||
if ((sent == 0) && (parse_error == 0))
|
||||
cli_out ("Getting daemon state failed");
|
||||
}
|
||||
|
||||
CLI_STACK_DESTROY (frame);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -35,107 +35,98 @@ extern struct cli_cmd global_cmds[];
|
||||
struct cli_cmd cli_misc_cmds[];
|
||||
|
||||
int
|
||||
cli_cmd_quit_cbk (struct cli_state *state, struct cli_cmd_word *word,
|
||||
const char **words, int wordcount)
|
||||
cli_cmd_quit_cbk(struct cli_state *state, struct cli_cmd_word *word,
|
||||
const char **words, int wordcount)
|
||||
{
|
||||
exit (0);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
static gf_boolean_t
|
||||
cli_is_help_command (const char *pattern)
|
||||
cli_is_help_command(const char *pattern)
|
||||
{
|
||||
/* FixFixFix
|
||||
* This is not the best way to determine whether
|
||||
* this is a help command
|
||||
*/
|
||||
if (strstr (pattern, "help"))
|
||||
return _gf_true;
|
||||
/* FixFixFix
|
||||
* This is not the best way to determine whether
|
||||
* this is a help command
|
||||
*/
|
||||
if (strstr(pattern, "help"))
|
||||
return _gf_true;
|
||||
|
||||
return _gf_false;
|
||||
return _gf_false;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cli_cmd_display_help (struct cli_state *state, struct cli_cmd_word *in_word,
|
||||
const char **words, int wordcount)
|
||||
cli_cmd_display_help(struct cli_state *state, struct cli_cmd_word *in_word,
|
||||
const char **words, int wordcount)
|
||||
{
|
||||
struct cli_cmd *cmd[] = {cli_misc_cmds, cli_probe_cmds,
|
||||
volume_cmds, bitrot_cmds, quota_cmds,
|
||||
struct cli_cmd *cmd[] = {
|
||||
cli_misc_cmds,
|
||||
cli_probe_cmds,
|
||||
volume_cmds,
|
||||
bitrot_cmds,
|
||||
quota_cmds,
|
||||
#if !defined(__NetBSD__)
|
||||
tier_cmds,
|
||||
tier_cmds,
|
||||
#endif
|
||||
snapshot_cmds, global_cmds, NULL};
|
||||
struct cli_cmd *cmd_ind = NULL;
|
||||
int i = 0;
|
||||
gf_boolean_t list_all = _gf_false;
|
||||
snapshot_cmds,
|
||||
global_cmds,
|
||||
NULL
|
||||
};
|
||||
struct cli_cmd *cmd_ind = NULL;
|
||||
int i = 0;
|
||||
gf_boolean_t list_all = _gf_false;
|
||||
|
||||
/* cli_system_cmds commands for internal usage
|
||||
they are not exposed
|
||||
*/
|
||||
/* cli_system_cmds commands for internal usage
|
||||
they are not exposed
|
||||
*/
|
||||
|
||||
/* If "help all" */
|
||||
if (wordcount == 2)
|
||||
list_all = _gf_true;
|
||||
/* If "help all" */
|
||||
if (wordcount == 2)
|
||||
list_all = _gf_true;
|
||||
|
||||
for (i = 0; cmd[i] != NULL; i++) {
|
||||
for (cmd_ind = cmd[i]; cmd_ind->pattern; cmd_ind++) {
|
||||
if ((_gf_false == cmd_ind->disable) &&
|
||||
cli_is_help_command (cmd_ind->pattern)) {
|
||||
if (list_all && (cmd_ind->cbk)) {
|
||||
cmd_ind->cbk (state, in_word, words,
|
||||
wordcount);
|
||||
} else {
|
||||
cli_out (" %-25s- %s", cmd_ind->pattern,
|
||||
cmd_ind->desc);
|
||||
}
|
||||
}
|
||||
for (i = 0; cmd[i] != NULL; i++) {
|
||||
for (cmd_ind = cmd[i]; cmd_ind->pattern; cmd_ind++) {
|
||||
if ((_gf_false == cmd_ind->disable) &&
|
||||
cli_is_help_command(cmd_ind->pattern)) {
|
||||
if (list_all && (cmd_ind->cbk)) {
|
||||
cmd_ind->cbk(state, in_word, words, wordcount);
|
||||
} else {
|
||||
cli_out(" %-25s- %s", cmd_ind->pattern, cmd_ind->desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cli_out ("\n");
|
||||
return 0;
|
||||
cli_out("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct cli_cmd cli_help_cmds[] = {
|
||||
{ "help [all]",
|
||||
cli_cmd_display_help,
|
||||
"display help for command classes"},
|
||||
{"help [all]", cli_cmd_display_help, "display help for command classes"},
|
||||
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
{NULL, NULL, NULL}};
|
||||
|
||||
struct cli_cmd cli_misc_cmds[] = {{"quit", cli_cmd_quit_cbk, "quit"},
|
||||
{"exit", cli_cmd_quit_cbk, "exit"},
|
||||
|
||||
struct cli_cmd cli_misc_cmds[] = {
|
||||
{ "quit",
|
||||
cli_cmd_quit_cbk,
|
||||
"quit"},
|
||||
{ "exit",
|
||||
cli_cmd_quit_cbk,
|
||||
"exit"},
|
||||
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
{NULL, NULL, NULL}};
|
||||
|
||||
int
|
||||
cli_cmd_misc_register (struct cli_state *state)
|
||||
cli_cmd_misc_register(struct cli_state *state)
|
||||
{
|
||||
int ret = 0;
|
||||
struct cli_cmd *cmd = NULL;
|
||||
int ret = 0;
|
||||
struct cli_cmd *cmd = NULL;
|
||||
|
||||
for (cmd = cli_misc_cmds; cmd->pattern; cmd++) {
|
||||
ret = cli_cmd_register (&state->tree, cmd);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
for (cmd = cli_misc_cmds; cmd->pattern; cmd++) {
|
||||
ret = cli_cmd_register(&state->tree, cmd);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (cmd = cli_help_cmds; cmd->pattern; cmd++) {
|
||||
ret = cli_cmd_register (&state->tree, cmd);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
for (cmd = cli_help_cmds; cmd->pattern; cmd++) {
|
||||
ret = cli_cmd_register(&state->tree, cmd);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
10043
cli/src/cli-cmd-parser.c
10043
cli/src/cli-cmd-parser.c
File diff suppressed because it is too large
Load Diff
@ -24,292 +24,282 @@ extern struct rpc_clnt *global_rpc;
|
||||
|
||||
extern rpc_clnt_prog_t *cli_rpc_prog;
|
||||
|
||||
int cli_cmd_peer_help_cbk (struct cli_state *state, struct cli_cmd_word *in_word,
|
||||
int
|
||||
cli_cmd_peer_help_cbk(struct cli_state *state, struct cli_cmd_word *in_word,
|
||||
const char **words, int wordcount);
|
||||
|
||||
int
|
||||
cli_cmd_peer_probe_cbk (struct cli_state *state, struct cli_cmd_word *word,
|
||||
const char **words, int wordcount)
|
||||
{
|
||||
int ret = -1;
|
||||
rpc_clnt_procedure_t *proc = NULL;
|
||||
call_frame_t *frame = NULL;
|
||||
dict_t *dict = NULL;
|
||||
int sent = 0;
|
||||
int parse_error = 0;
|
||||
cli_local_t *local = NULL;
|
||||
|
||||
if (!(wordcount == 3)) {
|
||||
cli_usage_out (word->pattern);
|
||||
parse_error = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
proc = &cli_rpc_prog->proctable[GLUSTER_CLI_PROBE];
|
||||
|
||||
frame = create_frame (THIS, THIS->ctx->pool);
|
||||
if (!frame)
|
||||
goto out;
|
||||
|
||||
dict = dict_new ();
|
||||
if (!dict)
|
||||
goto out;
|
||||
|
||||
ret = dict_set_str (dict, "hostname", (char *)words[2]);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = valid_internet_address ((char *) words[2], _gf_false);
|
||||
if (ret == 1) {
|
||||
ret = 0;
|
||||
} else {
|
||||
cli_out ("%s is an invalid address", words[2]);
|
||||
cli_usage_out (word->pattern);
|
||||
parse_error = 1;
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
/* if (words[3]) {
|
||||
ret = dict_set_str (dict, "port", (char *)words[3]);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
*/
|
||||
|
||||
CLI_LOCAL_INIT (local, words, frame, dict);
|
||||
|
||||
if (proc->fn) {
|
||||
ret = proc->fn (frame, THIS, dict);
|
||||
}
|
||||
|
||||
out:
|
||||
if (ret) {
|
||||
cli_cmd_sent_status_get (&sent);
|
||||
if ((sent == 0) && (parse_error == 0))
|
||||
cli_out ("Peer probe failed");
|
||||
}
|
||||
|
||||
CLI_STACK_DESTROY (frame);
|
||||
|
||||
if (ret == 0) {
|
||||
gf_event (EVENT_PEER_ATTACH, "host=%s", (char *)words[2]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cli_cmd_peer_deprobe_cbk (struct cli_state *state, struct cli_cmd_word *word,
|
||||
const char **words, int wordcount)
|
||||
{
|
||||
int ret = -1;
|
||||
rpc_clnt_procedure_t *proc = NULL;
|
||||
call_frame_t *frame = NULL;
|
||||
dict_t *dict = NULL;
|
||||
int flags = 0;
|
||||
int sent = 0;
|
||||
int parse_error = 0;
|
||||
cli_local_t *local = NULL;
|
||||
|
||||
if ((wordcount < 3) || (wordcount > 4)) {
|
||||
cli_usage_out (word->pattern);
|
||||
parse_error = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
proc = &cli_rpc_prog->proctable[GLUSTER_CLI_DEPROBE];
|
||||
|
||||
frame = create_frame (THIS, THIS->ctx->pool);
|
||||
if (!frame)
|
||||
goto out;
|
||||
|
||||
dict = dict_new ();
|
||||
|
||||
ret = dict_set_str (dict, "hostname", (char *)words[2]);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* if (words[3]) {
|
||||
ret = dict_set_str (dict, "port", (char *)words[3]);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
*/
|
||||
if (wordcount == 4) {
|
||||
if (!strcmp("force", words[3]))
|
||||
flags |= GF_CLI_FLAG_OP_FORCE;
|
||||
else {
|
||||
ret = -1;
|
||||
cli_usage_out (word->pattern);
|
||||
parse_error = 1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
ret = dict_set_int32 (dict, "flags", flags);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
CLI_LOCAL_INIT (local, words, frame, dict);
|
||||
|
||||
if (proc->fn) {
|
||||
ret = proc->fn (frame, THIS, dict);
|
||||
}
|
||||
|
||||
out:
|
||||
if (ret) {
|
||||
cli_cmd_sent_status_get (&sent);
|
||||
if ((sent == 0) && (parse_error == 0))
|
||||
cli_out ("Peer detach failed");
|
||||
}
|
||||
|
||||
CLI_STACK_DESTROY (frame);
|
||||
|
||||
if (ret == 0) {
|
||||
gf_event (EVENT_PEER_DETACH, "host=%s", (char *)words[2]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
cli_cmd_peer_status_cbk (struct cli_state *state, struct cli_cmd_word *word,
|
||||
const char **words, int wordcount)
|
||||
{
|
||||
int ret = -1;
|
||||
rpc_clnt_procedure_t *proc = NULL;
|
||||
call_frame_t *frame = NULL;
|
||||
int sent = 0;
|
||||
int parse_error = 0;
|
||||
|
||||
if (wordcount != 2) {
|
||||
cli_usage_out (word->pattern);
|
||||
parse_error = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
proc = &cli_rpc_prog->proctable[GLUSTER_CLI_LIST_FRIENDS];
|
||||
|
||||
frame = create_frame (THIS, THIS->ctx->pool);
|
||||
if (!frame)
|
||||
goto out;
|
||||
|
||||
if (proc->fn) {
|
||||
ret = proc->fn (frame, THIS, (void *)GF_CLI_LIST_PEERS);
|
||||
}
|
||||
|
||||
out:
|
||||
if (ret) {
|
||||
cli_cmd_sent_status_get (&sent);
|
||||
if ((sent == 0) && (parse_error == 0))
|
||||
cli_out ("Peer status failed");
|
||||
}
|
||||
|
||||
CLI_STACK_DESTROY (frame);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
cli_cmd_pool_list_cbk (struct cli_state *state, struct cli_cmd_word *word,
|
||||
cli_cmd_peer_probe_cbk(struct cli_state *state, struct cli_cmd_word *word,
|
||||
const char **words, int wordcount)
|
||||
{
|
||||
int ret = -1;
|
||||
rpc_clnt_procedure_t *proc = NULL;
|
||||
call_frame_t *frame = NULL;
|
||||
int sent = 0;
|
||||
int parse_error = 0;
|
||||
int ret = -1;
|
||||
rpc_clnt_procedure_t *proc = NULL;
|
||||
call_frame_t *frame = NULL;
|
||||
dict_t *dict = NULL;
|
||||
int sent = 0;
|
||||
int parse_error = 0;
|
||||
cli_local_t *local = NULL;
|
||||
|
||||
if (wordcount != 2) {
|
||||
cli_usage_out (word->pattern);
|
||||
parse_error = 1;
|
||||
goto out;
|
||||
}
|
||||
if (!(wordcount == 3)) {
|
||||
cli_usage_out(word->pattern);
|
||||
parse_error = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
proc = &cli_rpc_prog->proctable[GLUSTER_CLI_LIST_FRIENDS];
|
||||
proc = &cli_rpc_prog->proctable[GLUSTER_CLI_PROBE];
|
||||
|
||||
frame = create_frame (THIS, THIS->ctx->pool);
|
||||
if (!frame)
|
||||
goto out;
|
||||
frame = create_frame(THIS, THIS->ctx->pool);
|
||||
if (!frame)
|
||||
goto out;
|
||||
|
||||
if (proc->fn) {
|
||||
ret = proc->fn (frame, THIS,
|
||||
(void *)GF_CLI_LIST_POOL_NODES);
|
||||
}
|
||||
dict = dict_new();
|
||||
if (!dict)
|
||||
goto out;
|
||||
|
||||
ret = dict_set_str(dict, "hostname", (char *)words[2]);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = valid_internet_address((char *)words[2], _gf_false);
|
||||
if (ret == 1) {
|
||||
ret = 0;
|
||||
} else {
|
||||
cli_out("%s is an invalid address", words[2]);
|
||||
cli_usage_out(word->pattern);
|
||||
parse_error = 1;
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
/* if (words[3]) {
|
||||
ret = dict_set_str (dict, "port", (char *)words[3]);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
*/
|
||||
|
||||
CLI_LOCAL_INIT(local, words, frame, dict);
|
||||
|
||||
if (proc->fn) {
|
||||
ret = proc->fn(frame, THIS, dict);
|
||||
}
|
||||
|
||||
out:
|
||||
if (ret) {
|
||||
cli_cmd_sent_status_get (&sent);
|
||||
if ((sent == 0) && (parse_error == 0))
|
||||
cli_err ("pool list: command execution failed");
|
||||
if (ret) {
|
||||
cli_cmd_sent_status_get(&sent);
|
||||
if ((sent == 0) && (parse_error == 0))
|
||||
cli_out("Peer probe failed");
|
||||
}
|
||||
|
||||
CLI_STACK_DESTROY(frame);
|
||||
|
||||
if (ret == 0) {
|
||||
gf_event(EVENT_PEER_ATTACH, "host=%s", (char *)words[2]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
cli_cmd_peer_deprobe_cbk(struct cli_state *state, struct cli_cmd_word *word,
|
||||
const char **words, int wordcount)
|
||||
{
|
||||
int ret = -1;
|
||||
rpc_clnt_procedure_t *proc = NULL;
|
||||
call_frame_t *frame = NULL;
|
||||
dict_t *dict = NULL;
|
||||
int flags = 0;
|
||||
int sent = 0;
|
||||
int parse_error = 0;
|
||||
cli_local_t *local = NULL;
|
||||
|
||||
if ((wordcount < 3) || (wordcount > 4)) {
|
||||
cli_usage_out(word->pattern);
|
||||
parse_error = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
proc = &cli_rpc_prog->proctable[GLUSTER_CLI_DEPROBE];
|
||||
|
||||
frame = create_frame(THIS, THIS->ctx->pool);
|
||||
if (!frame)
|
||||
goto out;
|
||||
|
||||
dict = dict_new();
|
||||
|
||||
ret = dict_set_str(dict, "hostname", (char *)words[2]);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* if (words[3]) {
|
||||
ret = dict_set_str (dict, "port", (char *)words[3]);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
*/
|
||||
if (wordcount == 4) {
|
||||
if (!strcmp("force", words[3]))
|
||||
flags |= GF_CLI_FLAG_OP_FORCE;
|
||||
else {
|
||||
ret = -1;
|
||||
cli_usage_out(word->pattern);
|
||||
parse_error = 1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
ret = dict_set_int32(dict, "flags", flags);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
CLI_STACK_DESTROY (frame);
|
||||
CLI_LOCAL_INIT(local, words, frame, dict);
|
||||
|
||||
return ret;
|
||||
if (proc->fn) {
|
||||
ret = proc->fn(frame, THIS, dict);
|
||||
}
|
||||
|
||||
out:
|
||||
if (ret) {
|
||||
cli_cmd_sent_status_get(&sent);
|
||||
if ((sent == 0) && (parse_error == 0))
|
||||
cli_out("Peer detach failed");
|
||||
}
|
||||
|
||||
CLI_STACK_DESTROY(frame);
|
||||
|
||||
if (ret == 0) {
|
||||
gf_event(EVENT_PEER_DETACH, "host=%s", (char *)words[2]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
cli_cmd_peer_status_cbk(struct cli_state *state, struct cli_cmd_word *word,
|
||||
const char **words, int wordcount)
|
||||
{
|
||||
int ret = -1;
|
||||
rpc_clnt_procedure_t *proc = NULL;
|
||||
call_frame_t *frame = NULL;
|
||||
int sent = 0;
|
||||
int parse_error = 0;
|
||||
|
||||
if (wordcount != 2) {
|
||||
cli_usage_out(word->pattern);
|
||||
parse_error = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
proc = &cli_rpc_prog->proctable[GLUSTER_CLI_LIST_FRIENDS];
|
||||
|
||||
frame = create_frame(THIS, THIS->ctx->pool);
|
||||
if (!frame)
|
||||
goto out;
|
||||
|
||||
if (proc->fn) {
|
||||
ret = proc->fn(frame, THIS, (void *)GF_CLI_LIST_PEERS);
|
||||
}
|
||||
|
||||
out:
|
||||
if (ret) {
|
||||
cli_cmd_sent_status_get(&sent);
|
||||
if ((sent == 0) && (parse_error == 0))
|
||||
cli_out("Peer status failed");
|
||||
}
|
||||
|
||||
CLI_STACK_DESTROY(frame);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
cli_cmd_pool_list_cbk(struct cli_state *state, struct cli_cmd_word *word,
|
||||
const char **words, int wordcount)
|
||||
{
|
||||
int ret = -1;
|
||||
rpc_clnt_procedure_t *proc = NULL;
|
||||
call_frame_t *frame = NULL;
|
||||
int sent = 0;
|
||||
int parse_error = 0;
|
||||
|
||||
if (wordcount != 2) {
|
||||
cli_usage_out(word->pattern);
|
||||
parse_error = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
proc = &cli_rpc_prog->proctable[GLUSTER_CLI_LIST_FRIENDS];
|
||||
|
||||
frame = create_frame(THIS, THIS->ctx->pool);
|
||||
if (!frame)
|
||||
goto out;
|
||||
|
||||
if (proc->fn) {
|
||||
ret = proc->fn(frame, THIS, (void *)GF_CLI_LIST_POOL_NODES);
|
||||
}
|
||||
|
||||
out:
|
||||
if (ret) {
|
||||
cli_cmd_sent_status_get(&sent);
|
||||
if ((sent == 0) && (parse_error == 0))
|
||||
cli_err("pool list: command execution failed");
|
||||
}
|
||||
|
||||
CLI_STACK_DESTROY(frame);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct cli_cmd cli_probe_cmds[] = {
|
||||
{ "peer probe { <HOSTNAME> | <IP-address> }",
|
||||
cli_cmd_peer_probe_cbk,
|
||||
"probe peer specified by <HOSTNAME>"},
|
||||
{"peer probe { <HOSTNAME> | <IP-address> }", cli_cmd_peer_probe_cbk,
|
||||
"probe peer specified by <HOSTNAME>"},
|
||||
|
||||
{ "peer detach { <HOSTNAME> | <IP-address> } [force]",
|
||||
cli_cmd_peer_deprobe_cbk,
|
||||
"detach peer specified by <HOSTNAME>"},
|
||||
{"peer detach { <HOSTNAME> | <IP-address> } [force]",
|
||||
cli_cmd_peer_deprobe_cbk, "detach peer specified by <HOSTNAME>"},
|
||||
|
||||
{ "peer status",
|
||||
cli_cmd_peer_status_cbk,
|
||||
"list status of peers"},
|
||||
{"peer status", cli_cmd_peer_status_cbk, "list status of peers"},
|
||||
|
||||
{ "peer help",
|
||||
cli_cmd_peer_help_cbk,
|
||||
"display help for peer commands"},
|
||||
{"peer help", cli_cmd_peer_help_cbk, "display help for peer commands"},
|
||||
|
||||
{ "pool list",
|
||||
cli_cmd_pool_list_cbk,
|
||||
"list all the nodes in the pool (including localhost)"},
|
||||
{"pool list", cli_cmd_pool_list_cbk,
|
||||
"list all the nodes in the pool (including localhost)"},
|
||||
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
{NULL, NULL, NULL}};
|
||||
|
||||
int
|
||||
cli_cmd_peer_help_cbk (struct cli_state *state, struct cli_cmd_word *in_word,
|
||||
cli_cmd_peer_help_cbk(struct cli_state *state, struct cli_cmd_word *in_word,
|
||||
const char **words, int wordcount)
|
||||
{
|
||||
struct cli_cmd *cmd = NULL;
|
||||
struct cli_cmd *probe_cmd = NULL;
|
||||
int count = 0;
|
||||
struct cli_cmd *cmd = NULL;
|
||||
struct cli_cmd *probe_cmd = NULL;
|
||||
int count = 0;
|
||||
|
||||
cli_out ("\ngluster peer commands");
|
||||
cli_out ("======================\n");
|
||||
cli_out("\ngluster peer commands");
|
||||
cli_out("======================\n");
|
||||
|
||||
cmd = GF_MALLOC (sizeof (cli_probe_cmds), cli_mt_cli_cmd);
|
||||
memcpy (cmd, cli_probe_cmds, sizeof (cli_probe_cmds));
|
||||
count = (sizeof (cli_probe_cmds) / sizeof (struct cli_cmd));
|
||||
cli_cmd_sort (cmd, count);
|
||||
cmd = GF_MALLOC(sizeof(cli_probe_cmds), cli_mt_cli_cmd);
|
||||
memcpy(cmd, cli_probe_cmds, sizeof(cli_probe_cmds));
|
||||
count = (sizeof(cli_probe_cmds) / sizeof(struct cli_cmd));
|
||||
cli_cmd_sort(cmd, count);
|
||||
|
||||
for (probe_cmd = cmd; probe_cmd->pattern; probe_cmd++)
|
||||
cli_out ("%s - %s", probe_cmd->pattern, probe_cmd->desc);
|
||||
for (probe_cmd = cmd; probe_cmd->pattern; probe_cmd++)
|
||||
cli_out("%s - %s", probe_cmd->pattern, probe_cmd->desc);
|
||||
|
||||
GF_FREE (cmd);
|
||||
GF_FREE(cmd);
|
||||
|
||||
cli_out ("\n");
|
||||
return 0;
|
||||
cli_out("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
cli_cmd_probe_register (struct cli_state *state)
|
||||
cli_cmd_probe_register(struct cli_state *state)
|
||||
{
|
||||
int ret = 0;
|
||||
struct cli_cmd *cmd = NULL;
|
||||
int ret = 0;
|
||||
struct cli_cmd *cmd = NULL;
|
||||
|
||||
for (cmd = cli_probe_cmds; cmd->pattern; cmd++) {
|
||||
|
||||
ret = cli_cmd_register (&state->tree, cmd);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
for (cmd = cli_probe_cmds; cmd->pattern; cmd++) {
|
||||
ret = cli_cmd_register(&state->tree, cmd);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
@ -20,146 +20,118 @@
|
||||
extern rpc_clnt_prog_t *cli_rpc_prog;
|
||||
|
||||
int
|
||||
cli_cmd_snapshot_help_cbk (struct cli_state *state, struct cli_cmd_word *in_word,
|
||||
const char **words, int wordcount);
|
||||
cli_cmd_snapshot_help_cbk(struct cli_state *state, struct cli_cmd_word *in_word,
|
||||
const char **words, int wordcount);
|
||||
|
||||
int
|
||||
cli_cmd_snapshot_cbk (struct cli_state *state, struct cli_cmd_word *word,
|
||||
const char **words, int wordcount)
|
||||
cli_cmd_snapshot_cbk(struct cli_state *state, struct cli_cmd_word *word,
|
||||
const char **words, int wordcount)
|
||||
{
|
||||
int ret = 0;
|
||||
int parse_err = 0;
|
||||
dict_t *options = NULL;
|
||||
rpc_clnt_procedure_t *proc = NULL;
|
||||
call_frame_t *frame = NULL;
|
||||
cli_local_t *local = NULL;
|
||||
int ret = 0;
|
||||
int parse_err = 0;
|
||||
dict_t *options = NULL;
|
||||
rpc_clnt_procedure_t *proc = NULL;
|
||||
call_frame_t *frame = NULL;
|
||||
cli_local_t *local = NULL;
|
||||
|
||||
proc = &cli_rpc_prog->proctable [GLUSTER_CLI_SNAP];
|
||||
proc = &cli_rpc_prog->proctable[GLUSTER_CLI_SNAP];
|
||||
|
||||
frame = create_frame (THIS, THIS->ctx->pool);
|
||||
if (frame == NULL) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
frame = create_frame(THIS, THIS->ctx->pool);
|
||||
if (frame == NULL) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Parses the command entered by the user */
|
||||
ret = cli_cmd_snapshot_parse(words, wordcount, &options, state);
|
||||
if (ret) {
|
||||
if (ret < 0) {
|
||||
cli_usage_out(word->pattern);
|
||||
parse_err = 1;
|
||||
} else {
|
||||
/* User might have cancelled the snapshot operation */
|
||||
ret = 0;
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Parses the command entered by the user */
|
||||
ret = cli_cmd_snapshot_parse (words, wordcount, &options, state);
|
||||
if (ret) {
|
||||
if (ret < 0) {
|
||||
cli_usage_out (word->pattern);
|
||||
parse_err = 1;
|
||||
} else {
|
||||
/* User might have cancelled the snapshot operation */
|
||||
ret = 0;
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
CLI_LOCAL_INIT(local, words, frame, options);
|
||||
|
||||
CLI_LOCAL_INIT (local, words, frame, options);
|
||||
|
||||
if (proc->fn)
|
||||
ret = proc->fn (frame, THIS, options);
|
||||
if (proc->fn)
|
||||
ret = proc->fn(frame, THIS, options);
|
||||
|
||||
out:
|
||||
if (ret && parse_err == 0)
|
||||
cli_out ("Snapshot command failed");
|
||||
if (ret && parse_err == 0)
|
||||
cli_out("Snapshot command failed");
|
||||
|
||||
CLI_STACK_DESTROY (frame);
|
||||
CLI_STACK_DESTROY(frame);
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct cli_cmd snapshot_cmds[] = {
|
||||
{ "snapshot help",
|
||||
cli_cmd_snapshot_help_cbk,
|
||||
"display help for snapshot commands"
|
||||
},
|
||||
{ "snapshot create <snapname> <volname> [no-timestamp] "
|
||||
"[description <description>] [force]",
|
||||
cli_cmd_snapshot_cbk,
|
||||
"Snapshot Create."
|
||||
},
|
||||
{ "snapshot clone <clonename> <snapname>",
|
||||
cli_cmd_snapshot_cbk,
|
||||
"Snapshot Clone."
|
||||
},
|
||||
{ "snapshot restore <snapname>",
|
||||
cli_cmd_snapshot_cbk,
|
||||
"Snapshot Restore."
|
||||
},
|
||||
{ "snapshot status [(snapname | volume <volname>)]",
|
||||
cli_cmd_snapshot_cbk,
|
||||
"Snapshot Status."
|
||||
},
|
||||
{ "snapshot info [(snapname | volume <volname>)]",
|
||||
cli_cmd_snapshot_cbk,
|
||||
"Snapshot Info."
|
||||
},
|
||||
{ "snapshot list [volname]",
|
||||
cli_cmd_snapshot_cbk,
|
||||
"Snapshot List."
|
||||
},
|
||||
{"snapshot config [volname] ([snap-max-hard-limit <count>] "
|
||||
"[snap-max-soft-limit <percent>]) "
|
||||
"| ([auto-delete <enable|disable>])"
|
||||
"| ([activate-on-create <enable|disable>])",
|
||||
cli_cmd_snapshot_cbk,
|
||||
"Snapshot Config."
|
||||
},
|
||||
{"snapshot delete (all | snapname | volume <volname>)",
|
||||
cli_cmd_snapshot_cbk,
|
||||
"Snapshot Delete."
|
||||
},
|
||||
{"snapshot activate <snapname> [force]",
|
||||
cli_cmd_snapshot_cbk,
|
||||
"Activate snapshot volume."
|
||||
},
|
||||
{"snapshot deactivate <snapname>",
|
||||
cli_cmd_snapshot_cbk,
|
||||
"Deactivate snapshot volume."
|
||||
},
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
{"snapshot help", cli_cmd_snapshot_help_cbk,
|
||||
"display help for snapshot commands"},
|
||||
{"snapshot create <snapname> <volname> [no-timestamp] "
|
||||
"[description <description>] [force]",
|
||||
cli_cmd_snapshot_cbk, "Snapshot Create."},
|
||||
{"snapshot clone <clonename> <snapname>", cli_cmd_snapshot_cbk,
|
||||
"Snapshot Clone."},
|
||||
{"snapshot restore <snapname>", cli_cmd_snapshot_cbk, "Snapshot Restore."},
|
||||
{"snapshot status [(snapname | volume <volname>)]", cli_cmd_snapshot_cbk,
|
||||
"Snapshot Status."},
|
||||
{"snapshot info [(snapname | volume <volname>)]", cli_cmd_snapshot_cbk,
|
||||
"Snapshot Info."},
|
||||
{"snapshot list [volname]", cli_cmd_snapshot_cbk, "Snapshot List."},
|
||||
{"snapshot config [volname] ([snap-max-hard-limit <count>] "
|
||||
"[snap-max-soft-limit <percent>]) "
|
||||
"| ([auto-delete <enable|disable>])"
|
||||
"| ([activate-on-create <enable|disable>])",
|
||||
cli_cmd_snapshot_cbk, "Snapshot Config."},
|
||||
{"snapshot delete (all | snapname | volume <volname>)",
|
||||
cli_cmd_snapshot_cbk, "Snapshot Delete."},
|
||||
{"snapshot activate <snapname> [force]", cli_cmd_snapshot_cbk,
|
||||
"Activate snapshot volume."},
|
||||
{"snapshot deactivate <snapname>", cli_cmd_snapshot_cbk,
|
||||
"Deactivate snapshot volume."},
|
||||
{NULL, NULL, NULL}};
|
||||
|
||||
int
|
||||
cli_cmd_snapshot_help_cbk (struct cli_state *state,
|
||||
struct cli_cmd_word *in_word,
|
||||
const char **words,
|
||||
int wordcount)
|
||||
cli_cmd_snapshot_help_cbk(struct cli_state *state, struct cli_cmd_word *in_word,
|
||||
const char **words, int wordcount)
|
||||
{
|
||||
struct cli_cmd *cmd = NULL;
|
||||
struct cli_cmd *snap_cmd = NULL;
|
||||
int count = 0;
|
||||
struct cli_cmd *cmd = NULL;
|
||||
struct cli_cmd *snap_cmd = NULL;
|
||||
int count = 0;
|
||||
|
||||
cmd = GF_MALLOC (sizeof (snapshot_cmds), cli_mt_cli_cmd);
|
||||
memcpy (cmd, snapshot_cmds, sizeof (snapshot_cmds));
|
||||
count = (sizeof (snapshot_cmds) / sizeof (struct cli_cmd));
|
||||
cli_cmd_sort (cmd, count);
|
||||
cmd = GF_MALLOC(sizeof(snapshot_cmds), cli_mt_cli_cmd);
|
||||
memcpy(cmd, snapshot_cmds, sizeof(snapshot_cmds));
|
||||
count = (sizeof(snapshot_cmds) / sizeof(struct cli_cmd));
|
||||
cli_cmd_sort(cmd, count);
|
||||
|
||||
cli_out ("\ngluster snapshot commands");
|
||||
cli_out ("=========================\n");
|
||||
cli_out("\ngluster snapshot commands");
|
||||
cli_out("=========================\n");
|
||||
|
||||
for (snap_cmd = cmd; snap_cmd->pattern; snap_cmd++)
|
||||
if (_gf_false == snap_cmd->disable)
|
||||
cli_out ("%s - %s", snap_cmd->pattern, snap_cmd->desc);
|
||||
cli_out ("\n");
|
||||
for (snap_cmd = cmd; snap_cmd->pattern; snap_cmd++)
|
||||
if (_gf_false == snap_cmd->disable)
|
||||
cli_out("%s - %s", snap_cmd->pattern, snap_cmd->desc);
|
||||
cli_out("\n");
|
||||
|
||||
GF_FREE (cmd);
|
||||
return 0;
|
||||
GF_FREE(cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
cli_cmd_snapshot_register (struct cli_state *state)
|
||||
cli_cmd_snapshot_register(struct cli_state *state)
|
||||
{
|
||||
int ret = 0;
|
||||
struct cli_cmd *cmd = NULL;
|
||||
int ret = 0;
|
||||
struct cli_cmd *cmd = NULL;
|
||||
|
||||
for (cmd = snapshot_cmds; cmd->pattern; cmd++) {
|
||||
|
||||
ret = cli_cmd_register (&state->tree, cmd);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
for (cmd = snapshot_cmds; cmd->pattern; cmd++) {
|
||||
ret = cli_cmd_register(&state->tree, cmd);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -22,395 +22,390 @@
|
||||
|
||||
static int cmd_done;
|
||||
static int cmd_sent;
|
||||
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
|
||||
static pthread_mutex_t cond_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_cond_t conn = PTHREAD_COND_INITIALIZER;
|
||||
static pthread_mutex_t conn_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
|
||||
static pthread_mutex_t cond_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_cond_t conn = PTHREAD_COND_INITIALIZER;
|
||||
static pthread_mutex_t conn_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
int cli_op_ret = 0;
|
||||
int connected = 0;
|
||||
int cli_op_ret = 0;
|
||||
int connected = 0;
|
||||
|
||||
int cli_cmd_log_help_cbk (struct cli_state *state, struct cli_cmd_word *in_word,
|
||||
const char **words, int wordcount);
|
||||
int
|
||||
cli_cmd_log_help_cbk(struct cli_state *state, struct cli_cmd_word *in_word,
|
||||
const char **words, int wordcount);
|
||||
|
||||
static unsigned
|
||||
cli_cmd_needs_connection (struct cli_cmd_word *word)
|
||||
cli_cmd_needs_connection(struct cli_cmd_word *word)
|
||||
{
|
||||
if (!strcasecmp ("quit", word->word))
|
||||
return 0;
|
||||
if (!strcasecmp("quit", word->word))
|
||||
return 0;
|
||||
|
||||
if (!strcasecmp ("help", word->word))
|
||||
return 0;
|
||||
if (!strcasecmp("help", word->word))
|
||||
return 0;
|
||||
|
||||
if (!strcasecmp ("getwd", word->word))
|
||||
return 1;
|
||||
if (!strcasecmp("getwd", word->word))
|
||||
return 1;
|
||||
|
||||
if (!strcasecmp ("exit", word->word))
|
||||
return 0;
|
||||
if (!strcasecmp("exit", word->word))
|
||||
return 0;
|
||||
|
||||
return cli_default_conn_timeout;
|
||||
return cli_default_conn_timeout;
|
||||
}
|
||||
|
||||
int
|
||||
cli_cmd_status_reset (void)
|
||||
cli_cmd_status_reset(void)
|
||||
{
|
||||
int ret = 0;
|
||||
int ret = 0;
|
||||
|
||||
ret = cli_cmd_lock ();
|
||||
{
|
||||
if (ret == 0) {
|
||||
cmd_sent = 0;
|
||||
cmd_done = 0;
|
||||
}
|
||||
ret = cli_cmd_lock();
|
||||
{
|
||||
if (ret == 0) {
|
||||
cmd_sent = 0;
|
||||
cmd_done = 0;
|
||||
}
|
||||
ret = cli_cmd_unlock ();
|
||||
return ret;
|
||||
|
||||
}
|
||||
ret = cli_cmd_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
cli_cmd_sent_status_get (int *status)
|
||||
cli_cmd_sent_status_get(int *status)
|
||||
{
|
||||
int ret = 0;
|
||||
GF_ASSERT (status);
|
||||
int ret = 0;
|
||||
GF_ASSERT(status);
|
||||
|
||||
ret = cli_cmd_lock ();
|
||||
{
|
||||
if (ret == 0)
|
||||
*status = cmd_sent;
|
||||
}
|
||||
ret = cli_cmd_unlock ();
|
||||
return ret;
|
||||
ret = cli_cmd_lock();
|
||||
{
|
||||
if (ret == 0)
|
||||
*status = cmd_sent;
|
||||
}
|
||||
ret = cli_cmd_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
cli_cmd_process (struct cli_state *state, int argc, char **argv)
|
||||
cli_cmd_process(struct cli_state *state, int argc, char **argv)
|
||||
{
|
||||
int ret = 0;
|
||||
struct cli_cmd_word *word = NULL;
|
||||
struct cli_cmd_word *next = NULL;
|
||||
int i = 0;
|
||||
int ret = 0;
|
||||
struct cli_cmd_word *word = NULL;
|
||||
struct cli_cmd_word *next = NULL;
|
||||
int i = 0;
|
||||
|
||||
word = &state->tree.root;
|
||||
word = &state->tree.root;
|
||||
|
||||
if (!argc)
|
||||
return 0;
|
||||
if (!argc)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
next = cli_cmd_nextword (word, argv[i]);
|
||||
for (i = 0; i < argc; i++) {
|
||||
next = cli_cmd_nextword(word, argv[i]);
|
||||
|
||||
word = next;
|
||||
if (!word)
|
||||
break;
|
||||
word = next;
|
||||
if (!word)
|
||||
break;
|
||||
|
||||
if (word->cbkfn)
|
||||
break;
|
||||
}
|
||||
if (word->cbkfn)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!word) {
|
||||
cli_out ("unrecognized word: %s (position %d)",
|
||||
argv[i], i);
|
||||
return -1;
|
||||
}
|
||||
if (!word) {
|
||||
cli_out("unrecognized word: %s (position %d)", argv[i], i);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!word->cbkfn) {
|
||||
cli_out ("unrecognized command");
|
||||
return -1;
|
||||
}
|
||||
if (!word->cbkfn) {
|
||||
cli_out("unrecognized command");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( strcmp (word->word,"help")==0 )
|
||||
goto callback;
|
||||
if (strcmp(word->word, "help") == 0)
|
||||
goto callback;
|
||||
|
||||
state->await_connected = cli_cmd_needs_connection (word);
|
||||
state->await_connected = cli_cmd_needs_connection(word);
|
||||
|
||||
ret = cli_cmd_await_connected (state->await_connected);
|
||||
if (ret) {
|
||||
cli_out ("Connection failed. Please check if gluster "
|
||||
"daemon is operational.");
|
||||
gf_log ("", GF_LOG_INFO, "Exiting with: %d", ret);
|
||||
exit (ret);
|
||||
}
|
||||
ret = cli_cmd_await_connected(state->await_connected);
|
||||
if (ret) {
|
||||
cli_out(
|
||||
"Connection failed. Please check if gluster "
|
||||
"daemon is operational.");
|
||||
gf_log("", GF_LOG_INFO, "Exiting with: %d", ret);
|
||||
exit(ret);
|
||||
}
|
||||
|
||||
callback:
|
||||
ret = word->cbkfn (state, word, (const char **)argv, argc);
|
||||
(void) cli_cmd_status_reset ();
|
||||
return ret;
|
||||
ret = word->cbkfn(state, word, (const char **)argv, argc);
|
||||
(void)cli_cmd_status_reset();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
cli_cmd_input_token_count (const char *text)
|
||||
cli_cmd_input_token_count(const char *text)
|
||||
{
|
||||
int count = 0;
|
||||
const char *trav = NULL;
|
||||
int is_spc = 1;
|
||||
int count = 0;
|
||||
const char *trav = NULL;
|
||||
int is_spc = 1;
|
||||
|
||||
for (trav = text; *trav; trav++) {
|
||||
if (*trav == ' ') {
|
||||
is_spc = 1;
|
||||
} else {
|
||||
if (is_spc) {
|
||||
count++;
|
||||
is_spc = 0;
|
||||
}
|
||||
}
|
||||
for (trav = text; *trav; trav++) {
|
||||
if (*trav == ' ') {
|
||||
is_spc = 1;
|
||||
} else {
|
||||
if (is_spc) {
|
||||
count++;
|
||||
is_spc = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cli_cmd_process_line (struct cli_state *state, const char *text)
|
||||
cli_cmd_process_line(struct cli_state *state, const char *text)
|
||||
{
|
||||
int count = 0;
|
||||
char **tokens = NULL;
|
||||
char **tokenp = NULL;
|
||||
char *token = NULL;
|
||||
char *copy = NULL;
|
||||
char *saveptr = NULL;
|
||||
int i = 0;
|
||||
int ret = -1;
|
||||
int count = 0;
|
||||
char **tokens = NULL;
|
||||
char **tokenp = NULL;
|
||||
char *token = NULL;
|
||||
char *copy = NULL;
|
||||
char *saveptr = NULL;
|
||||
int i = 0;
|
||||
int ret = -1;
|
||||
|
||||
count = cli_cmd_input_token_count (text);
|
||||
count = cli_cmd_input_token_count(text);
|
||||
|
||||
tokens = calloc (count + 1, sizeof (*tokens));
|
||||
if (!tokens)
|
||||
return -1;
|
||||
tokens = calloc(count + 1, sizeof(*tokens));
|
||||
if (!tokens)
|
||||
return -1;
|
||||
|
||||
copy = strdup (text);
|
||||
if (!copy)
|
||||
goto out;
|
||||
copy = strdup(text);
|
||||
if (!copy)
|
||||
goto out;
|
||||
|
||||
tokenp = tokens;
|
||||
tokenp = tokens;
|
||||
|
||||
for (token = strtok_r (copy, " \t\r\n", &saveptr); token;
|
||||
token = strtok_r (NULL, " \t\r\n", &saveptr)) {
|
||||
*tokenp = strdup (token);
|
||||
for (token = strtok_r(copy, " \t\r\n", &saveptr); token;
|
||||
token = strtok_r(NULL, " \t\r\n", &saveptr)) {
|
||||
*tokenp = strdup(token);
|
||||
|
||||
if (!*tokenp)
|
||||
goto out;
|
||||
tokenp++;
|
||||
i++;
|
||||
if (!*tokenp)
|
||||
goto out;
|
||||
tokenp++;
|
||||
i++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ret = cli_cmd_process (state, count, tokens);
|
||||
ret = cli_cmd_process(state, count, tokens);
|
||||
out:
|
||||
free (copy);
|
||||
free(copy);
|
||||
|
||||
if (tokens)
|
||||
cli_cmd_tokens_destroy (tokens);
|
||||
if (tokens)
|
||||
cli_cmd_tokens_destroy(tokens);
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cli_cmds_register (struct cli_state *state)
|
||||
cli_cmds_register(struct cli_state *state)
|
||||
{
|
||||
int ret = 0;
|
||||
int ret = 0;
|
||||
|
||||
ret = cli_cmd_volume_register (state);
|
||||
if (ret)
|
||||
goto out;
|
||||
ret = cli_cmd_volume_register(state);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = cli_cmd_probe_register (state);
|
||||
if (ret)
|
||||
goto out;
|
||||
ret = cli_cmd_probe_register(state);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = cli_cmd_system_register (state);
|
||||
if (ret)
|
||||
goto out;
|
||||
ret = cli_cmd_system_register(state);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = cli_cmd_misc_register (state);
|
||||
if (ret)
|
||||
goto out;
|
||||
ret = cli_cmd_misc_register(state);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = cli_cmd_snapshot_register (state);
|
||||
if (ret)
|
||||
goto out;
|
||||
ret = cli_cmd_global_register (state);
|
||||
if (ret)
|
||||
goto out;
|
||||
ret = cli_cmd_snapshot_register(state);
|
||||
if (ret)
|
||||
goto out;
|
||||
ret = cli_cmd_global_register(state);
|
||||
if (ret)
|
||||
goto out;
|
||||
out:
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
cli_cmd_cond_init ()
|
||||
cli_cmd_cond_init()
|
||||
{
|
||||
pthread_mutex_init(&cond_mutex, NULL);
|
||||
pthread_cond_init(&cond, NULL);
|
||||
|
||||
pthread_mutex_init (&cond_mutex, NULL);
|
||||
pthread_cond_init (&cond, NULL);
|
||||
pthread_mutex_init(&conn_mutex, NULL);
|
||||
pthread_cond_init(&conn, NULL);
|
||||
|
||||
pthread_mutex_init (&conn_mutex, NULL);
|
||||
pthread_cond_init (&conn, NULL);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
cli_cmd_lock ()
|
||||
cli_cmd_lock()
|
||||
{
|
||||
pthread_mutex_lock (&cond_mutex);
|
||||
return 0;
|
||||
pthread_mutex_lock(&cond_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
cli_cmd_unlock ()
|
||||
cli_cmd_unlock()
|
||||
{
|
||||
pthread_mutex_unlock (&cond_mutex);
|
||||
return 0;
|
||||
pthread_mutex_unlock(&cond_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
seconds_from_now (unsigned secs, struct timespec *ts)
|
||||
seconds_from_now(unsigned secs, struct timespec *ts)
|
||||
{
|
||||
struct timeval tv = {0,};
|
||||
struct timeval tv = {
|
||||
0,
|
||||
};
|
||||
|
||||
gettimeofday (&tv, NULL);
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
ts->tv_sec = tv.tv_sec + secs;
|
||||
ts->tv_nsec = tv.tv_usec * 1000;
|
||||
ts->tv_sec = tv.tv_sec + secs;
|
||||
ts->tv_nsec = tv.tv_usec * 1000;
|
||||
}
|
||||
|
||||
int
|
||||
cli_cmd_await_response (unsigned time)
|
||||
cli_cmd_await_response(unsigned time)
|
||||
{
|
||||
struct timespec ts = {0,};
|
||||
int ret = 0;
|
||||
struct timespec ts = {
|
||||
0,
|
||||
};
|
||||
int ret = 0;
|
||||
|
||||
cli_op_ret = -1;
|
||||
cli_op_ret = -1;
|
||||
|
||||
seconds_from_now (time, &ts);
|
||||
while (!cmd_done && !ret) {
|
||||
ret = pthread_cond_timedwait (&cond, &cond_mutex,
|
||||
&ts);
|
||||
}
|
||||
seconds_from_now(time, &ts);
|
||||
while (!cmd_done && !ret) {
|
||||
ret = pthread_cond_timedwait(&cond, &cond_mutex, &ts);
|
||||
}
|
||||
|
||||
if (!cmd_done) {
|
||||
if (ret == ETIMEDOUT)
|
||||
cli_out ("Error : Request timed out");
|
||||
else
|
||||
cli_out ("Error : Command returned with error code:%d",
|
||||
ret);
|
||||
}
|
||||
cmd_done = 0;
|
||||
if (!cmd_done) {
|
||||
if (ret == ETIMEDOUT)
|
||||
cli_out("Error : Request timed out");
|
||||
else
|
||||
cli_out("Error : Command returned with error code:%d", ret);
|
||||
}
|
||||
cmd_done = 0;
|
||||
|
||||
return cli_op_ret;
|
||||
return cli_op_ret;
|
||||
}
|
||||
|
||||
/* This function must be called _only_ after all actions associated with
|
||||
* command processing is complete. Otherwise, gluster process may exit before
|
||||
* reporting results to stdout/stderr. */
|
||||
int
|
||||
cli_cmd_broadcast_response (int32_t status)
|
||||
cli_cmd_broadcast_response(int32_t status)
|
||||
{
|
||||
|
||||
pthread_mutex_lock (&cond_mutex);
|
||||
{
|
||||
if (!cmd_sent)
|
||||
goto out;
|
||||
cmd_done = 1;
|
||||
cli_op_ret = status;
|
||||
pthread_cond_broadcast (&cond);
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&cond_mutex);
|
||||
{
|
||||
if (!cmd_sent)
|
||||
goto out;
|
||||
cmd_done = 1;
|
||||
cli_op_ret = status;
|
||||
pthread_cond_broadcast(&cond);
|
||||
}
|
||||
|
||||
out:
|
||||
pthread_mutex_unlock (&cond_mutex);
|
||||
return 0;
|
||||
pthread_mutex_unlock(&cond_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t
|
||||
cli_cmd_await_connected (unsigned conn_timo)
|
||||
cli_cmd_await_connected(unsigned conn_timo)
|
||||
{
|
||||
int32_t ret = 0;
|
||||
struct timespec ts = {0,};
|
||||
int32_t ret = 0;
|
||||
struct timespec ts = {
|
||||
0,
|
||||
};
|
||||
|
||||
if (!conn_timo)
|
||||
return 0;
|
||||
if (!conn_timo)
|
||||
return 0;
|
||||
|
||||
pthread_mutex_lock (&conn_mutex);
|
||||
{
|
||||
seconds_from_now (conn_timo, &ts);
|
||||
while (!connected && !ret) {
|
||||
ret = pthread_cond_timedwait (&conn, &conn_mutex,
|
||||
&ts);
|
||||
}
|
||||
pthread_mutex_lock(&conn_mutex);
|
||||
{
|
||||
seconds_from_now(conn_timo, &ts);
|
||||
while (!connected && !ret) {
|
||||
ret = pthread_cond_timedwait(&conn, &conn_mutex, &ts);
|
||||
}
|
||||
pthread_mutex_unlock (&conn_mutex);
|
||||
}
|
||||
pthread_mutex_unlock(&conn_mutex);
|
||||
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t
|
||||
cli_cmd_broadcast_connected ()
|
||||
cli_cmd_broadcast_connected()
|
||||
{
|
||||
pthread_mutex_lock (&conn_mutex);
|
||||
{
|
||||
connected = 1;
|
||||
pthread_cond_broadcast (&conn);
|
||||
}
|
||||
pthread_mutex_lock(&conn_mutex);
|
||||
{
|
||||
connected = 1;
|
||||
pthread_cond_broadcast(&conn);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock (&conn_mutex);
|
||||
pthread_mutex_unlock(&conn_mutex);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
cli_cmd_submit (struct rpc_clnt* rpc, void *req, call_frame_t *frame,
|
||||
rpc_clnt_prog_t *prog,
|
||||
int procnum, struct iobref *iobref,
|
||||
xlator_t *this, fop_cbk_fn_t cbkfn, xdrproc_t xdrproc)
|
||||
cli_cmd_submit(struct rpc_clnt *rpc, void *req, call_frame_t *frame,
|
||||
rpc_clnt_prog_t *prog, int procnum, struct iobref *iobref,
|
||||
xlator_t *this, fop_cbk_fn_t cbkfn, xdrproc_t xdrproc)
|
||||
{
|
||||
int ret = -1;
|
||||
unsigned timeout = 0;
|
||||
int ret = -1;
|
||||
unsigned timeout = 0;
|
||||
|
||||
if ((GLUSTER_CLI_PROFILE_VOLUME == procnum) ||
|
||||
(GLUSTER_CLI_HEAL_VOLUME == procnum))
|
||||
timeout = cli_ten_minutes_timeout;
|
||||
else
|
||||
timeout = cli_default_conn_timeout;
|
||||
if ((GLUSTER_CLI_PROFILE_VOLUME == procnum) ||
|
||||
(GLUSTER_CLI_HEAL_VOLUME == procnum))
|
||||
timeout = cli_ten_minutes_timeout;
|
||||
else
|
||||
timeout = cli_default_conn_timeout;
|
||||
|
||||
cli_cmd_lock ();
|
||||
cmd_sent = 0;
|
||||
ret = cli_submit_request (rpc, req, frame, prog,
|
||||
procnum, NULL, this, cbkfn, xdrproc);
|
||||
cli_cmd_lock();
|
||||
cmd_sent = 0;
|
||||
ret = cli_submit_request(rpc, req, frame, prog, procnum, NULL, this, cbkfn,
|
||||
xdrproc);
|
||||
|
||||
if (!ret) {
|
||||
cmd_sent = 1;
|
||||
ret = cli_cmd_await_response (timeout);
|
||||
}
|
||||
if (!ret) {
|
||||
cmd_sent = 1;
|
||||
ret = cli_cmd_await_response(timeout);
|
||||
}
|
||||
|
||||
cli_cmd_unlock ();
|
||||
cli_cmd_unlock();
|
||||
|
||||
gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret);
|
||||
return ret;
|
||||
gf_log("cli", GF_LOG_DEBUG, "Returning %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
cli_cmd_pattern_cmp (void *a, void *b)
|
||||
cli_cmd_pattern_cmp(void *a, void *b)
|
||||
{
|
||||
struct cli_cmd *ia = NULL;
|
||||
struct cli_cmd *ib = NULL;
|
||||
int ret = 0;
|
||||
struct cli_cmd *ia = NULL;
|
||||
struct cli_cmd *ib = NULL;
|
||||
int ret = 0;
|
||||
|
||||
ia = a;
|
||||
ib = b;
|
||||
if (strcmp (ia->pattern, ib->pattern) > 0)
|
||||
ret = 1;
|
||||
else if (strcmp (ia->pattern, ib->pattern) < 0)
|
||||
ret = -1;
|
||||
else
|
||||
ret = 0;
|
||||
return ret;
|
||||
ia = a;
|
||||
ib = b;
|
||||
if (strcmp(ia->pattern, ib->pattern) > 0)
|
||||
ret = 1;
|
||||
else if (strcmp(ia->pattern, ib->pattern) < 0)
|
||||
ret = -1;
|
||||
else
|
||||
ret = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
cli_cmd_sort (struct cli_cmd *cmd, int count)
|
||||
cli_cmd_sort(struct cli_cmd *cmd, int count)
|
||||
{
|
||||
gf_array_insertionsort (cmd, 1, count - 2, sizeof(struct cli_cmd),
|
||||
cli_cmd_pattern_cmp);
|
||||
gf_array_insertionsort(cmd, 1, count - 2, sizeof(struct cli_cmd),
|
||||
cli_cmd_pattern_cmp);
|
||||
}
|
||||
|
@ -14,136 +14,131 @@ extern struct rpc_clnt global_quotad_rpc;
|
||||
extern struct rpc_clnt_program cli_quotad_clnt;
|
||||
|
||||
int
|
||||
cli_quotad_submit_request (void *req, call_frame_t *frame,
|
||||
rpc_clnt_prog_t *prog,
|
||||
int procnum, struct iobref *iobref,
|
||||
xlator_t *this, fop_cbk_fn_t cbkfn,
|
||||
xdrproc_t xdrproc)
|
||||
cli_quotad_submit_request(void *req, call_frame_t *frame, rpc_clnt_prog_t *prog,
|
||||
int procnum, struct iobref *iobref, xlator_t *this,
|
||||
fop_cbk_fn_t cbkfn, xdrproc_t xdrproc)
|
||||
{
|
||||
int ret = -1;
|
||||
int count = 0;
|
||||
struct iovec iov = {0, };
|
||||
struct iobuf *iobuf = NULL;
|
||||
char new_iobref = 0;
|
||||
ssize_t xdr_size = 0;
|
||||
int ret = -1;
|
||||
int count = 0;
|
||||
struct iovec iov = {
|
||||
0,
|
||||
};
|
||||
struct iobuf *iobuf = NULL;
|
||||
char new_iobref = 0;
|
||||
ssize_t xdr_size = 0;
|
||||
|
||||
GF_ASSERT (this);
|
||||
GF_ASSERT(this);
|
||||
|
||||
if (req) {
|
||||
xdr_size = xdr_sizeof (xdrproc, req);
|
||||
iobuf = iobuf_get2 (this->ctx->iobuf_pool, xdr_size);
|
||||
if (!iobuf) {
|
||||
goto out;
|
||||
};
|
||||
if (req) {
|
||||
xdr_size = xdr_sizeof(xdrproc, req);
|
||||
iobuf = iobuf_get2(this->ctx->iobuf_pool, xdr_size);
|
||||
if (!iobuf) {
|
||||
goto out;
|
||||
};
|
||||
|
||||
if (!iobref) {
|
||||
iobref = iobref_new ();
|
||||
if (!iobref) {
|
||||
goto out;
|
||||
}
|
||||
if (!iobref) {
|
||||
iobref = iobref_new();
|
||||
if (!iobref) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
new_iobref = 1;
|
||||
}
|
||||
|
||||
iobref_add (iobref, iobuf);
|
||||
|
||||
iov.iov_base = iobuf->ptr;
|
||||
iov.iov_len = iobuf_size (iobuf);
|
||||
|
||||
/* Create the xdr payload */
|
||||
ret = xdr_serialize_generic (iov, req, xdrproc);
|
||||
if (ret == -1) {
|
||||
goto out;
|
||||
}
|
||||
iov.iov_len = ret;
|
||||
count = 1;
|
||||
new_iobref = 1;
|
||||
}
|
||||
|
||||
/* Send the msg */
|
||||
ret = rpc_clnt_submit (&global_quotad_rpc, prog, procnum, cbkfn,
|
||||
&iov, count,
|
||||
NULL, 0, iobref, frame, NULL, 0, NULL, 0, NULL);
|
||||
ret = 0;
|
||||
iobref_add(iobref, iobuf);
|
||||
|
||||
iov.iov_base = iobuf->ptr;
|
||||
iov.iov_len = iobuf_size(iobuf);
|
||||
|
||||
/* Create the xdr payload */
|
||||
ret = xdr_serialize_generic(iov, req, xdrproc);
|
||||
if (ret == -1) {
|
||||
goto out;
|
||||
}
|
||||
iov.iov_len = ret;
|
||||
count = 1;
|
||||
}
|
||||
|
||||
/* Send the msg */
|
||||
ret = rpc_clnt_submit(&global_quotad_rpc, prog, procnum, cbkfn, &iov, count,
|
||||
NULL, 0, iobref, frame, NULL, 0, NULL, 0, NULL);
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
if (new_iobref)
|
||||
iobref_unref (iobref);
|
||||
if (iobuf)
|
||||
iobuf_unref (iobuf);
|
||||
if (new_iobref)
|
||||
iobref_unref(iobref);
|
||||
if (iobuf)
|
||||
iobuf_unref(iobuf);
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
cli_quotad_notify (struct rpc_clnt *rpc, void *mydata,
|
||||
rpc_clnt_event_t event, void *data)
|
||||
cli_quotad_notify(struct rpc_clnt *rpc, void *mydata, rpc_clnt_event_t event,
|
||||
void *data)
|
||||
{
|
||||
xlator_t *this = NULL;
|
||||
int ret = 0;
|
||||
xlator_t *this = NULL;
|
||||
int ret = 0;
|
||||
|
||||
this = mydata;
|
||||
this = mydata;
|
||||
|
||||
switch (event) {
|
||||
case RPC_CLNT_CONNECT:
|
||||
{
|
||||
gf_log (this->name, GF_LOG_TRACE, "got RPC_CLNT_CONNECT");
|
||||
break;
|
||||
switch (event) {
|
||||
case RPC_CLNT_CONNECT: {
|
||||
gf_log(this->name, GF_LOG_TRACE, "got RPC_CLNT_CONNECT");
|
||||
break;
|
||||
}
|
||||
|
||||
case RPC_CLNT_DISCONNECT:
|
||||
{
|
||||
gf_log (this->name, GF_LOG_TRACE, "got RPC_CLNT_DISCONNECT");
|
||||
break;
|
||||
case RPC_CLNT_DISCONNECT: {
|
||||
gf_log(this->name, GF_LOG_TRACE, "got RPC_CLNT_DISCONNECT");
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
gf_log (this->name, GF_LOG_TRACE,
|
||||
"got some other RPC event %d", event);
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
gf_log(this->name, GF_LOG_TRACE, "got some other RPC event %d",
|
||||
event);
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct rpc_clnt *
|
||||
cli_quotad_clnt_init (xlator_t *this, dict_t *options)
|
||||
cli_quotad_clnt_init(xlator_t *this, dict_t *options)
|
||||
{
|
||||
struct rpc_clnt *rpc = NULL;
|
||||
int ret = -1;
|
||||
struct rpc_clnt *rpc = NULL;
|
||||
int ret = -1;
|
||||
|
||||
ret = dict_set_str(options, "transport.address-family", "unix");
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = dict_set_str (options, "transport.address-family", "unix");
|
||||
if (ret)
|
||||
goto out;
|
||||
ret = dict_set_str(options, "transport-type", "socket");
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = dict_set_str (options, "transport-type", "socket");
|
||||
if (ret)
|
||||
goto out;
|
||||
ret = dict_set_str(options, "transport.socket.connect-path",
|
||||
"/var/run/gluster/quotad.socket");
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = dict_set_str (options, "transport.socket.connect-path",
|
||||
"/var/run/gluster/quotad.socket");
|
||||
if (ret)
|
||||
goto out;
|
||||
rpc = rpc_clnt_new(options, this, this->name, 16);
|
||||
if (!rpc)
|
||||
goto out;
|
||||
|
||||
rpc = rpc_clnt_new (options, this, this->name, 16);
|
||||
if (!rpc)
|
||||
goto out;
|
||||
ret = rpc_clnt_register_notify(rpc, cli_quotad_notify, this);
|
||||
if (ret) {
|
||||
gf_log("cli", GF_LOG_ERROR, "failed to register notify");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = rpc_clnt_register_notify (rpc, cli_quotad_notify, this);
|
||||
if (ret) {
|
||||
gf_log ("cli", GF_LOG_ERROR, "failed to register notify");
|
||||
goto out;
|
||||
}
|
||||
|
||||
rpc_clnt_start (rpc);
|
||||
rpc_clnt_start(rpc);
|
||||
out:
|
||||
if (ret) {
|
||||
if (rpc)
|
||||
rpc_clnt_unref (rpc);
|
||||
rpc = NULL;
|
||||
}
|
||||
if (ret) {
|
||||
if (rpc)
|
||||
rpc_clnt_unref(rpc);
|
||||
rpc = NULL;
|
||||
}
|
||||
|
||||
return rpc;
|
||||
return rpc;
|
||||
}
|
||||
|
||||
|
482
cli/src/cli-rl.c
482
cli/src/cli-rl.c
@ -27,392 +27,374 @@
|
||||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
|
||||
|
||||
int
|
||||
cli_rl_out (struct cli_state *state, const char *fmt, va_list ap)
|
||||
cli_rl_out(struct cli_state *state, const char *fmt, va_list ap)
|
||||
{
|
||||
int tmp_rl_point = rl_point;
|
||||
int n = rl_end;
|
||||
int ret = 0;
|
||||
int tmp_rl_point = rl_point;
|
||||
int n = rl_end;
|
||||
int ret = 0;
|
||||
|
||||
if (rl_end >= 0 ) {
|
||||
rl_kill_text (0, rl_end);
|
||||
rl_redisplay ();
|
||||
}
|
||||
if (rl_end >= 0) {
|
||||
rl_kill_text(0, rl_end);
|
||||
rl_redisplay();
|
||||
}
|
||||
|
||||
printf ("\r%*s\r", (int)strlen (state->prompt), "");
|
||||
printf("\r%*s\r", (int)strlen(state->prompt), "");
|
||||
|
||||
ret = vprintf (fmt, ap);
|
||||
ret = vprintf(fmt, ap);
|
||||
|
||||
printf ("\n");
|
||||
fflush(stdout);
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
|
||||
if (n) {
|
||||
rl_do_undo ();
|
||||
rl_point = tmp_rl_point;
|
||||
rl_reset_line_state ();
|
||||
}
|
||||
if (n) {
|
||||
rl_do_undo();
|
||||
rl_point = tmp_rl_point;
|
||||
rl_reset_line_state();
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
cli_rl_err (struct cli_state *state, const char *fmt, va_list ap)
|
||||
cli_rl_err(struct cli_state *state, const char *fmt, va_list ap)
|
||||
{
|
||||
int tmp_rl_point = rl_point;
|
||||
int n = rl_end;
|
||||
int ret = 0;
|
||||
int tmp_rl_point = rl_point;
|
||||
int n = rl_end;
|
||||
int ret = 0;
|
||||
|
||||
if (rl_end >= 0 ) {
|
||||
rl_kill_text (0, rl_end);
|
||||
rl_redisplay ();
|
||||
}
|
||||
if (rl_end >= 0) {
|
||||
rl_kill_text(0, rl_end);
|
||||
rl_redisplay();
|
||||
}
|
||||
|
||||
fprintf (stderr, "\r%*s\r", (int)strlen (state->prompt), "");
|
||||
fprintf(stderr, "\r%*s\r", (int)strlen(state->prompt), "");
|
||||
|
||||
ret = vfprintf (stderr, fmt, ap);
|
||||
ret = vfprintf(stderr, fmt, ap);
|
||||
|
||||
fprintf (stderr, "\n");
|
||||
fflush(stderr);
|
||||
fprintf(stderr, "\n");
|
||||
fflush(stderr);
|
||||
|
||||
if (n) {
|
||||
rl_do_undo ();
|
||||
rl_point = tmp_rl_point;
|
||||
rl_reset_line_state ();
|
||||
}
|
||||
if (n) {
|
||||
rl_do_undo();
|
||||
rl_point = tmp_rl_point;
|
||||
rl_reset_line_state();
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
cli_rl_process_line (char *line)
|
||||
cli_rl_process_line(char *line)
|
||||
{
|
||||
struct cli_state *state = NULL;
|
||||
int ret = 0;
|
||||
struct cli_state *state = NULL;
|
||||
int ret = 0;
|
||||
|
||||
state = global_state;
|
||||
state = global_state;
|
||||
|
||||
state->rl_processing = 1;
|
||||
{
|
||||
ret = cli_cmd_process_line (state, line);
|
||||
if (ret)
|
||||
gf_log (THIS->name, GF_LOG_WARNING,
|
||||
"failed to process line");
|
||||
|
||||
add_history (line);
|
||||
}
|
||||
state->rl_processing = 0;
|
||||
state->rl_processing = 1;
|
||||
{
|
||||
ret = cli_cmd_process_line(state, line);
|
||||
if (ret)
|
||||
gf_log(THIS->name, GF_LOG_WARNING, "failed to process line");
|
||||
|
||||
add_history(line);
|
||||
}
|
||||
state->rl_processing = 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cli_rl_stdin (int fd, int idx, int gen, void *data,
|
||||
int poll_out, int poll_in, int poll_err)
|
||||
cli_rl_stdin(int fd, int idx, int gen, void *data, int poll_out, int poll_in,
|
||||
int poll_err)
|
||||
{
|
||||
struct cli_state *state = NULL;
|
||||
struct cli_state *state = NULL;
|
||||
|
||||
state = data;
|
||||
state = data;
|
||||
|
||||
rl_callback_read_char ();
|
||||
rl_callback_read_char();
|
||||
|
||||
event_handled (state->ctx->event_pool, fd, idx, gen);
|
||||
event_handled(state->ctx->event_pool, fd, idx, gen);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
cli_rl_autocomplete_entry (const char *text, int times)
|
||||
cli_rl_autocomplete_entry(const char *text, int times)
|
||||
{
|
||||
struct cli_state *state = NULL;
|
||||
char *retp = NULL;
|
||||
struct cli_state *state = NULL;
|
||||
char *retp = NULL;
|
||||
|
||||
state = global_state;
|
||||
state = global_state;
|
||||
|
||||
if (!state->matchesp)
|
||||
return NULL;
|
||||
if (!state->matchesp)
|
||||
return NULL;
|
||||
|
||||
retp = *state->matchesp;
|
||||
retp = *state->matchesp;
|
||||
|
||||
state->matchesp++;
|
||||
state->matchesp++;
|
||||
|
||||
return retp ? strdup (retp) : NULL;
|
||||
return retp ? strdup(retp) : NULL;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cli_rl_token_count (const char *text)
|
||||
cli_rl_token_count(const char *text)
|
||||
{
|
||||
int count = 0;
|
||||
const char *trav = NULL;
|
||||
int is_spc = 1;
|
||||
int count = 0;
|
||||
const char *trav = NULL;
|
||||
int is_spc = 1;
|
||||
|
||||
for (trav = text; *trav; trav++) {
|
||||
if (*trav == ' ') {
|
||||
is_spc = 1;
|
||||
} else {
|
||||
if (is_spc) {
|
||||
count++;
|
||||
is_spc = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_spc)
|
||||
/* what needs to be autocompleted is a full
|
||||
new word, and not extend the last word
|
||||
*/
|
||||
for (trav = text; *trav; trav++) {
|
||||
if (*trav == ' ') {
|
||||
is_spc = 1;
|
||||
} else {
|
||||
if (is_spc) {
|
||||
count++;
|
||||
is_spc = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
if (is_spc)
|
||||
/* what needs to be autocompleted is a full
|
||||
new word, and not extend the last word
|
||||
*/
|
||||
count++;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
char **
|
||||
cli_rl_tokenize (const char *text)
|
||||
cli_rl_tokenize(const char *text)
|
||||
{
|
||||
int count = 0;
|
||||
char **tokens = NULL;
|
||||
char **tokenp = NULL;
|
||||
char *token = NULL;
|
||||
char *copy = NULL;
|
||||
char *saveptr = NULL;
|
||||
int i = 0;
|
||||
int count = 0;
|
||||
char **tokens = NULL;
|
||||
char **tokenp = NULL;
|
||||
char *token = NULL;
|
||||
char *copy = NULL;
|
||||
char *saveptr = NULL;
|
||||
int i = 0;
|
||||
|
||||
count = cli_rl_token_count (text);
|
||||
count = cli_rl_token_count(text);
|
||||
|
||||
tokens = calloc (count + 1, sizeof (*tokens));
|
||||
if (!tokens)
|
||||
return NULL;
|
||||
tokens = calloc(count + 1, sizeof(*tokens));
|
||||
if (!tokens)
|
||||
return NULL;
|
||||
|
||||
copy = strdup (text);
|
||||
if (!copy)
|
||||
goto out;
|
||||
copy = strdup(text);
|
||||
if (!copy)
|
||||
goto out;
|
||||
|
||||
tokenp = tokens;
|
||||
tokenp = tokens;
|
||||
|
||||
for (token = strtok_r (copy, " \t\r\n", &saveptr); token;
|
||||
token = strtok_r (NULL, " \t\r\n", &saveptr)) {
|
||||
*tokenp = strdup (token);
|
||||
for (token = strtok_r(copy, " \t\r\n", &saveptr); token;
|
||||
token = strtok_r(NULL, " \t\r\n", &saveptr)) {
|
||||
*tokenp = strdup(token);
|
||||
|
||||
if (!*tokenp)
|
||||
goto out;
|
||||
tokenp++;
|
||||
i++;
|
||||
if (!*tokenp)
|
||||
goto out;
|
||||
tokenp++;
|
||||
i++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (i < count) {
|
||||
/* symbolize that what needs to be autocompleted is
|
||||
the full set of possible nextwords, and not extend
|
||||
the last word
|
||||
*/
|
||||
*tokenp = strdup ("");
|
||||
if (!*tokenp)
|
||||
goto out;
|
||||
tokenp++;
|
||||
i++;
|
||||
}
|
||||
if (i < count) {
|
||||
/* symbolize that what needs to be autocompleted is
|
||||
the full set of possible nextwords, and not extend
|
||||
the last word
|
||||
*/
|
||||
*tokenp = strdup("");
|
||||
if (!*tokenp)
|
||||
goto out;
|
||||
tokenp++;
|
||||
i++;
|
||||
}
|
||||
|
||||
out:
|
||||
free (copy);
|
||||
free(copy);
|
||||
|
||||
if (i < count) {
|
||||
cli_cmd_tokens_destroy (tokens);
|
||||
tokens = NULL;
|
||||
}
|
||||
if (i < count) {
|
||||
cli_cmd_tokens_destroy(tokens);
|
||||
tokens = NULL;
|
||||
}
|
||||
|
||||
return tokens;
|
||||
return tokens;
|
||||
}
|
||||
|
||||
|
||||
char **
|
||||
cli_rl_get_matches (struct cli_state *state, struct cli_cmd_word *word,
|
||||
const char *text)
|
||||
cli_rl_get_matches(struct cli_state *state, struct cli_cmd_word *word,
|
||||
const char *text)
|
||||
{
|
||||
char **matches = NULL;
|
||||
char **matchesp = NULL;
|
||||
struct cli_cmd_word **next = NULL;
|
||||
int count = 0;
|
||||
int len = 0;
|
||||
char **matches = NULL;
|
||||
char **matchesp = NULL;
|
||||
struct cli_cmd_word **next = NULL;
|
||||
int count = 0;
|
||||
int len = 0;
|
||||
|
||||
len = strlen (text);
|
||||
len = strlen(text);
|
||||
|
||||
if (!word->nextwords)
|
||||
return NULL;
|
||||
if (!word->nextwords)
|
||||
return NULL;
|
||||
|
||||
for (next = word->nextwords; *next; next++)
|
||||
count++;
|
||||
for (next = word->nextwords; *next; next++)
|
||||
count++;
|
||||
|
||||
matches = calloc (count + 1, sizeof (*matches));
|
||||
matchesp = matches;
|
||||
matches = calloc(count + 1, sizeof(*matches));
|
||||
matchesp = matches;
|
||||
|
||||
for (next = word->nextwords; *next; next++) {
|
||||
if ((*next)->match) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strncmp ((*next)->word, text, len) == 0) {
|
||||
*matchesp = strdup ((*next)->word);
|
||||
matchesp++;
|
||||
}
|
||||
for (next = word->nextwords; *next; next++) {
|
||||
if ((*next)->match) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return matches;
|
||||
if (strncmp((*next)->word, text, len) == 0) {
|
||||
*matchesp = strdup((*next)->word);
|
||||
matchesp++;
|
||||
}
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cli_rl_autocomplete_prepare (struct cli_state *state, const char *text)
|
||||
cli_rl_autocomplete_prepare(struct cli_state *state, const char *text)
|
||||
{
|
||||
struct cli_cmd_word *word = NULL;
|
||||
struct cli_cmd_word *next = NULL;
|
||||
char **tokens = NULL;
|
||||
char **tokenp = NULL;
|
||||
char *token = NULL;
|
||||
char **matches = NULL;
|
||||
struct cli_cmd_word *word = NULL;
|
||||
struct cli_cmd_word *next = NULL;
|
||||
char **tokens = NULL;
|
||||
char **tokenp = NULL;
|
||||
char *token = NULL;
|
||||
char **matches = NULL;
|
||||
|
||||
tokens = cli_rl_tokenize (text);
|
||||
if (!tokens)
|
||||
return 0;
|
||||
tokens = cli_rl_tokenize(text);
|
||||
if (!tokens)
|
||||
return 0;
|
||||
|
||||
word = &state->tree.root;
|
||||
word = &state->tree.root;
|
||||
|
||||
for (tokenp = tokens; (token = *tokenp); tokenp++) {
|
||||
if (!*(tokenp+1)) {
|
||||
/* last word */
|
||||
break;
|
||||
}
|
||||
|
||||
next = cli_cmd_nextword (word, token);
|
||||
word = next;
|
||||
if (!word)
|
||||
break;
|
||||
for (tokenp = tokens; (token = *tokenp); tokenp++) {
|
||||
if (!*(tokenp + 1)) {
|
||||
/* last word */
|
||||
break;
|
||||
}
|
||||
|
||||
next = cli_cmd_nextword(word, token);
|
||||
word = next;
|
||||
if (!word)
|
||||
goto out;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!token)
|
||||
return 0;
|
||||
matches = cli_rl_get_matches (state, word, token);
|
||||
if (!word)
|
||||
goto out;
|
||||
|
||||
state->matches = matches;
|
||||
state->matchesp = matches;
|
||||
if (!token)
|
||||
return 0;
|
||||
matches = cli_rl_get_matches(state, word, token);
|
||||
|
||||
state->matches = matches;
|
||||
state->matchesp = matches;
|
||||
|
||||
out:
|
||||
cli_cmd_tokens_destroy (tokens);
|
||||
return 0;
|
||||
cli_cmd_tokens_destroy(tokens);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cli_rl_autocomplete_cleanup (struct cli_state *state)
|
||||
cli_rl_autocomplete_cleanup(struct cli_state *state)
|
||||
{
|
||||
if (state->matches)
|
||||
cli_cmd_tokens_destroy (state->matches);
|
||||
if (state->matches)
|
||||
cli_cmd_tokens_destroy(state->matches);
|
||||
|
||||
state->matches = NULL;
|
||||
state->matchesp = NULL;
|
||||
state->matches = NULL;
|
||||
state->matchesp = NULL;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
char **
|
||||
cli_rl_autocomplete (const char *text, int start, int end)
|
||||
cli_rl_autocomplete(const char *text, int start, int end)
|
||||
{
|
||||
struct cli_state *state = NULL;
|
||||
char **matches = NULL;
|
||||
char save = 0;
|
||||
struct cli_state *state = NULL;
|
||||
char **matches = NULL;
|
||||
char save = 0;
|
||||
|
||||
state = global_state;
|
||||
state = global_state;
|
||||
|
||||
/* hack to make the autocompletion code neater */
|
||||
/* fake it as though the cursor is at the end of line */
|
||||
/* hack to make the autocompletion code neater */
|
||||
/* fake it as though the cursor is at the end of line */
|
||||
|
||||
save = rl_line_buffer[rl_point];
|
||||
rl_line_buffer[rl_point] = 0;
|
||||
save = rl_line_buffer[rl_point];
|
||||
rl_line_buffer[rl_point] = 0;
|
||||
|
||||
cli_rl_autocomplete_prepare (state, rl_line_buffer);
|
||||
cli_rl_autocomplete_prepare(state, rl_line_buffer);
|
||||
|
||||
matches = rl_completion_matches (text, cli_rl_autocomplete_entry);
|
||||
matches = rl_completion_matches(text, cli_rl_autocomplete_entry);
|
||||
|
||||
cli_rl_autocomplete_cleanup (state);
|
||||
cli_rl_autocomplete_cleanup(state);
|
||||
|
||||
rl_line_buffer[rl_point] = save;
|
||||
rl_line_buffer[rl_point] = save;
|
||||
|
||||
return matches;
|
||||
return matches;
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
complete_none (const char *txt, int times)
|
||||
complete_none(const char *txt, int times)
|
||||
{
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
cli_rl_input (void *_data)
|
||||
cli_rl_input(void *_data)
|
||||
{
|
||||
struct cli_state *state = NULL;
|
||||
char *line = NULL;
|
||||
struct cli_state *state = NULL;
|
||||
char *line = NULL;
|
||||
|
||||
state = _data;
|
||||
state = _data;
|
||||
|
||||
for (;;) {
|
||||
line = readline (state->prompt);
|
||||
if (!line)
|
||||
exit(0); //break;
|
||||
for (;;) {
|
||||
line = readline(state->prompt);
|
||||
if (!line)
|
||||
exit(0); // break;
|
||||
|
||||
if (*line)
|
||||
cli_rl_process_line (line);
|
||||
if (*line)
|
||||
cli_rl_process_line(line);
|
||||
|
||||
free (line);
|
||||
}
|
||||
free(line);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cli_rl_enable (struct cli_state *state)
|
||||
cli_rl_enable(struct cli_state *state)
|
||||
{
|
||||
int ret = 0;
|
||||
int ret = 0;
|
||||
|
||||
rl_pre_input_hook = NULL;
|
||||
rl_attempted_completion_function = cli_rl_autocomplete;
|
||||
rl_completion_entry_function = complete_none;
|
||||
rl_pre_input_hook = NULL;
|
||||
rl_attempted_completion_function = cli_rl_autocomplete;
|
||||
rl_completion_entry_function = complete_none;
|
||||
|
||||
if (!state->rl_async) {
|
||||
ret = pthread_create (&state->input, NULL,
|
||||
cli_rl_input, state);
|
||||
if (ret == 0)
|
||||
state->rl_enabled = 1;
|
||||
goto out;
|
||||
}
|
||||
if (!state->rl_async) {
|
||||
ret = pthread_create(&state->input, NULL, cli_rl_input, state);
|
||||
if (ret == 0)
|
||||
state->rl_enabled = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = event_register (state->ctx->event_pool, 0, cli_rl_stdin, state,
|
||||
1, 0);
|
||||
if (ret == -1)
|
||||
goto out;
|
||||
ret = event_register(state->ctx->event_pool, 0, cli_rl_stdin, state, 1, 0);
|
||||
if (ret == -1)
|
||||
goto out;
|
||||
|
||||
state->rl_enabled = 1;
|
||||
rl_callback_handler_install (state->prompt, cli_rl_process_line);
|
||||
state->rl_enabled = 1;
|
||||
rl_callback_handler_install(state->prompt, cli_rl_process_line);
|
||||
|
||||
out:
|
||||
return state->rl_enabled;
|
||||
return state->rl_enabled;
|
||||
}
|
||||
|
||||
#else /* HAVE_READLINE */
|
||||
|
||||
int
|
||||
cli_rl_enable (struct cli_state *state)
|
||||
cli_rl_enable(struct cli_state *state)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* HAVE_READLINE */
|
||||
|
21076
cli/src/cli-rpc-ops.c
21076
cli/src/cli-rpc-ops.c
File diff suppressed because it is too large
Load Diff
10366
cli/src/cli-xml-output.c
10366
cli/src/cli-xml-output.c
File diff suppressed because it is too large
Load Diff
1157
cli/src/cli.c
1157
cli/src/cli.c
File diff suppressed because it is too large
Load Diff
@ -19,74 +19,72 @@
|
||||
#define CMDBUFSIZ 1024
|
||||
|
||||
void *
|
||||
cli_batch (void *d)
|
||||
cli_batch(void *d)
|
||||
{
|
||||
struct cli_state *state = NULL;
|
||||
int ret = 0;
|
||||
struct cli_state *state = NULL;
|
||||
int ret = 0;
|
||||
|
||||
state = d;
|
||||
state = d;
|
||||
|
||||
ret = cli_cmd_process (state, state->argc, state->argv);
|
||||
ret = cli_cmd_process(state, state->argc, state->argv);
|
||||
|
||||
gf_log ("", GF_LOG_INFO, "Exiting with: %d", ret);
|
||||
exit (-ret);
|
||||
gf_log("", GF_LOG_INFO, "Exiting with: %d", ret);
|
||||
exit(-ret);
|
||||
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
cli_input (void *d)
|
||||
cli_input(void *d)
|
||||
{
|
||||
struct cli_state *state = NULL;
|
||||
int ret = 0;
|
||||
char cmdbuf[CMDBUFSIZ];
|
||||
char *cmd = NULL;
|
||||
size_t len = 0;
|
||||
struct cli_state *state = NULL;
|
||||
int ret = 0;
|
||||
char cmdbuf[CMDBUFSIZ];
|
||||
char *cmd = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
state = d;
|
||||
state = d;
|
||||
|
||||
for (;;) {
|
||||
printf ("%s", state->prompt);
|
||||
for (;;) {
|
||||
printf("%s", state->prompt);
|
||||
|
||||
cmd = fgets (cmdbuf, CMDBUFSIZ, stdin);
|
||||
if (!cmd)
|
||||
break;
|
||||
len = strlen(cmd);
|
||||
if (len > 0 && cmd[len - 1] == '\n') //strip trailing \n
|
||||
cmd[len - 1] = '\0';
|
||||
ret = cli_cmd_process_line (state, cmd);
|
||||
if (ret != 0 && state->mode & GLUSTER_MODE_ERR_FATAL)
|
||||
break;
|
||||
}
|
||||
cmd = fgets(cmdbuf, CMDBUFSIZ, stdin);
|
||||
if (!cmd)
|
||||
break;
|
||||
len = strlen(cmd);
|
||||
if (len > 0 && cmd[len - 1] == '\n') // strip trailing \n
|
||||
cmd[len - 1] = '\0';
|
||||
ret = cli_cmd_process_line(state, cmd);
|
||||
if (ret != 0 && state->mode & GLUSTER_MODE_ERR_FATAL)
|
||||
break;
|
||||
}
|
||||
|
||||
exit (-ret);
|
||||
exit(-ret);
|
||||
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cli_input_init (struct cli_state *state)
|
||||
cli_input_init(struct cli_state *state)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (state->argc) {
|
||||
ret = pthread_create (&state->input, NULL, cli_batch, state);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (isatty (STDIN_FILENO)) {
|
||||
state->prompt = "gluster> ";
|
||||
|
||||
cli_rl_enable (state);
|
||||
} else {
|
||||
state->prompt = "";
|
||||
state->mode |= GLUSTER_MODE_SCRIPT | GLUSTER_MODE_ERR_FATAL;
|
||||
}
|
||||
|
||||
if (!state->rl_enabled)
|
||||
ret = pthread_create (&state->input, NULL, cli_input, state);
|
||||
int ret = 0;
|
||||
|
||||
if (state->argc) {
|
||||
ret = pthread_create(&state->input, NULL, cli_batch, state);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (isatty(STDIN_FILENO)) {
|
||||
state->prompt = "gluster> ";
|
||||
|
||||
cli_rl_enable(state);
|
||||
} else {
|
||||
state->prompt = "";
|
||||
state->mode |= GLUSTER_MODE_SCRIPT | GLUSTER_MODE_ERR_FATAL;
|
||||
}
|
||||
|
||||
if (!state->rl_enabled)
|
||||
ret = pthread_create(&state->input, NULL, cli_input, state);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -15,20 +15,18 @@
|
||||
#include "cli.h"
|
||||
#include "cli-cmd.h"
|
||||
|
||||
|
||||
static int
|
||||
__is_spc (int ch)
|
||||
__is_spc(int ch)
|
||||
{
|
||||
if (ch == ' ')
|
||||
return 1;
|
||||
return 0;
|
||||
if (ch == ' ')
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
__is_div (int ch)
|
||||
__is_div(int ch)
|
||||
{
|
||||
switch (ch) {
|
||||
switch (ch) {
|
||||
case '(':
|
||||
case ')':
|
||||
case '<':
|
||||
@ -38,369 +36,356 @@ __is_div (int ch)
|
||||
case '{':
|
||||
case '}':
|
||||
case '|':
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
__is_word (const char *word)
|
||||
__is_word(const char *word)
|
||||
{
|
||||
return (!__is_div (*word) && !__is_spc (*word));
|
||||
return (!__is_div(*word) && !__is_spc(*word));
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
counter_char (int ch)
|
||||
counter_char(int ch)
|
||||
{
|
||||
switch (ch) {
|
||||
switch (ch) {
|
||||
case '(':
|
||||
return ')';
|
||||
return ')';
|
||||
case '<':
|
||||
return '>';
|
||||
return '>';
|
||||
case '[':
|
||||
return ']';
|
||||
return ']';
|
||||
case '{':
|
||||
return '}';
|
||||
}
|
||||
return '}';
|
||||
}
|
||||
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
__is_template_balanced (const char *template)
|
||||
__is_template_balanced(const char *template)
|
||||
{
|
||||
const char *trav = NULL;
|
||||
int ch = 0;
|
||||
const char *trav = NULL;
|
||||
int ch = 0;
|
||||
|
||||
trav = template;
|
||||
trav = template;
|
||||
|
||||
while (*trav) {
|
||||
ch = *trav;
|
||||
while (*trav) {
|
||||
ch = *trav;
|
||||
|
||||
switch (ch) {
|
||||
case '<':
|
||||
case '(':
|
||||
case '[':
|
||||
trav = __is_template_balanced (trav+1);
|
||||
if (!trav)
|
||||
return NULL;
|
||||
if (*trav != counter_char (ch))
|
||||
return NULL;
|
||||
break;
|
||||
case '>':
|
||||
case ')':
|
||||
case ']':
|
||||
return trav;
|
||||
}
|
||||
|
||||
trav++;
|
||||
switch (ch) {
|
||||
case '<':
|
||||
case '(':
|
||||
case '[':
|
||||
trav = __is_template_balanced(trav + 1);
|
||||
if (!trav)
|
||||
return NULL;
|
||||
if (*trav != counter_char(ch))
|
||||
return NULL;
|
||||
break;
|
||||
case '>':
|
||||
case ')':
|
||||
case ']':
|
||||
return trav;
|
||||
}
|
||||
|
||||
return trav;
|
||||
trav++;
|
||||
}
|
||||
|
||||
return trav;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
is_template_balanced (const char *template)
|
||||
is_template_balanced(const char *template)
|
||||
{
|
||||
const char *trav = NULL;
|
||||
const char *trav = NULL;
|
||||
|
||||
trav = __is_template_balanced (template);
|
||||
if (!trav || *trav)
|
||||
return -1;
|
||||
trav = __is_template_balanced(template);
|
||||
if (!trav || *trav)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cli_cmd_token_count (const char *template)
|
||||
cli_cmd_token_count(const char *template)
|
||||
{
|
||||
int count = 0;
|
||||
const char *trav = NULL;
|
||||
int is_alnum = 0;
|
||||
int count = 0;
|
||||
const char *trav = NULL;
|
||||
int is_alnum = 0;
|
||||
|
||||
for (trav = template; *trav; trav++) {
|
||||
switch (*trav) {
|
||||
case '<':
|
||||
case '>':
|
||||
case '(':
|
||||
case ')':
|
||||
case '[':
|
||||
case ']':
|
||||
case '{':
|
||||
case '}':
|
||||
case '|':
|
||||
count++;
|
||||
/* fall through */
|
||||
case ' ':
|
||||
is_alnum = 0;
|
||||
break;
|
||||
default:
|
||||
if (!is_alnum) {
|
||||
is_alnum = 1;
|
||||
count++;
|
||||
}
|
||||
for (trav = template; *trav; trav++) {
|
||||
switch (*trav) {
|
||||
case '<':
|
||||
case '>':
|
||||
case '(':
|
||||
case ')':
|
||||
case '[':
|
||||
case ']':
|
||||
case '{':
|
||||
case '}':
|
||||
case '|':
|
||||
count++;
|
||||
/* fall through */
|
||||
case ' ':
|
||||
is_alnum = 0;
|
||||
break;
|
||||
default:
|
||||
if (!is_alnum) {
|
||||
is_alnum = 1;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count + 1;
|
||||
return count + 1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
cli_cmd_tokens_destroy (char **tokens)
|
||||
cli_cmd_tokens_destroy(char **tokens)
|
||||
{
|
||||
char **tokenp = NULL;
|
||||
char **tokenp = NULL;
|
||||
|
||||
if (!tokens)
|
||||
return;
|
||||
if (!tokens)
|
||||
return;
|
||||
|
||||
tokenp = tokens;
|
||||
while (*tokenp) {
|
||||
free (*tokenp);
|
||||
tokenp++;
|
||||
}
|
||||
tokenp = tokens;
|
||||
while (*tokenp) {
|
||||
free(*tokenp);
|
||||
tokenp++;
|
||||
}
|
||||
|
||||
free (tokens);
|
||||
free(tokens);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cli_cmd_tokens_fill (char **tokens, const char *template)
|
||||
cli_cmd_tokens_fill(char **tokens, const char *template)
|
||||
{
|
||||
const char *trav = NULL;
|
||||
char **tokenp = NULL;
|
||||
char *token = NULL;
|
||||
int ret = 0;
|
||||
int ch = 0;
|
||||
const char *trav = NULL;
|
||||
char **tokenp = NULL;
|
||||
char *token = NULL;
|
||||
int ret = 0;
|
||||
int ch = 0;
|
||||
|
||||
tokenp = tokens;
|
||||
tokenp = tokens;
|
||||
|
||||
for (trav = template; *trav; trav++) {
|
||||
ch = *trav;
|
||||
for (trav = template; *trav; trav++) {
|
||||
ch = *trav;
|
||||
|
||||
if (__is_spc (ch))
|
||||
continue;
|
||||
if (__is_spc(ch))
|
||||
continue;
|
||||
|
||||
if (__is_div (ch)) {
|
||||
token = calloc (2, 1);
|
||||
if (!token)
|
||||
return -1;
|
||||
token[0] = ch;
|
||||
if (__is_div(ch)) {
|
||||
token = calloc(2, 1);
|
||||
if (!token)
|
||||
return -1;
|
||||
token[0] = ch;
|
||||
|
||||
*tokenp = token;
|
||||
tokenp++;
|
||||
*tokenp = token;
|
||||
tokenp++;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
token = strdup (trav);
|
||||
*tokenp = token;
|
||||
tokenp++;
|
||||
|
||||
for (token++; *token; token++) {
|
||||
if (__is_spc (*token) || __is_div (*token)) {
|
||||
*token = 0;
|
||||
break;
|
||||
}
|
||||
trav++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
return ret;
|
||||
token = strdup(trav);
|
||||
*tokenp = token;
|
||||
tokenp++;
|
||||
|
||||
for (token++; *token; token++) {
|
||||
if (__is_spc(*token) || __is_div(*token)) {
|
||||
*token = 0;
|
||||
break;
|
||||
}
|
||||
trav++;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
char **
|
||||
cli_cmd_tokenize (const char *template)
|
||||
cli_cmd_tokenize(const char *template)
|
||||
{
|
||||
char **tokens = NULL;
|
||||
int ret = 0;
|
||||
int count = 0;
|
||||
char **tokens = NULL;
|
||||
int ret = 0;
|
||||
int count = 0;
|
||||
|
||||
ret = is_template_balanced (template);
|
||||
if (ret)
|
||||
return NULL;
|
||||
|
||||
count = cli_cmd_token_count (template);
|
||||
if (count <= 0)
|
||||
return NULL;
|
||||
|
||||
tokens = calloc (count + 1, sizeof (char *));
|
||||
if (!tokens)
|
||||
return NULL;
|
||||
|
||||
ret = cli_cmd_tokens_fill (tokens, template);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
return tokens;
|
||||
err:
|
||||
cli_cmd_tokens_destroy (tokens);
|
||||
ret = is_template_balanced(template);
|
||||
if (ret)
|
||||
return NULL;
|
||||
|
||||
count = cli_cmd_token_count(template);
|
||||
if (count <= 0)
|
||||
return NULL;
|
||||
|
||||
tokens = calloc(count + 1, sizeof(char *));
|
||||
if (!tokens)
|
||||
return NULL;
|
||||
|
||||
ret = cli_cmd_tokens_fill(tokens, template);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
return tokens;
|
||||
err:
|
||||
cli_cmd_tokens_destroy(tokens);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *
|
||||
cli_getunamb (const char *tok, void **choices, cli_selector_t sel)
|
||||
cli_getunamb(const char *tok, void **choices, cli_selector_t sel)
|
||||
{
|
||||
void **wcon = NULL;
|
||||
char *w = NULL;
|
||||
unsigned mn = 0;
|
||||
void *ret = NULL;
|
||||
void **wcon = NULL;
|
||||
char *w = NULL;
|
||||
unsigned mn = 0;
|
||||
void *ret = NULL;
|
||||
|
||||
if (!choices || !tok || !*tok)
|
||||
return NULL;
|
||||
if (!choices || !tok || !*tok)
|
||||
return NULL;
|
||||
|
||||
for (wcon = choices; *wcon; wcon++) {
|
||||
w = strtail ((char *)sel (*wcon), tok);
|
||||
if (!w)
|
||||
/* no match */
|
||||
continue;
|
||||
if (!*w)
|
||||
/* exact match */
|
||||
return *wcon;
|
||||
for (wcon = choices; *wcon; wcon++) {
|
||||
w = strtail((char *)sel(*wcon), tok);
|
||||
if (!w)
|
||||
/* no match */
|
||||
continue;
|
||||
if (!*w)
|
||||
/* exact match */
|
||||
return *wcon;
|
||||
|
||||
ret = *wcon;
|
||||
mn++;
|
||||
}
|
||||
ret = *wcon;
|
||||
mn++;
|
||||
}
|
||||
|
||||
#ifdef FORCE_MATCH_EXACT
|
||||
return NULL;
|
||||
return NULL;
|
||||
#else
|
||||
return (mn == 1) ? ret : NULL;
|
||||
return (mn == 1) ? ret : NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static const char *
|
||||
sel_cmd_word (void *wcon)
|
||||
sel_cmd_word(void *wcon)
|
||||
{
|
||||
return ((struct cli_cmd_word *)wcon)->word;
|
||||
return ((struct cli_cmd_word *)wcon)->word;
|
||||
}
|
||||
|
||||
struct cli_cmd_word *
|
||||
cli_cmd_nextword (struct cli_cmd_word *word, const char *token)
|
||||
cli_cmd_nextword(struct cli_cmd_word *word, const char *token)
|
||||
{
|
||||
return (struct cli_cmd_word *)cli_getunamb (token,
|
||||
(void **)word->nextwords,
|
||||
sel_cmd_word);
|
||||
return (struct cli_cmd_word *)cli_getunamb(token, (void **)word->nextwords,
|
||||
sel_cmd_word);
|
||||
}
|
||||
|
||||
|
||||
struct cli_cmd_word *
|
||||
cli_cmd_newword (struct cli_cmd_word *word, const char *token)
|
||||
cli_cmd_newword(struct cli_cmd_word *word, const char *token)
|
||||
{
|
||||
struct cli_cmd_word **nextwords = NULL;
|
||||
struct cli_cmd_word *nextword = NULL;
|
||||
struct cli_cmd_word **nextwords = NULL;
|
||||
struct cli_cmd_word *nextword = NULL;
|
||||
|
||||
nextwords = realloc (word->nextwords,
|
||||
(word->nextwords_cnt + 2) * sizeof (*nextwords));
|
||||
if (!nextwords)
|
||||
return NULL;
|
||||
nextwords = realloc(word->nextwords,
|
||||
(word->nextwords_cnt + 2) * sizeof(*nextwords));
|
||||
if (!nextwords)
|
||||
return NULL;
|
||||
|
||||
word->nextwords = nextwords;
|
||||
word->nextwords = nextwords;
|
||||
|
||||
nextword = calloc (1, sizeof (*nextword));
|
||||
if (!nextword)
|
||||
return NULL;
|
||||
nextword = calloc(1, sizeof(*nextword));
|
||||
if (!nextword)
|
||||
return NULL;
|
||||
|
||||
nextword->word = strdup (token);
|
||||
if (!nextword->word) {
|
||||
free (nextword);
|
||||
return NULL;
|
||||
}
|
||||
nextword->word = strdup(token);
|
||||
if (!nextword->word) {
|
||||
free(nextword);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nextword->tree = word->tree;
|
||||
nextwords[word->nextwords_cnt++] = nextword;
|
||||
nextwords[word->nextwords_cnt] = NULL;
|
||||
nextword->tree = word->tree;
|
||||
nextwords[word->nextwords_cnt++] = nextword;
|
||||
nextwords[word->nextwords_cnt] = NULL;
|
||||
|
||||
return nextword;
|
||||
return nextword;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cli_cmd_ingest (struct cli_cmd_tree *tree, char **tokens, cli_cmd_cbk_t *cbkfn,
|
||||
const char *desc, const char *pattern)
|
||||
cli_cmd_ingest(struct cli_cmd_tree *tree, char **tokens, cli_cmd_cbk_t *cbkfn,
|
||||
const char *desc, const char *pattern)
|
||||
{
|
||||
int ret = 0;
|
||||
char **tokenp = NULL;
|
||||
char *token = NULL;
|
||||
struct cli_cmd_word *word = NULL;
|
||||
struct cli_cmd_word *next = NULL;
|
||||
int ret = 0;
|
||||
char **tokenp = NULL;
|
||||
char *token = NULL;
|
||||
struct cli_cmd_word *word = NULL;
|
||||
struct cli_cmd_word *next = NULL;
|
||||
|
||||
word = &tree->root;
|
||||
word = &tree->root;
|
||||
|
||||
for (tokenp = tokens; (token = *tokenp); tokenp++) {
|
||||
if (!__is_word (token))
|
||||
break;
|
||||
for (tokenp = tokens; (token = *tokenp); tokenp++) {
|
||||
if (!__is_word(token))
|
||||
break;
|
||||
|
||||
next = cli_cmd_nextword (word, token);
|
||||
if (!next)
|
||||
next = cli_cmd_newword (word, token);
|
||||
|
||||
word = next;
|
||||
if (!word)
|
||||
break;
|
||||
}
|
||||
next = cli_cmd_nextword(word, token);
|
||||
if (!next)
|
||||
next = cli_cmd_newword(word, token);
|
||||
|
||||
word = next;
|
||||
if (!word)
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (word->cbkfn) {
|
||||
/* warning - command already registered */
|
||||
}
|
||||
if (!word)
|
||||
return -1;
|
||||
|
||||
word->cbkfn = cbkfn;
|
||||
word->desc = desc;
|
||||
word->pattern = pattern;
|
||||
if (word->cbkfn) {
|
||||
/* warning - command already registered */
|
||||
}
|
||||
|
||||
/* end of static strings in command template */
|
||||
word->cbkfn = cbkfn;
|
||||
word->desc = desc;
|
||||
word->pattern = pattern;
|
||||
|
||||
/* TODO: autocompletion beyond this point is just "nice to have" */
|
||||
/* end of static strings in command template */
|
||||
|
||||
return ret;
|
||||
/* TODO: autocompletion beyond this point is just "nice to have" */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cli_cmd_register (struct cli_cmd_tree *tree, struct cli_cmd *cmd)
|
||||
cli_cmd_register(struct cli_cmd_tree *tree, struct cli_cmd *cmd)
|
||||
{
|
||||
char **tokens = NULL;
|
||||
int ret = 0;
|
||||
char **tokens = NULL;
|
||||
int ret = 0;
|
||||
|
||||
GF_ASSERT (cmd);
|
||||
GF_ASSERT(cmd);
|
||||
|
||||
if (cmd->reg_cbk)
|
||||
cmd->reg_cbk (cmd);
|
||||
|
||||
if (cmd->disable) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
tokens = cli_cmd_tokenize (cmd->pattern);
|
||||
if (!tokens) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = cli_cmd_ingest (tree, tokens, cmd->cbk, cmd->desc, cmd->pattern);
|
||||
if (ret) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
if (cmd->reg_cbk)
|
||||
cmd->reg_cbk(cmd);
|
||||
|
||||
if (cmd->disable) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
tokens = cli_cmd_tokenize(cmd->pattern);
|
||||
if (!tokens) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = cli_cmd_ingest(tree, tokens, cmd->cbk, cmd->desc, cmd->pattern);
|
||||
if (ret) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
if (tokens)
|
||||
cli_cmd_tokens_destroy (tokens);
|
||||
if (tokens)
|
||||
cli_cmd_tokens_destroy(tokens);
|
||||
|
||||
gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret);
|
||||
return ret;
|
||||
gf_log("cli", GF_LOG_DEBUG, "Returning %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -25,365 +25,338 @@
|
||||
#include <sys/time.h>
|
||||
|
||||
struct state {
|
||||
char need_op_write:1;
|
||||
char need_op_read:1;
|
||||
char need_op_write : 1;
|
||||
char need_op_read : 1;
|
||||
|
||||
char need_iface_fileio:1;
|
||||
char need_iface_xattr:1;
|
||||
char need_iface_fileio : 1;
|
||||
char need_iface_xattr : 1;
|
||||
|
||||
char need_mode_posix:1;
|
||||
char need_mode_posix : 1;
|
||||
|
||||
char prefix[512];
|
||||
long int count;
|
||||
char prefix[512];
|
||||
long int count;
|
||||
|
||||
size_t block_size;
|
||||
size_t block_size;
|
||||
|
||||
char *specfile;
|
||||
char *specfile;
|
||||
|
||||
long int io_size;
|
||||
long int io_size;
|
||||
};
|
||||
|
||||
|
||||
#define MEASURE(func, arg) measure (func, #func, arg)
|
||||
|
||||
#define MEASURE(func, arg) measure(func, #func, arg)
|
||||
|
||||
void
|
||||
tv_difference (struct timeval *tv_stop,
|
||||
struct timeval *tv_start,
|
||||
struct timeval *tv_diff)
|
||||
tv_difference(struct timeval *tv_stop, struct timeval *tv_start,
|
||||
struct timeval *tv_diff)
|
||||
{
|
||||
if (tv_stop->tv_usec < tv_start->tv_usec) {
|
||||
tv_diff->tv_usec = (tv_stop->tv_usec + 1000000) - tv_start->tv_usec;
|
||||
tv_diff->tv_sec = (tv_stop->tv_sec - 1 - tv_start->tv_sec);
|
||||
} else {
|
||||
tv_diff->tv_usec = tv_stop->tv_usec - tv_start->tv_usec;
|
||||
tv_diff->tv_sec = tv_stop->tv_sec - tv_start->tv_sec;
|
||||
}
|
||||
if (tv_stop->tv_usec < tv_start->tv_usec) {
|
||||
tv_diff->tv_usec = (tv_stop->tv_usec + 1000000) - tv_start->tv_usec;
|
||||
tv_diff->tv_sec = (tv_stop->tv_sec - 1 - tv_start->tv_sec);
|
||||
} else {
|
||||
tv_diff->tv_usec = tv_stop->tv_usec - tv_start->tv_usec;
|
||||
tv_diff->tv_sec = tv_stop->tv_sec - tv_start->tv_sec;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
measure (int (*func)(struct state *state),
|
||||
char *func_name, struct state *state)
|
||||
measure(int (*func)(struct state *state), char *func_name, struct state *state)
|
||||
{
|
||||
struct timeval tv_start, tv_stop, tv_diff;
|
||||
state->io_size = 0;
|
||||
long int count;
|
||||
struct timeval tv_start, tv_stop, tv_diff;
|
||||
state->io_size = 0;
|
||||
long int count;
|
||||
|
||||
gettimeofday (&tv_start, NULL);
|
||||
count = func (state);
|
||||
gettimeofday (&tv_stop, NULL);
|
||||
gettimeofday(&tv_start, NULL);
|
||||
count = func(state);
|
||||
gettimeofday(&tv_stop, NULL);
|
||||
|
||||
tv_difference (&tv_stop, &tv_start, &tv_diff);
|
||||
tv_difference(&tv_stop, &tv_start, &tv_diff);
|
||||
|
||||
fprintf (stdout, "%s: count=%ld, size=%ld, time=%ld:%ld\n",
|
||||
func_name, count, state->io_size,
|
||||
tv_diff.tv_sec, tv_diff.tv_usec);
|
||||
fprintf(stdout, "%s: count=%ld, size=%ld, time=%ld:%ld\n", func_name, count,
|
||||
state->io_size, tv_diff.tv_sec, tv_diff.tv_usec);
|
||||
}
|
||||
|
||||
|
||||
static error_t
|
||||
parse_opts (int key, char *arg,
|
||||
struct argp_state *_state)
|
||||
parse_opts(int key, char *arg, struct argp_state *_state)
|
||||
{
|
||||
struct state *state = _state->input;
|
||||
struct state *state = _state->input;
|
||||
|
||||
switch (key)
|
||||
{
|
||||
switch (key) {
|
||||
case 'o':
|
||||
if (strcasecmp (arg, "read") == 0) {
|
||||
state->need_op_write = 0;
|
||||
state->need_op_read = 1;
|
||||
} else if (strcasecmp (arg, "write") == 0) {
|
||||
state->need_op_write = 1;
|
||||
state->need_op_read = 0;
|
||||
} else if (strcasecmp (arg, "both") == 0) {
|
||||
state->need_op_write = 1;
|
||||
state->need_op_read = 1;
|
||||
} else {
|
||||
fprintf (stderr, "unknown op: %s\n", arg);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
if (strcasecmp(arg, "read") == 0) {
|
||||
state->need_op_write = 0;
|
||||
state->need_op_read = 1;
|
||||
} else if (strcasecmp(arg, "write") == 0) {
|
||||
state->need_op_write = 1;
|
||||
state->need_op_read = 0;
|
||||
} else if (strcasecmp(arg, "both") == 0) {
|
||||
state->need_op_write = 1;
|
||||
state->need_op_read = 1;
|
||||
} else {
|
||||
fprintf(stderr, "unknown op: %s\n", arg);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
if (strcasecmp (arg, "fileio") == 0) {
|
||||
state->need_iface_fileio = 1;
|
||||
state->need_iface_xattr = 0;
|
||||
} else if (strcasecmp (arg, "xattr") == 0) {
|
||||
state->need_iface_fileio = 0;
|
||||
state->need_iface_xattr = 1;
|
||||
} else if (strcasecmp (arg, "both") == 0) {
|
||||
state->need_iface_fileio = 1;
|
||||
state->need_iface_xattr = 1;
|
||||
} else {
|
||||
fprintf (stderr, "unknown interface: %s\n", arg);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
{
|
||||
size_t block_size = atoi (arg);
|
||||
if (!block_size) {
|
||||
fprintf (stderr, "incorrect size: %s\n", arg);
|
||||
return -1;
|
||||
}
|
||||
state->block_size = block_size;
|
||||
}
|
||||
break;
|
||||
if (strcasecmp(arg, "fileio") == 0) {
|
||||
state->need_iface_fileio = 1;
|
||||
state->need_iface_xattr = 0;
|
||||
} else if (strcasecmp(arg, "xattr") == 0) {
|
||||
state->need_iface_fileio = 0;
|
||||
state->need_iface_xattr = 1;
|
||||
} else if (strcasecmp(arg, "both") == 0) {
|
||||
state->need_iface_fileio = 1;
|
||||
state->need_iface_xattr = 1;
|
||||
} else {
|
||||
fprintf(stderr, "unknown interface: %s\n", arg);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 'b': {
|
||||
size_t block_size = atoi(arg);
|
||||
if (!block_size) {
|
||||
fprintf(stderr, "incorrect size: %s\n", arg);
|
||||
return -1;
|
||||
}
|
||||
state->block_size = block_size;
|
||||
} break;
|
||||
case 's':
|
||||
state->specfile = strdup (arg);
|
||||
break;
|
||||
state->specfile = strdup(arg);
|
||||
break;
|
||||
case 'p':
|
||||
fprintf (stderr, "using prefix: %s\n", arg);
|
||||
strncpy (state->prefix, arg, 512);
|
||||
break;
|
||||
case 'c':
|
||||
{
|
||||
long count = atol (arg);
|
||||
if (!count) {
|
||||
fprintf (stderr, "incorrect count: %s\n", arg);
|
||||
return -1;
|
||||
}
|
||||
state->count = count;
|
||||
}
|
||||
break;
|
||||
fprintf(stderr, "using prefix: %s\n", arg);
|
||||
strncpy(state->prefix, arg, 512);
|
||||
break;
|
||||
case 'c': {
|
||||
long count = atol(arg);
|
||||
if (!count) {
|
||||
fprintf(stderr, "incorrect count: %s\n", arg);
|
||||
return -1;
|
||||
}
|
||||
state->count = count;
|
||||
} break;
|
||||
case ARGP_KEY_NO_ARGS:
|
||||
break;
|
||||
break;
|
||||
case ARGP_KEY_ARG:
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
do_mode_posix_iface_fileio_write(struct state *state)
|
||||
{
|
||||
long int i;
|
||||
int ret = -1;
|
||||
char block[state->block_size];
|
||||
|
||||
for (i = 0; i < state->count; i++) {
|
||||
int fd = -1;
|
||||
char filename[512];
|
||||
|
||||
sprintf(filename, "%s.%06ld", state->prefix, i);
|
||||
|
||||
fd = open(filename, O_CREAT | O_WRONLY, 00600);
|
||||
if (fd == -1) {
|
||||
fprintf(stderr, "open(%s) => %s\n", filename, strerror(errno));
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
do_mode_posix_iface_fileio_write (struct state *state)
|
||||
{
|
||||
long int i;
|
||||
int ret = -1;
|
||||
char block[state->block_size];
|
||||
|
||||
for (i=0; i<state->count; i++) {
|
||||
int fd = -1;
|
||||
char filename[512];
|
||||
|
||||
sprintf (filename, "%s.%06ld", state->prefix, i);
|
||||
|
||||
fd = open (filename, O_CREAT|O_WRONLY, 00600);
|
||||
if (fd == -1) {
|
||||
fprintf (stderr, "open(%s) => %s\n", filename, strerror (errno));
|
||||
break;
|
||||
}
|
||||
ret = write (fd, block, state->block_size);
|
||||
if (ret != state->block_size) {
|
||||
fprintf (stderr, "write (%s) => %d/%s\n", filename, ret,
|
||||
strerror (errno));
|
||||
close (fd);
|
||||
break;
|
||||
}
|
||||
close (fd);
|
||||
state->io_size += ret;
|
||||
ret = write(fd, block, state->block_size);
|
||||
if (ret != state->block_size) {
|
||||
fprintf(stderr, "write (%s) => %d/%s\n", filename, ret,
|
||||
strerror(errno));
|
||||
close(fd);
|
||||
break;
|
||||
}
|
||||
close(fd);
|
||||
state->io_size += ret;
|
||||
}
|
||||
|
||||
return i;
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
do_mode_posix_iface_fileio_read (struct state *state)
|
||||
do_mode_posix_iface_fileio_read(struct state *state)
|
||||
{
|
||||
long int i;
|
||||
int ret = -1;
|
||||
char block[state->block_size];
|
||||
long int i;
|
||||
int ret = -1;
|
||||
char block[state->block_size];
|
||||
|
||||
for (i=0; i<state->count; i++) {
|
||||
int fd = -1;
|
||||
char filename[512];
|
||||
for (i = 0; i < state->count; i++) {
|
||||
int fd = -1;
|
||||
char filename[512];
|
||||
|
||||
sprintf (filename, "%s.%06ld", state->prefix, i);
|
||||
sprintf(filename, "%s.%06ld", state->prefix, i);
|
||||
|
||||
fd = open (filename, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
fprintf (stderr, "open(%s) => %s\n", filename, strerror (errno));
|
||||
break;
|
||||
}
|
||||
ret = read (fd, block, state->block_size);
|
||||
if (ret == -1) {
|
||||
fprintf (stderr, "read(%s) => %d/%s\n", filename, ret, strerror (errno));
|
||||
close (fd);
|
||||
break;
|
||||
}
|
||||
close (fd);
|
||||
state->io_size += ret;
|
||||
fd = open(filename, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
fprintf(stderr, "open(%s) => %s\n", filename, strerror(errno));
|
||||
break;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
do_mode_posix_iface_fileio (struct state *state)
|
||||
{
|
||||
if (state->need_op_write)
|
||||
MEASURE (do_mode_posix_iface_fileio_write, state);
|
||||
|
||||
if (state->need_op_read)
|
||||
MEASURE (do_mode_posix_iface_fileio_read, state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
do_mode_posix_iface_xattr_write (struct state *state)
|
||||
{
|
||||
long int i;
|
||||
int ret = -1;
|
||||
char block[state->block_size];
|
||||
char *dname = NULL, *dirc = NULL;
|
||||
char *bname = NULL, *basec = NULL;
|
||||
|
||||
dirc = strdup (state->prefix);
|
||||
basec = strdup (state->prefix);
|
||||
dname = dirname (dirc);
|
||||
bname = basename (basec);
|
||||
|
||||
for (i=0; i<state->count; i++) {
|
||||
char key[512];
|
||||
|
||||
sprintf (key, "glusterfs.file.%s.%06ld", bname, i);
|
||||
|
||||
ret = lsetxattr (dname, key, block, state->block_size, 0);
|
||||
|
||||
if (ret != 0) {
|
||||
fprintf (stderr, "lsetxattr (%s, %s, %p) => %s\n",
|
||||
dname, key, block, strerror (errno));
|
||||
break;
|
||||
}
|
||||
state->io_size += state->block_size;
|
||||
ret = read(fd, block, state->block_size);
|
||||
if (ret == -1) {
|
||||
fprintf(stderr, "read(%s) => %d/%s\n", filename, ret,
|
||||
strerror(errno));
|
||||
close(fd);
|
||||
break;
|
||||
}
|
||||
close(fd);
|
||||
state->io_size += ret;
|
||||
}
|
||||
|
||||
free (dirc);
|
||||
free (basec);
|
||||
|
||||
return i;
|
||||
return i;
|
||||
}
|
||||
|
||||
int
|
||||
do_mode_posix_iface_fileio(struct state *state)
|
||||
{
|
||||
if (state->need_op_write)
|
||||
MEASURE(do_mode_posix_iface_fileio_write, state);
|
||||
|
||||
if (state->need_op_read)
|
||||
MEASURE(do_mode_posix_iface_fileio_read, state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
do_mode_posix_iface_xattr_read (struct state *state)
|
||||
do_mode_posix_iface_xattr_write(struct state *state)
|
||||
{
|
||||
long int i;
|
||||
int ret = -1;
|
||||
char block[state->block_size];
|
||||
char *dname = NULL, *dirc = NULL;
|
||||
char *bname = NULL, *basec = NULL;
|
||||
long int i;
|
||||
int ret = -1;
|
||||
char block[state->block_size];
|
||||
char *dname = NULL, *dirc = NULL;
|
||||
char *bname = NULL, *basec = NULL;
|
||||
|
||||
dirc = strdup (state->prefix);
|
||||
basec = strdup (state->prefix);
|
||||
dname = dirname (dirc);
|
||||
bname = basename (basec);
|
||||
dirc = strdup(state->prefix);
|
||||
basec = strdup(state->prefix);
|
||||
dname = dirname(dirc);
|
||||
bname = basename(basec);
|
||||
|
||||
for (i=0; i<state->count; i++) {
|
||||
char key[512];
|
||||
for (i = 0; i < state->count; i++) {
|
||||
char key[512];
|
||||
|
||||
sprintf (key, "glusterfs.file.%s.%06ld", bname, i);
|
||||
sprintf(key, "glusterfs.file.%s.%06ld", bname, i);
|
||||
|
||||
ret = lgetxattr (dname, key, block, state->block_size);
|
||||
ret = lsetxattr(dname, key, block, state->block_size, 0);
|
||||
|
||||
if (ret < 0) {
|
||||
fprintf (stderr, "lgetxattr (%s, %s, %p) => %s\n",
|
||||
dname, key, block, strerror (errno));
|
||||
break;
|
||||
}
|
||||
state->io_size += ret;
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "lsetxattr (%s, %s, %p) => %s\n", dname, key, block,
|
||||
strerror(errno));
|
||||
break;
|
||||
}
|
||||
state->io_size += state->block_size;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
free(dirc);
|
||||
free(basec);
|
||||
|
||||
|
||||
int
|
||||
do_mode_posix_iface_xattr (struct state *state)
|
||||
{
|
||||
if (state->need_op_write)
|
||||
MEASURE (do_mode_posix_iface_xattr_write, state);
|
||||
|
||||
if (state->need_op_read)
|
||||
MEASURE (do_mode_posix_iface_xattr_read, state);
|
||||
|
||||
return 0;
|
||||
return i;
|
||||
}
|
||||
|
||||
int
|
||||
do_mode_posix (struct state *state)
|
||||
do_mode_posix_iface_xattr_read(struct state *state)
|
||||
{
|
||||
if (state->need_iface_fileio)
|
||||
do_mode_posix_iface_fileio (state);
|
||||
long int i;
|
||||
int ret = -1;
|
||||
char block[state->block_size];
|
||||
char *dname = NULL, *dirc = NULL;
|
||||
char *bname = NULL, *basec = NULL;
|
||||
|
||||
if (state->need_iface_xattr)
|
||||
do_mode_posix_iface_xattr (state);
|
||||
dirc = strdup(state->prefix);
|
||||
basec = strdup(state->prefix);
|
||||
dname = dirname(dirc);
|
||||
bname = basename(basec);
|
||||
|
||||
return 0;
|
||||
for (i = 0; i < state->count; i++) {
|
||||
char key[512];
|
||||
|
||||
sprintf(key, "glusterfs.file.%s.%06ld", bname, i);
|
||||
|
||||
ret = lgetxattr(dname, key, block, state->block_size);
|
||||
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "lgetxattr (%s, %s, %p) => %s\n", dname, key, block,
|
||||
strerror(errno));
|
||||
break;
|
||||
}
|
||||
state->io_size += ret;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
int
|
||||
do_mode_posix_iface_xattr(struct state *state)
|
||||
{
|
||||
if (state->need_op_write)
|
||||
MEASURE(do_mode_posix_iface_xattr_write, state);
|
||||
|
||||
if (state->need_op_read)
|
||||
MEASURE(do_mode_posix_iface_xattr_read, state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
do_actions (struct state *state)
|
||||
do_mode_posix(struct state *state)
|
||||
{
|
||||
if (state->need_mode_posix)
|
||||
do_mode_posix (state);
|
||||
if (state->need_iface_fileio)
|
||||
do_mode_posix_iface_fileio(state);
|
||||
|
||||
return 0;
|
||||
if (state->need_iface_xattr)
|
||||
do_mode_posix_iface_xattr(state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
do_actions(struct state *state)
|
||||
{
|
||||
if (state->need_mode_posix)
|
||||
do_mode_posix(state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct argp_option options[] = {
|
||||
{"op", 'o', "OPERATIONS", 0,
|
||||
"WRITE|READ|BOTH - defaults to BOTH"},
|
||||
{"iface", 'i', "INTERFACE", 0,
|
||||
"FILEIO|XATTR|BOTH - defaults to FILEIO"},
|
||||
{"block", 'b', "BLOCKSIZE", 0,
|
||||
"<NUM> - defaults to 4096"},
|
||||
{"specfile", 's', "SPECFILE", 0,
|
||||
"absolute path to specfile"},
|
||||
{"prefix", 'p', "PREFIX", 0,
|
||||
"filename prefix"},
|
||||
{"count", 'c', "COUNT", 0,
|
||||
"number of files"},
|
||||
{0, 0, 0, 0, 0}
|
||||
};
|
||||
{"op", 'o', "OPERATIONS", 0, "WRITE|READ|BOTH - defaults to BOTH"},
|
||||
{"iface", 'i', "INTERFACE", 0, "FILEIO|XATTR|BOTH - defaults to FILEIO"},
|
||||
{"block", 'b', "BLOCKSIZE", 0, "<NUM> - defaults to 4096"},
|
||||
{"specfile", 's', "SPECFILE", 0, "absolute path to specfile"},
|
||||
{"prefix", 'p', "PREFIX", 0, "filename prefix"},
|
||||
{"count", 'c', "COUNT", 0, "number of files"},
|
||||
{0, 0, 0, 0, 0}};
|
||||
|
||||
static struct argp argp = {
|
||||
options,
|
||||
parse_opts,
|
||||
"tool",
|
||||
"tool to benchmark small file performance"
|
||||
};
|
||||
static struct argp argp = {options, parse_opts, "tool",
|
||||
"tool to benchmark small file performance"};
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct state state = {0, };
|
||||
struct state state = {
|
||||
0,
|
||||
};
|
||||
|
||||
state.need_op_write = 1;
|
||||
state.need_op_read = 1;
|
||||
state.need_op_write = 1;
|
||||
state.need_op_read = 1;
|
||||
|
||||
state.need_iface_fileio = 1;
|
||||
state.need_iface_xattr = 0;
|
||||
state.need_iface_fileio = 1;
|
||||
state.need_iface_xattr = 0;
|
||||
|
||||
state.need_mode_posix = 1;
|
||||
state.need_mode_posix = 1;
|
||||
|
||||
state.block_size = 4096;
|
||||
state.block_size = 4096;
|
||||
|
||||
strcpy (state.prefix, "tmpfile");
|
||||
state.count = 1048576;
|
||||
strcpy(state.prefix, "tmpfile");
|
||||
state.count = 1048576;
|
||||
|
||||
if (argp_parse (&argp, argc, argv, 0, 0, &state) != 0) {
|
||||
fprintf (stderr, "argp_parse() failed\n");
|
||||
return 1;
|
||||
}
|
||||
if (argp_parse(&argp, argc, argv, 0, 0, &state) != 0) {
|
||||
fprintf(stderr, "argp_parse() failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
do_actions (&state);
|
||||
do_actions(&state);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,37 +1,32 @@
|
||||
#pragma fragment CBK_TEMPLATE
|
||||
int32_t
|
||||
@FOP_PREFIX@_@NAME@_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
|
||||
int32_t op_ret, int32_t op_errno, @UNWIND_PARAMS@)
|
||||
int32_t @FOP_PREFIX @_ @NAME
|
||||
@_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret,
|
||||
int32_t op_errno, @UNWIND_PARAMS @)
|
||||
{
|
||||
STACK_UNWIND_STRICT (@NAME@, frame, op_ret, op_errno,
|
||||
@UNWIND_ARGS@);
|
||||
return 0;
|
||||
STACK_UNWIND_STRICT(@NAME @, frame, op_ret, op_errno, @UNWIND_ARGS @);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#pragma fragment COMMENT
|
||||
If you are generating the leaf xlators, remove the STACK_WIND
|
||||
and replace the @ERROR_ARGS@ to @UNWIND_ARGS@ if necessary
|
||||
If you are generating the leaf xlators, remove the STACK_WIND and replace the
|
||||
@ERROR_ARGS @to @UNWIND_ARGS @ if necessary
|
||||
|
||||
#pragma fragment FOP_TEMPLATE
|
||||
int32_t
|
||||
@FOP_PREFIX@_@NAME@ (call_frame_t *frame, xlator_t *this,
|
||||
@WIND_PARAMS@)
|
||||
int32_t @FOP_PREFIX @_ @NAME
|
||||
@(call_frame_t *frame, xlator_t *this, @WIND_PARAMS @)
|
||||
{
|
||||
STACK_WIND (frame, @FOP_PREFIX@_@NAME@_cbk,
|
||||
FIRST_CHILD(this), FIRST_CHILD(this)->fops->@NAME@,
|
||||
@WIND_ARGS@);
|
||||
return 0;
|
||||
STACK_WIND(frame, @FOP_PREFIX @_ @NAME @_cbk, FIRST_CHILD(this),
|
||||
FIRST_CHILD(this)->fops->@NAME @, @WIND_ARGS @);
|
||||
return 0;
|
||||
err:
|
||||
STACK_UNWIND_STRICT (@NAME@, frame, -1, errno,
|
||||
@ERROR_ARGS@);
|
||||
return 0;
|
||||
STACK_UNWIND_STRICT(@NAME @, frame, -1, errno, @ERROR_ARGS @);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#pragma fragment FUNC_TEMPLATE
|
||||
@RET_TYPE@
|
||||
@FOP_PREFIX@_@NAME@ (@FUNC_PARAMS@)
|
||||
@RET_TYPE @ @FOP_PREFIX @_ @NAME @(@FUNC_PARAMS @)
|
||||
{
|
||||
return @RET_VAR@;
|
||||
return @RET_VAR @;
|
||||
}
|
||||
|
||||
#pragma fragment CP
|
||||
@ -50,77 +45,71 @@ err:
|
||||
|
||||
#pragma fragment XLATOR_METHODS
|
||||
|
||||
static int32_t
|
||||
@FOP_PREFIX@_init (xlator_t *this)
|
||||
static int32_t @FOP_PREFIX @_init(xlator_t *this)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@FOP_PREFIX@_fini (xlator_t *this)
|
||||
static void @FOP_PREFIX @_fini(xlator_t *this)
|
||||
{
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
static int32_t
|
||||
@FOP_PREFIX@_reconfigure (xlator_t *this, dict_t *dict)
|
||||
static int32_t @FOP_PREFIX @_reconfigure(xlator_t *this, dict_t *dict)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
@FOP_PREFIX@_notify (xlator_t *this, int event, void *data, ...)
|
||||
static int @FOP_PREFIX @_notify(xlator_t *this, int event, void *data, ...)
|
||||
{
|
||||
return default_notify (this, event, data);
|
||||
return default_notify(this, event, data);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
@FOP_PREFIX@_mem_acct_init (xlator_t *this)
|
||||
static int32_t @FOP_PREFIX @_mem_acct_init(xlator_t *this)
|
||||
{
|
||||
int ret = -1;
|
||||
int ret = -1;
|
||||
|
||||
ret = xlator_mem_acct_init (this, gf_@FOP_PREFIX@_mt_end + 1);
|
||||
return ret;
|
||||
ret = xlator_mem_acct_init(this, gf_ @FOP_PREFIX @_mt_end + 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int32_t
|
||||
@FOP_PREFIX@_dump_metrics (xlator_t *this, int fd)
|
||||
static int32_t @FOP_PREFIX @_dump_metrics(xlator_t *this, int fd)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct volume_options @FOP_PREFIX@_options[] = {
|
||||
/*{ .key = {""},
|
||||
.type = GF_OPTION_TYPE_BOOL,
|
||||
.default_value = "",
|
||||
.op_version = {GD_OP_VERSION_},
|
||||
.flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC | OPT_FLAG_CLIENT_OPT,
|
||||
.tags = {""},
|
||||
.description = "",
|
||||
.category = GF_EXPERIMENTAL,
|
||||
},
|
||||
{ .key = {NULL} },
|
||||
*/
|
||||
struct volume_options @FOP_PREFIX @_options[] = {
|
||||
/*{ .key = {""},
|
||||
.type = GF_OPTION_TYPE_BOOL,
|
||||
.default_value = "",
|
||||
.op_version = {GD_OP_VERSION_},
|
||||
.flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC | OPT_FLAG_CLIENT_OPT,
|
||||
.tags = {""},
|
||||
.description = "",
|
||||
.category = GF_EXPERIMENTAL,
|
||||
},
|
||||
{ .key = {NULL} },
|
||||
*/
|
||||
};
|
||||
|
||||
xlator_api_t xlator_api = {
|
||||
.init = @FOP_PREFIX@_init,
|
||||
.fini = @FOP_PREFIX@_fini,
|
||||
.notify = @FOP_PREFIX@_notify,
|
||||
.reconfigure = @FOP_PREFIX@_reconfigure,
|
||||
.mem_acct_init = @FOP_PREFIX@_mem_acct_init,
|
||||
.dump_metrics = @FOP_PREFIX@_dump_metrics,
|
||||
.op_version = {GD_OP_VERSION_},
|
||||
.dumpops = &@FOP_PREFIX@_dumpops,
|
||||
.fops = &@FOP_PREFIX@_fops,
|
||||
.cbks = &@FOP_PREFIX@_cbks,
|
||||
.options = @FOP_PREFIX@_options,
|
||||
.identifier = "@XL_NAME@",
|
||||
.category = GF_EXPERIMENTAL,
|
||||
.init = @FOP_PREFIX @_init,
|
||||
.fini = @FOP_PREFIX @_fini,
|
||||
.notify = @FOP_PREFIX @_notify,
|
||||
.reconfigure = @FOP_PREFIX @_reconfigure,
|
||||
.mem_acct_init = @FOP_PREFIX @_mem_acct_init,
|
||||
.dump_metrics = @FOP_PREFIX @_dump_metrics,
|
||||
.op_version = {GD_OP_VERSION_},
|
||||
.dumpops = &@FOP_PREFIX @_dumpops,
|
||||
.fops = &@FOP_PREFIX @_fops,
|
||||
.cbks = &@FOP_PREFIX @_cbks,
|
||||
.options = @FOP_PREFIX @_options,
|
||||
.identifier = "@XL_NAME@",
|
||||
.category = GF_EXPERIMENTAL,
|
||||
};
|
||||
#pragma fragment HEADER_FMT
|
||||
#ifndef __@HFL_NAME@_H__
|
||||
#define __@HFL_NAME@_H__
|
||||
#ifndef __ @HFL_NAME @_H__
|
||||
#define __ @HFL_NAME @_H__
|
||||
|
||||
#include "@XL_NAME@-mem-types.h"
|
||||
#include "@XL_NAME@-messages.h"
|
||||
@ -131,21 +120,21 @@ xlator_api_t xlator_api = {
|
||||
#endif /* __@HFL_NAME@_H__ */
|
||||
|
||||
#pragma fragment MEM_HEADER_FMT
|
||||
#ifndef __@HFL_NAME@_H__
|
||||
#define __@HFL_NAME@_H__
|
||||
#ifndef __ @HFL_NAME @_H__
|
||||
#define __ @HFL_NAME @_H__
|
||||
|
||||
#include "mem-types.h"
|
||||
|
||||
enum gf_mdc_mem_types_ {
|
||||
gf_@FOP_PREFIX@_mt_ = gf_common_mt_end + 1,
|
||||
gf_@FOP_PREFIX@_mt_end
|
||||
gf_ @FOP_PREFIX @_mt_ = gf_common_mt_end + 1,
|
||||
gf_ @FOP_PREFIX @_mt_end
|
||||
};
|
||||
|
||||
#endif /* __@HFL_NAME@_H__ */
|
||||
|
||||
#pragma fragment MSG_HEADER_FMT
|
||||
#ifndef __@HFL_NAME@_H__
|
||||
#define __@HFL_NAME@_H__
|
||||
#ifndef __ @HFL_NAME @_H__
|
||||
#define __ @HFL_NAME @_H__
|
||||
|
||||
#include "glfs-message-id.h"
|
||||
|
||||
@ -159,8 +148,6 @@ enum gf_mdc_mem_types_ {
|
||||
* glfs-message-id.h.
|
||||
*/
|
||||
|
||||
GLFS_MSGID(@FOP_PREFIX@,
|
||||
@FOP_PREFIX@_MSG_NO_MEMORY
|
||||
);
|
||||
GLFS_MSGID(@FOP_PREFIX @, @FOP_PREFIX @_MSG_NO_MEMORY);
|
||||
|
||||
#endif /* __@HFL_NAME@_H__ */
|
||||
|
@ -15,96 +15,95 @@
|
||||
#endif
|
||||
|
||||
#ifndef GF_FUSE_AUX_GFID_HEAL
|
||||
#define GF_FUSE_AUX_GFID_HEAL "glusterfs.gfid.heal"
|
||||
#define GF_FUSE_AUX_GFID_HEAL "glusterfs.gfid.heal"
|
||||
#endif
|
||||
|
||||
#define GLFS_LINE_MAX (PATH_MAX + (2 * UUID_CANONICAL_FORM_LEN))
|
||||
#define GLFS_LINE_MAX (PATH_MAX + (2 * UUID_CANONICAL_FORM_LEN))
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
char *file = NULL;
|
||||
char *tmp = NULL;
|
||||
char *tmp1 = NULL;
|
||||
char *parent_dir = NULL;
|
||||
char *gfid = NULL;
|
||||
char *bname = NULL;
|
||||
int ret = -1;
|
||||
int len = 0;
|
||||
FILE *fp = NULL;
|
||||
char line[GLFS_LINE_MAX] = {0,};
|
||||
char *path = NULL;
|
||||
void *blob = NULL;
|
||||
void *tmp_blob = NULL;
|
||||
char *file = NULL;
|
||||
char *tmp = NULL;
|
||||
char *tmp1 = NULL;
|
||||
char *parent_dir = NULL;
|
||||
char *gfid = NULL;
|
||||
char *bname = NULL;
|
||||
int ret = -1;
|
||||
int len = 0;
|
||||
FILE *fp = NULL;
|
||||
char line[GLFS_LINE_MAX] = {
|
||||
0,
|
||||
};
|
||||
char *path = NULL;
|
||||
void *blob = NULL;
|
||||
void *tmp_blob = NULL;
|
||||
|
||||
if (argc != 2) {
|
||||
/* each line in the file has the following format
|
||||
* uuid-in-canonical-form path-relative-to-gluster-mount.
|
||||
* Both uuid and relative path are from master mount.
|
||||
*/
|
||||
fprintf (stderr, "usage: %s <file-of-paths-to-be-synced>\n",
|
||||
argv[0]);
|
||||
goto out;
|
||||
if (argc != 2) {
|
||||
/* each line in the file has the following format
|
||||
* uuid-in-canonical-form path-relative-to-gluster-mount.
|
||||
* Both uuid and relative path are from master mount.
|
||||
*/
|
||||
fprintf(stderr, "usage: %s <file-of-paths-to-be-synced>\n", argv[0]);
|
||||
goto out;
|
||||
}
|
||||
|
||||
file = argv[1];
|
||||
|
||||
fp = fopen(file, "r");
|
||||
if (fp == NULL) {
|
||||
fprintf(stderr, "cannot open %s for reading (%s)\n", file,
|
||||
strerror(errno));
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (fgets(line, GLFS_LINE_MAX, fp) != NULL) {
|
||||
tmp = line;
|
||||
path = gfid = line;
|
||||
|
||||
path += UUID_CANONICAL_FORM_LEN + 1;
|
||||
|
||||
while (isspace(*path))
|
||||
path++;
|
||||
|
||||
len = strlen(line);
|
||||
if ((len < GLFS_LINE_MAX) && (line[len - 1] == '\n'))
|
||||
line[len - 1] = '\0';
|
||||
|
||||
line[UUID_CANONICAL_FORM_LEN] = '\0';
|
||||
|
||||
tmp = strdup(path);
|
||||
tmp1 = strdup(path);
|
||||
parent_dir = dirname(tmp);
|
||||
bname = basename(tmp1);
|
||||
|
||||
/* gfid + '\0' + bname + '\0' */
|
||||
len = UUID_CANONICAL_FORM_LEN + 1 + strlen(bname) + 1;
|
||||
|
||||
blob = malloc(len);
|
||||
|
||||
memcpy(blob, gfid, UUID_CANONICAL_FORM_LEN);
|
||||
|
||||
tmp_blob = blob + UUID_CANONICAL_FORM_LEN + 1;
|
||||
|
||||
memcpy(tmp_blob, bname, strlen(bname));
|
||||
|
||||
ret = sys_lsetxattr(parent_dir, GF_FUSE_AUX_GFID_HEAL, blob, len, 0);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "setxattr on %s/%s failed (%s)\n", parent_dir,
|
||||
bname, strerror(errno));
|
||||
}
|
||||
memset(line, 0, GLFS_LINE_MAX);
|
||||
|
||||
file = argv[1];
|
||||
free(blob);
|
||||
free(tmp);
|
||||
free(tmp1);
|
||||
blob = NULL;
|
||||
}
|
||||
|
||||
fp = fopen (file, "r");
|
||||
if (fp == NULL) {
|
||||
fprintf (stderr, "cannot open %s for reading (%s)\n",
|
||||
file, strerror (errno));
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (fgets (line, GLFS_LINE_MAX, fp) != NULL) {
|
||||
tmp = line;
|
||||
path = gfid = line;
|
||||
|
||||
path += UUID_CANONICAL_FORM_LEN + 1;
|
||||
|
||||
while(isspace (*path))
|
||||
path++;
|
||||
|
||||
len = strlen (line);
|
||||
if ((len < GLFS_LINE_MAX) &&
|
||||
(line[len - 1] == '\n'))
|
||||
line[len - 1] = '\0';
|
||||
|
||||
line[UUID_CANONICAL_FORM_LEN] = '\0';
|
||||
|
||||
tmp = strdup (path);
|
||||
tmp1 = strdup (path);
|
||||
parent_dir = dirname (tmp);
|
||||
bname = basename (tmp1);
|
||||
|
||||
/* gfid + '\0' + bname + '\0' */
|
||||
len = UUID_CANONICAL_FORM_LEN + 1 + strlen (bname) + 1;
|
||||
|
||||
blob = malloc (len);
|
||||
|
||||
memcpy (blob, gfid, UUID_CANONICAL_FORM_LEN);
|
||||
|
||||
tmp_blob = blob + UUID_CANONICAL_FORM_LEN + 1;
|
||||
|
||||
memcpy (tmp_blob, bname, strlen (bname));
|
||||
|
||||
ret = sys_lsetxattr (parent_dir, GF_FUSE_AUX_GFID_HEAL,
|
||||
blob, len, 0);
|
||||
if (ret < 0) {
|
||||
fprintf (stderr, "setxattr on %s/%s failed (%s)\n",
|
||||
parent_dir, bname, strerror (errno));
|
||||
}
|
||||
memset (line, 0, GLFS_LINE_MAX);
|
||||
|
||||
free (blob);
|
||||
free (tmp); free (tmp1);
|
||||
blob = NULL;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
ret = 0;
|
||||
out:
|
||||
if (fp)
|
||||
fclose(fp);
|
||||
return ret;
|
||||
if (fp)
|
||||
fclose(fp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -40,33 +40,33 @@
|
||||
#define INVALID_MODE UINT32_MAX
|
||||
|
||||
struct file_stripe_info {
|
||||
int stripe_count;
|
||||
int stripe_size;
|
||||
int coalesce;
|
||||
mode_t mode;
|
||||
int fd[0];
|
||||
int stripe_count;
|
||||
int stripe_size;
|
||||
int coalesce;
|
||||
mode_t mode;
|
||||
int fd[0];
|
||||
};
|
||||
|
||||
static int close_files(struct file_stripe_info *);
|
||||
static int
|
||||
close_files(struct file_stripe_info *);
|
||||
|
||||
static struct
|
||||
file_stripe_info *alloc_file_stripe_info(int count)
|
||||
static struct file_stripe_info *
|
||||
alloc_file_stripe_info(int count)
|
||||
{
|
||||
int i;
|
||||
struct file_stripe_info *finfo;
|
||||
int i;
|
||||
struct file_stripe_info *finfo;
|
||||
|
||||
finfo = calloc(1, sizeof(struct file_stripe_info) +
|
||||
(sizeof(int) * count));
|
||||
if (!finfo)
|
||||
return NULL;
|
||||
finfo = calloc(1, sizeof(struct file_stripe_info) + (sizeof(int) * count));
|
||||
if (!finfo)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
finfo->fd[i] = INVALID_FD;
|
||||
for (i = 0; i < count; i++)
|
||||
finfo->fd[i] = INVALID_FD;
|
||||
|
||||
finfo->mode = INVALID_MODE;
|
||||
finfo->coalesce = INVALID_FD;
|
||||
finfo->mode = INVALID_MODE;
|
||||
finfo->coalesce = INVALID_FD;
|
||||
|
||||
return finfo;
|
||||
return finfo;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -77,39 +77,39 @@ file_stripe_info *alloc_file_stripe_info(int count)
|
||||
static int
|
||||
get_stripe_attr_name(const char *path, const char *pattern, char **attrname)
|
||||
{
|
||||
char attrbuf[4096];
|
||||
char *ptr, *match = NULL;
|
||||
int len, r, match_count = 0;
|
||||
char attrbuf[4096];
|
||||
char *ptr, *match = NULL;
|
||||
int len, r, match_count = 0;
|
||||
|
||||
if (!path || !pattern || !attrname)
|
||||
return -1;
|
||||
if (!path || !pattern || !attrname)
|
||||
return -1;
|
||||
|
||||
len = listxattr(path, attrbuf, sizeof(attrbuf));
|
||||
if (len < 0)
|
||||
return len;
|
||||
len = listxattr(path, attrbuf, sizeof(attrbuf));
|
||||
if (len < 0)
|
||||
return len;
|
||||
|
||||
ptr = attrbuf;
|
||||
while (ptr) {
|
||||
r = fnmatch(pattern, ptr, 0);
|
||||
if (!r) {
|
||||
if (!match)
|
||||
match = ptr;
|
||||
match_count++;
|
||||
} else if (r != FNM_NOMATCH) {
|
||||
return -1;
|
||||
}
|
||||
ptr = attrbuf;
|
||||
while (ptr) {
|
||||
r = fnmatch(pattern, ptr, 0);
|
||||
if (!r) {
|
||||
if (!match)
|
||||
match = ptr;
|
||||
match_count++;
|
||||
} else if (r != FNM_NOMATCH) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
len -= strlen(ptr) + 1;
|
||||
if (len > 0)
|
||||
ptr += strlen(ptr) + 1;
|
||||
else
|
||||
ptr = NULL;
|
||||
}
|
||||
len -= strlen(ptr) + 1;
|
||||
if (len > 0)
|
||||
ptr += strlen(ptr) + 1;
|
||||
else
|
||||
ptr = NULL;
|
||||
}
|
||||
|
||||
if (match)
|
||||
*attrname = strdup(match);
|
||||
if (match)
|
||||
*attrname = strdup(match);
|
||||
|
||||
return match_count;
|
||||
return match_count;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -118,19 +118,19 @@ get_stripe_attr_name(const char *path, const char *pattern, char **attrname)
|
||||
static int
|
||||
get_stripe_attr_val(const char *path, const char *attr, int *val)
|
||||
{
|
||||
char attrbuf[4096];
|
||||
int len;
|
||||
char attrbuf[4096];
|
||||
int len;
|
||||
|
||||
if (!path || !attr || !val)
|
||||
return -1;
|
||||
if (!path || !attr || !val)
|
||||
return -1;
|
||||
|
||||
len = getxattr(path, attr, attrbuf, sizeof(attrbuf));
|
||||
if (len < 0)
|
||||
return len;
|
||||
len = getxattr(path, attr, attrbuf, sizeof(attrbuf));
|
||||
if (len < 0)
|
||||
return len;
|
||||
|
||||
*val = atoi(attrbuf);
|
||||
*val = atoi(attrbuf);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -145,29 +145,31 @@ get_stripe_attr_val(const char *path, const char *attr, int *val)
|
||||
static int
|
||||
get_attr(const char *path, const char *pattern, char **buf, int *val)
|
||||
{
|
||||
int count = 1;
|
||||
int count = 1;
|
||||
|
||||
if (!buf)
|
||||
return -1;
|
||||
if (!buf)
|
||||
return -1;
|
||||
|
||||
if (!*buf) {
|
||||
count = get_stripe_attr_name(path, pattern, buf);
|
||||
if (count > 1) {
|
||||
/* pattern isn't good enough */
|
||||
fprintf(stderr, "ERROR: duplicate attributes found "
|
||||
"matching pattern: %s\n", pattern);
|
||||
free(*buf);
|
||||
*buf = NULL;
|
||||
return count;
|
||||
} else if (count < 1) {
|
||||
return count;
|
||||
}
|
||||
}
|
||||
if (!*buf) {
|
||||
count = get_stripe_attr_name(path, pattern, buf);
|
||||
if (count > 1) {
|
||||
/* pattern isn't good enough */
|
||||
fprintf(stderr,
|
||||
"ERROR: duplicate attributes found "
|
||||
"matching pattern: %s\n",
|
||||
pattern);
|
||||
free(*buf);
|
||||
*buf = NULL;
|
||||
return count;
|
||||
} else if (count < 1) {
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
if (get_stripe_attr_val(path, *buf, val) < 0)
|
||||
return -1;
|
||||
if (get_stripe_attr_val(path, *buf, val) < 0)
|
||||
return -1;
|
||||
|
||||
return count;
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -178,164 +180,168 @@ get_attr(const char *path, const char *pattern, char **buf, int *val)
|
||||
* print a warning if any files are missing. We proceed without error in the
|
||||
* latter case to support partial recovery.
|
||||
*/
|
||||
static struct
|
||||
file_stripe_info *validate_and_open_files(char *paths[], int count)
|
||||
static struct file_stripe_info *
|
||||
validate_and_open_files(char *paths[], int count)
|
||||
{
|
||||
int i, val, tmp;
|
||||
struct stat sbuf;
|
||||
char *stripe_count_attr = NULL;
|
||||
char *stripe_size_attr = NULL;
|
||||
char *stripe_index_attr = NULL;
|
||||
char *stripe_coalesce_attr = NULL;
|
||||
struct file_stripe_info *finfo = NULL;
|
||||
int i, val, tmp;
|
||||
struct stat sbuf;
|
||||
char *stripe_count_attr = NULL;
|
||||
char *stripe_size_attr = NULL;
|
||||
char *stripe_index_attr = NULL;
|
||||
char *stripe_coalesce_attr = NULL;
|
||||
struct file_stripe_info *finfo = NULL;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (!paths[i])
|
||||
goto err;
|
||||
for (i = 0; i < count; i++) {
|
||||
if (!paths[i])
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* Check the stripe count first so we can allocate the info
|
||||
* struct with the appropriate number of fds.
|
||||
*/
|
||||
if (get_attr(paths[i], ATTRNAME_STRIPE_COUNT,
|
||||
&stripe_count_attr, &val) != 1) {
|
||||
fprintf(stderr, "ERROR: %s: attribute: '%s'\n",
|
||||
paths[i], ATTRNAME_STRIPE_COUNT);
|
||||
goto err;
|
||||
}
|
||||
if (!finfo) {
|
||||
finfo = alloc_file_stripe_info(val);
|
||||
if (!finfo)
|
||||
goto err;
|
||||
/*
|
||||
* Check the stripe count first so we can allocate the info
|
||||
* struct with the appropriate number of fds.
|
||||
*/
|
||||
if (get_attr(paths[i], ATTRNAME_STRIPE_COUNT, &stripe_count_attr,
|
||||
&val) != 1) {
|
||||
fprintf(stderr, "ERROR: %s: attribute: '%s'\n", paths[i],
|
||||
ATTRNAME_STRIPE_COUNT);
|
||||
goto err;
|
||||
}
|
||||
if (!finfo) {
|
||||
finfo = alloc_file_stripe_info(val);
|
||||
if (!finfo)
|
||||
goto err;
|
||||
|
||||
if (val != count)
|
||||
fprintf(stderr, "WARNING: %s: stripe-count "
|
||||
"(%d) != file count (%d). Result may "
|
||||
"be incomplete.\n", paths[i], val,
|
||||
count);
|
||||
if (val != count)
|
||||
fprintf(stderr,
|
||||
"WARNING: %s: stripe-count "
|
||||
"(%d) != file count (%d). Result may "
|
||||
"be incomplete.\n",
|
||||
paths[i], val, count);
|
||||
|
||||
finfo->stripe_count = val;
|
||||
} else if (val != finfo->stripe_count) {
|
||||
fprintf(stderr, "ERROR %s: invalid stripe count: %d "
|
||||
"(expected %d)\n", paths[i], val,
|
||||
finfo->stripe_count);
|
||||
goto err;
|
||||
}
|
||||
finfo->stripe_count = val;
|
||||
} else if (val != finfo->stripe_count) {
|
||||
fprintf(stderr,
|
||||
"ERROR %s: invalid stripe count: %d "
|
||||
"(expected %d)\n",
|
||||
paths[i], val, finfo->stripe_count);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get and validate the chunk size.
|
||||
*/
|
||||
if (get_attr(paths[i], ATTRNAME_STRIPE_SIZE, &stripe_size_attr,
|
||||
&val) != 1) {
|
||||
fprintf(stderr, "ERROR: %s: attribute: '%s'\n",
|
||||
paths[i], ATTRNAME_STRIPE_SIZE);
|
||||
goto err;
|
||||
}
|
||||
/*
|
||||
* Get and validate the chunk size.
|
||||
*/
|
||||
if (get_attr(paths[i], ATTRNAME_STRIPE_SIZE, &stripe_size_attr, &val) !=
|
||||
1) {
|
||||
fprintf(stderr, "ERROR: %s: attribute: '%s'\n", paths[i],
|
||||
ATTRNAME_STRIPE_SIZE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!finfo->stripe_size) {
|
||||
finfo->stripe_size = val;
|
||||
} else if (val != finfo->stripe_size) {
|
||||
fprintf(stderr, "ERROR: %s: invalid stripe size: %d "
|
||||
"(expected %d)\n", paths[i], val,
|
||||
finfo->stripe_size);
|
||||
goto err;
|
||||
}
|
||||
if (!finfo->stripe_size) {
|
||||
finfo->stripe_size = val;
|
||||
} else if (val != finfo->stripe_size) {
|
||||
fprintf(stderr,
|
||||
"ERROR: %s: invalid stripe size: %d "
|
||||
"(expected %d)\n",
|
||||
paths[i], val, finfo->stripe_size);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* stripe-coalesce is a backward compatible attribute. If the
|
||||
* attribute does not exist, assume a value of zero for the
|
||||
* traditional stripe format.
|
||||
*/
|
||||
tmp = get_attr(paths[i], ATTRNAME_STRIPE_COALESCE,
|
||||
&stripe_coalesce_attr, &val);
|
||||
if (!tmp) {
|
||||
val = 0;
|
||||
} else if (tmp != 1) {
|
||||
fprintf(stderr, "ERROR: %s: attribute: '%s'\n",
|
||||
paths[i], ATTRNAME_STRIPE_COALESCE);
|
||||
goto err;
|
||||
}
|
||||
/*
|
||||
* stripe-coalesce is a backward compatible attribute. If the
|
||||
* attribute does not exist, assume a value of zero for the
|
||||
* traditional stripe format.
|
||||
*/
|
||||
tmp = get_attr(paths[i], ATTRNAME_STRIPE_COALESCE,
|
||||
&stripe_coalesce_attr, &val);
|
||||
if (!tmp) {
|
||||
val = 0;
|
||||
} else if (tmp != 1) {
|
||||
fprintf(stderr, "ERROR: %s: attribute: '%s'\n", paths[i],
|
||||
ATTRNAME_STRIPE_COALESCE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (finfo->coalesce == INVALID_FD) {
|
||||
finfo->coalesce = val;
|
||||
} else if (val != finfo->coalesce) {
|
||||
fprintf(stderr, "ERROR: %s: invalid coalesce flag\n",
|
||||
paths[i]);
|
||||
goto err;
|
||||
}
|
||||
if (finfo->coalesce == INVALID_FD) {
|
||||
finfo->coalesce = val;
|
||||
} else if (val != finfo->coalesce) {
|
||||
fprintf(stderr, "ERROR: %s: invalid coalesce flag\n", paths[i]);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get/validate the stripe index and open the file in the
|
||||
* appropriate fd slot.
|
||||
*/
|
||||
if (get_attr(paths[i], ATTRNAME_STRIPE_INDEX,
|
||||
&stripe_index_attr, &val) != 1) {
|
||||
fprintf(stderr, "ERROR: %s: attribute: '%s'\n",
|
||||
paths[i], ATTRNAME_STRIPE_INDEX);
|
||||
goto err;
|
||||
}
|
||||
if (finfo->fd[val] != INVALID_FD) {
|
||||
fprintf(stderr, "ERROR: %s: duplicate stripe index: "
|
||||
"%d\n", paths[i], val);
|
||||
goto err;
|
||||
}
|
||||
/*
|
||||
* Get/validate the stripe index and open the file in the
|
||||
* appropriate fd slot.
|
||||
*/
|
||||
if (get_attr(paths[i], ATTRNAME_STRIPE_INDEX, &stripe_index_attr,
|
||||
&val) != 1) {
|
||||
fprintf(stderr, "ERROR: %s: attribute: '%s'\n", paths[i],
|
||||
ATTRNAME_STRIPE_INDEX);
|
||||
goto err;
|
||||
}
|
||||
if (finfo->fd[val] != INVALID_FD) {
|
||||
fprintf(stderr,
|
||||
"ERROR: %s: duplicate stripe index: "
|
||||
"%d\n",
|
||||
paths[i], val);
|
||||
goto err;
|
||||
}
|
||||
|
||||
finfo->fd[val] = open(paths[i], O_RDONLY);
|
||||
if (finfo->fd[val] < 0)
|
||||
goto err;
|
||||
finfo->fd[val] = open(paths[i], O_RDONLY);
|
||||
if (finfo->fd[val] < 0)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* Get the creation mode for the file.
|
||||
*/
|
||||
if (fstat(finfo->fd[val], &sbuf) < 0)
|
||||
goto err;
|
||||
if (finfo->mode == INVALID_MODE) {
|
||||
finfo->mode = sbuf.st_mode;
|
||||
} else if (sbuf.st_mode != finfo->mode) {
|
||||
fprintf(stderr, "ERROR: %s: invalid mode\n", paths[i]);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Get the creation mode for the file.
|
||||
*/
|
||||
if (fstat(finfo->fd[val], &sbuf) < 0)
|
||||
goto err;
|
||||
if (finfo->mode == INVALID_MODE) {
|
||||
finfo->mode = sbuf.st_mode;
|
||||
} else if (sbuf.st_mode != finfo->mode) {
|
||||
fprintf(stderr, "ERROR: %s: invalid mode\n", paths[i]);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
free(stripe_count_attr);
|
||||
free(stripe_size_attr);
|
||||
free(stripe_index_attr);
|
||||
free(stripe_coalesce_attr);
|
||||
free(stripe_count_attr);
|
||||
free(stripe_size_attr);
|
||||
free(stripe_index_attr);
|
||||
free(stripe_coalesce_attr);
|
||||
|
||||
return finfo;
|
||||
return finfo;
|
||||
err:
|
||||
|
||||
free(stripe_count_attr);
|
||||
free(stripe_size_attr);
|
||||
free(stripe_index_attr);
|
||||
free(stripe_coalesce_attr);
|
||||
free(stripe_count_attr);
|
||||
free(stripe_size_attr);
|
||||
free(stripe_index_attr);
|
||||
free(stripe_coalesce_attr);
|
||||
|
||||
if (finfo) {
|
||||
close_files(finfo);
|
||||
free(finfo);
|
||||
}
|
||||
if (finfo) {
|
||||
close_files(finfo);
|
||||
free(finfo);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
close_files(struct file_stripe_info *finfo)
|
||||
{
|
||||
int i, ret;
|
||||
int i, ret;
|
||||
|
||||
if (!finfo)
|
||||
return -1;
|
||||
if (!finfo)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < finfo->stripe_count; i++) {
|
||||
if (finfo->fd[i] == INVALID_FD)
|
||||
continue;
|
||||
for (i = 0; i < finfo->stripe_count; i++) {
|
||||
if (finfo->fd[i] == INVALID_FD)
|
||||
continue;
|
||||
|
||||
ret = close(finfo->fd[i]);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
ret = close(finfo->fd[i]);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -351,43 +357,43 @@ close_files(struct file_stripe_info *finfo)
|
||||
static int
|
||||
generate_file_coalesce(int target, struct file_stripe_info *finfo)
|
||||
{
|
||||
char *buf;
|
||||
int ret = 0;
|
||||
int r, w, i;
|
||||
char *buf;
|
||||
int ret = 0;
|
||||
int r, w, i;
|
||||
|
||||
buf = malloc(finfo->stripe_size);
|
||||
if (!buf)
|
||||
return -1;
|
||||
buf = malloc(finfo->stripe_size);
|
||||
if (!buf)
|
||||
return -1;
|
||||
|
||||
i = 0;
|
||||
while (1) {
|
||||
if (finfo->fd[i] == INVALID_FD) {
|
||||
if (lseek(target, finfo->stripe_size, SEEK_CUR) < 0)
|
||||
break;
|
||||
i = 0;
|
||||
while (1) {
|
||||
if (finfo->fd[i] == INVALID_FD) {
|
||||
if (lseek(target, finfo->stripe_size, SEEK_CUR) < 0)
|
||||
break;
|
||||
|
||||
i = (i + 1) % finfo->stripe_count;
|
||||
continue;
|
||||
}
|
||||
i = (i + 1) % finfo->stripe_count;
|
||||
continue;
|
||||
}
|
||||
|
||||
r = read(finfo->fd[i], buf, finfo->stripe_size);
|
||||
if (r < 0) {
|
||||
ret = r;
|
||||
break;
|
||||
}
|
||||
if (!r)
|
||||
break;
|
||||
r = read(finfo->fd[i], buf, finfo->stripe_size);
|
||||
if (r < 0) {
|
||||
ret = r;
|
||||
break;
|
||||
}
|
||||
if (!r)
|
||||
break;
|
||||
|
||||
w = write(target, buf, r);
|
||||
if (w < 0) {
|
||||
ret = w;
|
||||
break;
|
||||
}
|
||||
w = write(target, buf, r);
|
||||
if (w < 0) {
|
||||
ret = w;
|
||||
break;
|
||||
}
|
||||
|
||||
i = (i + 1) % finfo->stripe_count;
|
||||
}
|
||||
i = (i + 1) % finfo->stripe_count;
|
||||
}
|
||||
|
||||
free(buf);
|
||||
return ret;
|
||||
free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -398,97 +404,100 @@ generate_file_coalesce(int target, struct file_stripe_info *finfo)
|
||||
static int
|
||||
generate_file_traditional(int target, struct file_stripe_info *finfo)
|
||||
{
|
||||
int i, j, max_ret, ret;
|
||||
char buf[finfo->stripe_count][4096];
|
||||
int i, j, max_ret, ret;
|
||||
char buf[finfo->stripe_count][4096];
|
||||
|
||||
do {
|
||||
char newbuf[4096] = {0, };
|
||||
do {
|
||||
char newbuf[4096] = {
|
||||
0,
|
||||
};
|
||||
|
||||
max_ret = 0;
|
||||
for (i = 0; i < finfo->stripe_count; i++) {
|
||||
memset(buf[i], 0, 4096);
|
||||
ret = read(finfo->fd[i], buf[i], 4096);
|
||||
if (ret > max_ret)
|
||||
max_ret = ret;
|
||||
}
|
||||
for (i = 0; i < max_ret; i++)
|
||||
for (j = 0; j < finfo->stripe_count; j++)
|
||||
newbuf[i] |= buf[j][i];
|
||||
write(target, newbuf, max_ret);
|
||||
} while (max_ret);
|
||||
max_ret = 0;
|
||||
for (i = 0; i < finfo->stripe_count; i++) {
|
||||
memset(buf[i], 0, 4096);
|
||||
ret = read(finfo->fd[i], buf[i], 4096);
|
||||
if (ret > max_ret)
|
||||
max_ret = ret;
|
||||
}
|
||||
for (i = 0; i < max_ret; i++)
|
||||
for (j = 0; j < finfo->stripe_count; j++)
|
||||
newbuf[i] |= buf[j][i];
|
||||
write(target, newbuf, max_ret);
|
||||
} while (max_ret);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
generate_file(int target, struct file_stripe_info *finfo)
|
||||
{
|
||||
if (finfo->coalesce)
|
||||
return generate_file_coalesce(target, finfo);
|
||||
if (finfo->coalesce)
|
||||
return generate_file_coalesce(target, finfo);
|
||||
|
||||
return generate_file_traditional(target, finfo);
|
||||
return generate_file_traditional(target, finfo);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(char *name)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [-o <outputfile>] <inputfile1> "
|
||||
"<inputfile2> ...\n", name);
|
||||
fprintf(stderr,
|
||||
"Usage: %s [-o <outputfile>] <inputfile1> "
|
||||
"<inputfile2> ...\n",
|
||||
name);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int file_count, opt;
|
||||
char *opath = NULL;
|
||||
int targetfd;
|
||||
struct file_stripe_info *finfo;
|
||||
int file_count, opt;
|
||||
char *opath = NULL;
|
||||
int targetfd;
|
||||
struct file_stripe_info *finfo;
|
||||
|
||||
while ((opt = getopt(argc, argv, "o:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'o':
|
||||
opath = optarg;
|
||||
break;
|
||||
default:
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
while ((opt = getopt(argc, argv, "o:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'o':
|
||||
opath = optarg;
|
||||
break;
|
||||
default:
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
file_count = argc - optind;
|
||||
file_count = argc - optind;
|
||||
|
||||
if (!opath || !file_count) {
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
if (!opath || !file_count) {
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
finfo = validate_and_open_files(&argv[optind], file_count);
|
||||
if (!finfo)
|
||||
goto err;
|
||||
finfo = validate_and_open_files(&argv[optind], file_count);
|
||||
if (!finfo)
|
||||
goto err;
|
||||
|
||||
targetfd = open(opath, O_RDWR|O_CREAT, finfo->mode);
|
||||
if (targetfd < 0)
|
||||
goto err;
|
||||
targetfd = open(opath, O_RDWR | O_CREAT, finfo->mode);
|
||||
if (targetfd < 0)
|
||||
goto err;
|
||||
|
||||
if (generate_file(targetfd, finfo) < 0)
|
||||
goto err;
|
||||
if (generate_file(targetfd, finfo) < 0)
|
||||
goto err;
|
||||
|
||||
if (fsync(targetfd) < 0)
|
||||
fprintf(stderr, "ERROR: %s\n", strerror(errno));
|
||||
if (close(targetfd) < 0)
|
||||
fprintf(stderr, "ERROR: %s\n", strerror(errno));
|
||||
if (fsync(targetfd) < 0)
|
||||
fprintf(stderr, "ERROR: %s\n", strerror(errno));
|
||||
if (close(targetfd) < 0)
|
||||
fprintf(stderr, "ERROR: %s\n", strerror(errno));
|
||||
|
||||
close_files(finfo);
|
||||
free(finfo);
|
||||
close_files(finfo);
|
||||
free(finfo);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
err:
|
||||
if (finfo) {
|
||||
close_files(finfo);
|
||||
free(finfo);
|
||||
}
|
||||
if (finfo) {
|
||||
close_files(finfo);
|
||||
free(finfo);
|
||||
}
|
||||
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -40,596 +40,576 @@
|
||||
/* Err number that is assigned to errno so that test application can
|
||||
* verify that the function was intercepted correctly.
|
||||
*/
|
||||
#define PRELOAD_ERRNO_VERF 6449
|
||||
#define set_errno() (errno = PRELOAD_ERRNO_VERF)
|
||||
#define PRELOAD_ERRNO_VERF 6449
|
||||
#define set_errno() (errno = PRELOAD_ERRNO_VERF)
|
||||
|
||||
void
|
||||
intercept (char *call, int tabs)
|
||||
intercept(char *call, int tabs)
|
||||
{
|
||||
while (tabs > 0) {
|
||||
fprintf (stdout, "\t");
|
||||
--tabs;
|
||||
}
|
||||
while (tabs > 0) {
|
||||
fprintf(stdout, "\t");
|
||||
--tabs;
|
||||
}
|
||||
|
||||
fprintf (stdout, "Intercepted by %s", call);
|
||||
fprintf(stdout, "Intercepted by %s", call);
|
||||
}
|
||||
|
||||
int
|
||||
creat64 (const char *pathname, mode_t mode)
|
||||
creat64(const char *pathname, mode_t mode)
|
||||
{
|
||||
intercept ("creat64", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("creat64", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
creat (const char *pathname, mode_t mode)
|
||||
creat(const char *pathname, mode_t mode)
|
||||
{
|
||||
intercept ("creat", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
close (int fd)
|
||||
{
|
||||
intercept ("close", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("creat", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
open64 (const char *pathname, int flags, ...)
|
||||
close(int fd)
|
||||
{
|
||||
intercept ("open64", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("close", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
open (const char *pathname, int flags, ...)
|
||||
open64(const char *pathname, int flags, ...)
|
||||
{
|
||||
intercept ("open", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("open64", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
open(const char *pathname, int flags, ...)
|
||||
{
|
||||
intercept("open", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
read (int fd, void *buf, size_t count)
|
||||
read(int fd, void *buf, size_t count)
|
||||
{
|
||||
intercept ("read", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("read", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
readv (int fd, const struct iovec *vector, int count)
|
||||
readv(int fd, const struct iovec *vector, int count)
|
||||
{
|
||||
intercept ("readv", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("readv", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
pread (int fd, void *buf, size_t count, unsigned long offset)
|
||||
pread(int fd, void *buf, size_t count, unsigned long offset)
|
||||
{
|
||||
intercept ("pread", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
pread64 (int fd, void *buf, size_t count, uint64_t offset)
|
||||
{
|
||||
intercept ("pread64", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("pread", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
write (int fd, const void *buf, size_t count)
|
||||
pread64(int fd, void *buf, size_t count, uint64_t offset)
|
||||
{
|
||||
intercept ("write", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("pread64", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
writev (int fd, const struct iovec *vector, int count)
|
||||
write(int fd, const void *buf, size_t count)
|
||||
{
|
||||
intercept ("writev", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("write", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
pwrite (int fd, const void *buf, size_t count, unsigned long offset)
|
||||
writev(int fd, const struct iovec *vector, int count)
|
||||
{
|
||||
intercept ("pwrite", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("writev", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
pwrite64 (int fd, const void *buf, size_t count, uint64_t offset)
|
||||
pwrite(int fd, const void *buf, size_t count, unsigned long offset)
|
||||
{
|
||||
intercept ("pwrite64", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("pwrite", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
off_t
|
||||
lseek (int fildes, unsigned long offset, int whence)
|
||||
ssize_t
|
||||
pwrite64(int fd, const void *buf, size_t count, uint64_t offset)
|
||||
{
|
||||
intercept ("lseek", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("pwrite64", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
off_t
|
||||
lseek64 (int fildes, uint64_t offset, int whence)
|
||||
lseek(int fildes, unsigned long offset, int whence)
|
||||
{
|
||||
intercept ("lseek64", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("lseek", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
dup (int fd)
|
||||
off_t
|
||||
lseek64(int fildes, uint64_t offset, int whence)
|
||||
{
|
||||
intercept ("dup", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("lseek64", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
dup2 (int oldfd, int newfd)
|
||||
dup(int fd)
|
||||
{
|
||||
intercept ("dup2", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("dup", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
mkdir (const char *pathname, mode_t mode)
|
||||
dup2(int oldfd, int newfd)
|
||||
{
|
||||
intercept ("mkdir", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("dup2", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
rmdir (const char *pathname)
|
||||
mkdir(const char *pathname, mode_t mode)
|
||||
{
|
||||
intercept ("rmdir", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("mkdir", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
chmod (const char *pathname, mode_t mode)
|
||||
rmdir(const char *pathname)
|
||||
{
|
||||
intercept ("chmod", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("rmdir", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
chown (const char *pathname, uid_t owner, gid_t group)
|
||||
chmod(const char *pathname, mode_t mode)
|
||||
{
|
||||
intercept ("chown", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("chmod", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
fchmod (int fd, mode_t mode)
|
||||
chown(const char *pathname, uid_t owner, gid_t group)
|
||||
{
|
||||
intercept ("fchmod", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("chown", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
fchown (int fd, uid_t uid, gid_t gid)
|
||||
fchmod(int fd, mode_t mode)
|
||||
{
|
||||
intercept ("fchown", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int fsync (int fd)
|
||||
{
|
||||
intercept ("fsync", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ftruncate (int fd, off_t length)
|
||||
{
|
||||
intercept ("ftruncate", 1);
|
||||
set_errno ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ftruncate64 (int fd, off_t length)
|
||||
{
|
||||
intercept ("ftruncate64", 1);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("fchmod", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
link (const char *oldpath, const char *newname)
|
||||
fchown(int fd, uid_t uid, gid_t gid)
|
||||
{
|
||||
intercept ("link", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("fchown", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
rename (const char *oldpath, const char *newpath)
|
||||
fsync(int fd)
|
||||
{
|
||||
intercept ("rename", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("fsync", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
utimes (const char *path, const struct timeval times[2])
|
||||
ftruncate(int fd, off_t length)
|
||||
{
|
||||
intercept ("utimes", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("ftruncate", 1);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
futimes (int fd, const struct timeval times[2])
|
||||
ftruncate64(int fd, off_t length)
|
||||
{
|
||||
intercept ("futimes", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("ftruncate64", 1);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
utime (const char *path, const struct utimbuf *buf)
|
||||
link(const char *oldpath, const char *newname)
|
||||
{
|
||||
intercept ("utime", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
mknod (const char *path, mode_t mode, dev_t dev)
|
||||
{
|
||||
intercept ("mknod", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("link", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
__xmknod (int ver, const char *path, mode_t mode, dev_t *dev)
|
||||
rename(const char *oldpath, const char *newpath)
|
||||
{
|
||||
intercept ("__xmknod", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("rename", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
mkfifo (const char *path, mode_t mode)
|
||||
utimes(const char *path, const struct timeval times[2])
|
||||
{
|
||||
intercept ("mkfifo", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("utimes", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
unlink (const char *path)
|
||||
futimes(int fd, const struct timeval times[2])
|
||||
{
|
||||
intercept ("unlink", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
symlink (const char *oldpath, const char *newpath)
|
||||
{
|
||||
intercept ("symlink", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("futimes", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
readlink (const char *path, char *buf, size_t bufsize)
|
||||
utime(const char *path, const struct utimbuf *buf)
|
||||
{
|
||||
intercept ("readlink", 1);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("utime", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
mknod(const char *path, mode_t mode, dev_t dev)
|
||||
{
|
||||
intercept("mknod", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
__xmknod(int ver, const char *path, mode_t mode, dev_t *dev)
|
||||
{
|
||||
intercept("__xmknod", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
mkfifo(const char *path, mode_t mode)
|
||||
{
|
||||
intercept("mkfifo", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
unlink(const char *path)
|
||||
{
|
||||
intercept("unlink", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
symlink(const char *oldpath, const char *newpath)
|
||||
{
|
||||
intercept("symlink", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
readlink(const char *path, char *buf, size_t bufsize)
|
||||
{
|
||||
intercept("readlink", 1);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *
|
||||
realpath (const char *path, char *resolved)
|
||||
realpath(const char *path, char *resolved)
|
||||
{
|
||||
intercept ("realpath", 1);
|
||||
set_errno ();
|
||||
return NULL;
|
||||
intercept("realpath", 1);
|
||||
set_errno();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
DIR *
|
||||
opendir (const char *path)
|
||||
opendir(const char *path)
|
||||
{
|
||||
intercept ("opendir", 2);
|
||||
set_errno ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
struct dirent *
|
||||
readdir (DIR *dir)
|
||||
{
|
||||
intercept ("readdir\t", 2);
|
||||
set_errno ();
|
||||
return NULL;
|
||||
intercept("opendir", 2);
|
||||
set_errno();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct dirent *
|
||||
readdir64 (DIR *dir)
|
||||
readdir(DIR *dir)
|
||||
{
|
||||
intercept ("readdir64", 2);
|
||||
set_errno ();
|
||||
return NULL;
|
||||
intercept("readdir\t", 2);
|
||||
set_errno();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
readdir_r (DIR *dir, struct dirent *entry, struct dirent **result)
|
||||
struct dirent *
|
||||
readdir64(DIR *dir)
|
||||
{
|
||||
intercept ("readdir_r", 1);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("readdir64", 2);
|
||||
set_errno();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
readdir64_r (DIR *dir, struct dirent *entry, struct dirent **result)
|
||||
readdir_r(DIR *dir, struct dirent *entry, struct dirent **result)
|
||||
{
|
||||
intercept ("readdir64_r", 1);
|
||||
set_errno ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
closedir (DIR *dh)
|
||||
{
|
||||
intercept ("closedir", 1);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("readdir_r", 1);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
__xstat (int ver, const char *path, struct stat *buf)
|
||||
readdir64_r(DIR *dir, struct dirent *entry, struct dirent **result)
|
||||
{
|
||||
intercept ("__xstat\t", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
__xstat64 (int ver, const char *path, struct stat *buf)
|
||||
{
|
||||
intercept ("__xstat64", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("readdir64_r", 1);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
stat (const char *path, struct stat *buf)
|
||||
closedir(DIR *dh)
|
||||
{
|
||||
intercept ("stat", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("closedir", 1);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
stat64 (const char *path, struct stat *buf)
|
||||
__xstat(int ver, const char *path, struct stat *buf)
|
||||
{
|
||||
intercept ("stat64", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("__xstat\t", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
__fxstat (int ver, int fd, struct stat *buf)
|
||||
__xstat64(int ver, const char *path, struct stat *buf)
|
||||
{
|
||||
intercept ("__fxstat\t", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
__fxstat64 (int ver, int fd, struct stat *buf)
|
||||
{
|
||||
intercept ("__fxstat64", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("__xstat64", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
fstat (int fd, struct stat *buf)
|
||||
stat(const char *path, struct stat *buf)
|
||||
{
|
||||
intercept ("fstat", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("stat", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
fstat64 (int fd , struct stat *buf)
|
||||
stat64(const char *path, struct stat *buf)
|
||||
{
|
||||
intercept ("fstat64", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("stat64", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
__lxstat (int ver, const char *path, struct stat *buf)
|
||||
__fxstat(int ver, int fd, struct stat *buf)
|
||||
{
|
||||
intercept ("__lxstat\t", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("__fxstat\t", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
__lxstat64 (int ver, const char *path, struct stat *buf)
|
||||
__fxstat64(int ver, int fd, struct stat *buf)
|
||||
{
|
||||
intercept ("__lxstat64", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("__fxstat64", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
lstat (const char *path, struct stat *buf)
|
||||
fstat(int fd, struct stat *buf)
|
||||
{
|
||||
intercept ("lstat", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("fstat", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
lstat64 (const char *path, struct stat *buf)
|
||||
fstat64(int fd, struct stat *buf)
|
||||
{
|
||||
intercept ("lstat64", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("fstat64", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
statfs (const char *path, struct statfs *buf)
|
||||
__lxstat(int ver, const char *path, struct stat *buf)
|
||||
{
|
||||
intercept ("statfs", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
statfs64 (const char *path, struct statfs *buf)
|
||||
{
|
||||
intercept ("statfs64", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("__lxstat\t", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
statvfs (const char *path, struct statvfs *buf)
|
||||
__lxstat64(int ver, const char *path, struct stat *buf)
|
||||
{
|
||||
intercept ("statvfs\t", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("__lxstat64", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
lstat(const char *path, struct stat *buf)
|
||||
{
|
||||
intercept("lstat", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
statvfs64 (const char *path, struct statvfs *buf)
|
||||
lstat64(const char *path, struct stat *buf)
|
||||
{
|
||||
intercept ("statvfs64", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("lstat64", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
statfs(const char *path, struct statfs *buf)
|
||||
{
|
||||
intercept("statfs", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
statfs64(const char *path, struct statfs *buf)
|
||||
{
|
||||
intercept("statfs64", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
statvfs(const char *path, struct statvfs *buf)
|
||||
{
|
||||
intercept("statvfs\t", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
statvfs64(const char *path, struct statvfs *buf)
|
||||
{
|
||||
intercept("statvfs64", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
getxattr (const char *path, const char *name, void *value, size_t size)
|
||||
getxattr(const char *path, const char *name, void *value, size_t size)
|
||||
{
|
||||
intercept ("getxattr", 1);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("getxattr", 1);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
lgetxattr (const char *path, const char *name, void *value, size_t size)
|
||||
lgetxattr(const char *path, const char *name, void *value, size_t size)
|
||||
{
|
||||
intercept ("lgetxattr", 1);
|
||||
set_errno ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
remove (const char* path)
|
||||
{
|
||||
intercept ("remove", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("lgetxattr", 1);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
lchown (const char *path, uid_t owner, gid_t group)
|
||||
remove(const char *path)
|
||||
{
|
||||
intercept ("lchown", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("remove", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
lchown(const char *path, uid_t owner, gid_t group)
|
||||
{
|
||||
intercept("lchown", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
rewinddir (DIR *dirp)
|
||||
rewinddir(DIR *dirp)
|
||||
{
|
||||
intercept ("rewinddir", 1);
|
||||
set_errno ();
|
||||
return;
|
||||
intercept("rewinddir", 1);
|
||||
set_errno();
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
seekdir (DIR *dirp, off_t offset)
|
||||
seekdir(DIR *dirp, off_t offset)
|
||||
{
|
||||
intercept ("seekdir", 2);
|
||||
set_errno ();
|
||||
return;
|
||||
intercept("seekdir", 2);
|
||||
set_errno();
|
||||
return;
|
||||
}
|
||||
|
||||
off_t
|
||||
telldir (DIR *dirp)
|
||||
telldir(DIR *dirp)
|
||||
{
|
||||
intercept ("telldir", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("telldir", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
sendfile (int out_fd, int in_fd, off_t *offset, size_t count)
|
||||
sendfile(int out_fd, int in_fd, off_t *offset, size_t count)
|
||||
{
|
||||
intercept ("sendfile\t", 1);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("sendfile\t", 1);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
sendfile64 (int out_fd, int in_fd, off_t *offset, size_t count)
|
||||
sendfile64(int out_fd, int in_fd, off_t *offset, size_t count)
|
||||
{
|
||||
intercept ("sendfile64", 1);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("sendfile64", 1);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
fcntl (int fd, int cmd, ...)
|
||||
fcntl(int fd, int cmd, ...)
|
||||
{
|
||||
intercept ("fcntl", 2);
|
||||
set_errno ();
|
||||
return -1;
|
||||
intercept("fcntl", 2);
|
||||
set_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -49,319 +49,310 @@
|
||||
#include <sys/xattr.h>
|
||||
#include <sys/sendfile.h>
|
||||
|
||||
|
||||
#define PRELOAD_ERRNO_VERF 6449
|
||||
#define PRELOAD_ERRNO_VERF 6449
|
||||
void
|
||||
check_err(int ret, char *call, int tabs)
|
||||
{
|
||||
while (tabs > 0) {
|
||||
fprintf (stdout, "\t");
|
||||
--tabs;
|
||||
}
|
||||
if (ret != -1) {
|
||||
fprintf (stdout, "Not intercepted: %s\n", call);
|
||||
return;
|
||||
}
|
||||
|
||||
if (errno != PRELOAD_ERRNO_VERF) {
|
||||
fprintf (stdout, "Not intercepted: %s: err: %s\n", call,
|
||||
strerror (errno));
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf (stdout, "Intercept verified: %s\n", call);
|
||||
while (tabs > 0) {
|
||||
fprintf(stdout, "\t");
|
||||
--tabs;
|
||||
}
|
||||
if (ret != -1) {
|
||||
fprintf(stdout, "Not intercepted: %s\n", call);
|
||||
return;
|
||||
}
|
||||
|
||||
if (errno != PRELOAD_ERRNO_VERF) {
|
||||
fprintf(stdout, "Not intercepted: %s: err: %s\n", call,
|
||||
strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(stdout, "Intercept verified: %s\n", call);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
usage (FILE *fp)
|
||||
usage(FILE *fp)
|
||||
{
|
||||
fprintf (fp, "Usage: ld-preload-test <Options>\n");
|
||||
fprintf (fp, "Options\n");
|
||||
fprintf (fp, "\t--path\t\tPathname is used as the file/directory"
|
||||
" created for the test.\n");
|
||||
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
run_file_tests (char *testfile)
|
||||
{
|
||||
int ret = -1;
|
||||
struct stat buf;
|
||||
|
||||
assert (testfile);
|
||||
fprintf (stdout, "Testing creat");
|
||||
ret = creat (testfile, S_IRWXU);
|
||||
check_err (ret, "creat", 2);
|
||||
|
||||
fprintf (stdout, "Testing close");
|
||||
ret = close (ret);
|
||||
check_err (ret, "close", 2);
|
||||
|
||||
fprintf (stdout, "Testing open");
|
||||
ret = open (testfile, O_RDONLY);
|
||||
check_err (ret, "open", 2);
|
||||
|
||||
fprintf (stdout, "Testing read");
|
||||
ret = read (0, NULL, 0);
|
||||
check_err (ret, "read", 2);
|
||||
|
||||
fprintf (stdout, "Testing readv");
|
||||
ret = readv (0, NULL, 0);
|
||||
check_err (ret, "readv", 2);
|
||||
|
||||
fprintf (stdout, "Testing pread");
|
||||
ret = pread (0, NULL, 0, 0);
|
||||
check_err (ret, "pread", 2);
|
||||
|
||||
fprintf (stdout, "Testing write");
|
||||
ret = write (0, NULL, 0);
|
||||
check_err (ret, "write", 2);
|
||||
|
||||
fprintf (stdout, "Testing writev");
|
||||
ret = writev (0, NULL, 0);
|
||||
check_err (ret, "writev", 2);
|
||||
|
||||
fprintf (stdout, "Testing pwrite");
|
||||
ret = pwrite (0, NULL, 0, 0);
|
||||
check_err (ret, "pwrite", 2);
|
||||
|
||||
fprintf (stdout, "Testing lseek");
|
||||
ret = lseek (0, 0, 0);
|
||||
check_err (ret, "lseek", 2);
|
||||
|
||||
fprintf (stdout, "Testing dup");
|
||||
ret = dup (0);
|
||||
check_err (ret, "dup", 2);
|
||||
|
||||
fprintf (stdout, "Testing dup2");
|
||||
ret = dup2 (0, 0);
|
||||
check_err (ret, "dup2", 2);
|
||||
|
||||
fprintf (stdout, "Testing fchmod");
|
||||
ret = fchmod (0, 0);
|
||||
check_err (ret, "fchmod", 2);
|
||||
|
||||
fprintf (stdout, "Testing fchown");
|
||||
ret = fchown (0, 0, 0);
|
||||
check_err (ret, "fchown", 2);
|
||||
|
||||
fprintf (stdout, "Testing fsync");
|
||||
ret = fsync (0);
|
||||
check_err (ret, "fsync", 2);
|
||||
|
||||
fprintf (stdout, "Testing ftruncate");
|
||||
ret = ftruncate (0, 0);
|
||||
check_err (ret, "ftruncate", 1);
|
||||
|
||||
fprintf (stdout, "Testing fstat");
|
||||
ret = fstat (0, &buf);
|
||||
check_err (ret, "fstat", 1);
|
||||
|
||||
fprintf (stdout, "Testing sendfile");
|
||||
ret = sendfile (0, 0, NULL, 0);
|
||||
check_err (ret, "sendfile", 1);
|
||||
|
||||
fprintf (stdout, "Testing fcntl");
|
||||
ret = fcntl (0, 0, NULL);
|
||||
check_err (ret, "fcntl", 2);
|
||||
|
||||
fprintf (stdout, "Testing close");
|
||||
ret = close (ret);
|
||||
check_err (ret, "close", 2);
|
||||
|
||||
fprintf (stdout, "Testing remove");
|
||||
ret = remove (testfile);
|
||||
check_err (ret, "remove", 2);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
run_attr_tests (char *testfile)
|
||||
{
|
||||
int ret = -1;
|
||||
char *res = NULL;
|
||||
struct stat buf;
|
||||
struct statfs sbuf;
|
||||
struct statvfs svbuf;
|
||||
|
||||
assert (testfile);
|
||||
|
||||
fprintf (stdout, "Testing chmod");
|
||||
ret = chmod (testfile, 0);
|
||||
check_err (ret, "chmod", 2);
|
||||
|
||||
fprintf (stdout, "Testing chown");
|
||||
ret = chown (testfile, 0, 0);
|
||||
check_err (ret, "chown", 2);
|
||||
|
||||
fprintf (stdout, "Testing link");
|
||||
ret = link (testfile, testfile);
|
||||
check_err (ret, "link", 2);
|
||||
|
||||
fprintf (stdout, "Testing rename");
|
||||
ret = rename (testfile, testfile);
|
||||
check_err (ret, "rename", 2);
|
||||
|
||||
fprintf (stdout, "Testing utimes");
|
||||
ret = utimes (testfile, NULL);
|
||||
check_err (ret, "utimes", 2);
|
||||
|
||||
fprintf (stdout, "Testing utime");
|
||||
ret = utime (testfile, NULL);
|
||||
check_err (ret, "utime", 2);
|
||||
|
||||
fprintf (stdout, "Testing unlink");
|
||||
ret = unlink (testfile);
|
||||
check_err (ret, "unlink", 2);
|
||||
|
||||
fprintf (stdout, "Testing symlink");
|
||||
ret = symlink (testfile, testfile);
|
||||
check_err (ret, "symlink", 2);
|
||||
|
||||
fprintf (stdout, "Testing readlink");
|
||||
ret = readlink (testfile, testfile, 0);
|
||||
check_err (ret, "readlink", 2);
|
||||
|
||||
fprintf (stdout, "Testing realpath");
|
||||
ret = 0;
|
||||
res = realpath ((const char *)testfile, testfile);
|
||||
if (!res)
|
||||
ret = -1;
|
||||
check_err (ret, "realpath", 2);
|
||||
|
||||
fprintf (stdout, "Testing stat");
|
||||
ret = stat (testfile, &buf);
|
||||
check_err (ret, "stat", 1);
|
||||
|
||||
fprintf (stdout, "Testing lstat");
|
||||
ret = lstat (testfile, &buf);
|
||||
check_err (ret, "lstat", 1);
|
||||
|
||||
fprintf (stdout, "Testing statfs");
|
||||
ret = statfs (testfile, &sbuf);
|
||||
check_err (ret, "statfs", 2);
|
||||
|
||||
fprintf (stdout, "Testing statvfs");
|
||||
ret = statvfs (testfile, &svbuf);
|
||||
check_err (ret, "statvfs", 1);
|
||||
|
||||
fprintf (stdout, "Testing getxattr");
|
||||
ret = getxattr (testfile, NULL, NULL, 0);
|
||||
check_err (ret, "getxattr", 2);
|
||||
|
||||
fprintf (stdout, "Testing lgetxattr");
|
||||
ret = lgetxattr (testfile, NULL, NULL, 0);
|
||||
check_err (ret, "lgetxattr", 1);
|
||||
|
||||
fprintf (stdout, "Testing lchown");
|
||||
ret = lchown (testfile, 0, 0);
|
||||
check_err (ret, "lchown", 2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
run_dev_tests (char *testfile)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
assert (testfile);
|
||||
|
||||
fprintf (stdout, "Testing mknod");
|
||||
ret = mknod (testfile, 0, 0);
|
||||
check_err (ret, "mknod", 2);
|
||||
|
||||
fprintf (stdout, "Testing mkfifo");
|
||||
ret = mkfifo (testfile, 0);
|
||||
check_err (ret, "mkfifo", 2);
|
||||
return 0;
|
||||
fprintf(fp, "Usage: ld-preload-test <Options>\n");
|
||||
fprintf(fp, "Options\n");
|
||||
fprintf(fp,
|
||||
"\t--path\t\tPathname is used as the file/directory"
|
||||
" created for the test.\n");
|
||||
}
|
||||
|
||||
int
|
||||
run_dir_tests (char *testpath)
|
||||
run_file_tests(char *testfile)
|
||||
{
|
||||
int ret = -1;
|
||||
DIR *dh = NULL;
|
||||
struct dirent *dire = NULL;
|
||||
int ret = -1;
|
||||
struct stat buf;
|
||||
|
||||
assert (testpath);
|
||||
assert(testfile);
|
||||
fprintf(stdout, "Testing creat");
|
||||
ret = creat(testfile, S_IRWXU);
|
||||
check_err(ret, "creat", 2);
|
||||
|
||||
fprintf (stdout, "Testing mkdir");
|
||||
ret = mkdir (testpath, 0);
|
||||
check_err (ret, "mkdir", 2);
|
||||
fprintf(stdout, "Testing close");
|
||||
ret = close(ret);
|
||||
check_err(ret, "close", 2);
|
||||
|
||||
fprintf (stdout, "Testing rmdir");
|
||||
ret = rmdir (testpath);
|
||||
check_err (ret, "rmdir", 2);
|
||||
fprintf(stdout, "Testing open");
|
||||
ret = open(testfile, O_RDONLY);
|
||||
check_err(ret, "open", 2);
|
||||
|
||||
fprintf (stdout, "Testing opendir");
|
||||
ret = 0;
|
||||
dh = opendir (testpath);
|
||||
if (!dh)
|
||||
ret = -1;
|
||||
check_err (ret, "opendir", 2);
|
||||
fprintf(stdout, "Testing read");
|
||||
ret = read(0, NULL, 0);
|
||||
check_err(ret, "read", 2);
|
||||
|
||||
fprintf (stdout, "Testing readdir");
|
||||
ret = 0;
|
||||
dire = readdir (dh);
|
||||
if (!dire)
|
||||
ret = -1;
|
||||
check_err (ret, "readdir", 1);
|
||||
fprintf(stdout, "Testing readv");
|
||||
ret = readv(0, NULL, 0);
|
||||
check_err(ret, "readv", 2);
|
||||
|
||||
fprintf (stdout, "Testing readdir_r");
|
||||
ret = readdir_r (dh, dire, &dire);
|
||||
check_err (ret, "readdir_r", 1);
|
||||
fprintf(stdout, "Testing pread");
|
||||
ret = pread(0, NULL, 0, 0);
|
||||
check_err(ret, "pread", 2);
|
||||
|
||||
fprintf (stdout, "Testing rewinddir");
|
||||
rewinddir (dh);
|
||||
check_err (-1, "rewinddir", 1);
|
||||
fprintf(stdout, "Testing write");
|
||||
ret = write(0, NULL, 0);
|
||||
check_err(ret, "write", 2);
|
||||
|
||||
fprintf (stdout, "Testing seekdir");
|
||||
seekdir (dh, 0);
|
||||
check_err (-1, "seekdir", 2);
|
||||
fprintf(stdout, "Testing writev");
|
||||
ret = writev(0, NULL, 0);
|
||||
check_err(ret, "writev", 2);
|
||||
|
||||
fprintf (stdout, "Testing telldir");
|
||||
ret = telldir (dh);
|
||||
check_err (ret, "telldir", 2);
|
||||
fprintf(stdout, "Testing pwrite");
|
||||
ret = pwrite(0, NULL, 0, 0);
|
||||
check_err(ret, "pwrite", 2);
|
||||
|
||||
fprintf (stdout, "Testing closedir");
|
||||
ret = closedir (dh);
|
||||
check_err (ret, "closedir", 2);
|
||||
return 0;
|
||||
fprintf(stdout, "Testing lseek");
|
||||
ret = lseek(0, 0, 0);
|
||||
check_err(ret, "lseek", 2);
|
||||
|
||||
fprintf(stdout, "Testing dup");
|
||||
ret = dup(0);
|
||||
check_err(ret, "dup", 2);
|
||||
|
||||
fprintf(stdout, "Testing dup2");
|
||||
ret = dup2(0, 0);
|
||||
check_err(ret, "dup2", 2);
|
||||
|
||||
fprintf(stdout, "Testing fchmod");
|
||||
ret = fchmod(0, 0);
|
||||
check_err(ret, "fchmod", 2);
|
||||
|
||||
fprintf(stdout, "Testing fchown");
|
||||
ret = fchown(0, 0, 0);
|
||||
check_err(ret, "fchown", 2);
|
||||
|
||||
fprintf(stdout, "Testing fsync");
|
||||
ret = fsync(0);
|
||||
check_err(ret, "fsync", 2);
|
||||
|
||||
fprintf(stdout, "Testing ftruncate");
|
||||
ret = ftruncate(0, 0);
|
||||
check_err(ret, "ftruncate", 1);
|
||||
|
||||
fprintf(stdout, "Testing fstat");
|
||||
ret = fstat(0, &buf);
|
||||
check_err(ret, "fstat", 1);
|
||||
|
||||
fprintf(stdout, "Testing sendfile");
|
||||
ret = sendfile(0, 0, NULL, 0);
|
||||
check_err(ret, "sendfile", 1);
|
||||
|
||||
fprintf(stdout, "Testing fcntl");
|
||||
ret = fcntl(0, 0, NULL);
|
||||
check_err(ret, "fcntl", 2);
|
||||
|
||||
fprintf(stdout, "Testing close");
|
||||
ret = close(ret);
|
||||
check_err(ret, "close", 2);
|
||||
|
||||
fprintf(stdout, "Testing remove");
|
||||
ret = remove(testfile);
|
||||
check_err(ret, "remove", 2);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
run_attr_tests(char *testfile)
|
||||
{
|
||||
int ret = -1;
|
||||
char *res = NULL;
|
||||
struct stat buf;
|
||||
struct statfs sbuf;
|
||||
struct statvfs svbuf;
|
||||
|
||||
assert(testfile);
|
||||
|
||||
fprintf(stdout, "Testing chmod");
|
||||
ret = chmod(testfile, 0);
|
||||
check_err(ret, "chmod", 2);
|
||||
|
||||
fprintf(stdout, "Testing chown");
|
||||
ret = chown(testfile, 0, 0);
|
||||
check_err(ret, "chown", 2);
|
||||
|
||||
fprintf(stdout, "Testing link");
|
||||
ret = link(testfile, testfile);
|
||||
check_err(ret, "link", 2);
|
||||
|
||||
fprintf(stdout, "Testing rename");
|
||||
ret = rename(testfile, testfile);
|
||||
check_err(ret, "rename", 2);
|
||||
|
||||
fprintf(stdout, "Testing utimes");
|
||||
ret = utimes(testfile, NULL);
|
||||
check_err(ret, "utimes", 2);
|
||||
|
||||
fprintf(stdout, "Testing utime");
|
||||
ret = utime(testfile, NULL);
|
||||
check_err(ret, "utime", 2);
|
||||
|
||||
fprintf(stdout, "Testing unlink");
|
||||
ret = unlink(testfile);
|
||||
check_err(ret, "unlink", 2);
|
||||
|
||||
fprintf(stdout, "Testing symlink");
|
||||
ret = symlink(testfile, testfile);
|
||||
check_err(ret, "symlink", 2);
|
||||
|
||||
fprintf(stdout, "Testing readlink");
|
||||
ret = readlink(testfile, testfile, 0);
|
||||
check_err(ret, "readlink", 2);
|
||||
|
||||
fprintf(stdout, "Testing realpath");
|
||||
ret = 0;
|
||||
res = realpath((const char *)testfile, testfile);
|
||||
if (!res)
|
||||
ret = -1;
|
||||
check_err(ret, "realpath", 2);
|
||||
|
||||
fprintf(stdout, "Testing stat");
|
||||
ret = stat(testfile, &buf);
|
||||
check_err(ret, "stat", 1);
|
||||
|
||||
fprintf(stdout, "Testing lstat");
|
||||
ret = lstat(testfile, &buf);
|
||||
check_err(ret, "lstat", 1);
|
||||
|
||||
fprintf(stdout, "Testing statfs");
|
||||
ret = statfs(testfile, &sbuf);
|
||||
check_err(ret, "statfs", 2);
|
||||
|
||||
fprintf(stdout, "Testing statvfs");
|
||||
ret = statvfs(testfile, &svbuf);
|
||||
check_err(ret, "statvfs", 1);
|
||||
|
||||
fprintf(stdout, "Testing getxattr");
|
||||
ret = getxattr(testfile, NULL, NULL, 0);
|
||||
check_err(ret, "getxattr", 2);
|
||||
|
||||
fprintf(stdout, "Testing lgetxattr");
|
||||
ret = lgetxattr(testfile, NULL, NULL, 0);
|
||||
check_err(ret, "lgetxattr", 1);
|
||||
|
||||
fprintf(stdout, "Testing lchown");
|
||||
ret = lchown(testfile, 0, 0);
|
||||
check_err(ret, "lchown", 2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
run_dev_tests(char *testfile)
|
||||
{
|
||||
char *testpath = NULL;
|
||||
int x = 0;
|
||||
int ret = -1;
|
||||
|
||||
for (;x < argc; ++x) {
|
||||
if (strcmp (argv[x], "--path") == 0) {
|
||||
testpath = argv[x+1];
|
||||
continue;
|
||||
}
|
||||
assert(testfile);
|
||||
|
||||
fprintf(stdout, "Testing mknod");
|
||||
ret = mknod(testfile, 0, 0);
|
||||
check_err(ret, "mknod", 2);
|
||||
|
||||
fprintf(stdout, "Testing mkfifo");
|
||||
ret = mkfifo(testfile, 0);
|
||||
check_err(ret, "mkfifo", 2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
run_dir_tests(char *testpath)
|
||||
{
|
||||
int ret = -1;
|
||||
DIR *dh = NULL;
|
||||
struct dirent *dire = NULL;
|
||||
|
||||
assert(testpath);
|
||||
|
||||
fprintf(stdout, "Testing mkdir");
|
||||
ret = mkdir(testpath, 0);
|
||||
check_err(ret, "mkdir", 2);
|
||||
|
||||
fprintf(stdout, "Testing rmdir");
|
||||
ret = rmdir(testpath);
|
||||
check_err(ret, "rmdir", 2);
|
||||
|
||||
fprintf(stdout, "Testing opendir");
|
||||
ret = 0;
|
||||
dh = opendir(testpath);
|
||||
if (!dh)
|
||||
ret = -1;
|
||||
check_err(ret, "opendir", 2);
|
||||
|
||||
fprintf(stdout, "Testing readdir");
|
||||
ret = 0;
|
||||
dire = readdir(dh);
|
||||
if (!dire)
|
||||
ret = -1;
|
||||
check_err(ret, "readdir", 1);
|
||||
|
||||
fprintf(stdout, "Testing readdir_r");
|
||||
ret = readdir_r(dh, dire, &dire);
|
||||
check_err(ret, "readdir_r", 1);
|
||||
|
||||
fprintf(stdout, "Testing rewinddir");
|
||||
rewinddir(dh);
|
||||
check_err(-1, "rewinddir", 1);
|
||||
|
||||
fprintf(stdout, "Testing seekdir");
|
||||
seekdir(dh, 0);
|
||||
check_err(-1, "seekdir", 2);
|
||||
|
||||
fprintf(stdout, "Testing telldir");
|
||||
ret = telldir(dh);
|
||||
check_err(ret, "telldir", 2);
|
||||
|
||||
fprintf(stdout, "Testing closedir");
|
||||
ret = closedir(dh);
|
||||
check_err(ret, "closedir", 2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
char *testpath = NULL;
|
||||
int x = 0;
|
||||
|
||||
for (; x < argc; ++x) {
|
||||
if (strcmp(argv[x], "--path") == 0) {
|
||||
testpath = argv[x + 1];
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!testpath) {
|
||||
fprintf (stderr, "--path not specified\n");
|
||||
usage (stderr);
|
||||
return -1;
|
||||
}
|
||||
if (!testpath) {
|
||||
fprintf(stderr, "--path not specified\n");
|
||||
usage(stderr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
run_file_tests (testpath);
|
||||
run_dir_tests (testpath);
|
||||
run_attr_tests (testpath);
|
||||
run_dev_tests (testpath);
|
||||
run_file_tests(testpath);
|
||||
run_dir_tests(testpath);
|
||||
run_attr_tests(testpath);
|
||||
run_dev_tests(testpath);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -9,56 +9,59 @@
|
||||
#include <string.h>
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int ret = -1;
|
||||
int fd = 0;
|
||||
char *filename = NULL;
|
||||
int loop = 0;
|
||||
struct stat stbuf = {0,};
|
||||
char string[1024] = {0,};
|
||||
int ret = -1;
|
||||
int fd = 0;
|
||||
char *filename = NULL;
|
||||
int loop = 0;
|
||||
struct stat stbuf = {
|
||||
0,
|
||||
};
|
||||
char string[1024] = {
|
||||
0,
|
||||
};
|
||||
|
||||
if (argc > 1)
|
||||
filename = argv[1];
|
||||
if (argc > 1)
|
||||
filename = argv[1];
|
||||
|
||||
if (!filename)
|
||||
filename = "temp-fd-test-file";
|
||||
if (!filename)
|
||||
filename = "temp-fd-test-file";
|
||||
|
||||
fd = open (filename, O_RDWR|O_CREAT|O_TRUNC);
|
||||
if (fd < 0) {
|
||||
fd = 0;
|
||||
fprintf (stderr, "open failed : %s\n", strerror (errno));
|
||||
goto out;
|
||||
fd = open(filename, O_RDWR | O_CREAT | O_TRUNC);
|
||||
if (fd < 0) {
|
||||
fd = 0;
|
||||
fprintf(stderr, "open failed : %s\n", strerror(errno));
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (loop < 1000) {
|
||||
/* Use it as a mechanism to test time delays */
|
||||
memset(string, 0, 1024);
|
||||
scanf("%s", string);
|
||||
|
||||
ret = write(fd, string, strlen(string));
|
||||
if (ret != strlen(string)) {
|
||||
fprintf(stderr, "write failed : %s (%s %d)\n", strerror(errno),
|
||||
string, loop);
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (loop < 1000) {
|
||||
/* Use it as a mechanism to test time delays */
|
||||
memset (string, 0, 1024);
|
||||
scanf ("%s", string);
|
||||
|
||||
ret = write (fd, string, strlen (string));
|
||||
if (ret != strlen (string)) {
|
||||
fprintf (stderr, "write failed : %s (%s %d)\n",
|
||||
strerror (errno), string, loop);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = write (fd, "\n", 1);
|
||||
if (ret != 1) {
|
||||
fprintf (stderr, "write failed : %s (%d)\n",
|
||||
strerror (errno), loop);
|
||||
goto out;
|
||||
}
|
||||
|
||||
loop++;
|
||||
ret = write(fd, "\n", 1);
|
||||
if (ret != 1) {
|
||||
fprintf(stderr, "write failed : %s (%d)\n", strerror(errno), loop);
|
||||
goto out;
|
||||
}
|
||||
|
||||
fprintf (stdout, "finishing the test after %d loops\n", loop);
|
||||
loop++;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
fprintf(stdout, "finishing the test after %d loops\n", loop);
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
if (fd)
|
||||
close (fd);
|
||||
if (fd)
|
||||
close(fd);
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -42,359 +42,362 @@
|
||||
int restricted = 0;
|
||||
|
||||
static int
|
||||
duplexpand (void **buf, size_t tsiz, size_t *len)
|
||||
duplexpand(void **buf, size_t tsiz, size_t *len)
|
||||
{
|
||||
size_t osiz = tsiz * *len;
|
||||
char *p = realloc (*buf, osiz << 1);
|
||||
if (!p) {
|
||||
free(*buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset (p + osiz, 0, osiz);
|
||||
*buf = p;
|
||||
*len <<= 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
str2argv (char *str, char ***argv)
|
||||
{
|
||||
char *p = NULL;
|
||||
char *savetok = NULL;
|
||||
char *temp = NULL;
|
||||
char *temp1 = NULL;
|
||||
int argc = 0;
|
||||
size_t argv_len = 32;
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
|
||||
assert (str);
|
||||
temp = str = strdup (str);
|
||||
if (!str)
|
||||
goto error;
|
||||
|
||||
*argv = calloc (argv_len, sizeof (**argv));
|
||||
if (!*argv)
|
||||
goto error;
|
||||
|
||||
while ((p = strtok_r (str, " ", &savetok))) {
|
||||
str = NULL;
|
||||
|
||||
argc++;
|
||||
if (argc == argv_len) {
|
||||
ret = duplexpand ((void *)argv,
|
||||
sizeof (**argv),
|
||||
&argv_len);
|
||||
if (ret == -1)
|
||||
goto error;
|
||||
}
|
||||
temp1 = strdup (p);
|
||||
if (!temp1)
|
||||
goto error;
|
||||
(*argv)[argc - 1] = temp1;
|
||||
}
|
||||
|
||||
free(temp);
|
||||
return argc;
|
||||
|
||||
error:
|
||||
fprintf (stderr, "out of memory\n");
|
||||
free(temp);
|
||||
for (i = 0; i < argc - 1; i++)
|
||||
free((*argv)[i]);
|
||||
free(*argv);
|
||||
size_t osiz = tsiz * *len;
|
||||
char *p = realloc(*buf, osiz << 1);
|
||||
if (!p) {
|
||||
free(*buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(p + osiz, 0, osiz);
|
||||
*buf = p;
|
||||
*len <<= 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
invoke_gsyncd (int argc, char **argv)
|
||||
str2argv(char *str, char ***argv)
|
||||
{
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
char *nargv[argc + 4];
|
||||
char *python = NULL;
|
||||
char *p = NULL;
|
||||
char *savetok = NULL;
|
||||
char *temp = NULL;
|
||||
char *temp1 = NULL;
|
||||
int argc = 0;
|
||||
size_t argv_len = 32;
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
|
||||
if (chdir ("/") == -1)
|
||||
assert(str);
|
||||
temp = str = strdup(str);
|
||||
if (!str)
|
||||
goto error;
|
||||
|
||||
*argv = calloc(argv_len, sizeof(**argv));
|
||||
if (!*argv)
|
||||
goto error;
|
||||
|
||||
while ((p = strtok_r(str, " ", &savetok))) {
|
||||
str = NULL;
|
||||
|
||||
argc++;
|
||||
if (argc == argv_len) {
|
||||
ret = duplexpand((void *)argv, sizeof(**argv), &argv_len);
|
||||
if (ret == -1)
|
||||
goto error;
|
||||
}
|
||||
temp1 = strdup(p);
|
||||
if (!temp1)
|
||||
goto error;
|
||||
(*argv)[argc - 1] = temp1;
|
||||
}
|
||||
|
||||
j = 0;
|
||||
python = getenv("PYTHON");
|
||||
if(!python)
|
||||
python = PYTHON;
|
||||
nargv[j++] = python;
|
||||
nargv[j++] = GSYNCD_PREFIX"/python/syncdaemon/"GSYNCD_PY;
|
||||
for (i = 1; i < argc; i++)
|
||||
nargv[j++] = argv[i];
|
||||
free(temp);
|
||||
return argc;
|
||||
|
||||
nargv[j++] = NULL;
|
||||
|
||||
execvp (python, nargv);
|
||||
|
||||
fprintf (stderr, "exec of '%s' failed\n", python);
|
||||
return 127;
|
||||
|
||||
error:
|
||||
fprintf (stderr, "gsyncd initializaion failed\n");
|
||||
return 1;
|
||||
error:
|
||||
fprintf(stderr, "out of memory\n");
|
||||
free(temp);
|
||||
for (i = 0; i < argc - 1; i++)
|
||||
free((*argv)[i]);
|
||||
free(*argv);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
invoke_gsyncd(int argc, char **argv)
|
||||
{
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
char *nargv[argc + 4];
|
||||
char *python = NULL;
|
||||
|
||||
if (chdir("/") == -1)
|
||||
goto error;
|
||||
|
||||
j = 0;
|
||||
python = getenv("PYTHON");
|
||||
if (!python)
|
||||
python = PYTHON;
|
||||
nargv[j++] = python;
|
||||
nargv[j++] = GSYNCD_PREFIX "/python/syncdaemon/" GSYNCD_PY;
|
||||
for (i = 1; i < argc; i++)
|
||||
nargv[j++] = argv[i];
|
||||
|
||||
nargv[j++] = NULL;
|
||||
|
||||
execvp(python, nargv);
|
||||
|
||||
fprintf(stderr, "exec of '%s' failed\n", python);
|
||||
return 127;
|
||||
|
||||
error:
|
||||
fprintf(stderr, "gsyncd initializaion failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
find_gsyncd (pid_t pid, pid_t ppid, char *name, void *data)
|
||||
find_gsyncd(pid_t pid, pid_t ppid, char *name, void *data)
|
||||
{
|
||||
char buf[NAME_MAX * 2] = {0,};
|
||||
char path[PATH_MAX] = {0,};
|
||||
char *p = NULL;
|
||||
int zeros = 0;
|
||||
int ret = 0;
|
||||
int fd = -1;
|
||||
pid_t *pida = (pid_t *)data;
|
||||
|
||||
if (ppid != pida[0])
|
||||
return 0;
|
||||
|
||||
snprintf (path, sizeof path, PROC"/%d/cmdline", pid);
|
||||
fd = open (path, O_RDONLY);
|
||||
if (fd == -1)
|
||||
return 0;
|
||||
ret = sys_read (fd, buf, sizeof (buf));
|
||||
sys_close (fd);
|
||||
if (ret == -1)
|
||||
return 0;
|
||||
for (zeros = 0, p = buf; zeros < 2 && p < buf + ret; p++)
|
||||
zeros += !*p;
|
||||
|
||||
ret = 0;
|
||||
switch (zeros) {
|
||||
case 2:
|
||||
if ((strcmp (basename (buf), basename (PYTHON)) ||
|
||||
strcmp (basename (buf + strlen (buf) + 1), GSYNCD_PY)) == 0) {
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
/* fallthrough */
|
||||
case 1:
|
||||
if (strcmp (basename (buf), GSYNCD_PY) == 0)
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
if (ret == 1) {
|
||||
if (pida[1] != -1) {
|
||||
fprintf (stderr, GSYNCD_PY" sibling is not unique");
|
||||
return -1;
|
||||
}
|
||||
pida[1] = pid;
|
||||
}
|
||||
char buf[NAME_MAX * 2] = {
|
||||
0,
|
||||
};
|
||||
char path[PATH_MAX] = {
|
||||
0,
|
||||
};
|
||||
char *p = NULL;
|
||||
int zeros = 0;
|
||||
int ret = 0;
|
||||
int fd = -1;
|
||||
pid_t *pida = (pid_t *)data;
|
||||
|
||||
if (ppid != pida[0])
|
||||
return 0;
|
||||
|
||||
snprintf(path, sizeof path, PROC "/%d/cmdline", pid);
|
||||
fd = open(path, O_RDONLY);
|
||||
if (fd == -1)
|
||||
return 0;
|
||||
ret = sys_read(fd, buf, sizeof(buf));
|
||||
sys_close(fd);
|
||||
if (ret == -1)
|
||||
return 0;
|
||||
for (zeros = 0, p = buf; zeros < 2 && p < buf + ret; p++)
|
||||
zeros += !*p;
|
||||
|
||||
ret = 0;
|
||||
switch (zeros) {
|
||||
case 2:
|
||||
if ((strcmp(basename(buf), basename(PYTHON)) ||
|
||||
strcmp(basename(buf + strlen(buf) + 1), GSYNCD_PY)) == 0) {
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
/* fallthrough */
|
||||
case 1:
|
||||
if (strcmp(basename(buf), GSYNCD_PY) == 0)
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
if (ret == 1) {
|
||||
if (pida[1] != -1) {
|
||||
fprintf(stderr, GSYNCD_PY " sibling is not unique");
|
||||
return -1;
|
||||
}
|
||||
pida[1] = pid;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
invoke_rsync (int argc, char **argv)
|
||||
invoke_rsync(int argc, char **argv)
|
||||
{
|
||||
int i = 0;
|
||||
char path[PATH_MAX] = {0,};
|
||||
pid_t pid = -1;
|
||||
pid_t ppid = -1;
|
||||
pid_t pida[] = {-1, -1};
|
||||
char *name = NULL;
|
||||
char buf[PATH_MAX + 1] = {0,};
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
char path[PATH_MAX] = {
|
||||
0,
|
||||
};
|
||||
pid_t pid = -1;
|
||||
pid_t ppid = -1;
|
||||
pid_t pida[] = {-1, -1};
|
||||
char *name = NULL;
|
||||
char buf[PATH_MAX + 1] = {
|
||||
0,
|
||||
};
|
||||
int ret = 0;
|
||||
|
||||
assert (argv[argc] == NULL);
|
||||
assert(argv[argc] == NULL);
|
||||
|
||||
if (argc < 2 || strcmp (argv[1], "--server") != 0)
|
||||
goto error;
|
||||
if (argc < 2 || strcmp(argv[1], "--server") != 0)
|
||||
goto error;
|
||||
|
||||
for (i = 2; i < argc && argv[i][0] == '-'; i++);
|
||||
for (i = 2; i < argc && argv[i][0] == '-'; i++)
|
||||
;
|
||||
|
||||
if (!(i == argc - 2 && strcmp (argv[i], ".") == 0 && argv[i + 1][0] == '/')) {
|
||||
fprintf (stderr, "need an rsync invocation without protected args\n");
|
||||
goto error;
|
||||
if (!(i == argc - 2 && strcmp(argv[i], ".") == 0 &&
|
||||
argv[i + 1][0] == '/')) {
|
||||
fprintf(stderr, "need an rsync invocation without protected args\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* look up sshd we are spawned from */
|
||||
for (pid = getpid();; pid = ppid) {
|
||||
ppid = pidinfo(pid, &name);
|
||||
if (ppid < 0) {
|
||||
fprintf(stderr, "sshd ancestor not found\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* look up sshd we are spawned from */
|
||||
for (pid = getpid () ;; pid = ppid) {
|
||||
ppid = pidinfo (pid, &name);
|
||||
if (ppid < 0) {
|
||||
fprintf (stderr, "sshd ancestor not found\n");
|
||||
goto error;
|
||||
}
|
||||
if (strcmp (name, "sshd") == 0) {
|
||||
GF_FREE (name);
|
||||
break;
|
||||
}
|
||||
GF_FREE (name);
|
||||
}
|
||||
/* look up "ssh-sibling" gsyncd */
|
||||
pida[0] = pid;
|
||||
ret = prociter (find_gsyncd, pida);
|
||||
if (ret == -1 || pida[1] == -1) {
|
||||
fprintf (stderr, "gsyncd sibling not found\n");
|
||||
goto error;
|
||||
}
|
||||
/* check if rsync target matches gsyncd target */
|
||||
snprintf (path, sizeof path, PROC"/%d/cwd", pida[1]);
|
||||
ret = sys_readlink (path, buf, sizeof (buf));
|
||||
if (ret == -1 || ret == sizeof (buf))
|
||||
goto error;
|
||||
if (strcmp (argv[argc - 1], "/") == 0 /* root dir cannot be a target */ ||
|
||||
(strcmp (argv[argc - 1], path) /* match against gluster target */ &&
|
||||
strcmp (argv[argc - 1], buf) /* match against file target */) != 0) {
|
||||
fprintf (stderr, "rsync target does not match "GEOREP" session\n");
|
||||
goto error;
|
||||
if (strcmp(name, "sshd") == 0) {
|
||||
GF_FREE(name);
|
||||
break;
|
||||
}
|
||||
GF_FREE(name);
|
||||
}
|
||||
/* look up "ssh-sibling" gsyncd */
|
||||
pida[0] = pid;
|
||||
ret = prociter(find_gsyncd, pida);
|
||||
if (ret == -1 || pida[1] == -1) {
|
||||
fprintf(stderr, "gsyncd sibling not found\n");
|
||||
goto error;
|
||||
}
|
||||
/* check if rsync target matches gsyncd target */
|
||||
snprintf(path, sizeof path, PROC "/%d/cwd", pida[1]);
|
||||
ret = sys_readlink(path, buf, sizeof(buf));
|
||||
if (ret == -1 || ret == sizeof(buf))
|
||||
goto error;
|
||||
if (strcmp(argv[argc - 1], "/") == 0 /* root dir cannot be a target */ ||
|
||||
(strcmp(argv[argc - 1], path) /* match against gluster target */ &&
|
||||
strcmp(argv[argc - 1], buf) /* match against file target */) != 0) {
|
||||
fprintf(stderr, "rsync target does not match " GEOREP " session\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
argv[0] = RSYNC;
|
||||
argv[0] = RSYNC;
|
||||
|
||||
execvp (RSYNC, argv);
|
||||
execvp(RSYNC, argv);
|
||||
|
||||
fprintf (stderr, "exec of "RSYNC" failed\n");
|
||||
return 127;
|
||||
fprintf(stderr, "exec of " RSYNC " failed\n");
|
||||
return 127;
|
||||
|
||||
error:
|
||||
fprintf (stderr, "disallowed "RSYNC" invocation\n");
|
||||
return 1;
|
||||
error:
|
||||
fprintf(stderr, "disallowed " RSYNC " invocation\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
invoke_gluster (int argc, char **argv)
|
||||
invoke_gluster(int argc, char **argv)
|
||||
{
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
int optsover = 0;
|
||||
char *ov = NULL;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
int optsover = 0;
|
||||
char *ov = NULL;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
ov = strtail (argv[i], "--");
|
||||
if (ov && !optsover) {
|
||||
if (*ov == '\0')
|
||||
optsover = 1;
|
||||
continue;
|
||||
}
|
||||
switch (++j) {
|
||||
case 1:
|
||||
if (strcmp (argv[i], "volume") != 0)
|
||||
goto error;
|
||||
break;
|
||||
case 2:
|
||||
if (strcmp (argv[i], "info") != 0)
|
||||
goto error;
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
default:
|
||||
goto error;
|
||||
}
|
||||
for (i = 1; i < argc; i++) {
|
||||
ov = strtail(argv[i], "--");
|
||||
if (ov && !optsover) {
|
||||
if (*ov == '\0')
|
||||
optsover = 1;
|
||||
continue;
|
||||
}
|
||||
switch (++j) {
|
||||
case 1:
|
||||
if (strcmp(argv[i], "volume") != 0)
|
||||
goto error;
|
||||
break;
|
||||
case 2:
|
||||
if (strcmp(argv[i], "info") != 0)
|
||||
goto error;
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
default:
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
argv[0] = "gluster";
|
||||
execvp (SBIN_DIR"/gluster", argv);
|
||||
fprintf (stderr, "exec of gluster failed\n");
|
||||
return 127;
|
||||
argv[0] = "gluster";
|
||||
execvp(SBIN_DIR "/gluster", argv);
|
||||
fprintf(stderr, "exec of gluster failed\n");
|
||||
return 127;
|
||||
|
||||
error:
|
||||
fprintf (stderr, "disallowed gluster invocation\n");
|
||||
return 1;
|
||||
error:
|
||||
fprintf(stderr, "disallowed gluster invocation\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct invocable {
|
||||
char *name;
|
||||
int (*invoker) (int argc, char **argv);
|
||||
char *name;
|
||||
int (*invoker)(int argc, char **argv);
|
||||
};
|
||||
|
||||
struct invocable invocables[] = {
|
||||
{ "rsync", invoke_rsync },
|
||||
{ "gsyncd", invoke_gsyncd },
|
||||
{ "gluster", invoke_gluster },
|
||||
{ NULL, NULL}
|
||||
};
|
||||
struct invocable invocables[] = {{"rsync", invoke_rsync},
|
||||
{"gsyncd", invoke_gsyncd},
|
||||
{"gluster", invoke_gluster},
|
||||
{NULL, NULL}};
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int ret = -1;
|
||||
char *evas = NULL;
|
||||
struct invocable *i = NULL;
|
||||
char *b = NULL;
|
||||
char *sargv = NULL;
|
||||
int j = 0;
|
||||
int ret = -1;
|
||||
char *evas = NULL;
|
||||
struct invocable *i = NULL;
|
||||
char *b = NULL;
|
||||
char *sargv = NULL;
|
||||
int j = 0;
|
||||
|
||||
#ifdef USE_LIBGLUSTERFS
|
||||
glusterfs_ctx_t *ctx = NULL;
|
||||
glusterfs_ctx_t *ctx = NULL;
|
||||
|
||||
ctx = glusterfs_ctx_new ();
|
||||
if (!ctx)
|
||||
return ENOMEM;
|
||||
ctx = glusterfs_ctx_new();
|
||||
if (!ctx)
|
||||
return ENOMEM;
|
||||
|
||||
if (glusterfs_globals_init (ctx))
|
||||
return 1;
|
||||
if (glusterfs_globals_init(ctx))
|
||||
return 1;
|
||||
|
||||
THIS->ctx = ctx;
|
||||
ret = default_mem_acct_init (THIS);
|
||||
if (ret) {
|
||||
fprintf (stderr, "internal error: mem accounting failed\n");
|
||||
return 1;
|
||||
}
|
||||
THIS->ctx = ctx;
|
||||
ret = default_mem_acct_init(THIS);
|
||||
if (ret) {
|
||||
fprintf(stderr, "internal error: mem accounting failed\n");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
evas = getenv (_GLUSTERD_CALLED_);
|
||||
if (evas && strcmp (evas, "1") == 0)
|
||||
/* OK, we know glusterd called us, no need to look for further config
|
||||
*...although this conclusion should not inherit to our children
|
||||
*/
|
||||
unsetenv (_GLUSTERD_CALLED_);
|
||||
else {
|
||||
/* we regard all gsyncd invocations unsafe
|
||||
* that do not come from glusterd and
|
||||
* therefore restrict it
|
||||
*/
|
||||
restricted = 1;
|
||||
|
||||
if (!getenv (_GSYNCD_DISPATCHED_)) {
|
||||
evas = getenv ("SSH_ORIGINAL_COMMAND");
|
||||
if (evas)
|
||||
sargv = evas;
|
||||
else {
|
||||
evas = getenv ("SHELL");
|
||||
if (evas && strcmp (basename (evas), "gsyncd") == 0 &&
|
||||
argc == 3 && strcmp (argv[1], "-c") == 0)
|
||||
sargv = argv[2];
|
||||
}
|
||||
}
|
||||
evas = getenv(_GLUSTERD_CALLED_);
|
||||
if (evas && strcmp(evas, "1") == 0)
|
||||
/* OK, we know glusterd called us, no need to look for further config
|
||||
*...although this conclusion should not inherit to our children
|
||||
*/
|
||||
unsetenv(_GLUSTERD_CALLED_);
|
||||
else {
|
||||
/* we regard all gsyncd invocations unsafe
|
||||
* that do not come from glusterd and
|
||||
* therefore restrict it
|
||||
*/
|
||||
restricted = 1;
|
||||
|
||||
if (!getenv(_GSYNCD_DISPATCHED_)) {
|
||||
evas = getenv("SSH_ORIGINAL_COMMAND");
|
||||
if (evas)
|
||||
sargv = evas;
|
||||
else {
|
||||
evas = getenv("SHELL");
|
||||
if (evas && strcmp(basename(evas), "gsyncd") == 0 &&
|
||||
argc == 3 && strcmp(argv[1], "-c") == 0)
|
||||
sargv = argv[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!(sargv && restricted))
|
||||
return invoke_gsyncd (argc, argv);
|
||||
if (!(sargv && restricted))
|
||||
return invoke_gsyncd(argc, argv);
|
||||
|
||||
argc = str2argv (sargv, &argv);
|
||||
argc = str2argv(sargv, &argv);
|
||||
|
||||
if (argc == -1) {
|
||||
fprintf (stderr, "internal error\n");
|
||||
return 1;
|
||||
}
|
||||
if (argc == -1) {
|
||||
fprintf(stderr, "internal error\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (setenv (_GSYNCD_DISPATCHED_, "1", 1) == -1) {
|
||||
fprintf (stderr, "internal error\n");
|
||||
goto out;
|
||||
}
|
||||
if (setenv(_GSYNCD_DISPATCHED_, "1", 1) == -1) {
|
||||
fprintf(stderr, "internal error\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
b = basename(argv[0]);
|
||||
for (i = invocables; i->name; i++) {
|
||||
if (strcmp(b, i->name) == 0)
|
||||
return i->invoker(argc, argv);
|
||||
}
|
||||
|
||||
b = basename (argv[0]);
|
||||
for (i = invocables; i->name; i++) {
|
||||
if (strcmp (b, i->name) == 0)
|
||||
return i->invoker (argc, argv);
|
||||
}
|
||||
|
||||
fprintf (stderr, "invoking %s in restricted SSH session is not allowed\n",
|
||||
b);
|
||||
fprintf(stderr, "invoking %s in restricted SSH session is not allowed\n",
|
||||
b);
|
||||
|
||||
out:
|
||||
for (j = 1; j < argc; j++)
|
||||
free(argv[j]);
|
||||
free(argv);
|
||||
return 1;
|
||||
for (j = 1; j < argc; j++)
|
||||
free(argv[j]);
|
||||
free(argv);
|
||||
return 1;
|
||||
}
|
||||
|
@ -20,107 +20,115 @@
|
||||
#include "procdiggy.h"
|
||||
|
||||
pid_t
|
||||
pidinfo (pid_t pid, char **name)
|
||||
pidinfo(pid_t pid, char **name)
|
||||
{
|
||||
char buf[NAME_MAX * 2] = {0,};
|
||||
FILE *f = NULL;
|
||||
char path[PATH_MAX] = {0,};
|
||||
char *p = NULL;
|
||||
int ret = 0;
|
||||
char buf[NAME_MAX * 2] = {
|
||||
0,
|
||||
};
|
||||
FILE *f = NULL;
|
||||
char path[PATH_MAX] = {
|
||||
0,
|
||||
};
|
||||
char *p = NULL;
|
||||
int ret = 0;
|
||||
|
||||
snprintf (path, sizeof path, PROC"/%d/status", pid);
|
||||
snprintf(path, sizeof path, PROC "/%d/status", pid);
|
||||
|
||||
f = fopen (path, "r");
|
||||
if (!f)
|
||||
return -1;
|
||||
f = fopen(path, "r");
|
||||
if (!f)
|
||||
return -1;
|
||||
|
||||
if (name)
|
||||
*name = NULL;
|
||||
for (;;) {
|
||||
size_t len;
|
||||
memset (buf, 0, sizeof (buf));
|
||||
if (fgets (buf, sizeof (buf), f) == NULL ||
|
||||
(len = strlen (buf)) == 0 ||
|
||||
buf[len - 1] != '\n') {
|
||||
pid = -1;
|
||||
goto out;
|
||||
if (name)
|
||||
*name = NULL;
|
||||
for (;;) {
|
||||
size_t len;
|
||||
memset(buf, 0, sizeof(buf));
|
||||
if (fgets(buf, sizeof(buf), f) == NULL || (len = strlen(buf)) == 0 ||
|
||||
buf[len - 1] != '\n') {
|
||||
pid = -1;
|
||||
goto out;
|
||||
}
|
||||
buf[len - 1] = '\0';
|
||||
|
||||
if (name && !*name) {
|
||||
p = strtail(buf, "Name:");
|
||||
if (p) {
|
||||
while (isspace(*++p))
|
||||
;
|
||||
*name = gf_strdup(p);
|
||||
if (!*name) {
|
||||
pid = -2;
|
||||
goto out;
|
||||
}
|
||||
buf[len - 1] = '\0';
|
||||
|
||||
if (name && !*name) {
|
||||
p = strtail (buf, "Name:");
|
||||
if (p) {
|
||||
while (isspace (*++p));
|
||||
*name = gf_strdup (p);
|
||||
if (!*name) {
|
||||
pid = -2;
|
||||
goto out;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
p = strtail (buf, "PPid:");
|
||||
if (p)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
while (isspace (*++p));
|
||||
ret = gf_string2int (p, &pid);
|
||||
if (ret == -1)
|
||||
pid = -1;
|
||||
p = strtail(buf, "PPid:");
|
||||
if (p)
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
fclose (f);
|
||||
if (pid == -1 && name && *name)
|
||||
GF_FREE (*name);
|
||||
if (pid == -2)
|
||||
fprintf (stderr, "out of memory\n");
|
||||
return pid;
|
||||
while (isspace(*++p))
|
||||
;
|
||||
ret = gf_string2int(p, &pid);
|
||||
if (ret == -1)
|
||||
pid = -1;
|
||||
|
||||
out:
|
||||
fclose(f);
|
||||
if (pid == -1 && name && *name)
|
||||
GF_FREE(*name);
|
||||
if (pid == -2)
|
||||
fprintf(stderr, "out of memory\n");
|
||||
return pid;
|
||||
}
|
||||
|
||||
int
|
||||
prociter (int (*proch) (pid_t pid, pid_t ppid, char *tmpname, void *data),
|
||||
void *data)
|
||||
prociter(int (*proch)(pid_t pid, pid_t ppid, char *tmpname, void *data),
|
||||
void *data)
|
||||
{
|
||||
char *name = NULL;
|
||||
DIR *d = NULL;
|
||||
struct dirent *de = NULL;
|
||||
struct dirent scratch[2] = {{0,},};
|
||||
pid_t pid = -1;
|
||||
pid_t ppid = -1;
|
||||
int ret = 0;
|
||||
char *name = NULL;
|
||||
DIR *d = NULL;
|
||||
struct dirent *de = NULL;
|
||||
struct dirent scratch[2] = {
|
||||
{
|
||||
0,
|
||||
},
|
||||
};
|
||||
pid_t pid = -1;
|
||||
pid_t ppid = -1;
|
||||
int ret = 0;
|
||||
|
||||
d = sys_opendir (PROC);
|
||||
if (!d)
|
||||
return -1;
|
||||
d = sys_opendir(PROC);
|
||||
if (!d)
|
||||
return -1;
|
||||
|
||||
for (;;) {
|
||||
errno = 0;
|
||||
de = sys_readdir (d, scratch);
|
||||
if (!de || errno != 0)
|
||||
break;
|
||||
for (;;) {
|
||||
errno = 0;
|
||||
de = sys_readdir(d, scratch);
|
||||
if (!de || errno != 0)
|
||||
break;
|
||||
|
||||
if (gf_string2int (de->d_name, &pid) != -1 && pid >= 0) {
|
||||
ppid = pidinfo (pid, &name);
|
||||
switch (ppid) {
|
||||
case -1:
|
||||
continue;
|
||||
case -2:
|
||||
break;
|
||||
}
|
||||
ret = proch (pid, ppid, name, data);
|
||||
GF_FREE (name);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
}
|
||||
sys_closedir (d);
|
||||
if (!de && errno) {
|
||||
fprintf (stderr, "failed to traverse "PROC" (%s)\n",
|
||||
strerror (errno));
|
||||
ret = -1;
|
||||
if (gf_string2int(de->d_name, &pid) != -1 && pid >= 0) {
|
||||
ppid = pidinfo(pid, &name);
|
||||
switch (ppid) {
|
||||
case -1:
|
||||
continue;
|
||||
case -2:
|
||||
break;
|
||||
}
|
||||
ret = proch(pid, ppid, name, data);
|
||||
GF_FREE(name);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
}
|
||||
sys_closedir(d);
|
||||
if (!de && errno) {
|
||||
fprintf(stderr, "failed to traverse " PROC " (%s)\n", strerror(errno));
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
@ -25,189 +25,186 @@ int done = 0;
|
||||
int rpc_status;
|
||||
|
||||
struct rpc_clnt_procedure gf_attach_actors[GLUSTERD_BRICK_MAXVALUE] = {
|
||||
[GLUSTERD_BRICK_NULL] = {"NULL", NULL },
|
||||
[GLUSTERD_BRICK_OP] = {"BRICK_OP", NULL },
|
||||
[GLUSTERD_BRICK_NULL] = {"NULL", NULL},
|
||||
[GLUSTERD_BRICK_OP] = {"BRICK_OP", NULL},
|
||||
};
|
||||
|
||||
struct rpc_clnt_program gf_attach_prog = {
|
||||
.progname = "brick operations",
|
||||
.prognum = GD_BRICK_PROGRAM,
|
||||
.progver = GD_BRICK_VERSION,
|
||||
.proctable = gf_attach_actors,
|
||||
.numproc = GLUSTERD_BRICK_MAXVALUE,
|
||||
.progname = "brick operations",
|
||||
.prognum = GD_BRICK_PROGRAM,
|
||||
.progver = GD_BRICK_VERSION,
|
||||
.proctable = gf_attach_actors,
|
||||
.numproc = GLUSTERD_BRICK_MAXVALUE,
|
||||
};
|
||||
|
||||
int32_t
|
||||
my_callback (struct rpc_req *req, struct iovec *iov, int count, void *frame)
|
||||
my_callback(struct rpc_req *req, struct iovec *iov, int count, void *frame)
|
||||
{
|
||||
rpc_status = req->rpc_status;
|
||||
done = 1;
|
||||
return 0;
|
||||
rpc_status = req->rpc_status;
|
||||
done = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* copied from gd_syncop_submit_request */
|
||||
int
|
||||
send_brick_req (xlator_t *this, struct rpc_clnt *rpc, char *path, int op)
|
||||
send_brick_req(xlator_t *this, struct rpc_clnt *rpc, char *path, int op)
|
||||
{
|
||||
int ret = -1;
|
||||
struct iobuf *iobuf = NULL;
|
||||
struct iobref *iobref = NULL;
|
||||
struct iovec iov = {0, };
|
||||
ssize_t req_size = 0;
|
||||
call_frame_t *frame = NULL;
|
||||
gd1_mgmt_brick_op_req brick_req;
|
||||
void *req = &brick_req;
|
||||
int i;
|
||||
int ret = -1;
|
||||
struct iobuf *iobuf = NULL;
|
||||
struct iobref *iobref = NULL;
|
||||
struct iovec iov = {
|
||||
0,
|
||||
};
|
||||
ssize_t req_size = 0;
|
||||
call_frame_t *frame = NULL;
|
||||
gd1_mgmt_brick_op_req brick_req;
|
||||
void *req = &brick_req;
|
||||
int i;
|
||||
|
||||
brick_req.op = op;
|
||||
brick_req.name = path;
|
||||
brick_req.input.input_val = NULL;
|
||||
brick_req.input.input_len = 0;
|
||||
brick_req.op = op;
|
||||
brick_req.name = path;
|
||||
brick_req.input.input_val = NULL;
|
||||
brick_req.input.input_len = 0;
|
||||
|
||||
req_size = xdr_sizeof ((xdrproc_t)xdr_gd1_mgmt_brick_op_req, req);
|
||||
iobuf = iobuf_get2 (rpc->ctx->iobuf_pool, req_size);
|
||||
if (!iobuf)
|
||||
goto out;
|
||||
req_size = xdr_sizeof((xdrproc_t)xdr_gd1_mgmt_brick_op_req, req);
|
||||
iobuf = iobuf_get2(rpc->ctx->iobuf_pool, req_size);
|
||||
if (!iobuf)
|
||||
goto out;
|
||||
|
||||
iobref = iobref_new ();
|
||||
if (!iobref)
|
||||
goto out;
|
||||
iobref = iobref_new();
|
||||
if (!iobref)
|
||||
goto out;
|
||||
|
||||
frame = create_frame (this, this->ctx->pool);
|
||||
if (!frame)
|
||||
goto out;
|
||||
frame = create_frame(this, this->ctx->pool);
|
||||
if (!frame)
|
||||
goto out;
|
||||
|
||||
iobref_add (iobref, iobuf);
|
||||
iobref_add(iobref, iobuf);
|
||||
|
||||
iov.iov_base = iobuf->ptr;
|
||||
iov.iov_len = iobuf_pagesize (iobuf);
|
||||
iov.iov_base = iobuf->ptr;
|
||||
iov.iov_len = iobuf_pagesize(iobuf);
|
||||
|
||||
/* Create the xdr payload */
|
||||
ret = xdr_serialize_generic (iov, req,
|
||||
(xdrproc_t)xdr_gd1_mgmt_brick_op_req);
|
||||
if (ret == -1)
|
||||
goto out;
|
||||
/* Create the xdr payload */
|
||||
ret = xdr_serialize_generic(iov, req, (xdrproc_t)xdr_gd1_mgmt_brick_op_req);
|
||||
if (ret == -1)
|
||||
goto out;
|
||||
|
||||
iov.iov_len = ret;
|
||||
iov.iov_len = ret;
|
||||
|
||||
for (i = 0; i < 60; ++i) {
|
||||
if (rpc->conn.connected) {
|
||||
break;
|
||||
}
|
||||
sleep (1);
|
||||
for (i = 0; i < 60; ++i) {
|
||||
if (rpc->conn.connected) {
|
||||
break;
|
||||
}
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
/* Send the msg */
|
||||
ret = rpc_clnt_submit (rpc, &gf_attach_prog, op,
|
||||
my_callback, &iov, 1, NULL, 0, iobref, frame,
|
||||
NULL, 0, NULL, 0, NULL);
|
||||
if (!ret) {
|
||||
for (i = 0; !done && (i < 120); ++i) {
|
||||
sleep (1);
|
||||
}
|
||||
/* Send the msg */
|
||||
ret = rpc_clnt_submit(rpc, &gf_attach_prog, op, my_callback, &iov, 1, NULL,
|
||||
0, iobref, frame, NULL, 0, NULL, 0, NULL);
|
||||
if (!ret) {
|
||||
for (i = 0; !done && (i < 120); ++i) {
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
iobref_unref (iobref);
|
||||
iobuf_unref (iobuf);
|
||||
if (frame)
|
||||
STACK_DESTROY (frame->root);
|
||||
|
||||
if (rpc_status != 0) {
|
||||
fprintf (stderr, "got error %d on RPC\n", rpc_status);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
printf ("OK\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
usage (char *prog)
|
||||
{
|
||||
fprintf (stderr, "Usage: %s uds_path volfile_path (to attach)\n",
|
||||
prog);
|
||||
fprintf (stderr, " %s -d uds_path brick_path (to detach)\n",
|
||||
prog);
|
||||
iobref_unref(iobref);
|
||||
iobuf_unref(iobuf);
|
||||
if (frame)
|
||||
STACK_DESTROY(frame->root);
|
||||
|
||||
if (rpc_status != 0) {
|
||||
fprintf(stderr, "got error %d on RPC\n", rpc_status);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
printf("OK\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
usage(char *prog)
|
||||
{
|
||||
glfs_t *fs;
|
||||
struct rpc_clnt *rpc;
|
||||
dict_t *options;
|
||||
int ret;
|
||||
int op = GLUSTERD_BRICK_ATTACH;
|
||||
fprintf(stderr, "Usage: %s uds_path volfile_path (to attach)\n", prog);
|
||||
fprintf(stderr, " %s -d uds_path brick_path (to detach)\n", prog);
|
||||
|
||||
for (;;) {
|
||||
switch (getopt (argc, argv, "d")) {
|
||||
case 'd':
|
||||
op = GLUSTERD_BRICK_TERMINATE;
|
||||
break;
|
||||
case -1:
|
||||
goto done_parsing;
|
||||
default:
|
||||
return usage (argv[0]);
|
||||
}
|
||||
}
|
||||
done_parsing:
|
||||
if (optind != (argc - 2)) {
|
||||
return usage (argv[0]);
|
||||
}
|
||||
|
||||
fs = glfs_new ("gf-attach");
|
||||
if (!fs) {
|
||||
fprintf (stderr, "glfs_new failed\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
(void) glfs_set_logging (fs, "/dev/stderr", 7);
|
||||
/*
|
||||
* This will actually fail because we haven't defined a volume, but
|
||||
* it will do enough initialization to get us going.
|
||||
*/
|
||||
(void) glfs_init (fs);
|
||||
|
||||
options = dict_new();
|
||||
if (!options) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
ret = dict_set_str (options, "transport-type", "socket");
|
||||
if (ret != 0) {
|
||||
fprintf (stderr, "failed to set transport type\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
ret = dict_set_str (options, "transport.address-family", "unix");
|
||||
if (ret != 0) {
|
||||
fprintf (stderr, "failed to set address family\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
ret = dict_set_str (options, "transport.socket.connect-path",
|
||||
argv[optind]);
|
||||
if (ret != 0) {
|
||||
fprintf (stderr, "failed to set connect path\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
rpc = rpc_clnt_new (options, fs->ctx->master, "gf-attach-rpc", 0);
|
||||
if (!rpc) {
|
||||
fprintf (stderr, "rpc_clnt_new failed\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (rpc_clnt_register_notify (rpc, NULL, NULL) != 0) {
|
||||
fprintf (stderr, "rpc_clnt_register_notify failed\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (rpc_clnt_start(rpc) != 0) {
|
||||
fprintf (stderr, "rpc_clnt_start failed\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return send_brick_req (fs->ctx->master, rpc, argv[optind+1], op);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
glfs_t *fs;
|
||||
struct rpc_clnt *rpc;
|
||||
dict_t *options;
|
||||
int ret;
|
||||
int op = GLUSTERD_BRICK_ATTACH;
|
||||
|
||||
for (;;) {
|
||||
switch (getopt(argc, argv, "d")) {
|
||||
case 'd':
|
||||
op = GLUSTERD_BRICK_TERMINATE;
|
||||
break;
|
||||
case -1:
|
||||
goto done_parsing;
|
||||
default:
|
||||
return usage(argv[0]);
|
||||
}
|
||||
}
|
||||
done_parsing:
|
||||
if (optind != (argc - 2)) {
|
||||
return usage(argv[0]);
|
||||
}
|
||||
|
||||
fs = glfs_new("gf-attach");
|
||||
if (!fs) {
|
||||
fprintf(stderr, "glfs_new failed\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
(void)glfs_set_logging(fs, "/dev/stderr", 7);
|
||||
/*
|
||||
* This will actually fail because we haven't defined a volume, but
|
||||
* it will do enough initialization to get us going.
|
||||
*/
|
||||
(void)glfs_init(fs);
|
||||
|
||||
options = dict_new();
|
||||
if (!options) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
ret = dict_set_str(options, "transport-type", "socket");
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "failed to set transport type\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
ret = dict_set_str(options, "transport.address-family", "unix");
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "failed to set address family\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
ret = dict_set_str(options, "transport.socket.connect-path", argv[optind]);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "failed to set connect path\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
rpc = rpc_clnt_new(options, fs->ctx->master, "gf-attach-rpc", 0);
|
||||
if (!rpc) {
|
||||
fprintf(stderr, "rpc_clnt_new failed\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (rpc_clnt_register_notify(rpc, NULL, NULL) != 0) {
|
||||
fprintf(stderr, "rpc_clnt_register_notify failed\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (rpc_clnt_start(rpc) != 0) {
|
||||
fprintf(stderr, "rpc_clnt_start failed\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return send_brick_req(fs->ctx->master, rpc, argv[optind + 1], op);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
2791
heal/src/glfs-heal.c
2791
heal/src/glfs-heal.c
File diff suppressed because it is too large
Load Diff
@ -114,10 +114,14 @@ GF_ATOMIC_TYPE(SIZEOF_LONG, uintptr); /* gf_atomic_uintptr_t */
|
||||
* builtin version depending on the size of the atomic structure. */
|
||||
#define GF_ATOMIC_CHOOSE(_atomic, _op, _args...) \
|
||||
((sizeof(_atomic) > sizeof(uint64_t)) \
|
||||
? ({ GF_ATOMIC_MACRO(GF_ATOMIC_LOCK_, _op) \
|
||||
(_atomic, ##_args); }) \
|
||||
: ({ GF_ATOMIC_MACRO(GF_ATOMIC_BASE_, _op) \
|
||||
(_atomic, ##_args); }))
|
||||
? ({ \
|
||||
GF_ATOMIC_MACRO(GF_ATOMIC_LOCK_, _op) \
|
||||
(_atomic, ##_args); \
|
||||
}) \
|
||||
: ({ \
|
||||
GF_ATOMIC_MACRO(GF_ATOMIC_BASE_, _op) \
|
||||
(_atomic, ##_args); \
|
||||
}))
|
||||
|
||||
/* Macros to implement the mutex-based atomics. */
|
||||
#define GF_ATOMIC_OP_PREPARE(_atomic, _name) \
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -22,24 +22,23 @@
|
||||
* data. Thus int32_t and uint32_t are sufficient
|
||||
*/
|
||||
uint32_t
|
||||
gf_rsync_weak_checksum (unsigned char *buf, size_t len)
|
||||
gf_rsync_weak_checksum(unsigned char *buf, size_t len)
|
||||
{
|
||||
return adler32 (0, buf, len);
|
||||
return adler32(0, buf, len);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The "strong" checksum required for the rsync algorithm.
|
||||
*/
|
||||
void
|
||||
gf_rsync_strong_checksum (unsigned char *data, size_t len,
|
||||
unsigned char *sha256_md)
|
||||
gf_rsync_strong_checksum(unsigned char *data, size_t len,
|
||||
unsigned char *sha256_md)
|
||||
{
|
||||
SHA256((const unsigned char *)data, len, sha256_md);
|
||||
SHA256((const unsigned char *)data, len, sha256_md);
|
||||
}
|
||||
|
||||
void
|
||||
gf_rsync_md5_checksum (unsigned char *data, size_t len, unsigned char *md5)
|
||||
gf_rsync_md5_checksum(unsigned char *data, size_t len, unsigned char *md5)
|
||||
{
|
||||
MD5 (data, len, md5);
|
||||
MD5(data, len, md5);
|
||||
}
|
||||
|
@ -12,190 +12,182 @@
|
||||
#include "libglusterfs-messages.h"
|
||||
|
||||
void
|
||||
cb_destroy_data (circular_buffer_t *cb,
|
||||
void (*destroy_buffer_data) (void *data))
|
||||
cb_destroy_data(circular_buffer_t *cb, void (*destroy_buffer_data)(void *data))
|
||||
{
|
||||
if (destroy_buffer_data)
|
||||
destroy_buffer_data (cb->data);
|
||||
GF_FREE (cb->data);
|
||||
return;
|
||||
if (destroy_buffer_data)
|
||||
destroy_buffer_data(cb->data);
|
||||
GF_FREE(cb->data);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* hold lock while calling this function */
|
||||
int
|
||||
__cb_add_entry_buffer (buffer_t *buffer, void *item)
|
||||
__cb_add_entry_buffer(buffer_t *buffer, void *item)
|
||||
{
|
||||
circular_buffer_t *ptr = NULL;
|
||||
int ret = -1;
|
||||
//DO we really need the assert here?
|
||||
GF_ASSERT (buffer->used_len <= buffer->size_buffer);
|
||||
circular_buffer_t *ptr = NULL;
|
||||
int ret = -1;
|
||||
// DO we really need the assert here?
|
||||
GF_ASSERT(buffer->used_len <= buffer->size_buffer);
|
||||
|
||||
if (buffer->use_once == _gf_true &&
|
||||
buffer->used_len == buffer->size_buffer) {
|
||||
gf_msg ("circ-buff", GF_LOG_WARNING, 0, LG_MSG_BUFFER_ERROR,
|
||||
"buffer %p is use once buffer", buffer);
|
||||
return -1;
|
||||
} else {
|
||||
if (buffer->used_len == buffer->size_buffer) {
|
||||
if (buffer->cb[buffer->w_index]) {
|
||||
ptr = buffer->cb[buffer->w_index];
|
||||
if (ptr->data) {
|
||||
cb_destroy_data (ptr,
|
||||
buffer->destroy_buffer_data);
|
||||
ptr->data = NULL;
|
||||
GF_FREE (ptr);
|
||||
}
|
||||
buffer->cb[buffer->w_index] = NULL;
|
||||
ptr = NULL;
|
||||
}
|
||||
if (buffer->use_once == _gf_true &&
|
||||
buffer->used_len == buffer->size_buffer) {
|
||||
gf_msg("circ-buff", GF_LOG_WARNING, 0, LG_MSG_BUFFER_ERROR,
|
||||
"buffer %p is use once buffer", buffer);
|
||||
return -1;
|
||||
} else {
|
||||
if (buffer->used_len == buffer->size_buffer) {
|
||||
if (buffer->cb[buffer->w_index]) {
|
||||
ptr = buffer->cb[buffer->w_index];
|
||||
if (ptr->data) {
|
||||
cb_destroy_data(ptr, buffer->destroy_buffer_data);
|
||||
ptr->data = NULL;
|
||||
GF_FREE(ptr);
|
||||
}
|
||||
|
||||
buffer->cb[buffer->w_index] =
|
||||
GF_CALLOC (1, sizeof (circular_buffer_t),
|
||||
gf_common_mt_circular_buffer_t);
|
||||
if (!buffer->cb[buffer->w_index])
|
||||
return -1;
|
||||
|
||||
buffer->cb[buffer->w_index]->data = item;
|
||||
ret = gettimeofday (&buffer->cb[buffer->w_index]->tv, NULL);
|
||||
if (ret == -1)
|
||||
gf_msg_callingfn ("circ-buff", GF_LOG_WARNING, 0,
|
||||
LG_MSG_GETTIMEOFDAY_FAILED,
|
||||
"getting time of the day failed");
|
||||
buffer->w_index++;
|
||||
buffer->w_index %= buffer->size_buffer;
|
||||
//used_buffer size cannot be greater than the total buffer size
|
||||
|
||||
if (buffer->used_len < buffer->size_buffer)
|
||||
buffer->used_len++;
|
||||
return buffer->w_index;
|
||||
buffer->cb[buffer->w_index] = NULL;
|
||||
ptr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
buffer->cb[buffer->w_index] = GF_CALLOC(1, sizeof(circular_buffer_t),
|
||||
gf_common_mt_circular_buffer_t);
|
||||
if (!buffer->cb[buffer->w_index])
|
||||
return -1;
|
||||
|
||||
buffer->cb[buffer->w_index]->data = item;
|
||||
ret = gettimeofday(&buffer->cb[buffer->w_index]->tv, NULL);
|
||||
if (ret == -1)
|
||||
gf_msg_callingfn("circ-buff", GF_LOG_WARNING, 0,
|
||||
LG_MSG_GETTIMEOFDAY_FAILED,
|
||||
"getting time of the day failed");
|
||||
buffer->w_index++;
|
||||
buffer->w_index %= buffer->size_buffer;
|
||||
// used_buffer size cannot be greater than the total buffer size
|
||||
|
||||
if (buffer->used_len < buffer->size_buffer)
|
||||
buffer->used_len++;
|
||||
return buffer->w_index;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
cb_add_entry_buffer (buffer_t *buffer, void *item)
|
||||
cb_add_entry_buffer(buffer_t *buffer, void *item)
|
||||
{
|
||||
int write_index = -1;
|
||||
int write_index = -1;
|
||||
|
||||
pthread_mutex_lock (&buffer->lock);
|
||||
{
|
||||
write_index = __cb_add_entry_buffer (buffer, item);
|
||||
}
|
||||
pthread_mutex_unlock (&buffer->lock);
|
||||
pthread_mutex_lock(&buffer->lock);
|
||||
{
|
||||
write_index = __cb_add_entry_buffer(buffer, item);
|
||||
}
|
||||
pthread_mutex_unlock(&buffer->lock);
|
||||
|
||||
return write_index;
|
||||
return write_index;
|
||||
}
|
||||
|
||||
void
|
||||
cb_buffer_show (buffer_t *buffer)
|
||||
cb_buffer_show(buffer_t *buffer)
|
||||
{
|
||||
pthread_mutex_lock (&buffer->lock);
|
||||
{
|
||||
gf_msg_debug ("circ-buff", 0, "w_index: %d, size: %"
|
||||
GF_PRI_SIZET" used_buffer: %d", buffer->w_index,
|
||||
buffer->size_buffer, buffer->used_len);
|
||||
}
|
||||
pthread_mutex_unlock (&buffer->lock);
|
||||
pthread_mutex_lock(&buffer->lock);
|
||||
{
|
||||
gf_msg_debug("circ-buff", 0,
|
||||
"w_index: %d, size: %" GF_PRI_SIZET " used_buffer: %d",
|
||||
buffer->w_index, buffer->size_buffer, buffer->used_len);
|
||||
}
|
||||
pthread_mutex_unlock(&buffer->lock);
|
||||
}
|
||||
|
||||
void
|
||||
cb_buffer_dump (buffer_t *buffer, void *data,
|
||||
int (fn) (circular_buffer_t *buffer, void *data))
|
||||
cb_buffer_dump(buffer_t *buffer, void *data,
|
||||
int(fn)(circular_buffer_t *buffer, void *data))
|
||||
{
|
||||
int index = 0;
|
||||
circular_buffer_t *entry = NULL;
|
||||
int entries = 0;
|
||||
int ul = 0;
|
||||
int w_ind = 0;
|
||||
int size_buff = 0;
|
||||
int i = 0;
|
||||
int index = 0;
|
||||
circular_buffer_t *entry = NULL;
|
||||
int entries = 0;
|
||||
int ul = 0;
|
||||
int w_ind = 0;
|
||||
int size_buff = 0;
|
||||
int i = 0;
|
||||
|
||||
ul = buffer->used_len;
|
||||
w_ind = buffer->w_index;
|
||||
size_buff = buffer->size_buffer;
|
||||
ul = buffer->used_len;
|
||||
w_ind = buffer->w_index;
|
||||
size_buff = buffer->size_buffer;
|
||||
|
||||
pthread_mutex_lock (&buffer->lock);
|
||||
{
|
||||
if (buffer->use_once == _gf_false) {
|
||||
index = (size_buff + (w_ind - ul))%size_buff;
|
||||
for (entries = 0; entries < buffer->used_len;
|
||||
entries++) {
|
||||
entry = buffer->cb[index];
|
||||
if (entry)
|
||||
fn (entry, data);
|
||||
else
|
||||
gf_msg_callingfn ("circ-buff",
|
||||
GF_LOG_WARNING, 0,
|
||||
LG_MSG_NULL_PTR,
|
||||
"Null entry in "
|
||||
"circular buffer at "
|
||||
"index %d.", index);
|
||||
pthread_mutex_lock(&buffer->lock);
|
||||
{
|
||||
if (buffer->use_once == _gf_false) {
|
||||
index = (size_buff + (w_ind - ul)) % size_buff;
|
||||
for (entries = 0; entries < buffer->used_len; entries++) {
|
||||
entry = buffer->cb[index];
|
||||
if (entry)
|
||||
fn(entry, data);
|
||||
else
|
||||
gf_msg_callingfn("circ-buff", GF_LOG_WARNING, 0,
|
||||
LG_MSG_NULL_PTR,
|
||||
"Null entry in "
|
||||
"circular buffer at "
|
||||
"index %d.",
|
||||
index);
|
||||
|
||||
index++;
|
||||
index %= buffer->size_buffer;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < buffer->used_len ; i++) {
|
||||
entry = buffer->cb[i];
|
||||
fn (entry, data);
|
||||
}
|
||||
}
|
||||
index++;
|
||||
index %= buffer->size_buffer;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < buffer->used_len; i++) {
|
||||
entry = buffer->cb[i];
|
||||
fn(entry, data);
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock (&buffer->lock);
|
||||
}
|
||||
pthread_mutex_unlock(&buffer->lock);
|
||||
}
|
||||
|
||||
buffer_t *
|
||||
cb_buffer_new (size_t buffer_size, gf_boolean_t use_once,
|
||||
void (*destroy_buffer_data) (void *data))
|
||||
cb_buffer_new(size_t buffer_size, gf_boolean_t use_once,
|
||||
void (*destroy_buffer_data)(void *data))
|
||||
{
|
||||
buffer_t *buffer = NULL;
|
||||
buffer_t *buffer = NULL;
|
||||
|
||||
buffer = GF_CALLOC (1, sizeof (*buffer), gf_common_mt_buffer_t);
|
||||
if (!buffer) {
|
||||
goto out;
|
||||
}
|
||||
buffer = GF_CALLOC(1, sizeof(*buffer), gf_common_mt_buffer_t);
|
||||
if (!buffer) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
buffer->cb = GF_CALLOC (buffer_size,
|
||||
sizeof (circular_buffer_t *),
|
||||
gf_common_mt_circular_buffer_t);
|
||||
if (!buffer->cb) {
|
||||
GF_FREE (buffer);
|
||||
buffer = NULL;
|
||||
goto out;
|
||||
}
|
||||
buffer->cb = GF_CALLOC(buffer_size, sizeof(circular_buffer_t *),
|
||||
gf_common_mt_circular_buffer_t);
|
||||
if (!buffer->cb) {
|
||||
GF_FREE(buffer);
|
||||
buffer = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
buffer->w_index = 0;
|
||||
buffer->size_buffer = buffer_size;
|
||||
buffer->use_once = use_once;
|
||||
buffer->used_len = 0;
|
||||
buffer->destroy_buffer_data = destroy_buffer_data;
|
||||
pthread_mutex_init (&buffer->lock, NULL);
|
||||
buffer->w_index = 0;
|
||||
buffer->size_buffer = buffer_size;
|
||||
buffer->use_once = use_once;
|
||||
buffer->used_len = 0;
|
||||
buffer->destroy_buffer_data = destroy_buffer_data;
|
||||
pthread_mutex_init(&buffer->lock, NULL);
|
||||
|
||||
out:
|
||||
return buffer;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void
|
||||
cb_buffer_destroy (buffer_t *buffer)
|
||||
cb_buffer_destroy(buffer_t *buffer)
|
||||
{
|
||||
int i = 0;
|
||||
circular_buffer_t *ptr = NULL;
|
||||
if (buffer) {
|
||||
if (buffer->cb) {
|
||||
for (i = 0; i < buffer->used_len ; i++) {
|
||||
ptr = buffer->cb[i];
|
||||
if (ptr->data) {
|
||||
cb_destroy_data (ptr,
|
||||
buffer->destroy_buffer_data);
|
||||
ptr->data = NULL;
|
||||
GF_FREE (ptr);
|
||||
}
|
||||
}
|
||||
GF_FREE (buffer->cb);
|
||||
int i = 0;
|
||||
circular_buffer_t *ptr = NULL;
|
||||
if (buffer) {
|
||||
if (buffer->cb) {
|
||||
for (i = 0; i < buffer->used_len; i++) {
|
||||
ptr = buffer->cb[i];
|
||||
if (ptr->data) {
|
||||
cb_destroy_data(ptr, buffer->destroy_buffer_data);
|
||||
ptr->data = NULL;
|
||||
GF_FREE(ptr);
|
||||
}
|
||||
pthread_mutex_destroy (&buffer->lock);
|
||||
GF_FREE (buffer);
|
||||
}
|
||||
GF_FREE(buffer->cb);
|
||||
}
|
||||
pthread_mutex_destroy(&buffer->lock);
|
||||
GF_FREE(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -14,125 +14,125 @@
|
||||
#include "dict.h"
|
||||
|
||||
void
|
||||
compound_args_cleanup (compound_args_t *args)
|
||||
compound_args_cleanup(compound_args_t *args)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
if (!args)
|
||||
return;
|
||||
if (!args)
|
||||
return;
|
||||
|
||||
if (args->xdata)
|
||||
dict_unref (args->xdata);
|
||||
if (args->xdata)
|
||||
dict_unref(args->xdata);
|
||||
|
||||
if (args->req_list) {
|
||||
for (i = 0; i < args->fop_length; i++) {
|
||||
args_wipe (&args->req_list[i]);
|
||||
}
|
||||
if (args->req_list) {
|
||||
for (i = 0; i < args->fop_length; i++) {
|
||||
args_wipe(&args->req_list[i]);
|
||||
}
|
||||
}
|
||||
|
||||
GF_FREE (args->enum_list);
|
||||
GF_FREE (args->req_list);
|
||||
GF_FREE (args);
|
||||
GF_FREE(args->enum_list);
|
||||
GF_FREE(args->req_list);
|
||||
GF_FREE(args);
|
||||
}
|
||||
|
||||
void
|
||||
compound_args_cbk_cleanup (compound_args_cbk_t *args_cbk)
|
||||
compound_args_cbk_cleanup(compound_args_cbk_t *args_cbk)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
if (!args_cbk)
|
||||
return;
|
||||
if (!args_cbk)
|
||||
return;
|
||||
|
||||
if (args_cbk->xdata)
|
||||
dict_unref (args_cbk->xdata);
|
||||
if (args_cbk->xdata)
|
||||
dict_unref(args_cbk->xdata);
|
||||
|
||||
if (args_cbk->rsp_list) {
|
||||
for (i = 0; i < args_cbk->fop_length; i++) {
|
||||
args_cbk_wipe (&args_cbk->rsp_list[i]);
|
||||
}
|
||||
if (args_cbk->rsp_list) {
|
||||
for (i = 0; i < args_cbk->fop_length; i++) {
|
||||
args_cbk_wipe(&args_cbk->rsp_list[i]);
|
||||
}
|
||||
}
|
||||
|
||||
GF_FREE (args_cbk->rsp_list);
|
||||
GF_FREE (args_cbk->enum_list);
|
||||
GF_FREE (args_cbk);
|
||||
GF_FREE(args_cbk->rsp_list);
|
||||
GF_FREE(args_cbk->enum_list);
|
||||
GF_FREE(args_cbk);
|
||||
}
|
||||
|
||||
compound_args_cbk_t*
|
||||
compound_args_cbk_alloc (int length, dict_t *xdata)
|
||||
compound_args_cbk_t *
|
||||
compound_args_cbk_alloc(int length, dict_t *xdata)
|
||||
{
|
||||
int i = 0;
|
||||
compound_args_cbk_t *args_cbk = NULL;
|
||||
int i = 0;
|
||||
compound_args_cbk_t *args_cbk = NULL;
|
||||
|
||||
args_cbk = GF_CALLOC (1, sizeof (*args_cbk), gf_mt_compound_rsp_t);
|
||||
if (!args_cbk)
|
||||
return NULL;
|
||||
|
||||
args_cbk->fop_length = length;
|
||||
|
||||
args_cbk->rsp_list = GF_CALLOC (length, sizeof (*args_cbk->rsp_list),
|
||||
gf_mt_default_args_cbk_t);
|
||||
if (!args_cbk->rsp_list)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
args_cbk_init (&args_cbk->rsp_list[i]);
|
||||
}
|
||||
|
||||
args_cbk->enum_list = GF_CALLOC (length, sizeof (*args_cbk->enum_list),
|
||||
gf_common_mt_int);
|
||||
if (!args_cbk->enum_list)
|
||||
goto out;
|
||||
|
||||
if (xdata) {
|
||||
args_cbk->xdata = dict_copy_with_ref (xdata, NULL);
|
||||
if (!args_cbk->xdata)
|
||||
goto out;
|
||||
}
|
||||
|
||||
return args_cbk;
|
||||
out:
|
||||
compound_args_cbk_cleanup (args_cbk);
|
||||
args_cbk = GF_CALLOC(1, sizeof(*args_cbk), gf_mt_compound_rsp_t);
|
||||
if (!args_cbk)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
compound_args_t*
|
||||
compound_fop_alloc (int length, glusterfs_compound_fop_t fop, dict_t *xdata)
|
||||
{
|
||||
compound_args_t *args = NULL;
|
||||
args_cbk->fop_length = length;
|
||||
|
||||
args = GF_CALLOC (1, sizeof (*args), gf_mt_compound_req_t);
|
||||
args_cbk->rsp_list = GF_CALLOC(length, sizeof(*args_cbk->rsp_list),
|
||||
gf_mt_default_args_cbk_t);
|
||||
if (!args_cbk->rsp_list)
|
||||
goto out;
|
||||
|
||||
if (!args)
|
||||
return NULL;
|
||||
for (i = 0; i < length; i++) {
|
||||
args_cbk_init(&args_cbk->rsp_list[i]);
|
||||
}
|
||||
|
||||
/* fop_enum can be used by xlators to see which fops are
|
||||
* included as part of compound fop. This will help in checking
|
||||
* for compatibility or support without going through the entire
|
||||
* fop list packed.
|
||||
*/
|
||||
args->fop_enum = fop;
|
||||
args->fop_length = length;
|
||||
args_cbk->enum_list = GF_CALLOC(length, sizeof(*args_cbk->enum_list),
|
||||
gf_common_mt_int);
|
||||
if (!args_cbk->enum_list)
|
||||
goto out;
|
||||
|
||||
args->enum_list = GF_CALLOC (length, sizeof (*args->enum_list),
|
||||
gf_common_mt_int);
|
||||
if (xdata) {
|
||||
args_cbk->xdata = dict_copy_with_ref(xdata, NULL);
|
||||
if (!args_cbk->xdata)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!args->enum_list)
|
||||
goto out;
|
||||
|
||||
args->req_list = GF_CALLOC (length, sizeof (*args->req_list),
|
||||
gf_mt_default_args_t);
|
||||
|
||||
if (!args->req_list)
|
||||
goto out;
|
||||
|
||||
if (xdata) {
|
||||
args->xdata = dict_copy_with_ref (xdata, args->xdata);
|
||||
if (!args->xdata)
|
||||
goto out;
|
||||
}
|
||||
|
||||
return args;
|
||||
return args_cbk;
|
||||
out:
|
||||
compound_args_cleanup (args);
|
||||
return NULL;
|
||||
compound_args_cbk_cleanup(args_cbk);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
compound_args_t *
|
||||
compound_fop_alloc(int length, glusterfs_compound_fop_t fop, dict_t *xdata)
|
||||
{
|
||||
compound_args_t *args = NULL;
|
||||
|
||||
args = GF_CALLOC(1, sizeof(*args), gf_mt_compound_req_t);
|
||||
|
||||
if (!args)
|
||||
return NULL;
|
||||
|
||||
/* fop_enum can be used by xlators to see which fops are
|
||||
* included as part of compound fop. This will help in checking
|
||||
* for compatibility or support without going through the entire
|
||||
* fop list packed.
|
||||
*/
|
||||
args->fop_enum = fop;
|
||||
args->fop_length = length;
|
||||
|
||||
args->enum_list = GF_CALLOC(length, sizeof(*args->enum_list),
|
||||
gf_common_mt_int);
|
||||
|
||||
if (!args->enum_list)
|
||||
goto out;
|
||||
|
||||
args->req_list = GF_CALLOC(length, sizeof(*args->req_list),
|
||||
gf_mt_default_args_t);
|
||||
|
||||
if (!args->req_list)
|
||||
goto out;
|
||||
|
||||
if (xdata) {
|
||||
args->xdata = dict_copy_with_ref(xdata, args->xdata);
|
||||
if (!args->xdata)
|
||||
goto out;
|
||||
}
|
||||
|
||||
return args;
|
||||
out:
|
||||
compound_args_cleanup(args);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -15,82 +15,82 @@
|
||||
#include "timer-wheel.h"
|
||||
|
||||
glusterfs_ctx_t *
|
||||
glusterfs_ctx_new ()
|
||||
glusterfs_ctx_new()
|
||||
{
|
||||
int ret = 0;
|
||||
glusterfs_ctx_t *ctx = NULL;
|
||||
int ret = 0;
|
||||
glusterfs_ctx_t *ctx = NULL;
|
||||
|
||||
/* no GF_CALLOC here, gf_acct_mem_set_enable is not
|
||||
yet decided at this point */
|
||||
ctx = calloc (1, sizeof (*ctx));
|
||||
if (!ctx) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
/* no GF_CALLOC here, gf_acct_mem_set_enable is not
|
||||
yet decided at this point */
|
||||
ctx = calloc(1, sizeof(*ctx));
|
||||
if (!ctx) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ctx->mem_acct_enable = gf_global_mem_acct_enable_get();
|
||||
ctx->mem_acct_enable = gf_global_mem_acct_enable_get();
|
||||
|
||||
INIT_LIST_HEAD (&ctx->graphs);
|
||||
INIT_LIST_HEAD (&ctx->mempool_list);
|
||||
INIT_LIST_HEAD (&ctx->volfile_list);
|
||||
INIT_LIST_HEAD(&ctx->graphs);
|
||||
INIT_LIST_HEAD(&ctx->mempool_list);
|
||||
INIT_LIST_HEAD(&ctx->volfile_list);
|
||||
|
||||
ctx->daemon_pipe[0] = -1;
|
||||
ctx->daemon_pipe[1] = -1;
|
||||
ctx->daemon_pipe[0] = -1;
|
||||
ctx->daemon_pipe[1] = -1;
|
||||
|
||||
ctx->log.loglevel = DEFAULT_LOG_LEVEL;
|
||||
ctx->log.loglevel = DEFAULT_LOG_LEVEL;
|
||||
|
||||
#ifdef RUN_WITH_VALGRIND
|
||||
ctx->cmd_args.valgrind = _gf_true;
|
||||
ctx->cmd_args.valgrind = _gf_true;
|
||||
#endif
|
||||
|
||||
/* lock is never destroyed! */
|
||||
ret = LOCK_INIT (&ctx->lock);
|
||||
if (ret) {
|
||||
free (ctx);
|
||||
ctx = NULL;
|
||||
goto out;
|
||||
}
|
||||
/* lock is never destroyed! */
|
||||
ret = LOCK_INIT(&ctx->lock);
|
||||
if (ret) {
|
||||
free(ctx);
|
||||
ctx = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
GF_ATOMIC_INIT (ctx->stats.max_dict_pairs, 0);
|
||||
GF_ATOMIC_INIT (ctx->stats.total_pairs_used, 0);
|
||||
GF_ATOMIC_INIT (ctx->stats.total_dicts_used, 0);
|
||||
GF_ATOMIC_INIT(ctx->stats.max_dict_pairs, 0);
|
||||
GF_ATOMIC_INIT(ctx->stats.total_pairs_used, 0);
|
||||
GF_ATOMIC_INIT(ctx->stats.total_dicts_used, 0);
|
||||
out:
|
||||
return ctx;
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static void
|
||||
glusterfs_ctx_tw_destroy (struct gf_ctx_tw *ctx_tw)
|
||||
glusterfs_ctx_tw_destroy(struct gf_ctx_tw *ctx_tw)
|
||||
{
|
||||
if (ctx_tw->timer_wheel)
|
||||
gf_tw_cleanup_timers (ctx_tw->timer_wheel);
|
||||
if (ctx_tw->timer_wheel)
|
||||
gf_tw_cleanup_timers(ctx_tw->timer_wheel);
|
||||
|
||||
GF_FREE (ctx_tw);
|
||||
GF_FREE(ctx_tw);
|
||||
}
|
||||
|
||||
struct tvec_base*
|
||||
glusterfs_ctx_tw_get (glusterfs_ctx_t *ctx)
|
||||
struct tvec_base *
|
||||
glusterfs_ctx_tw_get(glusterfs_ctx_t *ctx)
|
||||
{
|
||||
struct gf_ctx_tw *ctx_tw = NULL;
|
||||
struct gf_ctx_tw *ctx_tw = NULL;
|
||||
|
||||
LOCK (&ctx->lock);
|
||||
{
|
||||
if (ctx->tw) {
|
||||
ctx_tw = GF_REF_GET (ctx->tw);
|
||||
} else {
|
||||
ctx_tw = GF_CALLOC (1, sizeof (struct gf_ctx_tw),
|
||||
gf_common_mt_tw_ctx);
|
||||
ctx_tw->timer_wheel = gf_tw_init_timers();
|
||||
GF_REF_INIT (ctx_tw, glusterfs_ctx_tw_destroy);
|
||||
ctx->tw = ctx_tw;
|
||||
}
|
||||
LOCK(&ctx->lock);
|
||||
{
|
||||
if (ctx->tw) {
|
||||
ctx_tw = GF_REF_GET(ctx->tw);
|
||||
} else {
|
||||
ctx_tw = GF_CALLOC(1, sizeof(struct gf_ctx_tw),
|
||||
gf_common_mt_tw_ctx);
|
||||
ctx_tw->timer_wheel = gf_tw_init_timers();
|
||||
GF_REF_INIT(ctx_tw, glusterfs_ctx_tw_destroy);
|
||||
ctx->tw = ctx_tw;
|
||||
}
|
||||
UNLOCK (&ctx->lock);
|
||||
}
|
||||
UNLOCK(&ctx->lock);
|
||||
|
||||
return ctx_tw->timer_wheel;
|
||||
return ctx_tw->timer_wheel;
|
||||
}
|
||||
|
||||
void
|
||||
glusterfs_ctx_tw_put (glusterfs_ctx_t *ctx)
|
||||
glusterfs_ctx_tw_put(glusterfs_ctx_t *ctx)
|
||||
{
|
||||
GF_REF_PUT (ctx->tw);
|
||||
GF_REF_PUT(ctx->tw);
|
||||
}
|
||||
|
@ -14,53 +14,53 @@
|
||||
#include "daemon.h"
|
||||
|
||||
int
|
||||
os_daemon_return (int nochdir, int noclose)
|
||||
os_daemon_return(int nochdir, int noclose)
|
||||
{
|
||||
pid_t pid = -1;
|
||||
int ret = -1;
|
||||
FILE *ptr = NULL;
|
||||
pid_t pid = -1;
|
||||
int ret = -1;
|
||||
FILE *ptr = NULL;
|
||||
|
||||
ret = fork();
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = fork();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pid = setsid();
|
||||
pid = setsid();
|
||||
|
||||
if (pid == -1) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
if (pid == -1) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!nochdir)
|
||||
ret = chdir("/");
|
||||
if (!nochdir)
|
||||
ret = chdir("/");
|
||||
|
||||
if (!noclose) {
|
||||
ptr = freopen (DEVNULLPATH, "r", stdin);
|
||||
if (!ptr)
|
||||
goto out;
|
||||
if (!noclose) {
|
||||
ptr = freopen(DEVNULLPATH, "r", stdin);
|
||||
if (!ptr)
|
||||
goto out;
|
||||
|
||||
ptr = freopen (DEVNULLPATH, "w", stdout);
|
||||
if (!ptr)
|
||||
goto out;
|
||||
ptr = freopen(DEVNULLPATH, "w", stdout);
|
||||
if (!ptr)
|
||||
goto out;
|
||||
|
||||
ptr = freopen (DEVNULLPATH, "w", stderr);
|
||||
if (!ptr)
|
||||
goto out;
|
||||
}
|
||||
ptr = freopen(DEVNULLPATH, "w", stderr);
|
||||
if (!ptr)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
ret = 0;
|
||||
out:
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
os_daemon (int nochdir, int noclose)
|
||||
os_daemon(int nochdir, int noclose)
|
||||
{
|
||||
int ret = -1;
|
||||
int ret = -1;
|
||||
|
||||
ret = os_daemon_return (nochdir, noclose);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
ret = os_daemon_return(nochdir, noclose);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
|
||||
_exit (0);
|
||||
_exit(0);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -31,206 +31,191 @@
|
||||
#pragma generate
|
||||
|
||||
struct xlator_fops _default_fops = {
|
||||
.create = default_create,
|
||||
.open = default_open,
|
||||
.stat = default_stat,
|
||||
.readlink = default_readlink,
|
||||
.mknod = default_mknod,
|
||||
.mkdir = default_mkdir,
|
||||
.unlink = default_unlink,
|
||||
.rmdir = default_rmdir,
|
||||
.symlink = default_symlink,
|
||||
.rename = default_rename,
|
||||
.link = default_link,
|
||||
.truncate = default_truncate,
|
||||
.readv = default_readv,
|
||||
.writev = default_writev,
|
||||
.statfs = default_statfs,
|
||||
.flush = default_flush,
|
||||
.fsync = default_fsync,
|
||||
.setxattr = default_setxattr,
|
||||
.getxattr = default_getxattr,
|
||||
.fsetxattr = default_fsetxattr,
|
||||
.fgetxattr = default_fgetxattr,
|
||||
.removexattr = default_removexattr,
|
||||
.fremovexattr = default_fremovexattr,
|
||||
.opendir = default_opendir,
|
||||
.readdir = default_readdir,
|
||||
.readdirp = default_readdirp,
|
||||
.fsyncdir = default_fsyncdir,
|
||||
.access = default_access,
|
||||
.ftruncate = default_ftruncate,
|
||||
.fstat = default_fstat,
|
||||
.lk = default_lk,
|
||||
.inodelk = default_inodelk,
|
||||
.finodelk = default_finodelk,
|
||||
.entrylk = default_entrylk,
|
||||
.fentrylk = default_fentrylk,
|
||||
.lookup = default_lookup,
|
||||
.rchecksum = default_rchecksum,
|
||||
.xattrop = default_xattrop,
|
||||
.fxattrop = default_fxattrop,
|
||||
.setattr = default_setattr,
|
||||
.fsetattr = default_fsetattr,
|
||||
.fallocate = default_fallocate,
|
||||
.discard = default_discard,
|
||||
.zerofill = default_zerofill,
|
||||
.ipc = default_ipc,
|
||||
.seek = default_seek,
|
||||
.create = default_create,
|
||||
.open = default_open,
|
||||
.stat = default_stat,
|
||||
.readlink = default_readlink,
|
||||
.mknod = default_mknod,
|
||||
.mkdir = default_mkdir,
|
||||
.unlink = default_unlink,
|
||||
.rmdir = default_rmdir,
|
||||
.symlink = default_symlink,
|
||||
.rename = default_rename,
|
||||
.link = default_link,
|
||||
.truncate = default_truncate,
|
||||
.readv = default_readv,
|
||||
.writev = default_writev,
|
||||
.statfs = default_statfs,
|
||||
.flush = default_flush,
|
||||
.fsync = default_fsync,
|
||||
.setxattr = default_setxattr,
|
||||
.getxattr = default_getxattr,
|
||||
.fsetxattr = default_fsetxattr,
|
||||
.fgetxattr = default_fgetxattr,
|
||||
.removexattr = default_removexattr,
|
||||
.fremovexattr = default_fremovexattr,
|
||||
.opendir = default_opendir,
|
||||
.readdir = default_readdir,
|
||||
.readdirp = default_readdirp,
|
||||
.fsyncdir = default_fsyncdir,
|
||||
.access = default_access,
|
||||
.ftruncate = default_ftruncate,
|
||||
.fstat = default_fstat,
|
||||
.lk = default_lk,
|
||||
.inodelk = default_inodelk,
|
||||
.finodelk = default_finodelk,
|
||||
.entrylk = default_entrylk,
|
||||
.fentrylk = default_fentrylk,
|
||||
.lookup = default_lookup,
|
||||
.rchecksum = default_rchecksum,
|
||||
.xattrop = default_xattrop,
|
||||
.fxattrop = default_fxattrop,
|
||||
.setattr = default_setattr,
|
||||
.fsetattr = default_fsetattr,
|
||||
.fallocate = default_fallocate,
|
||||
.discard = default_discard,
|
||||
.zerofill = default_zerofill,
|
||||
.ipc = default_ipc,
|
||||
.seek = default_seek,
|
||||
|
||||
.getspec = default_getspec,
|
||||
.getactivelk = default_getactivelk,
|
||||
.setactivelk = default_setactivelk,
|
||||
.put = default_put,
|
||||
.icreate = default_icreate,
|
||||
.namelink = default_namelink,
|
||||
.getspec = default_getspec,
|
||||
.getactivelk = default_getactivelk,
|
||||
.setactivelk = default_setactivelk,
|
||||
.put = default_put,
|
||||
.icreate = default_icreate,
|
||||
.namelink = default_namelink,
|
||||
};
|
||||
struct xlator_fops *default_fops = &_default_fops;
|
||||
|
||||
|
||||
/*
|
||||
* Remaining functions don't follow the fop calling conventions, so they're
|
||||
* not generated.
|
||||
*/
|
||||
|
||||
int32_t
|
||||
default_forget (xlator_t *this, inode_t *inode)
|
||||
default_forget(xlator_t *this, inode_t *inode)
|
||||
{
|
||||
gf_log_callingfn (this->name, GF_LOG_DEBUG, "xlator does not "
|
||||
"implement forget_cbk");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int32_t
|
||||
default_releasedir (xlator_t *this, fd_t *fd)
|
||||
{
|
||||
gf_log_callingfn (this->name, GF_LOG_DEBUG, "xlator does not "
|
||||
"implement releasedir_cbk");
|
||||
return 0;
|
||||
gf_log_callingfn(this->name, GF_LOG_DEBUG,
|
||||
"xlator does not "
|
||||
"implement forget_cbk");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t
|
||||
default_release (xlator_t *this, fd_t *fd)
|
||||
default_releasedir(xlator_t *this, fd_t *fd)
|
||||
{
|
||||
gf_log_callingfn (this->name, GF_LOG_DEBUG, "xlator does not "
|
||||
"implement release_cbk");
|
||||
return 0;
|
||||
gf_log_callingfn(this->name, GF_LOG_DEBUG,
|
||||
"xlator does not "
|
||||
"implement releasedir_cbk");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t
|
||||
default_release(xlator_t *this, fd_t *fd)
|
||||
{
|
||||
gf_log_callingfn(this->name, GF_LOG_DEBUG,
|
||||
"xlator does not "
|
||||
"implement release_cbk");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* notify */
|
||||
int
|
||||
default_notify (xlator_t *this, int32_t event, void *data, ...)
|
||||
default_notify(xlator_t *this, int32_t event, void *data, ...)
|
||||
{
|
||||
GF_UNUSED int ret = 0;
|
||||
switch (event) {
|
||||
GF_UNUSED int ret = 0;
|
||||
switch (event) {
|
||||
case GF_EVENT_PARENT_UP:
|
||||
case GF_EVENT_PARENT_DOWN:
|
||||
{
|
||||
xlator_list_t *list = this->children;
|
||||
case GF_EVENT_PARENT_DOWN: {
|
||||
xlator_list_t *list = this->children;
|
||||
|
||||
while (list) {
|
||||
xlator_notify (list->xlator, event, this);
|
||||
list = list->next;
|
||||
}
|
||||
}
|
||||
break;
|
||||
while (list) {
|
||||
xlator_notify(list->xlator, event, this);
|
||||
list = list->next;
|
||||
}
|
||||
} break;
|
||||
case GF_EVENT_CHILD_CONNECTING:
|
||||
case GF_EVENT_CHILD_DOWN:
|
||||
case GF_EVENT_CHILD_UP:
|
||||
case GF_EVENT_AUTH_FAILED:
|
||||
{
|
||||
xlator_list_t *parent = this->parents;
|
||||
case GF_EVENT_AUTH_FAILED: {
|
||||
xlator_list_t *parent = this->parents;
|
||||
|
||||
/*
|
||||
* Handle case of CHILD_* & AUTH_FAILED event specially, send
|
||||
* it to fuse.
|
||||
*/
|
||||
if (!parent && this->ctx && this->ctx->master) {
|
||||
xlator_notify (this->ctx->master, event, this->graph,
|
||||
NULL);
|
||||
}
|
||||
/*
|
||||
* Handle case of CHILD_* & AUTH_FAILED event specially, send
|
||||
* it to fuse.
|
||||
*/
|
||||
if (!parent && this->ctx && this->ctx->master) {
|
||||
xlator_notify(this->ctx->master, event, this->graph, NULL);
|
||||
}
|
||||
|
||||
while (parent) {
|
||||
if (parent->xlator->init_succeeded)
|
||||
xlator_notify (parent->xlator, event,
|
||||
this, NULL);
|
||||
parent = parent->next;
|
||||
}
|
||||
while (parent) {
|
||||
if (parent->xlator->init_succeeded)
|
||||
xlator_notify(parent->xlator, event, this, NULL);
|
||||
parent = parent->next;
|
||||
}
|
||||
} break;
|
||||
case GF_EVENT_UPCALL: {
|
||||
xlator_list_t *parent = this->parents;
|
||||
|
||||
if (!parent && this->ctx && this->ctx->master)
|
||||
xlator_notify(this->ctx->master, event, data, NULL);
|
||||
|
||||
while (parent) {
|
||||
if (parent->xlator->init_succeeded)
|
||||
xlator_notify(parent->xlator, event, data, NULL);
|
||||
parent = parent->next;
|
||||
}
|
||||
} break;
|
||||
case GF_EVENT_CHILD_PING: {
|
||||
xlator_list_t *parent = this->parents;
|
||||
|
||||
while (parent) {
|
||||
if (parent->xlator->init_succeeded)
|
||||
XLATOR_NOTIFY(ret, parent->xlator, event, this, data);
|
||||
parent = parent->next;
|
||||
}
|
||||
} break;
|
||||
case GF_EVENT_CLEANUP: {
|
||||
xlator_list_t *list = this->children;
|
||||
|
||||
while (list) {
|
||||
xlator_notify(list->xlator, event, this);
|
||||
list = list->next;
|
||||
}
|
||||
} break;
|
||||
|
||||
default: {
|
||||
xlator_list_t *parent = this->parents;
|
||||
|
||||
while (parent) {
|
||||
if (parent->xlator->init_succeeded)
|
||||
xlator_notify(parent->xlator, event, this, NULL);
|
||||
parent = parent->next;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GF_EVENT_UPCALL:
|
||||
{
|
||||
xlator_list_t *parent = this->parents;
|
||||
/*
|
||||
* Apparently our picky-about-everything else coding standard allows
|
||||
* adjacent same-indendation-level close braces. Clearly it has
|
||||
* nothing to do with readability.
|
||||
*/
|
||||
}
|
||||
|
||||
if (!parent && this->ctx && this->ctx->master)
|
||||
xlator_notify (this->ctx->master, event, data, NULL);
|
||||
|
||||
while (parent) {
|
||||
if (parent->xlator->init_succeeded)
|
||||
xlator_notify (parent->xlator, event,
|
||||
data, NULL);
|
||||
parent = parent->next;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GF_EVENT_CHILD_PING:
|
||||
{
|
||||
xlator_list_t *parent = this->parents;
|
||||
|
||||
while (parent) {
|
||||
if (parent->xlator->init_succeeded)
|
||||
XLATOR_NOTIFY (ret, parent->xlator, event,
|
||||
this, data);
|
||||
parent = parent->next;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GF_EVENT_CLEANUP:
|
||||
{
|
||||
xlator_list_t *list = this->children;
|
||||
|
||||
while (list) {
|
||||
xlator_notify (list->xlator, event, this);
|
||||
list = list->next;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
xlator_list_t *parent = this->parents;
|
||||
|
||||
while (parent) {
|
||||
if (parent->xlator->init_succeeded)
|
||||
xlator_notify (parent->xlator, event,
|
||||
this, NULL);
|
||||
parent = parent->next;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Apparently our picky-about-everything else coding standard allows
|
||||
* adjacent same-indendation-level close braces. Clearly it has
|
||||
* nothing to do with readability.
|
||||
*/
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t
|
||||
default_mem_acct_init (xlator_t *this)
|
||||
default_mem_acct_init(xlator_t *this)
|
||||
{
|
||||
int ret = -1;
|
||||
int ret = -1;
|
||||
|
||||
ret = xlator_mem_acct_init (this, gf_common_mt_end);
|
||||
ret = xlator_mem_acct_init(this, gf_common_mt_end);
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
default_fini (xlator_t *this)
|
||||
default_fini(xlator_t *this)
|
||||
{
|
||||
if (this && this->private)
|
||||
GF_FREE (this->private);
|
||||
if (this && this->private)
|
||||
GF_FREE(this->private);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -12,72 +12,71 @@
|
||||
#include "libglusterfs-messages.h"
|
||||
|
||||
eh_t *
|
||||
eh_new (size_t buffer_size, gf_boolean_t use_buffer_once,
|
||||
void (*destroy_buffer_data) (void *data))
|
||||
eh_new(size_t buffer_size, gf_boolean_t use_buffer_once,
|
||||
void (*destroy_buffer_data)(void *data))
|
||||
{
|
||||
eh_t *history = NULL;
|
||||
buffer_t *buffer = NULL;
|
||||
eh_t *history = NULL;
|
||||
buffer_t *buffer = NULL;
|
||||
|
||||
history = GF_CALLOC (1, sizeof (eh_t), gf_common_mt_eh_t);
|
||||
if (!history) {
|
||||
goto out;
|
||||
}
|
||||
history = GF_CALLOC(1, sizeof(eh_t), gf_common_mt_eh_t);
|
||||
if (!history) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
buffer = cb_buffer_new (buffer_size, use_buffer_once,
|
||||
destroy_buffer_data);
|
||||
if (!buffer) {
|
||||
GF_FREE (history);
|
||||
history = NULL;
|
||||
goto out;
|
||||
}
|
||||
buffer = cb_buffer_new(buffer_size, use_buffer_once, destroy_buffer_data);
|
||||
if (!buffer) {
|
||||
GF_FREE(history);
|
||||
history = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
history->buffer = buffer;
|
||||
history->buffer = buffer;
|
||||
|
||||
pthread_mutex_init (&history->lock, NULL);
|
||||
pthread_mutex_init(&history->lock, NULL);
|
||||
out:
|
||||
return history;
|
||||
return history;
|
||||
}
|
||||
|
||||
void
|
||||
eh_dump (eh_t *history, void *data,
|
||||
int (dump_fn) (circular_buffer_t *buffer, void *data))
|
||||
eh_dump(eh_t *history, void *data,
|
||||
int(dump_fn)(circular_buffer_t *buffer, void *data))
|
||||
{
|
||||
if (!history) {
|
||||
gf_msg_debug ("event-history", 0, "history is NULL");
|
||||
goto out;
|
||||
}
|
||||
if (!history) {
|
||||
gf_msg_debug("event-history", 0, "history is NULL");
|
||||
goto out;
|
||||
}
|
||||
|
||||
cb_buffer_dump (history->buffer, data, dump_fn);
|
||||
cb_buffer_dump(history->buffer, data, dump_fn);
|
||||
|
||||
out:
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
eh_save_history (eh_t *history, void *data)
|
||||
eh_save_history(eh_t *history, void *data)
|
||||
{
|
||||
int ret = -1;
|
||||
int ret = -1;
|
||||
|
||||
ret = cb_add_entry_buffer (history->buffer, data);
|
||||
ret = cb_add_entry_buffer(history->buffer, data);
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
eh_destroy (eh_t *history)
|
||||
eh_destroy(eh_t *history)
|
||||
{
|
||||
if (!history) {
|
||||
gf_msg ("event-history", GF_LOG_INFO, 0, LG_MSG_INVALID_ARG,
|
||||
"history for the xlator is NULL");
|
||||
return -1;
|
||||
}
|
||||
if (!history) {
|
||||
gf_msg("event-history", GF_LOG_INFO, 0, LG_MSG_INVALID_ARG,
|
||||
"history for the xlator is NULL");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cb_buffer_destroy (history->buffer);
|
||||
history->buffer = NULL;
|
||||
cb_buffer_destroy(history->buffer);
|
||||
history->buffer = NULL;
|
||||
|
||||
pthread_mutex_destroy (&history->lock);
|
||||
pthread_mutex_destroy(&history->lock);
|
||||
|
||||
GF_FREE (history);
|
||||
GF_FREE(history);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
@ -23,490 +23,469 @@
|
||||
#include "syscall.h"
|
||||
#include "libglusterfs-messages.h"
|
||||
|
||||
|
||||
|
||||
struct event_slot_poll {
|
||||
int fd;
|
||||
int events;
|
||||
void *data;
|
||||
event_handler_t handler;
|
||||
int fd;
|
||||
int events;
|
||||
void *data;
|
||||
event_handler_t handler;
|
||||
};
|
||||
|
||||
static int
|
||||
event_register_poll(struct event_pool *event_pool, int fd,
|
||||
event_handler_t handler, void *data, int poll_in,
|
||||
int poll_out);
|
||||
|
||||
static int
|
||||
event_register_poll (struct event_pool *event_pool, int fd,
|
||||
event_handler_t handler,
|
||||
void *data, int poll_in, int poll_out);
|
||||
|
||||
|
||||
static int
|
||||
__flush_fd (int fd, int idx, int gen, void *data,
|
||||
int poll_in, int poll_out, int poll_err)
|
||||
__flush_fd(int fd, int idx, int gen, void *data, int poll_in, int poll_out,
|
||||
int poll_err)
|
||||
{
|
||||
char buf[64];
|
||||
int ret = -1;
|
||||
|
||||
if (!poll_in)
|
||||
return ret;
|
||||
|
||||
do {
|
||||
ret = sys_read (fd, buf, 64);
|
||||
if (ret == -1 && errno != EAGAIN) {
|
||||
gf_msg ("poll", GF_LOG_ERROR, errno,
|
||||
LG_MSG_FILE_OP_FAILED, "read on %d returned "
|
||||
"error", fd);
|
||||
}
|
||||
} while (ret == 64);
|
||||
char buf[64];
|
||||
int ret = -1;
|
||||
|
||||
if (!poll_in)
|
||||
return ret;
|
||||
|
||||
do {
|
||||
ret = sys_read(fd, buf, 64);
|
||||
if (ret == -1 && errno != EAGAIN) {
|
||||
gf_msg("poll", GF_LOG_ERROR, errno, LG_MSG_FILE_OP_FAILED,
|
||||
"read on %d returned "
|
||||
"error",
|
||||
fd);
|
||||
}
|
||||
} while (ret == 64);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
__event_getindex (struct event_pool *event_pool, int fd, int idx)
|
||||
__event_getindex(struct event_pool *event_pool, int fd, int idx)
|
||||
{
|
||||
int ret = -1;
|
||||
int i = 0;
|
||||
int ret = -1;
|
||||
int i = 0;
|
||||
|
||||
GF_VALIDATE_OR_GOTO ("event", event_pool, out);
|
||||
GF_VALIDATE_OR_GOTO("event", event_pool, out);
|
||||
|
||||
/* lookup in used space based on index provided */
|
||||
if (idx > -1 && idx < event_pool->used) {
|
||||
if (event_pool->reg[idx].fd == fd) {
|
||||
ret = idx;
|
||||
goto out;
|
||||
}
|
||||
/* lookup in used space based on index provided */
|
||||
if (idx > -1 && idx < event_pool->used) {
|
||||
if (event_pool->reg[idx].fd == fd) {
|
||||
ret = idx;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* search in used space, if lookup fails */
|
||||
for (i = 0; i < event_pool->used; i++) {
|
||||
if (event_pool->reg[i].fd == fd) {
|
||||
ret = i;
|
||||
break;
|
||||
}
|
||||
/* search in used space, if lookup fails */
|
||||
for (i = 0; i < event_pool->used; i++) {
|
||||
if (event_pool->reg[i].fd == fd) {
|
||||
ret = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static struct event_pool *
|
||||
event_pool_new_poll (int count, int eventthreadcount)
|
||||
event_pool_new_poll(int count, int eventthreadcount)
|
||||
{
|
||||
struct event_pool *event_pool = NULL;
|
||||
int ret = -1;
|
||||
struct event_pool *event_pool = NULL;
|
||||
int ret = -1;
|
||||
|
||||
event_pool = GF_CALLOC (1, sizeof (*event_pool),
|
||||
gf_common_mt_event_pool);
|
||||
event_pool = GF_CALLOC(1, sizeof(*event_pool), gf_common_mt_event_pool);
|
||||
|
||||
if (!event_pool)
|
||||
return NULL;
|
||||
if (!event_pool)
|
||||
return NULL;
|
||||
|
||||
event_pool->count = count;
|
||||
event_pool->reg = GF_CALLOC (event_pool->count,
|
||||
sizeof (*event_pool->reg),
|
||||
gf_common_mt_reg);
|
||||
event_pool->count = count;
|
||||
event_pool->reg = GF_CALLOC(event_pool->count, sizeof(*event_pool->reg),
|
||||
gf_common_mt_reg);
|
||||
|
||||
if (!event_pool->reg) {
|
||||
GF_FREE (event_pool);
|
||||
return NULL;
|
||||
}
|
||||
if (!event_pool->reg) {
|
||||
GF_FREE(event_pool);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pthread_mutex_init (&event_pool->mutex, NULL);
|
||||
pthread_mutex_init(&event_pool->mutex, NULL);
|
||||
|
||||
ret = pipe (event_pool->breaker);
|
||||
ret = pipe(event_pool->breaker);
|
||||
|
||||
if (ret == -1) {
|
||||
gf_msg ("poll", GF_LOG_ERROR, errno, LG_MSG_PIPE_CREATE_FAILED,
|
||||
"pipe creation failed");
|
||||
GF_FREE (event_pool->reg);
|
||||
GF_FREE (event_pool);
|
||||
return NULL;
|
||||
}
|
||||
if (ret == -1) {
|
||||
gf_msg("poll", GF_LOG_ERROR, errno, LG_MSG_PIPE_CREATE_FAILED,
|
||||
"pipe creation failed");
|
||||
GF_FREE(event_pool->reg);
|
||||
GF_FREE(event_pool);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = fcntl (event_pool->breaker[0], F_SETFL, O_NONBLOCK);
|
||||
if (ret == -1) {
|
||||
gf_msg ("poll", GF_LOG_ERROR, errno, LG_MSG_SET_PIPE_FAILED,
|
||||
"could not set pipe to non blocking mode");
|
||||
sys_close (event_pool->breaker[0]);
|
||||
sys_close (event_pool->breaker[1]);
|
||||
event_pool->breaker[0] = event_pool->breaker[1] = -1;
|
||||
ret = fcntl(event_pool->breaker[0], F_SETFL, O_NONBLOCK);
|
||||
if (ret == -1) {
|
||||
gf_msg("poll", GF_LOG_ERROR, errno, LG_MSG_SET_PIPE_FAILED,
|
||||
"could not set pipe to non blocking mode");
|
||||
sys_close(event_pool->breaker[0]);
|
||||
sys_close(event_pool->breaker[1]);
|
||||
event_pool->breaker[0] = event_pool->breaker[1] = -1;
|
||||
|
||||
GF_FREE (event_pool->reg);
|
||||
GF_FREE (event_pool);
|
||||
return NULL;
|
||||
}
|
||||
GF_FREE(event_pool->reg);
|
||||
GF_FREE(event_pool);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = fcntl (event_pool->breaker[1], F_SETFL, O_NONBLOCK);
|
||||
if (ret == -1) {
|
||||
gf_msg ("poll", GF_LOG_ERROR, errno, LG_MSG_SET_PIPE_FAILED,
|
||||
"could not set pipe to non blocking mode");
|
||||
ret = fcntl(event_pool->breaker[1], F_SETFL, O_NONBLOCK);
|
||||
if (ret == -1) {
|
||||
gf_msg("poll", GF_LOG_ERROR, errno, LG_MSG_SET_PIPE_FAILED,
|
||||
"could not set pipe to non blocking mode");
|
||||
|
||||
sys_close (event_pool->breaker[0]);
|
||||
sys_close (event_pool->breaker[1]);
|
||||
event_pool->breaker[0] = event_pool->breaker[1] = -1;
|
||||
sys_close(event_pool->breaker[0]);
|
||||
sys_close(event_pool->breaker[1]);
|
||||
event_pool->breaker[0] = event_pool->breaker[1] = -1;
|
||||
|
||||
GF_FREE (event_pool->reg);
|
||||
GF_FREE (event_pool);
|
||||
return NULL;
|
||||
}
|
||||
GF_FREE(event_pool->reg);
|
||||
GF_FREE(event_pool);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = event_register_poll (event_pool, event_pool->breaker[0],
|
||||
__flush_fd, NULL, 1, 0);
|
||||
if (ret == -1) {
|
||||
gf_msg ("poll", GF_LOG_ERROR, 0, LG_MSG_REGISTER_PIPE_FAILED,
|
||||
"could not register pipe fd with poll event loop");
|
||||
sys_close (event_pool->breaker[0]);
|
||||
sys_close (event_pool->breaker[1]);
|
||||
event_pool->breaker[0] = event_pool->breaker[1] = -1;
|
||||
ret = event_register_poll(event_pool, event_pool->breaker[0], __flush_fd,
|
||||
NULL, 1, 0);
|
||||
if (ret == -1) {
|
||||
gf_msg("poll", GF_LOG_ERROR, 0, LG_MSG_REGISTER_PIPE_FAILED,
|
||||
"could not register pipe fd with poll event loop");
|
||||
sys_close(event_pool->breaker[0]);
|
||||
sys_close(event_pool->breaker[1]);
|
||||
event_pool->breaker[0] = event_pool->breaker[1] = -1;
|
||||
|
||||
GF_FREE (event_pool->reg);
|
||||
GF_FREE (event_pool);
|
||||
return NULL;
|
||||
}
|
||||
GF_FREE(event_pool->reg);
|
||||
GF_FREE(event_pool);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (eventthreadcount > 1) {
|
||||
gf_msg ("poll", GF_LOG_INFO, 0,
|
||||
LG_MSG_POLL_IGNORE_MULTIPLE_THREADS, "Currently poll "
|
||||
"does not use multiple event processing threads, "
|
||||
"thread count (%d) ignored", eventthreadcount);
|
||||
}
|
||||
if (eventthreadcount > 1) {
|
||||
gf_msg("poll", GF_LOG_INFO, 0, LG_MSG_POLL_IGNORE_MULTIPLE_THREADS,
|
||||
"Currently poll "
|
||||
"does not use multiple event processing threads, "
|
||||
"thread count (%d) ignored",
|
||||
eventthreadcount);
|
||||
}
|
||||
|
||||
/* although, eventhreadcount for poll implementation is always
|
||||
* going to be 1, eventthreadcount needs to be set to 1 so that
|
||||
* rpcsvc_request_handler() thread scaling works flawlessly in
|
||||
* both epoll and poll models
|
||||
*/
|
||||
event_pool->eventthreadcount = 1;
|
||||
/* although, eventhreadcount for poll implementation is always
|
||||
* going to be 1, eventthreadcount needs to be set to 1 so that
|
||||
* rpcsvc_request_handler() thread scaling works flawlessly in
|
||||
* both epoll and poll models
|
||||
*/
|
||||
event_pool->eventthreadcount = 1;
|
||||
|
||||
return event_pool;
|
||||
return event_pool;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
event_register_poll (struct event_pool *event_pool, int fd,
|
||||
event_handler_t handler,
|
||||
void *data, int poll_in, int poll_out)
|
||||
event_register_poll(struct event_pool *event_pool, int fd,
|
||||
event_handler_t handler, void *data, int poll_in,
|
||||
int poll_out)
|
||||
{
|
||||
int idx = -1;
|
||||
int idx = -1;
|
||||
|
||||
GF_VALIDATE_OR_GOTO ("event", event_pool, out);
|
||||
GF_VALIDATE_OR_GOTO("event", event_pool, out);
|
||||
|
||||
pthread_mutex_lock (&event_pool->mutex);
|
||||
{
|
||||
if (event_pool->count == event_pool->used)
|
||||
{
|
||||
event_pool->count += 256;
|
||||
|
||||
event_pool->reg = GF_REALLOC (event_pool->reg,
|
||||
event_pool->count *
|
||||
sizeof (*event_pool->reg));
|
||||
if (!event_pool->reg)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
idx = event_pool->used++;
|
||||
|
||||
event_pool->reg[idx].fd = fd;
|
||||
event_pool->reg[idx].events = POLLPRI;
|
||||
event_pool->reg[idx].handler = handler;
|
||||
event_pool->reg[idx].data = data;
|
||||
|
||||
switch (poll_in) {
|
||||
case 1:
|
||||
event_pool->reg[idx].events |= POLLIN;
|
||||
break;
|
||||
case 0:
|
||||
event_pool->reg[idx].events &= ~POLLIN;
|
||||
break;
|
||||
case -1:
|
||||
/* do nothing */
|
||||
break;
|
||||
default:
|
||||
gf_msg ("poll", GF_LOG_ERROR, 0,
|
||||
LG_MSG_INVALID_POLL_IN,
|
||||
"invalid poll_in value %d", poll_in);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (poll_out) {
|
||||
case 1:
|
||||
event_pool->reg[idx].events |= POLLOUT;
|
||||
break;
|
||||
case 0:
|
||||
event_pool->reg[idx].events &= ~POLLOUT;
|
||||
break;
|
||||
case -1:
|
||||
/* do nothing */
|
||||
break;
|
||||
default:
|
||||
gf_msg ("poll", GF_LOG_ERROR, 0,
|
||||
LG_MSG_INVALID_POLL_OUT,
|
||||
"invalid poll_out value %d", poll_out);
|
||||
break;
|
||||
}
|
||||
|
||||
event_pool->changed = 1;
|
||||
pthread_mutex_lock(&event_pool->mutex);
|
||||
{
|
||||
if (event_pool->count == event_pool->used) {
|
||||
event_pool->count += 256;
|
||||
|
||||
event_pool->reg = GF_REALLOC(
|
||||
event_pool->reg, event_pool->count * sizeof(*event_pool->reg));
|
||||
if (!event_pool->reg)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
idx = event_pool->used++;
|
||||
|
||||
event_pool->reg[idx].fd = fd;
|
||||
event_pool->reg[idx].events = POLLPRI;
|
||||
event_pool->reg[idx].handler = handler;
|
||||
event_pool->reg[idx].data = data;
|
||||
|
||||
switch (poll_in) {
|
||||
case 1:
|
||||
event_pool->reg[idx].events |= POLLIN;
|
||||
break;
|
||||
case 0:
|
||||
event_pool->reg[idx].events &= ~POLLIN;
|
||||
break;
|
||||
case -1:
|
||||
/* do nothing */
|
||||
break;
|
||||
default:
|
||||
gf_msg("poll", GF_LOG_ERROR, 0, LG_MSG_INVALID_POLL_IN,
|
||||
"invalid poll_in value %d", poll_in);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (poll_out) {
|
||||
case 1:
|
||||
event_pool->reg[idx].events |= POLLOUT;
|
||||
break;
|
||||
case 0:
|
||||
event_pool->reg[idx].events &= ~POLLOUT;
|
||||
break;
|
||||
case -1:
|
||||
/* do nothing */
|
||||
break;
|
||||
default:
|
||||
gf_msg("poll", GF_LOG_ERROR, 0, LG_MSG_INVALID_POLL_OUT,
|
||||
"invalid poll_out value %d", poll_out);
|
||||
break;
|
||||
}
|
||||
|
||||
event_pool->changed = 1;
|
||||
}
|
||||
unlock:
|
||||
pthread_mutex_unlock (&event_pool->mutex);
|
||||
pthread_mutex_unlock(&event_pool->mutex);
|
||||
|
||||
out:
|
||||
return idx;
|
||||
return idx;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
event_unregister_poll (struct event_pool *event_pool, int fd, int idx_hint)
|
||||
event_unregister_poll(struct event_pool *event_pool, int fd, int idx_hint)
|
||||
{
|
||||
int idx = -1;
|
||||
int idx = -1;
|
||||
|
||||
GF_VALIDATE_OR_GOTO ("event", event_pool, out);
|
||||
GF_VALIDATE_OR_GOTO("event", event_pool, out);
|
||||
|
||||
pthread_mutex_lock (&event_pool->mutex);
|
||||
{
|
||||
idx = __event_getindex (event_pool, fd, idx_hint);
|
||||
pthread_mutex_lock(&event_pool->mutex);
|
||||
{
|
||||
idx = __event_getindex(event_pool, fd, idx_hint);
|
||||
|
||||
if (idx == -1) {
|
||||
gf_msg ("poll", GF_LOG_ERROR, 0, LG_MSG_INDEX_NOT_FOUND,
|
||||
"index not found for fd=%d (idx_hint=%d)",
|
||||
fd, idx_hint);
|
||||
errno = ENOENT;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
event_pool->reg[idx] = event_pool->reg[--event_pool->used];
|
||||
event_pool->changed = 1;
|
||||
if (idx == -1) {
|
||||
gf_msg("poll", GF_LOG_ERROR, 0, LG_MSG_INDEX_NOT_FOUND,
|
||||
"index not found for fd=%d (idx_hint=%d)", fd, idx_hint);
|
||||
errno = ENOENT;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
event_pool->reg[idx] = event_pool->reg[--event_pool->used];
|
||||
event_pool->changed = 1;
|
||||
}
|
||||
unlock:
|
||||
pthread_mutex_unlock (&event_pool->mutex);
|
||||
pthread_mutex_unlock(&event_pool->mutex);
|
||||
|
||||
out:
|
||||
return idx;
|
||||
return idx;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
event_unregister_close_poll (struct event_pool *event_pool, int fd,
|
||||
int idx_hint)
|
||||
event_unregister_close_poll(struct event_pool *event_pool, int fd, int idx_hint)
|
||||
{
|
||||
int ret = -1;
|
||||
int ret = -1;
|
||||
|
||||
ret = event_unregister_poll (event_pool, fd, idx_hint);
|
||||
ret = event_unregister_poll(event_pool, fd, idx_hint);
|
||||
|
||||
sys_close (fd);
|
||||
sys_close(fd);
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
event_select_on_poll (struct event_pool *event_pool, int fd, int idx_hint,
|
||||
int poll_in, int poll_out)
|
||||
event_select_on_poll(struct event_pool *event_pool, int fd, int idx_hint,
|
||||
int poll_in, int poll_out)
|
||||
{
|
||||
int idx = -1;
|
||||
int idx = -1;
|
||||
|
||||
GF_VALIDATE_OR_GOTO ("event", event_pool, out);
|
||||
GF_VALIDATE_OR_GOTO("event", event_pool, out);
|
||||
|
||||
pthread_mutex_lock (&event_pool->mutex);
|
||||
{
|
||||
idx = __event_getindex (event_pool, fd, idx_hint);
|
||||
pthread_mutex_lock(&event_pool->mutex);
|
||||
{
|
||||
idx = __event_getindex(event_pool, fd, idx_hint);
|
||||
|
||||
if (idx == -1) {
|
||||
gf_msg ("poll", GF_LOG_ERROR, 0, LG_MSG_INDEX_NOT_FOUND,
|
||||
"index not found for fd=%d (idx_hint=%d)",
|
||||
fd, idx_hint);
|
||||
errno = ENOENT;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
switch (poll_in) {
|
||||
case 1:
|
||||
event_pool->reg[idx].events |= POLLIN;
|
||||
break;
|
||||
case 0:
|
||||
event_pool->reg[idx].events &= ~POLLIN;
|
||||
break;
|
||||
case -1:
|
||||
/* do nothing */
|
||||
break;
|
||||
default:
|
||||
/* TODO: log error */
|
||||
break;
|
||||
}
|
||||
|
||||
switch (poll_out) {
|
||||
case 1:
|
||||
event_pool->reg[idx].events |= POLLOUT;
|
||||
break;
|
||||
case 0:
|
||||
event_pool->reg[idx].events &= ~POLLOUT;
|
||||
break;
|
||||
case -1:
|
||||
/* do nothing */
|
||||
break;
|
||||
default:
|
||||
/* TODO: log error */
|
||||
break;
|
||||
}
|
||||
|
||||
if (poll_in + poll_out > -2)
|
||||
event_pool->changed = 1;
|
||||
if (idx == -1) {
|
||||
gf_msg("poll", GF_LOG_ERROR, 0, LG_MSG_INDEX_NOT_FOUND,
|
||||
"index not found for fd=%d (idx_hint=%d)", fd, idx_hint);
|
||||
errno = ENOENT;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
switch (poll_in) {
|
||||
case 1:
|
||||
event_pool->reg[idx].events |= POLLIN;
|
||||
break;
|
||||
case 0:
|
||||
event_pool->reg[idx].events &= ~POLLIN;
|
||||
break;
|
||||
case -1:
|
||||
/* do nothing */
|
||||
break;
|
||||
default:
|
||||
/* TODO: log error */
|
||||
break;
|
||||
}
|
||||
|
||||
switch (poll_out) {
|
||||
case 1:
|
||||
event_pool->reg[idx].events |= POLLOUT;
|
||||
break;
|
||||
case 0:
|
||||
event_pool->reg[idx].events &= ~POLLOUT;
|
||||
break;
|
||||
case -1:
|
||||
/* do nothing */
|
||||
break;
|
||||
default:
|
||||
/* TODO: log error */
|
||||
break;
|
||||
}
|
||||
|
||||
if (poll_in + poll_out > -2)
|
||||
event_pool->changed = 1;
|
||||
}
|
||||
unlock:
|
||||
pthread_mutex_unlock (&event_pool->mutex);
|
||||
pthread_mutex_unlock(&event_pool->mutex);
|
||||
|
||||
out:
|
||||
return idx;
|
||||
return idx;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
event_dispatch_poll_handler (struct event_pool *event_pool,
|
||||
struct pollfd *ufds, int i)
|
||||
event_dispatch_poll_handler(struct event_pool *event_pool, struct pollfd *ufds,
|
||||
int i)
|
||||
{
|
||||
event_handler_t handler = NULL;
|
||||
void *data = NULL;
|
||||
int idx = -1;
|
||||
int ret = 0;
|
||||
event_handler_t handler = NULL;
|
||||
void *data = NULL;
|
||||
int idx = -1;
|
||||
int ret = 0;
|
||||
|
||||
handler = NULL;
|
||||
data = NULL;
|
||||
handler = NULL;
|
||||
data = NULL;
|
||||
|
||||
pthread_mutex_lock (&event_pool->mutex);
|
||||
{
|
||||
idx = __event_getindex (event_pool, ufds[i].fd, i);
|
||||
pthread_mutex_lock(&event_pool->mutex);
|
||||
{
|
||||
idx = __event_getindex(event_pool, ufds[i].fd, i);
|
||||
|
||||
if (idx == -1) {
|
||||
gf_msg ("poll", GF_LOG_ERROR, 0,
|
||||
LG_MSG_INDEX_NOT_FOUND, "index not found for "
|
||||
"fd=%d (idx_hint=%d)", ufds[i].fd, i);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
handler = event_pool->reg[idx].handler;
|
||||
data = event_pool->reg[idx].data;
|
||||
if (idx == -1) {
|
||||
gf_msg("poll", GF_LOG_ERROR, 0, LG_MSG_INDEX_NOT_FOUND,
|
||||
"index not found for "
|
||||
"fd=%d (idx_hint=%d)",
|
||||
ufds[i].fd, i);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
handler = event_pool->reg[idx].handler;
|
||||
data = event_pool->reg[idx].data;
|
||||
}
|
||||
unlock:
|
||||
pthread_mutex_unlock (&event_pool->mutex);
|
||||
pthread_mutex_unlock(&event_pool->mutex);
|
||||
|
||||
if (handler)
|
||||
ret = handler (ufds[i].fd, idx, 0, data,
|
||||
(ufds[i].revents & (POLLIN|POLLPRI)),
|
||||
(ufds[i].revents & (POLLOUT)),
|
||||
(ufds[i].revents & (POLLERR|POLLHUP|POLLNVAL)));
|
||||
if (handler)
|
||||
ret = handler(ufds[i].fd, idx, 0, data,
|
||||
(ufds[i].revents & (POLLIN | POLLPRI)),
|
||||
(ufds[i].revents & (POLLOUT)),
|
||||
(ufds[i].revents & (POLLERR | POLLHUP | POLLNVAL)));
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
event_dispatch_poll_resize (struct event_pool *event_pool,
|
||||
struct pollfd *ufds, int size)
|
||||
event_dispatch_poll_resize(struct event_pool *event_pool, struct pollfd *ufds,
|
||||
int size)
|
||||
{
|
||||
int i = 0;
|
||||
int i = 0;
|
||||
|
||||
pthread_mutex_lock (&event_pool->mutex);
|
||||
{
|
||||
if (event_pool->changed == 0) {
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (event_pool->used > event_pool->evcache_size) {
|
||||
GF_FREE (event_pool->evcache);
|
||||
|
||||
event_pool->evcache = ufds = NULL;
|
||||
|
||||
event_pool->evcache_size = event_pool->used;
|
||||
|
||||
ufds = GF_CALLOC (sizeof (struct pollfd),
|
||||
event_pool->evcache_size,
|
||||
gf_common_mt_pollfd);
|
||||
if (!ufds)
|
||||
goto unlock;
|
||||
event_pool->evcache = ufds;
|
||||
}
|
||||
|
||||
if (ufds == NULL) {
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
for (i = 0; i < event_pool->used; i++) {
|
||||
ufds[i].fd = event_pool->reg[i].fd;
|
||||
ufds[i].events = event_pool->reg[i].events;
|
||||
ufds[i].revents = 0;
|
||||
}
|
||||
|
||||
size = i;
|
||||
pthread_mutex_lock(&event_pool->mutex);
|
||||
{
|
||||
if (event_pool->changed == 0) {
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (event_pool->used > event_pool->evcache_size) {
|
||||
GF_FREE(event_pool->evcache);
|
||||
|
||||
event_pool->evcache = ufds = NULL;
|
||||
|
||||
event_pool->evcache_size = event_pool->used;
|
||||
|
||||
ufds = GF_CALLOC(sizeof(struct pollfd), event_pool->evcache_size,
|
||||
gf_common_mt_pollfd);
|
||||
if (!ufds)
|
||||
goto unlock;
|
||||
event_pool->evcache = ufds;
|
||||
}
|
||||
|
||||
if (ufds == NULL) {
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
for (i = 0; i < event_pool->used; i++) {
|
||||
ufds[i].fd = event_pool->reg[i].fd;
|
||||
ufds[i].events = event_pool->reg[i].events;
|
||||
ufds[i].revents = 0;
|
||||
}
|
||||
|
||||
size = i;
|
||||
}
|
||||
unlock:
|
||||
pthread_mutex_unlock (&event_pool->mutex);
|
||||
pthread_mutex_unlock(&event_pool->mutex);
|
||||
|
||||
return size;
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
event_dispatch_poll (struct event_pool *event_pool)
|
||||
event_dispatch_poll(struct event_pool *event_pool)
|
||||
{
|
||||
struct pollfd *ufds = NULL;
|
||||
int size = 0;
|
||||
int i = 0;
|
||||
int ret = -1;
|
||||
struct pollfd *ufds = NULL;
|
||||
int size = 0;
|
||||
int i = 0;
|
||||
int ret = -1;
|
||||
|
||||
GF_VALIDATE_OR_GOTO ("event", event_pool, out);
|
||||
GF_VALIDATE_OR_GOTO("event", event_pool, out);
|
||||
|
||||
pthread_mutex_lock (&event_pool->mutex);
|
||||
pthread_mutex_lock(&event_pool->mutex);
|
||||
{
|
||||
event_pool->activethreadcount = 1;
|
||||
}
|
||||
pthread_mutex_unlock(&event_pool->mutex);
|
||||
|
||||
while (1) {
|
||||
pthread_mutex_lock(&event_pool->mutex);
|
||||
{
|
||||
event_pool->activethreadcount = 1;
|
||||
if (event_pool->destroy == 1) {
|
||||
event_pool->activethreadcount = 0;
|
||||
pthread_cond_broadcast(&event_pool->cond);
|
||||
pthread_mutex_unlock(&event_pool->mutex);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock (&event_pool->mutex);
|
||||
pthread_mutex_unlock(&event_pool->mutex);
|
||||
|
||||
while (1) {
|
||||
pthread_mutex_lock (&event_pool->mutex);
|
||||
{
|
||||
if (event_pool->destroy == 1) {
|
||||
event_pool->activethreadcount = 0;
|
||||
pthread_cond_broadcast (&event_pool->cond);
|
||||
pthread_mutex_unlock (&event_pool->mutex);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock (&event_pool->mutex);
|
||||
size = event_dispatch_poll_resize(event_pool, ufds, size);
|
||||
ufds = event_pool->evcache;
|
||||
|
||||
size = event_dispatch_poll_resize (event_pool, ufds, size);
|
||||
ufds = event_pool->evcache;
|
||||
ret = poll(ufds, size, 1);
|
||||
|
||||
ret = poll (ufds, size, 1);
|
||||
if (ret == 0)
|
||||
/* timeout */
|
||||
continue;
|
||||
|
||||
if (ret == 0)
|
||||
/* timeout */
|
||||
continue;
|
||||
if (ret == -1 && errno == EINTR)
|
||||
/* sys call */
|
||||
continue;
|
||||
|
||||
if (ret == -1 && errno == EINTR)
|
||||
/* sys call */
|
||||
continue;
|
||||
for (i = 0; i < size; i++) {
|
||||
if (!ufds[i].revents)
|
||||
continue;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
if (!ufds[i].revents)
|
||||
continue;
|
||||
|
||||
event_dispatch_poll_handler (event_pool, ufds, i);
|
||||
}
|
||||
event_dispatch_poll_handler(event_pool, ufds, i);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
event_reconfigure_threads_poll (struct event_pool *event_pool, int value)
|
||||
event_reconfigure_threads_poll(struct event_pool *event_pool, int value)
|
||||
{
|
||||
/* No-op for poll */
|
||||
/* No-op for poll */
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This function is the destructor for the event_pool data structure
|
||||
@ -514,33 +493,32 @@ event_reconfigure_threads_poll (struct event_pool *event_pool, int value)
|
||||
* else will lead to crashes.
|
||||
*/
|
||||
static int
|
||||
event_pool_destroy_poll (struct event_pool *event_pool)
|
||||
event_pool_destroy_poll(struct event_pool *event_pool)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = sys_close (event_pool->breaker[0]);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = sys_close (event_pool->breaker[1]);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
event_pool->breaker[0] = event_pool->breaker[1] = -1;
|
||||
|
||||
GF_FREE (event_pool->reg);
|
||||
GF_FREE (event_pool);
|
||||
int ret = 0;
|
||||
|
||||
ret = sys_close(event_pool->breaker[0]);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = sys_close(event_pool->breaker[1]);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
event_pool->breaker[0] = event_pool->breaker[1] = -1;
|
||||
|
||||
GF_FREE(event_pool->reg);
|
||||
GF_FREE(event_pool);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct event_ops event_ops_poll = {
|
||||
.new = event_pool_new_poll,
|
||||
.event_register = event_register_poll,
|
||||
.event_select_on = event_select_on_poll,
|
||||
.event_unregister = event_unregister_poll,
|
||||
.event_unregister_close = event_unregister_close_poll,
|
||||
.event_dispatch = event_dispatch_poll,
|
||||
.event_reconfigure_threads = event_reconfigure_threads_poll,
|
||||
.event_pool_destroy = event_pool_destroy_poll
|
||||
};
|
||||
.new = event_pool_new_poll,
|
||||
.event_register = event_register_poll,
|
||||
.event_select_on = event_select_on_poll,
|
||||
.event_unregister = event_unregister_poll,
|
||||
.event_unregister_close = event_unregister_close_poll,
|
||||
.event_dispatch = event_dispatch_poll,
|
||||
.event_reconfigure_threads = event_reconfigure_threads_poll,
|
||||
.event_pool_destroy = event_pool_destroy_poll};
|
||||
|
@ -23,173 +23,164 @@
|
||||
#include "libglusterfs-messages.h"
|
||||
#include "syscall.h"
|
||||
|
||||
|
||||
|
||||
struct event_pool *
|
||||
event_pool_new (int count, int eventthreadcount)
|
||||
event_pool_new(int count, int eventthreadcount)
|
||||
{
|
||||
struct event_pool *event_pool = NULL;
|
||||
extern struct event_ops event_ops_poll;
|
||||
struct event_pool *event_pool = NULL;
|
||||
extern struct event_ops event_ops_poll;
|
||||
|
||||
#ifdef HAVE_SYS_EPOLL_H
|
||||
extern struct event_ops event_ops_epoll;
|
||||
extern struct event_ops event_ops_epoll;
|
||||
|
||||
event_pool = event_ops_epoll.new (count, eventthreadcount);
|
||||
event_pool = event_ops_epoll.new(count, eventthreadcount);
|
||||
|
||||
if (event_pool) {
|
||||
event_pool->ops = &event_ops_epoll;
|
||||
} else {
|
||||
gf_msg ("event", GF_LOG_WARNING, 0, LG_MSG_FALLBACK_TO_POLL,
|
||||
"falling back to poll based event handling");
|
||||
}
|
||||
if (event_pool) {
|
||||
event_pool->ops = &event_ops_epoll;
|
||||
} else {
|
||||
gf_msg("event", GF_LOG_WARNING, 0, LG_MSG_FALLBACK_TO_POLL,
|
||||
"falling back to poll based event handling");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!event_pool) {
|
||||
event_pool = event_ops_poll.new (count, eventthreadcount);
|
||||
if (!event_pool) {
|
||||
event_pool = event_ops_poll.new(count, eventthreadcount);
|
||||
|
||||
if (event_pool)
|
||||
event_pool->ops = &event_ops_poll;
|
||||
}
|
||||
if (event_pool)
|
||||
event_pool->ops = &event_ops_poll;
|
||||
}
|
||||
|
||||
return event_pool;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
event_register (struct event_pool *event_pool, int fd,
|
||||
event_handler_t handler,
|
||||
void *data, int poll_in, int poll_out)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
GF_VALIDATE_OR_GOTO ("event", event_pool, out);
|
||||
|
||||
ret = event_pool->ops->event_register (event_pool, fd, handler, data,
|
||||
poll_in, poll_out);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
event_unregister (struct event_pool *event_pool, int fd, int idx)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
GF_VALIDATE_OR_GOTO ("event", event_pool, out);
|
||||
|
||||
ret = event_pool->ops->event_unregister (event_pool, fd, idx);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
event_unregister_close (struct event_pool *event_pool, int fd, int idx)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
GF_VALIDATE_OR_GOTO ("event", event_pool, out);
|
||||
|
||||
ret = event_pool->ops->event_unregister_close (event_pool, fd, idx);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
event_select_on (struct event_pool *event_pool, int fd, int idx_hint,
|
||||
int poll_in, int poll_out)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
GF_VALIDATE_OR_GOTO ("event", event_pool, out);
|
||||
|
||||
ret = event_pool->ops->event_select_on (event_pool, fd, idx_hint,
|
||||
poll_in, poll_out);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
event_dispatch (struct event_pool *event_pool)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
GF_VALIDATE_OR_GOTO ("event", event_pool, out);
|
||||
|
||||
ret = event_pool->ops->event_dispatch (event_pool);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
return event_pool;
|
||||
}
|
||||
|
||||
int
|
||||
event_reconfigure_threads (struct event_pool *event_pool, int value)
|
||||
event_register(struct event_pool *event_pool, int fd, event_handler_t handler,
|
||||
void *data, int poll_in, int poll_out)
|
||||
{
|
||||
int ret = -1;
|
||||
int ret = -1;
|
||||
|
||||
GF_VALIDATE_OR_GOTO ("event", event_pool, out);
|
||||
|
||||
/* call event refresh function */
|
||||
ret = event_pool->ops->event_reconfigure_threads (event_pool,
|
||||
value);
|
||||
GF_VALIDATE_OR_GOTO("event", event_pool, out);
|
||||
|
||||
ret = event_pool->ops->event_register(event_pool, fd, handler, data,
|
||||
poll_in, poll_out);
|
||||
out:
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
event_pool_destroy (struct event_pool *event_pool)
|
||||
event_unregister(struct event_pool *event_pool, int fd, int idx)
|
||||
{
|
||||
int ret = -1;
|
||||
int destroy = 0, activethreadcount = 0;
|
||||
int ret = -1;
|
||||
|
||||
GF_VALIDATE_OR_GOTO ("event", event_pool, out);
|
||||
GF_VALIDATE_OR_GOTO("event", event_pool, out);
|
||||
|
||||
pthread_mutex_lock (&event_pool->mutex);
|
||||
{
|
||||
destroy = event_pool->destroy;
|
||||
activethreadcount = event_pool->activethreadcount;
|
||||
}
|
||||
pthread_mutex_unlock (&event_pool->mutex);
|
||||
ret = event_pool->ops->event_unregister(event_pool, fd, idx);
|
||||
|
||||
if (!destroy || (activethreadcount > 0)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = event_pool->ops->event_pool_destroy (event_pool);
|
||||
out:
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
poller_destroy_handler (int fd, int idx, int gen, void *data,
|
||||
int poll_out, int poll_in, int poll_err)
|
||||
event_unregister_close(struct event_pool *event_pool, int fd, int idx)
|
||||
{
|
||||
struct event_destroy_data *destroy = NULL;
|
||||
int readfd = -1, ret = -1;
|
||||
char buf = '\0';
|
||||
int ret = -1;
|
||||
|
||||
destroy = data;
|
||||
readfd = destroy->readfd;
|
||||
if (readfd < 0) {
|
||||
goto out;
|
||||
}
|
||||
GF_VALIDATE_OR_GOTO("event", event_pool, out);
|
||||
|
||||
while (sys_read (readfd, &buf, 1) > 0) {
|
||||
}
|
||||
ret = event_pool->ops->event_unregister_close(event_pool, fd, idx);
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
event_handled (destroy->pool, fd, idx, gen);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
int
|
||||
event_select_on(struct event_pool *event_pool, int fd, int idx_hint,
|
||||
int poll_in, int poll_out)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
GF_VALIDATE_OR_GOTO("event", event_pool, out);
|
||||
|
||||
ret = event_pool->ops->event_select_on(event_pool, fd, idx_hint, poll_in,
|
||||
poll_out);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
event_dispatch(struct event_pool *event_pool)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
GF_VALIDATE_OR_GOTO("event", event_pool, out);
|
||||
|
||||
ret = event_pool->ops->event_dispatch(event_pool);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
event_reconfigure_threads(struct event_pool *event_pool, int value)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
GF_VALIDATE_OR_GOTO("event", event_pool, out);
|
||||
|
||||
/* call event refresh function */
|
||||
ret = event_pool->ops->event_reconfigure_threads(event_pool, value);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
event_pool_destroy(struct event_pool *event_pool)
|
||||
{
|
||||
int ret = -1;
|
||||
int destroy = 0, activethreadcount = 0;
|
||||
|
||||
GF_VALIDATE_OR_GOTO("event", event_pool, out);
|
||||
|
||||
pthread_mutex_lock(&event_pool->mutex);
|
||||
{
|
||||
destroy = event_pool->destroy;
|
||||
activethreadcount = event_pool->activethreadcount;
|
||||
}
|
||||
pthread_mutex_unlock(&event_pool->mutex);
|
||||
|
||||
if (!destroy || (activethreadcount > 0)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = event_pool->ops->event_pool_destroy(event_pool);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
poller_destroy_handler(int fd, int idx, int gen, void *data, int poll_out,
|
||||
int poll_in, int poll_err)
|
||||
{
|
||||
struct event_destroy_data *destroy = NULL;
|
||||
int readfd = -1, ret = -1;
|
||||
char buf = '\0';
|
||||
|
||||
destroy = data;
|
||||
readfd = destroy->readfd;
|
||||
if (readfd < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (sys_read(readfd, &buf, 1) > 0) {
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
event_handled(destroy->pool, fd, idx, gen);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* This function destroys all the poller threads.
|
||||
@ -204,109 +195,111 @@ out:
|
||||
* threads are destroyed)
|
||||
*/
|
||||
int
|
||||
event_dispatch_destroy (struct event_pool *event_pool)
|
||||
event_dispatch_destroy(struct event_pool *event_pool)
|
||||
{
|
||||
int ret = -1, threadcount = 0;
|
||||
int fd[2] = {-1};
|
||||
int idx = -1;
|
||||
int flags = 0;
|
||||
struct timespec sleep_till = {0, };
|
||||
struct event_destroy_data data = {0, };
|
||||
int ret = -1, threadcount = 0;
|
||||
int fd[2] = {-1};
|
||||
int idx = -1;
|
||||
int flags = 0;
|
||||
struct timespec sleep_till = {
|
||||
0,
|
||||
};
|
||||
struct event_destroy_data data = {
|
||||
0,
|
||||
};
|
||||
|
||||
GF_VALIDATE_OR_GOTO ("event", event_pool, out);
|
||||
GF_VALIDATE_OR_GOTO("event", event_pool, out);
|
||||
|
||||
ret = pipe (fd);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
ret = pipe(fd);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
/* Make the read end of the pipe nonblocking */
|
||||
flags = fcntl(fd[0], F_GETFL);
|
||||
flags |= O_NONBLOCK;
|
||||
ret = fcntl(fd[0], F_SETFL, flags);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
/* Make the read end of the pipe nonblocking */
|
||||
flags = fcntl(fd[0], F_GETFL);
|
||||
flags |= O_NONBLOCK;
|
||||
ret = fcntl(fd[0], F_SETFL, flags);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
/* Make the write end of the pipe nonblocking */
|
||||
flags = fcntl(fd[1], F_GETFL);
|
||||
flags |= O_NONBLOCK;
|
||||
ret = fcntl(fd[1], F_SETFL, flags);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
/* Make the write end of the pipe nonblocking */
|
||||
flags = fcntl(fd[1], F_GETFL);
|
||||
flags |= O_NONBLOCK;
|
||||
ret = fcntl(fd[1], F_SETFL, flags);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
data.pool = event_pool;
|
||||
data.readfd = fd[1];
|
||||
data.pool = event_pool;
|
||||
data.readfd = fd[1];
|
||||
|
||||
/* From the main thread register an event on the pipe fd[0],
|
||||
/* From the main thread register an event on the pipe fd[0],
|
||||
*/
|
||||
idx = event_register(event_pool, fd[0], poller_destroy_handler, &data, 1,
|
||||
0);
|
||||
if (idx < 0)
|
||||
goto out;
|
||||
|
||||
/* Enter the destroy mode first, set this before reconfiguring to 0
|
||||
* threads, to prevent further reconfigure to thread count > 0.
|
||||
*/
|
||||
pthread_mutex_lock(&event_pool->mutex);
|
||||
{
|
||||
threadcount = event_pool->eventthreadcount;
|
||||
event_pool->destroy = 1;
|
||||
}
|
||||
pthread_mutex_unlock(&event_pool->mutex);
|
||||
|
||||
ret = event_reconfigure_threads(event_pool, 0);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
/* Write something onto the write end of the pipe(fd[1]) so that
|
||||
* poll wakes up and calls the handler, poller_destroy_handler()
|
||||
*/
|
||||
pthread_mutex_lock(&event_pool->mutex);
|
||||
{
|
||||
/* Write to pipe(fd[1]) and then wait for 1 second or until
|
||||
* a poller thread that is dying, broadcasts. Make sure we
|
||||
* do not loop forever by limiting to 10 retries
|
||||
*/
|
||||
idx = event_register (event_pool, fd[0], poller_destroy_handler,
|
||||
&data, 1, 0);
|
||||
if (idx < 0)
|
||||
goto out;
|
||||
int retry = 0;
|
||||
|
||||
/* Enter the destroy mode first, set this before reconfiguring to 0
|
||||
* threads, to prevent further reconfigure to thread count > 0.
|
||||
*/
|
||||
pthread_mutex_lock (&event_pool->mutex);
|
||||
{
|
||||
threadcount = event_pool->eventthreadcount;
|
||||
event_pool->destroy = 1;
|
||||
while (event_pool->activethreadcount > 0 &&
|
||||
(retry++ < (threadcount + 10))) {
|
||||
if (sys_write(fd[1], "dummy", 6) == -1) {
|
||||
break;
|
||||
}
|
||||
sleep_till.tv_sec = time(NULL) + 1;
|
||||
ret = pthread_cond_timedwait(&event_pool->cond, &event_pool->mutex,
|
||||
&sleep_till);
|
||||
if (ret) {
|
||||
gf_msg_debug("event", 0,
|
||||
"thread cond-timedwait failed "
|
||||
"active-thread-count: %d, "
|
||||
"retry: %d",
|
||||
event_pool->activethreadcount, retry);
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock (&event_pool->mutex);
|
||||
}
|
||||
pthread_mutex_unlock(&event_pool->mutex);
|
||||
|
||||
ret = event_reconfigure_threads (event_pool, 0);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
ret = event_unregister(event_pool, fd[0], idx);
|
||||
|
||||
/* Write something onto the write end of the pipe(fd[1]) so that
|
||||
* poll wakes up and calls the handler, poller_destroy_handler()
|
||||
*/
|
||||
pthread_mutex_lock (&event_pool->mutex);
|
||||
{
|
||||
/* Write to pipe(fd[1]) and then wait for 1 second or until
|
||||
* a poller thread that is dying, broadcasts. Make sure we
|
||||
* do not loop forever by limiting to 10 retries
|
||||
*/
|
||||
int retry = 0;
|
||||
out:
|
||||
if (fd[0] != -1)
|
||||
sys_close(fd[0]);
|
||||
if (fd[1] != -1)
|
||||
sys_close(fd[1]);
|
||||
|
||||
while (event_pool->activethreadcount > 0
|
||||
&& (retry++ < (threadcount + 10))) {
|
||||
if (sys_write (fd[1], "dummy", 6) == -1) {
|
||||
break;
|
||||
}
|
||||
sleep_till.tv_sec = time (NULL) + 1;
|
||||
ret = pthread_cond_timedwait (&event_pool->cond,
|
||||
&event_pool->mutex,
|
||||
&sleep_till);
|
||||
if (ret) {
|
||||
gf_msg_debug ("event", 0,
|
||||
"thread cond-timedwait failed "
|
||||
"active-thread-count: %d, "
|
||||
"retry: %d",
|
||||
event_pool->activethreadcount,
|
||||
retry);
|
||||
}
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock (&event_pool->mutex);
|
||||
|
||||
ret = event_unregister (event_pool, fd[0], idx);
|
||||
|
||||
out:
|
||||
if (fd[0] != -1)
|
||||
sys_close (fd[0]);
|
||||
if (fd[1] != -1)
|
||||
sys_close (fd[1]);
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
event_handled (struct event_pool *event_pool, int fd, int idx, int gen)
|
||||
event_handled(struct event_pool *event_pool, int fd, int idx, int gen)
|
||||
{
|
||||
int ret = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (event_pool->ops->event_handled)
|
||||
ret = event_pool->ops->event_handled (event_pool, fd, idx, gen);
|
||||
if (event_pool->ops->event_handled)
|
||||
ret = event_pool->ops->event_handled(event_pool, fd, idx, gen);
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
@ -25,112 +25,109 @@
|
||||
#include "globals.h"
|
||||
#include "events.h"
|
||||
|
||||
|
||||
#define EVENT_HOST "127.0.0.1"
|
||||
#define EVENT_PORT 24009
|
||||
|
||||
|
||||
int
|
||||
_gf_event (eventtypes_t event, const char *fmt, ...)
|
||||
_gf_event(eventtypes_t event, const char *fmt, ...)
|
||||
{
|
||||
int ret = 0;
|
||||
int sock = -1;
|
||||
char *eventstr = NULL;
|
||||
struct sockaddr_in server;
|
||||
va_list arguments;
|
||||
char *msg = NULL;
|
||||
glusterfs_ctx_t *ctx = NULL;
|
||||
char *host = NULL;
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *result = NULL;
|
||||
int ret = 0;
|
||||
int sock = -1;
|
||||
char *eventstr = NULL;
|
||||
struct sockaddr_in server;
|
||||
va_list arguments;
|
||||
char *msg = NULL;
|
||||
glusterfs_ctx_t *ctx = NULL;
|
||||
char *host = NULL;
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *result = NULL;
|
||||
|
||||
/* Global context */
|
||||
ctx = THIS->ctx;
|
||||
/* Global context */
|
||||
ctx = THIS->ctx;
|
||||
|
||||
if (event < 0 || event >= EVENT_LAST) {
|
||||
ret = EVENT_ERROR_INVALID_INPUTS;
|
||||
goto out;
|
||||
if (event < 0 || event >= EVENT_LAST) {
|
||||
ret = EVENT_ERROR_INVALID_INPUTS;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Initialize UDP socket */
|
||||
sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sock < 0) {
|
||||
ret = EVENT_ERROR_SOCKET;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
|
||||
/* Get Host name to send message */
|
||||
if (ctx && ctx->cmd_args.volfile_server) {
|
||||
/* If it is client code then volfile_server is set
|
||||
use that information to push the events. */
|
||||
if ((getaddrinfo(ctx->cmd_args.volfile_server, NULL, &hints,
|
||||
&result)) != 0) {
|
||||
ret = EVENT_ERROR_RESOLVE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Initialize UDP socket */
|
||||
sock = socket (AF_INET, SOCK_DGRAM, 0);
|
||||
if (sock < 0) {
|
||||
ret = EVENT_ERROR_SOCKET;
|
||||
goto out;
|
||||
if (get_ip_from_addrinfo(result, &host) == NULL) {
|
||||
ret = EVENT_ERROR_RESOLVE;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* Localhost, Use the defined IP for localhost */
|
||||
host = gf_strdup(EVENT_HOST);
|
||||
}
|
||||
|
||||
memset (&hints, 0, sizeof (hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
/* Socket Configurations */
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_port = htons(EVENT_PORT);
|
||||
server.sin_addr.s_addr = inet_addr(host);
|
||||
memset(&server.sin_zero, '\0', sizeof(server.sin_zero));
|
||||
|
||||
/* Get Host name to send message */
|
||||
if (ctx && ctx->cmd_args.volfile_server) {
|
||||
/* If it is client code then volfile_server is set
|
||||
use that information to push the events. */
|
||||
if ((getaddrinfo (ctx->cmd_args.volfile_server,
|
||||
NULL, &hints, &result)) != 0) {
|
||||
ret = EVENT_ERROR_RESOLVE;
|
||||
goto out;
|
||||
}
|
||||
va_start(arguments, fmt);
|
||||
ret = gf_vasprintf(&msg, fmt, arguments);
|
||||
va_end(arguments);
|
||||
|
||||
if (get_ip_from_addrinfo (result, &host) == NULL) {
|
||||
ret = EVENT_ERROR_RESOLVE;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* Localhost, Use the defined IP for localhost */
|
||||
host = gf_strdup (EVENT_HOST);
|
||||
}
|
||||
if (ret < 0) {
|
||||
ret = EVENT_ERROR_INVALID_INPUTS;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Socket Configurations */
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_port = htons (EVENT_PORT);
|
||||
server.sin_addr.s_addr = inet_addr (host);
|
||||
memset (&server.sin_zero, '\0', sizeof (server.sin_zero));
|
||||
ret = gf_asprintf(&eventstr, "%u %d %s", (unsigned)time(NULL), event, msg);
|
||||
|
||||
va_start (arguments, fmt);
|
||||
ret = gf_vasprintf (&msg, fmt, arguments);
|
||||
va_end (arguments);
|
||||
if (ret <= 0) {
|
||||
ret = EVENT_ERROR_MSG_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
ret = EVENT_ERROR_INVALID_INPUTS;
|
||||
goto out;
|
||||
}
|
||||
/* Send Message */
|
||||
if (sendto(sock, eventstr, strlen(eventstr), 0, (struct sockaddr *)&server,
|
||||
sizeof(server)) <= 0) {
|
||||
ret = EVENT_ERROR_SEND;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = gf_asprintf (&eventstr, "%u %d %s",
|
||||
(unsigned)time(NULL), event, msg);
|
||||
ret = EVENT_SEND_OK;
|
||||
|
||||
if (ret <= 0) {
|
||||
ret = EVENT_ERROR_MSG_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
if (sock >= 0) {
|
||||
sys_close(sock);
|
||||
}
|
||||
|
||||
/* Send Message */
|
||||
if (sendto (sock, eventstr, strlen (eventstr),
|
||||
0, (struct sockaddr *)&server, sizeof (server)) <= 0) {
|
||||
ret = EVENT_ERROR_SEND;
|
||||
goto out;
|
||||
}
|
||||
/* Allocated by gf_vasprintf */
|
||||
if (msg)
|
||||
GF_FREE(msg);
|
||||
|
||||
ret = EVENT_SEND_OK;
|
||||
/* Allocated by gf_asprintf */
|
||||
if (eventstr)
|
||||
GF_FREE(eventstr);
|
||||
|
||||
out:
|
||||
if (sock >= 0) {
|
||||
sys_close (sock);
|
||||
}
|
||||
if (host)
|
||||
GF_FREE(host);
|
||||
|
||||
/* Allocated by gf_vasprintf */
|
||||
if (msg)
|
||||
GF_FREE (msg);
|
||||
if (result)
|
||||
freeaddrinfo(result);
|
||||
|
||||
/* Allocated by gf_asprintf */
|
||||
if (eventstr)
|
||||
GF_FREE (eventstr);
|
||||
|
||||
if (host)
|
||||
GF_FREE (host);
|
||||
|
||||
if (result)
|
||||
freeaddrinfo (result);
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
@ -13,430 +13,421 @@
|
||||
#include "libglusterfs-messages.h"
|
||||
|
||||
int32_t
|
||||
_fd_lk_delete_lock (fd_lk_ctx_node_t *lock)
|
||||
_fd_lk_delete_lock(fd_lk_ctx_node_t *lock)
|
||||
{
|
||||
int32_t ret = -1;
|
||||
int32_t ret = -1;
|
||||
|
||||
GF_VALIDATE_OR_GOTO ("fd-lk", lock, out);
|
||||
GF_VALIDATE_OR_GOTO("fd-lk", lock, out);
|
||||
|
||||
list_del_init (&lock->next);
|
||||
list_del_init(&lock->next);
|
||||
|
||||
ret = 0;
|
||||
ret = 0;
|
||||
out:
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t
|
||||
_fd_lk_destroy_lock (fd_lk_ctx_node_t *lock)
|
||||
_fd_lk_destroy_lock(fd_lk_ctx_node_t *lock)
|
||||
{
|
||||
int32_t ret = -1;
|
||||
int32_t ret = -1;
|
||||
|
||||
GF_VALIDATE_OR_GOTO ("fd-lk", lock, out);
|
||||
GF_VALIDATE_OR_GOTO("fd-lk", lock, out);
|
||||
|
||||
GF_FREE (lock);
|
||||
GF_FREE(lock);
|
||||
|
||||
ret = 0;
|
||||
ret = 0;
|
||||
out:
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
_fd_lk_destroy_lock_list (fd_lk_ctx_t *lk_ctx)
|
||||
_fd_lk_destroy_lock_list(fd_lk_ctx_t *lk_ctx)
|
||||
{
|
||||
int ret = -1;
|
||||
fd_lk_ctx_node_t *lk = NULL;
|
||||
fd_lk_ctx_node_t *tmp = NULL;
|
||||
int ret = -1;
|
||||
fd_lk_ctx_node_t *lk = NULL;
|
||||
fd_lk_ctx_node_t *tmp = NULL;
|
||||
|
||||
GF_VALIDATE_OR_GOTO ("fd-lk", lk_ctx, out);
|
||||
GF_VALIDATE_OR_GOTO("fd-lk", lk_ctx, out);
|
||||
|
||||
list_for_each_entry_safe (lk, tmp, &lk_ctx->lk_list, next) {
|
||||
_fd_lk_delete_lock (lk);
|
||||
_fd_lk_destroy_lock (lk);
|
||||
}
|
||||
ret = 0;
|
||||
list_for_each_entry_safe(lk, tmp, &lk_ctx->lk_list, next)
|
||||
{
|
||||
_fd_lk_delete_lock(lk);
|
||||
_fd_lk_destroy_lock(lk);
|
||||
}
|
||||
ret = 0;
|
||||
out:
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
fd_lk_ctx_unref (fd_lk_ctx_t *lk_ctx)
|
||||
fd_lk_ctx_unref(fd_lk_ctx_t *lk_ctx)
|
||||
{
|
||||
int ref = -1;
|
||||
int ref = -1;
|
||||
|
||||
GF_VALIDATE_OR_GOTO ("fd-lk", lk_ctx, err);
|
||||
GF_VALIDATE_OR_GOTO("fd-lk", lk_ctx, err);
|
||||
|
||||
ref = GF_ATOMIC_DEC (lk_ctx->ref);
|
||||
if (ref < 0)
|
||||
GF_ASSERT (!ref);
|
||||
if (ref == 0)
|
||||
_fd_lk_destroy_lock_list (lk_ctx);
|
||||
ref = GF_ATOMIC_DEC(lk_ctx->ref);
|
||||
if (ref < 0)
|
||||
GF_ASSERT(!ref);
|
||||
if (ref == 0)
|
||||
_fd_lk_destroy_lock_list(lk_ctx);
|
||||
|
||||
if (ref == 0) {
|
||||
LOCK_DESTROY (&lk_ctx->lock);
|
||||
GF_FREE (lk_ctx);
|
||||
}
|
||||
if (ref == 0) {
|
||||
LOCK_DESTROY(&lk_ctx->lock);
|
||||
GF_FREE(lk_ctx);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
err:
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd_lk_ctx_t *
|
||||
fd_lk_ctx_ref (fd_lk_ctx_t *lk_ctx)
|
||||
fd_lk_ctx_ref(fd_lk_ctx_t *lk_ctx)
|
||||
{
|
||||
if (!lk_ctx) {
|
||||
gf_msg_callingfn ("fd-lk", GF_LOG_WARNING, EINVAL,
|
||||
LG_MSG_INVALID_ARG, "invalid argument");
|
||||
return NULL;
|
||||
}
|
||||
if (!lk_ctx) {
|
||||
gf_msg_callingfn("fd-lk", GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
|
||||
"invalid argument");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GF_ATOMIC_INC (lk_ctx->ref);
|
||||
GF_ATOMIC_INC(lk_ctx->ref);
|
||||
|
||||
return lk_ctx;
|
||||
return lk_ctx;
|
||||
}
|
||||
|
||||
fd_lk_ctx_t *
|
||||
fd_lk_ctx_create ()
|
||||
fd_lk_ctx_create()
|
||||
{
|
||||
fd_lk_ctx_t *fd_lk_ctx = NULL;
|
||||
fd_lk_ctx_t *fd_lk_ctx = NULL;
|
||||
|
||||
fd_lk_ctx = GF_CALLOC (1, sizeof (fd_lk_ctx_t),
|
||||
gf_common_mt_fd_lk_ctx_t);
|
||||
if (!fd_lk_ctx)
|
||||
goto out;
|
||||
fd_lk_ctx = GF_CALLOC(1, sizeof(fd_lk_ctx_t), gf_common_mt_fd_lk_ctx_t);
|
||||
if (!fd_lk_ctx)
|
||||
goto out;
|
||||
|
||||
INIT_LIST_HEAD (&fd_lk_ctx->lk_list);
|
||||
INIT_LIST_HEAD(&fd_lk_ctx->lk_list);
|
||||
|
||||
LOCK_INIT (&fd_lk_ctx->lock);
|
||||
LOCK_INIT(&fd_lk_ctx->lock);
|
||||
|
||||
fd_lk_ctx = fd_lk_ctx_ref (fd_lk_ctx);
|
||||
fd_lk_ctx = fd_lk_ctx_ref(fd_lk_ctx);
|
||||
out:
|
||||
return fd_lk_ctx;
|
||||
return fd_lk_ctx;
|
||||
}
|
||||
|
||||
int
|
||||
_fd_lk_insert_lock (fd_lk_ctx_t *lk_ctx,
|
||||
fd_lk_ctx_node_t *lock)
|
||||
_fd_lk_insert_lock(fd_lk_ctx_t *lk_ctx, fd_lk_ctx_node_t *lock)
|
||||
{
|
||||
list_add_tail (&lock->next, &lk_ctx->lk_list);
|
||||
return 0;
|
||||
list_add_tail(&lock->next, &lk_ctx->lk_list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static off_t
|
||||
_fd_lk_get_lock_len (off_t start, off_t end)
|
||||
_fd_lk_get_lock_len(off_t start, off_t end)
|
||||
{
|
||||
if (end == LLONG_MAX)
|
||||
return 0;
|
||||
else
|
||||
return (end - start + 1);
|
||||
if (end == LLONG_MAX)
|
||||
return 0;
|
||||
else
|
||||
return (end - start + 1);
|
||||
}
|
||||
|
||||
fd_lk_ctx_node_t *
|
||||
fd_lk_ctx_node_new (int32_t cmd, struct gf_flock *flock)
|
||||
fd_lk_ctx_node_new(int32_t cmd, struct gf_flock *flock)
|
||||
{
|
||||
fd_lk_ctx_node_t *new_lock = NULL;
|
||||
fd_lk_ctx_node_t *new_lock = NULL;
|
||||
|
||||
/* TODO: get from mem-pool */
|
||||
new_lock = GF_CALLOC (1, sizeof (fd_lk_ctx_node_t),
|
||||
gf_common_mt_fd_lk_ctx_node_t);
|
||||
if (!new_lock)
|
||||
goto out;
|
||||
/* TODO: get from mem-pool */
|
||||
new_lock = GF_CALLOC(1, sizeof(fd_lk_ctx_node_t),
|
||||
gf_common_mt_fd_lk_ctx_node_t);
|
||||
if (!new_lock)
|
||||
goto out;
|
||||
|
||||
new_lock->cmd = cmd;
|
||||
new_lock->cmd = cmd;
|
||||
|
||||
if (flock) {
|
||||
new_lock->fl_type = flock->l_type;
|
||||
new_lock->fl_start = flock->l_start;
|
||||
if (flock) {
|
||||
new_lock->fl_type = flock->l_type;
|
||||
new_lock->fl_start = flock->l_start;
|
||||
|
||||
if (flock->l_len == 0)
|
||||
new_lock->fl_end = LLONG_MAX;
|
||||
else
|
||||
new_lock->fl_end = flock->l_start + flock->l_len - 1;
|
||||
if (flock->l_len == 0)
|
||||
new_lock->fl_end = LLONG_MAX;
|
||||
else
|
||||
new_lock->fl_end = flock->l_start + flock->l_len - 1;
|
||||
|
||||
memcpy (&new_lock->user_flock, flock,
|
||||
sizeof (struct gf_flock));
|
||||
}
|
||||
memcpy(&new_lock->user_flock, flock, sizeof(struct gf_flock));
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD (&new_lock->next);
|
||||
INIT_LIST_HEAD(&new_lock->next);
|
||||
out:
|
||||
return new_lock;
|
||||
return new_lock;
|
||||
}
|
||||
|
||||
int32_t
|
||||
_fd_lk_delete_unlck_locks (fd_lk_ctx_t *lk_ctx)
|
||||
_fd_lk_delete_unlck_locks(fd_lk_ctx_t *lk_ctx)
|
||||
{
|
||||
int32_t ret = -1;
|
||||
fd_lk_ctx_node_t *tmp = NULL;
|
||||
fd_lk_ctx_node_t *lk = NULL;
|
||||
int32_t ret = -1;
|
||||
fd_lk_ctx_node_t *tmp = NULL;
|
||||
fd_lk_ctx_node_t *lk = NULL;
|
||||
|
||||
GF_VALIDATE_OR_GOTO ("fd-lk", lk_ctx, out);
|
||||
GF_VALIDATE_OR_GOTO("fd-lk", lk_ctx, out);
|
||||
|
||||
list_for_each_entry_safe (lk, tmp, &lk_ctx->lk_list, next) {
|
||||
if (lk->fl_type == F_UNLCK) {
|
||||
_fd_lk_delete_lock (lk);
|
||||
_fd_lk_destroy_lock (lk);
|
||||
}
|
||||
list_for_each_entry_safe(lk, tmp, &lk_ctx->lk_list, next)
|
||||
{
|
||||
if (lk->fl_type == F_UNLCK) {
|
||||
_fd_lk_delete_lock(lk);
|
||||
_fd_lk_destroy_lock(lk);
|
||||
}
|
||||
}
|
||||
out:
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
fd_lk_overlap (fd_lk_ctx_node_t *l1,
|
||||
fd_lk_ctx_node_t *l2)
|
||||
fd_lk_overlap(fd_lk_ctx_node_t *l1, fd_lk_ctx_node_t *l2)
|
||||
{
|
||||
if (l1->fl_end >= l2->fl_start &&
|
||||
l2->fl_end >= l1->fl_start)
|
||||
return 1;
|
||||
if (l1->fl_end >= l2->fl_start && l2->fl_end >= l1->fl_start)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
fd_lk_ctx_node_t *
|
||||
_fd_lk_add_locks (fd_lk_ctx_node_t *l1,
|
||||
fd_lk_ctx_node_t *l2)
|
||||
_fd_lk_add_locks(fd_lk_ctx_node_t *l1, fd_lk_ctx_node_t *l2)
|
||||
{
|
||||
fd_lk_ctx_node_t *sum = NULL;
|
||||
fd_lk_ctx_node_t *sum = NULL;
|
||||
|
||||
sum = fd_lk_ctx_node_new (0, NULL);
|
||||
if (!sum)
|
||||
goto out;
|
||||
sum = fd_lk_ctx_node_new(0, NULL);
|
||||
if (!sum)
|
||||
goto out;
|
||||
|
||||
sum->fl_start = min (l1->fl_start, l2->fl_start);
|
||||
sum->fl_end = max (l1->fl_end, l2->fl_end);
|
||||
sum->fl_start = min(l1->fl_start, l2->fl_start);
|
||||
sum->fl_end = max(l1->fl_end, l2->fl_end);
|
||||
|
||||
sum->user_flock.l_start = sum->fl_start;
|
||||
sum->user_flock.l_len = _fd_lk_get_lock_len (sum->fl_start,
|
||||
sum->fl_end);
|
||||
sum->user_flock.l_start = sum->fl_start;
|
||||
sum->user_flock.l_len = _fd_lk_get_lock_len(sum->fl_start, sum->fl_end);
|
||||
out:
|
||||
return sum;
|
||||
return sum;
|
||||
}
|
||||
|
||||
/* Subtract two locks */
|
||||
struct _values {
|
||||
fd_lk_ctx_node_t *locks[3];
|
||||
fd_lk_ctx_node_t *locks[3];
|
||||
};
|
||||
|
||||
int32_t
|
||||
_fd_lk_sub_locks (struct _values *v,
|
||||
fd_lk_ctx_node_t *big,
|
||||
fd_lk_ctx_node_t *small)
|
||||
_fd_lk_sub_locks(struct _values *v, fd_lk_ctx_node_t *big,
|
||||
fd_lk_ctx_node_t *small)
|
||||
{
|
||||
int32_t ret = -1;
|
||||
int32_t ret = -1;
|
||||
|
||||
if ((big->fl_start == small->fl_start) &&
|
||||
(big->fl_end == small->fl_end)) {
|
||||
/* both edges coincide with big */
|
||||
v->locks[0] = fd_lk_ctx_node_new (small->cmd, NULL);
|
||||
if (!v->locks[0])
|
||||
goto out;
|
||||
if ((big->fl_start == small->fl_start) && (big->fl_end == small->fl_end)) {
|
||||
/* both edges coincide with big */
|
||||
v->locks[0] = fd_lk_ctx_node_new(small->cmd, NULL);
|
||||
if (!v->locks[0])
|
||||
goto out;
|
||||
|
||||
memcpy (v->locks[0], big, sizeof (fd_lk_ctx_node_t));
|
||||
memcpy(v->locks[0], big, sizeof(fd_lk_ctx_node_t));
|
||||
|
||||
v->locks[0]->fl_type = small->fl_type;
|
||||
v->locks[0]->user_flock.l_type = small->fl_type;
|
||||
} else if ((small->fl_start > big->fl_start) &&
|
||||
(small->fl_end < big->fl_end)) {
|
||||
/* small lock is completely inside big lock,
|
||||
break it down into 3 different locks. */
|
||||
v->locks[0] = fd_lk_ctx_node_new (big->cmd, NULL);
|
||||
if (!v->locks[0])
|
||||
goto out;
|
||||
v->locks[0]->fl_type = small->fl_type;
|
||||
v->locks[0]->user_flock.l_type = small->fl_type;
|
||||
} else if ((small->fl_start > big->fl_start) &&
|
||||
(small->fl_end < big->fl_end)) {
|
||||
/* small lock is completely inside big lock,
|
||||
break it down into 3 different locks. */
|
||||
v->locks[0] = fd_lk_ctx_node_new(big->cmd, NULL);
|
||||
if (!v->locks[0])
|
||||
goto out;
|
||||
|
||||
v->locks[1] = fd_lk_ctx_node_new (small->cmd, NULL);
|
||||
if (!v->locks[1])
|
||||
goto out;
|
||||
v->locks[1] = fd_lk_ctx_node_new(small->cmd, NULL);
|
||||
if (!v->locks[1])
|
||||
goto out;
|
||||
|
||||
v->locks[2] = fd_lk_ctx_node_new (big->cmd, NULL);
|
||||
if (!v->locks[2])
|
||||
goto out;
|
||||
v->locks[2] = fd_lk_ctx_node_new(big->cmd, NULL);
|
||||
if (!v->locks[2])
|
||||
goto out;
|
||||
|
||||
memcpy (v->locks[0], big, sizeof (fd_lk_ctx_node_t));
|
||||
v->locks[0]->fl_end = small->fl_start - 1;
|
||||
v->locks[0]->user_flock.l_len =
|
||||
_fd_lk_get_lock_len (v->locks[0]->fl_start,
|
||||
v->locks[0]->fl_end);
|
||||
memcpy(v->locks[0], big, sizeof(fd_lk_ctx_node_t));
|
||||
v->locks[0]->fl_end = small->fl_start - 1;
|
||||
v->locks[0]->user_flock.l_len = _fd_lk_get_lock_len(
|
||||
v->locks[0]->fl_start, v->locks[0]->fl_end);
|
||||
|
||||
memcpy (v->locks[1], small, sizeof (fd_lk_ctx_node_t));
|
||||
memcpy(v->locks[1], small, sizeof(fd_lk_ctx_node_t));
|
||||
|
||||
memcpy (v->locks[2], big, sizeof (fd_lk_ctx_node_t));
|
||||
v->locks[2]->fl_start = small->fl_end + 1;
|
||||
v->locks[2]->user_flock.l_len =
|
||||
_fd_lk_get_lock_len (v->locks[2]->fl_start,
|
||||
v->locks[2]->fl_end);
|
||||
} else if (small->fl_start == big->fl_start) {
|
||||
/* One of the ends co-incide, break the
|
||||
locks into two separate parts */
|
||||
v->locks[0] = fd_lk_ctx_node_new (small->cmd, NULL);
|
||||
if (!v->locks[0])
|
||||
goto out;
|
||||
memcpy(v->locks[2], big, sizeof(fd_lk_ctx_node_t));
|
||||
v->locks[2]->fl_start = small->fl_end + 1;
|
||||
v->locks[2]->user_flock.l_len = _fd_lk_get_lock_len(
|
||||
v->locks[2]->fl_start, v->locks[2]->fl_end);
|
||||
} else if (small->fl_start == big->fl_start) {
|
||||
/* One of the ends co-incide, break the
|
||||
locks into two separate parts */
|
||||
v->locks[0] = fd_lk_ctx_node_new(small->cmd, NULL);
|
||||
if (!v->locks[0])
|
||||
goto out;
|
||||
|
||||
v->locks[1] = fd_lk_ctx_node_new (big->cmd, NULL);
|
||||
if (!v->locks[1])
|
||||
goto out;
|
||||
v->locks[1] = fd_lk_ctx_node_new(big->cmd, NULL);
|
||||
if (!v->locks[1])
|
||||
goto out;
|
||||
|
||||
memcpy (v->locks[0], small, sizeof (fd_lk_ctx_node_t));
|
||||
memcpy(v->locks[0], small, sizeof(fd_lk_ctx_node_t));
|
||||
|
||||
memcpy (v->locks[1], big, sizeof (fd_lk_ctx_node_t));
|
||||
v->locks[1]->fl_start = small->fl_end + 1;
|
||||
v->locks[1]->user_flock.l_start = small->fl_end + 1;
|
||||
} else if (small->fl_end == big->fl_end) {
|
||||
/* One of the ends co-incide, break the
|
||||
locks into two separate parts */
|
||||
v->locks[0] = fd_lk_ctx_node_new (small->cmd, NULL);
|
||||
if (!v->locks[0])
|
||||
goto out;
|
||||
memcpy(v->locks[1], big, sizeof(fd_lk_ctx_node_t));
|
||||
v->locks[1]->fl_start = small->fl_end + 1;
|
||||
v->locks[1]->user_flock.l_start = small->fl_end + 1;
|
||||
} else if (small->fl_end == big->fl_end) {
|
||||
/* One of the ends co-incide, break the
|
||||
locks into two separate parts */
|
||||
v->locks[0] = fd_lk_ctx_node_new(small->cmd, NULL);
|
||||
if (!v->locks[0])
|
||||
goto out;
|
||||
|
||||
v->locks[1] = fd_lk_ctx_node_new (big->cmd, NULL);
|
||||
if (!v->locks[1])
|
||||
goto out;
|
||||
v->locks[1] = fd_lk_ctx_node_new(big->cmd, NULL);
|
||||
if (!v->locks[1])
|
||||
goto out;
|
||||
|
||||
memcpy (v->locks[0], big, sizeof (fd_lk_ctx_node_t));
|
||||
v->locks[0]->fl_end = small->fl_start - 1;
|
||||
v->locks[0]->user_flock.l_len =
|
||||
_fd_lk_get_lock_len (v->locks[0]->fl_start,
|
||||
v->locks[0]->fl_end);
|
||||
memcpy(v->locks[0], big, sizeof(fd_lk_ctx_node_t));
|
||||
v->locks[0]->fl_end = small->fl_start - 1;
|
||||
v->locks[0]->user_flock.l_len = _fd_lk_get_lock_len(
|
||||
v->locks[0]->fl_start, v->locks[0]->fl_end);
|
||||
|
||||
memcpy (v->locks[1], small, sizeof (fd_lk_ctx_node_t));
|
||||
} else {
|
||||
/* We should never come to this case */
|
||||
GF_ASSERT (!"Invalid case");
|
||||
}
|
||||
ret = 0;
|
||||
memcpy(v->locks[1], small, sizeof(fd_lk_ctx_node_t));
|
||||
} else {
|
||||
/* We should never come to this case */
|
||||
GF_ASSERT(!"Invalid case");
|
||||
}
|
||||
ret = 0;
|
||||
out:
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
_fd_lk_insert_and_merge (fd_lk_ctx_t *lk_ctx,
|
||||
fd_lk_ctx_node_t *lock)
|
||||
_fd_lk_insert_and_merge(fd_lk_ctx_t *lk_ctx, fd_lk_ctx_node_t *lock)
|
||||
{
|
||||
int32_t ret = -1;
|
||||
int32_t i = 0;
|
||||
fd_lk_ctx_node_t *entry = NULL;
|
||||
fd_lk_ctx_node_t *t = NULL;
|
||||
fd_lk_ctx_node_t *sum = NULL;
|
||||
struct _values v = {.locks = {0, 0, 0 }};
|
||||
int32_t ret = -1;
|
||||
int32_t i = 0;
|
||||
fd_lk_ctx_node_t *entry = NULL;
|
||||
fd_lk_ctx_node_t *t = NULL;
|
||||
fd_lk_ctx_node_t *sum = NULL;
|
||||
struct _values v = {.locks = {0, 0, 0}};
|
||||
|
||||
list_for_each_entry_safe (entry, t, &lk_ctx->lk_list, next) {
|
||||
if (!fd_lk_overlap (entry, lock))
|
||||
continue;
|
||||
list_for_each_entry_safe(entry, t, &lk_ctx->lk_list, next)
|
||||
{
|
||||
if (!fd_lk_overlap(entry, lock))
|
||||
continue;
|
||||
|
||||
if (entry->fl_type == lock->fl_type) {
|
||||
sum = _fd_lk_add_locks (entry, lock);
|
||||
if (!sum)
|
||||
return;
|
||||
sum->fl_type = entry->fl_type;
|
||||
sum->user_flock.l_type = entry->fl_type;
|
||||
_fd_lk_delete_lock (entry);
|
||||
_fd_lk_destroy_lock (entry);
|
||||
_fd_lk_destroy_lock (lock);
|
||||
_fd_lk_insert_and_merge (lk_ctx, sum);
|
||||
return;
|
||||
} else {
|
||||
sum = _fd_lk_add_locks (entry, lock);
|
||||
sum->fl_type = lock->fl_type;
|
||||
sum->user_flock.l_type = lock->fl_type;
|
||||
ret = _fd_lk_sub_locks (&v, sum, lock);
|
||||
if (ret)
|
||||
return;
|
||||
_fd_lk_delete_lock (entry);
|
||||
_fd_lk_destroy_lock (entry);
|
||||
|
||||
_fd_lk_delete_lock (lock);
|
||||
_fd_lk_destroy_lock (lock);
|
||||
|
||||
_fd_lk_destroy_lock (sum);
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (!v.locks[i])
|
||||
continue;
|
||||
|
||||
INIT_LIST_HEAD (&v.locks[i]->next);
|
||||
_fd_lk_insert_and_merge (lk_ctx, v.locks[i]);
|
||||
}
|
||||
_fd_lk_delete_unlck_locks (lk_ctx);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* no conflicts, so just insert */
|
||||
if (lock->fl_type != F_UNLCK) {
|
||||
_fd_lk_insert_lock (lk_ctx, lock);
|
||||
if (entry->fl_type == lock->fl_type) {
|
||||
sum = _fd_lk_add_locks(entry, lock);
|
||||
if (!sum)
|
||||
return;
|
||||
sum->fl_type = entry->fl_type;
|
||||
sum->user_flock.l_type = entry->fl_type;
|
||||
_fd_lk_delete_lock(entry);
|
||||
_fd_lk_destroy_lock(entry);
|
||||
_fd_lk_destroy_lock(lock);
|
||||
_fd_lk_insert_and_merge(lk_ctx, sum);
|
||||
return;
|
||||
} else {
|
||||
_fd_lk_destroy_lock (lock);
|
||||
sum = _fd_lk_add_locks(entry, lock);
|
||||
sum->fl_type = lock->fl_type;
|
||||
sum->user_flock.l_type = lock->fl_type;
|
||||
ret = _fd_lk_sub_locks(&v, sum, lock);
|
||||
if (ret)
|
||||
return;
|
||||
_fd_lk_delete_lock(entry);
|
||||
_fd_lk_destroy_lock(entry);
|
||||
|
||||
_fd_lk_delete_lock(lock);
|
||||
_fd_lk_destroy_lock(lock);
|
||||
|
||||
_fd_lk_destroy_lock(sum);
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (!v.locks[i])
|
||||
continue;
|
||||
|
||||
INIT_LIST_HEAD(&v.locks[i]->next);
|
||||
_fd_lk_insert_and_merge(lk_ctx, v.locks[i]);
|
||||
}
|
||||
_fd_lk_delete_unlck_locks(lk_ctx);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* no conflicts, so just insert */
|
||||
if (lock->fl_type != F_UNLCK) {
|
||||
_fd_lk_insert_lock(lk_ctx, lock);
|
||||
} else {
|
||||
_fd_lk_destroy_lock(lock);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_lock_list (fd_lk_ctx_t *lk_ctx)
|
||||
print_lock_list(fd_lk_ctx_t *lk_ctx)
|
||||
{
|
||||
fd_lk_ctx_node_t *lk = NULL;
|
||||
fd_lk_ctx_node_t *lk = NULL;
|
||||
|
||||
gf_msg_debug ("fd-lk", 0, "lock list:");
|
||||
gf_msg_debug("fd-lk", 0, "lock list:");
|
||||
|
||||
list_for_each_entry (lk, &lk_ctx->lk_list, next)
|
||||
gf_msg_debug ("fd-lk", 0, "owner = %s, cmd = %s fl_type = %s,"
|
||||
" fs_start = %"PRId64", fs_end = %"PRId64", "
|
||||
"user_flock: l_type = %s, l_start = %"PRId64", "
|
||||
"l_len = %"PRId64", ",
|
||||
lkowner_utoa (&lk->user_flock.l_owner),
|
||||
get_lk_cmd (lk->cmd), get_lk_type (lk->fl_type),
|
||||
lk->fl_start, lk->fl_end,
|
||||
get_lk_type (lk->user_flock.l_type),
|
||||
lk->user_flock.l_start, lk->user_flock.l_len);
|
||||
list_for_each_entry(lk, &lk_ctx->lk_list, next)
|
||||
gf_msg_debug("fd-lk", 0,
|
||||
"owner = %s, cmd = %s fl_type = %s,"
|
||||
" fs_start = %" PRId64 ", fs_end = %" PRId64
|
||||
", "
|
||||
"user_flock: l_type = %s, l_start = %" PRId64
|
||||
", "
|
||||
"l_len = %" PRId64 ", ",
|
||||
lkowner_utoa(&lk->user_flock.l_owner), get_lk_cmd(lk->cmd),
|
||||
get_lk_type(lk->fl_type), lk->fl_start, lk->fl_end,
|
||||
get_lk_type(lk->user_flock.l_type), lk->user_flock.l_start,
|
||||
lk->user_flock.l_len);
|
||||
}
|
||||
|
||||
int
|
||||
fd_lk_insert_and_merge (fd_t *fd, int32_t cmd,
|
||||
struct gf_flock *flock)
|
||||
fd_lk_insert_and_merge(fd_t *fd, int32_t cmd, struct gf_flock *flock)
|
||||
{
|
||||
int32_t ret = -1;
|
||||
fd_lk_ctx_t *lk_ctx = NULL;
|
||||
fd_lk_ctx_node_t *lk = NULL;
|
||||
int32_t ret = -1;
|
||||
fd_lk_ctx_t *lk_ctx = NULL;
|
||||
fd_lk_ctx_node_t *lk = NULL;
|
||||
|
||||
GF_VALIDATE_OR_GOTO ("fd-lk", fd, out);
|
||||
GF_VALIDATE_OR_GOTO ("fd-lk", flock, out);
|
||||
GF_VALIDATE_OR_GOTO("fd-lk", fd, out);
|
||||
GF_VALIDATE_OR_GOTO("fd-lk", flock, out);
|
||||
|
||||
lk_ctx = fd_lk_ctx_ref (fd->lk_ctx);
|
||||
lk = fd_lk_ctx_node_new (cmd, flock);
|
||||
lk_ctx = fd_lk_ctx_ref(fd->lk_ctx);
|
||||
lk = fd_lk_ctx_node_new(cmd, flock);
|
||||
|
||||
gf_msg_debug ("fd-lk", 0, "new lock request: owner = %s, fl_type = %s"
|
||||
", fs_start = %"PRId64", fs_end = %"PRId64", user_flock:"
|
||||
" l_type = %s, l_start = %"PRId64", l_len = %"PRId64,
|
||||
lkowner_utoa (&flock->l_owner),
|
||||
get_lk_type (lk->fl_type), lk->fl_start, lk->fl_end,
|
||||
get_lk_type (lk->user_flock.l_type),
|
||||
lk->user_flock.l_start, lk->user_flock.l_len);
|
||||
gf_msg_debug("fd-lk", 0,
|
||||
"new lock request: owner = %s, fl_type = %s"
|
||||
", fs_start = %" PRId64 ", fs_end = %" PRId64
|
||||
", user_flock:"
|
||||
" l_type = %s, l_start = %" PRId64 ", l_len = %" PRId64,
|
||||
lkowner_utoa(&flock->l_owner), get_lk_type(lk->fl_type),
|
||||
lk->fl_start, lk->fl_end, get_lk_type(lk->user_flock.l_type),
|
||||
lk->user_flock.l_start, lk->user_flock.l_len);
|
||||
|
||||
LOCK (&lk_ctx->lock);
|
||||
{
|
||||
_fd_lk_insert_and_merge (lk_ctx, lk);
|
||||
print_lock_list (lk_ctx);
|
||||
}
|
||||
UNLOCK (&lk_ctx->lock);
|
||||
LOCK(&lk_ctx->lock);
|
||||
{
|
||||
_fd_lk_insert_and_merge(lk_ctx, lk);
|
||||
print_lock_list(lk_ctx);
|
||||
}
|
||||
UNLOCK(&lk_ctx->lock);
|
||||
|
||||
fd_lk_ctx_unref (lk_ctx);
|
||||
fd_lk_ctx_unref(lk_ctx);
|
||||
|
||||
ret = 0;
|
||||
ret = 0;
|
||||
out:
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
gf_boolean_t
|
||||
fd_lk_ctx_empty (fd_lk_ctx_t *lk_ctx)
|
||||
fd_lk_ctx_empty(fd_lk_ctx_t *lk_ctx)
|
||||
{
|
||||
gf_boolean_t verdict = _gf_true;
|
||||
gf_boolean_t verdict = _gf_true;
|
||||
|
||||
if (!lk_ctx)
|
||||
return _gf_true;
|
||||
if (!lk_ctx)
|
||||
return _gf_true;
|
||||
|
||||
LOCK (&lk_ctx->lock);
|
||||
{
|
||||
verdict = list_empty (&lk_ctx->lk_list);
|
||||
}
|
||||
UNLOCK (&lk_ctx->lock);
|
||||
LOCK(&lk_ctx->lock);
|
||||
{
|
||||
verdict = list_empty(&lk_ctx->lk_list);
|
||||
}
|
||||
UNLOCK(&lk_ctx->lock);
|
||||
|
||||
return verdict;
|
||||
return verdict;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -8,8 +8,6 @@
|
||||
cases as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
@ -22,223 +20,221 @@
|
||||
#define BACKEND_D_OFF_BITS 63
|
||||
#define TOP_BIT (ONE << (PRESENT_D_OFF_BITS - 1))
|
||||
#define MASK (~0ULL)
|
||||
#define SHIFT_BITS (max (0, (BACKEND_D_OFF_BITS - PRESENT_D_OFF_BITS + 1)))
|
||||
#define SHIFT_BITS (max(0, (BACKEND_D_OFF_BITS - PRESENT_D_OFF_BITS + 1)))
|
||||
#define PRESENT_MASK (MASK >> (64 - PRESENT_D_OFF_BITS))
|
||||
|
||||
static uint64_t
|
||||
bits_for (uint64_t num)
|
||||
bits_for(uint64_t num)
|
||||
{
|
||||
uint64_t bits = 0, ctrl = 1;
|
||||
uint64_t bits = 0, ctrl = 1;
|
||||
|
||||
while (ctrl < num) {
|
||||
ctrl *= 2;
|
||||
bits++;
|
||||
}
|
||||
while (ctrl < num) {
|
||||
ctrl *= 2;
|
||||
bits++;
|
||||
}
|
||||
|
||||
return bits;
|
||||
return bits;
|
||||
}
|
||||
|
||||
int
|
||||
gf_deitransform(xlator_t *this,
|
||||
uint64_t offset)
|
||||
gf_deitransform(xlator_t *this, uint64_t offset)
|
||||
{
|
||||
int cnt = 0;
|
||||
int max = 0;
|
||||
int max_bits = 0;
|
||||
uint64_t off_mask = 0;
|
||||
uint64_t host_mask = 0;
|
||||
int cnt = 0;
|
||||
int max = 0;
|
||||
int max_bits = 0;
|
||||
uint64_t off_mask = 0;
|
||||
uint64_t host_mask = 0;
|
||||
|
||||
max = glusterfs_get_leaf_count(this->graph);
|
||||
max = glusterfs_get_leaf_count(this->graph);
|
||||
|
||||
if (max == 1) {
|
||||
cnt = 0;
|
||||
goto out;
|
||||
}
|
||||
if (max == 1) {
|
||||
cnt = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (offset & TOP_BIT) {
|
||||
/* HUGE d_off */
|
||||
max_bits = bits_for (max);
|
||||
off_mask = (MASK << max_bits);
|
||||
host_mask = ~(off_mask);
|
||||
if (offset & TOP_BIT) {
|
||||
/* HUGE d_off */
|
||||
max_bits = bits_for(max);
|
||||
off_mask = (MASK << max_bits);
|
||||
host_mask = ~(off_mask);
|
||||
|
||||
cnt = offset & host_mask;
|
||||
} else {
|
||||
/* small d_off */
|
||||
cnt = offset % max;
|
||||
}
|
||||
cnt = offset & host_mask;
|
||||
} else {
|
||||
/* small d_off */
|
||||
cnt = offset % max;
|
||||
}
|
||||
out:
|
||||
return cnt;
|
||||
return cnt;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
gf_dirent_orig_offset(xlator_t *this,
|
||||
uint64_t offset)
|
||||
gf_dirent_orig_offset(xlator_t *this, uint64_t offset)
|
||||
{
|
||||
int max = 0;
|
||||
int max_bits = 0;
|
||||
uint64_t off_mask = 0;
|
||||
uint64_t orig_offset;
|
||||
int max = 0;
|
||||
int max_bits = 0;
|
||||
uint64_t off_mask = 0;
|
||||
uint64_t orig_offset;
|
||||
|
||||
max = glusterfs_get_leaf_count(this->graph);
|
||||
max = glusterfs_get_leaf_count(this->graph);
|
||||
|
||||
if (max == 1) {
|
||||
orig_offset = offset;
|
||||
goto out;
|
||||
}
|
||||
if (max == 1) {
|
||||
orig_offset = offset;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (offset & TOP_BIT) {
|
||||
/* HUGE d_off */
|
||||
max_bits = bits_for (max);
|
||||
off_mask = (MASK << max_bits);
|
||||
orig_offset = ((offset & ~TOP_BIT) & off_mask) << SHIFT_BITS;
|
||||
} else {
|
||||
/* small d_off */
|
||||
orig_offset = offset / max;
|
||||
}
|
||||
if (offset & TOP_BIT) {
|
||||
/* HUGE d_off */
|
||||
max_bits = bits_for(max);
|
||||
off_mask = (MASK << max_bits);
|
||||
orig_offset = ((offset & ~TOP_BIT) & off_mask) << SHIFT_BITS;
|
||||
} else {
|
||||
/* small d_off */
|
||||
orig_offset = offset / max;
|
||||
}
|
||||
out:
|
||||
return orig_offset;
|
||||
return orig_offset;
|
||||
}
|
||||
|
||||
int
|
||||
gf_itransform (xlator_t *this, uint64_t x, uint64_t *y_p, int client_id)
|
||||
gf_itransform(xlator_t *this, uint64_t x, uint64_t *y_p, int client_id)
|
||||
{
|
||||
int max = 0;
|
||||
uint64_t y = 0;
|
||||
uint64_t hi_mask = 0;
|
||||
uint64_t off_mask = 0;
|
||||
int max_bits = 0;
|
||||
int max = 0;
|
||||
uint64_t y = 0;
|
||||
uint64_t hi_mask = 0;
|
||||
uint64_t off_mask = 0;
|
||||
int max_bits = 0;
|
||||
|
||||
if (x == ((uint64_t) -1)) {
|
||||
y = (uint64_t) -1;
|
||||
goto out;
|
||||
}
|
||||
if (x == ((uint64_t)-1)) {
|
||||
y = (uint64_t)-1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!x) {
|
||||
y = 0;
|
||||
goto out;
|
||||
}
|
||||
if (!x) {
|
||||
y = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
max = glusterfs_get_leaf_count(this->graph);
|
||||
max = glusterfs_get_leaf_count(this->graph);
|
||||
|
||||
if (max == 1) {
|
||||
y = x;
|
||||
goto out;
|
||||
}
|
||||
if (max == 1) {
|
||||
y = x;
|
||||
goto out;
|
||||
}
|
||||
|
||||
max_bits = bits_for (max);
|
||||
max_bits = bits_for(max);
|
||||
|
||||
hi_mask = ~(PRESENT_MASK >> (max_bits + 1));
|
||||
hi_mask = ~(PRESENT_MASK >> (max_bits + 1));
|
||||
|
||||
if (x & hi_mask) {
|
||||
/* HUGE d_off */
|
||||
off_mask = MASK << max_bits;
|
||||
y = TOP_BIT | ((x >> SHIFT_BITS) & off_mask) | client_id;
|
||||
} else {
|
||||
/* small d_off */
|
||||
y = ((x * max) + client_id);
|
||||
}
|
||||
if (x & hi_mask) {
|
||||
/* HUGE d_off */
|
||||
off_mask = MASK << max_bits;
|
||||
y = TOP_BIT | ((x >> SHIFT_BITS) & off_mask) | client_id;
|
||||
} else {
|
||||
/* small d_off */
|
||||
y = ((x * max) + client_id);
|
||||
}
|
||||
|
||||
out:
|
||||
if (y_p)
|
||||
*y_p = y;
|
||||
if (y_p)
|
||||
*y_p = y;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
gf_dirent_t *
|
||||
gf_dirent_for_name (const char *name)
|
||||
gf_dirent_for_name(const char *name)
|
||||
{
|
||||
gf_dirent_t *gf_dirent = NULL;
|
||||
gf_dirent_t *gf_dirent = NULL;
|
||||
|
||||
/* TODO: use mem-pool */
|
||||
gf_dirent = GF_CALLOC (gf_dirent_size (name), 1,
|
||||
gf_common_mt_gf_dirent_t);
|
||||
if (!gf_dirent)
|
||||
return NULL;
|
||||
/* TODO: use mem-pool */
|
||||
gf_dirent = GF_CALLOC(gf_dirent_size(name), 1, gf_common_mt_gf_dirent_t);
|
||||
if (!gf_dirent)
|
||||
return NULL;
|
||||
|
||||
INIT_LIST_HEAD (&gf_dirent->list);
|
||||
strcpy (gf_dirent->d_name, name);
|
||||
INIT_LIST_HEAD(&gf_dirent->list);
|
||||
strcpy(gf_dirent->d_name, name);
|
||||
|
||||
gf_dirent->d_off = 0;
|
||||
gf_dirent->d_ino = -1;
|
||||
gf_dirent->d_type = 0;
|
||||
gf_dirent->d_len = strlen (name);
|
||||
gf_dirent->d_off = 0;
|
||||
gf_dirent->d_ino = -1;
|
||||
gf_dirent->d_type = 0;
|
||||
gf_dirent->d_len = strlen(name);
|
||||
|
||||
return gf_dirent;
|
||||
return gf_dirent;
|
||||
}
|
||||
|
||||
void
|
||||
gf_dirent_entry_free (gf_dirent_t *entry)
|
||||
gf_dirent_entry_free(gf_dirent_t *entry)
|
||||
{
|
||||
if (!entry)
|
||||
return;
|
||||
if (!entry)
|
||||
return;
|
||||
|
||||
if (entry->dict)
|
||||
dict_unref (entry->dict);
|
||||
if (entry->inode)
|
||||
inode_unref (entry->inode);
|
||||
if (entry->dict)
|
||||
dict_unref(entry->dict);
|
||||
if (entry->inode)
|
||||
inode_unref(entry->inode);
|
||||
|
||||
list_del_init (&entry->list);
|
||||
GF_FREE (entry);
|
||||
list_del_init(&entry->list);
|
||||
GF_FREE(entry);
|
||||
}
|
||||
|
||||
void
|
||||
gf_dirent_free (gf_dirent_t *entries)
|
||||
gf_dirent_free(gf_dirent_t *entries)
|
||||
{
|
||||
gf_dirent_t *entry = NULL;
|
||||
gf_dirent_t *tmp = NULL;
|
||||
gf_dirent_t *entry = NULL;
|
||||
gf_dirent_t *tmp = NULL;
|
||||
|
||||
if (!entries)
|
||||
return;
|
||||
if (!entries)
|
||||
return;
|
||||
|
||||
if (list_empty (&entries->list))
|
||||
return;
|
||||
if (list_empty(&entries->list))
|
||||
return;
|
||||
|
||||
list_for_each_entry_safe (entry, tmp, &entries->list, list) {
|
||||
gf_dirent_entry_free (entry);
|
||||
}
|
||||
list_for_each_entry_safe(entry, tmp, &entries->list, list)
|
||||
{
|
||||
gf_dirent_entry_free(entry);
|
||||
}
|
||||
}
|
||||
|
||||
gf_dirent_t *
|
||||
entry_copy (gf_dirent_t *source)
|
||||
entry_copy(gf_dirent_t *source)
|
||||
{
|
||||
gf_dirent_t *sink = NULL;
|
||||
gf_dirent_t *sink = NULL;
|
||||
|
||||
sink = gf_dirent_for_name (source->d_name);
|
||||
if (!sink)
|
||||
return NULL;
|
||||
sink = gf_dirent_for_name(source->d_name);
|
||||
if (!sink)
|
||||
return NULL;
|
||||
|
||||
sink->d_off = source->d_off;
|
||||
sink->d_ino = source->d_ino;
|
||||
sink->d_type = source->d_type;
|
||||
sink->d_stat = source->d_stat;
|
||||
sink->d_len = source->d_len;
|
||||
sink->d_off = source->d_off;
|
||||
sink->d_ino = source->d_ino;
|
||||
sink->d_type = source->d_type;
|
||||
sink->d_stat = source->d_stat;
|
||||
sink->d_len = source->d_len;
|
||||
|
||||
if (source->inode)
|
||||
sink->inode = inode_ref (source->inode);
|
||||
if (source->inode)
|
||||
sink->inode = inode_ref(source->inode);
|
||||
|
||||
if (source->dict)
|
||||
sink->dict = dict_ref (source->dict);
|
||||
return sink;
|
||||
if (source->dict)
|
||||
sink->dict = dict_ref(source->dict);
|
||||
return sink;
|
||||
}
|
||||
|
||||
void
|
||||
gf_link_inode_from_dirent (xlator_t *this, inode_t *parent, gf_dirent_t *entry)
|
||||
gf_link_inode_from_dirent(xlator_t *this, inode_t *parent, gf_dirent_t *entry)
|
||||
{
|
||||
inode_t *link_inode = NULL;
|
||||
inode_t *tmp = NULL;
|
||||
inode_t *link_inode = NULL;
|
||||
inode_t *tmp = NULL;
|
||||
|
||||
if (!entry->inode)
|
||||
return;
|
||||
link_inode = inode_link (entry->inode, parent,
|
||||
entry->d_name, &entry->d_stat);
|
||||
if (!link_inode)
|
||||
return;
|
||||
if (!entry->inode)
|
||||
return;
|
||||
link_inode = inode_link(entry->inode, parent, entry->d_name,
|
||||
&entry->d_stat);
|
||||
if (!link_inode)
|
||||
return;
|
||||
|
||||
inode_lookup (link_inode);
|
||||
tmp = entry->inode;
|
||||
entry->inode = link_inode;
|
||||
inode_unref (tmp);
|
||||
inode_lookup(link_inode);
|
||||
tmp = entry->inode;
|
||||
entry->inode = link_inode;
|
||||
inode_unref(tmp);
|
||||
}
|
||||
|
||||
/* TODO: Currently, with this function, we will be breaking the
|
||||
@ -247,55 +243,60 @@ gf_link_inode_from_dirent (xlator_t *this, inode_t *parent, gf_dirent_t *entry)
|
||||
Need more thoughts before finalizing this function
|
||||
*/
|
||||
int
|
||||
gf_link_inodes_from_dirent (xlator_t *this, inode_t *parent,
|
||||
gf_dirent_t *entries)
|
||||
gf_link_inodes_from_dirent(xlator_t *this, inode_t *parent,
|
||||
gf_dirent_t *entries)
|
||||
{
|
||||
gf_dirent_t *entry = NULL;
|
||||
gf_dirent_t *entry = NULL;
|
||||
|
||||
list_for_each_entry (entry, &entries->list, list) {
|
||||
gf_link_inode_from_dirent (this, parent, entry);
|
||||
}
|
||||
list_for_each_entry(entry, &entries->list, list)
|
||||
{
|
||||
gf_link_inode_from_dirent(this, parent, entry);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
gf_fill_iatt_for_dirent (gf_dirent_t *entry, inode_t *parent, xlator_t *subvol)
|
||||
gf_fill_iatt_for_dirent(gf_dirent_t *entry, inode_t *parent, xlator_t *subvol)
|
||||
{
|
||||
loc_t loc = {0, };
|
||||
int ret = -1;
|
||||
char *path = NULL;
|
||||
struct iatt iatt = {0,};
|
||||
loc_t loc = {
|
||||
0,
|
||||
};
|
||||
int ret = -1;
|
||||
char *path = NULL;
|
||||
struct iatt iatt = {
|
||||
0,
|
||||
};
|
||||
|
||||
loc.inode = inode_grep (parent->table, parent, entry->d_name);
|
||||
if (!loc.inode) {
|
||||
loc.inode = inode_new (parent->table);
|
||||
gf_uuid_copy (loc.inode->gfid, entry->d_stat.ia_gfid);
|
||||
}
|
||||
loc.inode = inode_grep(parent->table, parent, entry->d_name);
|
||||
if (!loc.inode) {
|
||||
loc.inode = inode_new(parent->table);
|
||||
gf_uuid_copy(loc.inode->gfid, entry->d_stat.ia_gfid);
|
||||
}
|
||||
|
||||
gf_uuid_copy (loc.pargfid, parent->gfid);
|
||||
loc.name = entry->d_name;
|
||||
loc.parent = inode_ref (parent);
|
||||
ret = inode_path (loc.inode, entry->d_name, &path);
|
||||
loc.path = path;
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
gf_uuid_copy(loc.pargfid, parent->gfid);
|
||||
loc.name = entry->d_name;
|
||||
loc.parent = inode_ref(parent);
|
||||
ret = inode_path(loc.inode, entry->d_name, &path);
|
||||
loc.path = path;
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = syncop_lookup (subvol, &loc, &iatt, NULL, NULL, NULL);
|
||||
if (ret)
|
||||
goto out;
|
||||
ret = syncop_lookup(subvol, &loc, &iatt, NULL, NULL, NULL);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
entry->d_stat = iatt;
|
||||
entry->inode = inode_ref (loc.inode);
|
||||
/* We don't need to link inode here, because as part of readdirp_cbk
|
||||
* we will link all dirents.
|
||||
*
|
||||
* Since we did a proper lookup, we don't need to set need_lookup
|
||||
* flag.
|
||||
*/
|
||||
entry->d_stat = iatt;
|
||||
entry->inode = inode_ref(loc.inode);
|
||||
/* We don't need to link inode here, because as part of readdirp_cbk
|
||||
* we will link all dirents.
|
||||
*
|
||||
* Since we did a proper lookup, we don't need to set need_lookup
|
||||
* flag.
|
||||
*/
|
||||
|
||||
ret = 0;
|
||||
ret = 0;
|
||||
out:
|
||||
loc_wipe (&loc);
|
||||
return ret;
|
||||
loc_wipe(&loc);
|
||||
return ret;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -9,151 +9,139 @@
|
||||
* ****************************************************************************/
|
||||
|
||||
/*Create a single link info structure*/
|
||||
gfdb_link_info_t*
|
||||
gfdb_link_info_new ()
|
||||
gfdb_link_info_t *
|
||||
gfdb_link_info_new()
|
||||
{
|
||||
gfdb_link_info_t *link_info = NULL;
|
||||
gfdb_link_info_t *link_info = NULL;
|
||||
|
||||
link_info = GF_CALLOC (1, sizeof(gfdb_link_info_t),
|
||||
gf_mt_gfdb_link_info_t);
|
||||
if (!link_info) {
|
||||
gf_msg (GFDB_DATA_STORE, GF_LOG_ERROR, ENOMEM,
|
||||
LG_MSG_NO_MEMORY, "Memory allocation failed for "
|
||||
"link_info ");
|
||||
goto out;
|
||||
}
|
||||
link_info = GF_CALLOC(1, sizeof(gfdb_link_info_t), gf_mt_gfdb_link_info_t);
|
||||
if (!link_info) {
|
||||
gf_msg(GFDB_DATA_STORE, GF_LOG_ERROR, ENOMEM, LG_MSG_NO_MEMORY,
|
||||
"Memory allocation failed for "
|
||||
"link_info ");
|
||||
goto out;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD (&link_info->list);
|
||||
INIT_LIST_HEAD(&link_info->list);
|
||||
|
||||
out:
|
||||
|
||||
return link_info;
|
||||
return link_info;
|
||||
}
|
||||
|
||||
/*Destroy a link info structure*/
|
||||
void
|
||||
gfdb_link_info_free(gfdb_link_info_t *link_info)
|
||||
{
|
||||
GF_FREE (link_info);
|
||||
GF_FREE(link_info);
|
||||
}
|
||||
|
||||
|
||||
/*Function to create the query_record*/
|
||||
gfdb_query_record_t *
|
||||
gfdb_query_record_new()
|
||||
{
|
||||
int ret = -1;
|
||||
gfdb_query_record_t *query_record = NULL;
|
||||
int ret = -1;
|
||||
gfdb_query_record_t *query_record = NULL;
|
||||
|
||||
query_record = GF_CALLOC (1, sizeof(gfdb_query_record_t),
|
||||
gf_mt_gfdb_query_record_t);
|
||||
if (!query_record) {
|
||||
gf_msg (GFDB_DATA_STORE, GF_LOG_ERROR, ENOMEM,
|
||||
LG_MSG_NO_MEMORY, "Memory allocation failed for "
|
||||
"query_record ");
|
||||
goto out;
|
||||
}
|
||||
query_record = GF_CALLOC(1, sizeof(gfdb_query_record_t),
|
||||
gf_mt_gfdb_query_record_t);
|
||||
if (!query_record) {
|
||||
gf_msg(GFDB_DATA_STORE, GF_LOG_ERROR, ENOMEM, LG_MSG_NO_MEMORY,
|
||||
"Memory allocation failed for "
|
||||
"query_record ");
|
||||
goto out;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD (&query_record->link_list);
|
||||
INIT_LIST_HEAD(&query_record->link_list);
|
||||
|
||||
ret = 0;
|
||||
ret = 0;
|
||||
out:
|
||||
if (ret == -1) {
|
||||
GF_FREE (query_record);
|
||||
}
|
||||
return query_record;
|
||||
if (ret == -1) {
|
||||
GF_FREE(query_record);
|
||||
}
|
||||
return query_record;
|
||||
}
|
||||
|
||||
|
||||
/*Function to delete a single linkinfo from list*/
|
||||
static void
|
||||
gfdb_delete_linkinfo_from_list (gfdb_link_info_t **link_info)
|
||||
gfdb_delete_linkinfo_from_list(gfdb_link_info_t **link_info)
|
||||
{
|
||||
GF_VALIDATE_OR_GOTO (GFDB_DATA_STORE, link_info, out);
|
||||
GF_VALIDATE_OR_GOTO (GFDB_DATA_STORE, *link_info, out);
|
||||
GF_VALIDATE_OR_GOTO(GFDB_DATA_STORE, link_info, out);
|
||||
GF_VALIDATE_OR_GOTO(GFDB_DATA_STORE, *link_info, out);
|
||||
|
||||
/*Remove hard link from list*/
|
||||
list_del(&(*link_info)->list);
|
||||
gfdb_link_info_free (*link_info);
|
||||
link_info = NULL;
|
||||
/*Remove hard link from list*/
|
||||
list_del(&(*link_info)->list);
|
||||
gfdb_link_info_free(*link_info);
|
||||
link_info = NULL;
|
||||
out:
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*Function to destroy link_info list*/
|
||||
void
|
||||
gfdb_free_link_info_list (gfdb_query_record_t *query_record)
|
||||
gfdb_free_link_info_list(gfdb_query_record_t *query_record)
|
||||
{
|
||||
gfdb_link_info_t *link_info = NULL;
|
||||
gfdb_link_info_t *temp = NULL;
|
||||
gfdb_link_info_t *link_info = NULL;
|
||||
gfdb_link_info_t *temp = NULL;
|
||||
|
||||
GF_VALIDATE_OR_GOTO (GFDB_DATA_STORE, query_record, out);
|
||||
GF_VALIDATE_OR_GOTO(GFDB_DATA_STORE, query_record, out);
|
||||
|
||||
list_for_each_entry_safe(link_info, temp,
|
||||
&query_record->link_list, list)
|
||||
{
|
||||
gfdb_delete_linkinfo_from_list (&link_info);
|
||||
link_info = NULL;
|
||||
}
|
||||
list_for_each_entry_safe(link_info, temp, &query_record->link_list, list)
|
||||
{
|
||||
gfdb_delete_linkinfo_from_list(&link_info);
|
||||
link_info = NULL;
|
||||
}
|
||||
|
||||
out:
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Function to add linkinfo to the query record */
|
||||
int
|
||||
gfdb_add_link_to_query_record (gfdb_query_record_t *query_record,
|
||||
uuid_t pgfid,
|
||||
char *base_name)
|
||||
gfdb_add_link_to_query_record(gfdb_query_record_t *query_record, uuid_t pgfid,
|
||||
char *base_name)
|
||||
{
|
||||
int ret = -1;
|
||||
gfdb_link_info_t *link_info = NULL;
|
||||
int base_name_len = 0;
|
||||
int ret = -1;
|
||||
gfdb_link_info_t *link_info = NULL;
|
||||
int base_name_len = 0;
|
||||
|
||||
GF_VALIDATE_OR_GOTO (GFDB_DATA_STORE, query_record, out);
|
||||
GF_VALIDATE_OR_GOTO (GFDB_DATA_STORE, pgfid, out);
|
||||
GF_VALIDATE_OR_GOTO (GFDB_DATA_STORE, base_name, out);
|
||||
GF_VALIDATE_OR_GOTO(GFDB_DATA_STORE, query_record, out);
|
||||
GF_VALIDATE_OR_GOTO(GFDB_DATA_STORE, pgfid, out);
|
||||
GF_VALIDATE_OR_GOTO(GFDB_DATA_STORE, base_name, out);
|
||||
|
||||
link_info = gfdb_link_info_new ();
|
||||
if (!link_info) {
|
||||
goto out;
|
||||
}
|
||||
link_info = gfdb_link_info_new();
|
||||
if (!link_info) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
gf_uuid_copy (link_info->pargfid, pgfid);
|
||||
base_name_len = strlen (base_name);
|
||||
memcpy (link_info->file_name, base_name, base_name_len);
|
||||
link_info->file_name[base_name_len] = '\0';
|
||||
gf_uuid_copy(link_info->pargfid, pgfid);
|
||||
base_name_len = strlen(base_name);
|
||||
memcpy(link_info->file_name, base_name, base_name_len);
|
||||
link_info->file_name[base_name_len] = '\0';
|
||||
|
||||
list_add_tail (&link_info->list,
|
||||
&query_record->link_list);
|
||||
list_add_tail(&link_info->list, &query_record->link_list);
|
||||
|
||||
query_record->link_count++;
|
||||
query_record->link_count++;
|
||||
|
||||
ret = 0;
|
||||
ret = 0;
|
||||
out:
|
||||
if (ret) {
|
||||
gfdb_link_info_free (link_info);
|
||||
link_info = NULL;
|
||||
}
|
||||
return ret;
|
||||
if (ret) {
|
||||
gfdb_link_info_free(link_info);
|
||||
link_info = NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*Function to destroy query record*/
|
||||
void
|
||||
gfdb_query_record_free(gfdb_query_record_t *query_record)
|
||||
{
|
||||
if (query_record) {
|
||||
gfdb_free_link_info_list (query_record);
|
||||
GF_FREE (query_record);
|
||||
}
|
||||
if (query_record) {
|
||||
gfdb_free_link_info_list(query_record);
|
||||
GF_FREE(query_record);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
SERIALIZATION/DE-SERIALIZATION OF QUERY RECORD
|
||||
*******************************************************************************/
|
||||
@ -197,40 +185,39 @@ gfdb_query_record_free(gfdb_query_record_t *query_record)
|
||||
* ****************************************************************************/
|
||||
|
||||
#define GFDB_QUERY_RECORD_FOOTER 0xBAADF00D
|
||||
#define UUID_LEN 16
|
||||
#define UUID_LEN 16
|
||||
|
||||
/*Function to get the potential length of the serialized buffer*/
|
||||
static int32_t
|
||||
gfdb_query_record_serialized_length (gfdb_query_record_t *query_record)
|
||||
gfdb_query_record_serialized_length(gfdb_query_record_t *query_record)
|
||||
{
|
||||
int32_t len = -1;
|
||||
gfdb_link_info_t *link_info = NULL;
|
||||
int32_t len = -1;
|
||||
gfdb_link_info_t *link_info = NULL;
|
||||
|
||||
GF_VALIDATE_OR_GOTO (GFDB_DATA_STORE, query_record, out);
|
||||
GF_VALIDATE_OR_GOTO(GFDB_DATA_STORE, query_record, out);
|
||||
|
||||
/* Length of GFID */
|
||||
len = UUID_LEN;
|
||||
/* Length of GFID */
|
||||
len = UUID_LEN;
|
||||
|
||||
/* length of number of links*/
|
||||
len += sizeof (int32_t);
|
||||
/* length of number of links*/
|
||||
len += sizeof(int32_t);
|
||||
|
||||
list_for_each_entry (link_info, &query_record->link_list, list) {
|
||||
list_for_each_entry(link_info, &query_record->link_list, list)
|
||||
{
|
||||
/* length of PFID */
|
||||
len += UUID_LEN;
|
||||
|
||||
/* length of PFID */
|
||||
len += UUID_LEN;
|
||||
/* Add size of base name length*/
|
||||
len += sizeof(int32_t);
|
||||
|
||||
/* Add size of base name length*/
|
||||
len += sizeof (int32_t);
|
||||
/* Length of base_name */
|
||||
len += strlen(link_info->file_name);
|
||||
}
|
||||
|
||||
/* Length of base_name */
|
||||
len += strlen (link_info->file_name);
|
||||
|
||||
}
|
||||
|
||||
/* length of footer */
|
||||
len += sizeof (int32_t);
|
||||
/* length of footer */
|
||||
len += sizeof(int32_t);
|
||||
out:
|
||||
return len;
|
||||
return len;
|
||||
}
|
||||
|
||||
/* Function for serializing query record.
|
||||
@ -259,211 +246,201 @@ out:
|
||||
*
|
||||
* */
|
||||
static int
|
||||
gfdb_query_record_serialize (gfdb_query_record_t *query_record,
|
||||
char **in_buffer)
|
||||
gfdb_query_record_serialize(gfdb_query_record_t *query_record, char **in_buffer)
|
||||
{
|
||||
gfdb_link_info_t *link_info = NULL;
|
||||
int count = -1;
|
||||
int base_name_len = 0;
|
||||
int buffer_length = 0;
|
||||
int footer = GFDB_QUERY_RECORD_FOOTER;
|
||||
char *buffer = NULL;
|
||||
char *ret_buffer = NULL;
|
||||
gfdb_link_info_t *link_info = NULL;
|
||||
int count = -1;
|
||||
int base_name_len = 0;
|
||||
int buffer_length = 0;
|
||||
int footer = GFDB_QUERY_RECORD_FOOTER;
|
||||
char *buffer = NULL;
|
||||
char *ret_buffer = NULL;
|
||||
|
||||
GF_VALIDATE_OR_GOTO (GFDB_DATA_STORE, query_record, out);
|
||||
GF_VALIDATE_OR_GOTO (GFDB_DATA_STORE,
|
||||
(query_record->link_count > 0), out);
|
||||
GF_VALIDATE_OR_GOTO (GFDB_DATA_STORE, in_buffer, out);
|
||||
GF_VALIDATE_OR_GOTO(GFDB_DATA_STORE, query_record, out);
|
||||
GF_VALIDATE_OR_GOTO(GFDB_DATA_STORE, (query_record->link_count > 0), out);
|
||||
GF_VALIDATE_OR_GOTO(GFDB_DATA_STORE, in_buffer, out);
|
||||
|
||||
/* Calculate the total length of the serialized buffer */
|
||||
buffer_length = gfdb_query_record_serialized_length(query_record);
|
||||
if (buffer_length <= 0) {
|
||||
gf_msg(GFDB_DATA_STORE, GF_LOG_ERROR, 0, LG_MSG_DB_ERROR,
|
||||
"Failed to calculate the length of "
|
||||
"serialized buffer");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Calculate the total length of the serialized buffer */
|
||||
buffer_length = gfdb_query_record_serialized_length (query_record);
|
||||
if (buffer_length <= 0) {
|
||||
gf_msg (GFDB_DATA_STORE, GF_LOG_ERROR, 0,
|
||||
LG_MSG_DB_ERROR, "Failed to calculate the length of "
|
||||
"serialized buffer");
|
||||
goto out;
|
||||
}
|
||||
/* Allocate memory to the serialized buffer */
|
||||
ret_buffer = GF_CALLOC(1, buffer_length, gf_common_mt_char);
|
||||
if (!ret_buffer) {
|
||||
gf_msg(GFDB_DATA_STORE, GF_LOG_ERROR, 0, LG_MSG_DB_ERROR,
|
||||
"Memory allocation failed for "
|
||||
"serialized buffer.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Allocate memory to the serialized buffer */
|
||||
ret_buffer = GF_CALLOC (1, buffer_length, gf_common_mt_char);
|
||||
if (!ret_buffer) {
|
||||
gf_msg (GFDB_DATA_STORE, GF_LOG_ERROR, 0,
|
||||
LG_MSG_DB_ERROR, "Memory allocation failed for "
|
||||
"serialized buffer.");
|
||||
goto out;
|
||||
}
|
||||
buffer = ret_buffer;
|
||||
|
||||
buffer = ret_buffer;
|
||||
count = 0;
|
||||
|
||||
count = 0;
|
||||
/* Copying the GFID */
|
||||
memcpy(buffer, query_record->gfid, UUID_LEN);
|
||||
buffer += UUID_LEN;
|
||||
count += UUID_LEN;
|
||||
|
||||
/* Copying the GFID */
|
||||
memcpy (buffer, query_record->gfid, UUID_LEN);
|
||||
/* Copying the number of links */
|
||||
memcpy(buffer, &query_record->link_count, sizeof(int32_t));
|
||||
buffer += sizeof(int32_t);
|
||||
count += sizeof(int32_t);
|
||||
|
||||
list_for_each_entry(link_info, &query_record->link_list, list)
|
||||
{
|
||||
/* Copying the PFID */
|
||||
memcpy(buffer, link_info->pargfid, UUID_LEN);
|
||||
buffer += UUID_LEN;
|
||||
count += UUID_LEN;
|
||||
|
||||
/* Copying the number of links */
|
||||
memcpy (buffer, &query_record->link_count, sizeof (int32_t));
|
||||
buffer += sizeof (int32_t);
|
||||
count += sizeof (int32_t);
|
||||
/* Copying base name length*/
|
||||
base_name_len = strlen(link_info->file_name);
|
||||
memcpy(buffer, &base_name_len, sizeof(int32_t));
|
||||
buffer += sizeof(int32_t);
|
||||
count += sizeof(int32_t);
|
||||
|
||||
list_for_each_entry (link_info, &query_record->link_list, list) {
|
||||
/* Length of base_name */
|
||||
memcpy(buffer, link_info->file_name, base_name_len);
|
||||
buffer += base_name_len;
|
||||
count += base_name_len;
|
||||
}
|
||||
|
||||
/* Copying the PFID */
|
||||
memcpy(buffer, link_info->pargfid, UUID_LEN);
|
||||
buffer += UUID_LEN;
|
||||
count += UUID_LEN;
|
||||
|
||||
/* Copying base name length*/
|
||||
base_name_len = strlen (link_info->file_name);
|
||||
memcpy (buffer, &base_name_len, sizeof (int32_t));
|
||||
buffer += sizeof (int32_t);
|
||||
count += sizeof (int32_t);
|
||||
|
||||
/* Length of base_name */
|
||||
memcpy(buffer, link_info->file_name, base_name_len);
|
||||
buffer += base_name_len;
|
||||
count += base_name_len;
|
||||
|
||||
}
|
||||
|
||||
/* Copying the Footer of the record */
|
||||
memcpy (buffer, &footer, sizeof (int32_t));
|
||||
buffer += sizeof (int32_t);
|
||||
count += sizeof (int32_t);
|
||||
/* Copying the Footer of the record */
|
||||
memcpy(buffer, &footer, sizeof(int32_t));
|
||||
buffer += sizeof(int32_t);
|
||||
count += sizeof(int32_t);
|
||||
|
||||
out:
|
||||
if (count < 0) {
|
||||
GF_FREE (ret_buffer);
|
||||
ret_buffer = NULL;
|
||||
}
|
||||
*in_buffer = ret_buffer;
|
||||
return count;
|
||||
if (count < 0) {
|
||||
GF_FREE(ret_buffer);
|
||||
ret_buffer = NULL;
|
||||
}
|
||||
*in_buffer = ret_buffer;
|
||||
return count;
|
||||
}
|
||||
|
||||
static gf_boolean_t
|
||||
is_serialized_buffer_valid (char *in_buffer, int buffer_length) {
|
||||
gf_boolean_t ret = _gf_false;
|
||||
int footer = 0;
|
||||
is_serialized_buffer_valid(char *in_buffer, int buffer_length)
|
||||
{
|
||||
gf_boolean_t ret = _gf_false;
|
||||
int footer = 0;
|
||||
|
||||
/* Read the footer */
|
||||
in_buffer += (buffer_length - sizeof (int32_t));
|
||||
memcpy (&footer, in_buffer, sizeof (int32_t));
|
||||
/* Read the footer */
|
||||
in_buffer += (buffer_length - sizeof(int32_t));
|
||||
memcpy(&footer, in_buffer, sizeof(int32_t));
|
||||
|
||||
/*
|
||||
* if the footer is not GFDB_QUERY_RECORD_FOOTER
|
||||
* then the serialized record is invalid
|
||||
*
|
||||
* */
|
||||
if (footer != GFDB_QUERY_RECORD_FOOTER) {
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
* if the footer is not GFDB_QUERY_RECORD_FOOTER
|
||||
* then the serialized record is invalid
|
||||
*
|
||||
* */
|
||||
if (footer != GFDB_QUERY_RECORD_FOOTER) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = _gf_true;
|
||||
ret = _gf_true;
|
||||
out:
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
gfdb_query_record_deserialize (char *in_buffer,
|
||||
int buffer_length,
|
||||
gfdb_query_record_t **query_record)
|
||||
gfdb_query_record_deserialize(char *in_buffer, int buffer_length,
|
||||
gfdb_query_record_t **query_record)
|
||||
{
|
||||
int ret = -1;
|
||||
char *buffer = NULL;
|
||||
int i = 0;
|
||||
gfdb_link_info_t *link_info = NULL;
|
||||
int count = 0;
|
||||
int base_name_len = 0;
|
||||
gfdb_query_record_t *ret_qrecord = NULL;
|
||||
int ret = -1;
|
||||
char *buffer = NULL;
|
||||
int i = 0;
|
||||
gfdb_link_info_t *link_info = NULL;
|
||||
int count = 0;
|
||||
int base_name_len = 0;
|
||||
gfdb_query_record_t *ret_qrecord = NULL;
|
||||
|
||||
GF_VALIDATE_OR_GOTO (GFDB_DATA_STORE, in_buffer, out);
|
||||
GF_VALIDATE_OR_GOTO (GFDB_DATA_STORE, query_record, out);
|
||||
GF_VALIDATE_OR_GOTO (GFDB_DATA_STORE, (buffer_length > 0), out);
|
||||
GF_VALIDATE_OR_GOTO(GFDB_DATA_STORE, in_buffer, out);
|
||||
GF_VALIDATE_OR_GOTO(GFDB_DATA_STORE, query_record, out);
|
||||
GF_VALIDATE_OR_GOTO(GFDB_DATA_STORE, (buffer_length > 0), out);
|
||||
|
||||
if (!is_serialized_buffer_valid (in_buffer, buffer_length)) {
|
||||
gf_msg (GFDB_DATA_STORE, GF_LOG_ERROR, 0,
|
||||
LG_MSG_DB_ERROR, "Invalid serialized query record");
|
||||
goto out;
|
||||
if (!is_serialized_buffer_valid(in_buffer, buffer_length)) {
|
||||
gf_msg(GFDB_DATA_STORE, GF_LOG_ERROR, 0, LG_MSG_DB_ERROR,
|
||||
"Invalid serialized query record");
|
||||
goto out;
|
||||
}
|
||||
|
||||
buffer = in_buffer;
|
||||
|
||||
ret_qrecord = gfdb_query_record_new();
|
||||
if (!ret_qrecord) {
|
||||
gf_msg(GFDB_DATA_STORE, GF_LOG_ERROR, 0, LG_MSG_DB_ERROR,
|
||||
"Failed to allocate space to "
|
||||
"gfdb_query_record_t");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* READ GFID */
|
||||
memcpy((ret_qrecord)->gfid, buffer, UUID_LEN);
|
||||
buffer += UUID_LEN;
|
||||
count += UUID_LEN;
|
||||
|
||||
/* Read the number of link */
|
||||
memcpy(&(ret_qrecord->link_count), buffer, sizeof(int32_t));
|
||||
buffer += sizeof(int32_t);
|
||||
count += sizeof(int32_t);
|
||||
|
||||
/* Read all the links */
|
||||
for (i = 0; i < ret_qrecord->link_count; i++) {
|
||||
if (count >= buffer_length) {
|
||||
gf_msg(GFDB_DATA_STORE, GF_LOG_ERROR, 0, LG_MSG_DB_ERROR,
|
||||
"Invalid serialized "
|
||||
"query record");
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
buffer = in_buffer;
|
||||
|
||||
ret_qrecord = gfdb_query_record_new ();
|
||||
if (!ret_qrecord) {
|
||||
gf_msg (GFDB_DATA_STORE, GF_LOG_ERROR, 0,
|
||||
LG_MSG_DB_ERROR, "Failed to allocate space to "
|
||||
"gfdb_query_record_t");
|
||||
goto out;
|
||||
link_info = gfdb_link_info_new();
|
||||
if (!link_info) {
|
||||
gf_msg(GFDB_DATA_STORE, GF_LOG_ERROR, 0, LG_MSG_DB_ERROR,
|
||||
"Failed to create link_info");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* READ GFID */
|
||||
memcpy ((ret_qrecord)->gfid, buffer, UUID_LEN);
|
||||
/* READ PGFID */
|
||||
memcpy(link_info->pargfid, buffer, UUID_LEN);
|
||||
buffer += UUID_LEN;
|
||||
count += UUID_LEN;
|
||||
|
||||
/* Read the number of link */
|
||||
memcpy (&(ret_qrecord->link_count), buffer, sizeof (int32_t));
|
||||
buffer += sizeof (int32_t);
|
||||
count += sizeof (int32_t);
|
||||
/* Read base name length */
|
||||
memcpy(&base_name_len, buffer, sizeof(int32_t));
|
||||
buffer += sizeof(int32_t);
|
||||
count += sizeof(int32_t);
|
||||
|
||||
/* Read all the links */
|
||||
for (i = 0; i < ret_qrecord->link_count; i++) {
|
||||
if (count >= buffer_length) {
|
||||
gf_msg (GFDB_DATA_STORE, GF_LOG_ERROR, 0,
|
||||
LG_MSG_DB_ERROR, "Invalid serialized "
|
||||
"query record");
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
/* READ basename */
|
||||
memcpy(link_info->file_name, buffer, base_name_len);
|
||||
buffer += base_name_len;
|
||||
count += base_name_len;
|
||||
link_info->file_name[base_name_len] = '\0';
|
||||
|
||||
link_info = gfdb_link_info_new ();
|
||||
if (!link_info) {
|
||||
gf_msg (GFDB_DATA_STORE, GF_LOG_ERROR, 0,
|
||||
LG_MSG_DB_ERROR, "Failed to create link_info");
|
||||
goto out;
|
||||
}
|
||||
/* Add link_info to the list */
|
||||
list_add_tail(&link_info->list, &(ret_qrecord->link_list));
|
||||
|
||||
/* READ PGFID */
|
||||
memcpy (link_info->pargfid, buffer, UUID_LEN);
|
||||
buffer += UUID_LEN;
|
||||
count += UUID_LEN;
|
||||
/* Resetting link_info */
|
||||
link_info = NULL;
|
||||
}
|
||||
|
||||
/* Read base name length */
|
||||
memcpy (&base_name_len, buffer, sizeof (int32_t));
|
||||
buffer += sizeof (int32_t);
|
||||
count += sizeof (int32_t);
|
||||
|
||||
/* READ basename */
|
||||
memcpy (link_info->file_name, buffer, base_name_len);
|
||||
buffer += base_name_len;
|
||||
count += base_name_len;
|
||||
link_info->file_name[base_name_len] = '\0';
|
||||
|
||||
/* Add link_info to the list */
|
||||
list_add_tail (&link_info->list,
|
||||
&(ret_qrecord->link_list));
|
||||
|
||||
/* Resetting link_info */
|
||||
link_info = NULL;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
ret = 0;
|
||||
out:
|
||||
if (ret) {
|
||||
gfdb_query_record_free (ret_qrecord);
|
||||
ret_qrecord = NULL;
|
||||
}
|
||||
*query_record = ret_qrecord;
|
||||
return ret;
|
||||
if (ret) {
|
||||
gfdb_query_record_free(ret_qrecord);
|
||||
ret_qrecord = NULL;
|
||||
}
|
||||
*query_record = ret_qrecord;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Function to write query record to file
|
||||
*
|
||||
* Disk format
|
||||
@ -477,57 +454,54 @@ out:
|
||||
*
|
||||
* */
|
||||
int
|
||||
gfdb_write_query_record (int fd,
|
||||
gfdb_query_record_t *query_record)
|
||||
gfdb_write_query_record(int fd, gfdb_query_record_t *query_record)
|
||||
{
|
||||
int ret = -1;
|
||||
int buffer_len = 0;
|
||||
char *buffer = NULL;
|
||||
int write_len = 0;
|
||||
char *write_buffer = NULL;
|
||||
int ret = -1;
|
||||
int buffer_len = 0;
|
||||
char *buffer = NULL;
|
||||
int write_len = 0;
|
||||
char *write_buffer = NULL;
|
||||
|
||||
GF_VALIDATE_OR_GOTO (GFDB_DATA_STORE, (fd >= 0), out);
|
||||
GF_VALIDATE_OR_GOTO (GFDB_DATA_STORE, query_record, out);
|
||||
GF_VALIDATE_OR_GOTO(GFDB_DATA_STORE, (fd >= 0), out);
|
||||
GF_VALIDATE_OR_GOTO(GFDB_DATA_STORE, query_record, out);
|
||||
|
||||
buffer_len = gfdb_query_record_serialize (query_record, &buffer);
|
||||
if (buffer_len < 0) {
|
||||
gf_msg (GFDB_DATA_STORE, GF_LOG_ERROR, 0,
|
||||
LG_MSG_DB_ERROR, "Failed to serialize query record");
|
||||
goto out;
|
||||
}
|
||||
buffer_len = gfdb_query_record_serialize(query_record, &buffer);
|
||||
if (buffer_len < 0) {
|
||||
gf_msg(GFDB_DATA_STORE, GF_LOG_ERROR, 0, LG_MSG_DB_ERROR,
|
||||
"Failed to serialize query record");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Serialize the buffer length and write to file */
|
||||
ret = write (fd, &buffer_len, sizeof (int32_t));
|
||||
/* Serialize the buffer length and write to file */
|
||||
ret = write(fd, &buffer_len, sizeof(int32_t));
|
||||
if (ret < 0) {
|
||||
gf_msg(GFDB_DATA_STORE, GF_LOG_ERROR, 0, LG_MSG_DB_ERROR,
|
||||
"Failed to write buffer length"
|
||||
" to file");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Write the serialized query record to file */
|
||||
write_len = buffer_len;
|
||||
write_buffer = buffer;
|
||||
while ((ret = write(fd, write_buffer, write_len)) < write_len) {
|
||||
if (ret < 0) {
|
||||
gf_msg (GFDB_DATA_STORE, GF_LOG_ERROR, 0,
|
||||
LG_MSG_DB_ERROR, "Failed to write buffer length"
|
||||
" to file");
|
||||
goto out;
|
||||
gf_msg(GFDB_DATA_STORE, GF_LOG_ERROR, errno, LG_MSG_DB_ERROR,
|
||||
"Failed to write serialized "
|
||||
"query record to file");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Write the serialized query record to file */
|
||||
write_len = buffer_len;
|
||||
write_buffer = buffer;
|
||||
while ((ret = write (fd, write_buffer, write_len)) < write_len) {
|
||||
if (ret < 0) {
|
||||
gf_msg (GFDB_DATA_STORE, GF_LOG_ERROR, errno,
|
||||
LG_MSG_DB_ERROR, "Failed to write serialized "
|
||||
"query record to file");
|
||||
goto out;
|
||||
}
|
||||
write_buffer += ret;
|
||||
write_len -= ret;
|
||||
}
|
||||
|
||||
write_buffer += ret;
|
||||
write_len -= ret;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
ret = 0;
|
||||
out:
|
||||
GF_FREE (buffer);
|
||||
return ret;
|
||||
GF_FREE(buffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Function to read query record from file.
|
||||
* Allocates memory to query record and
|
||||
* returns length of serialized query record when successful
|
||||
@ -535,86 +509,81 @@ out:
|
||||
* Return 0 when reached EOF.
|
||||
* */
|
||||
int
|
||||
gfdb_read_query_record (int fd,
|
||||
gfdb_query_record_t **query_record)
|
||||
gfdb_read_query_record(int fd, gfdb_query_record_t **query_record)
|
||||
{
|
||||
int ret = -1;
|
||||
int buffer_len = 0;
|
||||
int read_len = 0;
|
||||
char *buffer = NULL;
|
||||
char *read_buffer = NULL;
|
||||
int ret = -1;
|
||||
int buffer_len = 0;
|
||||
int read_len = 0;
|
||||
char *buffer = NULL;
|
||||
char *read_buffer = NULL;
|
||||
|
||||
GF_VALIDATE_OR_GOTO (GFDB_DATA_STORE, (fd >= 0), out);
|
||||
GF_VALIDATE_OR_GOTO (GFDB_DATA_STORE, query_record, out);
|
||||
GF_VALIDATE_OR_GOTO(GFDB_DATA_STORE, (fd >= 0), out);
|
||||
GF_VALIDATE_OR_GOTO(GFDB_DATA_STORE, query_record, out);
|
||||
|
||||
/* Read serialized query record length from the file*/
|
||||
ret = sys_read(fd, &buffer_len, sizeof(int32_t));
|
||||
if (ret < 0) {
|
||||
gf_msg(GFDB_DATA_STORE, GF_LOG_ERROR, 0, LG_MSG_DB_ERROR,
|
||||
"Failed reading buffer length"
|
||||
" from file");
|
||||
goto out;
|
||||
}
|
||||
/* EOF */
|
||||
else if (ret == 0) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Read serialized query record length from the file*/
|
||||
ret = sys_read (fd, &buffer_len, sizeof (int32_t));
|
||||
/* Assumed sane range is 1B - 10MB */
|
||||
if ((buffer_len <= 0) || (buffer_len > (10 * 1024 * 1024))) {
|
||||
ret = -1;
|
||||
gf_msg(GFDB_DATA_STORE, GF_LOG_ERROR, 0, LG_MSG_DB_ERROR,
|
||||
"buffer length range is out of bound %d", buffer_len);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Allocating memory to the serialization buffer */
|
||||
buffer = GF_CALLOC(1, buffer_len, gf_common_mt_char);
|
||||
if (!buffer) {
|
||||
gf_msg(GFDB_DATA_STORE, GF_LOG_ERROR, 0, LG_MSG_DB_ERROR,
|
||||
"Failed to allocate space to "
|
||||
"serialized buffer");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Read the serialized query record from file */
|
||||
read_len = buffer_len;
|
||||
read_buffer = buffer;
|
||||
while ((ret = sys_read(fd, read_buffer, read_len)) < read_len) {
|
||||
/*Any error */
|
||||
if (ret < 0) {
|
||||
gf_msg (GFDB_DATA_STORE, GF_LOG_ERROR, 0,
|
||||
LG_MSG_DB_ERROR, "Failed reading buffer length"
|
||||
" from file");
|
||||
goto out;
|
||||
gf_msg(GFDB_DATA_STORE, GF_LOG_ERROR, errno, LG_MSG_DB_ERROR,
|
||||
"Failed to read serialized "
|
||||
"query record from file");
|
||||
goto out;
|
||||
}
|
||||
/* EOF */
|
||||
else if (ret == 0) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
gf_msg(GFDB_DATA_STORE, GF_LOG_ERROR, 0, LG_MSG_DB_ERROR,
|
||||
"Invalid query record or "
|
||||
"corrupted query file");
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Assumed sane range is 1B - 10MB */
|
||||
if ((buffer_len <= 0) || (buffer_len > (10 * 1024 * 1024))) {
|
||||
ret = -1;
|
||||
gf_msg (GFDB_DATA_STORE, GF_LOG_ERROR, 0, LG_MSG_DB_ERROR,
|
||||
"buffer length range is out of bound %d", buffer_len);
|
||||
goto out;
|
||||
}
|
||||
read_buffer += ret;
|
||||
read_len -= ret;
|
||||
}
|
||||
|
||||
/* Allocating memory to the serialization buffer */
|
||||
buffer = GF_CALLOC (1, buffer_len, gf_common_mt_char);
|
||||
if (!buffer) {
|
||||
gf_msg (GFDB_DATA_STORE, GF_LOG_ERROR, 0,
|
||||
LG_MSG_DB_ERROR, "Failed to allocate space to "
|
||||
"serialized buffer");
|
||||
goto out;
|
||||
}
|
||||
ret = gfdb_query_record_deserialize(buffer, buffer_len, query_record);
|
||||
if (ret) {
|
||||
gf_msg(GFDB_DATA_STORE, GF_LOG_ERROR, 0, LG_MSG_DB_ERROR,
|
||||
"Failed to de-serialize query record");
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
/* Read the serialized query record from file */
|
||||
read_len = buffer_len;
|
||||
read_buffer = buffer;
|
||||
while ((ret = sys_read (fd, read_buffer, read_len)) < read_len) {
|
||||
|
||||
/*Any error */
|
||||
if (ret < 0) {
|
||||
gf_msg (GFDB_DATA_STORE, GF_LOG_ERROR, errno,
|
||||
LG_MSG_DB_ERROR, "Failed to read serialized "
|
||||
"query record from file");
|
||||
goto out;
|
||||
}
|
||||
/* EOF */
|
||||
else if (ret == 0) {
|
||||
gf_msg (GFDB_DATA_STORE, GF_LOG_ERROR, 0,
|
||||
LG_MSG_DB_ERROR, "Invalid query record or "
|
||||
"corrupted query file");
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
read_buffer += ret;
|
||||
read_len -= ret;
|
||||
}
|
||||
|
||||
ret = gfdb_query_record_deserialize (buffer, buffer_len,
|
||||
query_record);
|
||||
if (ret) {
|
||||
gf_msg (GFDB_DATA_STORE, GF_LOG_ERROR, 0,
|
||||
LG_MSG_DB_ERROR, "Failed to de-serialize query record");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = buffer_len;
|
||||
ret = buffer_len;
|
||||
out:
|
||||
GF_FREE (buffer);
|
||||
return ret;
|
||||
GF_FREE(buffer);
|
||||
return ret;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -16,37 +16,39 @@
|
||||
* out after a configurable interval. Hardly rocket science, but lots of
|
||||
* details to worry about.
|
||||
*/
|
||||
#define BUCKET_START(p,n) ((p) + ((n) * AUX_GID_CACHE_ASSOC))
|
||||
#define BUCKET_START(p, n) ((p) + ((n)*AUX_GID_CACHE_ASSOC))
|
||||
|
||||
/*
|
||||
* Initialize the cache.
|
||||
*/
|
||||
int gid_cache_init(gid_cache_t *cache, uint32_t timeout)
|
||||
int
|
||||
gid_cache_init(gid_cache_t *cache, uint32_t timeout)
|
||||
{
|
||||
if (!cache)
|
||||
return -1;
|
||||
if (!cache)
|
||||
return -1;
|
||||
|
||||
LOCK_INIT(&cache->gc_lock);
|
||||
cache->gc_max_age = timeout;
|
||||
cache->gc_nbuckets = AUX_GID_CACHE_BUCKETS;
|
||||
memset(cache->gc_cache, 0, sizeof(gid_list_t) * AUX_GID_CACHE_SIZE);
|
||||
LOCK_INIT(&cache->gc_lock);
|
||||
cache->gc_max_age = timeout;
|
||||
cache->gc_nbuckets = AUX_GID_CACHE_BUCKETS;
|
||||
memset(cache->gc_cache, 0, sizeof(gid_list_t) * AUX_GID_CACHE_SIZE);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reconfigure the cache timeout.
|
||||
*/
|
||||
int gid_cache_reconf(gid_cache_t *cache, uint32_t timeout)
|
||||
int
|
||||
gid_cache_reconf(gid_cache_t *cache, uint32_t timeout)
|
||||
{
|
||||
if (!cache)
|
||||
return -1;
|
||||
if (!cache)
|
||||
return -1;
|
||||
|
||||
LOCK(&cache->gc_lock);
|
||||
cache->gc_max_age = timeout;
|
||||
UNLOCK(&cache->gc_lock);
|
||||
LOCK(&cache->gc_lock);
|
||||
cache->gc_max_age = timeout;
|
||||
UNLOCK(&cache->gc_lock);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -54,153 +56,155 @@ int gid_cache_reconf(gid_cache_t *cache, uint32_t timeout)
|
||||
* an additional allocation and memory copy. The caller should copy the data and
|
||||
* release (unlock) the cache as soon as possible.
|
||||
*/
|
||||
const gid_list_t *gid_cache_lookup(gid_cache_t *cache, uint64_t id,
|
||||
uint64_t uid, uint64_t gid)
|
||||
const gid_list_t *
|
||||
gid_cache_lookup(gid_cache_t *cache, uint64_t id, uint64_t uid, uint64_t gid)
|
||||
{
|
||||
int bucket;
|
||||
int i;
|
||||
time_t now;
|
||||
const gid_list_t *agl;
|
||||
int bucket;
|
||||
int i;
|
||||
time_t now;
|
||||
const gid_list_t *agl;
|
||||
|
||||
LOCK(&cache->gc_lock);
|
||||
now = time(NULL);
|
||||
bucket = id % cache->gc_nbuckets;
|
||||
agl = BUCKET_START(cache->gc_cache, bucket);
|
||||
for (i = 0; i < AUX_GID_CACHE_ASSOC; i++, agl++) {
|
||||
if (!agl->gl_list)
|
||||
continue;
|
||||
if (agl->gl_id != id)
|
||||
continue;
|
||||
LOCK(&cache->gc_lock);
|
||||
now = time(NULL);
|
||||
bucket = id % cache->gc_nbuckets;
|
||||
agl = BUCKET_START(cache->gc_cache, bucket);
|
||||
for (i = 0; i < AUX_GID_CACHE_ASSOC; i++, agl++) {
|
||||
if (!agl->gl_list)
|
||||
continue;
|
||||
if (agl->gl_id != id)
|
||||
continue;
|
||||
|
||||
/*
|
||||
@uid and @gid reflect the latest UID/GID of the
|
||||
process performing the syscall (taken from frame->root).
|
||||
/*
|
||||
@uid and @gid reflect the latest UID/GID of the
|
||||
process performing the syscall (taken from frame->root).
|
||||
|
||||
If the UID and GID has changed for the PID since the
|
||||
time we cached it, we should treat the cache as having
|
||||
stale values and query them freshly.
|
||||
*/
|
||||
if (agl->gl_uid != uid || agl->gl_gid != gid)
|
||||
break;
|
||||
If the UID and GID has changed for the PID since the
|
||||
time we cached it, we should treat the cache as having
|
||||
stale values and query them freshly.
|
||||
*/
|
||||
if (agl->gl_uid != uid || agl->gl_gid != gid)
|
||||
break;
|
||||
|
||||
/*
|
||||
* We don't put new entries in the cache when expiration=0, but
|
||||
* there might be entries still in there if expiration was
|
||||
* changed very recently. Writing the check this way ensures
|
||||
* that they're not used.
|
||||
*/
|
||||
if (now < agl->gl_deadline) {
|
||||
return agl;
|
||||
}
|
||||
/*
|
||||
* We don't put new entries in the cache when expiration=0, but
|
||||
* there might be entries still in there if expiration was
|
||||
* changed very recently. Writing the check this way ensures
|
||||
* that they're not used.
|
||||
*/
|
||||
if (now < agl->gl_deadline) {
|
||||
return agl;
|
||||
}
|
||||
|
||||
/*
|
||||
* We're not going to find any more UID matches, and reaping
|
||||
* is handled further down to maintain LRU order.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
UNLOCK(&cache->gc_lock);
|
||||
return NULL;
|
||||
/*
|
||||
* We're not going to find any more UID matches, and reaping
|
||||
* is handled further down to maintain LRU order.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
UNLOCK(&cache->gc_lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Release an entry found via lookup.
|
||||
*/
|
||||
void gid_cache_release(gid_cache_t *cache, const gid_list_t *agl)
|
||||
void
|
||||
gid_cache_release(gid_cache_t *cache, const gid_list_t *agl)
|
||||
{
|
||||
UNLOCK(&cache->gc_lock);
|
||||
UNLOCK(&cache->gc_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a new list entry to the cache. If an entry for this ID already exists,
|
||||
* update it.
|
||||
*/
|
||||
int gid_cache_add(gid_cache_t *cache, gid_list_t *gl)
|
||||
int
|
||||
gid_cache_add(gid_cache_t *cache, gid_list_t *gl)
|
||||
{
|
||||
gid_list_t *agl;
|
||||
int bucket;
|
||||
int i;
|
||||
time_t now;
|
||||
gid_list_t *agl;
|
||||
int bucket;
|
||||
int i;
|
||||
time_t now;
|
||||
|
||||
if (!gl || !gl->gl_list)
|
||||
return -1;
|
||||
if (!gl || !gl->gl_list)
|
||||
return -1;
|
||||
|
||||
if (!cache->gc_max_age)
|
||||
return 0;
|
||||
if (!cache->gc_max_age)
|
||||
return 0;
|
||||
|
||||
LOCK(&cache->gc_lock);
|
||||
now = time(NULL);
|
||||
LOCK(&cache->gc_lock);
|
||||
now = time(NULL);
|
||||
|
||||
/*
|
||||
* Scan for the first free entry or one that matches this id. The id
|
||||
* check is added to address a bug where the cache might contain an
|
||||
* expired entry for this id. Since lookup occurs in LRU order and
|
||||
* does not reclaim entries, it will always return failure on discovery
|
||||
* of an expired entry. This leads to duplicate entries being added,
|
||||
* which still do not satisfy lookups until the expired entry (and
|
||||
* everything before it) is reclaimed.
|
||||
*
|
||||
* We address this through reuse of an entry already allocated to this
|
||||
* id, whether expired or not, since we have obviously already received
|
||||
* more recent data. The entry is repopulated with the new data and a new
|
||||
* deadline and is pushed forward to reside as the last populated entry in
|
||||
* the bucket.
|
||||
*/
|
||||
bucket = gl->gl_id % cache->gc_nbuckets;
|
||||
agl = BUCKET_START(cache->gc_cache, bucket);
|
||||
for (i = 0; i < AUX_GID_CACHE_ASSOC; ++i, ++agl) {
|
||||
if (agl->gl_id == gl->gl_id)
|
||||
break;
|
||||
if (!agl->gl_list)
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Scan for the first free entry or one that matches this id. The id
|
||||
* check is added to address a bug where the cache might contain an
|
||||
* expired entry for this id. Since lookup occurs in LRU order and
|
||||
* does not reclaim entries, it will always return failure on discovery
|
||||
* of an expired entry. This leads to duplicate entries being added,
|
||||
* which still do not satisfy lookups until the expired entry (and
|
||||
* everything before it) is reclaimed.
|
||||
*
|
||||
* We address this through reuse of an entry already allocated to this
|
||||
* id, whether expired or not, since we have obviously already received
|
||||
* more recent data. The entry is repopulated with the new data and a new
|
||||
* deadline and is pushed forward to reside as the last populated entry in
|
||||
* the bucket.
|
||||
*/
|
||||
bucket = gl->gl_id % cache->gc_nbuckets;
|
||||
agl = BUCKET_START(cache->gc_cache, bucket);
|
||||
for (i = 0; i < AUX_GID_CACHE_ASSOC; ++i, ++agl) {
|
||||
if (agl->gl_id == gl->gl_id)
|
||||
break;
|
||||
if (!agl->gl_list)
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* The way we allocate free entries naturally places the newest
|
||||
* ones at the highest indices, so evicting the lowest makes
|
||||
* sense, but that also means we can't just replace it with the
|
||||
* one that caused the eviction. That would cause us to thrash
|
||||
* the first entry while others remain idle. Therefore, we
|
||||
* need to slide the other entries down and add the new one at
|
||||
* the end just as if the *last* slot had been free.
|
||||
*
|
||||
* Deadline expiration is also handled here, since the oldest
|
||||
* expired entry will be in the first position. This does mean
|
||||
* the bucket can stay full of expired entries if we're idle
|
||||
* but, if the small amount of extra memory or scan time before
|
||||
* we decide to evict someone ever become issues, we could
|
||||
* easily add a reaper thread.
|
||||
*/
|
||||
/*
|
||||
* The way we allocate free entries naturally places the newest
|
||||
* ones at the highest indices, so evicting the lowest makes
|
||||
* sense, but that also means we can't just replace it with the
|
||||
* one that caused the eviction. That would cause us to thrash
|
||||
* the first entry while others remain idle. Therefore, we
|
||||
* need to slide the other entries down and add the new one at
|
||||
* the end just as if the *last* slot had been free.
|
||||
*
|
||||
* Deadline expiration is also handled here, since the oldest
|
||||
* expired entry will be in the first position. This does mean
|
||||
* the bucket can stay full of expired entries if we're idle
|
||||
* but, if the small amount of extra memory or scan time before
|
||||
* we decide to evict someone ever become issues, we could
|
||||
* easily add a reaper thread.
|
||||
*/
|
||||
|
||||
if (i >= AUX_GID_CACHE_ASSOC) {
|
||||
/* cache full, evict the first (LRU) entry */
|
||||
i = 0;
|
||||
agl = BUCKET_START(cache->gc_cache, bucket);
|
||||
GF_FREE(agl->gl_list);
|
||||
} else if (agl->gl_list) {
|
||||
/* evict the old entry we plan to reuse */
|
||||
GF_FREE(agl->gl_list);
|
||||
}
|
||||
if (i >= AUX_GID_CACHE_ASSOC) {
|
||||
/* cache full, evict the first (LRU) entry */
|
||||
i = 0;
|
||||
agl = BUCKET_START(cache->gc_cache, bucket);
|
||||
GF_FREE(agl->gl_list);
|
||||
} else if (agl->gl_list) {
|
||||
/* evict the old entry we plan to reuse */
|
||||
GF_FREE(agl->gl_list);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have evicted an entry, slide the subsequent populated entries
|
||||
* back and populate the last entry.
|
||||
*/
|
||||
for (; i < AUX_GID_CACHE_ASSOC - 1; i++) {
|
||||
if (!agl[1].gl_list)
|
||||
break;
|
||||
agl[0] = agl[1];
|
||||
agl++;
|
||||
}
|
||||
/*
|
||||
* If we have evicted an entry, slide the subsequent populated entries
|
||||
* back and populate the last entry.
|
||||
*/
|
||||
for (; i < AUX_GID_CACHE_ASSOC - 1; i++) {
|
||||
if (!agl[1].gl_list)
|
||||
break;
|
||||
agl[0] = agl[1];
|
||||
agl++;
|
||||
}
|
||||
|
||||
agl->gl_id = gl->gl_id;
|
||||
agl->gl_uid = gl->gl_uid;
|
||||
agl->gl_gid = gl->gl_gid;
|
||||
agl->gl_count = gl->gl_count;
|
||||
agl->gl_list = gl->gl_list;
|
||||
agl->gl_deadline = now + cache->gc_max_age;
|
||||
agl->gl_id = gl->gl_id;
|
||||
agl->gl_uid = gl->gl_uid;
|
||||
agl->gl_gid = gl->gl_gid;
|
||||
agl->gl_count = gl->gl_count;
|
||||
agl->gl_list = gl->gl_list;
|
||||
agl->gl_deadline = now + cache->gc_max_age;
|
||||
|
||||
UNLOCK(&cache->gc_lock);
|
||||
UNLOCK(&cache->gc_lock);
|
||||
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
@ -19,75 +19,75 @@
|
||||
#include "upcall-utils.h"
|
||||
|
||||
const char *gf_fop_list[GF_FOP_MAXVALUE] = {
|
||||
[GF_FOP_NULL] = "NULL",
|
||||
[GF_FOP_STAT] = "STAT",
|
||||
[GF_FOP_READLINK] = "READLINK",
|
||||
[GF_FOP_MKNOD] = "MKNOD",
|
||||
[GF_FOP_MKDIR] = "MKDIR",
|
||||
[GF_FOP_UNLINK] = "UNLINK",
|
||||
[GF_FOP_RMDIR] = "RMDIR",
|
||||
[GF_FOP_SYMLINK] = "SYMLINK",
|
||||
[GF_FOP_RENAME] = "RENAME",
|
||||
[GF_FOP_LINK] = "LINK",
|
||||
[GF_FOP_TRUNCATE] = "TRUNCATE",
|
||||
[GF_FOP_OPEN] = "OPEN",
|
||||
[GF_FOP_READ] = "READ",
|
||||
[GF_FOP_WRITE] = "WRITE",
|
||||
[GF_FOP_STATFS] = "STATFS",
|
||||
[GF_FOP_FLUSH] = "FLUSH",
|
||||
[GF_FOP_FSYNC] = "FSYNC",
|
||||
[GF_FOP_SETXATTR] = "SETXATTR",
|
||||
[GF_FOP_GETXATTR] = "GETXATTR",
|
||||
[GF_FOP_REMOVEXATTR] = "REMOVEXATTR",
|
||||
[GF_FOP_OPENDIR] = "OPENDIR",
|
||||
[GF_FOP_FSYNCDIR] = "FSYNCDIR",
|
||||
[GF_FOP_ACCESS] = "ACCESS",
|
||||
[GF_FOP_CREATE] = "CREATE",
|
||||
[GF_FOP_FTRUNCATE] = "FTRUNCATE",
|
||||
[GF_FOP_FSTAT] = "FSTAT",
|
||||
[GF_FOP_LK] = "LK",
|
||||
[GF_FOP_LOOKUP] = "LOOKUP",
|
||||
[GF_FOP_READDIR] = "READDIR",
|
||||
[GF_FOP_INODELK] = "INODELK",
|
||||
[GF_FOP_FINODELK] = "FINODELK",
|
||||
[GF_FOP_ENTRYLK] = "ENTRYLK",
|
||||
[GF_FOP_FENTRYLK] = "FENTRYLK",
|
||||
[GF_FOP_XATTROP] = "XATTROP",
|
||||
[GF_FOP_FXATTROP] = "FXATTROP",
|
||||
[GF_FOP_FSETXATTR] = "FSETXATTR",
|
||||
[GF_FOP_FGETXATTR] = "FGETXATTR",
|
||||
[GF_FOP_RCHECKSUM] = "RCHECKSUM",
|
||||
[GF_FOP_SETATTR] = "SETATTR",
|
||||
[GF_FOP_FSETATTR] = "FSETATTR",
|
||||
[GF_FOP_READDIRP] = "READDIRP",
|
||||
[GF_FOP_GETSPEC] = "GETSPEC",
|
||||
[GF_FOP_FORGET] = "FORGET",
|
||||
[GF_FOP_RELEASE] = "RELEASE",
|
||||
[GF_FOP_RELEASEDIR] = "RELEASEDIR",
|
||||
[GF_FOP_FREMOVEXATTR]= "FREMOVEXATTR",
|
||||
[GF_FOP_FALLOCATE] = "FALLOCATE",
|
||||
[GF_FOP_DISCARD] = "DISCARD",
|
||||
[GF_FOP_ZEROFILL] = "ZEROFILL",
|
||||
[GF_FOP_IPC] = "IPC",
|
||||
[GF_FOP_SEEK] = "SEEK",
|
||||
[GF_FOP_LEASE] = "LEASE",
|
||||
[GF_FOP_COMPOUND] = "COMPOUND",
|
||||
[GF_FOP_GETACTIVELK] = "GETACTIVELK",
|
||||
[GF_FOP_SETACTIVELK] = "SETACTIVELK",
|
||||
[GF_FOP_PUT] = "PUT",
|
||||
[GF_FOP_ICREATE] = "ICREATE",
|
||||
[GF_FOP_NAMELINK] = "NAMELINK",
|
||||
[GF_FOP_NULL] = "NULL",
|
||||
[GF_FOP_STAT] = "STAT",
|
||||
[GF_FOP_READLINK] = "READLINK",
|
||||
[GF_FOP_MKNOD] = "MKNOD",
|
||||
[GF_FOP_MKDIR] = "MKDIR",
|
||||
[GF_FOP_UNLINK] = "UNLINK",
|
||||
[GF_FOP_RMDIR] = "RMDIR",
|
||||
[GF_FOP_SYMLINK] = "SYMLINK",
|
||||
[GF_FOP_RENAME] = "RENAME",
|
||||
[GF_FOP_LINK] = "LINK",
|
||||
[GF_FOP_TRUNCATE] = "TRUNCATE",
|
||||
[GF_FOP_OPEN] = "OPEN",
|
||||
[GF_FOP_READ] = "READ",
|
||||
[GF_FOP_WRITE] = "WRITE",
|
||||
[GF_FOP_STATFS] = "STATFS",
|
||||
[GF_FOP_FLUSH] = "FLUSH",
|
||||
[GF_FOP_FSYNC] = "FSYNC",
|
||||
[GF_FOP_SETXATTR] = "SETXATTR",
|
||||
[GF_FOP_GETXATTR] = "GETXATTR",
|
||||
[GF_FOP_REMOVEXATTR] = "REMOVEXATTR",
|
||||
[GF_FOP_OPENDIR] = "OPENDIR",
|
||||
[GF_FOP_FSYNCDIR] = "FSYNCDIR",
|
||||
[GF_FOP_ACCESS] = "ACCESS",
|
||||
[GF_FOP_CREATE] = "CREATE",
|
||||
[GF_FOP_FTRUNCATE] = "FTRUNCATE",
|
||||
[GF_FOP_FSTAT] = "FSTAT",
|
||||
[GF_FOP_LK] = "LK",
|
||||
[GF_FOP_LOOKUP] = "LOOKUP",
|
||||
[GF_FOP_READDIR] = "READDIR",
|
||||
[GF_FOP_INODELK] = "INODELK",
|
||||
[GF_FOP_FINODELK] = "FINODELK",
|
||||
[GF_FOP_ENTRYLK] = "ENTRYLK",
|
||||
[GF_FOP_FENTRYLK] = "FENTRYLK",
|
||||
[GF_FOP_XATTROP] = "XATTROP",
|
||||
[GF_FOP_FXATTROP] = "FXATTROP",
|
||||
[GF_FOP_FSETXATTR] = "FSETXATTR",
|
||||
[GF_FOP_FGETXATTR] = "FGETXATTR",
|
||||
[GF_FOP_RCHECKSUM] = "RCHECKSUM",
|
||||
[GF_FOP_SETATTR] = "SETATTR",
|
||||
[GF_FOP_FSETATTR] = "FSETATTR",
|
||||
[GF_FOP_READDIRP] = "READDIRP",
|
||||
[GF_FOP_GETSPEC] = "GETSPEC",
|
||||
[GF_FOP_FORGET] = "FORGET",
|
||||
[GF_FOP_RELEASE] = "RELEASE",
|
||||
[GF_FOP_RELEASEDIR] = "RELEASEDIR",
|
||||
[GF_FOP_FREMOVEXATTR] = "FREMOVEXATTR",
|
||||
[GF_FOP_FALLOCATE] = "FALLOCATE",
|
||||
[GF_FOP_DISCARD] = "DISCARD",
|
||||
[GF_FOP_ZEROFILL] = "ZEROFILL",
|
||||
[GF_FOP_IPC] = "IPC",
|
||||
[GF_FOP_SEEK] = "SEEK",
|
||||
[GF_FOP_LEASE] = "LEASE",
|
||||
[GF_FOP_COMPOUND] = "COMPOUND",
|
||||
[GF_FOP_GETACTIVELK] = "GETACTIVELK",
|
||||
[GF_FOP_SETACTIVELK] = "SETACTIVELK",
|
||||
[GF_FOP_PUT] = "PUT",
|
||||
[GF_FOP_ICREATE] = "ICREATE",
|
||||
[GF_FOP_NAMELINK] = "NAMELINK",
|
||||
};
|
||||
|
||||
const char *gf_upcall_list[GF_UPCALL_FLAGS_MAXVALUE] = {
|
||||
[GF_UPCALL_NULL] = "NULL",
|
||||
[GF_UPCALL] = "UPCALL",
|
||||
[GF_UPCALL_CI_STAT] = "CI_IATT",
|
||||
[GF_UPCALL_CI_XATTR] = "CI_XATTR",
|
||||
[GF_UPCALL_CI_RENAME] = "CI_RENAME",
|
||||
[GF_UPCALL_CI_NLINK] = "CI_UNLINK",
|
||||
[GF_UPCALL_CI_FORGET] = "CI_FORGET",
|
||||
[GF_UPCALL_LEASE_RECALL] = "LEASE_RECALL",
|
||||
[GF_UPCALL_NULL] = "NULL",
|
||||
[GF_UPCALL] = "UPCALL",
|
||||
[GF_UPCALL_CI_STAT] = "CI_IATT",
|
||||
[GF_UPCALL_CI_XATTR] = "CI_XATTR",
|
||||
[GF_UPCALL_CI_RENAME] = "CI_RENAME",
|
||||
[GF_UPCALL_CI_NLINK] = "CI_UNLINK",
|
||||
[GF_UPCALL_CI_FORGET] = "CI_FORGET",
|
||||
[GF_UPCALL_LEASE_RECALL] = "LEASE_RECALL",
|
||||
};
|
||||
|
||||
/* THIS */
|
||||
@ -101,461 +101,452 @@ xlator_t global_xlator;
|
||||
static pthread_key_t this_xlator_key;
|
||||
static pthread_key_t synctask_key;
|
||||
static pthread_key_t uuid_buf_key;
|
||||
static char global_uuid_buf[GF_UUID_BUF_SIZE];
|
||||
static char global_uuid_buf[GF_UUID_BUF_SIZE];
|
||||
static pthread_key_t lkowner_buf_key;
|
||||
static char global_lkowner_buf[GF_LKOWNER_BUF_SIZE];
|
||||
static char global_lkowner_buf[GF_LKOWNER_BUF_SIZE];
|
||||
static pthread_key_t leaseid_buf_key;
|
||||
static int gf_global_mem_acct_enable = 1;
|
||||
static pthread_once_t globals_inited = PTHREAD_ONCE_INIT;
|
||||
|
||||
|
||||
int
|
||||
gf_global_mem_acct_enable_get (void)
|
||||
gf_global_mem_acct_enable_get(void)
|
||||
{
|
||||
return gf_global_mem_acct_enable;
|
||||
return gf_global_mem_acct_enable;
|
||||
}
|
||||
|
||||
int
|
||||
gf_global_mem_acct_enable_set (int val)
|
||||
gf_global_mem_acct_enable_set(int val)
|
||||
{
|
||||
gf_global_mem_acct_enable = val;
|
||||
return 0;
|
||||
gf_global_mem_acct_enable = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
glusterfs_this_destroy (void *ptr)
|
||||
glusterfs_this_destroy(void *ptr)
|
||||
{
|
||||
FREE (ptr);
|
||||
FREE(ptr);
|
||||
}
|
||||
|
||||
static struct xlator_cbks global_cbks = {
|
||||
.forget = NULL,
|
||||
.release = NULL,
|
||||
.releasedir = NULL,
|
||||
.invalidate = NULL,
|
||||
.client_destroy = NULL,
|
||||
.client_disconnect = NULL,
|
||||
.ictxmerge = NULL,
|
||||
.ictxsize = NULL,
|
||||
.fdctxsize = NULL,
|
||||
.forget = NULL,
|
||||
.release = NULL,
|
||||
.releasedir = NULL,
|
||||
.invalidate = NULL,
|
||||
.client_destroy = NULL,
|
||||
.client_disconnect = NULL,
|
||||
.ictxmerge = NULL,
|
||||
.ictxsize = NULL,
|
||||
.fdctxsize = NULL,
|
||||
};
|
||||
|
||||
/* This is required to get through the check in graph.c */
|
||||
static struct xlator_fops global_fops = {
|
||||
};
|
||||
static struct xlator_fops global_fops = {};
|
||||
|
||||
static int
|
||||
global_xl_reconfigure (xlator_t *this, dict_t *options)
|
||||
global_xl_reconfigure(xlator_t *this, dict_t *options)
|
||||
{
|
||||
int ret = -1;
|
||||
gf_boolean_t bool_opt = _gf_false;
|
||||
int ret = -1;
|
||||
gf_boolean_t bool_opt = _gf_false;
|
||||
|
||||
/* This is not added in volume dump, hence adding the options in log
|
||||
would be helpful for debugging later */
|
||||
dict_dump_to_log (options);
|
||||
/* This is not added in volume dump, hence adding the options in log
|
||||
would be helpful for debugging later */
|
||||
dict_dump_to_log(options);
|
||||
|
||||
GF_OPTION_RECONF ("measure-latency", bool_opt, options, bool, out);
|
||||
this->ctx->measure_latency = bool_opt;
|
||||
GF_OPTION_RECONF("measure-latency", bool_opt, options, bool, out);
|
||||
this->ctx->measure_latency = bool_opt;
|
||||
|
||||
GF_OPTION_RECONF ("metrics-dump-path", this->ctx->config.metrics_dumppath,
|
||||
options, str, out);
|
||||
GF_OPTION_RECONF("metrics-dump-path", this->ctx->config.metrics_dumppath,
|
||||
options, str, out);
|
||||
|
||||
/* TODO: add more things here */
|
||||
ret = 0;
|
||||
/* TODO: add more things here */
|
||||
ret = 0;
|
||||
out:
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
global_xl_init (xlator_t *this)
|
||||
global_xl_init(xlator_t *this)
|
||||
{
|
||||
int ret = -1;
|
||||
gf_boolean_t bool_opt = false;
|
||||
int ret = -1;
|
||||
gf_boolean_t bool_opt = false;
|
||||
|
||||
GF_OPTION_INIT ("measure-latency", bool_opt, bool, out);
|
||||
this->ctx->measure_latency = bool_opt;
|
||||
GF_OPTION_INIT("measure-latency", bool_opt, bool, out);
|
||||
this->ctx->measure_latency = bool_opt;
|
||||
|
||||
GF_OPTION_INIT ("metrics-dump-path", this->ctx->config.metrics_dumppath,
|
||||
str, out);
|
||||
GF_OPTION_INIT("metrics-dump-path", this->ctx->config.metrics_dumppath, str,
|
||||
out);
|
||||
|
||||
ret = 0;
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
global_xl_fini (xlator_t *this)
|
||||
global_xl_fini(xlator_t *this)
|
||||
{
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
struct volume_options global_xl_options[] = {
|
||||
{ .key = {"measure-latency"},
|
||||
.type = GF_OPTION_TYPE_BOOL,
|
||||
.default_value = "no",
|
||||
.op_version = {GD_OP_VERSION_4_0_0},
|
||||
.flags = OPT_FLAG_SETTABLE,
|
||||
.tags = {"global", "context"},
|
||||
.description = "Use this option to toggle measuring latency"
|
||||
},
|
||||
{ .key = {"metrics-dump-path"},
|
||||
.type = GF_OPTION_TYPE_STR,
|
||||
.default_value = "{{gluster_workdir}}/metrics",
|
||||
.op_version = {GD_OP_VERSION_4_0_0},
|
||||
.flags = OPT_FLAG_SETTABLE,
|
||||
.tags = {"global", "context"},
|
||||
.description = "Use this option to set the metrics dump path"
|
||||
},
|
||||
{.key = {"measure-latency"},
|
||||
.type = GF_OPTION_TYPE_BOOL,
|
||||
.default_value = "no",
|
||||
.op_version = {GD_OP_VERSION_4_0_0},
|
||||
.flags = OPT_FLAG_SETTABLE,
|
||||
.tags = {"global", "context"},
|
||||
.description = "Use this option to toggle measuring latency"},
|
||||
{.key = {"metrics-dump-path"},
|
||||
.type = GF_OPTION_TYPE_STR,
|
||||
.default_value = "{{gluster_workdir}}/metrics",
|
||||
.op_version = {GD_OP_VERSION_4_0_0},
|
||||
.flags = OPT_FLAG_SETTABLE,
|
||||
.tags = {"global", "context"},
|
||||
.description = "Use this option to set the metrics dump path"},
|
||||
|
||||
{ .key = {NULL},},
|
||||
{
|
||||
.key = {NULL},
|
||||
},
|
||||
};
|
||||
|
||||
static volume_opt_list_t global_xl_opt_list;
|
||||
|
||||
int
|
||||
glusterfs_this_init ()
|
||||
glusterfs_this_init()
|
||||
{
|
||||
int ret = 0;
|
||||
ret = pthread_key_create (&this_xlator_key, glusterfs_this_destroy);
|
||||
if (ret != 0) {
|
||||
gf_msg ("", GF_LOG_WARNING, ret,
|
||||
LG_MSG_PTHREAD_KEY_CREATE_FAILED, "failed to create "
|
||||
"the pthread key");
|
||||
return ret;
|
||||
}
|
||||
|
||||
global_xlator.name = "glusterfs";
|
||||
global_xlator.type = GF_GLOBAL_XLATOR_NAME;
|
||||
global_xlator.cbks = &global_cbks;
|
||||
global_xlator.fops = &global_fops;
|
||||
global_xlator.reconfigure = global_xl_reconfigure;
|
||||
global_xlator.init = global_xl_init;
|
||||
global_xlator.fini = global_xl_fini;
|
||||
|
||||
INIT_LIST_HEAD (&global_xlator.volume_options);
|
||||
INIT_LIST_HEAD (&global_xl_opt_list.list);
|
||||
global_xl_opt_list.given_opt = global_xl_options;
|
||||
|
||||
list_add_tail (&global_xl_opt_list.list, &global_xlator.volume_options);
|
||||
|
||||
int ret = 0;
|
||||
ret = pthread_key_create(&this_xlator_key, glusterfs_this_destroy);
|
||||
if (ret != 0) {
|
||||
gf_msg("", GF_LOG_WARNING, ret, LG_MSG_PTHREAD_KEY_CREATE_FAILED,
|
||||
"failed to create "
|
||||
"the pthread key");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
global_xlator.name = "glusterfs";
|
||||
global_xlator.type = GF_GLOBAL_XLATOR_NAME;
|
||||
global_xlator.cbks = &global_cbks;
|
||||
global_xlator.fops = &global_fops;
|
||||
global_xlator.reconfigure = global_xl_reconfigure;
|
||||
global_xlator.init = global_xl_init;
|
||||
global_xlator.fini = global_xl_fini;
|
||||
|
||||
INIT_LIST_HEAD(&global_xlator.volume_options);
|
||||
INIT_LIST_HEAD(&global_xl_opt_list.list);
|
||||
global_xl_opt_list.given_opt = global_xl_options;
|
||||
|
||||
list_add_tail(&global_xl_opt_list.list, &global_xlator.volume_options);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
xlator_t **
|
||||
__glusterfs_this_location ()
|
||||
__glusterfs_this_location()
|
||||
{
|
||||
xlator_t **this_location = NULL;
|
||||
int ret = 0;
|
||||
xlator_t **this_location = NULL;
|
||||
int ret = 0;
|
||||
|
||||
this_location = pthread_getspecific (this_xlator_key);
|
||||
this_location = pthread_getspecific(this_xlator_key);
|
||||
|
||||
if (!this_location) {
|
||||
this_location = CALLOC (1, sizeof (*this_location));
|
||||
if (!this_location)
|
||||
goto out;
|
||||
if (!this_location) {
|
||||
this_location = CALLOC(1, sizeof(*this_location));
|
||||
if (!this_location)
|
||||
goto out;
|
||||
|
||||
ret = pthread_setspecific (this_xlator_key, this_location);
|
||||
if (ret != 0) {
|
||||
FREE (this_location);
|
||||
this_location = NULL;
|
||||
goto out;
|
||||
}
|
||||
ret = pthread_setspecific(this_xlator_key, this_location);
|
||||
if (ret != 0) {
|
||||
FREE(this_location);
|
||||
this_location = NULL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
out:
|
||||
if (this_location) {
|
||||
if (!*this_location)
|
||||
*this_location = &global_xlator;
|
||||
}
|
||||
return this_location;
|
||||
if (this_location) {
|
||||
if (!*this_location)
|
||||
*this_location = &global_xlator;
|
||||
}
|
||||
return this_location;
|
||||
}
|
||||
|
||||
|
||||
xlator_t *
|
||||
glusterfs_this_get ()
|
||||
glusterfs_this_get()
|
||||
{
|
||||
xlator_t **this_location = NULL;
|
||||
xlator_t **this_location = NULL;
|
||||
|
||||
this_location = __glusterfs_this_location ();
|
||||
if (!this_location)
|
||||
return &global_xlator;
|
||||
this_location = __glusterfs_this_location();
|
||||
if (!this_location)
|
||||
return &global_xlator;
|
||||
|
||||
return *this_location;
|
||||
return *this_location;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
glusterfs_this_set (xlator_t *this)
|
||||
glusterfs_this_set(xlator_t *this)
|
||||
{
|
||||
xlator_t **this_location = NULL;
|
||||
xlator_t **this_location = NULL;
|
||||
|
||||
this_location = __glusterfs_this_location ();
|
||||
if (!this_location)
|
||||
return -ENOMEM;
|
||||
this_location = __glusterfs_this_location();
|
||||
if (!this_location)
|
||||
return -ENOMEM;
|
||||
|
||||
*this_location = this;
|
||||
*this_location = this;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* SYNCOPCTX */
|
||||
static pthread_key_t syncopctx_key;
|
||||
|
||||
static void
|
||||
syncopctx_key_destroy (void *ptr)
|
||||
syncopctx_key_destroy(void *ptr)
|
||||
{
|
||||
struct syncopctx *opctx = ptr;
|
||||
struct syncopctx *opctx = ptr;
|
||||
|
||||
if (opctx) {
|
||||
if (opctx->groups)
|
||||
GF_FREE (opctx->groups);
|
||||
if (opctx) {
|
||||
if (opctx->groups)
|
||||
GF_FREE(opctx->groups);
|
||||
|
||||
GF_FREE (opctx);
|
||||
}
|
||||
GF_FREE(opctx);
|
||||
}
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
void *
|
||||
syncopctx_getctx ()
|
||||
syncopctx_getctx()
|
||||
{
|
||||
void *opctx = NULL;
|
||||
void *opctx = NULL;
|
||||
|
||||
opctx = pthread_getspecific (syncopctx_key);
|
||||
opctx = pthread_getspecific(syncopctx_key);
|
||||
|
||||
return opctx;
|
||||
return opctx;
|
||||
}
|
||||
|
||||
int
|
||||
syncopctx_setctx (void *ctx)
|
||||
syncopctx_setctx(void *ctx)
|
||||
{
|
||||
int ret = 0;
|
||||
int ret = 0;
|
||||
|
||||
ret = pthread_setspecific (syncopctx_key, ctx);
|
||||
ret = pthread_setspecific(syncopctx_key, ctx);
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
syncopctx_init (void)
|
||||
syncopctx_init(void)
|
||||
{
|
||||
int ret;
|
||||
int ret;
|
||||
|
||||
ret = pthread_key_create (&syncopctx_key, syncopctx_key_destroy);
|
||||
ret = pthread_key_create(&syncopctx_key, syncopctx_key_destroy);
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* SYNCTASK */
|
||||
|
||||
int
|
||||
synctask_init ()
|
||||
synctask_init()
|
||||
{
|
||||
int ret = 0;
|
||||
int ret = 0;
|
||||
|
||||
ret = pthread_key_create (&synctask_key, NULL);
|
||||
ret = pthread_key_create(&synctask_key, NULL);
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *
|
||||
synctask_get ()
|
||||
synctask_get()
|
||||
{
|
||||
void *synctask = NULL;
|
||||
void *synctask = NULL;
|
||||
|
||||
synctask = pthread_getspecific (synctask_key);
|
||||
synctask = pthread_getspecific(synctask_key);
|
||||
|
||||
return synctask;
|
||||
return synctask;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
synctask_set (void *synctask)
|
||||
synctask_set(void *synctask)
|
||||
{
|
||||
int ret = 0;
|
||||
int ret = 0;
|
||||
|
||||
pthread_setspecific (synctask_key, synctask);
|
||||
pthread_setspecific(synctask_key, synctask);
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
//UUID_BUFFER
|
||||
// UUID_BUFFER
|
||||
|
||||
void
|
||||
glusterfs_uuid_buf_destroy (void *ptr)
|
||||
glusterfs_uuid_buf_destroy(void *ptr)
|
||||
{
|
||||
FREE (ptr);
|
||||
FREE(ptr);
|
||||
}
|
||||
|
||||
int
|
||||
glusterfs_uuid_buf_init ()
|
||||
glusterfs_uuid_buf_init()
|
||||
{
|
||||
int ret = 0;
|
||||
int ret = 0;
|
||||
|
||||
ret = pthread_key_create (&uuid_buf_key,
|
||||
glusterfs_uuid_buf_destroy);
|
||||
return ret;
|
||||
ret = pthread_key_create(&uuid_buf_key, glusterfs_uuid_buf_destroy);
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *
|
||||
glusterfs_uuid_buf_get ()
|
||||
glusterfs_uuid_buf_get()
|
||||
{
|
||||
char *buf;
|
||||
int ret = 0;
|
||||
char *buf;
|
||||
int ret = 0;
|
||||
|
||||
buf = pthread_getspecific (uuid_buf_key);
|
||||
if(!buf) {
|
||||
buf = MALLOC (GF_UUID_BUF_SIZE);
|
||||
ret = pthread_setspecific (uuid_buf_key, (void *) buf);
|
||||
if (ret)
|
||||
buf = global_uuid_buf;
|
||||
}
|
||||
return buf;
|
||||
buf = pthread_getspecific(uuid_buf_key);
|
||||
if (!buf) {
|
||||
buf = MALLOC(GF_UUID_BUF_SIZE);
|
||||
ret = pthread_setspecific(uuid_buf_key, (void *)buf);
|
||||
if (ret)
|
||||
buf = global_uuid_buf;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* LKOWNER_BUFFER */
|
||||
|
||||
void
|
||||
glusterfs_lkowner_buf_destroy (void *ptr)
|
||||
glusterfs_lkowner_buf_destroy(void *ptr)
|
||||
{
|
||||
FREE (ptr);
|
||||
FREE(ptr);
|
||||
}
|
||||
|
||||
int
|
||||
glusterfs_lkowner_buf_init ()
|
||||
glusterfs_lkowner_buf_init()
|
||||
{
|
||||
int ret = 0;
|
||||
int ret = 0;
|
||||
|
||||
ret = pthread_key_create (&lkowner_buf_key,
|
||||
glusterfs_lkowner_buf_destroy);
|
||||
return ret;
|
||||
ret = pthread_key_create(&lkowner_buf_key, glusterfs_lkowner_buf_destroy);
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *
|
||||
glusterfs_lkowner_buf_get ()
|
||||
glusterfs_lkowner_buf_get()
|
||||
{
|
||||
char *buf;
|
||||
int ret = 0;
|
||||
char *buf;
|
||||
int ret = 0;
|
||||
|
||||
buf = pthread_getspecific (lkowner_buf_key);
|
||||
if(!buf) {
|
||||
buf = MALLOC (GF_LKOWNER_BUF_SIZE);
|
||||
ret = pthread_setspecific (lkowner_buf_key, (void *) buf);
|
||||
if (ret)
|
||||
buf = global_lkowner_buf;
|
||||
}
|
||||
return buf;
|
||||
buf = pthread_getspecific(lkowner_buf_key);
|
||||
if (!buf) {
|
||||
buf = MALLOC(GF_LKOWNER_BUF_SIZE);
|
||||
ret = pthread_setspecific(lkowner_buf_key, (void *)buf);
|
||||
if (ret)
|
||||
buf = global_lkowner_buf;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* Leaseid buffer */
|
||||
void
|
||||
glusterfs_leaseid_buf_destroy (void *ptr)
|
||||
glusterfs_leaseid_buf_destroy(void *ptr)
|
||||
{
|
||||
FREE (ptr);
|
||||
FREE(ptr);
|
||||
}
|
||||
|
||||
int
|
||||
glusterfs_leaseid_buf_init ()
|
||||
glusterfs_leaseid_buf_init()
|
||||
{
|
||||
int ret = 0;
|
||||
int ret = 0;
|
||||
|
||||
ret = pthread_key_create (&leaseid_buf_key,
|
||||
glusterfs_leaseid_buf_destroy);
|
||||
return ret;
|
||||
ret = pthread_key_create(&leaseid_buf_key, glusterfs_leaseid_buf_destroy);
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *
|
||||
glusterfs_leaseid_buf_get ()
|
||||
glusterfs_leaseid_buf_get()
|
||||
{
|
||||
char *buf = NULL;
|
||||
int ret = 0;
|
||||
char *buf = NULL;
|
||||
int ret = 0;
|
||||
|
||||
buf = pthread_getspecific (leaseid_buf_key);
|
||||
if (!buf) {
|
||||
buf = CALLOC (1, GF_LEASE_ID_BUF_SIZE);
|
||||
ret = pthread_setspecific (leaseid_buf_key, (void *) buf);
|
||||
if (ret) {
|
||||
FREE (buf);
|
||||
buf = NULL;
|
||||
}
|
||||
buf = pthread_getspecific(leaseid_buf_key);
|
||||
if (!buf) {
|
||||
buf = CALLOC(1, GF_LEASE_ID_BUF_SIZE);
|
||||
ret = pthread_setspecific(leaseid_buf_key, (void *)buf);
|
||||
if (ret) {
|
||||
FREE(buf);
|
||||
buf = NULL;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
char *
|
||||
glusterfs_leaseid_exist ()
|
||||
glusterfs_leaseid_exist()
|
||||
{
|
||||
return pthread_getspecific (leaseid_buf_key);
|
||||
return pthread_getspecific(leaseid_buf_key);
|
||||
}
|
||||
|
||||
static void
|
||||
gf_globals_init_once ()
|
||||
gf_globals_init_once()
|
||||
{
|
||||
int ret = 0;
|
||||
int ret = 0;
|
||||
|
||||
ret = glusterfs_this_init ();
|
||||
if (ret) {
|
||||
gf_msg ("", GF_LOG_CRITICAL, 0, LG_MSG_TRANSLATOR_INIT_FAILED,
|
||||
"ERROR: glusterfs-translator init failed");
|
||||
goto out;
|
||||
}
|
||||
ret = glusterfs_this_init();
|
||||
if (ret) {
|
||||
gf_msg("", GF_LOG_CRITICAL, 0, LG_MSG_TRANSLATOR_INIT_FAILED,
|
||||
"ERROR: glusterfs-translator init failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = glusterfs_uuid_buf_init ();
|
||||
if(ret) {
|
||||
gf_msg ("", GF_LOG_CRITICAL, 0, LG_MSG_UUID_BUF_INIT_FAILED,
|
||||
"ERROR: glusterfs uuid buffer init failed");
|
||||
goto out;
|
||||
}
|
||||
ret = glusterfs_uuid_buf_init();
|
||||
if (ret) {
|
||||
gf_msg("", GF_LOG_CRITICAL, 0, LG_MSG_UUID_BUF_INIT_FAILED,
|
||||
"ERROR: glusterfs uuid buffer init failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = glusterfs_lkowner_buf_init ();
|
||||
if(ret) {
|
||||
gf_msg ("", GF_LOG_CRITICAL, 0, LG_MSG_LKOWNER_BUF_INIT_FAILED,
|
||||
"ERROR: glusterfs lkowner buffer init failed");
|
||||
goto out;
|
||||
}
|
||||
ret = glusterfs_lkowner_buf_init();
|
||||
if (ret) {
|
||||
gf_msg("", GF_LOG_CRITICAL, 0, LG_MSG_LKOWNER_BUF_INIT_FAILED,
|
||||
"ERROR: glusterfs lkowner buffer init failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = glusterfs_leaseid_buf_init ();
|
||||
if (ret) {
|
||||
gf_msg ("", GF_LOG_CRITICAL, 0, LG_MSG_LEASEID_BUF_INIT_FAILED,
|
||||
"ERROR: glusterfs leaseid buffer init failed");
|
||||
goto out;
|
||||
}
|
||||
ret = glusterfs_leaseid_buf_init();
|
||||
if (ret) {
|
||||
gf_msg("", GF_LOG_CRITICAL, 0, LG_MSG_LEASEID_BUF_INIT_FAILED,
|
||||
"ERROR: glusterfs leaseid buffer init failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = synctask_init ();
|
||||
if (ret) {
|
||||
gf_msg ("", GF_LOG_CRITICAL, 0, LG_MSG_SYNCTASK_INIT_FAILED,
|
||||
"ERROR: glusterfs synctask init failed");
|
||||
goto out;
|
||||
}
|
||||
ret = synctask_init();
|
||||
if (ret) {
|
||||
gf_msg("", GF_LOG_CRITICAL, 0, LG_MSG_SYNCTASK_INIT_FAILED,
|
||||
"ERROR: glusterfs synctask init failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = syncopctx_init ();
|
||||
if (ret) {
|
||||
gf_msg ("", GF_LOG_CRITICAL, 0, LG_MSG_SYNCOPCTX_INIT_FAILED,
|
||||
"ERROR: glusterfs syncopctx init failed");
|
||||
goto out;
|
||||
}
|
||||
ret = syncopctx_init();
|
||||
if (ret) {
|
||||
gf_msg("", GF_LOG_CRITICAL, 0, LG_MSG_SYNCOPCTX_INIT_FAILED,
|
||||
"ERROR: glusterfs syncopctx init failed");
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
|
||||
if (ret) {
|
||||
gf_msg ("", GF_LOG_CRITICAL, 0, LG_MSG_GLOBAL_INIT_FAILED,
|
||||
"Exiting as global initialization failed");
|
||||
exit (ret);
|
||||
}
|
||||
if (ret) {
|
||||
gf_msg("", GF_LOG_CRITICAL, 0, LG_MSG_GLOBAL_INIT_FAILED,
|
||||
"Exiting as global initialization failed");
|
||||
exit(ret);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
glusterfs_globals_init (glusterfs_ctx_t *ctx)
|
||||
glusterfs_globals_init(glusterfs_ctx_t *ctx)
|
||||
{
|
||||
int ret = 0;
|
||||
int ret = 0;
|
||||
|
||||
gf_log_globals_init (ctx, GF_LOG_INFO);
|
||||
gf_log_globals_init(ctx, GF_LOG_INFO);
|
||||
|
||||
ret = pthread_once (&globals_inited, gf_globals_init_once);
|
||||
ret = pthread_once(&globals_inited, gf_globals_init_once);
|
||||
|
||||
if (ret)
|
||||
gf_msg ("", GF_LOG_CRITICAL, ret, LG_MSG_PTHREAD_FAILED,
|
||||
"pthread_once failed");
|
||||
if (ret)
|
||||
gf_msg("", GF_LOG_CRITICAL, ret, LG_MSG_PTHREAD_FAILED,
|
||||
"pthread_once failed");
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
@ -15,183 +15,180 @@
|
||||
#include "graph-utils.h"
|
||||
#include "libglusterfs-messages.h"
|
||||
|
||||
|
||||
struct gf_printer {
|
||||
ssize_t (*write) (struct gf_printer *gp, char *buf, size_t len);
|
||||
void *priv;
|
||||
int len;
|
||||
ssize_t (*write)(struct gf_printer *gp, char *buf, size_t len);
|
||||
void *priv;
|
||||
int len;
|
||||
};
|
||||
|
||||
static ssize_t
|
||||
gp_write_file (struct gf_printer *gp, char *buf, size_t len)
|
||||
gp_write_file(struct gf_printer *gp, char *buf, size_t len)
|
||||
{
|
||||
FILE *f = gp->priv;
|
||||
FILE *f = gp->priv;
|
||||
|
||||
if (fwrite (buf, len, 1, f) != 1) {
|
||||
gf_msg ("graph-print", GF_LOG_ERROR, errno,
|
||||
LG_MSG_FWRITE_FAILED, "fwrite failed");
|
||||
if (fwrite(buf, len, 1, f) != 1) {
|
||||
gf_msg("graph-print", GF_LOG_ERROR, errno, LG_MSG_FWRITE_FAILED,
|
||||
"fwrite failed");
|
||||
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
return len;
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
gp_write_buf (struct gf_printer *gp, char *buf, size_t len)
|
||||
gp_write_buf(struct gf_printer *gp, char *buf, size_t len)
|
||||
{
|
||||
struct iovec *iov = gp->priv;
|
||||
struct iovec *iov = gp->priv;
|
||||
|
||||
if (iov->iov_len < len) {
|
||||
gf_msg ("graph-print", GF_LOG_ERROR, 0, LG_MSG_BUFFER_FULL,
|
||||
"buffer full");
|
||||
if (iov->iov_len < len) {
|
||||
gf_msg("graph-print", GF_LOG_ERROR, 0, LG_MSG_BUFFER_FULL,
|
||||
"buffer full");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy (iov->iov_base, buf, len);
|
||||
iov->iov_base += len;
|
||||
iov->iov_len -= len;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int
|
||||
gpprintf (struct gf_printer *gp, const char *format, ...)
|
||||
{
|
||||
va_list arg;
|
||||
char *str = NULL;
|
||||
int ret = 0;
|
||||
|
||||
va_start (arg, format);
|
||||
ret = gf_vasprintf (&str, format, arg);
|
||||
va_end (arg);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = gp->write (gp, str, ret);
|
||||
|
||||
GF_FREE (str);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define GPPRINTF(gp, fmt, ...) do { \
|
||||
ret = gpprintf (gp, fmt, ## __VA_ARGS__); \
|
||||
if (ret == -1) \
|
||||
goto out; \
|
||||
else \
|
||||
gp->len += ret; \
|
||||
} while (0)
|
||||
|
||||
static int
|
||||
_print_volume_options (dict_t *d, char *k, data_t *v,
|
||||
void *tmp)
|
||||
{
|
||||
struct gf_printer *gp = tmp;
|
||||
int ret = 0;
|
||||
GPPRINTF (gp, " option %s %s\n", k, v->data);
|
||||
return 0;
|
||||
out:
|
||||
/* means, it is a failure */
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(iov->iov_base, buf, len);
|
||||
iov->iov_base += len;
|
||||
iov->iov_len -= len;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int
|
||||
glusterfs_graph_print (struct gf_printer *gp, glusterfs_graph_t *graph)
|
||||
gpprintf(struct gf_printer *gp, const char *format, ...)
|
||||
{
|
||||
xlator_t *trav = NULL;
|
||||
xlator_list_t *xch = NULL;
|
||||
int ret = 0;
|
||||
ssize_t len = 0;
|
||||
va_list arg;
|
||||
char *str = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (!graph->first)
|
||||
return 0;
|
||||
va_start(arg, format);
|
||||
ret = gf_vasprintf(&str, format, arg);
|
||||
va_end(arg);
|
||||
|
||||
for (trav = graph->first; trav->next; trav = trav->next);
|
||||
for (; trav; trav = trav->prev) {
|
||||
GPPRINTF (gp, "volume %s\n type %s\n", trav->name,
|
||||
trav->type);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = dict_foreach (trav->options, _print_volume_options, gp);
|
||||
if (ret)
|
||||
goto out;
|
||||
ret = gp->write(gp, str, ret);
|
||||
|
||||
if (trav->children) {
|
||||
GPPRINTF (gp, " subvolumes");
|
||||
GF_FREE(str);
|
||||
|
||||
for (xch = trav->children; xch; xch = xch->next)
|
||||
GPPRINTF (gp, " %s", xch->xlator->name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
GPPRINTF (gp, "\n");
|
||||
}
|
||||
#define GPPRINTF(gp, fmt, ...) \
|
||||
do { \
|
||||
ret = gpprintf(gp, fmt, ##__VA_ARGS__); \
|
||||
if (ret == -1) \
|
||||
goto out; \
|
||||
else \
|
||||
gp->len += ret; \
|
||||
} while (0)
|
||||
|
||||
GPPRINTF (gp, "end-volume\n");
|
||||
if (trav != graph->first)
|
||||
GPPRINTF (gp, "\n");
|
||||
static int
|
||||
_print_volume_options(dict_t *d, char *k, data_t *v, void *tmp)
|
||||
{
|
||||
struct gf_printer *gp = tmp;
|
||||
int ret = 0;
|
||||
GPPRINTF(gp, " option %s %s\n", k, v->data);
|
||||
return 0;
|
||||
out:
|
||||
/* means, it is a failure */
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
glusterfs_graph_print(struct gf_printer *gp, glusterfs_graph_t *graph)
|
||||
{
|
||||
xlator_t *trav = NULL;
|
||||
xlator_list_t *xch = NULL;
|
||||
int ret = 0;
|
||||
ssize_t len = 0;
|
||||
|
||||
if (!graph->first)
|
||||
return 0;
|
||||
|
||||
for (trav = graph->first; trav->next; trav = trav->next)
|
||||
;
|
||||
for (; trav; trav = trav->prev) {
|
||||
GPPRINTF(gp, "volume %s\n type %s\n", trav->name, trav->type);
|
||||
|
||||
ret = dict_foreach(trav->options, _print_volume_options, gp);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (trav->children) {
|
||||
GPPRINTF(gp, " subvolumes");
|
||||
|
||||
for (xch = trav->children; xch; xch = xch->next)
|
||||
GPPRINTF(gp, " %s", xch->xlator->name);
|
||||
|
||||
GPPRINTF(gp, "\n");
|
||||
}
|
||||
|
||||
GPPRINTF(gp, "end-volume\n");
|
||||
if (trav != graph->first)
|
||||
GPPRINTF(gp, "\n");
|
||||
}
|
||||
|
||||
out:
|
||||
len = gp->len;
|
||||
if (ret == -1) {
|
||||
gf_msg ("graph-print", GF_LOG_ERROR, 0, LG_MSG_PRINT_FAILED,
|
||||
"printing failed");
|
||||
len = gp->len;
|
||||
if (ret == -1) {
|
||||
gf_msg("graph-print", GF_LOG_ERROR, 0, LG_MSG_PRINT_FAILED,
|
||||
"printing failed");
|
||||
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
return len;
|
||||
return len;
|
||||
|
||||
#undef GPPRINTF
|
||||
}
|
||||
|
||||
int
|
||||
glusterfs_graph_print_file (FILE *file, glusterfs_graph_t *graph)
|
||||
glusterfs_graph_print_file(FILE *file, glusterfs_graph_t *graph)
|
||||
{
|
||||
struct gf_printer gp = { .write = gp_write_file,
|
||||
.priv = file
|
||||
};
|
||||
struct gf_printer gp = {.write = gp_write_file, .priv = file};
|
||||
|
||||
return glusterfs_graph_print (&gp, graph);
|
||||
return glusterfs_graph_print(&gp, graph);
|
||||
}
|
||||
|
||||
char *
|
||||
glusterfs_graph_print_buf (glusterfs_graph_t *graph)
|
||||
glusterfs_graph_print_buf(glusterfs_graph_t *graph)
|
||||
{
|
||||
FILE *f = NULL;
|
||||
struct iovec iov = {0,};
|
||||
int len = 0;
|
||||
char *buf = NULL;
|
||||
struct gf_printer gp = { .write = gp_write_buf,
|
||||
.priv = &iov
|
||||
};
|
||||
FILE *f = NULL;
|
||||
struct iovec iov = {
|
||||
0,
|
||||
};
|
||||
int len = 0;
|
||||
char *buf = NULL;
|
||||
struct gf_printer gp = {.write = gp_write_buf, .priv = &iov};
|
||||
|
||||
f = fopen ("/dev/null", "a");
|
||||
if (!f) {
|
||||
gf_msg ("graph-print", GF_LOG_ERROR, errno,
|
||||
LG_MSG_DIR_OP_FAILED, "cannot open /dev/null");
|
||||
f = fopen("/dev/null", "a");
|
||||
if (!f) {
|
||||
gf_msg("graph-print", GF_LOG_ERROR, errno, LG_MSG_DIR_OP_FAILED,
|
||||
"cannot open /dev/null");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
len = glusterfs_graph_print_file (f, graph);
|
||||
fclose (f);
|
||||
if (len == -1)
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
len = glusterfs_graph_print_file(f, graph);
|
||||
fclose(f);
|
||||
if (len == -1)
|
||||
return NULL;
|
||||
|
||||
buf = GF_CALLOC (1, len + 1, gf_common_mt_graph_buf);
|
||||
if (!buf) {
|
||||
return NULL;
|
||||
}
|
||||
iov.iov_base = buf;
|
||||
iov.iov_len = len;
|
||||
buf = GF_CALLOC(1, len + 1, gf_common_mt_graph_buf);
|
||||
if (!buf) {
|
||||
return NULL;
|
||||
}
|
||||
iov.iov_base = buf;
|
||||
iov.iov_len = len;
|
||||
|
||||
len = glusterfs_graph_print (&gp, graph);
|
||||
if (len == -1) {
|
||||
GF_FREE (buf);
|
||||
len = glusterfs_graph_print(&gp, graph);
|
||||
if (len == -1) {
|
||||
GF_FREE(buf);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return buf;
|
||||
return buf;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -13,21 +13,20 @@
|
||||
|
||||
#include "hashfn.h"
|
||||
|
||||
#define get16bits(d) (*((const uint16_t *) (d)))
|
||||
#define get16bits(d) (*((const uint16_t *)(d)))
|
||||
|
||||
#define DM_DELTA 0x9E3779B9
|
||||
#define DM_FULLROUNDS 10 /* 32 is overkill, 16 is strong crypto */
|
||||
#define DM_PARTROUNDS 6 /* 6 gets complete mixing */
|
||||
|
||||
#define DM_FULLROUNDS 10 /* 32 is overkill, 16 is strong crypto */
|
||||
#define DM_PARTROUNDS 6 /* 6 gets complete mixing */
|
||||
|
||||
uint32_t
|
||||
ReallySimpleHash (char *path, int len)
|
||||
ReallySimpleHash(char *path, int len)
|
||||
{
|
||||
uint32_t hash = 0;
|
||||
for (;len > 0; len--)
|
||||
hash ^= (char)path[len];
|
||||
uint32_t hash = 0;
|
||||
for (; len > 0; len--)
|
||||
hash ^= (char)path[len];
|
||||
|
||||
return hash;
|
||||
return hash;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -37,146 +36,145 @@ ReallySimpleHash (char *path, int len)
|
||||
|
||||
/* In any case make sure, you return 1 */
|
||||
|
||||
uint32_t SuperFastHash (const char * data, int32_t len) {
|
||||
uint32_t hash = len, tmp;
|
||||
int32_t rem;
|
||||
uint32_t
|
||||
SuperFastHash(const char *data, int32_t len)
|
||||
{
|
||||
uint32_t hash = len, tmp;
|
||||
int32_t rem;
|
||||
|
||||
if (len <= 1 || data == NULL) return 1;
|
||||
if (len <= 1 || data == NULL)
|
||||
return 1;
|
||||
|
||||
rem = len & 3;
|
||||
len >>= 2;
|
||||
rem = len & 3;
|
||||
len >>= 2;
|
||||
|
||||
/* Main loop */
|
||||
for (;len > 0; len--) {
|
||||
hash += get16bits (data);
|
||||
tmp = (get16bits (data+2) << 11) ^ hash;
|
||||
hash = (hash << 16) ^ tmp;
|
||||
data += 2*sizeof (uint16_t);
|
||||
hash += hash >> 11;
|
||||
}
|
||||
/* Main loop */
|
||||
for (; len > 0; len--) {
|
||||
hash += get16bits(data);
|
||||
tmp = (get16bits(data + 2) << 11) ^ hash;
|
||||
hash = (hash << 16) ^ tmp;
|
||||
data += 2 * sizeof(uint16_t);
|
||||
hash += hash >> 11;
|
||||
}
|
||||
|
||||
/* Handle end cases */
|
||||
switch (rem) {
|
||||
case 3: hash += get16bits (data);
|
||||
hash ^= hash << 16;
|
||||
hash ^= data[sizeof (uint16_t)] << 18;
|
||||
hash += hash >> 11;
|
||||
break;
|
||||
case 2: hash += get16bits (data);
|
||||
hash ^= hash << 11;
|
||||
hash += hash >> 17;
|
||||
break;
|
||||
case 1: hash += *data;
|
||||
hash ^= hash << 10;
|
||||
hash += hash >> 1;
|
||||
}
|
||||
/* Handle end cases */
|
||||
switch (rem) {
|
||||
case 3:
|
||||
hash += get16bits(data);
|
||||
hash ^= hash << 16;
|
||||
hash ^= data[sizeof(uint16_t)] << 18;
|
||||
hash += hash >> 11;
|
||||
break;
|
||||
case 2:
|
||||
hash += get16bits(data);
|
||||
hash ^= hash << 11;
|
||||
hash += hash >> 17;
|
||||
break;
|
||||
case 1:
|
||||
hash += *data;
|
||||
hash ^= hash << 10;
|
||||
hash += hash >> 1;
|
||||
}
|
||||
|
||||
/* Force "avalanching" of final 127 bits */
|
||||
hash ^= hash << 3;
|
||||
hash += hash >> 5;
|
||||
hash ^= hash << 4;
|
||||
hash += hash >> 17;
|
||||
hash ^= hash << 25;
|
||||
hash += hash >> 6;
|
||||
/* Force "avalanching" of final 127 bits */
|
||||
hash ^= hash << 3;
|
||||
hash += hash >> 5;
|
||||
hash ^= hash << 4;
|
||||
hash += hash >> 17;
|
||||
hash ^= hash << 25;
|
||||
hash += hash >> 6;
|
||||
|
||||
return hash;
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
/* Davies-Meyer hashing function implementation
|
||||
*/
|
||||
static int
|
||||
dm_round (int rounds, uint32_t *array, uint32_t *h0, uint32_t *h1)
|
||||
dm_round(int rounds, uint32_t *array, uint32_t *h0, uint32_t *h1)
|
||||
{
|
||||
uint32_t sum = 0;
|
||||
int n = 0;
|
||||
uint32_t b0 = 0;
|
||||
uint32_t b1 = 0;
|
||||
uint32_t sum = 0;
|
||||
int n = 0;
|
||||
uint32_t b0 = 0;
|
||||
uint32_t b1 = 0;
|
||||
|
||||
b0 = *h0;
|
||||
b1 = *h1;
|
||||
b0 = *h0;
|
||||
b1 = *h1;
|
||||
|
||||
n = rounds;
|
||||
n = rounds;
|
||||
|
||||
do {
|
||||
sum += DM_DELTA;
|
||||
b0 += ((b1 << 4) + array[0])
|
||||
^ (b1 + sum)
|
||||
^ ((b1 >> 5) + array[1]);
|
||||
b1 += ((b0 << 4) + array[2])
|
||||
^ (b0 + sum)
|
||||
^ ((b0 >> 5) + array[3]);
|
||||
} while (--n);
|
||||
do {
|
||||
sum += DM_DELTA;
|
||||
b0 += ((b1 << 4) + array[0]) ^ (b1 + sum) ^ ((b1 >> 5) + array[1]);
|
||||
b1 += ((b0 << 4) + array[2]) ^ (b0 + sum) ^ ((b0 >> 5) + array[3]);
|
||||
} while (--n);
|
||||
|
||||
*h0 += b0;
|
||||
*h1 += b1;
|
||||
*h0 += b0;
|
||||
*h1 += b1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
uint32_t
|
||||
__pad (int len)
|
||||
{
|
||||
uint32_t pad = 0;
|
||||
|
||||
pad = (uint32_t) len | ((uint32_t) len << 8);
|
||||
pad |= pad << 16;
|
||||
|
||||
return pad;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
gf_dm_hashfn (const char *msg, int len)
|
||||
__pad(int len)
|
||||
{
|
||||
uint32_t h0 = 0x9464a485;
|
||||
uint32_t h1 = 0x542e1a94;
|
||||
uint32_t array[4];
|
||||
uint32_t pad = 0;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
int full_quads = 0;
|
||||
int full_words = 0;
|
||||
int full_bytes = 0;
|
||||
uint32_t *intmsg = NULL;
|
||||
int word = 0;
|
||||
uint32_t pad = 0;
|
||||
|
||||
pad = (uint32_t)len | ((uint32_t)len << 8);
|
||||
pad |= pad << 16;
|
||||
|
||||
intmsg = (uint32_t *) msg;
|
||||
pad = __pad (len);
|
||||
return pad;
|
||||
}
|
||||
|
||||
full_bytes = len;
|
||||
full_words = len / 4;
|
||||
full_quads = len / 16;
|
||||
uint32_t
|
||||
gf_dm_hashfn(const char *msg, int len)
|
||||
{
|
||||
uint32_t h0 = 0x9464a485;
|
||||
uint32_t h1 = 0x542e1a94;
|
||||
uint32_t array[4];
|
||||
uint32_t pad = 0;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
int full_quads = 0;
|
||||
int full_words = 0;
|
||||
int full_bytes = 0;
|
||||
uint32_t *intmsg = NULL;
|
||||
int word = 0;
|
||||
|
||||
for (i = 0; i < full_quads; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
word = *intmsg;
|
||||
array[j] = word;
|
||||
intmsg++;
|
||||
full_words--;
|
||||
full_bytes -= 4;
|
||||
}
|
||||
dm_round (DM_PARTROUNDS, &array[0], &h0, &h1);
|
||||
}
|
||||
intmsg = (uint32_t *)msg;
|
||||
pad = __pad(len);
|
||||
|
||||
full_bytes = len;
|
||||
full_words = len / 4;
|
||||
full_quads = len / 16;
|
||||
|
||||
for (i = 0; i < full_quads; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
if (full_words) {
|
||||
word = *intmsg;
|
||||
array[j] = word;
|
||||
intmsg++;
|
||||
full_words--;
|
||||
full_bytes -= 4;
|
||||
} else {
|
||||
array[j] = pad;
|
||||
while (full_bytes) {
|
||||
array[j] <<= 8;
|
||||
array[j] |= msg[len - full_bytes];
|
||||
full_bytes--;
|
||||
}
|
||||
}
|
||||
word = *intmsg;
|
||||
array[j] = word;
|
||||
intmsg++;
|
||||
full_words--;
|
||||
full_bytes -= 4;
|
||||
}
|
||||
dm_round (DM_FULLROUNDS, &array[0], &h0, &h1);
|
||||
dm_round(DM_PARTROUNDS, &array[0], &h0, &h1);
|
||||
}
|
||||
|
||||
return h0 ^ h1;
|
||||
for (j = 0; j < 4; j++) {
|
||||
if (full_words) {
|
||||
word = *intmsg;
|
||||
array[j] = word;
|
||||
intmsg++;
|
||||
full_words--;
|
||||
full_bytes -= 4;
|
||||
} else {
|
||||
array[j] = pad;
|
||||
while (full_bytes) {
|
||||
array[j] <<= 8;
|
||||
array[j] |= msg[len - full_bytes];
|
||||
full_bytes--;
|
||||
}
|
||||
}
|
||||
}
|
||||
dm_round(DM_FULLROUNDS, &array[0], &h0, &h1);
|
||||
|
||||
return h0 ^ h1;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -8,7 +8,6 @@
|
||||
cases as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* This file contains functions to support dumping of
|
||||
* latencies of FOPs broken down by subvolumes.
|
||||
@ -21,82 +20,77 @@
|
||||
#include "libglusterfs-messages.h"
|
||||
|
||||
void
|
||||
gf_update_latency (call_frame_t *frame)
|
||||
gf_update_latency(call_frame_t *frame)
|
||||
{
|
||||
double elapsed;
|
||||
struct timespec *begin, *end;
|
||||
double elapsed;
|
||||
struct timespec *begin, *end;
|
||||
|
||||
fop_latency_t *lat;
|
||||
fop_latency_t *lat;
|
||||
|
||||
begin = &frame->begin;
|
||||
end = &frame->end;
|
||||
begin = &frame->begin;
|
||||
end = &frame->end;
|
||||
|
||||
if (!(begin->tv_sec && end->tv_sec))
|
||||
goto out;
|
||||
if (!(begin->tv_sec && end->tv_sec))
|
||||
goto out;
|
||||
|
||||
elapsed = (end->tv_sec - begin->tv_sec) * 1e9
|
||||
+ (end->tv_nsec - begin->tv_nsec);
|
||||
elapsed = (end->tv_sec - begin->tv_sec) * 1e9 +
|
||||
(end->tv_nsec - begin->tv_nsec);
|
||||
|
||||
if (frame->op < 0 || frame->op >= GF_FOP_MAXVALUE) {
|
||||
gf_log ("[core]", GF_LOG_WARNING,
|
||||
"Invalid frame op value: %d",
|
||||
frame->op);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Can happen mostly at initiator xlator, as STACK_WIND/UNWIND macros
|
||||
set it right anyways for those frames */
|
||||
if (!frame->op)
|
||||
frame->op = frame->root->op;
|
||||
|
||||
lat = &frame->this->stats.interval.latencies[frame->op];
|
||||
|
||||
if (lat->max < elapsed)
|
||||
lat->max = elapsed;
|
||||
|
||||
if (lat->min > elapsed)
|
||||
lat->min = elapsed;
|
||||
|
||||
lat->total += elapsed;
|
||||
lat->count++;
|
||||
out:
|
||||
if (frame->op < 0 || frame->op >= GF_FOP_MAXVALUE) {
|
||||
gf_log("[core]", GF_LOG_WARNING, "Invalid frame op value: %d",
|
||||
frame->op);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Can happen mostly at initiator xlator, as STACK_WIND/UNWIND macros
|
||||
set it right anyways for those frames */
|
||||
if (!frame->op)
|
||||
frame->op = frame->root->op;
|
||||
|
||||
lat = &frame->this->stats.interval.latencies[frame->op];
|
||||
|
||||
if (lat->max < elapsed)
|
||||
lat->max = elapsed;
|
||||
|
||||
if (lat->min > elapsed)
|
||||
lat->min = elapsed;
|
||||
|
||||
lat->total += elapsed;
|
||||
lat->count++;
|
||||
out:
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
gf_proc_dump_latency_info (xlator_t *xl)
|
||||
gf_proc_dump_latency_info(xlator_t *xl)
|
||||
{
|
||||
char key_prefix[GF_DUMP_MAX_BUF_LEN];
|
||||
char key[GF_DUMP_MAX_BUF_LEN];
|
||||
int i;
|
||||
char key_prefix[GF_DUMP_MAX_BUF_LEN];
|
||||
char key[GF_DUMP_MAX_BUF_LEN];
|
||||
int i;
|
||||
|
||||
snprintf (key_prefix, GF_DUMP_MAX_BUF_LEN, "%s.latency", xl->name);
|
||||
gf_proc_dump_add_section (key_prefix);
|
||||
snprintf(key_prefix, GF_DUMP_MAX_BUF_LEN, "%s.latency", xl->name);
|
||||
gf_proc_dump_add_section(key_prefix);
|
||||
|
||||
for (i = 0; i < GF_FOP_MAXVALUE; i++) {
|
||||
gf_proc_dump_build_key (key, key_prefix, "%s",
|
||||
(char *)gf_fop_list[i]);
|
||||
for (i = 0; i < GF_FOP_MAXVALUE; i++) {
|
||||
gf_proc_dump_build_key(key, key_prefix, "%s", (char *)gf_fop_list[i]);
|
||||
|
||||
fop_latency_t *lat = &xl->stats.interval.latencies[i];
|
||||
fop_latency_t *lat = &xl->stats.interval.latencies[i];
|
||||
|
||||
/* Doesn't make sense to continue if there are no fops
|
||||
came in the given interval */
|
||||
if (!lat->count)
|
||||
continue;
|
||||
/* Doesn't make sense to continue if there are no fops
|
||||
came in the given interval */
|
||||
if (!lat->count)
|
||||
continue;
|
||||
|
||||
gf_proc_dump_write (key, "%.03f,%"PRId64",%.03f",
|
||||
(lat->total / lat->count), lat->count,
|
||||
lat->total);
|
||||
}
|
||||
gf_proc_dump_write(key, "%.03f,%" PRId64 ",%.03f",
|
||||
(lat->total / lat->count), lat->count, lat->total);
|
||||
}
|
||||
|
||||
memset (xl->stats.interval.latencies, 0,
|
||||
sizeof (xl->stats.interval.latencies));
|
||||
memset(xl->stats.interval.latencies, 0,
|
||||
sizeof(xl->stats.interval.latencies));
|
||||
|
||||
/* make sure 'min' is set to high value, so it would be
|
||||
properly set later */
|
||||
for (i = 0; i < GF_FOP_MAXVALUE; i++) {
|
||||
xl->stats.interval.latencies[i].min = 0xffffffff;
|
||||
}
|
||||
/* make sure 'min' is set to high value, so it would be
|
||||
properly set later */
|
||||
for (i = 0; i < GF_FOP_MAXVALUE; i++) {
|
||||
xl->stats.interval.latencies[i].min = 0xffffffff;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,10 +19,9 @@
|
||||
|
||||
int use_spinlocks = 0;
|
||||
|
||||
static void __attribute__((constructor))
|
||||
gf_lock_setup (void)
|
||||
static void __attribute__((constructor)) gf_lock_setup(void)
|
||||
{
|
||||
//use_spinlocks = (sysconf(_SC_NPROCESSORS_ONLN) > 1);
|
||||
// use_spinlocks = (sysconf(_SC_NPROCESSORS_ONLN) > 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -17,254 +17,256 @@
|
||||
static void
|
||||
dump_mem_acct_details(xlator_t *xl, int fd)
|
||||
{
|
||||
struct mem_acct_rec *mem_rec;
|
||||
int i = 0;
|
||||
struct mem_acct_rec *mem_rec;
|
||||
int i = 0;
|
||||
|
||||
if (!xl || !xl->mem_acct || (xl->ctx->active != xl->graph))
|
||||
return;
|
||||
if (!xl || !xl->mem_acct || (xl->ctx->active != xl->graph))
|
||||
return;
|
||||
|
||||
dprintf (fd, "# %s.%s.total.num_types %d\n", xl->type, xl->name,
|
||||
xl->mem_acct->num_types);
|
||||
dprintf(fd, "# %s.%s.total.num_types %d\n", xl->type, xl->name,
|
||||
xl->mem_acct->num_types);
|
||||
|
||||
dprintf (fd, "# type, in-use-size, in-use-units, max-size, "
|
||||
"max-units, total-allocs\n");
|
||||
dprintf(fd,
|
||||
"# type, in-use-size, in-use-units, max-size, "
|
||||
"max-units, total-allocs\n");
|
||||
|
||||
for (i = 0; i < xl->mem_acct->num_types; i++) {
|
||||
mem_rec = &xl->mem_acct->rec[i];
|
||||
if (mem_rec->num_allocs == 0)
|
||||
continue;
|
||||
dprintf (fd, "# %s, %"GF_PRI_SIZET", %u, %"GF_PRI_SIZET", %u,"
|
||||
" %u\n", mem_rec->typestr, mem_rec->size,
|
||||
mem_rec->num_allocs, mem_rec->max_size,
|
||||
mem_rec->max_num_allocs, mem_rec->total_allocs);
|
||||
}
|
||||
for (i = 0; i < xl->mem_acct->num_types; i++) {
|
||||
mem_rec = &xl->mem_acct->rec[i];
|
||||
if (mem_rec->num_allocs == 0)
|
||||
continue;
|
||||
dprintf(fd,
|
||||
"# %s, %" GF_PRI_SIZET ", %u, %" GF_PRI_SIZET
|
||||
", %u,"
|
||||
" %u\n",
|
||||
mem_rec->typestr, mem_rec->size, mem_rec->num_allocs,
|
||||
mem_rec->max_size, mem_rec->max_num_allocs,
|
||||
mem_rec->total_allocs);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dump_global_memory_accounting (int fd)
|
||||
dump_global_memory_accounting(int fd)
|
||||
{
|
||||
#if MEMORY_ACCOUNTING_STATS
|
||||
int i = 0;
|
||||
uint64_t count = 0;
|
||||
int i = 0;
|
||||
uint64_t count = 0;
|
||||
|
||||
uint64_t tcalloc = GF_ATOMIC_GET (gf_memory_stat_counts.total_calloc);
|
||||
uint64_t tmalloc = GF_ATOMIC_GET (gf_memory_stat_counts.total_malloc);
|
||||
uint64_t tfree = GF_ATOMIC_GET (gf_memory_stat_counts.total_free);
|
||||
uint64_t tcalloc = GF_ATOMIC_GET(gf_memory_stat_counts.total_calloc);
|
||||
uint64_t tmalloc = GF_ATOMIC_GET(gf_memory_stat_counts.total_malloc);
|
||||
uint64_t tfree = GF_ATOMIC_GET(gf_memory_stat_counts.total_free);
|
||||
|
||||
dprintf (fd, "memory.total.calloc %lu\n", tcalloc);
|
||||
dprintf (fd, "memory.total.malloc %lu\n", tmalloc);
|
||||
dprintf (fd, "memory.total.realloc %lu\n",
|
||||
GF_ATOMIC_GET (gf_memory_stat_counts.total_realloc));
|
||||
dprintf (fd, "memory.total.free %lu\n", tfree);
|
||||
dprintf (fd, "memory.total.in-use %lu\n", ((tcalloc + tmalloc) - tfree));
|
||||
dprintf(fd, "memory.total.calloc %lu\n", tcalloc);
|
||||
dprintf(fd, "memory.total.malloc %lu\n", tmalloc);
|
||||
dprintf(fd, "memory.total.realloc %lu\n",
|
||||
GF_ATOMIC_GET(gf_memory_stat_counts.total_realloc));
|
||||
dprintf(fd, "memory.total.free %lu\n", tfree);
|
||||
dprintf(fd, "memory.total.in-use %lu\n", ((tcalloc + tmalloc) - tfree));
|
||||
|
||||
for (i = 0; i < GF_BLK_MAX_VALUE; i++) {
|
||||
count = GF_ATOMIC_GET (gf_memory_stat_counts.blk_size[i]);
|
||||
dprintf (fd, "memory.total.blk_size.%s %lu\n",
|
||||
gf_mem_stats_blk[i].blk_size_str, count);
|
||||
}
|
||||
for (i = 0; i < GF_BLK_MAX_VALUE; i++) {
|
||||
count = GF_ATOMIC_GET(gf_memory_stat_counts.blk_size[i]);
|
||||
dprintf(fd, "memory.total.blk_size.%s %lu\n",
|
||||
gf_mem_stats_blk[i].blk_size_str, count);
|
||||
}
|
||||
|
||||
dprintf (fd, "#----\n");
|
||||
dprintf(fd, "#----\n");
|
||||
#endif
|
||||
|
||||
/* This is not a metric to be watched in admin guide,
|
||||
but keeping it here till we resolve all leak-issues
|
||||
would be great */
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
dump_latency_and_count (xlator_t *xl, int fd)
|
||||
{
|
||||
int32_t index = 0;
|
||||
uint64_t fop;
|
||||
uint64_t cbk;
|
||||
uint64_t count;
|
||||
|
||||
if (xl->winds)
|
||||
dprintf (fd, "%s.total.pending-winds.count %lu\n", xl->name, xl->winds);
|
||||
|
||||
/* Need 'fuse' data, and don't need all the old graph info */
|
||||
if ((xl != xl->ctx->master) && (xl->ctx->active != xl->graph))
|
||||
return;
|
||||
|
||||
count = GF_ATOMIC_GET (xl->stats.total.count);
|
||||
dprintf (fd, "%s.total.fop-count %lu\n", xl->name, count);
|
||||
|
||||
count = GF_ATOMIC_GET (xl->stats.interval.count);
|
||||
dprintf (fd, "%s.interval.fop-count %lu\n", xl->name, count);
|
||||
GF_ATOMIC_INIT (xl->stats.interval.count, 0);
|
||||
|
||||
for (index = 0; index < GF_FOP_MAXVALUE; index++) {
|
||||
fop = GF_ATOMIC_GET (xl->stats.total.metrics[index].fop);
|
||||
if (fop) {
|
||||
dprintf (fd, "%s.total.%s.count %lu\n",
|
||||
xl->name, gf_fop_list[index], fop);
|
||||
}
|
||||
fop = GF_ATOMIC_GET (xl->stats.interval.metrics[index].fop);
|
||||
if (fop) {
|
||||
dprintf (fd, "%s.interval.%s.count %lu\n",
|
||||
xl->name, gf_fop_list[index], fop);
|
||||
}
|
||||
cbk = GF_ATOMIC_GET (xl->stats.interval.metrics[index].cbk);
|
||||
if (cbk) {
|
||||
dprintf (fd, "%s.interval.%s.fail_count %lu\n",
|
||||
xl->name, gf_fop_list[index], cbk);
|
||||
}
|
||||
if (xl->stats.interval.latencies[index].count != 0.0) {
|
||||
dprintf (fd, "%s.interval.%s.latency %lf\n",
|
||||
xl->name, gf_fop_list[index],
|
||||
(xl->stats.interval.latencies[index].total /
|
||||
xl->stats.interval.latencies[index].count));
|
||||
dprintf (fd, "%s.interval.%s.max %lf\n",
|
||||
xl->name, gf_fop_list[index],
|
||||
xl->stats.interval.latencies[index].max);
|
||||
dprintf (fd, "%s.interval.%s.min %lf\n",
|
||||
xl->name, gf_fop_list[index],
|
||||
xl->stats.interval.latencies[index].min);
|
||||
}
|
||||
GF_ATOMIC_INIT (xl->stats.interval.metrics[index].cbk, 0);
|
||||
GF_ATOMIC_INIT (xl->stats.interval.metrics[index].fop, 0);
|
||||
}
|
||||
memset (xl->stats.interval.latencies, 0,
|
||||
sizeof (xl->stats.interval.latencies));
|
||||
}
|
||||
|
||||
static inline void
|
||||
dump_call_stack_details (glusterfs_ctx_t *ctx, int fd)
|
||||
{
|
||||
dprintf (fd, "total.stack.count %lu\n",
|
||||
GF_ATOMIC_GET (ctx->pool->total_count));
|
||||
dprintf (fd, "total.stack.in-flight %lu\n",
|
||||
ctx->pool->cnt);
|
||||
}
|
||||
|
||||
static inline void
|
||||
dump_dict_details (glusterfs_ctx_t *ctx, int fd)
|
||||
{
|
||||
uint64_t total_dicts = 0;
|
||||
uint64_t total_pairs = 0;
|
||||
|
||||
total_dicts = GF_ATOMIC_GET (ctx->stats.total_dicts_used);
|
||||
total_pairs = GF_ATOMIC_GET (ctx->stats.total_pairs_used);
|
||||
|
||||
dprintf (fd, "total.dict.max-pairs-per %lu\n",
|
||||
GF_ATOMIC_GET (ctx->stats.max_dict_pairs));
|
||||
dprintf (fd, "total.dict.pairs-used %lu\n", total_pairs);
|
||||
dprintf (fd, "total.dict.used %lu\n", total_dicts);
|
||||
dprintf (fd, "total.dict.average-pairs %lu\n",
|
||||
(total_pairs / total_dicts));
|
||||
/* This is not a metric to be watched in admin guide,
|
||||
but keeping it here till we resolve all leak-issues
|
||||
would be great */
|
||||
}
|
||||
|
||||
static void
|
||||
dump_inode_stats (glusterfs_ctx_t *ctx, int fd)
|
||||
dump_latency_and_count(xlator_t *xl, int fd)
|
||||
{
|
||||
}
|
||||
int32_t index = 0;
|
||||
uint64_t fop;
|
||||
uint64_t cbk;
|
||||
uint64_t count;
|
||||
|
||||
static void
|
||||
dump_global_metrics (glusterfs_ctx_t *ctx, int fd)
|
||||
{
|
||||
struct timeval tv;
|
||||
time_t nowtime;
|
||||
struct tm *nowtm;
|
||||
char tmbuf[64] = {0,};
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
nowtime = tv.tv_sec;
|
||||
nowtm = localtime(&nowtime);
|
||||
strftime(tmbuf, sizeof tmbuf, "%Y-%m-%d %H:%M:%S", nowtm);
|
||||
|
||||
/* Let every file have information on which process dumped info */
|
||||
dprintf (fd, "## %s\n", ctx->cmdlinestr);
|
||||
dprintf (fd, "### %s\n", tmbuf);
|
||||
dprintf (fd, "### BrickName: %s\n", ctx->cmd_args.brick_name);
|
||||
dprintf (fd, "### MountName: %s\n", ctx->cmd_args.mount_point);
|
||||
dprintf (fd, "### VolumeName: %s\n", ctx->cmd_args.volume_name);
|
||||
|
||||
/* Dump memory accounting */
|
||||
dump_global_memory_accounting (fd);
|
||||
dprintf (fd, "# -----\n");
|
||||
|
||||
dump_call_stack_details (ctx, fd);
|
||||
dump_dict_details (ctx, fd);
|
||||
dprintf (fd, "# -----\n");
|
||||
|
||||
dump_inode_stats (ctx, fd);
|
||||
dprintf (fd, "# -----\n");
|
||||
}
|
||||
|
||||
static void
|
||||
dump_xl_metrics (glusterfs_ctx_t *ctx, int fd)
|
||||
{
|
||||
xlator_t *xl;
|
||||
|
||||
xl = ctx->active->top;
|
||||
|
||||
while (xl) {
|
||||
dump_latency_and_count (xl, fd);
|
||||
dump_mem_acct_details (xl, fd);
|
||||
if (xl->dump_metrics)
|
||||
xl->dump_metrics (xl, fd);
|
||||
xl = xl->next;
|
||||
}
|
||||
|
||||
if (ctx->master) {
|
||||
xl = ctx->master;
|
||||
|
||||
dump_latency_and_count (xl, fd);
|
||||
dump_mem_acct_details (xl, fd);
|
||||
if (xl->dump_metrics)
|
||||
xl->dump_metrics (xl, fd);
|
||||
}
|
||||
if (xl->winds)
|
||||
dprintf(fd, "%s.total.pending-winds.count %lu\n", xl->name, xl->winds);
|
||||
|
||||
/* Need 'fuse' data, and don't need all the old graph info */
|
||||
if ((xl != xl->ctx->master) && (xl->ctx->active != xl->graph))
|
||||
return;
|
||||
|
||||
count = GF_ATOMIC_GET(xl->stats.total.count);
|
||||
dprintf(fd, "%s.total.fop-count %lu\n", xl->name, count);
|
||||
|
||||
count = GF_ATOMIC_GET(xl->stats.interval.count);
|
||||
dprintf(fd, "%s.interval.fop-count %lu\n", xl->name, count);
|
||||
GF_ATOMIC_INIT(xl->stats.interval.count, 0);
|
||||
|
||||
for (index = 0; index < GF_FOP_MAXVALUE; index++) {
|
||||
fop = GF_ATOMIC_GET(xl->stats.total.metrics[index].fop);
|
||||
if (fop) {
|
||||
dprintf(fd, "%s.total.%s.count %lu\n", xl->name, gf_fop_list[index],
|
||||
fop);
|
||||
}
|
||||
fop = GF_ATOMIC_GET(xl->stats.interval.metrics[index].fop);
|
||||
if (fop) {
|
||||
dprintf(fd, "%s.interval.%s.count %lu\n", xl->name,
|
||||
gf_fop_list[index], fop);
|
||||
}
|
||||
cbk = GF_ATOMIC_GET(xl->stats.interval.metrics[index].cbk);
|
||||
if (cbk) {
|
||||
dprintf(fd, "%s.interval.%s.fail_count %lu\n", xl->name,
|
||||
gf_fop_list[index], cbk);
|
||||
}
|
||||
if (xl->stats.interval.latencies[index].count != 0.0) {
|
||||
dprintf(fd, "%s.interval.%s.latency %lf\n", xl->name,
|
||||
gf_fop_list[index],
|
||||
(xl->stats.interval.latencies[index].total /
|
||||
xl->stats.interval.latencies[index].count));
|
||||
dprintf(fd, "%s.interval.%s.max %lf\n", xl->name,
|
||||
gf_fop_list[index],
|
||||
xl->stats.interval.latencies[index].max);
|
||||
dprintf(fd, "%s.interval.%s.min %lf\n", xl->name,
|
||||
gf_fop_list[index],
|
||||
xl->stats.interval.latencies[index].min);
|
||||
}
|
||||
GF_ATOMIC_INIT(xl->stats.interval.metrics[index].cbk, 0);
|
||||
GF_ATOMIC_INIT(xl->stats.interval.metrics[index].fop, 0);
|
||||
}
|
||||
memset(xl->stats.interval.latencies, 0,
|
||||
sizeof(xl->stats.interval.latencies));
|
||||
}
|
||||
|
||||
static inline void
|
||||
dump_call_stack_details(glusterfs_ctx_t *ctx, int fd)
|
||||
{
|
||||
dprintf(fd, "total.stack.count %lu\n",
|
||||
GF_ATOMIC_GET(ctx->pool->total_count));
|
||||
dprintf(fd, "total.stack.in-flight %lu\n", ctx->pool->cnt);
|
||||
}
|
||||
|
||||
static inline void
|
||||
dump_dict_details(glusterfs_ctx_t *ctx, int fd)
|
||||
{
|
||||
uint64_t total_dicts = 0;
|
||||
uint64_t total_pairs = 0;
|
||||
|
||||
total_dicts = GF_ATOMIC_GET(ctx->stats.total_dicts_used);
|
||||
total_pairs = GF_ATOMIC_GET(ctx->stats.total_pairs_used);
|
||||
|
||||
dprintf(fd, "total.dict.max-pairs-per %lu\n",
|
||||
GF_ATOMIC_GET(ctx->stats.max_dict_pairs));
|
||||
dprintf(fd, "total.dict.pairs-used %lu\n", total_pairs);
|
||||
dprintf(fd, "total.dict.used %lu\n", total_dicts);
|
||||
dprintf(fd, "total.dict.average-pairs %lu\n", (total_pairs / total_dicts));
|
||||
}
|
||||
|
||||
static void
|
||||
dump_inode_stats(glusterfs_ctx_t *ctx, int fd)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
dump_global_metrics(glusterfs_ctx_t *ctx, int fd)
|
||||
{
|
||||
struct timeval tv;
|
||||
time_t nowtime;
|
||||
struct tm *nowtm;
|
||||
char tmbuf[64] = {
|
||||
0,
|
||||
};
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
nowtime = tv.tv_sec;
|
||||
nowtm = localtime(&nowtime);
|
||||
strftime(tmbuf, sizeof tmbuf, "%Y-%m-%d %H:%M:%S", nowtm);
|
||||
|
||||
/* Let every file have information on which process dumped info */
|
||||
dprintf(fd, "## %s\n", ctx->cmdlinestr);
|
||||
dprintf(fd, "### %s\n", tmbuf);
|
||||
dprintf(fd, "### BrickName: %s\n", ctx->cmd_args.brick_name);
|
||||
dprintf(fd, "### MountName: %s\n", ctx->cmd_args.mount_point);
|
||||
dprintf(fd, "### VolumeName: %s\n", ctx->cmd_args.volume_name);
|
||||
|
||||
/* Dump memory accounting */
|
||||
dump_global_memory_accounting(fd);
|
||||
dprintf(fd, "# -----\n");
|
||||
|
||||
dump_call_stack_details(ctx, fd);
|
||||
dump_dict_details(ctx, fd);
|
||||
dprintf(fd, "# -----\n");
|
||||
|
||||
dump_inode_stats(ctx, fd);
|
||||
dprintf(fd, "# -----\n");
|
||||
}
|
||||
|
||||
static void
|
||||
dump_xl_metrics(glusterfs_ctx_t *ctx, int fd)
|
||||
{
|
||||
xlator_t *xl;
|
||||
|
||||
xl = ctx->active->top;
|
||||
|
||||
while (xl) {
|
||||
dump_latency_and_count(xl, fd);
|
||||
dump_mem_acct_details(xl, fd);
|
||||
if (xl->dump_metrics)
|
||||
xl->dump_metrics(xl, fd);
|
||||
xl = xl->next;
|
||||
}
|
||||
|
||||
if (ctx->master) {
|
||||
xl = ctx->master;
|
||||
|
||||
dump_latency_and_count(xl, fd);
|
||||
dump_mem_acct_details(xl, fd);
|
||||
if (xl->dump_metrics)
|
||||
xl->dump_metrics(xl, fd);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
char *
|
||||
gf_monitor_metrics (glusterfs_ctx_t *ctx)
|
||||
gf_monitor_metrics(glusterfs_ctx_t *ctx)
|
||||
{
|
||||
int ret = -1;
|
||||
int fd = 0;
|
||||
char *filepath, *dumppath;
|
||||
int ret = -1;
|
||||
int fd = 0;
|
||||
char *filepath, *dumppath;
|
||||
|
||||
dumppath = ctx->config.metrics_dumppath;
|
||||
if (dumppath == NULL) {
|
||||
dumppath = GLUSTER_METRICS_DIR;
|
||||
}
|
||||
dumppath = ctx->config.metrics_dumppath;
|
||||
if (dumppath == NULL) {
|
||||
dumppath = GLUSTER_METRICS_DIR;
|
||||
}
|
||||
|
||||
ret = gf_asprintf(&filepath, "%s/gmetrics.XXXXXX", dumppath);
|
||||
if (ret < 0) {
|
||||
return NULL;
|
||||
}
|
||||
ret = gf_asprintf(&filepath, "%s/gmetrics.XXXXXX", dumppath);
|
||||
if (ret < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* coverity[secure_temp] mkstemp uses 0600 as the mode and is safe */
|
||||
fd = mkstemp (filepath);
|
||||
if (fd < 0) {
|
||||
gf_msg ("monitoring", GF_LOG_ERROR, 0, LG_MSG_STRDUP_ERROR,
|
||||
"failed to open tmp file %s (%s)",
|
||||
filepath, strerror (errno));
|
||||
GF_FREE (filepath);
|
||||
return NULL;
|
||||
}
|
||||
/* coverity[secure_temp] mkstemp uses 0600 as the mode and is safe */
|
||||
fd = mkstemp(filepath);
|
||||
if (fd < 0) {
|
||||
gf_msg("monitoring", GF_LOG_ERROR, 0, LG_MSG_STRDUP_ERROR,
|
||||
"failed to open tmp file %s (%s)", filepath, strerror(errno));
|
||||
GF_FREE(filepath);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dump_global_metrics (ctx, fd);
|
||||
dump_global_metrics(ctx, fd);
|
||||
|
||||
dump_xl_metrics (ctx, fd);
|
||||
dump_xl_metrics(ctx, fd);
|
||||
|
||||
/* This below line is used just to capture any errors with dprintf() */
|
||||
ret = dprintf (fd, "\n# End of metrics\n");
|
||||
if (ret < 0) {
|
||||
gf_msg ("monitoring", GF_LOG_WARNING, 0, LG_MSG_STRDUP_ERROR,
|
||||
"dprintf() failed: %s", strerror (errno));
|
||||
}
|
||||
/* This below line is used just to capture any errors with dprintf() */
|
||||
ret = dprintf(fd, "\n# End of metrics\n");
|
||||
if (ret < 0) {
|
||||
gf_msg("monitoring", GF_LOG_WARNING, 0, LG_MSG_STRDUP_ERROR,
|
||||
"dprintf() failed: %s", strerror(errno));
|
||||
}
|
||||
|
||||
ret = sys_fsync (fd);
|
||||
if (ret < 0) {
|
||||
gf_msg ("monitoring", GF_LOG_WARNING, 0, LG_MSG_STRDUP_ERROR,
|
||||
"fsync() failed: %s", strerror (errno));
|
||||
}
|
||||
sys_close (fd);
|
||||
ret = sys_fsync(fd);
|
||||
if (ret < 0) {
|
||||
gf_msg("monitoring", GF_LOG_WARNING, 0, LG_MSG_STRDUP_ERROR,
|
||||
"fsync() failed: %s", strerror(errno));
|
||||
}
|
||||
sys_close(fd);
|
||||
|
||||
/* Figure this out, not happy with returning this string */
|
||||
return filepath;
|
||||
/* Figure this out, not happy with returning this string */
|
||||
return filepath;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -76,8 +76,8 @@ typedef enum {
|
||||
* try a solution in GD2 for this.
|
||||
*/
|
||||
/* typedef int (*option_validation_fn) (glusterd_volinfo_t *volinfo, dict_t
|
||||
*dict, char *key, char *value, char **op_errstr);
|
||||
*/
|
||||
*dict, char *key, char *value, char **op_errstr);
|
||||
*/
|
||||
|
||||
/* Each translator should define this structure */
|
||||
/* XXX: This structure is in use by GD2, and SHOULD NOT be modified.
|
||||
|
@ -36,33 +36,33 @@
|
||||
* : failure: NULL (on failure to compile regex or allocate memory)
|
||||
*/
|
||||
struct parser *
|
||||
parser_init (const char *regex)
|
||||
parser_init(const char *regex)
|
||||
{
|
||||
int rc = 0;
|
||||
struct parser *parser = NULL;
|
||||
int rc = 0;
|
||||
struct parser *parser = NULL;
|
||||
|
||||
parser = GF_MALLOC (sizeof(*parser), gf_common_mt_parser_t);
|
||||
if (!parser)
|
||||
goto out;
|
||||
parser = GF_MALLOC(sizeof(*parser), gf_common_mt_parser_t);
|
||||
if (!parser)
|
||||
goto out;
|
||||
|
||||
parser->regex = gf_strdup (regex);
|
||||
if (!parser->regex) {
|
||||
GF_FREE (parser);
|
||||
parser = NULL;
|
||||
goto out;
|
||||
}
|
||||
parser->regex = gf_strdup(regex);
|
||||
if (!parser->regex) {
|
||||
GF_FREE(parser);
|
||||
parser = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = regcomp (&parser->preg, parser->regex, REG_EXTENDED);
|
||||
if (rc != 0) {
|
||||
gf_msg (GF_PARSE, GF_LOG_INFO, 0, LG_MSG_REGEX_OP_FAILED,
|
||||
"Failed to compile regex pattern.");
|
||||
parser_deinit (parser);
|
||||
parser = NULL;
|
||||
goto out;
|
||||
}
|
||||
parser->complete_str = NULL;
|
||||
rc = regcomp(&parser->preg, parser->regex, REG_EXTENDED);
|
||||
if (rc != 0) {
|
||||
gf_msg(GF_PARSE, GF_LOG_INFO, 0, LG_MSG_REGEX_OP_FAILED,
|
||||
"Failed to compile regex pattern.");
|
||||
parser_deinit(parser);
|
||||
parser = NULL;
|
||||
goto out;
|
||||
}
|
||||
parser->complete_str = NULL;
|
||||
out:
|
||||
return parser;
|
||||
return parser;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -78,22 +78,22 @@ out:
|
||||
* failure: -EINVAL for NULL args, -ENOMEM for allocation errors
|
||||
*/
|
||||
int
|
||||
parser_set_string (struct parser *parser, const char *complete_str)
|
||||
parser_set_string(struct parser *parser, const char *complete_str)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
int ret = -EINVAL;
|
||||
|
||||
GF_VALIDATE_OR_GOTO (GF_PARSE, parser, out);
|
||||
GF_VALIDATE_OR_GOTO (GF_PARSE, complete_str, out);
|
||||
GF_VALIDATE_OR_GOTO(GF_PARSE, parser, out);
|
||||
GF_VALIDATE_OR_GOTO(GF_PARSE, complete_str, out);
|
||||
|
||||
parser->complete_str = gf_strdup (complete_str);
|
||||
GF_CHECK_ALLOC_AND_LOG (GF_PARSE, parser, ret,
|
||||
"Failed to duplicate string!", out);
|
||||
parser->complete_str = gf_strdup(complete_str);
|
||||
GF_CHECK_ALLOC_AND_LOG(GF_PARSE, parser, ret, "Failed to duplicate string!",
|
||||
out);
|
||||
|
||||
/* Point the temp internal string to what we just dup'ed */
|
||||
parser->_rstr = (char *)parser->complete_str;
|
||||
ret = 0;
|
||||
/* Point the temp internal string to what we just dup'ed */
|
||||
parser->_rstr = (char *)parser->complete_str;
|
||||
ret = 0;
|
||||
out:
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -107,17 +107,17 @@ out:
|
||||
* : failure: -EINVAL on NULL args
|
||||
*/
|
||||
int
|
||||
parser_unset_string (struct parser *parser)
|
||||
parser_unset_string(struct parser *parser)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
int ret = -EINVAL;
|
||||
|
||||
GF_VALIDATE_OR_GOTO (GF_PARSE, parser, out);
|
||||
GF_VALIDATE_OR_GOTO(GF_PARSE, parser, out);
|
||||
|
||||
GF_FREE (parser->complete_str);
|
||||
parser->complete_str = NULL; /* Avoid double frees in parser_deinit */
|
||||
ret = 0;
|
||||
GF_FREE(parser->complete_str);
|
||||
parser->complete_str = NULL; /* Avoid double frees in parser_deinit */
|
||||
ret = 0;
|
||||
out:
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -128,15 +128,15 @@ out:
|
||||
* @return : nothing
|
||||
*/
|
||||
void
|
||||
parser_deinit (struct parser *ptr)
|
||||
parser_deinit(struct parser *ptr)
|
||||
{
|
||||
if (!ptr)
|
||||
return;
|
||||
if (!ptr)
|
||||
return;
|
||||
|
||||
regfree (&ptr->preg);
|
||||
GF_FREE (ptr->complete_str);
|
||||
GF_FREE (ptr->regex);
|
||||
GF_FREE (ptr);
|
||||
regfree(&ptr->preg);
|
||||
GF_FREE(ptr->complete_str);
|
||||
GF_FREE(ptr->regex);
|
||||
GF_FREE(ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -149,29 +149,28 @@ parser_deinit (struct parser *ptr)
|
||||
* : failure: NULL
|
||||
*/
|
||||
char *
|
||||
parser_get_next_match (struct parser *parser)
|
||||
parser_get_next_match(struct parser *parser)
|
||||
{
|
||||
int rc = -EINVAL;
|
||||
size_t copy_len = 0;
|
||||
char *match = NULL;
|
||||
int rc = -EINVAL;
|
||||
size_t copy_len = 0;
|
||||
char *match = NULL;
|
||||
|
||||
GF_VALIDATE_OR_GOTO (GF_PARSE, parser, out);
|
||||
GF_VALIDATE_OR_GOTO(GF_PARSE, parser, out);
|
||||
|
||||
rc = regexec (&parser->preg, parser->_rstr, 1, parser->pmatch, 0);
|
||||
if (rc != 0) {
|
||||
gf_msg_debug (GF_PARSE, 0,
|
||||
"Could not match %s with regex %s",
|
||||
parser->_rstr, parser->regex);
|
||||
goto out;
|
||||
}
|
||||
rc = regexec(&parser->preg, parser->_rstr, 1, parser->pmatch, 0);
|
||||
if (rc != 0) {
|
||||
gf_msg_debug(GF_PARSE, 0, "Could not match %s with regex %s",
|
||||
parser->_rstr, parser->regex);
|
||||
goto out;
|
||||
}
|
||||
|
||||
copy_len = parser->pmatch[0].rm_eo - parser->pmatch[0].rm_so;
|
||||
copy_len = parser->pmatch[0].rm_eo - parser->pmatch[0].rm_so;
|
||||
|
||||
match = gf_strndup (parser->_rstr + parser->pmatch[0].rm_so, copy_len);
|
||||
GF_CHECK_ALLOC_AND_LOG (GF_PARSE, match, rc,
|
||||
"Duplicating match failed!", out);
|
||||
match = gf_strndup(parser->_rstr + parser->pmatch[0].rm_so, copy_len);
|
||||
GF_CHECK_ALLOC_AND_LOG(GF_PARSE, match, rc, "Duplicating match failed!",
|
||||
out);
|
||||
|
||||
parser->_rstr = &parser->_rstr[parser->pmatch[0].rm_eo];
|
||||
parser->_rstr = &parser->_rstr[parser->pmatch[0].rm_eo];
|
||||
out:
|
||||
return match;
|
||||
return match;
|
||||
}
|
||||
|
@ -8,7 +8,6 @@
|
||||
cases as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
|
||||
#include "dict.h"
|
||||
#include "logging.h"
|
||||
#include "byte-order.h"
|
||||
@ -17,227 +16,224 @@
|
||||
#include "libglusterfs-messages.h"
|
||||
|
||||
gf_boolean_t
|
||||
quota_meta_is_null (const quota_meta_t *meta)
|
||||
quota_meta_is_null(const quota_meta_t *meta)
|
||||
{
|
||||
if (meta->size == 0 &&
|
||||
meta->file_count == 0 &&
|
||||
meta->dir_count == 0)
|
||||
return _gf_true;
|
||||
if (meta->size == 0 && meta->file_count == 0 && meta->dir_count == 0)
|
||||
return _gf_true;
|
||||
|
||||
return _gf_false;
|
||||
return _gf_false;
|
||||
}
|
||||
|
||||
int32_t
|
||||
quota_data_to_meta (data_t *data, char *key, quota_meta_t *meta)
|
||||
quota_data_to_meta(data_t *data, char *key, quota_meta_t *meta)
|
||||
{
|
||||
int32_t ret = -1;
|
||||
quota_meta_t *value = NULL;
|
||||
int64_t *size = NULL;
|
||||
int32_t ret = -1;
|
||||
quota_meta_t *value = NULL;
|
||||
int64_t *size = NULL;
|
||||
|
||||
if (!data || !key || !meta)
|
||||
goto out;
|
||||
if (!data || !key || !meta)
|
||||
goto out;
|
||||
|
||||
if (data->len > sizeof (int64_t)) {
|
||||
value = (quota_meta_t *) data->data;
|
||||
meta->size = ntoh64 (value->size);
|
||||
meta->file_count = ntoh64 (value->file_count);
|
||||
if (data->len > (sizeof (int64_t)) * 2)
|
||||
meta->dir_count = ntoh64 (value->dir_count);
|
||||
else
|
||||
meta->dir_count = 0;
|
||||
} else {
|
||||
size = (int64_t *) data->data;
|
||||
meta->size = ntoh64 (*size);
|
||||
meta->file_count = 0;
|
||||
meta->dir_count = 0;
|
||||
/* This can happen during software upgrade.
|
||||
* Older version of glusterfs will not have inode count.
|
||||
* Return failure, this will be healed as part of lookup
|
||||
*/
|
||||
gf_msg_callingfn ("quota", GF_LOG_DEBUG, 0,
|
||||
LG_MSG_QUOTA_XATTRS_MISSING, "Object quota "
|
||||
"xattrs missing: len = %d", data->len);
|
||||
ret = -2;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t
|
||||
quota_dict_get_inode_meta (dict_t *dict, char *key, quota_meta_t *meta)
|
||||
{
|
||||
int32_t ret = -1;
|
||||
data_t *data = NULL;
|
||||
|
||||
if (!dict || !key || !meta)
|
||||
goto out;
|
||||
|
||||
data = dict_get (dict, key);
|
||||
if (!data || !data->data)
|
||||
goto out;
|
||||
|
||||
ret = quota_data_to_meta (data, key, meta);
|
||||
|
||||
out:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t
|
||||
quota_dict_get_meta (dict_t *dict, char *key, quota_meta_t *meta)
|
||||
{
|
||||
int32_t ret = -1;
|
||||
|
||||
ret = quota_dict_get_inode_meta (dict, key, meta);
|
||||
if (ret == -2)
|
||||
ret = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t
|
||||
quota_dict_set_meta (dict_t *dict, char *key, const quota_meta_t *meta,
|
||||
ia_type_t ia_type)
|
||||
{
|
||||
int32_t ret = -ENOMEM;
|
||||
quota_meta_t *value = NULL;
|
||||
|
||||
value = GF_MALLOC (sizeof (quota_meta_t), gf_common_quota_meta_t);
|
||||
if (value == NULL) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
value->size = hton64 (meta->size);
|
||||
value->file_count = hton64 (meta->file_count);
|
||||
value->dir_count = hton64 (meta->dir_count);
|
||||
|
||||
if (ia_type == IA_IFDIR) {
|
||||
ret = dict_set_bin (dict, key, value, sizeof (*value));
|
||||
} else {
|
||||
/* For a file we don't need to store dir_count in the
|
||||
* quota size xattr, so we set the len of the data in the dict
|
||||
* as 128bits, so when the posix xattrop reads the dict, it only
|
||||
* performs operations on size and file_count
|
||||
*/
|
||||
ret = dict_set_bin (dict, key, value,
|
||||
sizeof (*value) - sizeof (int64_t));
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
gf_msg_callingfn ("quota", GF_LOG_ERROR, 0,
|
||||
LG_MSG_DICT_SET_FAILED, "dict set failed");
|
||||
GF_FREE (value);
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t
|
||||
quota_conf_read_header (int fd, char *buf)
|
||||
{
|
||||
int ret = 0;
|
||||
const int header_len = SLEN (QUOTA_CONF_HEADER);
|
||||
|
||||
ret = gf_nread (fd, buf, header_len);
|
||||
if (ret <= 0) {
|
||||
goto out;
|
||||
} else if (ret > 0 && ret != header_len) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
buf[header_len-1] = 0;
|
||||
|
||||
out:
|
||||
if (ret < 0)
|
||||
gf_msg_callingfn ("quota", GF_LOG_ERROR, 0,
|
||||
LG_MSG_QUOTA_CONF_ERROR, "failed to read "
|
||||
"header from a quota conf");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t
|
||||
quota_conf_read_version (int fd, float *version)
|
||||
{
|
||||
int ret = 0;
|
||||
char buf[PATH_MAX] = "";
|
||||
char *tail = NULL;
|
||||
float value = 0.0f;
|
||||
|
||||
ret = quota_conf_read_header (fd, buf);
|
||||
if (ret == 0) {
|
||||
/* quota.conf is empty */
|
||||
value = GF_QUOTA_CONF_VERSION;
|
||||
goto out;
|
||||
} else if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
value = strtof ((buf + strlen(buf) - 3), &tail);
|
||||
if (tail[0] != '\0') {
|
||||
ret = -1;
|
||||
gf_msg_callingfn ("quota", GF_LOG_ERROR, 0,
|
||||
LG_MSG_QUOTA_CONF_ERROR, "invalid quota conf"
|
||||
" version");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
if (ret >= 0)
|
||||
*version = value;
|
||||
if (data->len > sizeof(int64_t)) {
|
||||
value = (quota_meta_t *)data->data;
|
||||
meta->size = ntoh64(value->size);
|
||||
meta->file_count = ntoh64(value->file_count);
|
||||
if (data->len > (sizeof(int64_t)) * 2)
|
||||
meta->dir_count = ntoh64(value->dir_count);
|
||||
else
|
||||
gf_msg_callingfn ("quota", GF_LOG_ERROR, 0,
|
||||
LG_MSG_QUOTA_CONF_ERROR, "failed to "
|
||||
"read version from a quota conf header");
|
||||
meta->dir_count = 0;
|
||||
} else {
|
||||
size = (int64_t *)data->data;
|
||||
meta->size = ntoh64(*size);
|
||||
meta->file_count = 0;
|
||||
meta->dir_count = 0;
|
||||
/* This can happen during software upgrade.
|
||||
* Older version of glusterfs will not have inode count.
|
||||
* Return failure, this will be healed as part of lookup
|
||||
*/
|
||||
gf_msg_callingfn("quota", GF_LOG_DEBUG, 0, LG_MSG_QUOTA_XATTRS_MISSING,
|
||||
"Object quota "
|
||||
"xattrs missing: len = %d",
|
||||
data->len);
|
||||
ret = -2;
|
||||
goto out;
|
||||
}
|
||||
|
||||
return ret;
|
||||
ret = 0;
|
||||
out:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t
|
||||
quota_conf_read_gfid (int fd, void *buf, char *type, float version)
|
||||
quota_dict_get_inode_meta(dict_t *dict, char *key, quota_meta_t *meta)
|
||||
{
|
||||
int ret = 0;
|
||||
int32_t ret = -1;
|
||||
data_t *data = NULL;
|
||||
|
||||
ret = gf_nread (fd, buf, 16);
|
||||
if (ret <= 0)
|
||||
goto out;
|
||||
if (!dict || !key || !meta)
|
||||
goto out;
|
||||
|
||||
if (ret != 16) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
data = dict_get(dict, key);
|
||||
if (!data || !data->data)
|
||||
goto out;
|
||||
|
||||
if (version >= 1.2f) {
|
||||
ret = gf_nread (fd, type, 1);
|
||||
if (ret != 1) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
ret = 17;
|
||||
} else {
|
||||
*type = GF_QUOTA_CONF_TYPE_USAGE;
|
||||
}
|
||||
ret = quota_data_to_meta(data, key, meta);
|
||||
|
||||
out:
|
||||
if (ret < 0)
|
||||
gf_msg_callingfn ("quota", GF_LOG_ERROR, 0,
|
||||
LG_MSG_QUOTA_CONF_ERROR, "failed to "
|
||||
"read gfid from a quota conf");
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t
|
||||
quota_conf_skip_header (int fd)
|
||||
quota_dict_get_meta(dict_t *dict, char *key, quota_meta_t *meta)
|
||||
{
|
||||
return gf_skip_header_section (fd, strlen (QUOTA_CONF_HEADER));
|
||||
int32_t ret = -1;
|
||||
|
||||
ret = quota_dict_get_inode_meta(dict, key, meta);
|
||||
if (ret == -2)
|
||||
ret = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t
|
||||
quota_dict_set_meta(dict_t *dict, char *key, const quota_meta_t *meta,
|
||||
ia_type_t ia_type)
|
||||
{
|
||||
int32_t ret = -ENOMEM;
|
||||
quota_meta_t *value = NULL;
|
||||
|
||||
value = GF_MALLOC(sizeof(quota_meta_t), gf_common_quota_meta_t);
|
||||
if (value == NULL) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
value->size = hton64(meta->size);
|
||||
value->file_count = hton64(meta->file_count);
|
||||
value->dir_count = hton64(meta->dir_count);
|
||||
|
||||
if (ia_type == IA_IFDIR) {
|
||||
ret = dict_set_bin(dict, key, value, sizeof(*value));
|
||||
} else {
|
||||
/* For a file we don't need to store dir_count in the
|
||||
* quota size xattr, so we set the len of the data in the dict
|
||||
* as 128bits, so when the posix xattrop reads the dict, it only
|
||||
* performs operations on size and file_count
|
||||
*/
|
||||
ret = dict_set_bin(dict, key, value, sizeof(*value) - sizeof(int64_t));
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
gf_msg_callingfn("quota", GF_LOG_ERROR, 0, LG_MSG_DICT_SET_FAILED,
|
||||
"dict set failed");
|
||||
GF_FREE(value);
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t
|
||||
quota_conf_read_header(int fd, char *buf)
|
||||
{
|
||||
int ret = 0;
|
||||
const int header_len = SLEN(QUOTA_CONF_HEADER);
|
||||
|
||||
ret = gf_nread(fd, buf, header_len);
|
||||
if (ret <= 0) {
|
||||
goto out;
|
||||
} else if (ret > 0 && ret != header_len) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
buf[header_len - 1] = 0;
|
||||
|
||||
out:
|
||||
if (ret < 0)
|
||||
gf_msg_callingfn("quota", GF_LOG_ERROR, 0, LG_MSG_QUOTA_CONF_ERROR,
|
||||
"failed to read "
|
||||
"header from a quota conf");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t
|
||||
quota_conf_read_version(int fd, float *version)
|
||||
{
|
||||
int ret = 0;
|
||||
char buf[PATH_MAX] = "";
|
||||
char *tail = NULL;
|
||||
float value = 0.0f;
|
||||
|
||||
ret = quota_conf_read_header(fd, buf);
|
||||
if (ret == 0) {
|
||||
/* quota.conf is empty */
|
||||
value = GF_QUOTA_CONF_VERSION;
|
||||
goto out;
|
||||
} else if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
value = strtof((buf + strlen(buf) - 3), &tail);
|
||||
if (tail[0] != '\0') {
|
||||
ret = -1;
|
||||
gf_msg_callingfn("quota", GF_LOG_ERROR, 0, LG_MSG_QUOTA_CONF_ERROR,
|
||||
"invalid quota conf"
|
||||
" version");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
if (ret >= 0)
|
||||
*version = value;
|
||||
else
|
||||
gf_msg_callingfn("quota", GF_LOG_ERROR, 0, LG_MSG_QUOTA_CONF_ERROR,
|
||||
"failed to "
|
||||
"read version from a quota conf header");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t
|
||||
quota_conf_read_gfid(int fd, void *buf, char *type, float version)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = gf_nread(fd, buf, 16);
|
||||
if (ret <= 0)
|
||||
goto out;
|
||||
|
||||
if (ret != 16) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (version >= 1.2f) {
|
||||
ret = gf_nread(fd, type, 1);
|
||||
if (ret != 1) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
ret = 17;
|
||||
} else {
|
||||
*type = GF_QUOTA_CONF_TYPE_USAGE;
|
||||
}
|
||||
|
||||
out:
|
||||
if (ret < 0)
|
||||
gf_msg_callingfn("quota", GF_LOG_ERROR, 0, LG_MSG_QUOTA_CONF_ERROR,
|
||||
"failed to "
|
||||
"read gfid from a quota conf");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t
|
||||
quota_conf_skip_header(int fd)
|
||||
{
|
||||
return gf_skip_header_section(fd, strlen(QUOTA_CONF_HEADER));
|
||||
}
|
||||
|
@ -8,7 +8,6 @@
|
||||
cases as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
|
||||
#include "rbthash.h"
|
||||
#include "rb.h"
|
||||
#include "locking.h"
|
||||
@ -19,59 +18,57 @@
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
int
|
||||
rbthash_comparator (void *entry1, void *entry2, void *param)
|
||||
rbthash_comparator(void *entry1, void *entry2, void *param)
|
||||
{
|
||||
int ret = 0;
|
||||
rbthash_entry_t *e1 = NULL;
|
||||
rbthash_entry_t *e2 = NULL;
|
||||
int ret = 0;
|
||||
rbthash_entry_t *e1 = NULL;
|
||||
rbthash_entry_t *e2 = NULL;
|
||||
|
||||
if ((!entry1) || (!entry2) || (!param))
|
||||
return -1;
|
||||
if ((!entry1) || (!entry2) || (!param))
|
||||
return -1;
|
||||
|
||||
e1 = (rbthash_entry_t *)entry1;
|
||||
e2 = (rbthash_entry_t *)entry2;
|
||||
e1 = (rbthash_entry_t *)entry1;
|
||||
e2 = (rbthash_entry_t *)entry2;
|
||||
|
||||
if (e1->keylen != e2->keylen) {
|
||||
if (e1->keylen < e2->keylen)
|
||||
ret = -1;
|
||||
else if (e1->keylen > e2->keylen)
|
||||
ret = 1;
|
||||
} else
|
||||
ret = memcmp (e1->key, e2->key, e1->keylen);
|
||||
if (e1->keylen != e2->keylen) {
|
||||
if (e1->keylen < e2->keylen)
|
||||
ret = -1;
|
||||
else if (e1->keylen > e2->keylen)
|
||||
ret = 1;
|
||||
} else
|
||||
ret = memcmp(e1->key, e2->key, e1->keylen);
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
__rbthash_init_buckets (rbthash_table_t *tbl, int buckets)
|
||||
__rbthash_init_buckets(rbthash_table_t *tbl, int buckets)
|
||||
{
|
||||
int i = 0;
|
||||
int ret = -1;
|
||||
int i = 0;
|
||||
int ret = -1;
|
||||
|
||||
if (!tbl)
|
||||
return -1;
|
||||
if (!tbl)
|
||||
return -1;
|
||||
|
||||
for (; i < buckets; i++) {
|
||||
LOCK_INIT (&tbl->buckets[i].bucketlock);
|
||||
tbl->buckets[i].bucket = rb_create ((rb_comparison_func *)rbthash_comparator, tbl, NULL);
|
||||
if (!tbl->buckets[i].bucket) {
|
||||
gf_msg (GF_RBTHASH, GF_LOG_ERROR, 0,
|
||||
LG_MSG_RB_TABLE_CREATE_FAILED, "Failed to "
|
||||
"create rb table bucket");
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
for (; i < buckets; i++) {
|
||||
LOCK_INIT(&tbl->buckets[i].bucketlock);
|
||||
tbl->buckets[i].bucket = rb_create(
|
||||
(rb_comparison_func *)rbthash_comparator, tbl, NULL);
|
||||
if (!tbl->buckets[i].bucket) {
|
||||
gf_msg(GF_RBTHASH, GF_LOG_ERROR, 0, LG_MSG_RB_TABLE_CREATE_FAILED,
|
||||
"Failed to "
|
||||
"create rb table bucket");
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
ret = 0;
|
||||
err:
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* rbthash_table_init - Initialize a RBT based hash table
|
||||
* @buckets - Number of buckets in the hash table
|
||||
@ -83,391 +80,377 @@ err:
|
||||
*/
|
||||
|
||||
rbthash_table_t *
|
||||
rbthash_table_init (glusterfs_ctx_t *ctx, int buckets, rbt_hasher_t hfunc,
|
||||
rbt_data_destroyer_t dfunc,
|
||||
unsigned long expected_entries,
|
||||
struct mem_pool *entrypool)
|
||||
rbthash_table_init(glusterfs_ctx_t *ctx, int buckets, rbt_hasher_t hfunc,
|
||||
rbt_data_destroyer_t dfunc, unsigned long expected_entries,
|
||||
struct mem_pool *entrypool)
|
||||
{
|
||||
rbthash_table_t *newtab = NULL;
|
||||
int ret = -1;
|
||||
rbthash_table_t *newtab = NULL;
|
||||
int ret = -1;
|
||||
|
||||
if (!hfunc) {
|
||||
gf_msg (GF_RBTHASH, GF_LOG_ERROR, 0, LG_MSG_HASH_FUNC_ERROR,
|
||||
"Hash function not given");
|
||||
return NULL;
|
||||
if (!hfunc) {
|
||||
gf_msg(GF_RBTHASH, GF_LOG_ERROR, 0, LG_MSG_HASH_FUNC_ERROR,
|
||||
"Hash function not given");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!entrypool && !expected_entries) {
|
||||
gf_msg(GF_RBTHASH, GF_LOG_ERROR, 0, LG_MSG_INVALID_ENTRY,
|
||||
"Both mem-pool and expected entries not provided");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (entrypool && expected_entries) {
|
||||
gf_msg(GF_RBTHASH, GF_LOG_ERROR, 0, LG_MSG_INVALID_ENTRY,
|
||||
"Both mem-pool and expected entries are provided");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
newtab = GF_CALLOC(1, sizeof(*newtab), gf_common_mt_rbthash_table_t);
|
||||
if (!newtab)
|
||||
return NULL;
|
||||
|
||||
newtab->buckets = GF_CALLOC(buckets, sizeof(struct rbthash_bucket),
|
||||
gf_common_mt_rbthash_bucket);
|
||||
if (!newtab->buckets) {
|
||||
goto free_newtab;
|
||||
}
|
||||
|
||||
if (expected_entries) {
|
||||
newtab->entrypool = mem_pool_new_ctx(ctx, rbthash_entry_t,
|
||||
expected_entries);
|
||||
if (!newtab->entrypool) {
|
||||
goto free_buckets;
|
||||
}
|
||||
newtab->pool_alloced = _gf_true;
|
||||
} else {
|
||||
newtab->entrypool = entrypool;
|
||||
}
|
||||
|
||||
if (!entrypool && !expected_entries) {
|
||||
gf_msg (GF_RBTHASH, GF_LOG_ERROR, 0, LG_MSG_INVALID_ENTRY,
|
||||
"Both mem-pool and expected entries not provided");
|
||||
return NULL;
|
||||
}
|
||||
LOCK_INIT(&newtab->tablelock);
|
||||
INIT_LIST_HEAD(&newtab->list);
|
||||
newtab->numbuckets = buckets;
|
||||
ret = __rbthash_init_buckets(newtab, buckets);
|
||||
|
||||
if (entrypool && expected_entries) {
|
||||
gf_msg (GF_RBTHASH, GF_LOG_ERROR, 0, LG_MSG_INVALID_ENTRY,
|
||||
"Both mem-pool and expected entries are provided");
|
||||
return NULL;
|
||||
}
|
||||
if (ret == -1) {
|
||||
gf_msg(GF_RBTHASH, GF_LOG_ERROR, 0, LG_MSG_RBTHASH_INIT_BUCKET_FAILED,
|
||||
"Failed to init buckets");
|
||||
if (newtab->pool_alloced)
|
||||
mem_pool_destroy(newtab->entrypool);
|
||||
} else {
|
||||
gf_msg_trace(GF_RBTHASH, 0,
|
||||
"Inited hash table: buckets:"
|
||||
" %d",
|
||||
buckets);
|
||||
}
|
||||
|
||||
|
||||
newtab = GF_CALLOC (1, sizeof (*newtab),
|
||||
gf_common_mt_rbthash_table_t);
|
||||
if (!newtab)
|
||||
return NULL;
|
||||
|
||||
newtab->buckets = GF_CALLOC (buckets, sizeof (struct rbthash_bucket),
|
||||
gf_common_mt_rbthash_bucket);
|
||||
if (!newtab->buckets) {
|
||||
goto free_newtab;
|
||||
}
|
||||
|
||||
if (expected_entries) {
|
||||
newtab->entrypool =
|
||||
mem_pool_new_ctx (ctx, rbthash_entry_t,
|
||||
expected_entries);
|
||||
if (!newtab->entrypool) {
|
||||
goto free_buckets;
|
||||
}
|
||||
newtab->pool_alloced = _gf_true;
|
||||
} else {
|
||||
newtab->entrypool = entrypool;
|
||||
}
|
||||
|
||||
LOCK_INIT (&newtab->tablelock);
|
||||
INIT_LIST_HEAD (&newtab->list);
|
||||
newtab->numbuckets = buckets;
|
||||
ret = __rbthash_init_buckets (newtab, buckets);
|
||||
|
||||
if (ret == -1) {
|
||||
gf_msg (GF_RBTHASH, GF_LOG_ERROR, 0,
|
||||
LG_MSG_RBTHASH_INIT_BUCKET_FAILED,
|
||||
"Failed to init buckets");
|
||||
if (newtab->pool_alloced)
|
||||
mem_pool_destroy (newtab->entrypool);
|
||||
} else {
|
||||
gf_msg_trace (GF_RBTHASH, 0, "Inited hash table: buckets:"
|
||||
" %d", buckets);
|
||||
}
|
||||
|
||||
newtab->hashfunc = hfunc;
|
||||
newtab->dfunc = dfunc;
|
||||
newtab->hashfunc = hfunc;
|
||||
newtab->dfunc = dfunc;
|
||||
|
||||
free_buckets:
|
||||
if (ret == -1)
|
||||
GF_FREE (newtab->buckets);
|
||||
if (ret == -1)
|
||||
GF_FREE(newtab->buckets);
|
||||
|
||||
free_newtab:
|
||||
if (ret == -1) {
|
||||
GF_FREE (newtab);
|
||||
newtab = NULL;
|
||||
}
|
||||
if (ret == -1) {
|
||||
GF_FREE(newtab);
|
||||
newtab = NULL;
|
||||
}
|
||||
|
||||
return newtab;
|
||||
return newtab;
|
||||
}
|
||||
|
||||
rbthash_entry_t *
|
||||
rbthash_init_entry (rbthash_table_t *tbl, void *data, void *key, int keylen)
|
||||
rbthash_init_entry(rbthash_table_t *tbl, void *data, void *key, int keylen)
|
||||
{
|
||||
int ret = -1;
|
||||
rbthash_entry_t *entry = NULL;
|
||||
int ret = -1;
|
||||
rbthash_entry_t *entry = NULL;
|
||||
|
||||
if ((!tbl) || (!data) || (!key))
|
||||
return NULL;
|
||||
if ((!tbl) || (!data) || (!key))
|
||||
return NULL;
|
||||
|
||||
entry = mem_get (tbl->entrypool);
|
||||
if (!entry) {
|
||||
gf_msg (GF_RBTHASH, GF_LOG_ERROR, 0,
|
||||
LG_MSG_RBTHASH_GET_ENTRY_FAILED,
|
||||
"Failed to get entry from mem-pool");
|
||||
goto ret;
|
||||
}
|
||||
entry = mem_get(tbl->entrypool);
|
||||
if (!entry) {
|
||||
gf_msg(GF_RBTHASH, GF_LOG_ERROR, 0, LG_MSG_RBTHASH_GET_ENTRY_FAILED,
|
||||
"Failed to get entry from mem-pool");
|
||||
goto ret;
|
||||
}
|
||||
|
||||
entry->data = data;
|
||||
entry->key = GF_MALLOC (keylen, gf_common_mt_char);
|
||||
if (!entry->key) {
|
||||
goto free_entry;
|
||||
}
|
||||
entry->data = data;
|
||||
entry->key = GF_MALLOC(keylen, gf_common_mt_char);
|
||||
if (!entry->key) {
|
||||
goto free_entry;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD (&entry->list);
|
||||
memcpy (entry->key, key, keylen);
|
||||
entry->keylen = keylen;
|
||||
entry->keyhash = tbl->hashfunc (entry->key, entry->keylen);
|
||||
gf_msg_trace (GF_RBTHASH, 0, "HASH: %u", entry->keyhash);
|
||||
INIT_LIST_HEAD(&entry->list);
|
||||
memcpy(entry->key, key, keylen);
|
||||
entry->keylen = keylen;
|
||||
entry->keyhash = tbl->hashfunc(entry->key, entry->keylen);
|
||||
gf_msg_trace(GF_RBTHASH, 0, "HASH: %u", entry->keyhash);
|
||||
|
||||
ret = 0;
|
||||
ret = 0;
|
||||
free_entry:
|
||||
if (ret == -1) {
|
||||
mem_put (entry);
|
||||
entry = NULL;
|
||||
}
|
||||
if (ret == -1) {
|
||||
mem_put(entry);
|
||||
entry = NULL;
|
||||
}
|
||||
|
||||
ret:
|
||||
return entry;
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
rbthash_deinit_entry (rbthash_table_t *tbl, rbthash_entry_t *entry)
|
||||
rbthash_deinit_entry(rbthash_table_t *tbl, rbthash_entry_t *entry)
|
||||
{
|
||||
|
||||
if (!entry)
|
||||
return;
|
||||
|
||||
GF_FREE (entry->key);
|
||||
|
||||
if (tbl) {
|
||||
if ((entry->data) && (tbl->dfunc))
|
||||
tbl->dfunc (entry->data);
|
||||
|
||||
LOCK (&tbl->tablelock);
|
||||
{
|
||||
list_del_init (&entry->list);
|
||||
}
|
||||
UNLOCK (&tbl->tablelock);
|
||||
|
||||
mem_put (entry);
|
||||
}
|
||||
|
||||
if (!entry)
|
||||
return;
|
||||
}
|
||||
|
||||
GF_FREE(entry->key);
|
||||
|
||||
static struct rbthash_bucket *
|
||||
rbthash_entry_bucket (rbthash_table_t *tbl, rbthash_entry_t * entry)
|
||||
{
|
||||
int nbucket = 0;
|
||||
if (tbl) {
|
||||
if ((entry->data) && (tbl->dfunc))
|
||||
tbl->dfunc(entry->data);
|
||||
|
||||
nbucket = (entry->keyhash % tbl->numbuckets);
|
||||
gf_msg_trace (GF_RBTHASH, 0, "BUCKET: %d", nbucket);
|
||||
return &tbl->buckets[nbucket];
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
rbthash_insert_entry (rbthash_table_t *tbl, rbthash_entry_t *entry)
|
||||
{
|
||||
struct rbthash_bucket *bucket = NULL;
|
||||
int ret = -1;
|
||||
|
||||
if ((!tbl) || (!entry))
|
||||
return -1;
|
||||
|
||||
bucket = rbthash_entry_bucket (tbl, entry);
|
||||
if (!bucket) {
|
||||
gf_msg (GF_RBTHASH, GF_LOG_ERROR, 0,
|
||||
LG_MSG_RBTHASH_GET_BUCKET_FAILED,
|
||||
"Failed to get bucket");
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
LOCK (&bucket->bucketlock);
|
||||
LOCK(&tbl->tablelock);
|
||||
{
|
||||
if (!rb_probe (bucket->bucket, (void *)entry)) {
|
||||
gf_msg (GF_RBTHASH, GF_LOG_ERROR, 0,
|
||||
LG_MSG_RBTHASH_INSERT_FAILED, "Failed to insert"
|
||||
" entry");
|
||||
ret = -1;
|
||||
}
|
||||
list_del_init(&entry->list);
|
||||
}
|
||||
UNLOCK (&bucket->bucketlock);
|
||||
UNLOCK(&tbl->tablelock);
|
||||
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
mem_put(entry);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
rbthash_insert (rbthash_table_t *tbl, void *data, void *key, int keylen)
|
||||
{
|
||||
rbthash_entry_t *entry = NULL;
|
||||
int ret = -1;
|
||||
|
||||
if ((!tbl) || (!data) || (!key))
|
||||
return -1;
|
||||
|
||||
entry = rbthash_init_entry (tbl, data, key, keylen);
|
||||
if (!entry) {
|
||||
gf_msg (GF_RBTHASH, GF_LOG_ERROR, 0,
|
||||
LG_MSG_RBTHASH_INIT_ENTRY_FAILED,
|
||||
"Failed to init entry");
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = rbthash_insert_entry (tbl, entry);
|
||||
|
||||
if (ret == -1) {
|
||||
gf_msg (GF_RBTHASH, GF_LOG_ERROR, 0,
|
||||
LG_MSG_RBTHASH_INSERT_FAILED,
|
||||
"Failed to insert entry");
|
||||
rbthash_deinit_entry (tbl, entry);
|
||||
}
|
||||
|
||||
LOCK (&tbl->tablelock);
|
||||
{
|
||||
list_add_tail (&entry->list, &tbl->list);
|
||||
}
|
||||
UNLOCK (&tbl->tablelock);
|
||||
|
||||
err:
|
||||
return ret;
|
||||
return;
|
||||
}
|
||||
|
||||
static struct rbthash_bucket *
|
||||
rbthash_key_bucket (rbthash_table_t *tbl, void *key, int keylen)
|
||||
rbthash_entry_bucket(rbthash_table_t *tbl, rbthash_entry_t *entry)
|
||||
{
|
||||
uint32_t keyhash = 0;
|
||||
int nbucket = 0;
|
||||
int nbucket = 0;
|
||||
|
||||
if ((!tbl) || (!key))
|
||||
return NULL;
|
||||
|
||||
keyhash = tbl->hashfunc (key, keylen);
|
||||
gf_msg_trace (GF_RBTHASH, 0, "HASH: %u", keyhash);
|
||||
nbucket = (keyhash % tbl->numbuckets);
|
||||
gf_msg_trace (GF_RBTHASH, 0, "BUCKET: %u", nbucket);
|
||||
|
||||
return &tbl->buckets[nbucket];
|
||||
nbucket = (entry->keyhash % tbl->numbuckets);
|
||||
gf_msg_trace(GF_RBTHASH, 0, "BUCKET: %d", nbucket);
|
||||
return &tbl->buckets[nbucket];
|
||||
}
|
||||
|
||||
int
|
||||
rbthash_insert_entry(rbthash_table_t *tbl, rbthash_entry_t *entry)
|
||||
{
|
||||
struct rbthash_bucket *bucket = NULL;
|
||||
int ret = -1;
|
||||
|
||||
if ((!tbl) || (!entry))
|
||||
return -1;
|
||||
|
||||
bucket = rbthash_entry_bucket(tbl, entry);
|
||||
if (!bucket) {
|
||||
gf_msg(GF_RBTHASH, GF_LOG_ERROR, 0, LG_MSG_RBTHASH_GET_BUCKET_FAILED,
|
||||
"Failed to get bucket");
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
LOCK(&bucket->bucketlock);
|
||||
{
|
||||
if (!rb_probe(bucket->bucket, (void *)entry)) {
|
||||
gf_msg(GF_RBTHASH, GF_LOG_ERROR, 0, LG_MSG_RBTHASH_INSERT_FAILED,
|
||||
"Failed to insert"
|
||||
" entry");
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
UNLOCK(&bucket->bucketlock);
|
||||
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
rbthash_insert(rbthash_table_t *tbl, void *data, void *key, int keylen)
|
||||
{
|
||||
rbthash_entry_t *entry = NULL;
|
||||
int ret = -1;
|
||||
|
||||
if ((!tbl) || (!data) || (!key))
|
||||
return -1;
|
||||
|
||||
entry = rbthash_init_entry(tbl, data, key, keylen);
|
||||
if (!entry) {
|
||||
gf_msg(GF_RBTHASH, GF_LOG_ERROR, 0, LG_MSG_RBTHASH_INIT_ENTRY_FAILED,
|
||||
"Failed to init entry");
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = rbthash_insert_entry(tbl, entry);
|
||||
|
||||
if (ret == -1) {
|
||||
gf_msg(GF_RBTHASH, GF_LOG_ERROR, 0, LG_MSG_RBTHASH_INSERT_FAILED,
|
||||
"Failed to insert entry");
|
||||
rbthash_deinit_entry(tbl, entry);
|
||||
}
|
||||
|
||||
LOCK(&tbl->tablelock);
|
||||
{
|
||||
list_add_tail(&entry->list, &tbl->list);
|
||||
}
|
||||
UNLOCK(&tbl->tablelock);
|
||||
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct rbthash_bucket *
|
||||
rbthash_key_bucket(rbthash_table_t *tbl, void *key, int keylen)
|
||||
{
|
||||
uint32_t keyhash = 0;
|
||||
int nbucket = 0;
|
||||
|
||||
if ((!tbl) || (!key))
|
||||
return NULL;
|
||||
|
||||
keyhash = tbl->hashfunc(key, keylen);
|
||||
gf_msg_trace(GF_RBTHASH, 0, "HASH: %u", keyhash);
|
||||
nbucket = (keyhash % tbl->numbuckets);
|
||||
gf_msg_trace(GF_RBTHASH, 0, "BUCKET: %u", nbucket);
|
||||
|
||||
return &tbl->buckets[nbucket];
|
||||
}
|
||||
|
||||
void *
|
||||
rbthash_get (rbthash_table_t *tbl, void *key, int keylen)
|
||||
rbthash_get(rbthash_table_t *tbl, void *key, int keylen)
|
||||
{
|
||||
struct rbthash_bucket *bucket = NULL;
|
||||
rbthash_entry_t *entry = NULL;
|
||||
rbthash_entry_t searchentry = {0, };
|
||||
struct rbthash_bucket *bucket = NULL;
|
||||
rbthash_entry_t *entry = NULL;
|
||||
rbthash_entry_t searchentry = {
|
||||
0,
|
||||
};
|
||||
|
||||
if ((!tbl) || (!key))
|
||||
return NULL;
|
||||
if ((!tbl) || (!key))
|
||||
return NULL;
|
||||
|
||||
bucket = rbthash_key_bucket (tbl, key, keylen);
|
||||
if (!bucket) {
|
||||
gf_msg (GF_RBTHASH, GF_LOG_ERROR, 0, LG_MSG_GET_BUCKET_FAILED,
|
||||
"Failed to get bucket");
|
||||
return NULL;
|
||||
}
|
||||
bucket = rbthash_key_bucket(tbl, key, keylen);
|
||||
if (!bucket) {
|
||||
gf_msg(GF_RBTHASH, GF_LOG_ERROR, 0, LG_MSG_GET_BUCKET_FAILED,
|
||||
"Failed to get bucket");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
searchentry.key = key;
|
||||
searchentry.keylen = keylen;
|
||||
LOCK (&bucket->bucketlock);
|
||||
{
|
||||
entry = rb_find (bucket->bucket, &searchentry);
|
||||
}
|
||||
UNLOCK (&bucket->bucketlock);
|
||||
searchentry.key = key;
|
||||
searchentry.keylen = keylen;
|
||||
LOCK(&bucket->bucketlock);
|
||||
{
|
||||
entry = rb_find(bucket->bucket, &searchentry);
|
||||
}
|
||||
UNLOCK(&bucket->bucketlock);
|
||||
|
||||
if (!entry)
|
||||
return NULL;
|
||||
if (!entry)
|
||||
return NULL;
|
||||
|
||||
return entry->data;
|
||||
return entry->data;
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
rbthash_remove (rbthash_table_t *tbl, void *key, int keylen)
|
||||
rbthash_remove(rbthash_table_t *tbl, void *key, int keylen)
|
||||
{
|
||||
struct rbthash_bucket *bucket = NULL;
|
||||
rbthash_entry_t *entry = NULL;
|
||||
rbthash_entry_t searchentry = {0, };
|
||||
void *dataref = NULL;
|
||||
struct rbthash_bucket *bucket = NULL;
|
||||
rbthash_entry_t *entry = NULL;
|
||||
rbthash_entry_t searchentry = {
|
||||
0,
|
||||
};
|
||||
void *dataref = NULL;
|
||||
|
||||
if ((!tbl) || (!key))
|
||||
return NULL;
|
||||
if ((!tbl) || (!key))
|
||||
return NULL;
|
||||
|
||||
bucket = rbthash_key_bucket (tbl, key, keylen);
|
||||
if (!bucket) {
|
||||
gf_msg (GF_RBTHASH, GF_LOG_ERROR, 0,
|
||||
LG_MSG_RBTHASH_GET_BUCKET_FAILED,
|
||||
"Failed to get bucket");
|
||||
return NULL;
|
||||
}
|
||||
bucket = rbthash_key_bucket(tbl, key, keylen);
|
||||
if (!bucket) {
|
||||
gf_msg(GF_RBTHASH, GF_LOG_ERROR, 0, LG_MSG_RBTHASH_GET_BUCKET_FAILED,
|
||||
"Failed to get bucket");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
searchentry.key = key;
|
||||
searchentry.keylen = keylen;
|
||||
searchentry.key = key;
|
||||
searchentry.keylen = keylen;
|
||||
|
||||
LOCK (&bucket->bucketlock);
|
||||
{
|
||||
entry = rb_delete (bucket->bucket, &searchentry);
|
||||
}
|
||||
UNLOCK (&bucket->bucketlock);
|
||||
LOCK(&bucket->bucketlock);
|
||||
{
|
||||
entry = rb_delete(bucket->bucket, &searchentry);
|
||||
}
|
||||
UNLOCK(&bucket->bucketlock);
|
||||
|
||||
if (!entry)
|
||||
return NULL;
|
||||
if (!entry)
|
||||
return NULL;
|
||||
|
||||
GF_FREE (entry->key);
|
||||
dataref = entry->data;
|
||||
GF_FREE(entry->key);
|
||||
dataref = entry->data;
|
||||
|
||||
LOCK (&tbl->tablelock);
|
||||
{
|
||||
list_del_init (&entry->list);
|
||||
}
|
||||
UNLOCK (&tbl->tablelock);
|
||||
LOCK(&tbl->tablelock);
|
||||
{
|
||||
list_del_init(&entry->list);
|
||||
}
|
||||
UNLOCK(&tbl->tablelock);
|
||||
|
||||
mem_put (entry);
|
||||
mem_put(entry);
|
||||
|
||||
return dataref;
|
||||
return dataref;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
rbthash_entry_deiniter (void *entry, void *rbparam)
|
||||
rbthash_entry_deiniter(void *entry, void *rbparam)
|
||||
{
|
||||
if (!entry)
|
||||
return;
|
||||
|
||||
rbthash_deinit_entry (rbparam, entry);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
rbthash_table_destroy_buckets (rbthash_table_t *tbl)
|
||||
{
|
||||
int x = 0;
|
||||
if (!tbl)
|
||||
return;
|
||||
|
||||
for (;x < tbl->numbuckets; x++) {
|
||||
LOCK_DESTROY (&tbl->buckets[x].bucketlock);
|
||||
rb_destroy (tbl->buckets[x].bucket, rbthash_entry_deiniter);
|
||||
}
|
||||
|
||||
if (!entry)
|
||||
return;
|
||||
|
||||
rbthash_deinit_entry(rbparam, entry);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
rbthash_table_destroy (rbthash_table_t *tbl)
|
||||
rbthash_table_destroy_buckets(rbthash_table_t *tbl)
|
||||
{
|
||||
if (!tbl)
|
||||
return;
|
||||
int x = 0;
|
||||
if (!tbl)
|
||||
return;
|
||||
|
||||
rbthash_table_destroy_buckets (tbl);
|
||||
if (tbl->pool_alloced)
|
||||
mem_pool_destroy (tbl->entrypool);
|
||||
for (; x < tbl->numbuckets; x++) {
|
||||
LOCK_DESTROY(&tbl->buckets[x].bucketlock);
|
||||
rb_destroy(tbl->buckets[x].bucket, rbthash_entry_deiniter);
|
||||
}
|
||||
|
||||
GF_FREE (tbl->buckets);
|
||||
GF_FREE (tbl);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
rbthash_table_destroy(rbthash_table_t *tbl)
|
||||
{
|
||||
if (!tbl)
|
||||
return;
|
||||
|
||||
rbthash_table_destroy_buckets(tbl);
|
||||
if (tbl->pool_alloced)
|
||||
mem_pool_destroy(tbl->entrypool);
|
||||
|
||||
GF_FREE(tbl->buckets);
|
||||
GF_FREE(tbl);
|
||||
}
|
||||
|
||||
void
|
||||
rbthash_table_traverse (rbthash_table_t *tbl, rbt_traverse_t traverse,
|
||||
void *mydata)
|
||||
rbthash_table_traverse(rbthash_table_t *tbl, rbt_traverse_t traverse,
|
||||
void *mydata)
|
||||
{
|
||||
rbthash_entry_t *entry = NULL;
|
||||
rbthash_entry_t *entry = NULL;
|
||||
|
||||
if ((tbl == NULL) || (traverse == NULL)) {
|
||||
goto out;
|
||||
}
|
||||
if ((tbl == NULL) || (traverse == NULL)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
LOCK (&tbl->tablelock);
|
||||
LOCK(&tbl->tablelock);
|
||||
{
|
||||
list_for_each_entry(entry, &tbl->list, list)
|
||||
{
|
||||
list_for_each_entry (entry, &tbl->list, list) {
|
||||
traverse (entry->data, mydata);
|
||||
}
|
||||
traverse(entry->data, mydata);
|
||||
}
|
||||
UNLOCK (&tbl->tablelock);
|
||||
}
|
||||
UNLOCK(&tbl->tablelock);
|
||||
|
||||
out:
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
@ -14,96 +14,95 @@
|
||||
#ifndef REFCOUNT_NEEDS_LOCK
|
||||
|
||||
void *
|
||||
_gf_ref_get (gf_ref_t *ref)
|
||||
_gf_ref_get(gf_ref_t *ref)
|
||||
{
|
||||
unsigned int cnt = __sync_fetch_and_add (&ref->cnt, 1);
|
||||
unsigned int cnt = __sync_fetch_and_add(&ref->cnt, 1);
|
||||
|
||||
/* if cnt == 0, we're in a fatal position, the object will be free'd
|
||||
*
|
||||
* There is a race when two threads do a _gf_ref_get(). Only one of
|
||||
* them may get a 0 returned. That is acceptable, because one
|
||||
* _gf_ref_get() returning 0 should be handled as a fatal problem and
|
||||
* when correct usage/locking is used, it should never happen.
|
||||
*/
|
||||
GF_ASSERT (cnt != 0);
|
||||
/* if cnt == 0, we're in a fatal position, the object will be free'd
|
||||
*
|
||||
* There is a race when two threads do a _gf_ref_get(). Only one of
|
||||
* them may get a 0 returned. That is acceptable, because one
|
||||
* _gf_ref_get() returning 0 should be handled as a fatal problem and
|
||||
* when correct usage/locking is used, it should never happen.
|
||||
*/
|
||||
GF_ASSERT(cnt != 0);
|
||||
|
||||
return cnt ? ref->data : NULL;
|
||||
return cnt ? ref->data : NULL;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
_gf_ref_put (gf_ref_t *ref)
|
||||
_gf_ref_put(gf_ref_t *ref)
|
||||
{
|
||||
unsigned int cnt = __sync_fetch_and_sub (&ref->cnt, 1);
|
||||
unsigned int cnt = __sync_fetch_and_sub(&ref->cnt, 1);
|
||||
|
||||
/* if cnt == 1, the last user just did a _gf_ref_put()
|
||||
*
|
||||
* When cnt == 0, one _gf_ref_put() was done too much and there has
|
||||
* been a thread using the refcounted structure when it was not
|
||||
* supposed to.
|
||||
*/
|
||||
GF_ASSERT (cnt != 0);
|
||||
/* if cnt == 1, the last user just did a _gf_ref_put()
|
||||
*
|
||||
* When cnt == 0, one _gf_ref_put() was done too much and there has
|
||||
* been a thread using the refcounted structure when it was not
|
||||
* supposed to.
|
||||
*/
|
||||
GF_ASSERT(cnt != 0);
|
||||
|
||||
if (cnt == 1 && ref->release)
|
||||
ref->release (ref->data);
|
||||
if (cnt == 1 && ref->release)
|
||||
ref->release(ref->data);
|
||||
|
||||
return (cnt != 1);
|
||||
return (cnt != 1);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void *
|
||||
_gf_ref_get (gf_ref_t *ref)
|
||||
_gf_ref_get(gf_ref_t *ref)
|
||||
{
|
||||
unsigned int cnt = 0;
|
||||
unsigned int cnt = 0;
|
||||
|
||||
LOCK (&ref->lk);
|
||||
{
|
||||
/* never can be 0, should have been free'd */
|
||||
if (ref->cnt > 0)
|
||||
cnt = ++ref->cnt;
|
||||
else
|
||||
GF_ASSERT (ref->cnt > 0);
|
||||
}
|
||||
UNLOCK (&ref->lk);
|
||||
LOCK(&ref->lk);
|
||||
{
|
||||
/* never can be 0, should have been free'd */
|
||||
if (ref->cnt > 0)
|
||||
cnt = ++ref->cnt;
|
||||
else
|
||||
GF_ASSERT(ref->cnt > 0);
|
||||
}
|
||||
UNLOCK(&ref->lk);
|
||||
|
||||
return cnt ? ref->data : NULL;
|
||||
return cnt ? ref->data : NULL;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
_gf_ref_put (gf_ref_t *ref)
|
||||
_gf_ref_put(gf_ref_t *ref)
|
||||
{
|
||||
unsigned int cnt = 0;
|
||||
int release = 0;
|
||||
unsigned int cnt = 0;
|
||||
int release = 0;
|
||||
|
||||
LOCK (&ref->lk);
|
||||
{
|
||||
if (ref->cnt != 0) {
|
||||
cnt = --ref->cnt;
|
||||
/* call release() only when cnt == 0 */
|
||||
release = (cnt == 0);
|
||||
} else
|
||||
GF_ASSERT (ref->cnt != 0);
|
||||
}
|
||||
UNLOCK (&ref->lk);
|
||||
LOCK(&ref->lk);
|
||||
{
|
||||
if (ref->cnt != 0) {
|
||||
cnt = --ref->cnt;
|
||||
/* call release() only when cnt == 0 */
|
||||
release = (cnt == 0);
|
||||
} else
|
||||
GF_ASSERT(ref->cnt != 0);
|
||||
}
|
||||
UNLOCK(&ref->lk);
|
||||
|
||||
if (release && ref->release)
|
||||
ref->release (ref->data);
|
||||
if (release && ref->release)
|
||||
ref->release(ref->data);
|
||||
|
||||
return !release;
|
||||
return !release;
|
||||
}
|
||||
|
||||
#endif /* REFCOUNT_NEEDS_LOCK */
|
||||
|
||||
|
||||
void
|
||||
_gf_ref_init (gf_ref_t *ref, gf_ref_release_t release, void *data)
|
||||
_gf_ref_init(gf_ref_t *ref, gf_ref_release_t release, void *data)
|
||||
{
|
||||
GF_ASSERT (ref);
|
||||
GF_ASSERT(ref);
|
||||
|
||||
#ifdef REFCOUNT_NEEDS_LOCK
|
||||
LOCK_INIT (&ref->lk);
|
||||
LOCK_INIT(&ref->lk);
|
||||
#endif
|
||||
ref->cnt = 1;
|
||||
ref->release = release;
|
||||
ref->data = data;
|
||||
ref->cnt = 1;
|
||||
ref->release = release;
|
||||
ref->data = data;
|
||||
}
|
||||
|
@ -26,10 +26,10 @@
|
||||
* TODO: do away with opaques (use arrays with indexing).
|
||||
*/
|
||||
|
||||
#define ROT_BUFF_DEFAULT_COUNT 2
|
||||
#define ROT_BUFF_ALLOC_SIZE (1 * 1024 * 1024) /* 1MB per iovec */
|
||||
#define ROT_BUFF_DEFAULT_COUNT 2
|
||||
#define ROT_BUFF_ALLOC_SIZE (1 * 1024 * 1024) /* 1MB per iovec */
|
||||
|
||||
#define RLIST_IOV_MELDED_ALLOC_SIZE (RBUF_IOVEC_SIZE + ROT_BUFF_ALLOC_SIZE)
|
||||
#define RLIST_IOV_MELDED_ALLOC_SIZE (RBUF_IOVEC_SIZE + ROT_BUFF_ALLOC_SIZE)
|
||||
|
||||
/**
|
||||
* iovec list is not shrunk (deallocated) if usage/total count
|
||||
@ -37,373 +37,369 @@
|
||||
* most of the workloads. for the rest shrinking iovec list is
|
||||
* generous.
|
||||
*/
|
||||
#define RVEC_LOW_WATERMARK_COUNT 1
|
||||
#define RVEC_LOW_WATERMARK_COUNT 1
|
||||
#define RVEC_HIGH_WATERMARK_COUNT (1 << 4)
|
||||
|
||||
static inline
|
||||
rbuf_list_t *rbuf_current_buffer (rbuf_t *rbuf)
|
||||
static inline rbuf_list_t *
|
||||
rbuf_current_buffer(rbuf_t *rbuf)
|
||||
{
|
||||
return rbuf->current;
|
||||
return rbuf->current;
|
||||
}
|
||||
|
||||
static void
|
||||
rlist_mark_waiting (rbuf_list_t *rlist)
|
||||
rlist_mark_waiting(rbuf_list_t *rlist)
|
||||
{
|
||||
LOCK (&rlist->c_lock);
|
||||
{
|
||||
rlist->awaiting = _gf_true;
|
||||
}
|
||||
UNLOCK (&rlist->c_lock);
|
||||
LOCK(&rlist->c_lock);
|
||||
{
|
||||
rlist->awaiting = _gf_true;
|
||||
}
|
||||
UNLOCK(&rlist->c_lock);
|
||||
}
|
||||
|
||||
static int
|
||||
__rlist_has_waiter (rbuf_list_t *rlist)
|
||||
__rlist_has_waiter(rbuf_list_t *rlist)
|
||||
{
|
||||
return (rlist->awaiting == _gf_true);
|
||||
return (rlist->awaiting == _gf_true);
|
||||
}
|
||||
|
||||
static void *
|
||||
rbuf_alloc_rvec ()
|
||||
rbuf_alloc_rvec()
|
||||
{
|
||||
return GF_CALLOC (1, RLIST_IOV_MELDED_ALLOC_SIZE, gf_common_mt_rvec_t);
|
||||
return GF_CALLOC(1, RLIST_IOV_MELDED_ALLOC_SIZE, gf_common_mt_rvec_t);
|
||||
}
|
||||
|
||||
static void
|
||||
rlist_reset_vector_usage (rbuf_list_t *rlist)
|
||||
rlist_reset_vector_usage(rbuf_list_t *rlist)
|
||||
{
|
||||
rlist->used = 1;
|
||||
rlist->used = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
rlist_increment_vector_usage (rbuf_list_t *rlist)
|
||||
rlist_increment_vector_usage(rbuf_list_t *rlist)
|
||||
{
|
||||
rlist->used++;
|
||||
rlist->used++;
|
||||
}
|
||||
|
||||
static void
|
||||
rlist_increment_total_usage (rbuf_list_t *rlist)
|
||||
rlist_increment_total_usage(rbuf_list_t *rlist)
|
||||
{
|
||||
rlist->total++;
|
||||
rlist->total++;
|
||||
}
|
||||
|
||||
static int
|
||||
rvec_in_watermark_range (rbuf_list_t *rlist)
|
||||
rvec_in_watermark_range(rbuf_list_t *rlist)
|
||||
{
|
||||
return ((rlist->total >= RVEC_LOW_WATERMARK_COUNT)
|
||||
&& (rlist->total <= RVEC_HIGH_WATERMARK_COUNT));
|
||||
return ((rlist->total >= RVEC_LOW_WATERMARK_COUNT) &&
|
||||
(rlist->total <= RVEC_HIGH_WATERMARK_COUNT));
|
||||
}
|
||||
|
||||
static void
|
||||
rbuf_reset_rvec (rbuf_iovec_t *rvec)
|
||||
rbuf_reset_rvec(rbuf_iovec_t *rvec)
|
||||
{
|
||||
/* iov_base is _never_ modified */
|
||||
rvec->iov.iov_len = 0;
|
||||
/* iov_base is _never_ modified */
|
||||
rvec->iov.iov_len = 0;
|
||||
}
|
||||
|
||||
/* TODO: alloc multiple rbuf_iovec_t */
|
||||
static int
|
||||
rlist_add_new_vec (rbuf_list_t *rlist)
|
||||
rlist_add_new_vec(rbuf_list_t *rlist)
|
||||
{
|
||||
rbuf_iovec_t *rvec = NULL;
|
||||
rbuf_iovec_t *rvec = NULL;
|
||||
|
||||
rvec = (rbuf_iovec_t *) rbuf_alloc_rvec ();
|
||||
if (!rvec)
|
||||
return -1;
|
||||
INIT_LIST_HEAD (&rvec->list);
|
||||
rvec->iov.iov_base = ((char *)rvec) + RBUF_IOVEC_SIZE;
|
||||
rvec->iov.iov_len = 0;
|
||||
rvec = (rbuf_iovec_t *)rbuf_alloc_rvec();
|
||||
if (!rvec)
|
||||
return -1;
|
||||
INIT_LIST_HEAD(&rvec->list);
|
||||
rvec->iov.iov_base = ((char *)rvec) + RBUF_IOVEC_SIZE;
|
||||
rvec->iov.iov_len = 0;
|
||||
|
||||
list_add_tail (&rvec->list, &rlist->veclist);
|
||||
list_add_tail(&rvec->list, &rlist->veclist);
|
||||
|
||||
rlist->rvec = rvec; /* cache the latest */
|
||||
rlist->rvec = rvec; /* cache the latest */
|
||||
|
||||
rlist_increment_vector_usage (rlist);
|
||||
rlist_increment_total_usage (rlist);
|
||||
rlist_increment_vector_usage(rlist);
|
||||
rlist_increment_total_usage(rlist);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
rlist_free_rvec (rbuf_iovec_t *rvec)
|
||||
rlist_free_rvec(rbuf_iovec_t *rvec)
|
||||
{
|
||||
if (!rvec)
|
||||
return;
|
||||
list_del (&rvec->list);
|
||||
GF_FREE (rvec);
|
||||
if (!rvec)
|
||||
return;
|
||||
list_del(&rvec->list);
|
||||
GF_FREE(rvec);
|
||||
}
|
||||
|
||||
static void
|
||||
rlist_purge_all_rvec (rbuf_list_t *rlist)
|
||||
rlist_purge_all_rvec(rbuf_list_t *rlist)
|
||||
{
|
||||
rbuf_iovec_t *rvec = NULL;
|
||||
rbuf_iovec_t *rvec = NULL;
|
||||
|
||||
if (!rlist)
|
||||
return;
|
||||
while (!list_empty (&rlist->veclist)) {
|
||||
rvec = list_first_entry (&rlist->veclist, rbuf_iovec_t, list);
|
||||
rlist_free_rvec (rvec);
|
||||
}
|
||||
if (!rlist)
|
||||
return;
|
||||
while (!list_empty(&rlist->veclist)) {
|
||||
rvec = list_first_entry(&rlist->veclist, rbuf_iovec_t, list);
|
||||
rlist_free_rvec(rvec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
rlist_shrink_rvec (rbuf_list_t *rlist, unsigned long long shrink)
|
||||
rlist_shrink_rvec(rbuf_list_t *rlist, unsigned long long shrink)
|
||||
{
|
||||
rbuf_iovec_t *rvec = NULL;
|
||||
rbuf_iovec_t *rvec = NULL;
|
||||
|
||||
while (!list_empty (&rlist->veclist) && (shrink-- > 0)) {
|
||||
rvec = list_first_entry (&rlist->veclist, rbuf_iovec_t, list);
|
||||
rlist_free_rvec (rvec);
|
||||
}
|
||||
while (!list_empty(&rlist->veclist) && (shrink-- > 0)) {
|
||||
rvec = list_first_entry(&rlist->veclist, rbuf_iovec_t, list);
|
||||
rlist_free_rvec(rvec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
rbuf_purge_rlist (rbuf_t *rbuf)
|
||||
rbuf_purge_rlist(rbuf_t *rbuf)
|
||||
{
|
||||
rbuf_list_t *rlist = NULL;
|
||||
rbuf_list_t *rlist = NULL;
|
||||
|
||||
while (!list_empty (&rbuf->freelist)) {
|
||||
rlist = list_first_entry (&rbuf->freelist, rbuf_list_t, list);
|
||||
list_del (&rlist->list);
|
||||
while (!list_empty(&rbuf->freelist)) {
|
||||
rlist = list_first_entry(&rbuf->freelist, rbuf_list_t, list);
|
||||
list_del(&rlist->list);
|
||||
|
||||
rlist_purge_all_rvec (rlist);
|
||||
rlist_purge_all_rvec(rlist);
|
||||
|
||||
LOCK_DESTROY (&rlist->c_lock);
|
||||
LOCK_DESTROY(&rlist->c_lock);
|
||||
|
||||
(void) pthread_mutex_destroy (&rlist->b_lock);
|
||||
(void) pthread_cond_destroy (&rlist->b_cond);
|
||||
(void)pthread_mutex_destroy(&rlist->b_lock);
|
||||
(void)pthread_cond_destroy(&rlist->b_cond);
|
||||
|
||||
GF_FREE (rlist);
|
||||
}
|
||||
GF_FREE(rlist);
|
||||
}
|
||||
}
|
||||
|
||||
rbuf_t *
|
||||
rbuf_init (int bufcount)
|
||||
rbuf_init(int bufcount)
|
||||
{
|
||||
int j = 0;
|
||||
int ret = 0;
|
||||
rbuf_t *rbuf = NULL;
|
||||
rbuf_list_t *rlist = NULL;
|
||||
int j = 0;
|
||||
int ret = 0;
|
||||
rbuf_t *rbuf = NULL;
|
||||
rbuf_list_t *rlist = NULL;
|
||||
|
||||
if (bufcount <= 0)
|
||||
bufcount = ROT_BUFF_DEFAULT_COUNT;
|
||||
if (bufcount <= 0)
|
||||
bufcount = ROT_BUFF_DEFAULT_COUNT;
|
||||
|
||||
rbuf = GF_CALLOC (1, sizeof (rbuf_t), gf_common_mt_rbuf_t);
|
||||
if (!rbuf)
|
||||
goto error_return;
|
||||
rbuf = GF_CALLOC(1, sizeof(rbuf_t), gf_common_mt_rbuf_t);
|
||||
if (!rbuf)
|
||||
goto error_return;
|
||||
|
||||
LOCK_INIT (&rbuf->lock);
|
||||
INIT_LIST_HEAD (&rbuf->freelist);
|
||||
LOCK_INIT(&rbuf->lock);
|
||||
INIT_LIST_HEAD(&rbuf->freelist);
|
||||
|
||||
/* it could have been one big calloc() but this is just once.. */
|
||||
for (j = 0; j < bufcount; j++) {
|
||||
rlist = GF_CALLOC (1,
|
||||
sizeof (rbuf_list_t), gf_common_mt_rlist_t);
|
||||
if (!rlist) {
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD (&rlist->list);
|
||||
INIT_LIST_HEAD (&rlist->veclist);
|
||||
|
||||
rlist->pending = rlist->completed = 0;
|
||||
|
||||
ret = rlist_add_new_vec (rlist);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
LOCK_INIT (&rlist->c_lock);
|
||||
|
||||
rlist->awaiting = _gf_false;
|
||||
ret = pthread_mutex_init (&rlist->b_lock, 0);
|
||||
if (ret != 0) {
|
||||
GF_FREE (rlist);
|
||||
break;
|
||||
}
|
||||
|
||||
ret = pthread_cond_init (&rlist->b_cond, 0);
|
||||
if (ret != 0) {
|
||||
GF_FREE (rlist);
|
||||
break;
|
||||
}
|
||||
|
||||
list_add_tail (&rlist->list, &rbuf->freelist);
|
||||
/* it could have been one big calloc() but this is just once.. */
|
||||
for (j = 0; j < bufcount; j++) {
|
||||
rlist = GF_CALLOC(1, sizeof(rbuf_list_t), gf_common_mt_rlist_t);
|
||||
if (!rlist) {
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret != 0)
|
||||
goto dealloc_rlist;
|
||||
INIT_LIST_HEAD(&rlist->list);
|
||||
INIT_LIST_HEAD(&rlist->veclist);
|
||||
|
||||
/* cache currently used buffer: first in the list */
|
||||
rbuf->current = list_first_entry (&rbuf->freelist, rbuf_list_t, list);
|
||||
return rbuf;
|
||||
rlist->pending = rlist->completed = 0;
|
||||
|
||||
dealloc_rlist:
|
||||
rbuf_purge_rlist (rbuf);
|
||||
LOCK_DESTROY (&rbuf->lock);
|
||||
GF_FREE (rbuf);
|
||||
error_return:
|
||||
return NULL;
|
||||
ret = rlist_add_new_vec(rlist);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
LOCK_INIT(&rlist->c_lock);
|
||||
|
||||
rlist->awaiting = _gf_false;
|
||||
ret = pthread_mutex_init(&rlist->b_lock, 0);
|
||||
if (ret != 0) {
|
||||
GF_FREE(rlist);
|
||||
break;
|
||||
}
|
||||
|
||||
ret = pthread_cond_init(&rlist->b_cond, 0);
|
||||
if (ret != 0) {
|
||||
GF_FREE(rlist);
|
||||
break;
|
||||
}
|
||||
|
||||
list_add_tail(&rlist->list, &rbuf->freelist);
|
||||
}
|
||||
|
||||
if (ret != 0)
|
||||
goto dealloc_rlist;
|
||||
|
||||
/* cache currently used buffer: first in the list */
|
||||
rbuf->current = list_first_entry(&rbuf->freelist, rbuf_list_t, list);
|
||||
return rbuf;
|
||||
|
||||
dealloc_rlist:
|
||||
rbuf_purge_rlist(rbuf);
|
||||
LOCK_DESTROY(&rbuf->lock);
|
||||
GF_FREE(rbuf);
|
||||
error_return:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
rbuf_dtor (rbuf_t *rbuf)
|
||||
rbuf_dtor(rbuf_t *rbuf)
|
||||
{
|
||||
if (!rbuf)
|
||||
return;
|
||||
rbuf->current = NULL;
|
||||
rbuf_purge_rlist (rbuf);
|
||||
LOCK_DESTROY (&rbuf->lock);
|
||||
if (!rbuf)
|
||||
return;
|
||||
rbuf->current = NULL;
|
||||
rbuf_purge_rlist(rbuf);
|
||||
LOCK_DESTROY(&rbuf->lock);
|
||||
|
||||
GF_FREE (rbuf);
|
||||
GF_FREE(rbuf);
|
||||
}
|
||||
|
||||
static char *
|
||||
rbuf_adjust_write_area (struct iovec *iov, size_t bytes)
|
||||
rbuf_adjust_write_area(struct iovec *iov, size_t bytes)
|
||||
{
|
||||
char *wbuf = NULL;
|
||||
char *wbuf = NULL;
|
||||
|
||||
wbuf = iov->iov_base + iov->iov_len;
|
||||
iov->iov_len += bytes;
|
||||
return wbuf;
|
||||
wbuf = iov->iov_base + iov->iov_len;
|
||||
iov->iov_len += bytes;
|
||||
return wbuf;
|
||||
}
|
||||
|
||||
static char *
|
||||
rbuf_alloc_write_area (rbuf_list_t *rlist, size_t bytes)
|
||||
rbuf_alloc_write_area(rbuf_list_t *rlist, size_t bytes)
|
||||
{
|
||||
int ret = 0;
|
||||
struct iovec *iov = NULL;
|
||||
int ret = 0;
|
||||
struct iovec *iov = NULL;
|
||||
|
||||
/* check for available space in _current_ IO buffer */
|
||||
iov = &rlist->rvec->iov;
|
||||
if (iov->iov_len + bytes <= ROT_BUFF_ALLOC_SIZE)
|
||||
return rbuf_adjust_write_area (iov, bytes); /* fast path */
|
||||
/* check for available space in _current_ IO buffer */
|
||||
iov = &rlist->rvec->iov;
|
||||
if (iov->iov_len + bytes <= ROT_BUFF_ALLOC_SIZE)
|
||||
return rbuf_adjust_write_area(iov, bytes); /* fast path */
|
||||
|
||||
/* not enough bytes, try next available buffers */
|
||||
if (list_is_last (&rlist->rvec->list, &rlist->veclist)) {
|
||||
/* OH! consumed all vector buffers */
|
||||
GF_ASSERT (rlist->used == rlist->total);
|
||||
ret = rlist_add_new_vec (rlist);
|
||||
if (ret)
|
||||
goto error_return;
|
||||
} else {
|
||||
/* not the end, have available rbuf_iovec's */
|
||||
rlist->rvec = list_next_entry (rlist->rvec, list);
|
||||
rlist->used++;
|
||||
rbuf_reset_rvec (rlist->rvec);
|
||||
}
|
||||
/* not enough bytes, try next available buffers */
|
||||
if (list_is_last(&rlist->rvec->list, &rlist->veclist)) {
|
||||
/* OH! consumed all vector buffers */
|
||||
GF_ASSERT(rlist->used == rlist->total);
|
||||
ret = rlist_add_new_vec(rlist);
|
||||
if (ret)
|
||||
goto error_return;
|
||||
} else {
|
||||
/* not the end, have available rbuf_iovec's */
|
||||
rlist->rvec = list_next_entry(rlist->rvec, list);
|
||||
rlist->used++;
|
||||
rbuf_reset_rvec(rlist->rvec);
|
||||
}
|
||||
|
||||
iov = &rlist->rvec->iov;
|
||||
return rbuf_adjust_write_area (iov, bytes);
|
||||
iov = &rlist->rvec->iov;
|
||||
return rbuf_adjust_write_area(iov, bytes);
|
||||
|
||||
error_return:
|
||||
return NULL;
|
||||
error_return:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *
|
||||
rbuf_reserve_write_area (rbuf_t *rbuf, size_t bytes, void **opaque)
|
||||
rbuf_reserve_write_area(rbuf_t *rbuf, size_t bytes, void **opaque)
|
||||
{
|
||||
char *wbuf = NULL;
|
||||
rbuf_list_t *rlist = NULL;
|
||||
char *wbuf = NULL;
|
||||
rbuf_list_t *rlist = NULL;
|
||||
|
||||
if (!rbuf || (bytes <= 0) || (bytes > ROT_BUFF_ALLOC_SIZE) || !opaque)
|
||||
return NULL;
|
||||
if (!rbuf || (bytes <= 0) || (bytes > ROT_BUFF_ALLOC_SIZE) || !opaque)
|
||||
return NULL;
|
||||
|
||||
LOCK (&rbuf->lock);
|
||||
{
|
||||
rlist = rbuf_current_buffer (rbuf);
|
||||
wbuf = rbuf_alloc_write_area (rlist, bytes);
|
||||
if (!wbuf)
|
||||
goto unblock;
|
||||
rlist->pending++;
|
||||
}
|
||||
unblock:
|
||||
UNLOCK (&rbuf->lock);
|
||||
LOCK(&rbuf->lock);
|
||||
{
|
||||
rlist = rbuf_current_buffer(rbuf);
|
||||
wbuf = rbuf_alloc_write_area(rlist, bytes);
|
||||
if (!wbuf)
|
||||
goto unblock;
|
||||
rlist->pending++;
|
||||
}
|
||||
unblock:
|
||||
UNLOCK(&rbuf->lock);
|
||||
|
||||
if (wbuf)
|
||||
*opaque = rlist;
|
||||
return wbuf;
|
||||
if (wbuf)
|
||||
*opaque = rlist;
|
||||
return wbuf;
|
||||
}
|
||||
|
||||
static void
|
||||
rbuf_notify_waiter (rbuf_list_t *rlist)
|
||||
rbuf_notify_waiter(rbuf_list_t *rlist)
|
||||
{
|
||||
pthread_mutex_lock (&rlist->b_lock);
|
||||
{
|
||||
pthread_cond_signal (&rlist->b_cond);
|
||||
}
|
||||
pthread_mutex_unlock (&rlist->b_lock);
|
||||
pthread_mutex_lock(&rlist->b_lock);
|
||||
{
|
||||
pthread_cond_signal(&rlist->b_cond);
|
||||
}
|
||||
pthread_mutex_unlock(&rlist->b_lock);
|
||||
}
|
||||
|
||||
int
|
||||
rbuf_write_complete (void *opaque)
|
||||
rbuf_write_complete(void *opaque)
|
||||
{
|
||||
rbuf_list_t *rlist = NULL;
|
||||
gf_boolean_t notify = _gf_false;
|
||||
rbuf_list_t *rlist = NULL;
|
||||
gf_boolean_t notify = _gf_false;
|
||||
|
||||
if (!opaque)
|
||||
return -1;
|
||||
if (!opaque)
|
||||
return -1;
|
||||
|
||||
rlist = opaque;
|
||||
rlist = opaque;
|
||||
|
||||
LOCK (&rlist->c_lock);
|
||||
{
|
||||
rlist->completed++;
|
||||
/**
|
||||
* it's safe to test ->pending without rbuf->lock *only* if
|
||||
* there's a waiter as there can be no new incoming writes.
|
||||
*/
|
||||
if (__rlist_has_waiter (rlist)
|
||||
&& (rlist->completed == rlist->pending))
|
||||
notify = _gf_true;
|
||||
}
|
||||
UNLOCK (&rlist->c_lock);
|
||||
LOCK(&rlist->c_lock);
|
||||
{
|
||||
rlist->completed++;
|
||||
/**
|
||||
* it's safe to test ->pending without rbuf->lock *only* if
|
||||
* there's a waiter as there can be no new incoming writes.
|
||||
*/
|
||||
if (__rlist_has_waiter(rlist) && (rlist->completed == rlist->pending))
|
||||
notify = _gf_true;
|
||||
}
|
||||
UNLOCK(&rlist->c_lock);
|
||||
|
||||
if (notify)
|
||||
rbuf_notify_waiter (rlist);
|
||||
if (notify)
|
||||
rbuf_notify_waiter(rlist);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
rbuf_get_buffer (rbuf_t *rbuf,
|
||||
void **opaque, sequence_fn *seqfn, void *mydata)
|
||||
rbuf_get_buffer(rbuf_t *rbuf, void **opaque, sequence_fn *seqfn, void *mydata)
|
||||
{
|
||||
int retval = RBUF_CONSUMABLE;
|
||||
rbuf_list_t *rlist = NULL;
|
||||
int retval = RBUF_CONSUMABLE;
|
||||
rbuf_list_t *rlist = NULL;
|
||||
|
||||
if (!rbuf || !opaque)
|
||||
return -1;
|
||||
if (!rbuf || !opaque)
|
||||
return -1;
|
||||
|
||||
LOCK (&rbuf->lock);
|
||||
{
|
||||
rlist = rbuf_current_buffer (rbuf);
|
||||
if (!rlist->pending) {
|
||||
retval = RBUF_EMPTY;
|
||||
goto unblock;
|
||||
}
|
||||
|
||||
if (list_is_singular (&rbuf->freelist)) {
|
||||
/**
|
||||
* removal would lead to writer starvation, disallow
|
||||
* switching.
|
||||
*/
|
||||
retval = RBUF_WOULD_STARVE;
|
||||
goto unblock;
|
||||
}
|
||||
|
||||
list_del_init (&rlist->list);
|
||||
if (seqfn)
|
||||
seqfn (rlist, mydata);
|
||||
rbuf->current =
|
||||
list_first_entry (&rbuf->freelist, rbuf_list_t, list);
|
||||
LOCK(&rbuf->lock);
|
||||
{
|
||||
rlist = rbuf_current_buffer(rbuf);
|
||||
if (!rlist->pending) {
|
||||
retval = RBUF_EMPTY;
|
||||
goto unblock;
|
||||
}
|
||||
unblock:
|
||||
UNLOCK (&rbuf->lock);
|
||||
|
||||
if (retval == RBUF_CONSUMABLE)
|
||||
*opaque = rlist; /* caller _owns_ the buffer */
|
||||
if (list_is_singular(&rbuf->freelist)) {
|
||||
/**
|
||||
* removal would lead to writer starvation, disallow
|
||||
* switching.
|
||||
*/
|
||||
retval = RBUF_WOULD_STARVE;
|
||||
goto unblock;
|
||||
}
|
||||
|
||||
return retval;
|
||||
list_del_init(&rlist->list);
|
||||
if (seqfn)
|
||||
seqfn(rlist, mydata);
|
||||
rbuf->current = list_first_entry(&rbuf->freelist, rbuf_list_t, list);
|
||||
}
|
||||
unblock:
|
||||
UNLOCK(&rbuf->lock);
|
||||
|
||||
if (retval == RBUF_CONSUMABLE)
|
||||
*opaque = rlist; /* caller _owns_ the buffer */
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -412,10 +408,10 @@ rbuf_get_buffer (rbuf_t *rbuf,
|
||||
*/
|
||||
|
||||
static void
|
||||
__rbuf_wait_for_writers (rbuf_list_t *rlist)
|
||||
__rbuf_wait_for_writers(rbuf_list_t *rlist)
|
||||
{
|
||||
while (rlist->completed != rlist->pending)
|
||||
pthread_cond_wait (&rlist->b_cond, &rlist->b_lock);
|
||||
while (rlist->completed != rlist->pending)
|
||||
pthread_cond_wait(&rlist->b_cond, &rlist->b_lock);
|
||||
}
|
||||
|
||||
#ifndef M_E
|
||||
@ -423,69 +419,69 @@ __rbuf_wait_for_writers (rbuf_list_t *rlist)
|
||||
#endif
|
||||
|
||||
static void
|
||||
rlist_shrink_vector (rbuf_list_t *rlist)
|
||||
rlist_shrink_vector(rbuf_list_t *rlist)
|
||||
{
|
||||
unsigned long long shrink = 0;
|
||||
unsigned long long shrink = 0;
|
||||
|
||||
/**
|
||||
* fast path: don't bother to deallocate if vectors are hardly
|
||||
* used.
|
||||
*/
|
||||
if (rvec_in_watermark_range (rlist))
|
||||
return;
|
||||
/**
|
||||
* fast path: don't bother to deallocate if vectors are hardly
|
||||
* used.
|
||||
*/
|
||||
if (rvec_in_watermark_range(rlist))
|
||||
return;
|
||||
|
||||
/**
|
||||
* Calculate the shrink count based on total allocated vectors.
|
||||
* Note that the calculation sticks to rlist->total irrespective
|
||||
* of the actual usage count (rlist->used). Later, ->used could
|
||||
* be used to apply slack to the calculation based on how much
|
||||
* it lags from ->total. For now, let's stick to slow decay.
|
||||
*/
|
||||
shrink = rlist->total - (rlist->total * pow (M_E, -0.2));
|
||||
/**
|
||||
* Calculate the shrink count based on total allocated vectors.
|
||||
* Note that the calculation sticks to rlist->total irrespective
|
||||
* of the actual usage count (rlist->used). Later, ->used could
|
||||
* be used to apply slack to the calculation based on how much
|
||||
* it lags from ->total. For now, let's stick to slow decay.
|
||||
*/
|
||||
shrink = rlist->total - (rlist->total * pow(M_E, -0.2));
|
||||
|
||||
rlist_shrink_rvec (rlist, shrink);
|
||||
rlist->total -= shrink;
|
||||
rlist_shrink_rvec(rlist, shrink);
|
||||
rlist->total -= shrink;
|
||||
}
|
||||
|
||||
int
|
||||
rbuf_wait_for_completion (rbuf_t *rbuf, void *opaque,
|
||||
void (*fn)(rbuf_list_t *, void *), void *arg)
|
||||
rbuf_wait_for_completion(rbuf_t *rbuf, void *opaque,
|
||||
void (*fn)(rbuf_list_t *, void *), void *arg)
|
||||
{
|
||||
rbuf_list_t *rlist = NULL;
|
||||
rbuf_list_t *rlist = NULL;
|
||||
|
||||
if (!rbuf || !opaque)
|
||||
return -1;
|
||||
if (!rbuf || !opaque)
|
||||
return -1;
|
||||
|
||||
rlist = opaque;
|
||||
rlist = opaque;
|
||||
|
||||
pthread_mutex_lock (&rlist->b_lock);
|
||||
{
|
||||
rlist_mark_waiting (rlist);
|
||||
__rbuf_wait_for_writers (rlist);
|
||||
}
|
||||
pthread_mutex_unlock (&rlist->b_lock);
|
||||
pthread_mutex_lock(&rlist->b_lock);
|
||||
{
|
||||
rlist_mark_waiting(rlist);
|
||||
__rbuf_wait_for_writers(rlist);
|
||||
}
|
||||
pthread_mutex_unlock(&rlist->b_lock);
|
||||
|
||||
/**
|
||||
* from here on, no need of locking until the rlist is put
|
||||
* back into rotation.
|
||||
*/
|
||||
/**
|
||||
* from here on, no need of locking until the rlist is put
|
||||
* back into rotation.
|
||||
*/
|
||||
|
||||
fn (rlist, arg); /* invoke dispatcher */
|
||||
fn(rlist, arg); /* invoke dispatcher */
|
||||
|
||||
rlist->awaiting = _gf_false;
|
||||
rlist->pending = rlist->completed = 0;
|
||||
rlist->awaiting = _gf_false;
|
||||
rlist->pending = rlist->completed = 0;
|
||||
|
||||
rlist_shrink_vector (rlist);
|
||||
rlist_reset_vector_usage (rlist);
|
||||
rlist_shrink_vector(rlist);
|
||||
rlist_reset_vector_usage(rlist);
|
||||
|
||||
rlist->rvec = list_first_entry (&rlist->veclist, rbuf_iovec_t, list);
|
||||
rbuf_reset_rvec (rlist->rvec);
|
||||
rlist->rvec = list_first_entry(&rlist->veclist, rbuf_iovec_t, list);
|
||||
rbuf_reset_rvec(rlist->rvec);
|
||||
|
||||
LOCK (&rbuf->lock);
|
||||
{
|
||||
list_add_tail (&rlist->list, &rbuf->freelist);
|
||||
}
|
||||
UNLOCK (&rbuf->lock);
|
||||
LOCK(&rbuf->lock);
|
||||
{
|
||||
list_add_tail(&rlist->list, &rbuf->freelist);
|
||||
}
|
||||
UNLOCK(&rbuf->lock);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
@ -42,8 +42,9 @@
|
||||
*
|
||||
* $ cc -DRUN_DO_DEMO -DRUN_STANDALONE -orun run.c
|
||||
*/
|
||||
#if defined(RUN_STANDALONE ) || defined(RUN_DO_DEMO)
|
||||
int close_fds_except (int *fdv, size_t count);
|
||||
#if defined(RUN_STANDALONE) || defined(RUN_DO_DEMO)
|
||||
int
|
||||
close_fds_except(int *fdv, size_t count);
|
||||
#define sys_read(f, b, c) read(f, b, c)
|
||||
#define sys_write(f, b, c) write(f, b, c)
|
||||
#define sys_close(f) close(f)
|
||||
@ -54,36 +55,37 @@ int close_fds_except (int *fdv, size_t count);
|
||||
#define gf_strdup(s) strdup(s)
|
||||
#define gf_vasprintf(p, f, va) vasprintf(p, f, va)
|
||||
#define gf_loglevel_t int
|
||||
#define gf_msg_callingfn(dom, level, errnum, msgid, fmt, args...) printf("LOG: " fmt "\n", ##args)
|
||||
#define gf_msg_callingfn(dom, level, errnum, msgid, fmt, args...) \
|
||||
printf("LOG: " fmt "\n", ##args)
|
||||
#define LOG_DEBUG 0
|
||||
#ifdef RUN_STANDALONE
|
||||
#include <stdbool.h>
|
||||
#include <sys/resource.h>
|
||||
int
|
||||
close_fds_except (int *fdv, size_t count)
|
||||
close_fds_except(int *fdv, size_t count)
|
||||
{
|
||||
int i = 0;
|
||||
size_t j = 0;
|
||||
bool should_close = true;
|
||||
struct rlimit rl;
|
||||
int ret = -1;
|
||||
int i = 0;
|
||||
size_t j = 0;
|
||||
bool should_close = true;
|
||||
struct rlimit rl;
|
||||
int ret = -1;
|
||||
|
||||
ret = getrlimit (RLIMIT_NOFILE, &rl);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = getrlimit(RLIMIT_NOFILE, &rl);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < rl.rlim_cur; i++) {
|
||||
should_close = true;
|
||||
for (j = 0; j < count; j++) {
|
||||
if (i == fdv[j]) {
|
||||
should_close = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (should_close)
|
||||
sys_close (i);
|
||||
for (i = 0; i < rl.rlim_cur; i++) {
|
||||
should_close = true;
|
||||
for (j = 0; j < count; j++) {
|
||||
if (i == fdv[j]) {
|
||||
should_close = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
if (should_close)
|
||||
sys_close(i);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
@ -97,470 +99,472 @@ close_fds_except (int *fdv, size_t count)
|
||||
|
||||
#include "run.h"
|
||||
void
|
||||
runinit (runner_t *runner)
|
||||
runinit(runner_t *runner)
|
||||
{
|
||||
int i = 0;
|
||||
int i = 0;
|
||||
|
||||
runner->argvlen = 64;
|
||||
runner->argv = GF_CALLOC (runner->argvlen,
|
||||
sizeof (*runner->argv),
|
||||
gf_common_mt_run_argv);
|
||||
runner->runerr = runner->argv ? 0 : errno;
|
||||
runner->chpid = -1;
|
||||
for (i = 0; i < 3; i++) {
|
||||
runner->chfd[i] = -1;
|
||||
runner->chio[i] = NULL;
|
||||
}
|
||||
runner->argvlen = 64;
|
||||
runner->argv = GF_CALLOC(runner->argvlen, sizeof(*runner->argv),
|
||||
gf_common_mt_run_argv);
|
||||
runner->runerr = runner->argv ? 0 : errno;
|
||||
runner->chpid = -1;
|
||||
for (i = 0; i < 3; i++) {
|
||||
runner->chfd[i] = -1;
|
||||
runner->chio[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
FILE *
|
||||
runner_chio (runner_t *runner, int fd)
|
||||
runner_chio(runner_t *runner, int fd)
|
||||
{
|
||||
GF_ASSERT (fd > 0 && fd < 3);
|
||||
GF_ASSERT(fd > 0 && fd < 3);
|
||||
|
||||
if ((fd > 0) && (fd < 3))
|
||||
return runner->chio[fd];
|
||||
if ((fd > 0) && (fd < 3))
|
||||
return runner->chio[fd];
|
||||
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
runner_insert_arg (runner_t *runner, char *arg)
|
||||
runner_insert_arg(runner_t *runner, char *arg)
|
||||
{
|
||||
int i = 0;
|
||||
int i = 0;
|
||||
|
||||
GF_ASSERT (arg);
|
||||
GF_ASSERT(arg);
|
||||
|
||||
if (runner->runerr)
|
||||
return;
|
||||
if (runner->runerr)
|
||||
return;
|
||||
|
||||
for (i = 0; i < runner->argvlen; i++) {
|
||||
if (runner->argv[i] == NULL)
|
||||
break;
|
||||
for (i = 0; i < runner->argvlen; i++) {
|
||||
if (runner->argv[i] == NULL)
|
||||
break;
|
||||
}
|
||||
GF_ASSERT(i < runner->argvlen);
|
||||
|
||||
if (i == runner->argvlen - 1) {
|
||||
runner->argv = GF_REALLOC(runner->argv,
|
||||
runner->argvlen * 2 * sizeof(*runner->argv));
|
||||
if (!runner->argv) {
|
||||
runner->runerr = errno;
|
||||
return;
|
||||
}
|
||||
GF_ASSERT (i < runner->argvlen);
|
||||
memset(/* "+" is aware of the type of its left side,
|
||||
* no need to multiply with type-size */
|
||||
runner->argv + runner->argvlen, 0,
|
||||
runner->argvlen * sizeof(*runner->argv));
|
||||
runner->argvlen *= 2;
|
||||
}
|
||||
|
||||
if (i == runner->argvlen - 1) {
|
||||
runner->argv = GF_REALLOC (runner->argv,
|
||||
runner->argvlen * 2 * sizeof (*runner->argv));
|
||||
if (!runner->argv) {
|
||||
runner->runerr = errno;
|
||||
return;
|
||||
}
|
||||
memset (/* "+" is aware of the type of its left side,
|
||||
* no need to multiply with type-size */
|
||||
runner->argv + runner->argvlen,
|
||||
0, runner->argvlen * sizeof (*runner->argv));
|
||||
runner->argvlen *= 2;
|
||||
}
|
||||
|
||||
runner->argv[i] = arg;
|
||||
runner->argv[i] = arg;
|
||||
}
|
||||
|
||||
void
|
||||
runner_add_arg (runner_t *runner, const char *arg)
|
||||
runner_add_arg(runner_t *runner, const char *arg)
|
||||
{
|
||||
arg = gf_strdup (arg);
|
||||
if (!arg) {
|
||||
runner->runerr = errno;
|
||||
return;
|
||||
}
|
||||
arg = gf_strdup(arg);
|
||||
if (!arg) {
|
||||
runner->runerr = errno;
|
||||
return;
|
||||
}
|
||||
|
||||
runner_insert_arg (runner, (char *)arg);
|
||||
runner_insert_arg(runner, (char *)arg);
|
||||
}
|
||||
|
||||
static void
|
||||
runner_va_add_args (runner_t *runner, va_list argp)
|
||||
runner_va_add_args(runner_t *runner, va_list argp)
|
||||
{
|
||||
const char *arg;
|
||||
const char *arg;
|
||||
|
||||
while ((arg = va_arg (argp, const char *)))
|
||||
runner_add_arg (runner, arg);
|
||||
while ((arg = va_arg(argp, const char *)))
|
||||
runner_add_arg(runner, arg);
|
||||
}
|
||||
|
||||
void
|
||||
runner_add_args (runner_t *runner, ...)
|
||||
runner_add_args(runner_t *runner, ...)
|
||||
{
|
||||
va_list argp;
|
||||
va_list argp;
|
||||
|
||||
va_start (argp, runner);
|
||||
runner_va_add_args (runner, argp);
|
||||
va_end (argp);
|
||||
va_start(argp, runner);
|
||||
runner_va_add_args(runner, argp);
|
||||
va_end(argp);
|
||||
}
|
||||
|
||||
void
|
||||
runner_argprintf (runner_t *runner, const char *format, ...)
|
||||
runner_argprintf(runner_t *runner, const char *format, ...)
|
||||
{
|
||||
va_list argva;
|
||||
char *arg = NULL;
|
||||
int ret = 0;
|
||||
va_list argva;
|
||||
char *arg = NULL;
|
||||
int ret = 0;
|
||||
|
||||
va_start (argva, format);
|
||||
ret = gf_vasprintf (&arg, format, argva);
|
||||
va_end (argva);
|
||||
va_start(argva, format);
|
||||
ret = gf_vasprintf(&arg, format, argva);
|
||||
va_end(argva);
|
||||
|
||||
if (ret < 0) {
|
||||
runner->runerr = errno;
|
||||
return;
|
||||
}
|
||||
if (ret < 0) {
|
||||
runner->runerr = errno;
|
||||
return;
|
||||
}
|
||||
|
||||
runner_insert_arg (runner, arg);
|
||||
runner_insert_arg(runner, arg);
|
||||
}
|
||||
|
||||
void
|
||||
runner_log (runner_t *runner, const char *dom, gf_loglevel_t lvl,
|
||||
const char *msg)
|
||||
runner_log(runner_t *runner, const char *dom, gf_loglevel_t lvl,
|
||||
const char *msg)
|
||||
{
|
||||
char *buf = NULL;
|
||||
size_t len = 0;
|
||||
int i = 0;
|
||||
char *buf = NULL;
|
||||
size_t len = 0;
|
||||
int i = 0;
|
||||
|
||||
if (runner->runerr)
|
||||
return;
|
||||
if (runner->runerr)
|
||||
return;
|
||||
|
||||
for (i = 0;; i++) {
|
||||
if (runner->argv[i] == NULL)
|
||||
break;
|
||||
len += (strlen (runner->argv[i]) + 1);
|
||||
}
|
||||
for (i = 0;; i++) {
|
||||
if (runner->argv[i] == NULL)
|
||||
break;
|
||||
len += (strlen(runner->argv[i]) + 1);
|
||||
}
|
||||
|
||||
buf = GF_CALLOC (1, len + 1, gf_common_mt_run_logbuf);
|
||||
if (!buf) {
|
||||
runner->runerr = errno;
|
||||
return;
|
||||
}
|
||||
for (i = 0;; i++) {
|
||||
if (runner->argv[i] == NULL)
|
||||
break;
|
||||
strcat (buf, runner->argv[i]);
|
||||
strcat (buf, " ");
|
||||
}
|
||||
if (len > 0)
|
||||
buf[len - 1] = '\0';
|
||||
buf = GF_CALLOC(1, len + 1, gf_common_mt_run_logbuf);
|
||||
if (!buf) {
|
||||
runner->runerr = errno;
|
||||
return;
|
||||
}
|
||||
for (i = 0;; i++) {
|
||||
if (runner->argv[i] == NULL)
|
||||
break;
|
||||
strcat(buf, runner->argv[i]);
|
||||
strcat(buf, " ");
|
||||
}
|
||||
if (len > 0)
|
||||
buf[len - 1] = '\0';
|
||||
|
||||
gf_msg_callingfn (dom, lvl, 0, LG_MSG_RUNNER_LOG, "%s: %s", msg, buf);
|
||||
gf_msg_callingfn(dom, lvl, 0, LG_MSG_RUNNER_LOG, "%s: %s", msg, buf);
|
||||
|
||||
GF_FREE (buf);
|
||||
GF_FREE(buf);
|
||||
}
|
||||
|
||||
void
|
||||
runner_redir (runner_t *runner, int fd, int tgt_fd)
|
||||
runner_redir(runner_t *runner, int fd, int tgt_fd)
|
||||
{
|
||||
GF_ASSERT (fd > 0 && fd < 3);
|
||||
GF_ASSERT(fd > 0 && fd < 3);
|
||||
|
||||
if ((fd > 0) && (fd < 3))
|
||||
runner->chfd[fd] = (tgt_fd >= 0) ? tgt_fd : -2;
|
||||
if ((fd > 0) && (fd < 3))
|
||||
runner->chfd[fd] = (tgt_fd >= 0) ? tgt_fd : -2;
|
||||
}
|
||||
|
||||
int
|
||||
runner_start (runner_t *runner)
|
||||
runner_start(runner_t *runner)
|
||||
{
|
||||
int pi[3][2] = {{-1, -1}, {-1, -1}, {-1, -1}};
|
||||
int xpi[2];
|
||||
int ret = 0;
|
||||
int errno_priv = 0;
|
||||
int i = 0;
|
||||
sigset_t set;
|
||||
int pi[3][2] = {{-1, -1}, {-1, -1}, {-1, -1}};
|
||||
int xpi[2];
|
||||
int ret = 0;
|
||||
int errno_priv = 0;
|
||||
int i = 0;
|
||||
sigset_t set;
|
||||
|
||||
if (runner->runerr) {
|
||||
errno = runner->runerr;
|
||||
return -1;
|
||||
}
|
||||
|
||||
GF_ASSERT (runner->argv[0]);
|
||||
|
||||
/* set up a channel to child to communicate back
|
||||
* possible execve(2) failures
|
||||
*/
|
||||
ret = pipe(xpi);
|
||||
if (ret != -1)
|
||||
ret = fcntl (xpi[1], F_SETFD, FD_CLOEXEC);
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (runner->chfd[i] != -2)
|
||||
continue;
|
||||
ret = pipe (pi[i]);
|
||||
if (ret != -1) {
|
||||
runner->chio[i] = fdopen (pi[i][i ? 0 : 1], i ? "r" : "w");
|
||||
if (!runner->chio[i])
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret != -1)
|
||||
runner->chpid = fork ();
|
||||
switch (runner->chpid) {
|
||||
case -1:
|
||||
errno_priv = errno;
|
||||
sys_close (xpi[0]);
|
||||
sys_close (xpi[1]);
|
||||
for (i = 0; i < 3; i++) {
|
||||
sys_close (pi[i][0]);
|
||||
sys_close (pi[i][1]);
|
||||
}
|
||||
errno = errno_priv;
|
||||
return -1;
|
||||
case 0:
|
||||
for (i = 0; i < 3; i++)
|
||||
sys_close (pi[i][i ? 0 : 1]);
|
||||
sys_close (xpi[0]);
|
||||
ret = 0;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (ret == -1)
|
||||
break;
|
||||
switch (runner->chfd[i]) {
|
||||
case -1:
|
||||
/* no redir */
|
||||
break;
|
||||
case -2:
|
||||
/* redir to pipe */
|
||||
ret = dup2 (pi[i][i ? 1 : 0], i);
|
||||
break;
|
||||
default:
|
||||
/* redir to file */
|
||||
ret = dup2 (runner->chfd[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
if (ret != -1 ) {
|
||||
int fdv[4] = {0, 1, 2, xpi[1]};
|
||||
|
||||
ret = close_fds_except(fdv, sizeof (fdv) / sizeof (*fdv));
|
||||
}
|
||||
|
||||
if (ret != -1) {
|
||||
/* save child from inheriting our signal handling */
|
||||
sigemptyset (&set);
|
||||
sigprocmask (SIG_SETMASK, &set, NULL);
|
||||
|
||||
execvp (runner->argv[0], runner->argv);
|
||||
}
|
||||
ret = sys_write (xpi[1], &errno, sizeof (errno));
|
||||
_exit (1);
|
||||
}
|
||||
|
||||
errno_priv = errno;
|
||||
for (i = 0; i < 3; i++)
|
||||
sys_close (pi[i][i ? 1 : 0]);
|
||||
sys_close (xpi[1]);
|
||||
if (ret == -1) {
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (runner->chio[i]) {
|
||||
fclose (runner->chio[i]);
|
||||
runner->chio[i] = NULL;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ret = sys_read (xpi[0], (char *)&errno_priv, sizeof (errno_priv));
|
||||
sys_close (xpi[0]);
|
||||
if (ret <= 0)
|
||||
return 0;
|
||||
GF_ASSERT (ret == sizeof (errno_priv));
|
||||
}
|
||||
errno = errno_priv;
|
||||
if (runner->runerr) {
|
||||
errno = runner->runerr;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
runner_end_reuse (runner_t *runner)
|
||||
{
|
||||
int i = 0;
|
||||
int ret = 1;
|
||||
int chstat = 0;
|
||||
GF_ASSERT(runner->argv[0]);
|
||||
|
||||
if (runner->chpid > 0) {
|
||||
if (waitpid (runner->chpid, &chstat, 0) == runner->chpid) {
|
||||
if (WIFEXITED(chstat)) {
|
||||
ret = WEXITSTATUS(chstat);
|
||||
} else {
|
||||
ret = chstat;
|
||||
}
|
||||
}
|
||||
/* set up a channel to child to communicate back
|
||||
* possible execve(2) failures
|
||||
*/
|
||||
ret = pipe(xpi);
|
||||
if (ret != -1)
|
||||
ret = fcntl(xpi[1], F_SETFD, FD_CLOEXEC);
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (runner->chfd[i] != -2)
|
||||
continue;
|
||||
ret = pipe(pi[i]);
|
||||
if (ret != -1) {
|
||||
runner->chio[i] = fdopen(pi[i][i ? 0 : 1], i ? "r" : "w");
|
||||
if (!runner->chio[i])
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret != -1)
|
||||
runner->chpid = fork();
|
||||
switch (runner->chpid) {
|
||||
case -1:
|
||||
errno_priv = errno;
|
||||
sys_close(xpi[0]);
|
||||
sys_close(xpi[1]);
|
||||
for (i = 0; i < 3; i++) {
|
||||
sys_close(pi[i][0]);
|
||||
sys_close(pi[i][1]);
|
||||
}
|
||||
errno = errno_priv;
|
||||
return -1;
|
||||
case 0:
|
||||
for (i = 0; i < 3; i++)
|
||||
sys_close(pi[i][i ? 0 : 1]);
|
||||
sys_close(xpi[0]);
|
||||
ret = 0;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (ret == -1)
|
||||
break;
|
||||
switch (runner->chfd[i]) {
|
||||
case -1:
|
||||
/* no redir */
|
||||
break;
|
||||
case -2:
|
||||
/* redir to pipe */
|
||||
ret = dup2(pi[i][i ? 1 : 0], i);
|
||||
break;
|
||||
default:
|
||||
/* redir to file */
|
||||
ret = dup2(runner->chfd[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
if (ret != -1) {
|
||||
int fdv[4] = {0, 1, 2, xpi[1]};
|
||||
|
||||
ret = close_fds_except(fdv, sizeof(fdv) / sizeof(*fdv));
|
||||
}
|
||||
|
||||
if (ret != -1) {
|
||||
/* save child from inheriting our signal handling */
|
||||
sigemptyset(&set);
|
||||
sigprocmask(SIG_SETMASK, &set, NULL);
|
||||
|
||||
execvp(runner->argv[0], runner->argv);
|
||||
}
|
||||
ret = sys_write(xpi[1], &errno, sizeof(errno));
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
errno_priv = errno;
|
||||
for (i = 0; i < 3; i++)
|
||||
sys_close(pi[i][i ? 1 : 0]);
|
||||
sys_close(xpi[1]);
|
||||
if (ret == -1) {
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (runner->chio[i]) {
|
||||
fclose (runner->chio[i]);
|
||||
runner->chio[i] = NULL;
|
||||
}
|
||||
if (runner->chio[i]) {
|
||||
fclose(runner->chio[i]);
|
||||
runner->chio[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return -ret;
|
||||
} else {
|
||||
ret = sys_read(xpi[0], (char *)&errno_priv, sizeof(errno_priv));
|
||||
sys_close(xpi[0]);
|
||||
if (ret <= 0)
|
||||
return 0;
|
||||
GF_ASSERT(ret == sizeof(errno_priv));
|
||||
}
|
||||
errno = errno_priv;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
runner_end (runner_t *runner)
|
||||
runner_end_reuse(runner_t *runner)
|
||||
{
|
||||
int i = 0;
|
||||
int ret = -1;
|
||||
char **p = NULL;
|
||||
int i = 0;
|
||||
int ret = 1;
|
||||
int chstat = 0;
|
||||
|
||||
ret = runner_end_reuse (runner);
|
||||
|
||||
if (runner->argv) {
|
||||
for (p = runner->argv; *p; p++)
|
||||
GF_FREE (*p);
|
||||
GF_FREE (runner->argv);
|
||||
if (runner->chpid > 0) {
|
||||
if (waitpid(runner->chpid, &chstat, 0) == runner->chpid) {
|
||||
if (WIFEXITED(chstat)) {
|
||||
ret = WEXITSTATUS(chstat);
|
||||
} else {
|
||||
ret = chstat;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 3; i++)
|
||||
sys_close (runner->chfd[i]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (runner->chio[i]) {
|
||||
fclose(runner->chio[i]);
|
||||
runner->chio[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return -ret;
|
||||
}
|
||||
|
||||
int
|
||||
runner_end(runner_t *runner)
|
||||
{
|
||||
int i = 0;
|
||||
int ret = -1;
|
||||
char **p = NULL;
|
||||
|
||||
ret = runner_end_reuse(runner);
|
||||
|
||||
if (runner->argv) {
|
||||
for (p = runner->argv; *p; p++)
|
||||
GF_FREE(*p);
|
||||
GF_FREE(runner->argv);
|
||||
}
|
||||
for (i = 0; i < 3; i++)
|
||||
sys_close(runner->chfd[i]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
runner_run_generic (runner_t *runner, int (*rfin)(runner_t *runner))
|
||||
runner_run_generic(runner_t *runner, int (*rfin)(runner_t *runner))
|
||||
{
|
||||
int ret = 0;
|
||||
int ret = 0;
|
||||
|
||||
ret = runner_start (runner);
|
||||
if (ret)
|
||||
goto out;
|
||||
ret = rfin (runner);
|
||||
ret = runner_start(runner);
|
||||
if (ret)
|
||||
goto out;
|
||||
ret = rfin(runner);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
runner_run (runner_t *runner)
|
||||
runner_run(runner_t *runner)
|
||||
{
|
||||
return runner_run_generic (runner, runner_end);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
runner_run_nowait (runner_t *runner)
|
||||
{
|
||||
int pid;
|
||||
|
||||
pid = fork ();
|
||||
|
||||
if (!pid) {
|
||||
setsid ();
|
||||
_exit (runner_start (runner));
|
||||
}
|
||||
|
||||
if (pid > 0)
|
||||
runner->chpid = pid;
|
||||
return runner_end (runner);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
runner_run_reuse (runner_t *runner)
|
||||
{
|
||||
return runner_run_generic (runner, runner_end_reuse);
|
||||
return runner_run_generic(runner, runner_end);
|
||||
}
|
||||
|
||||
int
|
||||
runcmd (const char *arg, ...)
|
||||
runner_run_nowait(runner_t *runner)
|
||||
{
|
||||
runner_t runner;
|
||||
va_list argp;
|
||||
int pid;
|
||||
|
||||
runinit (&runner);
|
||||
/* ISO C requires a named argument before '...' */
|
||||
runner_add_arg (&runner, arg);
|
||||
pid = fork();
|
||||
|
||||
va_start (argp, arg);
|
||||
runner_va_add_args (&runner, argp);
|
||||
va_end (argp);
|
||||
if (!pid) {
|
||||
setsid();
|
||||
_exit(runner_start(runner));
|
||||
}
|
||||
|
||||
return runner_run (&runner);
|
||||
if (pid > 0)
|
||||
runner->chpid = pid;
|
||||
return runner_end(runner);
|
||||
}
|
||||
|
||||
int
|
||||
runner_run_reuse(runner_t *runner)
|
||||
{
|
||||
return runner_run_generic(runner, runner_end_reuse);
|
||||
}
|
||||
|
||||
int
|
||||
runcmd(const char *arg, ...)
|
||||
{
|
||||
runner_t runner;
|
||||
va_list argp;
|
||||
|
||||
runinit(&runner);
|
||||
/* ISO C requires a named argument before '...' */
|
||||
runner_add_arg(&runner, arg);
|
||||
|
||||
va_start(argp, arg);
|
||||
runner_va_add_args(&runner, argp);
|
||||
va_end(argp);
|
||||
|
||||
return runner_run(&runner);
|
||||
}
|
||||
|
||||
#ifdef RUN_DO_DEMO
|
||||
static void
|
||||
TBANNER (const char *txt)
|
||||
TBANNER(const char *txt)
|
||||
{
|
||||
printf("######\n### demoing %s\n", txt);
|
||||
printf("######\n### demoing %s\n", txt);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
runner_t runner;
|
||||
char buf[80];
|
||||
char *wdbuf;;
|
||||
int ret;
|
||||
int fd;
|
||||
long pathmax = pathconf ("/", _PC_PATH_MAX);
|
||||
struct timeval tv = {0,};
|
||||
struct timeval *tvp = NULL;
|
||||
char *tfile;
|
||||
runner_t runner;
|
||||
char buf[80];
|
||||
char *wdbuf;
|
||||
;
|
||||
int ret;
|
||||
int fd;
|
||||
long pathmax = pathconf("/", _PC_PATH_MAX);
|
||||
struct timeval tv = {
|
||||
0,
|
||||
};
|
||||
struct timeval *tvp = NULL;
|
||||
char *tfile;
|
||||
|
||||
wdbuf = malloc (pathmax);
|
||||
assert (wdbuf);
|
||||
getcwd (wdbuf, pathmax);
|
||||
wdbuf = malloc(pathmax);
|
||||
assert(wdbuf);
|
||||
getcwd(wdbuf, pathmax);
|
||||
|
||||
TBANNER ("basic functionality: running \"echo a b\"");
|
||||
runcmd ("echo", "a", "b", NULL);
|
||||
TBANNER("basic functionality: running \"echo a b\"");
|
||||
runcmd("echo", "a", "b", NULL);
|
||||
|
||||
TBANNER ("argv extension: running \"echo 1 2 ... 100\"");
|
||||
runcmd ("echo", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
|
||||
"11", "12", "13", "14", "15", "16", "17", "18", "19", "20",
|
||||
"21", "22", "23", "24", "25", "26", "27", "28", "29", "30",
|
||||
"31", "32", "33", "34", "35", "36", "37", "38", "39", "40",
|
||||
"41", "42", "43", "44", "45", "46", "47", "48", "49", "50",
|
||||
"51", "52", "53", "54", "55", "56", "57", "58", "59", "60",
|
||||
"61", "62", "63", "64", "65", "66", "67", "68", "69", "70",
|
||||
"71", "72", "73", "74", "75", "76", "77", "78", "79", "80",
|
||||
"81", "82", "83", "84", "85", "86", "87", "88", "89", "90",
|
||||
"91", "92", "93", "94", "95", "96", "97", "98", "99", "100", NULL);
|
||||
TBANNER("argv extension: running \"echo 1 2 ... 100\"");
|
||||
runcmd("echo", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11",
|
||||
"12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22",
|
||||
"23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33",
|
||||
"34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44",
|
||||
"45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55",
|
||||
"56", "57", "58", "59", "60", "61", "62", "63", "64", "65", "66",
|
||||
"67", "68", "69", "70", "71", "72", "73", "74", "75", "76", "77",
|
||||
"78", "79", "80", "81", "82", "83", "84", "85", "86", "87", "88",
|
||||
"89", "90", "91", "92", "93", "94", "95", "96", "97", "98", "99",
|
||||
"100", NULL);
|
||||
|
||||
TBANNER ("add_args, argprintf, log, and popen-style functionality:\n"
|
||||
" running a multiline echo command, emit a log about it,\n"
|
||||
" redirect it to a pipe, read output lines\n"
|
||||
" and print them prefixed with \"got: \"");
|
||||
runinit (&runner);
|
||||
runner_add_args (&runner, "echo", "pid:", NULL);
|
||||
runner_argprintf (&runner, "%d\n", getpid());
|
||||
runner_add_arg (&runner, "wd:");
|
||||
runner_add_arg (&runner, wdbuf);
|
||||
runner_redir (&runner, 1, RUN_PIPE);
|
||||
runner_start (&runner);
|
||||
runner_log (&runner, "(x)", LOG_DEBUG, "starting program");
|
||||
while (fgets (buf, sizeof(buf), runner_chio (&runner, 1)))
|
||||
printf ("got: %s", buf);
|
||||
runner_end (&runner);
|
||||
TBANNER(
|
||||
"add_args, argprintf, log, and popen-style functionality:\n"
|
||||
" running a multiline echo command, emit a log about it,\n"
|
||||
" redirect it to a pipe, read output lines\n"
|
||||
" and print them prefixed with \"got: \"");
|
||||
runinit(&runner);
|
||||
runner_add_args(&runner, "echo", "pid:", NULL);
|
||||
runner_argprintf(&runner, "%d\n", getpid());
|
||||
runner_add_arg(&runner, "wd:");
|
||||
runner_add_arg(&runner, wdbuf);
|
||||
runner_redir(&runner, 1, RUN_PIPE);
|
||||
runner_start(&runner);
|
||||
runner_log(&runner, "(x)", LOG_DEBUG, "starting program");
|
||||
while (fgets(buf, sizeof(buf), runner_chio(&runner, 1)))
|
||||
printf("got: %s", buf);
|
||||
runner_end(&runner);
|
||||
|
||||
TBANNER ("execve error reporting: running a non-existent command");
|
||||
ret = runcmd ("bafflavvitty", NULL);
|
||||
printf ("%d %d [%s]\n", ret, errno, strerror (errno));
|
||||
TBANNER("execve error reporting: running a non-existent command");
|
||||
ret = runcmd("bafflavvitty", NULL);
|
||||
printf("%d %d [%s]\n", ret, errno, strerror(errno));
|
||||
|
||||
TBANNER ("output redirection: running \"echo foo\" redirected "
|
||||
"to a temp file");
|
||||
tfile = strdup ("/tmp/foofXXXXXX");
|
||||
assert (tfile);
|
||||
fd = mkstemp (tfile);
|
||||
assert (fd != -1);
|
||||
printf ("redirecting to %s\n", tfile);
|
||||
runinit (&runner);
|
||||
runner_add_args (&runner, "echo", "foo", NULL);
|
||||
runner_redir (&runner, 1, fd);
|
||||
ret = runner_run (&runner);
|
||||
printf ("runner_run returned: %d", ret);
|
||||
if (ret != 0)
|
||||
printf (", with errno %d [%s]", errno, strerror (errno));
|
||||
putchar ('\n');
|
||||
TBANNER(
|
||||
"output redirection: running \"echo foo\" redirected "
|
||||
"to a temp file");
|
||||
tfile = strdup("/tmp/foofXXXXXX");
|
||||
assert(tfile);
|
||||
fd = mkstemp(tfile);
|
||||
assert(fd != -1);
|
||||
printf("redirecting to %s\n", tfile);
|
||||
runinit(&runner);
|
||||
runner_add_args(&runner, "echo", "foo", NULL);
|
||||
runner_redir(&runner, 1, fd);
|
||||
ret = runner_run(&runner);
|
||||
printf("runner_run returned: %d", ret);
|
||||
if (ret != 0)
|
||||
printf(", with errno %d [%s]", errno, strerror(errno));
|
||||
putchar('\n');
|
||||
|
||||
/* sleep for seconds given as argument (0 means forever)
|
||||
* to allow investigation of post-execution state to
|
||||
* cbeck for resource leaks (eg. zombies).
|
||||
*/
|
||||
if (argc > 1) {
|
||||
tv.tv_sec = strtoul (argv[1], NULL, 10);
|
||||
printf ("### %s", "sleeping for");
|
||||
if (tv.tv_sec > 0) {
|
||||
printf (" %d seconds\n", tv.tv_sec);
|
||||
tvp = &tv;
|
||||
} else
|
||||
printf ("%s\n", "ever");
|
||||
select (0, 0, 0, 0, tvp);
|
||||
}
|
||||
/* sleep for seconds given as argument (0 means forever)
|
||||
* to allow investigation of post-execution state to
|
||||
* cbeck for resource leaks (eg. zombies).
|
||||
*/
|
||||
if (argc > 1) {
|
||||
tv.tv_sec = strtoul(argv[1], NULL, 10);
|
||||
printf("### %s", "sleeping for");
|
||||
if (tv.tv_sec > 0) {
|
||||
printf(" %d seconds\n", tv.tv_sec);
|
||||
tvp = &tv;
|
||||
} else
|
||||
printf("%s\n", "ever");
|
||||
select(0, 0, 0, 0, tvp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@ -13,433 +13,433 @@
|
||||
#include "libglusterfs-messages.h"
|
||||
|
||||
call_frame_t *
|
||||
create_frame (xlator_t *xl, call_pool_t *pool)
|
||||
create_frame(xlator_t *xl, call_pool_t *pool)
|
||||
{
|
||||
call_stack_t *stack = NULL;
|
||||
call_frame_t *frame = NULL;
|
||||
call_stack_t *stack = NULL;
|
||||
call_frame_t *frame = NULL;
|
||||
|
||||
if (!xl || !pool) {
|
||||
return NULL;
|
||||
}
|
||||
if (!xl || !pool) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
stack = mem_get0 (pool->stack_mem_pool);
|
||||
if (!stack)
|
||||
return NULL;
|
||||
stack = mem_get0(pool->stack_mem_pool);
|
||||
if (!stack)
|
||||
return NULL;
|
||||
|
||||
INIT_LIST_HEAD (&stack->myframes);
|
||||
INIT_LIST_HEAD(&stack->myframes);
|
||||
|
||||
frame = mem_get0 (pool->frame_mem_pool);
|
||||
if (!frame) {
|
||||
mem_put (stack);
|
||||
return NULL;
|
||||
}
|
||||
frame = mem_get0(pool->frame_mem_pool);
|
||||
if (!frame) {
|
||||
mem_put(stack);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
frame->root = stack;
|
||||
frame->this = xl;
|
||||
LOCK_INIT (&frame->lock);
|
||||
INIT_LIST_HEAD (&frame->frames);
|
||||
list_add (&frame->frames, &stack->myframes);
|
||||
frame->root = stack;
|
||||
frame->this = xl;
|
||||
LOCK_INIT(&frame->lock);
|
||||
INIT_LIST_HEAD(&frame->frames);
|
||||
list_add(&frame->frames, &stack->myframes);
|
||||
|
||||
stack->pool = pool;
|
||||
stack->ctx = xl->ctx;
|
||||
stack->pool = pool;
|
||||
stack->ctx = xl->ctx;
|
||||
|
||||
if (frame->root->ctx->measure_latency) {
|
||||
timespec_now (&stack->tv);
|
||||
memcpy (&frame->begin, &stack->tv,
|
||||
sizeof (stack->tv));
|
||||
}
|
||||
if (frame->root->ctx->measure_latency) {
|
||||
timespec_now(&stack->tv);
|
||||
memcpy(&frame->begin, &stack->tv, sizeof(stack->tv));
|
||||
}
|
||||
|
||||
LOCK (&pool->lock);
|
||||
{
|
||||
list_add (&stack->all_frames, &pool->all_frames);
|
||||
pool->cnt++;
|
||||
}
|
||||
UNLOCK (&pool->lock);
|
||||
GF_ATOMIC_INC (pool->total_count);
|
||||
LOCK(&pool->lock);
|
||||
{
|
||||
list_add(&stack->all_frames, &pool->all_frames);
|
||||
pool->cnt++;
|
||||
}
|
||||
UNLOCK(&pool->lock);
|
||||
GF_ATOMIC_INC(pool->total_count);
|
||||
|
||||
LOCK_INIT (&stack->stack_lock);
|
||||
LOCK_INIT(&stack->stack_lock);
|
||||
|
||||
return frame;
|
||||
return frame;
|
||||
}
|
||||
|
||||
void
|
||||
call_stack_set_groups (call_stack_t *stack, int ngrps, gid_t **groupbuf_p)
|
||||
call_stack_set_groups(call_stack_t *stack, int ngrps, gid_t **groupbuf_p)
|
||||
{
|
||||
/* We take the ownership of the passed group buffer. */
|
||||
/* We take the ownership of the passed group buffer. */
|
||||
|
||||
if (ngrps <= SMALL_GROUP_COUNT) {
|
||||
memcpy (stack->groups_small, *groupbuf_p,
|
||||
sizeof (gid_t) * ngrps);
|
||||
stack->groups = stack->groups_small;
|
||||
GF_FREE (*groupbuf_p);
|
||||
} else {
|
||||
stack->groups_large = *groupbuf_p;
|
||||
stack->groups = stack->groups_large;
|
||||
}
|
||||
if (ngrps <= SMALL_GROUP_COUNT) {
|
||||
memcpy(stack->groups_small, *groupbuf_p, sizeof(gid_t) * ngrps);
|
||||
stack->groups = stack->groups_small;
|
||||
GF_FREE(*groupbuf_p);
|
||||
} else {
|
||||
stack->groups_large = *groupbuf_p;
|
||||
stack->groups = stack->groups_large;
|
||||
}
|
||||
|
||||
stack->ngrps = ngrps;
|
||||
/* Set a canary. */
|
||||
*groupbuf_p = (void *)0xdeadf00d;
|
||||
stack->ngrps = ngrps;
|
||||
/* Set a canary. */
|
||||
*groupbuf_p = (void *)0xdeadf00d;
|
||||
}
|
||||
|
||||
void
|
||||
gf_proc_dump_call_frame (call_frame_t *call_frame, const char *key_buf,...)
|
||||
gf_proc_dump_call_frame(call_frame_t *call_frame, const char *key_buf, ...)
|
||||
{
|
||||
char prefix[GF_DUMP_MAX_BUF_LEN];
|
||||
va_list ap;
|
||||
call_frame_t my_frame;
|
||||
int ret = -1;
|
||||
char timestr[256] = {
|
||||
0,
|
||||
};
|
||||
int len;
|
||||
|
||||
char prefix[GF_DUMP_MAX_BUF_LEN];
|
||||
va_list ap;
|
||||
call_frame_t my_frame;
|
||||
int ret = -1;
|
||||
char timestr[256] = {0,};
|
||||
int len;
|
||||
if (!call_frame)
|
||||
return;
|
||||
|
||||
if (!call_frame)
|
||||
return;
|
||||
GF_ASSERT(key_buf);
|
||||
|
||||
GF_ASSERT (key_buf);
|
||||
va_start(ap, key_buf);
|
||||
vsnprintf(prefix, GF_DUMP_MAX_BUF_LEN, key_buf, ap);
|
||||
va_end(ap);
|
||||
|
||||
va_start(ap, key_buf);
|
||||
vsnprintf(prefix, GF_DUMP_MAX_BUF_LEN, key_buf, ap);
|
||||
va_end(ap);
|
||||
ret = TRY_LOCK(&call_frame->lock);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = TRY_LOCK(&call_frame->lock);
|
||||
if (ret)
|
||||
goto out;
|
||||
memcpy(&my_frame, call_frame, sizeof(my_frame));
|
||||
UNLOCK(&call_frame->lock);
|
||||
|
||||
memcpy(&my_frame, call_frame, sizeof(my_frame));
|
||||
UNLOCK(&call_frame->lock);
|
||||
if (my_frame.root->ctx->measure_latency) {
|
||||
gf_time_fmt(timestr, sizeof(timestr), my_frame.begin.tv_sec,
|
||||
gf_timefmt_FT);
|
||||
len = strlen(timestr);
|
||||
snprintf(timestr + len, sizeof(timestr) - len, ".%" GF_PRI_SNSECONDS,
|
||||
my_frame.begin.tv_nsec);
|
||||
gf_proc_dump_write("frame-creation-time", "%s", timestr);
|
||||
gf_proc_dump_write(
|
||||
"timings", "%ld.%" GF_PRI_SNSECONDS " -> %ld.%" GF_PRI_SNSECONDS,
|
||||
my_frame.begin.tv_sec, my_frame.begin.tv_nsec, my_frame.end.tv_sec,
|
||||
my_frame.end.tv_nsec);
|
||||
}
|
||||
|
||||
if (my_frame.root->ctx->measure_latency) {
|
||||
gf_time_fmt (timestr, sizeof (timestr), my_frame.begin.tv_sec,
|
||||
gf_timefmt_FT);
|
||||
len = strlen (timestr);
|
||||
snprintf (timestr + len, sizeof (timestr) - len,
|
||||
".%"GF_PRI_SNSECONDS, my_frame.begin.tv_nsec);
|
||||
gf_proc_dump_write("frame-creation-time", "%s", timestr);
|
||||
gf_proc_dump_write("timings", "%ld.%"GF_PRI_SNSECONDS
|
||||
" -> %ld.%"GF_PRI_SNSECONDS,
|
||||
my_frame.begin.tv_sec,
|
||||
my_frame.begin.tv_nsec,
|
||||
my_frame.end.tv_sec,
|
||||
my_frame.end.tv_nsec);
|
||||
}
|
||||
gf_proc_dump_write("frame", "%p", call_frame);
|
||||
gf_proc_dump_write("ref_count", "%d", my_frame.ref_count);
|
||||
gf_proc_dump_write("translator", "%s", my_frame.this->name);
|
||||
gf_proc_dump_write("complete", "%d", my_frame.complete);
|
||||
|
||||
gf_proc_dump_write("frame", "%p", call_frame);
|
||||
gf_proc_dump_write("ref_count", "%d", my_frame.ref_count);
|
||||
gf_proc_dump_write("translator", "%s", my_frame.this->name);
|
||||
gf_proc_dump_write("complete", "%d", my_frame.complete);
|
||||
if (my_frame.parent)
|
||||
gf_proc_dump_write("parent", "%s", my_frame.parent->this->name);
|
||||
|
||||
if (my_frame.parent)
|
||||
gf_proc_dump_write("parent", "%s", my_frame.parent->this->name);
|
||||
if (my_frame.wind_from)
|
||||
gf_proc_dump_write("wind_from", "%s", my_frame.wind_from);
|
||||
|
||||
if (my_frame.wind_from)
|
||||
gf_proc_dump_write("wind_from", "%s", my_frame.wind_from);
|
||||
if (my_frame.wind_to)
|
||||
gf_proc_dump_write("wind_to", "%s", my_frame.wind_to);
|
||||
|
||||
if (my_frame.wind_to)
|
||||
gf_proc_dump_write("wind_to", "%s", my_frame.wind_to);
|
||||
if (my_frame.unwind_from)
|
||||
gf_proc_dump_write("unwind_from", "%s", my_frame.unwind_from);
|
||||
|
||||
if (my_frame.unwind_from)
|
||||
gf_proc_dump_write("unwind_from", "%s", my_frame.unwind_from);
|
||||
if (my_frame.unwind_to)
|
||||
gf_proc_dump_write("unwind_to", "%s", my_frame.unwind_to);
|
||||
|
||||
if (my_frame.unwind_to)
|
||||
gf_proc_dump_write("unwind_to", "%s", my_frame.unwind_to);
|
||||
|
||||
ret = 0;
|
||||
ret = 0;
|
||||
out:
|
||||
if (ret) {
|
||||
gf_proc_dump_write("Unable to dump the frame information",
|
||||
"(Lock acquisition failed) %p", my_frame);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
gf_proc_dump_call_stack (call_stack_t *call_stack, const char *key_buf,...)
|
||||
{
|
||||
char prefix[GF_DUMP_MAX_BUF_LEN];
|
||||
va_list ap;
|
||||
call_frame_t *trav;
|
||||
int32_t i = 1, cnt = 0;
|
||||
char timestr[256] = {0,};
|
||||
int len;
|
||||
|
||||
if (!call_stack)
|
||||
return;
|
||||
|
||||
GF_ASSERT (key_buf);
|
||||
|
||||
va_start(ap, key_buf);
|
||||
vsnprintf(prefix, GF_DUMP_MAX_BUF_LEN, key_buf, ap);
|
||||
va_end(ap);
|
||||
|
||||
cnt = call_frames_count (call_stack);
|
||||
gf_time_fmt (timestr, sizeof (timestr), call_stack->tv.tv_sec,
|
||||
gf_timefmt_FT);
|
||||
len = strlen (timestr);
|
||||
snprintf (timestr + len, sizeof (timestr) - len,
|
||||
".%"GF_PRI_SNSECONDS, call_stack->tv.tv_nsec);
|
||||
gf_proc_dump_write("callstack-creation-time", "%s", timestr);
|
||||
|
||||
gf_proc_dump_write("stack", "%p", call_stack);
|
||||
gf_proc_dump_write("uid", "%d", call_stack->uid);
|
||||
gf_proc_dump_write("gid", "%d", call_stack->gid);
|
||||
gf_proc_dump_write("pid", "%d", call_stack->pid);
|
||||
gf_proc_dump_write("unique", "%Ld", call_stack->unique);
|
||||
gf_proc_dump_write("lk-owner", "%s", lkowner_utoa (&call_stack->lk_owner));
|
||||
gf_proc_dump_write("ctime", "%lld.%"GF_PRI_SNSECONDS,
|
||||
call_stack->tv.tv_sec, call_stack->tv.tv_nsec);
|
||||
|
||||
if (call_stack->type == GF_OP_TYPE_FOP)
|
||||
gf_proc_dump_write("op", "%s",
|
||||
(char *)gf_fop_list[call_stack->op]);
|
||||
else
|
||||
gf_proc_dump_write("op", "stack");
|
||||
|
||||
gf_proc_dump_write("type", "%d", call_stack->type);
|
||||
gf_proc_dump_write("cnt", "%d", cnt);
|
||||
|
||||
list_for_each_entry (trav, &call_stack->myframes, frames) {
|
||||
gf_proc_dump_add_section("%s.frame.%d", prefix, i);
|
||||
gf_proc_dump_call_frame(trav, "%s.frame.%d", prefix, i);
|
||||
i++;
|
||||
}
|
||||
if (ret) {
|
||||
gf_proc_dump_write("Unable to dump the frame information",
|
||||
"(Lock acquisition failed) %p", my_frame);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gf_proc_dump_pending_frames (call_pool_t *call_pool)
|
||||
gf_proc_dump_call_stack(call_stack_t *call_stack, const char *key_buf, ...)
|
||||
{
|
||||
char prefix[GF_DUMP_MAX_BUF_LEN];
|
||||
va_list ap;
|
||||
call_frame_t *trav;
|
||||
int32_t i = 1, cnt = 0;
|
||||
char timestr[256] = {
|
||||
0,
|
||||
};
|
||||
int len;
|
||||
|
||||
call_stack_t *trav = NULL;
|
||||
int i = 1;
|
||||
int ret = -1;
|
||||
gf_boolean_t section_added = _gf_false;
|
||||
if (!call_stack)
|
||||
return;
|
||||
|
||||
if (!call_pool)
|
||||
return;
|
||||
GF_ASSERT(key_buf);
|
||||
|
||||
ret = TRY_LOCK (&(call_pool->lock));
|
||||
if (ret)
|
||||
goto out;
|
||||
va_start(ap, key_buf);
|
||||
vsnprintf(prefix, GF_DUMP_MAX_BUF_LEN, key_buf, ap);
|
||||
va_end(ap);
|
||||
|
||||
cnt = call_frames_count(call_stack);
|
||||
gf_time_fmt(timestr, sizeof(timestr), call_stack->tv.tv_sec, gf_timefmt_FT);
|
||||
len = strlen(timestr);
|
||||
snprintf(timestr + len, sizeof(timestr) - len, ".%" GF_PRI_SNSECONDS,
|
||||
call_stack->tv.tv_nsec);
|
||||
gf_proc_dump_write("callstack-creation-time", "%s", timestr);
|
||||
|
||||
gf_proc_dump_add_section("global.callpool");
|
||||
section_added = _gf_true;
|
||||
gf_proc_dump_write("callpool_address","%p", call_pool);
|
||||
gf_proc_dump_write("callpool.cnt","%d", call_pool->cnt);
|
||||
gf_proc_dump_write("stack", "%p", call_stack);
|
||||
gf_proc_dump_write("uid", "%d", call_stack->uid);
|
||||
gf_proc_dump_write("gid", "%d", call_stack->gid);
|
||||
gf_proc_dump_write("pid", "%d", call_stack->pid);
|
||||
gf_proc_dump_write("unique", "%Ld", call_stack->unique);
|
||||
gf_proc_dump_write("lk-owner", "%s", lkowner_utoa(&call_stack->lk_owner));
|
||||
gf_proc_dump_write("ctime", "%lld.%" GF_PRI_SNSECONDS,
|
||||
call_stack->tv.tv_sec, call_stack->tv.tv_nsec);
|
||||
|
||||
if (call_stack->type == GF_OP_TYPE_FOP)
|
||||
gf_proc_dump_write("op", "%s", (char *)gf_fop_list[call_stack->op]);
|
||||
else
|
||||
gf_proc_dump_write("op", "stack");
|
||||
|
||||
list_for_each_entry (trav, &call_pool->all_frames, all_frames) {
|
||||
gf_proc_dump_add_section("global.callpool.stack.%d",i);
|
||||
gf_proc_dump_call_stack(trav, "global.callpool.stack.%d", i);
|
||||
i++;
|
||||
}
|
||||
UNLOCK (&(call_pool->lock));
|
||||
gf_proc_dump_write("type", "%d", call_stack->type);
|
||||
gf_proc_dump_write("cnt", "%d", cnt);
|
||||
|
||||
ret = 0;
|
||||
list_for_each_entry(trav, &call_stack->myframes, frames)
|
||||
{
|
||||
gf_proc_dump_add_section("%s.frame.%d", prefix, i);
|
||||
gf_proc_dump_call_frame(trav, "%s.frame.%d", prefix, i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gf_proc_dump_pending_frames(call_pool_t *call_pool)
|
||||
{
|
||||
call_stack_t *trav = NULL;
|
||||
int i = 1;
|
||||
int ret = -1;
|
||||
gf_boolean_t section_added = _gf_false;
|
||||
|
||||
if (!call_pool)
|
||||
return;
|
||||
|
||||
ret = TRY_LOCK(&(call_pool->lock));
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
gf_proc_dump_add_section("global.callpool");
|
||||
section_added = _gf_true;
|
||||
gf_proc_dump_write("callpool_address", "%p", call_pool);
|
||||
gf_proc_dump_write("callpool.cnt", "%d", call_pool->cnt);
|
||||
|
||||
list_for_each_entry(trav, &call_pool->all_frames, all_frames)
|
||||
{
|
||||
gf_proc_dump_add_section("global.callpool.stack.%d", i);
|
||||
gf_proc_dump_call_stack(trav, "global.callpool.stack.%d", i);
|
||||
i++;
|
||||
}
|
||||
UNLOCK(&(call_pool->lock));
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
if (ret) {
|
||||
if (_gf_false == section_added)
|
||||
gf_proc_dump_add_section("global.callpool");
|
||||
gf_proc_dump_write("Unable to dump the callpool",
|
||||
"(Lock acquisition failed) %p",
|
||||
call_pool);
|
||||
}
|
||||
return;
|
||||
if (ret) {
|
||||
if (_gf_false == section_added)
|
||||
gf_proc_dump_add_section("global.callpool");
|
||||
gf_proc_dump_write("Unable to dump the callpool",
|
||||
"(Lock acquisition failed) %p", call_pool);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
gf_proc_dump_call_frame_to_dict (call_frame_t *call_frame,
|
||||
char *prefix, dict_t *dict)
|
||||
gf_proc_dump_call_frame_to_dict(call_frame_t *call_frame, char *prefix,
|
||||
dict_t *dict)
|
||||
{
|
||||
int ret = -1;
|
||||
char key[GF_DUMP_MAX_BUF_LEN] = {0,};
|
||||
char msg[GF_DUMP_MAX_BUF_LEN] = {0,};
|
||||
call_frame_t tmp_frame = {0,};
|
||||
|
||||
if (!call_frame || !dict)
|
||||
return;
|
||||
|
||||
ret = TRY_LOCK (&call_frame->lock);
|
||||
if (ret)
|
||||
return;
|
||||
memcpy (&tmp_frame, call_frame, sizeof (tmp_frame));
|
||||
UNLOCK (&call_frame->lock);
|
||||
|
||||
snprintf (key, sizeof (key), "%s.refcount", prefix);
|
||||
ret = dict_set_int32 (dict, key, tmp_frame.ref_count);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
snprintf (key, sizeof (key), "%s.translator", prefix);
|
||||
ret = dict_set_dynstr (dict, key, gf_strdup (tmp_frame.this->name));
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
snprintf (key, sizeof (key), "%s.complete", prefix);
|
||||
ret = dict_set_int32 (dict, key, tmp_frame.complete);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
if (tmp_frame.root->ctx->measure_latency) {
|
||||
snprintf (key, sizeof (key), "%s.timings", prefix);
|
||||
snprintf (msg, sizeof (msg), "%ld.%"GF_PRI_SNSECONDS
|
||||
" -> %ld.%"GF_PRI_SNSECONDS,
|
||||
tmp_frame.begin.tv_sec, tmp_frame.begin.tv_nsec,
|
||||
tmp_frame.end.tv_sec, tmp_frame.end.tv_nsec);
|
||||
ret = dict_set_str (dict, key, msg);
|
||||
if (ret)
|
||||
return;
|
||||
}
|
||||
|
||||
if (tmp_frame.parent) {
|
||||
snprintf (key, sizeof (key), "%s.parent", prefix);
|
||||
ret = dict_set_dynstr (dict, key,
|
||||
gf_strdup (tmp_frame.parent->this->name));
|
||||
if (ret)
|
||||
return;
|
||||
}
|
||||
|
||||
if (tmp_frame.wind_from) {
|
||||
snprintf (key, sizeof (key), "%s.windfrom", prefix);
|
||||
ret = dict_set_dynstr (dict, key,
|
||||
gf_strdup (tmp_frame.wind_from));
|
||||
if (ret)
|
||||
return;
|
||||
}
|
||||
|
||||
if (tmp_frame.wind_to) {
|
||||
snprintf (key, sizeof (key), "%s.windto", prefix);
|
||||
ret = dict_set_dynstr (dict, key,
|
||||
gf_strdup (tmp_frame.wind_to));
|
||||
if (ret)
|
||||
return;
|
||||
}
|
||||
|
||||
if (tmp_frame.unwind_from) {
|
||||
snprintf (key, sizeof (key), "%s.unwindfrom", prefix);
|
||||
ret = dict_set_dynstr (dict, key,
|
||||
gf_strdup (tmp_frame.unwind_from));
|
||||
if (ret)
|
||||
return;
|
||||
}
|
||||
|
||||
if (tmp_frame.unwind_to) {
|
||||
snprintf (key, sizeof (key), "%s.unwind_to", prefix);
|
||||
ret = dict_set_dynstr (dict, key,
|
||||
gf_strdup (tmp_frame.unwind_to));
|
||||
}
|
||||
int ret = -1;
|
||||
char key[GF_DUMP_MAX_BUF_LEN] = {
|
||||
0,
|
||||
};
|
||||
char msg[GF_DUMP_MAX_BUF_LEN] = {
|
||||
0,
|
||||
};
|
||||
call_frame_t tmp_frame = {
|
||||
0,
|
||||
};
|
||||
|
||||
if (!call_frame || !dict)
|
||||
return;
|
||||
|
||||
ret = TRY_LOCK(&call_frame->lock);
|
||||
if (ret)
|
||||
return;
|
||||
memcpy(&tmp_frame, call_frame, sizeof(tmp_frame));
|
||||
UNLOCK(&call_frame->lock);
|
||||
|
||||
snprintf(key, sizeof(key), "%s.refcount", prefix);
|
||||
ret = dict_set_int32(dict, key, tmp_frame.ref_count);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
snprintf(key, sizeof(key), "%s.translator", prefix);
|
||||
ret = dict_set_dynstr(dict, key, gf_strdup(tmp_frame.this->name));
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
snprintf(key, sizeof(key), "%s.complete", prefix);
|
||||
ret = dict_set_int32(dict, key, tmp_frame.complete);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
if (tmp_frame.root->ctx->measure_latency) {
|
||||
snprintf(key, sizeof(key), "%s.timings", prefix);
|
||||
snprintf(msg, sizeof(msg),
|
||||
"%ld.%" GF_PRI_SNSECONDS " -> %ld.%" GF_PRI_SNSECONDS,
|
||||
tmp_frame.begin.tv_sec, tmp_frame.begin.tv_nsec,
|
||||
tmp_frame.end.tv_sec, tmp_frame.end.tv_nsec);
|
||||
ret = dict_set_str(dict, key, msg);
|
||||
if (ret)
|
||||
return;
|
||||
}
|
||||
|
||||
if (tmp_frame.parent) {
|
||||
snprintf(key, sizeof(key), "%s.parent", prefix);
|
||||
ret = dict_set_dynstr(dict, key,
|
||||
gf_strdup(tmp_frame.parent->this->name));
|
||||
if (ret)
|
||||
return;
|
||||
}
|
||||
|
||||
if (tmp_frame.wind_from) {
|
||||
snprintf(key, sizeof(key), "%s.windfrom", prefix);
|
||||
ret = dict_set_dynstr(dict, key, gf_strdup(tmp_frame.wind_from));
|
||||
if (ret)
|
||||
return;
|
||||
}
|
||||
|
||||
if (tmp_frame.wind_to) {
|
||||
snprintf(key, sizeof(key), "%s.windto", prefix);
|
||||
ret = dict_set_dynstr(dict, key, gf_strdup(tmp_frame.wind_to));
|
||||
if (ret)
|
||||
return;
|
||||
}
|
||||
|
||||
if (tmp_frame.unwind_from) {
|
||||
snprintf(key, sizeof(key), "%s.unwindfrom", prefix);
|
||||
ret = dict_set_dynstr(dict, key, gf_strdup(tmp_frame.unwind_from));
|
||||
if (ret)
|
||||
return;
|
||||
}
|
||||
|
||||
if (tmp_frame.unwind_to) {
|
||||
snprintf(key, sizeof(key), "%s.unwind_to", prefix);
|
||||
ret = dict_set_dynstr(dict, key, gf_strdup(tmp_frame.unwind_to));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
gf_proc_dump_call_stack_to_dict (call_stack_t *call_stack,
|
||||
char *prefix, dict_t *dict)
|
||||
gf_proc_dump_call_stack_to_dict(call_stack_t *call_stack, char *prefix,
|
||||
dict_t *dict)
|
||||
{
|
||||
int ret = -1;
|
||||
char key[GF_DUMP_MAX_BUF_LEN] = {0,};
|
||||
call_frame_t *trav = NULL;
|
||||
int i = 0;
|
||||
int count = 0;
|
||||
|
||||
if (!call_stack || !dict)
|
||||
return;
|
||||
|
||||
count = call_frames_count (call_stack);
|
||||
snprintf (key, sizeof (key), "%s.uid", prefix);
|
||||
ret = dict_set_int32 (dict, key, call_stack->uid);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
snprintf (key, sizeof (key), "%s.gid", prefix);
|
||||
ret = dict_set_int32 (dict, key, call_stack->gid);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
snprintf (key, sizeof (key), "%s.pid", prefix);
|
||||
ret = dict_set_int32 (dict, key, call_stack->pid);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
snprintf (key, sizeof (key), "%s.unique", prefix);
|
||||
ret = dict_set_uint64 (dict, key, call_stack->unique);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
snprintf (key, sizeof (key), "%s.op", prefix);
|
||||
if (call_stack->type == GF_OP_TYPE_FOP)
|
||||
ret = dict_set_str (dict, key,
|
||||
(char *)gf_fop_list[call_stack->op]);
|
||||
else
|
||||
ret = dict_set_str (dict, key, "other");
|
||||
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
snprintf (key, sizeof (key), "%s.type", prefix);
|
||||
ret = dict_set_int32 (dict, key, call_stack->type);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
snprintf (key, sizeof (key), "%s.count", prefix);
|
||||
ret = dict_set_int32 (dict, key, count);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
list_for_each_entry (trav, &call_stack->myframes, frames) {
|
||||
snprintf (key, sizeof (key), "%s.frame%d",
|
||||
prefix, i);
|
||||
gf_proc_dump_call_frame_to_dict (trav, key, dict);
|
||||
i++;
|
||||
}
|
||||
int ret = -1;
|
||||
char key[GF_DUMP_MAX_BUF_LEN] = {
|
||||
0,
|
||||
};
|
||||
call_frame_t *trav = NULL;
|
||||
int i = 0;
|
||||
int count = 0;
|
||||
|
||||
if (!call_stack || !dict)
|
||||
return;
|
||||
|
||||
count = call_frames_count(call_stack);
|
||||
snprintf(key, sizeof(key), "%s.uid", prefix);
|
||||
ret = dict_set_int32(dict, key, call_stack->uid);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
snprintf(key, sizeof(key), "%s.gid", prefix);
|
||||
ret = dict_set_int32(dict, key, call_stack->gid);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
snprintf(key, sizeof(key), "%s.pid", prefix);
|
||||
ret = dict_set_int32(dict, key, call_stack->pid);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
snprintf(key, sizeof(key), "%s.unique", prefix);
|
||||
ret = dict_set_uint64(dict, key, call_stack->unique);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
snprintf(key, sizeof(key), "%s.op", prefix);
|
||||
if (call_stack->type == GF_OP_TYPE_FOP)
|
||||
ret = dict_set_str(dict, key, (char *)gf_fop_list[call_stack->op]);
|
||||
else
|
||||
ret = dict_set_str(dict, key, "other");
|
||||
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
snprintf(key, sizeof(key), "%s.type", prefix);
|
||||
ret = dict_set_int32(dict, key, call_stack->type);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
snprintf(key, sizeof(key), "%s.count", prefix);
|
||||
ret = dict_set_int32(dict, key, count);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
list_for_each_entry(trav, &call_stack->myframes, frames)
|
||||
{
|
||||
snprintf(key, sizeof(key), "%s.frame%d", prefix, i);
|
||||
gf_proc_dump_call_frame_to_dict(trav, key, dict);
|
||||
i++;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
gf_proc_dump_pending_frames_to_dict (call_pool_t *call_pool, dict_t *dict)
|
||||
gf_proc_dump_pending_frames_to_dict(call_pool_t *call_pool, dict_t *dict)
|
||||
{
|
||||
int ret = -1;
|
||||
call_stack_t *trav = NULL;
|
||||
char key[GF_DUMP_MAX_BUF_LEN] = {0,};
|
||||
int i = 0;
|
||||
int ret = -1;
|
||||
call_stack_t *trav = NULL;
|
||||
char key[GF_DUMP_MAX_BUF_LEN] = {
|
||||
0,
|
||||
};
|
||||
int i = 0;
|
||||
|
||||
if (!call_pool || !dict)
|
||||
return;
|
||||
if (!call_pool || !dict)
|
||||
return;
|
||||
|
||||
ret = TRY_LOCK (&call_pool->lock);
|
||||
if (ret) {
|
||||
gf_msg (THIS->name, GF_LOG_WARNING, errno,
|
||||
LG_MSG_LOCK_FAILURE, "Unable to dump call "
|
||||
"pool to dict.");
|
||||
return;
|
||||
}
|
||||
ret = TRY_LOCK(&call_pool->lock);
|
||||
if (ret) {
|
||||
gf_msg(THIS->name, GF_LOG_WARNING, errno, LG_MSG_LOCK_FAILURE,
|
||||
"Unable to dump call "
|
||||
"pool to dict.");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = dict_set_int32 (dict, "callpool.count", call_pool->cnt);
|
||||
if (ret)
|
||||
goto out;
|
||||
ret = dict_set_int32(dict, "callpool.count", call_pool->cnt);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
list_for_each_entry (trav, &call_pool->all_frames, all_frames) {
|
||||
snprintf (key, sizeof (key), "callpool.stack%d", i);
|
||||
gf_proc_dump_call_stack_to_dict (trav, key, dict);
|
||||
i++;
|
||||
}
|
||||
list_for_each_entry(trav, &call_pool->all_frames, all_frames)
|
||||
{
|
||||
snprintf(key, sizeof(key), "callpool.stack%d", i);
|
||||
gf_proc_dump_call_stack_to_dict(trav, key, dict);
|
||||
i++;
|
||||
}
|
||||
|
||||
out:
|
||||
UNLOCK (&call_pool->lock);
|
||||
UNLOCK(&call_pool->lock);
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
gf_boolean_t
|
||||
__is_fuse_call (call_frame_t *frame)
|
||||
__is_fuse_call(call_frame_t *frame)
|
||||
{
|
||||
gf_boolean_t is_fuse_call = _gf_false;
|
||||
GF_ASSERT (frame);
|
||||
GF_ASSERT (frame->root);
|
||||
gf_boolean_t is_fuse_call = _gf_false;
|
||||
GF_ASSERT(frame);
|
||||
GF_ASSERT(frame->root);
|
||||
|
||||
if (NFS_PID != frame->root->pid)
|
||||
is_fuse_call = _gf_true;
|
||||
return is_fuse_call;
|
||||
if (NFS_PID != frame->root->pid)
|
||||
is_fuse_call = _gf_true;
|
||||
return is_fuse_call;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -16,77 +16,78 @@
|
||||
#include "common-utils.h"
|
||||
|
||||
strfd_t *
|
||||
strfd_open ()
|
||||
strfd_open()
|
||||
{
|
||||
strfd_t *strfd = NULL;
|
||||
strfd_t *strfd = NULL;
|
||||
|
||||
strfd = GF_CALLOC(1, sizeof(*strfd), gf_common_mt_strfd_t);
|
||||
strfd = GF_CALLOC(1, sizeof(*strfd), gf_common_mt_strfd_t);
|
||||
|
||||
return strfd;
|
||||
return strfd;
|
||||
}
|
||||
|
||||
int
|
||||
strvprintf (strfd_t *strfd, const char *fmt, va_list ap)
|
||||
strvprintf(strfd_t *strfd, const char *fmt, va_list ap)
|
||||
{
|
||||
char *str = NULL;
|
||||
int size = 0;
|
||||
char *str = NULL;
|
||||
int size = 0;
|
||||
|
||||
size = vasprintf (&str, fmt, ap);
|
||||
|
||||
if (size < 0)
|
||||
return size;
|
||||
|
||||
if (!strfd->alloc_size) {
|
||||
strfd->data = GF_CALLOC (max(size + 1, 4096), 1,
|
||||
gf_common_mt_strfd_data_t);
|
||||
if (!strfd->data) {
|
||||
free (str); /* NOT GF_FREE */
|
||||
return -1;
|
||||
}
|
||||
strfd->alloc_size = max(size + 1, 4096);
|
||||
}
|
||||
|
||||
if (strfd->alloc_size <= (strfd->size + size)) {
|
||||
char *tmp_ptr = NULL;
|
||||
int new_size = max ((strfd->alloc_size * 2),
|
||||
gf_roundup_next_power_of_two (strfd->size + size + 1));
|
||||
tmp_ptr = GF_REALLOC (strfd->data, new_size);
|
||||
if (!tmp_ptr) {
|
||||
free (str); /* NOT GF_FREE */
|
||||
return -1;
|
||||
}
|
||||
strfd->alloc_size = new_size;
|
||||
strfd->data = tmp_ptr;
|
||||
}
|
||||
|
||||
/* Copy the trailing '\0', but do not account for it in ->size.
|
||||
This allows safe use of strfd->data as a string. */
|
||||
memcpy (strfd->data + strfd->size, str, size + 1);
|
||||
strfd->size += size;
|
||||
|
||||
free (str); /* NOT GF_FREE */
|
||||
size = vasprintf(&str, fmt, ap);
|
||||
|
||||
if (size < 0)
|
||||
return size;
|
||||
|
||||
if (!strfd->alloc_size) {
|
||||
strfd->data = GF_CALLOC(max(size + 1, 4096), 1,
|
||||
gf_common_mt_strfd_data_t);
|
||||
if (!strfd->data) {
|
||||
free(str); /* NOT GF_FREE */
|
||||
return -1;
|
||||
}
|
||||
strfd->alloc_size = max(size + 1, 4096);
|
||||
}
|
||||
|
||||
if (strfd->alloc_size <= (strfd->size + size)) {
|
||||
char *tmp_ptr = NULL;
|
||||
int new_size = max(
|
||||
(strfd->alloc_size * 2),
|
||||
gf_roundup_next_power_of_two(strfd->size + size + 1));
|
||||
tmp_ptr = GF_REALLOC(strfd->data, new_size);
|
||||
if (!tmp_ptr) {
|
||||
free(str); /* NOT GF_FREE */
|
||||
return -1;
|
||||
}
|
||||
strfd->alloc_size = new_size;
|
||||
strfd->data = tmp_ptr;
|
||||
}
|
||||
|
||||
/* Copy the trailing '\0', but do not account for it in ->size.
|
||||
This allows safe use of strfd->data as a string. */
|
||||
memcpy(strfd->data + strfd->size, str, size + 1);
|
||||
strfd->size += size;
|
||||
|
||||
free(str); /* NOT GF_FREE */
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
strprintf (strfd_t *strfd, const char *fmt, ...)
|
||||
strprintf(strfd_t *strfd, const char *fmt, ...)
|
||||
{
|
||||
int ret = 0;
|
||||
va_list ap;
|
||||
int ret = 0;
|
||||
va_list ap;
|
||||
|
||||
va_start (ap, fmt);
|
||||
ret = strvprintf (strfd, fmt, ap);
|
||||
va_end (ap);
|
||||
va_start(ap, fmt);
|
||||
ret = strvprintf(strfd, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
strfd_close (strfd_t *strfd)
|
||||
strfd_close(strfd_t *strfd)
|
||||
{
|
||||
GF_FREE (strfd->data);
|
||||
GF_FREE (strfd);
|
||||
GF_FREE(strfd->data);
|
||||
GF_FREE(strfd);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -27,93 +27,93 @@
|
||||
#include "throttle-tbf.h"
|
||||
|
||||
typedef struct tbf_throttle {
|
||||
char done;
|
||||
char done;
|
||||
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
|
||||
unsigned long tokens;
|
||||
unsigned long tokens;
|
||||
|
||||
struct list_head list;
|
||||
struct list_head list;
|
||||
} tbf_throttle_t;
|
||||
|
||||
static tbf_throttle_t *
|
||||
tbf_init_throttle (unsigned long tokens_required)
|
||||
tbf_init_throttle(unsigned long tokens_required)
|
||||
{
|
||||
tbf_throttle_t *throttle = NULL;
|
||||
tbf_throttle_t *throttle = NULL;
|
||||
|
||||
throttle = GF_CALLOC (1, sizeof (*throttle),
|
||||
gf_common_mt_tbf_throttle_t);
|
||||
if (!throttle)
|
||||
return NULL;
|
||||
throttle = GF_CALLOC(1, sizeof(*throttle), gf_common_mt_tbf_throttle_t);
|
||||
if (!throttle)
|
||||
return NULL;
|
||||
|
||||
throttle->done = 0;
|
||||
throttle->tokens = tokens_required;
|
||||
INIT_LIST_HEAD (&throttle->list);
|
||||
throttle->done = 0;
|
||||
throttle->tokens = tokens_required;
|
||||
INIT_LIST_HEAD(&throttle->list);
|
||||
|
||||
(void) pthread_mutex_init (&throttle->mutex, NULL);
|
||||
(void) pthread_cond_init (&throttle->cond, NULL);
|
||||
(void)pthread_mutex_init(&throttle->mutex, NULL);
|
||||
(void)pthread_cond_init(&throttle->cond, NULL);
|
||||
|
||||
return throttle;
|
||||
return throttle;
|
||||
}
|
||||
|
||||
void
|
||||
_tbf_dispatch_queued (tbf_bucket_t *bucket)
|
||||
_tbf_dispatch_queued(tbf_bucket_t *bucket)
|
||||
{
|
||||
gf_boolean_t xcont = _gf_false;
|
||||
tbf_throttle_t *tmp = NULL;
|
||||
tbf_throttle_t *throttle = NULL;
|
||||
gf_boolean_t xcont = _gf_false;
|
||||
tbf_throttle_t *tmp = NULL;
|
||||
tbf_throttle_t *throttle = NULL;
|
||||
|
||||
list_for_each_entry_safe (throttle, tmp, &bucket->queued, list) {
|
||||
list_for_each_entry_safe(throttle, tmp, &bucket->queued, list)
|
||||
{
|
||||
pthread_mutex_lock(&throttle->mutex);
|
||||
{
|
||||
if (bucket->tokens < throttle->tokens) {
|
||||
xcont = _gf_true;
|
||||
goto unblock;
|
||||
}
|
||||
|
||||
pthread_mutex_lock (&throttle->mutex);
|
||||
{
|
||||
if (bucket->tokens < throttle->tokens) {
|
||||
xcont = _gf_true;
|
||||
goto unblock;
|
||||
}
|
||||
/* this request can now be serviced */
|
||||
throttle->done = 1;
|
||||
list_del_init(&throttle->list);
|
||||
|
||||
/* this request can now be serviced */
|
||||
throttle->done = 1;
|
||||
list_del_init (&throttle->list);
|
||||
|
||||
bucket->tokens -= throttle->tokens;
|
||||
pthread_cond_signal (&throttle->cond);
|
||||
}
|
||||
unblock:
|
||||
pthread_mutex_unlock (&throttle->mutex);
|
||||
if (xcont)
|
||||
break;
|
||||
bucket->tokens -= throttle->tokens;
|
||||
pthread_cond_signal(&throttle->cond);
|
||||
}
|
||||
unblock:
|
||||
pthread_mutex_unlock(&throttle->mutex);
|
||||
if (xcont)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void *tbf_tokengenerator (void *arg)
|
||||
void *
|
||||
tbf_tokengenerator(void *arg)
|
||||
{
|
||||
unsigned long tokenrate = 0;
|
||||
unsigned long maxtokens = 0;
|
||||
unsigned long token_gen_interval = 0;
|
||||
tbf_bucket_t *bucket = arg;
|
||||
unsigned long tokenrate = 0;
|
||||
unsigned long maxtokens = 0;
|
||||
unsigned long token_gen_interval = 0;
|
||||
tbf_bucket_t *bucket = arg;
|
||||
|
||||
tokenrate = bucket->tokenrate;
|
||||
maxtokens = bucket->maxtokens;
|
||||
token_gen_interval = bucket->token_gen_interval;
|
||||
tokenrate = bucket->tokenrate;
|
||||
maxtokens = bucket->maxtokens;
|
||||
token_gen_interval = bucket->token_gen_interval;
|
||||
|
||||
while (1) {
|
||||
usleep (token_gen_interval);
|
||||
while (1) {
|
||||
usleep(token_gen_interval);
|
||||
|
||||
LOCK (&bucket->lock);
|
||||
{
|
||||
bucket->tokens += tokenrate;
|
||||
if (bucket->tokens > maxtokens)
|
||||
bucket->tokens = maxtokens;
|
||||
LOCK(&bucket->lock);
|
||||
{
|
||||
bucket->tokens += tokenrate;
|
||||
if (bucket->tokens > maxtokens)
|
||||
bucket->tokens = maxtokens;
|
||||
|
||||
if (!list_empty (&bucket->queued))
|
||||
_tbf_dispatch_queued (bucket);
|
||||
}
|
||||
UNLOCK (&bucket->lock);
|
||||
if (!list_empty(&bucket->queued))
|
||||
_tbf_dispatch_queued(bucket);
|
||||
}
|
||||
UNLOCK(&bucket->lock);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -122,170 +122,169 @@ void *tbf_tokengenerator (void *arg)
|
||||
* updated _after_ all the required variables are initialized.
|
||||
*/
|
||||
static int32_t
|
||||
tbf_init_bucket (tbf_t *tbf, tbf_opspec_t *spec)
|
||||
tbf_init_bucket(tbf_t *tbf, tbf_opspec_t *spec)
|
||||
{
|
||||
int ret = 0;
|
||||
tbf_bucket_t *curr = NULL;
|
||||
tbf_bucket_t **bucket = NULL;
|
||||
int ret = 0;
|
||||
tbf_bucket_t *curr = NULL;
|
||||
tbf_bucket_t **bucket = NULL;
|
||||
|
||||
GF_ASSERT (spec->op >= TBF_OP_MIN);
|
||||
GF_ASSERT (spec->op <= TBF_OP_MAX);
|
||||
GF_ASSERT(spec->op >= TBF_OP_MIN);
|
||||
GF_ASSERT(spec->op <= TBF_OP_MAX);
|
||||
|
||||
/* no rate? no throttling. */
|
||||
if (!spec->rate)
|
||||
return 0;
|
||||
|
||||
bucket = tbf->bucket + spec->op;
|
||||
|
||||
curr = GF_CALLOC (1, sizeof (*curr), gf_common_mt_tbf_bucket_t);
|
||||
if (!curr)
|
||||
goto error_return;
|
||||
|
||||
LOCK_INIT (&curr->lock);
|
||||
INIT_LIST_HEAD (&curr->queued);
|
||||
|
||||
curr->tokens = 0;
|
||||
curr->tokenrate = spec->rate;
|
||||
curr->maxtokens = spec->maxlimit;
|
||||
curr->token_gen_interval = spec->token_gen_interval;
|
||||
|
||||
ret = gf_thread_create (&curr->tokener,
|
||||
NULL, tbf_tokengenerator, curr, "tbfclock");
|
||||
if (ret != 0)
|
||||
goto freemem;
|
||||
|
||||
*bucket = curr;
|
||||
/* no rate? no throttling. */
|
||||
if (!spec->rate)
|
||||
return 0;
|
||||
|
||||
freemem:
|
||||
LOCK_DESTROY (&curr->lock);
|
||||
GF_FREE (curr);
|
||||
error_return:
|
||||
return -1;
|
||||
bucket = tbf->bucket + spec->op;
|
||||
|
||||
curr = GF_CALLOC(1, sizeof(*curr), gf_common_mt_tbf_bucket_t);
|
||||
if (!curr)
|
||||
goto error_return;
|
||||
|
||||
LOCK_INIT(&curr->lock);
|
||||
INIT_LIST_HEAD(&curr->queued);
|
||||
|
||||
curr->tokens = 0;
|
||||
curr->tokenrate = spec->rate;
|
||||
curr->maxtokens = spec->maxlimit;
|
||||
curr->token_gen_interval = spec->token_gen_interval;
|
||||
|
||||
ret = gf_thread_create(&curr->tokener, NULL, tbf_tokengenerator, curr,
|
||||
"tbfclock");
|
||||
if (ret != 0)
|
||||
goto freemem;
|
||||
|
||||
*bucket = curr;
|
||||
return 0;
|
||||
|
||||
freemem:
|
||||
LOCK_DESTROY(&curr->lock);
|
||||
GF_FREE(curr);
|
||||
error_return:
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define TBF_ALLOC_SIZE \
|
||||
(sizeof (tbf_t) + (TBF_OP_MAX * sizeof (tbf_bucket_t)))
|
||||
#define TBF_ALLOC_SIZE (sizeof(tbf_t) + (TBF_OP_MAX * sizeof(tbf_bucket_t)))
|
||||
|
||||
tbf_t *
|
||||
tbf_init (tbf_opspec_t *tbfspec, unsigned int count)
|
||||
tbf_init(tbf_opspec_t *tbfspec, unsigned int count)
|
||||
{
|
||||
int32_t i = 0;
|
||||
int32_t ret = 0;
|
||||
tbf_t *tbf = NULL;
|
||||
tbf_opspec_t *opspec = NULL;
|
||||
int32_t i = 0;
|
||||
int32_t ret = 0;
|
||||
tbf_t *tbf = NULL;
|
||||
tbf_opspec_t *opspec = NULL;
|
||||
|
||||
tbf = GF_CALLOC (1, TBF_ALLOC_SIZE, gf_common_mt_tbf_t);
|
||||
if (!tbf)
|
||||
goto error_return;
|
||||
tbf = GF_CALLOC(1, TBF_ALLOC_SIZE, gf_common_mt_tbf_t);
|
||||
if (!tbf)
|
||||
goto error_return;
|
||||
|
||||
tbf->bucket = (tbf_bucket_t **) ((char *)tbf + sizeof (*tbf));
|
||||
for (i = 0; i < TBF_OP_MAX; i++) {
|
||||
*(tbf->bucket + i) = NULL;
|
||||
}
|
||||
tbf->bucket = (tbf_bucket_t **)((char *)tbf + sizeof(*tbf));
|
||||
for (i = 0; i < TBF_OP_MAX; i++) {
|
||||
*(tbf->bucket + i) = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
opspec = tbfspec + i;
|
||||
|
||||
ret = tbf_init_bucket (tbf, opspec);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
for (i = 0; i < count; i++) {
|
||||
opspec = tbfspec + i;
|
||||
|
||||
ret = tbf_init_bucket(tbf, opspec);
|
||||
if (ret)
|
||||
goto error_return;
|
||||
break;
|
||||
}
|
||||
|
||||
return tbf;
|
||||
if (ret)
|
||||
goto error_return;
|
||||
|
||||
error_return:
|
||||
return NULL;
|
||||
return tbf;
|
||||
|
||||
error_return:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
tbf_mod_bucket (tbf_bucket_t *bucket, tbf_opspec_t *spec)
|
||||
tbf_mod_bucket(tbf_bucket_t *bucket, tbf_opspec_t *spec)
|
||||
{
|
||||
LOCK (&bucket->lock);
|
||||
{
|
||||
bucket->tokens = 0;
|
||||
bucket->tokenrate = spec->rate;
|
||||
bucket->maxtokens = spec->maxlimit;
|
||||
}
|
||||
UNLOCK (&bucket->lock);
|
||||
LOCK(&bucket->lock);
|
||||
{
|
||||
bucket->tokens = 0;
|
||||
bucket->tokenrate = spec->rate;
|
||||
bucket->maxtokens = spec->maxlimit;
|
||||
}
|
||||
UNLOCK(&bucket->lock);
|
||||
|
||||
/* next token tick would unqueue pending operations */
|
||||
/* next token tick would unqueue pending operations */
|
||||
}
|
||||
|
||||
int
|
||||
tbf_mod (tbf_t *tbf, tbf_opspec_t *tbfspec)
|
||||
tbf_mod(tbf_t *tbf, tbf_opspec_t *tbfspec)
|
||||
{
|
||||
int ret = 0;
|
||||
tbf_bucket_t *bucket = NULL;
|
||||
tbf_ops_t op = TBF_OP_MIN;
|
||||
int ret = 0;
|
||||
tbf_bucket_t *bucket = NULL;
|
||||
tbf_ops_t op = TBF_OP_MIN;
|
||||
|
||||
if (!tbf || !tbfspec)
|
||||
return -1;
|
||||
if (!tbf || !tbfspec)
|
||||
return -1;
|
||||
|
||||
op = tbfspec->op;
|
||||
op = tbfspec->op;
|
||||
|
||||
GF_ASSERT (op >= TBF_OP_MIN);
|
||||
GF_ASSERT (op <= TBF_OP_MAX);
|
||||
GF_ASSERT(op >= TBF_OP_MIN);
|
||||
GF_ASSERT(op <= TBF_OP_MAX);
|
||||
|
||||
bucket = *(tbf->bucket + op);
|
||||
if (bucket) {
|
||||
tbf_mod_bucket (bucket, tbfspec);
|
||||
} else {
|
||||
ret = tbf_init_bucket (tbf, tbfspec);
|
||||
}
|
||||
bucket = *(tbf->bucket + op);
|
||||
if (bucket) {
|
||||
tbf_mod_bucket(bucket, tbfspec);
|
||||
} else {
|
||||
ret = tbf_init_bucket(tbf, tbfspec);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
tbf_throttle (tbf_t *tbf, tbf_ops_t op, unsigned long tokens_requested)
|
||||
tbf_throttle(tbf_t *tbf, tbf_ops_t op, unsigned long tokens_requested)
|
||||
{
|
||||
char waitq = 0;
|
||||
tbf_bucket_t *bucket = NULL;
|
||||
tbf_throttle_t *throttle = NULL;
|
||||
char waitq = 0;
|
||||
tbf_bucket_t *bucket = NULL;
|
||||
tbf_throttle_t *throttle = NULL;
|
||||
|
||||
GF_ASSERT (op >= TBF_OP_MIN);
|
||||
GF_ASSERT (op <= TBF_OP_MAX);
|
||||
GF_ASSERT(op >= TBF_OP_MIN);
|
||||
GF_ASSERT(op <= TBF_OP_MAX);
|
||||
|
||||
bucket = *(tbf->bucket + op);
|
||||
if (!bucket)
|
||||
return;
|
||||
bucket = *(tbf->bucket + op);
|
||||
if (!bucket)
|
||||
return;
|
||||
|
||||
LOCK (&bucket->lock);
|
||||
{
|
||||
/**
|
||||
* if there are enough tokens in the bucket there is no need
|
||||
* to throttle the request: therefore, consume the required
|
||||
* number of tokens and continue.
|
||||
*/
|
||||
if (tokens_requested <= bucket->tokens) {
|
||||
bucket->tokens -= tokens_requested;
|
||||
} else {
|
||||
throttle = tbf_init_throttle (tokens_requested);
|
||||
if (!throttle) /* let it slip through for now.. */
|
||||
goto unblock;
|
||||
LOCK(&bucket->lock);
|
||||
{
|
||||
/**
|
||||
* if there are enough tokens in the bucket there is no need
|
||||
* to throttle the request: therefore, consume the required
|
||||
* number of tokens and continue.
|
||||
*/
|
||||
if (tokens_requested <= bucket->tokens) {
|
||||
bucket->tokens -= tokens_requested;
|
||||
} else {
|
||||
throttle = tbf_init_throttle(tokens_requested);
|
||||
if (!throttle) /* let it slip through for now.. */
|
||||
goto unblock;
|
||||
|
||||
waitq = 1;
|
||||
pthread_mutex_lock (&throttle->mutex);
|
||||
list_add_tail (&throttle->list, &bucket->queued);
|
||||
}
|
||||
waitq = 1;
|
||||
pthread_mutex_lock(&throttle->mutex);
|
||||
list_add_tail(&throttle->list, &bucket->queued);
|
||||
}
|
||||
unblock:
|
||||
UNLOCK (&bucket->lock);
|
||||
}
|
||||
unblock:
|
||||
UNLOCK(&bucket->lock);
|
||||
|
||||
if (waitq) {
|
||||
while (!throttle->done) {
|
||||
pthread_cond_wait (&throttle->cond, &throttle->mutex);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock (&throttle->mutex);
|
||||
|
||||
pthread_mutex_destroy (&throttle->mutex);
|
||||
pthread_cond_destroy (&throttle->cond);
|
||||
|
||||
GF_FREE (throttle);
|
||||
if (waitq) {
|
||||
while (!throttle->done) {
|
||||
pthread_cond_wait(&throttle->cond, &throttle->mutex);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&throttle->mutex);
|
||||
|
||||
pthread_mutex_destroy(&throttle->mutex);
|
||||
pthread_cond_destroy(&throttle->cond);
|
||||
|
||||
GF_FREE(throttle);
|
||||
}
|
||||
}
|
||||
|
@ -17,265 +17,255 @@
|
||||
|
||||
/* fwd decl */
|
||||
static gf_timer_registry_t *
|
||||
gf_timer_registry_init (glusterfs_ctx_t *);
|
||||
gf_timer_registry_init(glusterfs_ctx_t *);
|
||||
|
||||
gf_timer_t *
|
||||
gf_timer_call_after (glusterfs_ctx_t *ctx,
|
||||
struct timespec delta,
|
||||
gf_timer_cbk_t callbk,
|
||||
void *data)
|
||||
gf_timer_call_after(glusterfs_ctx_t *ctx, struct timespec delta,
|
||||
gf_timer_cbk_t callbk, void *data)
|
||||
{
|
||||
gf_timer_registry_t *reg = NULL;
|
||||
gf_timer_t *event = NULL;
|
||||
gf_timer_t *trav = NULL;
|
||||
uint64_t at = 0;
|
||||
gf_timer_registry_t *reg = NULL;
|
||||
gf_timer_t *event = NULL;
|
||||
gf_timer_t *trav = NULL;
|
||||
uint64_t at = 0;
|
||||
|
||||
if ((ctx == NULL) || (ctx->cleanup_started))
|
||||
if ((ctx == NULL) || (ctx->cleanup_started)) {
|
||||
gf_msg_callingfn("timer", GF_LOG_ERROR, EINVAL, LG_MSG_INVALID_ARG,
|
||||
"Either ctx is NULL or"
|
||||
" ctx cleanup started");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
reg = gf_timer_registry_init(ctx);
|
||||
|
||||
if (!reg) {
|
||||
gf_msg_callingfn("timer", GF_LOG_ERROR, 0, LG_MSG_TIMER_REGISTER_ERROR,
|
||||
"!reg");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
event = GF_CALLOC(1, sizeof(*event), gf_common_mt_gf_timer_t);
|
||||
if (!event) {
|
||||
return NULL;
|
||||
}
|
||||
timespec_now(&event->at);
|
||||
timespec_adjust_delta(&event->at, delta);
|
||||
at = TS(event->at);
|
||||
event->callbk = callbk;
|
||||
event->data = data;
|
||||
event->xl = THIS;
|
||||
LOCK(®->lock);
|
||||
{
|
||||
list_for_each_entry_reverse(trav, ®->active, list)
|
||||
{
|
||||
gf_msg_callingfn ("timer", GF_LOG_ERROR, EINVAL,
|
||||
LG_MSG_INVALID_ARG, "Either ctx is NULL or"
|
||||
" ctx cleanup started");
|
||||
return NULL;
|
||||
if (TS(trav->at) < at)
|
||||
break;
|
||||
}
|
||||
|
||||
reg = gf_timer_registry_init (ctx);
|
||||
|
||||
if (!reg) {
|
||||
gf_msg_callingfn ("timer", GF_LOG_ERROR, 0,
|
||||
LG_MSG_TIMER_REGISTER_ERROR, "!reg");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
event = GF_CALLOC (1, sizeof (*event), gf_common_mt_gf_timer_t);
|
||||
if (!event) {
|
||||
return NULL;
|
||||
}
|
||||
timespec_now (&event->at);
|
||||
timespec_adjust_delta (&event->at, delta);
|
||||
at = TS (event->at);
|
||||
event->callbk = callbk;
|
||||
event->data = data;
|
||||
event->xl = THIS;
|
||||
LOCK (®->lock);
|
||||
{
|
||||
list_for_each_entry_reverse (trav, ®->active, list) {
|
||||
if (TS (trav->at) < at)
|
||||
break;
|
||||
}
|
||||
list_add (&event->list, &trav->list);
|
||||
}
|
||||
UNLOCK (®->lock);
|
||||
return event;
|
||||
list_add(&event->list, &trav->list);
|
||||
}
|
||||
UNLOCK(®->lock);
|
||||
return event;
|
||||
}
|
||||
|
||||
|
||||
int32_t
|
||||
gf_timer_call_cancel (glusterfs_ctx_t *ctx,
|
||||
gf_timer_t *event)
|
||||
gf_timer_call_cancel(glusterfs_ctx_t *ctx, gf_timer_t *event)
|
||||
{
|
||||
gf_timer_registry_t *reg = NULL;
|
||||
gf_boolean_t fired = _gf_false;
|
||||
gf_timer_registry_t *reg = NULL;
|
||||
gf_boolean_t fired = _gf_false;
|
||||
|
||||
if (ctx == NULL || event == NULL)
|
||||
{
|
||||
gf_msg_callingfn ("timer", GF_LOG_ERROR, EINVAL,
|
||||
LG_MSG_INVALID_ARG, "invalid argument");
|
||||
return 0;
|
||||
}
|
||||
if (ctx == NULL || event == NULL) {
|
||||
gf_msg_callingfn("timer", GF_LOG_ERROR, EINVAL, LG_MSG_INVALID_ARG,
|
||||
"invalid argument");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ctx->cleanup_started) {
|
||||
gf_msg_callingfn ("timer", GF_LOG_INFO, 0,
|
||||
LG_MSG_CTX_CLEANUP_STARTED,
|
||||
"ctx cleanup started");
|
||||
return 0;
|
||||
}
|
||||
if (ctx->cleanup_started) {
|
||||
gf_msg_callingfn("timer", GF_LOG_INFO, 0, LG_MSG_CTX_CLEANUP_STARTED,
|
||||
"ctx cleanup started");
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOCK (&ctx->lock);
|
||||
{
|
||||
reg = ctx->timer;
|
||||
}
|
||||
UNLOCK (&ctx->lock);
|
||||
LOCK(&ctx->lock);
|
||||
{
|
||||
reg = ctx->timer;
|
||||
}
|
||||
UNLOCK(&ctx->lock);
|
||||
|
||||
if (!reg) {
|
||||
/* This can happen when cleanup may have just started and
|
||||
* gf_timer_registry_destroy() sets ctx->timer to NULL.
|
||||
* Just bail out as success as gf_timer_proc() takes
|
||||
* care of cleaning up the events.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
if (!reg) {
|
||||
/* This can happen when cleanup may have just started and
|
||||
* gf_timer_registry_destroy() sets ctx->timer to NULL.
|
||||
* Just bail out as success as gf_timer_proc() takes
|
||||
* care of cleaning up the events.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOCK (®->lock);
|
||||
{
|
||||
fired = event->fired;
|
||||
if (fired)
|
||||
goto unlock;
|
||||
list_del (&event->list);
|
||||
}
|
||||
LOCK(®->lock);
|
||||
{
|
||||
fired = event->fired;
|
||||
if (fired)
|
||||
goto unlock;
|
||||
list_del(&event->list);
|
||||
}
|
||||
unlock:
|
||||
UNLOCK (®->lock);
|
||||
UNLOCK(®->lock);
|
||||
|
||||
if (!fired) {
|
||||
GF_FREE (event);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
if (!fired) {
|
||||
GF_FREE(event);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
gf_timer_proc (void *data)
|
||||
gf_timer_proc(void *data)
|
||||
{
|
||||
gf_timer_registry_t *reg = data;
|
||||
struct timespec sleepts;
|
||||
gf_timer_t *event = NULL;
|
||||
gf_timer_t *tmp = NULL;
|
||||
xlator_t *old_THIS = NULL;
|
||||
gf_timer_registry_t *reg = data;
|
||||
struct timespec sleepts;
|
||||
gf_timer_t *event = NULL;
|
||||
gf_timer_t *tmp = NULL;
|
||||
xlator_t *old_THIS = NULL;
|
||||
|
||||
while (!reg->fin) {
|
||||
uint64_t now;
|
||||
struct timespec now_ts;
|
||||
while (!reg->fin) {
|
||||
uint64_t now;
|
||||
struct timespec now_ts;
|
||||
|
||||
timespec_now (&now_ts);
|
||||
now = TS (now_ts);
|
||||
while (1) {
|
||||
uint64_t at;
|
||||
char need_cbk = 0;
|
||||
timespec_now(&now_ts);
|
||||
now = TS(now_ts);
|
||||
while (1) {
|
||||
uint64_t at;
|
||||
char need_cbk = 0;
|
||||
|
||||
/*
|
||||
* This will be overridden with a shorter interval if
|
||||
* there's an event scheduled sooner. That makes the
|
||||
* system more responsive in most cases, but doesn't
|
||||
* include the case where a timer is added while we're
|
||||
* asleep. It's tempting to use pthread_cond_timedwait,
|
||||
* with the caveat that we'd be relying on system time
|
||||
* instead of monotonic time. That's a mess when the
|
||||
* system time is adjusted. Another alternative might
|
||||
* be to use pthread_kill, but that will remain TBD for
|
||||
* now.
|
||||
*/
|
||||
sleepts.tv_sec = 1;
|
||||
sleepts.tv_nsec = 0;
|
||||
/*
|
||||
* This will be overridden with a shorter interval if
|
||||
* there's an event scheduled sooner. That makes the
|
||||
* system more responsive in most cases, but doesn't
|
||||
* include the case where a timer is added while we're
|
||||
* asleep. It's tempting to use pthread_cond_timedwait,
|
||||
* with the caveat that we'd be relying on system time
|
||||
* instead of monotonic time. That's a mess when the
|
||||
* system time is adjusted. Another alternative might
|
||||
* be to use pthread_kill, but that will remain TBD for
|
||||
* now.
|
||||
*/
|
||||
sleepts.tv_sec = 1;
|
||||
sleepts.tv_nsec = 0;
|
||||
|
||||
LOCK (®->lock);
|
||||
{
|
||||
/*
|
||||
* Using list_for_each and then always breaking
|
||||
* after the first iteration might seem strange,
|
||||
* but (unlike alternatives) is independent of
|
||||
* the underlying list implementation.
|
||||
*/
|
||||
list_for_each_entry_safe (event,
|
||||
tmp, ®->active, list) {
|
||||
at = TS (event->at);
|
||||
if (now >= at) {
|
||||
need_cbk = 1;
|
||||
event->fired = _gf_true;
|
||||
list_del (&event->list);
|
||||
} else {
|
||||
uint64_t diff = now - at;
|
||||
|
||||
if (diff < 1000000000) {
|
||||
sleepts.tv_sec = 0;
|
||||
sleepts.tv_nsec = diff;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
UNLOCK (®->lock);
|
||||
if (need_cbk) {
|
||||
old_THIS = NULL;
|
||||
if (event->xl) {
|
||||
old_THIS = THIS;
|
||||
THIS = event->xl;
|
||||
}
|
||||
event->callbk (event->data);
|
||||
GF_FREE (event);
|
||||
if (old_THIS) {
|
||||
THIS = old_THIS;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
nanosleep (&sleepts, NULL);
|
||||
}
|
||||
|
||||
LOCK (®->lock);
|
||||
{
|
||||
/* Do not call gf_timer_call_cancel(),
|
||||
* it will lead to deadlock
|
||||
LOCK(®->lock);
|
||||
{
|
||||
/*
|
||||
* Using list_for_each and then always breaking
|
||||
* after the first iteration might seem strange,
|
||||
* but (unlike alternatives) is independent of
|
||||
* the underlying list implementation.
|
||||
*/
|
||||
list_for_each_entry_safe (event, tmp, ®->active, list) {
|
||||
list_del (&event->list);
|
||||
GF_FREE (event);
|
||||
list_for_each_entry_safe(event, tmp, ®->active, list)
|
||||
{
|
||||
at = TS(event->at);
|
||||
if (now >= at) {
|
||||
need_cbk = 1;
|
||||
event->fired = _gf_true;
|
||||
list_del(&event->list);
|
||||
} else {
|
||||
uint64_t diff = now - at;
|
||||
|
||||
if (diff < 1000000000) {
|
||||
sleepts.tv_sec = 0;
|
||||
sleepts.tv_nsec = diff;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
UNLOCK(®->lock);
|
||||
if (need_cbk) {
|
||||
old_THIS = NULL;
|
||||
if (event->xl) {
|
||||
old_THIS = THIS;
|
||||
THIS = event->xl;
|
||||
}
|
||||
event->callbk(event->data);
|
||||
GF_FREE(event);
|
||||
if (old_THIS) {
|
||||
THIS = old_THIS;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
UNLOCK (®->lock);
|
||||
LOCK_DESTROY (®->lock);
|
||||
nanosleep(&sleepts, NULL);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
LOCK(®->lock);
|
||||
{
|
||||
/* Do not call gf_timer_call_cancel(),
|
||||
* it will lead to deadlock
|
||||
*/
|
||||
list_for_each_entry_safe(event, tmp, ®->active, list)
|
||||
{
|
||||
list_del(&event->list);
|
||||
GF_FREE(event);
|
||||
}
|
||||
}
|
||||
UNLOCK(®->lock);
|
||||
LOCK_DESTROY(®->lock);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static gf_timer_registry_t *
|
||||
gf_timer_registry_init (glusterfs_ctx_t *ctx)
|
||||
gf_timer_registry_init(glusterfs_ctx_t *ctx)
|
||||
{
|
||||
gf_timer_registry_t *reg = NULL;
|
||||
int ret = -1;
|
||||
gf_timer_registry_t *reg = NULL;
|
||||
int ret = -1;
|
||||
|
||||
LOCK (&ctx->lock);
|
||||
{
|
||||
reg = ctx->timer;
|
||||
if (reg) {
|
||||
UNLOCK (&ctx->lock);
|
||||
goto out;
|
||||
}
|
||||
reg = GF_CALLOC (1, sizeof (*reg),
|
||||
gf_common_mt_gf_timer_registry_t);
|
||||
if (!reg) {
|
||||
UNLOCK (&ctx->lock);
|
||||
goto out;
|
||||
}
|
||||
ctx->timer = reg;
|
||||
LOCK_INIT (®->lock);
|
||||
INIT_LIST_HEAD (®->active);
|
||||
LOCK(&ctx->lock);
|
||||
{
|
||||
reg = ctx->timer;
|
||||
if (reg) {
|
||||
UNLOCK(&ctx->lock);
|
||||
goto out;
|
||||
}
|
||||
UNLOCK (&ctx->lock);
|
||||
ret = gf_thread_create (®->th, NULL, gf_timer_proc, reg, "timer");
|
||||
if (ret) {
|
||||
gf_msg (THIS->name, GF_LOG_ERROR, ret,
|
||||
LG_MSG_PTHREAD_FAILED,
|
||||
"Thread creation failed");
|
||||
reg = GF_CALLOC(1, sizeof(*reg), gf_common_mt_gf_timer_registry_t);
|
||||
if (!reg) {
|
||||
UNLOCK(&ctx->lock);
|
||||
goto out;
|
||||
}
|
||||
ctx->timer = reg;
|
||||
LOCK_INIT(®->lock);
|
||||
INIT_LIST_HEAD(®->active);
|
||||
}
|
||||
UNLOCK(&ctx->lock);
|
||||
ret = gf_thread_create(®->th, NULL, gf_timer_proc, reg, "timer");
|
||||
if (ret) {
|
||||
gf_msg(THIS->name, GF_LOG_ERROR, ret, LG_MSG_PTHREAD_FAILED,
|
||||
"Thread creation failed");
|
||||
}
|
||||
|
||||
out:
|
||||
return reg;
|
||||
return reg;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
gf_timer_registry_destroy (glusterfs_ctx_t *ctx)
|
||||
gf_timer_registry_destroy(glusterfs_ctx_t *ctx)
|
||||
{
|
||||
pthread_t thr_id;
|
||||
gf_timer_registry_t *reg = NULL;
|
||||
pthread_t thr_id;
|
||||
gf_timer_registry_t *reg = NULL;
|
||||
|
||||
if (ctx == NULL)
|
||||
return;
|
||||
if (ctx == NULL)
|
||||
return;
|
||||
|
||||
LOCK (&ctx->lock);
|
||||
{
|
||||
reg = ctx->timer;
|
||||
ctx->timer = NULL;
|
||||
}
|
||||
UNLOCK (&ctx->lock);
|
||||
LOCK(&ctx->lock);
|
||||
{
|
||||
reg = ctx->timer;
|
||||
ctx->timer = NULL;
|
||||
}
|
||||
UNLOCK(&ctx->lock);
|
||||
|
||||
if (!reg)
|
||||
return;
|
||||
if (!reg)
|
||||
return;
|
||||
|
||||
thr_id = reg->th;
|
||||
reg->fin = 1;
|
||||
pthread_join (thr_id, NULL);
|
||||
GF_FREE (reg);
|
||||
thr_id = reg->th;
|
||||
reg->fin = 1;
|
||||
pthread_join(thr_id, NULL);
|
||||
GF_FREE(reg);
|
||||
}
|
||||
|
@ -24,65 +24,69 @@ static mach_timebase_info_data_t gf_timebase;
|
||||
#include "libglusterfs-messages.h"
|
||||
#include "common-utils.h"
|
||||
|
||||
void timespec_now (struct timespec *ts)
|
||||
void
|
||||
timespec_now(struct timespec *ts)
|
||||
{
|
||||
#if defined GF_LINUX_HOST_OS || defined GF_SOLARIS_HOST_OS || defined GF_BSD_HOST_OS
|
||||
if (0 == clock_gettime(CLOCK_MONOTONIC, ts)) {
|
||||
/* All good */
|
||||
return;
|
||||
}
|
||||
#if defined GF_LINUX_HOST_OS || defined GF_SOLARIS_HOST_OS || \
|
||||
defined GF_BSD_HOST_OS
|
||||
if (0 == clock_gettime(CLOCK_MONOTONIC, ts)) {
|
||||
/* All good */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Fall back, but there is hope in gettimeofday() syscall */
|
||||
struct timeval tv;
|
||||
if (0 == gettimeofday(&tv, NULL)) {
|
||||
/* Again, all good */
|
||||
TIMEVAL_TO_TIMESPEC(&tv, ts);
|
||||
return;
|
||||
}
|
||||
/* Fall back, but there is hope in gettimeofday() syscall */
|
||||
struct timeval tv;
|
||||
if (0 == gettimeofday(&tv, NULL)) {
|
||||
/* Again, all good */
|
||||
TIMEVAL_TO_TIMESPEC(&tv, ts);
|
||||
return;
|
||||
}
|
||||
|
||||
/* If control hits here, there is surely a problem,
|
||||
mainly because, as per man page too, these syscalls
|
||||
shouldn't fail. Best way is to ABORT, because it is
|
||||
not right */
|
||||
GF_ABORT ("gettimeofday() failed!!");
|
||||
/* If control hits here, there is surely a problem,
|
||||
mainly because, as per man page too, these syscalls
|
||||
shouldn't fail. Best way is to ABORT, because it is
|
||||
not right */
|
||||
GF_ABORT("gettimeofday() failed!!");
|
||||
|
||||
#elif defined GF_DARWIN_HOST_OS
|
||||
uint64_t time = mach_absolute_time();
|
||||
static double scaling = 0.0;
|
||||
uint64_t time = mach_absolute_time();
|
||||
static double scaling = 0.0;
|
||||
|
||||
if (mach_timebase_info(&gf_timebase) != KERN_SUCCESS) {
|
||||
gf_timebase.numer = 1;
|
||||
gf_timebase.denom = 1;
|
||||
}
|
||||
if (gf_timebase.denom == 0) {
|
||||
gf_timebase.numer = 1;
|
||||
gf_timebase.denom = 1;
|
||||
}
|
||||
if (mach_timebase_info(&gf_timebase) != KERN_SUCCESS) {
|
||||
gf_timebase.numer = 1;
|
||||
gf_timebase.denom = 1;
|
||||
}
|
||||
if (gf_timebase.denom == 0) {
|
||||
gf_timebase.numer = 1;
|
||||
gf_timebase.denom = 1;
|
||||
}
|
||||
|
||||
scaling = (double) gf_timebase.numer / (double) gf_timebase.denom;
|
||||
time *= scaling;
|
||||
scaling = (double)gf_timebase.numer / (double)gf_timebase.denom;
|
||||
time *= scaling;
|
||||
|
||||
ts->tv_sec = (time * NANO);
|
||||
ts->tv_nsec = (time - (ts->tv_sec * GIGA));
|
||||
ts->tv_sec = (time * NANO);
|
||||
ts->tv_nsec = (time - (ts->tv_sec * GIGA));
|
||||
|
||||
#endif /* Platform verification */
|
||||
}
|
||||
|
||||
void timespec_adjust_delta (struct timespec *ts, struct timespec delta)
|
||||
void
|
||||
timespec_adjust_delta(struct timespec *ts, struct timespec delta)
|
||||
{
|
||||
ts->tv_nsec = ((ts->tv_nsec + delta.tv_nsec) % 1000000000);
|
||||
ts->tv_sec += ((ts->tv_nsec + delta.tv_nsec) / 1000000000);
|
||||
ts->tv_sec += delta.tv_sec;
|
||||
ts->tv_nsec = ((ts->tv_nsec + delta.tv_nsec) % 1000000000);
|
||||
ts->tv_sec += ((ts->tv_nsec + delta.tv_nsec) / 1000000000);
|
||||
ts->tv_sec += delta.tv_sec;
|
||||
}
|
||||
|
||||
void timespec_sub (const struct timespec *begin, const struct timespec *end,
|
||||
struct timespec *res)
|
||||
void
|
||||
timespec_sub(const struct timespec *begin, const struct timespec *end,
|
||||
struct timespec *res)
|
||||
{
|
||||
if (end->tv_nsec < begin->tv_nsec) {
|
||||
res->tv_sec = end->tv_sec - begin->tv_sec - 1;
|
||||
res->tv_nsec = end->tv_nsec + 1000000000 - begin->tv_nsec;
|
||||
} else {
|
||||
res->tv_sec = end->tv_sec - begin->tv_sec;
|
||||
res->tv_nsec = end->tv_nsec - begin->tv_nsec;
|
||||
}
|
||||
if (end->tv_nsec < begin->tv_nsec) {
|
||||
res->tv_sec = end->tv_sec - begin->tv_sec - 1;
|
||||
res->tv_nsec = end->tv_nsec + 1000000000 - begin->tv_nsec;
|
||||
} else {
|
||||
res->tv_sec = end->tv_sec - begin->tv_sec;
|
||||
res->tv_nsec = end->tv_nsec - begin->tv_nsec;
|
||||
}
|
||||
}
|
||||
|
@ -17,371 +17,352 @@
|
||||
#include "trie.h"
|
||||
|
||||
#define DISTANCE_EDIT 1
|
||||
#define DISTANCE_INS 1
|
||||
#define DISTANCE_DEL 1
|
||||
|
||||
#define DISTANCE_INS 1
|
||||
#define DISTANCE_DEL 1
|
||||
|
||||
struct trienode {
|
||||
char id;
|
||||
char eow;
|
||||
int depth;
|
||||
void *data;
|
||||
struct trie *trie;
|
||||
struct trienode *parent;
|
||||
struct trienode *subnodes[255];
|
||||
char id;
|
||||
char eow;
|
||||
int depth;
|
||||
void *data;
|
||||
struct trie *trie;
|
||||
struct trienode *parent;
|
||||
struct trienode *subnodes[255];
|
||||
};
|
||||
|
||||
struct trie {
|
||||
struct trienode root;
|
||||
int nodecnt;
|
||||
size_t len;
|
||||
struct trienode root;
|
||||
int nodecnt;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
|
||||
trie_t *
|
||||
trie_new ()
|
||||
trie_new()
|
||||
{
|
||||
trie_t *trie = NULL;
|
||||
trie_t *trie = NULL;
|
||||
|
||||
trie = GF_CALLOC (1, sizeof (*trie), gf_common_mt_trie_trie);
|
||||
if (!trie)
|
||||
return NULL;
|
||||
trie = GF_CALLOC(1, sizeof(*trie), gf_common_mt_trie_trie);
|
||||
if (!trie)
|
||||
return NULL;
|
||||
|
||||
trie->root.trie = trie;
|
||||
trie->root.trie = trie;
|
||||
|
||||
return trie;
|
||||
return trie;
|
||||
}
|
||||
|
||||
|
||||
static trienode_t *
|
||||
trie_subnode (trienode_t *node, int id)
|
||||
trie_subnode(trienode_t *node, int id)
|
||||
{
|
||||
trienode_t *subnode = NULL;
|
||||
trienode_t *subnode = NULL;
|
||||
|
||||
subnode = node->subnodes[id];
|
||||
if (!subnode) {
|
||||
subnode = GF_CALLOC (1, sizeof (*subnode),
|
||||
gf_common_mt_trie_node);
|
||||
if (!subnode)
|
||||
return NULL;
|
||||
subnode = node->subnodes[id];
|
||||
if (!subnode) {
|
||||
subnode = GF_CALLOC(1, sizeof(*subnode), gf_common_mt_trie_node);
|
||||
if (!subnode)
|
||||
return NULL;
|
||||
|
||||
subnode->id = id;
|
||||
subnode->depth = node->depth + 1;
|
||||
node->subnodes[id] = subnode;
|
||||
subnode->parent = node;
|
||||
subnode->trie = node->trie;
|
||||
node->trie->nodecnt++;
|
||||
}
|
||||
subnode->id = id;
|
||||
subnode->depth = node->depth + 1;
|
||||
node->subnodes[id] = subnode;
|
||||
subnode->parent = node;
|
||||
subnode->trie = node->trie;
|
||||
node->trie->nodecnt++;
|
||||
}
|
||||
|
||||
return subnode;
|
||||
return subnode;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
trie_add (trie_t *trie, const char *dword)
|
||||
trie_add(trie_t *trie, const char *dword)
|
||||
{
|
||||
trienode_t *node = NULL;
|
||||
int i = 0;
|
||||
char id = 0;
|
||||
trienode_t *subnode = NULL;
|
||||
trienode_t *node = NULL;
|
||||
int i = 0;
|
||||
char id = 0;
|
||||
trienode_t *subnode = NULL;
|
||||
|
||||
node = &trie->root;
|
||||
node = &trie->root;
|
||||
|
||||
for (i = 0; i < strlen (dword); i++) {
|
||||
id = dword[i];
|
||||
for (i = 0; i < strlen(dword); i++) {
|
||||
id = dword[i];
|
||||
|
||||
subnode = trie_subnode (node, id);
|
||||
if (!subnode)
|
||||
return -1;
|
||||
node = subnode;
|
||||
}
|
||||
subnode = trie_subnode(node, id);
|
||||
if (!subnode)
|
||||
return -1;
|
||||
node = subnode;
|
||||
}
|
||||
|
||||
node->eow = 1;
|
||||
node->eow = 1;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
trienode_free (trienode_t *node)
|
||||
trienode_free(trienode_t *node)
|
||||
{
|
||||
trienode_t *trav = NULL;
|
||||
int i = 0;
|
||||
trienode_t *trav = NULL;
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < 255; i++) {
|
||||
trav = node->subnodes[i];
|
||||
for (i = 0; i < 255; i++) {
|
||||
trav = node->subnodes[i];
|
||||
|
||||
if (trav)
|
||||
trienode_free (trav);
|
||||
}
|
||||
if (trav)
|
||||
trienode_free(trav);
|
||||
}
|
||||
|
||||
GF_FREE (node->data);
|
||||
GF_FREE (node);
|
||||
GF_FREE(node->data);
|
||||
GF_FREE(node);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
trie_destroy (trie_t *trie)
|
||||
trie_destroy(trie_t *trie)
|
||||
{
|
||||
trienode_free ((trienode_t *)trie);
|
||||
trienode_free((trienode_t *)trie);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
trie_destroy_bynode (trienode_t *node)
|
||||
trie_destroy_bynode(trienode_t *node)
|
||||
{
|
||||
trie_destroy (node->trie);
|
||||
trie_destroy(node->trie);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
trienode_walk (trienode_t *node, int (*fn)(trienode_t *node, void *data),
|
||||
void *data, int eowonly)
|
||||
trienode_walk(trienode_t *node, int (*fn)(trienode_t *node, void *data),
|
||||
void *data, int eowonly)
|
||||
{
|
||||
trienode_t *trav = NULL;
|
||||
int i = 0;
|
||||
int cret = 0;
|
||||
int ret = 0;
|
||||
trienode_t *trav = NULL;
|
||||
int i = 0;
|
||||
int cret = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (!eowonly || node->eow)
|
||||
ret = fn (node, data);
|
||||
if (!eowonly || node->eow)
|
||||
ret = fn(node, data);
|
||||
|
||||
if (ret)
|
||||
goto out;
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < 255; i++) {
|
||||
trav = node->subnodes[i];
|
||||
if (!trav)
|
||||
continue;
|
||||
for (i = 0; i < 255; i++) {
|
||||
trav = node->subnodes[i];
|
||||
if (!trav)
|
||||
continue;
|
||||
|
||||
cret = trienode_walk (trav, fn, data, eowonly);
|
||||
if (cret < 0) {
|
||||
ret = cret;
|
||||
goto out;
|
||||
}
|
||||
ret += cret;
|
||||
cret = trienode_walk(trav, fn, data, eowonly);
|
||||
if (cret < 0) {
|
||||
ret = cret;
|
||||
goto out;
|
||||
}
|
||||
ret += cret;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
trie_walk (trie_t *trie, int (*fn)(trienode_t *node, void *data),
|
||||
void *data, int eowonly)
|
||||
trie_walk(trie_t *trie, int (*fn)(trienode_t *node, void *data), void *data,
|
||||
int eowonly)
|
||||
{
|
||||
return trienode_walk (&trie->root, fn, data, eowonly);
|
||||
return trienode_walk(&trie->root, fn, data, eowonly);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
print_node (trienode_t *node, char **buf)
|
||||
print_node(trienode_t *node, char **buf)
|
||||
{
|
||||
if (!node->parent)
|
||||
return;
|
||||
if (!node->parent)
|
||||
return;
|
||||
|
||||
if (node->parent) {
|
||||
print_node (node->parent, buf);
|
||||
*(*buf)++ = node->id;
|
||||
}
|
||||
if (node->parent) {
|
||||
print_node(node->parent, buf);
|
||||
*(*buf)++ = node->id;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
trienode_get_word (trienode_t *node, char **bufp)
|
||||
trienode_get_word(trienode_t *node, char **bufp)
|
||||
{
|
||||
char *buf = NULL;
|
||||
char *buf = NULL;
|
||||
|
||||
buf = GF_CALLOC (1, node->depth + 1, gf_common_mt_trie_buf);
|
||||
if (!buf)
|
||||
return -1;
|
||||
*bufp = buf;
|
||||
buf = GF_CALLOC(1, node->depth + 1, gf_common_mt_trie_buf);
|
||||
if (!buf)
|
||||
return -1;
|
||||
*bufp = buf;
|
||||
|
||||
print_node (node, &buf);
|
||||
print_node(node, &buf);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
calc_dist (trienode_t *node, void *data)
|
||||
calc_dist(trienode_t *node, void *data)
|
||||
{
|
||||
const char *word = NULL;
|
||||
int i = 0;
|
||||
int *row = NULL;
|
||||
int *uprow = NULL;
|
||||
int distu = 0;
|
||||
int distl = 0;
|
||||
int distul = 0;
|
||||
const char *word = NULL;
|
||||
int i = 0;
|
||||
int *row = NULL;
|
||||
int *uprow = NULL;
|
||||
int distu = 0;
|
||||
int distl = 0;
|
||||
int distul = 0;
|
||||
|
||||
word = data;
|
||||
word = data;
|
||||
|
||||
node->data = GF_CALLOC (node->trie->len, sizeof (int),
|
||||
gf_common_mt_trie_data);
|
||||
if (!node->data)
|
||||
return -1;
|
||||
row = node->data;
|
||||
node->data = GF_CALLOC(node->trie->len, sizeof(int),
|
||||
gf_common_mt_trie_data);
|
||||
if (!node->data)
|
||||
return -1;
|
||||
row = node->data;
|
||||
|
||||
if (!node->parent) {
|
||||
for (i = 0; i < node->trie->len; i++)
|
||||
row[i] = i+1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uprow = node->parent->data;
|
||||
|
||||
distu = node->depth; /* up node */
|
||||
distul = node->parent->depth; /* up-left node */
|
||||
|
||||
for (i = 0; i < node->trie->len; i++) {
|
||||
distl = uprow[i]; /* left node */
|
||||
|
||||
if (word[i] == node->id)
|
||||
row[i] = distul;
|
||||
else
|
||||
row[i] = min ((distul + DISTANCE_EDIT),
|
||||
min ((distu + DISTANCE_DEL),
|
||||
(distl + DISTANCE_INS)));
|
||||
|
||||
distu = row[i];
|
||||
distul = distl;
|
||||
}
|
||||
if (!node->parent) {
|
||||
for (i = 0; i < node->trie->len; i++)
|
||||
row[i] = i + 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uprow = node->parent->data;
|
||||
|
||||
distu = node->depth; /* up node */
|
||||
distul = node->parent->depth; /* up-left node */
|
||||
|
||||
for (i = 0; i < node->trie->len; i++) {
|
||||
distl = uprow[i]; /* left node */
|
||||
|
||||
if (word[i] == node->id)
|
||||
row[i] = distul;
|
||||
else
|
||||
row[i] = min((distul + DISTANCE_EDIT),
|
||||
min((distu + DISTANCE_DEL), (distl + DISTANCE_INS)));
|
||||
|
||||
distu = row[i];
|
||||
distul = distl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
trienode_get_dist (trienode_t *node)
|
||||
trienode_get_dist(trienode_t *node)
|
||||
{
|
||||
int *row = NULL;
|
||||
int *row = NULL;
|
||||
|
||||
row = node->data;
|
||||
row = node->data;
|
||||
|
||||
return row[node->trie->len - 1];
|
||||
return row[node->trie->len - 1];
|
||||
}
|
||||
|
||||
|
||||
struct trienodevec_w {
|
||||
struct trienodevec *vec;
|
||||
const char *word;
|
||||
struct trienodevec *vec;
|
||||
const char *word;
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
trienodevec_clear (struct trienodevec *nodevec)
|
||||
trienodevec_clear(struct trienodevec *nodevec)
|
||||
{
|
||||
memset(nodevec->nodes, 0, sizeof (*nodevec->nodes) * nodevec->cnt);
|
||||
memset(nodevec->nodes, 0, sizeof(*nodevec->nodes) * nodevec->cnt);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
collect_closest (trienode_t *node, void *data)
|
||||
collect_closest(trienode_t *node, void *data)
|
||||
{
|
||||
struct trienodevec_w *nodevec_w = NULL;
|
||||
struct trienodevec *nodevec = NULL;
|
||||
int dist = 0;
|
||||
int i = 0;
|
||||
struct trienodevec_w *nodevec_w = NULL;
|
||||
struct trienodevec *nodevec = NULL;
|
||||
int dist = 0;
|
||||
int i = 0;
|
||||
|
||||
nodevec_w = data;
|
||||
nodevec = nodevec_w->vec;
|
||||
nodevec_w = data;
|
||||
nodevec = nodevec_w->vec;
|
||||
|
||||
if (calc_dist (node, (void *)nodevec_w->word))
|
||||
return -1;
|
||||
if (calc_dist(node, (void *)nodevec_w->word))
|
||||
return -1;
|
||||
|
||||
if (!node->eow || !nodevec->cnt)
|
||||
return 0;
|
||||
if (!node->eow || !nodevec->cnt)
|
||||
return 0;
|
||||
|
||||
dist = trienode_get_dist (node);
|
||||
dist = trienode_get_dist(node);
|
||||
|
||||
/*
|
||||
* I thought that when descending further after some dictionary word dw,
|
||||
* if we see that child's distance is bigger than it was for dw, then we
|
||||
* can prune this branch, as it can contain only worse nodes.
|
||||
*
|
||||
* This conjecture fails, see eg:
|
||||
*
|
||||
* d("AB", "B") = 1;
|
||||
* d("AB", "BA") = 2;
|
||||
* d("AB", "BAB") = 1;
|
||||
*
|
||||
* -- if both "B" and "BAB" are in dict., then pruning at "BA" * would
|
||||
* miss "BAB".
|
||||
*
|
||||
* (example courtesy of Richard Bann <richardbann at gmail.com>)
|
||||
/*
|
||||
* I thought that when descending further after some dictionary word dw,
|
||||
* if we see that child's distance is bigger than it was for dw, then we
|
||||
* can prune this branch, as it can contain only worse nodes.
|
||||
*
|
||||
* This conjecture fails, see eg:
|
||||
*
|
||||
* d("AB", "B") = 1;
|
||||
* d("AB", "BA") = 2;
|
||||
* d("AB", "BAB") = 1;
|
||||
*
|
||||
* -- if both "B" and "BAB" are in dict., then pruning at "BA" * would
|
||||
* miss "BAB".
|
||||
*
|
||||
* (example courtesy of Richard Bann <richardbann at gmail.com>)
|
||||
|
||||
if (node->parent->eow && dist > trienode_get_dist (node->parent))
|
||||
return 1;
|
||||
if (node->parent->eow && dist > trienode_get_dist (node->parent))
|
||||
return 1;
|
||||
|
||||
*/
|
||||
*/
|
||||
|
||||
if (nodevec->nodes[0] &&
|
||||
dist < trienode_get_dist (nodevec->nodes[0])) {
|
||||
/* improving over the findings so far */
|
||||
trienodevec_clear (nodevec);
|
||||
nodevec->nodes[0] = node;
|
||||
} else if (!nodevec->nodes[0] ||
|
||||
dist == trienode_get_dist (nodevec->nodes[0])) {
|
||||
/* as good as the best so far, add if there is free space */
|
||||
for (i = 0; i < nodevec->cnt; i++) {
|
||||
if (!nodevec->nodes[i]) {
|
||||
nodevec->nodes[i] = node;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (nodevec->nodes[0] && dist < trienode_get_dist(nodevec->nodes[0])) {
|
||||
/* improving over the findings so far */
|
||||
trienodevec_clear(nodevec);
|
||||
nodevec->nodes[0] = node;
|
||||
} else if (!nodevec->nodes[0] ||
|
||||
dist == trienode_get_dist(nodevec->nodes[0])) {
|
||||
/* as good as the best so far, add if there is free space */
|
||||
for (i = 0; i < nodevec->cnt; i++) {
|
||||
if (!nodevec->nodes[i]) {
|
||||
nodevec->nodes[i] = node;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
trie_measure (trie_t *trie, const char *word, trienode_t **nodes,
|
||||
int nodecnt)
|
||||
trie_measure(trie_t *trie, const char *word, trienode_t **nodes, int nodecnt)
|
||||
{
|
||||
struct trienodevec nodevec = {0,};
|
||||
struct trienodevec nodevec = {
|
||||
0,
|
||||
};
|
||||
|
||||
nodevec.nodes = nodes;
|
||||
nodevec.cnt = nodecnt;
|
||||
nodevec.nodes = nodes;
|
||||
nodevec.cnt = nodecnt;
|
||||
|
||||
return trie_measure_vec (trie, word, &nodevec);
|
||||
return trie_measure_vec(trie, word, &nodevec);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
trie_measure_vec (trie_t *trie, const char *word, struct trienodevec *nodevec)
|
||||
trie_measure_vec(trie_t *trie, const char *word, struct trienodevec *nodevec)
|
||||
{
|
||||
struct trienodevec_w nodevec_w = {0,};
|
||||
int ret = 0;
|
||||
struct trienodevec_w nodevec_w = {
|
||||
0,
|
||||
};
|
||||
int ret = 0;
|
||||
|
||||
trie->len = strlen (word);
|
||||
trie->len = strlen(word);
|
||||
|
||||
trienodevec_clear (nodevec);
|
||||
nodevec_w.vec = nodevec;
|
||||
nodevec_w.word = word;
|
||||
trienodevec_clear(nodevec);
|
||||
nodevec_w.vec = nodevec;
|
||||
nodevec_w.word = word;
|
||||
|
||||
ret = trie_walk (trie, collect_closest, &nodevec_w, 0);
|
||||
if (ret > 0)
|
||||
ret = 0;
|
||||
ret = trie_walk(trie, collect_closest, &nodevec_w, 0);
|
||||
if (ret > 0)
|
||||
ret = 0;
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
trienode_reset (trienode_t *node, void *data)
|
||||
trienode_reset(trienode_t *node, void *data)
|
||||
{
|
||||
GF_FREE (node->data);
|
||||
GF_FREE(node->data);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
trie_reset_search (trie_t *trie)
|
||||
trie_reset_search(trie_t *trie)
|
||||
{
|
||||
trie->len = 0;
|
||||
trie->len = 0;
|
||||
|
||||
trie_walk (trie, trienode_reset, NULL, 0);
|
||||
trie_walk(trie, trienode_reset, NULL, 0);
|
||||
}
|
||||
|
@ -18,7 +18,8 @@
|
||||
|
||||
#include <cmocka.h>
|
||||
|
||||
xlator_t **__glusterfs_this_location ()
|
||||
xlator_t **
|
||||
__glusterfs_this_location()
|
||||
{
|
||||
return ((xlator_t **)(uintptr_t)mock());
|
||||
}
|
||||
|
@ -18,33 +18,35 @@
|
||||
|
||||
#include <cmocka.h>
|
||||
|
||||
int _gf_log (const char *domain, const char *file,
|
||||
const char *function, int32_t line, gf_loglevel_t level,
|
||||
const char *fmt, ...)
|
||||
int
|
||||
_gf_log(const char *domain, const char *file, const char *function,
|
||||
int32_t line, gf_loglevel_t level, const char *fmt, ...)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _gf_log_callingfn (const char *domain, const char *file,
|
||||
const char *function, int32_t line, gf_loglevel_t level,
|
||||
const char *fmt, ...)
|
||||
int
|
||||
_gf_log_callingfn(const char *domain, const char *file, const char *function,
|
||||
int32_t line, gf_loglevel_t level, const char *fmt, ...)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _gf_log_nomem (const char *domain, const char *file,
|
||||
const char *function, int line, gf_loglevel_t level,
|
||||
size_t size)
|
||||
int
|
||||
_gf_log_nomem(const char *domain, const char *file, const char *function,
|
||||
int line, gf_loglevel_t level, size_t size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _gf_msg_nomem (const char *domain, const char *file,
|
||||
const char *function, int line, gf_loglevel_t level,
|
||||
size_t size)
|
||||
int
|
||||
_gf_msg_nomem(const char *domain, const char *file, const char *function,
|
||||
int line, gf_loglevel_t level, size_t size)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
gf_log_globals_init (void *data, gf_loglevel_t level) {}
|
||||
gf_log_globals_init(void *data, gf_loglevel_t level)
|
||||
{
|
||||
}
|
||||
|
@ -21,10 +21,10 @@
|
||||
#include <cmocka.h>
|
||||
|
||||
#ifndef assert_ptr_equal
|
||||
#define assert_ptr_equal(a, b) \
|
||||
_assert_int_equal(cast_ptr_to_largest_integral_type(a), \
|
||||
cast_ptr_to_largest_integral_type(b), \
|
||||
__FILE__, __LINE__)
|
||||
#define assert_ptr_equal(a, b) \
|
||||
_assert_int_equal(cast_ptr_to_largest_integral_type(a), \
|
||||
cast_ptr_to_largest_integral_type(b), __FILE__, \
|
||||
__LINE__)
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -42,8 +42,8 @@ typedef struct __attribute__((packed)) {
|
||||
* Prototypes to private functions
|
||||
*/
|
||||
int
|
||||
gf_mem_set_acct_info (xlator_t *xl, char **alloc_ptr, size_t size,
|
||||
uint32_t type, const char *typestr);
|
||||
gf_mem_set_acct_info(xlator_t *xl, char **alloc_ptr, size_t size, uint32_t type,
|
||||
const char *typestr);
|
||||
|
||||
/*
|
||||
* Helper functions
|
||||
@ -59,16 +59,16 @@ helper_xlator_init(uint32_t num_types)
|
||||
xl = test_calloc(1, sizeof(xlator_t));
|
||||
assert_non_null(xl);
|
||||
xl->mem_acct->num_types = num_types;
|
||||
xl->mem_acct = test_calloc (sizeof(struct mem_acct)
|
||||
+ sizeof(struct mem_acct_rec) * num_types);
|
||||
xl->mem_acct = test_calloc(sizeof(struct mem_acct) +
|
||||
sizeof(struct mem_acct_rec) * num_types);
|
||||
assert_non_null(xl->mem_acct);
|
||||
|
||||
xl->ctx = test_calloc(1, sizeof(glusterfs_ctx_t));
|
||||
assert_non_null(xl->ctx);
|
||||
|
||||
for (i = 0; i < num_types; i++) {
|
||||
ret = LOCK_INIT(&(xl->mem_acct->rec[i].lock));
|
||||
assert_int_equal(ret, 0);
|
||||
ret = LOCK_INIT(&(xl->mem_acct->rec[i].lock));
|
||||
assert_int_equal(ret, 0);
|
||||
}
|
||||
|
||||
ENSURE(num_types == xl->mem_acct->num_types);
|
||||
@ -83,8 +83,8 @@ helper_xlator_destroy(xlator_t *xl)
|
||||
int i, ret;
|
||||
|
||||
for (i = 0; i < xl->mem_acct->num_types; i++) {
|
||||
ret = LOCK_DESTROY(&(xl->mem_acct->rec[i].lock));
|
||||
assert_int_equal(ret, 0);
|
||||
ret = LOCK_DESTROY(&(xl->mem_acct->rec[i].lock));
|
||||
assert_int_equal(ret, 0);
|
||||
}
|
||||
|
||||
free(xl->mem_acct->rec);
|
||||
@ -94,20 +94,16 @@ helper_xlator_destroy(xlator_t *xl)
|
||||
}
|
||||
|
||||
static void
|
||||
helper_check_memory_headers( char *mem,
|
||||
xlator_t *xl,
|
||||
size_t size,
|
||||
uint32_t type)
|
||||
helper_check_memory_headers(char *mem, xlator_t *xl, size_t size, uint32_t type)
|
||||
{
|
||||
mem_header_t *p;
|
||||
|
||||
p = (mem_header_t *)mem,
|
||||
assert_int_equal(p->type, type);
|
||||
p = (mem_header_t *)mem, assert_int_equal(p->type, type);
|
||||
assert_int_equal(p->size, size);
|
||||
assert_true(p->xl == xl);
|
||||
assert_int_equal(p->header_magic, GF_MEM_HEADER_MAGIC);
|
||||
assert_true(*(uint32_t *)(mem+sizeof(mem_header_t)+size) == GF_MEM_TRAILER_MAGIC);
|
||||
|
||||
assert_true(*(uint32_t *)(mem + sizeof(mem_header_t) + size) ==
|
||||
GF_MEM_TRAILER_MAGIC);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -116,7 +112,7 @@ helper_check_memory_headers( char *mem,
|
||||
static void
|
||||
test_gf_mem_acct_enable_set(void **state)
|
||||
{
|
||||
(void) state;
|
||||
(void)state;
|
||||
glusterfs_ctx_t test_ctx;
|
||||
|
||||
expect_assert_failure(gf_mem_acct_enable_set(NULL));
|
||||
@ -143,14 +139,16 @@ test_gf_mem_set_acct_info_asserts(void **state)
|
||||
size = 8196;
|
||||
type = 0;
|
||||
|
||||
|
||||
// Check xl is NULL
|
||||
expect_assert_failure(gf_mem_set_acct_info(NULL, &alloc_ptr, size, type, ""));
|
||||
expect_assert_failure(
|
||||
gf_mem_set_acct_info(NULL, &alloc_ptr, size, type, ""));
|
||||
// Check xl->mem_acct = NULL
|
||||
expect_assert_failure(gf_mem_set_acct_info(&xltest, &alloc_ptr, 0, type, ""));
|
||||
expect_assert_failure(
|
||||
gf_mem_set_acct_info(&xltest, &alloc_ptr, 0, type, ""));
|
||||
// Check type <= xl->mem_acct->num_types
|
||||
type = 100;
|
||||
expect_assert_failure(gf_mem_set_acct_info(&xltest, &alloc_ptr, 0, type, ""));
|
||||
expect_assert_failure(
|
||||
gf_mem_set_acct_info(&xltest, &alloc_ptr, 0, type, ""));
|
||||
// Check alloc is NULL
|
||||
assert_int_equal(-1, gf_mem_set_acct_info(&xltest, NULL, size, type, ""));
|
||||
|
||||
@ -189,7 +187,7 @@ test_gf_mem_set_acct_info_memory(void **state)
|
||||
alloc_ptr = temp_ptr;
|
||||
gf_mem_set_acct_info(xl, &alloc_ptr, size, type, typestr);
|
||||
|
||||
//Check values
|
||||
// Check values
|
||||
assert_ptr_equal(typestr, xl->mem_acct->rec[type].typestr);
|
||||
assert_int_equal(xl->mem_acct->rec[type].size, size);
|
||||
assert_int_equal(xl->mem_acct->rec[type].num_allocs, 1);
|
||||
@ -420,10 +418,10 @@ test_gf_realloc_mem_acct_enabled(void **state)
|
||||
// not to the realloc + the malloc.
|
||||
// Is this a bug?
|
||||
//
|
||||
assert_int_equal(xl->mem_acct->rec[type].size, size+1024);
|
||||
assert_int_equal(xl->mem_acct->rec[type].size, size + 1024);
|
||||
assert_int_equal(xl->mem_acct->rec[type].num_allocs, 2);
|
||||
assert_int_equal(xl->mem_acct->rec[type].total_allocs, 2);
|
||||
assert_int_equal(xl->mem_acct->rec[type].max_size, size+1024);
|
||||
assert_int_equal(xl->mem_acct->rec[type].max_size, size + 1024);
|
||||
assert_int_equal(xl->mem_acct->rec[type].max_num_allocs, 2);
|
||||
|
||||
// Check memory
|
||||
@ -465,7 +463,9 @@ test_gf_realloc_ptr(void **state)
|
||||
helper_xlator_destroy(xl);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest libglusterfs_mem_pool_tests[] = {
|
||||
cmocka_unit_test(test_gf_mem_acct_enable_set),
|
||||
cmocka_unit_test(test_gf_mem_set_acct_info_asserts),
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -8,8 +8,6 @@
|
||||
cases as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "rpcsvc.h"
|
||||
#include "list.h"
|
||||
#include "dict.h"
|
||||
@ -21,386 +19,369 @@
|
||||
/* V1 */
|
||||
|
||||
ssize_t
|
||||
xdr_to_glusterfs_auth (char *buf, struct auth_glusterfs_parms *req)
|
||||
xdr_to_glusterfs_auth(char *buf, struct auth_glusterfs_parms *req)
|
||||
{
|
||||
XDR xdr;
|
||||
ssize_t ret = -1;
|
||||
XDR xdr;
|
||||
ssize_t ret = -1;
|
||||
|
||||
if ((!buf) || (!req))
|
||||
return -1;
|
||||
if ((!buf) || (!req))
|
||||
return -1;
|
||||
|
||||
xdrmem_create (&xdr, buf, sizeof (struct auth_glusterfs_parms),
|
||||
XDR_DECODE);
|
||||
if (!xdr_auth_glusterfs_parms (&xdr, req)) {
|
||||
gf_log ("", GF_LOG_WARNING,
|
||||
"failed to decode glusterfs parameters");
|
||||
ret = -1;
|
||||
goto ret;
|
||||
}
|
||||
xdrmem_create(&xdr, buf, sizeof(struct auth_glusterfs_parms), XDR_DECODE);
|
||||
if (!xdr_auth_glusterfs_parms(&xdr, req)) {
|
||||
gf_log("", GF_LOG_WARNING, "failed to decode glusterfs parameters");
|
||||
ret = -1;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
ret = (((size_t)(&xdr)->x_private) - ((size_t)(&xdr)->x_base));
|
||||
ret = (((size_t)(&xdr)->x_private) - ((size_t)(&xdr)->x_base));
|
||||
ret:
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
int
|
||||
auth_glusterfs_request_init (rpcsvc_request_t *req, void *priv)
|
||||
auth_glusterfs_request_init(rpcsvc_request_t *req, void *priv)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int auth_glusterfs_authenticate (rpcsvc_request_t *req, void *priv)
|
||||
int
|
||||
auth_glusterfs_authenticate(rpcsvc_request_t *req, void *priv)
|
||||
{
|
||||
struct auth_glusterfs_parms au = {0,};
|
||||
struct auth_glusterfs_parms au = {
|
||||
0,
|
||||
};
|
||||
|
||||
int ret = RPCSVC_AUTH_REJECT;
|
||||
int j = 0;
|
||||
int i = 0;
|
||||
int gidcount = 0;
|
||||
int ret = RPCSVC_AUTH_REJECT;
|
||||
int j = 0;
|
||||
int i = 0;
|
||||
int gidcount = 0;
|
||||
|
||||
if (!req)
|
||||
return ret;
|
||||
|
||||
ret = xdr_to_glusterfs_auth (req->cred.authdata, &au);
|
||||
if (ret == -1) {
|
||||
gf_log ("", GF_LOG_WARNING,
|
||||
"failed to decode glusterfs credentials");
|
||||
ret = RPCSVC_AUTH_REJECT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
req->pid = au.pid;
|
||||
req->uid = au.uid;
|
||||
req->gid = au.gid;
|
||||
req->lk_owner.len = 8;
|
||||
{
|
||||
for (i = 0; i < req->lk_owner.len; i++, j += 8)
|
||||
req->lk_owner.data[i] = (char)((au.lk_owner >> j) & 0xff);
|
||||
}
|
||||
req->auxgidcount = au.ngrps;
|
||||
|
||||
if (req->auxgidcount > 16) {
|
||||
gf_log ("", GF_LOG_WARNING,
|
||||
"more than 16 aux gids found, failing authentication");
|
||||
ret = RPCSVC_AUTH_REJECT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (req->auxgidcount > SMALL_GROUP_COUNT) {
|
||||
req->auxgidlarge = GF_CALLOC(req->auxgidcount,
|
||||
sizeof(req->auxgids[0]),
|
||||
gf_common_mt_auxgids);
|
||||
req->auxgids = req->auxgidlarge;
|
||||
} else {
|
||||
req->auxgids = req->auxgidsmall;
|
||||
}
|
||||
|
||||
if (!req->auxgids) {
|
||||
gf_log ("auth-glusterfs", GF_LOG_WARNING,
|
||||
"cannot allocate gid list");
|
||||
ret = RPCSVC_AUTH_REJECT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (gidcount = 0; gidcount < au.ngrps; ++gidcount)
|
||||
req->auxgids[gidcount] = au.groups[gidcount];
|
||||
|
||||
|
||||
gf_log (GF_RPCSVC, GF_LOG_TRACE, "Auth Info: pid: %u, uid: %d"
|
||||
", gid: %d, owner: %s",
|
||||
req->pid, req->uid, req->gid, lkowner_utoa (&req->lk_owner));
|
||||
ret = RPCSVC_AUTH_ACCEPT;
|
||||
err:
|
||||
if (!req)
|
||||
return ret;
|
||||
|
||||
ret = xdr_to_glusterfs_auth(req->cred.authdata, &au);
|
||||
if (ret == -1) {
|
||||
gf_log("", GF_LOG_WARNING, "failed to decode glusterfs credentials");
|
||||
ret = RPCSVC_AUTH_REJECT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
req->pid = au.pid;
|
||||
req->uid = au.uid;
|
||||
req->gid = au.gid;
|
||||
req->lk_owner.len = 8;
|
||||
{
|
||||
for (i = 0; i < req->lk_owner.len; i++, j += 8)
|
||||
req->lk_owner.data[i] = (char)((au.lk_owner >> j) & 0xff);
|
||||
}
|
||||
req->auxgidcount = au.ngrps;
|
||||
|
||||
if (req->auxgidcount > 16) {
|
||||
gf_log("", GF_LOG_WARNING,
|
||||
"more than 16 aux gids found, failing authentication");
|
||||
ret = RPCSVC_AUTH_REJECT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (req->auxgidcount > SMALL_GROUP_COUNT) {
|
||||
req->auxgidlarge = GF_CALLOC(req->auxgidcount, sizeof(req->auxgids[0]),
|
||||
gf_common_mt_auxgids);
|
||||
req->auxgids = req->auxgidlarge;
|
||||
} else {
|
||||
req->auxgids = req->auxgidsmall;
|
||||
}
|
||||
|
||||
if (!req->auxgids) {
|
||||
gf_log("auth-glusterfs", GF_LOG_WARNING, "cannot allocate gid list");
|
||||
ret = RPCSVC_AUTH_REJECT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (gidcount = 0; gidcount < au.ngrps; ++gidcount)
|
||||
req->auxgids[gidcount] = au.groups[gidcount];
|
||||
|
||||
gf_log(GF_RPCSVC, GF_LOG_TRACE,
|
||||
"Auth Info: pid: %u, uid: %d"
|
||||
", gid: %d, owner: %s",
|
||||
req->pid, req->uid, req->gid, lkowner_utoa(&req->lk_owner));
|
||||
ret = RPCSVC_AUTH_ACCEPT;
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
rpcsvc_auth_ops_t auth_glusterfs_ops = {
|
||||
.transport_init = NULL,
|
||||
.request_init = auth_glusterfs_request_init,
|
||||
.authenticate = auth_glusterfs_authenticate
|
||||
};
|
||||
|
||||
rpcsvc_auth_t rpcsvc_auth_glusterfs = {
|
||||
.authname = "AUTH_GLUSTERFS",
|
||||
.authnum = AUTH_GLUSTERFS,
|
||||
.authops = &auth_glusterfs_ops,
|
||||
.authprivate = NULL
|
||||
};
|
||||
.transport_init = NULL,
|
||||
.request_init = auth_glusterfs_request_init,
|
||||
.authenticate = auth_glusterfs_authenticate};
|
||||
|
||||
rpcsvc_auth_t rpcsvc_auth_glusterfs = {.authname = "AUTH_GLUSTERFS",
|
||||
.authnum = AUTH_GLUSTERFS,
|
||||
.authops = &auth_glusterfs_ops,
|
||||
.authprivate = NULL};
|
||||
|
||||
rpcsvc_auth_t *
|
||||
rpcsvc_auth_glusterfs_init (rpcsvc_t *svc, dict_t *options)
|
||||
rpcsvc_auth_glusterfs_init(rpcsvc_t *svc, dict_t *options)
|
||||
{
|
||||
return &rpcsvc_auth_glusterfs;
|
||||
return &rpcsvc_auth_glusterfs;
|
||||
}
|
||||
|
||||
/* V2 */
|
||||
|
||||
ssize_t
|
||||
xdr_to_glusterfs_auth_v2 (char *buf, struct auth_glusterfs_parms_v2 *req)
|
||||
xdr_to_glusterfs_auth_v2(char *buf, struct auth_glusterfs_parms_v2 *req)
|
||||
{
|
||||
XDR xdr;
|
||||
ssize_t ret = -1;
|
||||
XDR xdr;
|
||||
ssize_t ret = -1;
|
||||
|
||||
if ((!buf) || (!req))
|
||||
return -1;
|
||||
if ((!buf) || (!req))
|
||||
return -1;
|
||||
|
||||
xdrmem_create (&xdr, buf, GF_MAX_AUTH_BYTES, XDR_DECODE);
|
||||
if (!xdr_auth_glusterfs_parms_v2 (&xdr, req)) {
|
||||
gf_log ("", GF_LOG_WARNING,
|
||||
"failed to decode glusterfs v2 parameters");
|
||||
ret = -1;
|
||||
goto ret;
|
||||
}
|
||||
xdrmem_create(&xdr, buf, GF_MAX_AUTH_BYTES, XDR_DECODE);
|
||||
if (!xdr_auth_glusterfs_parms_v2(&xdr, req)) {
|
||||
gf_log("", GF_LOG_WARNING, "failed to decode glusterfs v2 parameters");
|
||||
ret = -1;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
ret = (((size_t)(&xdr)->x_private) - ((size_t)(&xdr)->x_base));
|
||||
ret = (((size_t)(&xdr)->x_private) - ((size_t)(&xdr)->x_base));
|
||||
ret:
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
int
|
||||
auth_glusterfs_v2_request_init (rpcsvc_request_t *req, void *priv)
|
||||
auth_glusterfs_v2_request_init(rpcsvc_request_t *req, void *priv)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int auth_glusterfs_v2_authenticate (rpcsvc_request_t *req, void *priv)
|
||||
int
|
||||
auth_glusterfs_v2_authenticate(rpcsvc_request_t *req, void *priv)
|
||||
{
|
||||
struct auth_glusterfs_parms_v2 au = {0,};
|
||||
int ret = RPCSVC_AUTH_REJECT;
|
||||
int i = 0;
|
||||
int max_groups = 0;
|
||||
int max_lk_owner_len = 0;
|
||||
|
||||
if (!req)
|
||||
return ret;
|
||||
|
||||
ret = xdr_to_glusterfs_auth_v2 (req->cred.authdata, &au);
|
||||
if (ret == -1) {
|
||||
gf_log ("", GF_LOG_WARNING,
|
||||
"failed to decode glusterfs credentials");
|
||||
ret = RPCSVC_AUTH_REJECT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
req->pid = au.pid;
|
||||
req->uid = au.uid;
|
||||
req->gid = au.gid;
|
||||
req->lk_owner.len = au.lk_owner.lk_owner_len;
|
||||
req->auxgidcount = au.groups.groups_len;
|
||||
|
||||
/* the number of groups and size of lk_owner depend on each other */
|
||||
max_groups = GF_AUTH_GLUSTERFS_MAX_GROUPS (req->lk_owner.len,
|
||||
AUTH_GLUSTERFS_v2);
|
||||
max_lk_owner_len = GF_AUTH_GLUSTERFS_MAX_LKOWNER (req->auxgidcount,
|
||||
AUTH_GLUSTERFS_v2);
|
||||
|
||||
if (req->auxgidcount > max_groups) {
|
||||
gf_log ("", GF_LOG_WARNING,
|
||||
"more than max aux gids found (%d) , truncating it "
|
||||
"to %d and continuing", au.groups.groups_len,
|
||||
max_groups);
|
||||
req->auxgidcount = max_groups;
|
||||
}
|
||||
|
||||
if (req->lk_owner.len > max_lk_owner_len) {
|
||||
gf_log ("", GF_LOG_WARNING,
|
||||
"lkowner field to big (%d), depends on the number of "
|
||||
"groups (%d), failing authentication",
|
||||
req->lk_owner.len, req->auxgidcount);
|
||||
ret = RPCSVC_AUTH_REJECT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (req->auxgidcount > SMALL_GROUP_COUNT) {
|
||||
req->auxgidlarge = GF_CALLOC(req->auxgidcount,
|
||||
sizeof(req->auxgids[0]),
|
||||
gf_common_mt_auxgids);
|
||||
req->auxgids = req->auxgidlarge;
|
||||
} else {
|
||||
req->auxgids = req->auxgidsmall;
|
||||
}
|
||||
|
||||
if (!req->auxgids) {
|
||||
gf_log ("auth-glusterfs-v2", GF_LOG_WARNING,
|
||||
"cannot allocate gid list");
|
||||
ret = RPCSVC_AUTH_REJECT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (i = 0; i < req->auxgidcount; ++i)
|
||||
req->auxgids[i] = au.groups.groups_val[i];
|
||||
|
||||
for (i = 0; i < au.lk_owner.lk_owner_len; ++i)
|
||||
req->lk_owner.data[i] = au.lk_owner.lk_owner_val[i];
|
||||
|
||||
|
||||
gf_log (GF_RPCSVC, GF_LOG_TRACE, "Auth Info: pid: %u, uid: %d"
|
||||
", gid: %d, owner: %s",
|
||||
req->pid, req->uid, req->gid, lkowner_utoa (&req->lk_owner));
|
||||
ret = RPCSVC_AUTH_ACCEPT;
|
||||
err:
|
||||
/* TODO: instead use alloca() for these variables */
|
||||
free (au.groups.groups_val);
|
||||
free (au.lk_owner.lk_owner_val);
|
||||
struct auth_glusterfs_parms_v2 au = {
|
||||
0,
|
||||
};
|
||||
int ret = RPCSVC_AUTH_REJECT;
|
||||
int i = 0;
|
||||
int max_groups = 0;
|
||||
int max_lk_owner_len = 0;
|
||||
|
||||
if (!req)
|
||||
return ret;
|
||||
|
||||
ret = xdr_to_glusterfs_auth_v2(req->cred.authdata, &au);
|
||||
if (ret == -1) {
|
||||
gf_log("", GF_LOG_WARNING, "failed to decode glusterfs credentials");
|
||||
ret = RPCSVC_AUTH_REJECT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
req->pid = au.pid;
|
||||
req->uid = au.uid;
|
||||
req->gid = au.gid;
|
||||
req->lk_owner.len = au.lk_owner.lk_owner_len;
|
||||
req->auxgidcount = au.groups.groups_len;
|
||||
|
||||
/* the number of groups and size of lk_owner depend on each other */
|
||||
max_groups = GF_AUTH_GLUSTERFS_MAX_GROUPS(req->lk_owner.len,
|
||||
AUTH_GLUSTERFS_v2);
|
||||
max_lk_owner_len = GF_AUTH_GLUSTERFS_MAX_LKOWNER(req->auxgidcount,
|
||||
AUTH_GLUSTERFS_v2);
|
||||
|
||||
if (req->auxgidcount > max_groups) {
|
||||
gf_log("", GF_LOG_WARNING,
|
||||
"more than max aux gids found (%d) , truncating it "
|
||||
"to %d and continuing",
|
||||
au.groups.groups_len, max_groups);
|
||||
req->auxgidcount = max_groups;
|
||||
}
|
||||
|
||||
if (req->lk_owner.len > max_lk_owner_len) {
|
||||
gf_log("", GF_LOG_WARNING,
|
||||
"lkowner field to big (%d), depends on the number of "
|
||||
"groups (%d), failing authentication",
|
||||
req->lk_owner.len, req->auxgidcount);
|
||||
ret = RPCSVC_AUTH_REJECT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (req->auxgidcount > SMALL_GROUP_COUNT) {
|
||||
req->auxgidlarge = GF_CALLOC(req->auxgidcount, sizeof(req->auxgids[0]),
|
||||
gf_common_mt_auxgids);
|
||||
req->auxgids = req->auxgidlarge;
|
||||
} else {
|
||||
req->auxgids = req->auxgidsmall;
|
||||
}
|
||||
|
||||
if (!req->auxgids) {
|
||||
gf_log("auth-glusterfs-v2", GF_LOG_WARNING, "cannot allocate gid list");
|
||||
ret = RPCSVC_AUTH_REJECT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (i = 0; i < req->auxgidcount; ++i)
|
||||
req->auxgids[i] = au.groups.groups_val[i];
|
||||
|
||||
for (i = 0; i < au.lk_owner.lk_owner_len; ++i)
|
||||
req->lk_owner.data[i] = au.lk_owner.lk_owner_val[i];
|
||||
|
||||
gf_log(GF_RPCSVC, GF_LOG_TRACE,
|
||||
"Auth Info: pid: %u, uid: %d"
|
||||
", gid: %d, owner: %s",
|
||||
req->pid, req->uid, req->gid, lkowner_utoa(&req->lk_owner));
|
||||
ret = RPCSVC_AUTH_ACCEPT;
|
||||
err:
|
||||
/* TODO: instead use alloca() for these variables */
|
||||
free(au.groups.groups_val);
|
||||
free(au.lk_owner.lk_owner_val);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
rpcsvc_auth_ops_t auth_glusterfs_ops_v2 = {
|
||||
.transport_init = NULL,
|
||||
.request_init = auth_glusterfs_v2_request_init,
|
||||
.authenticate = auth_glusterfs_v2_authenticate
|
||||
};
|
||||
|
||||
rpcsvc_auth_t rpcsvc_auth_glusterfs_v2 = {
|
||||
.authname = "AUTH_GLUSTERFS-v2",
|
||||
.authnum = AUTH_GLUSTERFS_v2,
|
||||
.authops = &auth_glusterfs_ops_v2,
|
||||
.authprivate = NULL
|
||||
};
|
||||
.transport_init = NULL,
|
||||
.request_init = auth_glusterfs_v2_request_init,
|
||||
.authenticate = auth_glusterfs_v2_authenticate};
|
||||
|
||||
rpcsvc_auth_t rpcsvc_auth_glusterfs_v2 = {.authname = "AUTH_GLUSTERFS-v2",
|
||||
.authnum = AUTH_GLUSTERFS_v2,
|
||||
.authops = &auth_glusterfs_ops_v2,
|
||||
.authprivate = NULL};
|
||||
|
||||
rpcsvc_auth_t *
|
||||
rpcsvc_auth_glusterfs_v2_init (rpcsvc_t *svc, dict_t *options)
|
||||
rpcsvc_auth_glusterfs_v2_init(rpcsvc_t *svc, dict_t *options)
|
||||
{
|
||||
return &rpcsvc_auth_glusterfs_v2;
|
||||
return &rpcsvc_auth_glusterfs_v2;
|
||||
}
|
||||
|
||||
/* V3 */
|
||||
|
||||
ssize_t
|
||||
xdr_to_glusterfs_auth_v3 (char *buf, struct auth_glusterfs_params_v3 *req)
|
||||
xdr_to_glusterfs_auth_v3(char *buf, struct auth_glusterfs_params_v3 *req)
|
||||
{
|
||||
XDR xdr;
|
||||
ssize_t ret = -1;
|
||||
XDR xdr;
|
||||
ssize_t ret = -1;
|
||||
|
||||
if ((!buf) || (!req))
|
||||
return -1;
|
||||
if ((!buf) || (!req))
|
||||
return -1;
|
||||
|
||||
xdrmem_create (&xdr, buf, GF_MAX_AUTH_BYTES, XDR_DECODE);
|
||||
if (!xdr_auth_glusterfs_params_v3 (&xdr, req)) {
|
||||
gf_log ("", GF_LOG_WARNING,
|
||||
"failed to decode glusterfs v3 parameters");
|
||||
ret = -1;
|
||||
goto ret;
|
||||
}
|
||||
xdrmem_create(&xdr, buf, GF_MAX_AUTH_BYTES, XDR_DECODE);
|
||||
if (!xdr_auth_glusterfs_params_v3(&xdr, req)) {
|
||||
gf_log("", GF_LOG_WARNING, "failed to decode glusterfs v3 parameters");
|
||||
ret = -1;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
ret = (((size_t)(&xdr)->x_private) - ((size_t)(&xdr)->x_base));
|
||||
ret = (((size_t)(&xdr)->x_private) - ((size_t)(&xdr)->x_base));
|
||||
ret:
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
auth_glusterfs_v3_request_init (rpcsvc_request_t *req, void *priv)
|
||||
auth_glusterfs_v3_request_init(rpcsvc_request_t *req, void *priv)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int auth_glusterfs_v3_authenticate (rpcsvc_request_t *req, void *priv)
|
||||
int
|
||||
auth_glusterfs_v3_authenticate(rpcsvc_request_t *req, void *priv)
|
||||
{
|
||||
struct auth_glusterfs_params_v3 au = {0,};
|
||||
int ret = RPCSVC_AUTH_REJECT;
|
||||
int i = 0;
|
||||
int max_groups = 0;
|
||||
int max_lk_owner_len = 0;
|
||||
|
||||
if (!req)
|
||||
return ret;
|
||||
|
||||
ret = xdr_to_glusterfs_auth_v3 (req->cred.authdata, &au);
|
||||
if (ret == -1) {
|
||||
gf_log ("", GF_LOG_WARNING,
|
||||
"failed to decode glusterfs credentials");
|
||||
ret = RPCSVC_AUTH_REJECT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
req->pid = au.pid;
|
||||
req->uid = au.uid;
|
||||
req->gid = au.gid;
|
||||
req->lk_owner.len = au.lk_owner.lk_owner_len;
|
||||
req->auxgidcount = au.groups.groups_len;
|
||||
|
||||
/* the number of groups and size of lk_owner depend on each other */
|
||||
max_groups = GF_AUTH_GLUSTERFS_MAX_GROUPS (req->lk_owner.len,
|
||||
AUTH_GLUSTERFS_v3);
|
||||
max_lk_owner_len = GF_AUTH_GLUSTERFS_MAX_LKOWNER (req->auxgidcount,
|
||||
AUTH_GLUSTERFS_v3);
|
||||
|
||||
if (req->auxgidcount > max_groups) {
|
||||
gf_log ("", GF_LOG_WARNING,
|
||||
"more than max aux gids found (%d) , truncating it "
|
||||
"to %d and continuing", au.groups.groups_len,
|
||||
max_groups);
|
||||
req->auxgidcount = max_groups;
|
||||
}
|
||||
|
||||
if (req->lk_owner.len > max_lk_owner_len) {
|
||||
gf_log ("", GF_LOG_WARNING,
|
||||
"lkowner field to big (%d), depends on the number of "
|
||||
"groups (%d), failing authentication",
|
||||
req->lk_owner.len, req->auxgidcount);
|
||||
ret = RPCSVC_AUTH_REJECT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (req->auxgidcount > SMALL_GROUP_COUNT) {
|
||||
req->auxgidlarge = GF_CALLOC(req->auxgidcount,
|
||||
sizeof(req->auxgids[0]),
|
||||
gf_common_mt_auxgids);
|
||||
req->auxgids = req->auxgidlarge;
|
||||
} else {
|
||||
req->auxgids = req->auxgidsmall;
|
||||
}
|
||||
|
||||
if (!req->auxgids) {
|
||||
gf_log ("auth-glusterfs-v2", GF_LOG_WARNING,
|
||||
"cannot allocate gid list");
|
||||
ret = RPCSVC_AUTH_REJECT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (i = 0; i < req->auxgidcount; ++i)
|
||||
req->auxgids[i] = au.groups.groups_val[i];
|
||||
|
||||
for (i = 0; i < au.lk_owner.lk_owner_len; ++i)
|
||||
req->lk_owner.data[i] = au.lk_owner.lk_owner_val[i];
|
||||
|
||||
/* All new things, starting glusterfs-4.0.0 */
|
||||
req->flags = au.flags;
|
||||
req->ctime.tv_sec = au.ctime_sec;
|
||||
req->ctime.tv_nsec = au.ctime_nsec;
|
||||
|
||||
gf_log (GF_RPCSVC, GF_LOG_TRACE, "Auth Info: pid: %u, uid: %d"
|
||||
", gid: %d, owner: %s, flags: %d",
|
||||
req->pid, req->uid, req->gid, lkowner_utoa (&req->lk_owner),
|
||||
req->flags);
|
||||
ret = RPCSVC_AUTH_ACCEPT;
|
||||
err:
|
||||
/* TODO: instead use alloca() for these variables */
|
||||
free (au.groups.groups_val);
|
||||
free (au.lk_owner.lk_owner_val);
|
||||
struct auth_glusterfs_params_v3 au = {
|
||||
0,
|
||||
};
|
||||
int ret = RPCSVC_AUTH_REJECT;
|
||||
int i = 0;
|
||||
int max_groups = 0;
|
||||
int max_lk_owner_len = 0;
|
||||
|
||||
if (!req)
|
||||
return ret;
|
||||
|
||||
ret = xdr_to_glusterfs_auth_v3(req->cred.authdata, &au);
|
||||
if (ret == -1) {
|
||||
gf_log("", GF_LOG_WARNING, "failed to decode glusterfs credentials");
|
||||
ret = RPCSVC_AUTH_REJECT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
req->pid = au.pid;
|
||||
req->uid = au.uid;
|
||||
req->gid = au.gid;
|
||||
req->lk_owner.len = au.lk_owner.lk_owner_len;
|
||||
req->auxgidcount = au.groups.groups_len;
|
||||
|
||||
/* the number of groups and size of lk_owner depend on each other */
|
||||
max_groups = GF_AUTH_GLUSTERFS_MAX_GROUPS(req->lk_owner.len,
|
||||
AUTH_GLUSTERFS_v3);
|
||||
max_lk_owner_len = GF_AUTH_GLUSTERFS_MAX_LKOWNER(req->auxgidcount,
|
||||
AUTH_GLUSTERFS_v3);
|
||||
|
||||
if (req->auxgidcount > max_groups) {
|
||||
gf_log("", GF_LOG_WARNING,
|
||||
"more than max aux gids found (%d) , truncating it "
|
||||
"to %d and continuing",
|
||||
au.groups.groups_len, max_groups);
|
||||
req->auxgidcount = max_groups;
|
||||
}
|
||||
|
||||
if (req->lk_owner.len > max_lk_owner_len) {
|
||||
gf_log("", GF_LOG_WARNING,
|
||||
"lkowner field to big (%d), depends on the number of "
|
||||
"groups (%d), failing authentication",
|
||||
req->lk_owner.len, req->auxgidcount);
|
||||
ret = RPCSVC_AUTH_REJECT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (req->auxgidcount > SMALL_GROUP_COUNT) {
|
||||
req->auxgidlarge = GF_CALLOC(req->auxgidcount, sizeof(req->auxgids[0]),
|
||||
gf_common_mt_auxgids);
|
||||
req->auxgids = req->auxgidlarge;
|
||||
} else {
|
||||
req->auxgids = req->auxgidsmall;
|
||||
}
|
||||
|
||||
if (!req->auxgids) {
|
||||
gf_log("auth-glusterfs-v2", GF_LOG_WARNING, "cannot allocate gid list");
|
||||
ret = RPCSVC_AUTH_REJECT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (i = 0; i < req->auxgidcount; ++i)
|
||||
req->auxgids[i] = au.groups.groups_val[i];
|
||||
|
||||
for (i = 0; i < au.lk_owner.lk_owner_len; ++i)
|
||||
req->lk_owner.data[i] = au.lk_owner.lk_owner_val[i];
|
||||
|
||||
/* All new things, starting glusterfs-4.0.0 */
|
||||
req->flags = au.flags;
|
||||
req->ctime.tv_sec = au.ctime_sec;
|
||||
req->ctime.tv_nsec = au.ctime_nsec;
|
||||
|
||||
gf_log(GF_RPCSVC, GF_LOG_TRACE,
|
||||
"Auth Info: pid: %u, uid: %d"
|
||||
", gid: %d, owner: %s, flags: %d",
|
||||
req->pid, req->uid, req->gid, lkowner_utoa(&req->lk_owner),
|
||||
req->flags);
|
||||
ret = RPCSVC_AUTH_ACCEPT;
|
||||
err:
|
||||
/* TODO: instead use alloca() for these variables */
|
||||
free(au.groups.groups_val);
|
||||
free(au.lk_owner.lk_owner_val);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
rpcsvc_auth_ops_t auth_glusterfs_ops_v3 = {
|
||||
.transport_init = NULL,
|
||||
.request_init = auth_glusterfs_v3_request_init,
|
||||
.authenticate = auth_glusterfs_v3_authenticate
|
||||
};
|
||||
|
||||
rpcsvc_auth_t rpcsvc_auth_glusterfs_v3 = {
|
||||
.authname = "AUTH_GLUSTERFS-v3",
|
||||
.authnum = AUTH_GLUSTERFS_v3,
|
||||
.authops = &auth_glusterfs_ops_v3,
|
||||
.authprivate = NULL
|
||||
};
|
||||
.transport_init = NULL,
|
||||
.request_init = auth_glusterfs_v3_request_init,
|
||||
.authenticate = auth_glusterfs_v3_authenticate};
|
||||
|
||||
rpcsvc_auth_t rpcsvc_auth_glusterfs_v3 = {.authname = "AUTH_GLUSTERFS-v3",
|
||||
.authnum = AUTH_GLUSTERFS_v3,
|
||||
.authops = &auth_glusterfs_ops_v3,
|
||||
.authprivate = NULL};
|
||||
|
||||
rpcsvc_auth_t *
|
||||
rpcsvc_auth_glusterfs_v3_init (rpcsvc_t *svc, dict_t *options)
|
||||
rpcsvc_auth_glusterfs_v3_init(rpcsvc_t *svc, dict_t *options)
|
||||
{
|
||||
return &rpcsvc_auth_glusterfs_v3;
|
||||
return &rpcsvc_auth_glusterfs_v3;
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user