Change module command parameter types
This commit introduces safe session references that can be handled without holding locks. This allows the safe searching of sessions with the unique ID of the session. Remove the use of raw pointers passed as strings. Change the comments of the argument types and add more details to the parsing function documentation.
This commit is contained in:
@ -277,25 +277,15 @@ static bool process_argument(modulecmd_arg_type_t *type, const void* value,
|
||||
break;
|
||||
|
||||
case MODULECMD_ARG_SESSION:
|
||||
arg->type.type = MODULECMD_ARG_SESSION;
|
||||
arg->value.session = (SESSION*)strtol((char*)value, NULL, 0);
|
||||
rval = true;
|
||||
break;
|
||||
|
||||
case MODULECMD_ARG_SESSION_PTR:
|
||||
arg->type.type = MODULECMD_ARG_SESSION_PTR;
|
||||
arg->value.session = (SESSION*)value;
|
||||
if ((arg->value.session = session_get_ref(atoi(value))))
|
||||
{
|
||||
arg->type.type = MODULECMD_ARG_SESSION;
|
||||
}
|
||||
rval = true;
|
||||
break;
|
||||
|
||||
case MODULECMD_ARG_DCB:
|
||||
arg->type.type = MODULECMD_ARG_DCB;
|
||||
arg->value.dcb = (DCB*)strtol((char*)value, NULL, 0);
|
||||
rval = true;
|
||||
break;
|
||||
|
||||
case MODULECMD_ARG_DCB_PTR:
|
||||
arg->type.type = MODULECMD_ARG_DCB_PTR;
|
||||
arg->value.dcb = (DCB*)value;
|
||||
rval = true;
|
||||
break;
|
||||
@ -373,6 +363,10 @@ static void free_argument(struct arg_node *arg)
|
||||
MXS_FREE(arg->value.string);
|
||||
break;
|
||||
|
||||
case MODULECMD_ARG_SESSION:
|
||||
session_put_ref(arg->value.session);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -625,18 +619,10 @@ char* modulecmd_argtype_to_str(modulecmd_arg_type_t *type)
|
||||
strtype = "SESSION";
|
||||
break;
|
||||
|
||||
case MODULECMD_ARG_SESSION_PTR:
|
||||
strtype = "SESSION_PTR";
|
||||
break;
|
||||
|
||||
case MODULECMD_ARG_DCB:
|
||||
strtype = "DCB";
|
||||
break;
|
||||
|
||||
case MODULECMD_ARG_DCB_PTR:
|
||||
strtype = "DCB_PTR";
|
||||
break;
|
||||
|
||||
case MODULECMD_ARG_MONITOR:
|
||||
strtype = "MONITOR";
|
||||
break;
|
||||
|
||||
@ -915,3 +915,40 @@ const char* session_trx_state_to_string(session_trx_state_t state)
|
||||
MXS_ERROR("Unknown session_trx_state_t value: %d", (int)state);
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
static bool ses_find_id(DCB *dcb, void *data)
|
||||
{
|
||||
void **params = (void**)data;
|
||||
SESSION **ses = (SESSION**)params[0];
|
||||
int *id = (int*)params[1];
|
||||
bool rval = true;
|
||||
|
||||
if (dcb->session->ses_id == *id)
|
||||
{
|
||||
/** We need to increment the reference count of the session to prevent it
|
||||
* from being freed while it's in use. */
|
||||
atomic_add(&dcb->session->refcount, 1);
|
||||
*ses = dcb->session;
|
||||
rval = false;
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
SESSION* session_get_ref(int id)
|
||||
{
|
||||
SESSION *session = NULL;
|
||||
void *params[] = {&session, &id};
|
||||
|
||||
dcb_foreach(ses_find_id, params);
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
void session_put_ref(SESSION *session)
|
||||
{
|
||||
if (session)
|
||||
{
|
||||
session_free(session);
|
||||
}
|
||||
}
|
||||
|
||||
@ -305,16 +305,12 @@ int test_map()
|
||||
}
|
||||
|
||||
static DCB my_dcb;
|
||||
static SESSION my_session;
|
||||
|
||||
bool ptrfn(const MODULECMD_ARG *argv)
|
||||
{
|
||||
bool rval = false;
|
||||
|
||||
if (argv->argc == 4 && argv->argv[0].value.dcb == &my_dcb &&
|
||||
argv->argv[1].value.dcb == &my_dcb &&
|
||||
argv->argv[2].value.session == &my_session &&
|
||||
argv->argv[3].value.session == &my_session)
|
||||
if (argv->argc == 1 && argv->argv[0].value.dcb == &my_dcb)
|
||||
{
|
||||
rval = true;
|
||||
}
|
||||
@ -329,26 +325,18 @@ int test_pointers()
|
||||
|
||||
modulecmd_arg_type_t args[] =
|
||||
{
|
||||
{MODULECMD_ARG_DCB, ""},
|
||||
{MODULECMD_ARG_DCB_PTR, ""},
|
||||
{MODULECMD_ARG_SESSION, ""},
|
||||
{MODULECMD_ARG_SESSION_PTR, ""}
|
||||
{MODULECMD_ARG_DCB, ""}
|
||||
};
|
||||
|
||||
TEST(modulecmd_register_command(ns, id, ptrfn, 4, args), "Registering a command should succeed");
|
||||
TEST(modulecmd_register_command(ns, id, ptrfn, 1, args), "Registering a command should succeed");
|
||||
TEST(strlen(modulecmd_get_error()) == 0, "Error message should be empty");
|
||||
|
||||
const MODULECMD *cmd = modulecmd_find_command(ns, id);
|
||||
TEST(cmd, "The registered command should be found");
|
||||
char dcb_str[200];
|
||||
char session_str[200];
|
||||
|
||||
sprintf(dcb_str, "%p", &my_dcb);
|
||||
sprintf(session_str, "%p", &my_session);
|
||||
const void* params[] = {&my_dcb};
|
||||
|
||||
const void* params[] = {dcb_str, &my_dcb, session_str, &my_session};
|
||||
|
||||
MODULECMD_ARG *arg = modulecmd_arg_parse(cmd, 4, params);
|
||||
MODULECMD_ARG *arg = modulecmd_arg_parse(cmd, 1, params);
|
||||
TEST(arg, "Parsing arguments should succeed");
|
||||
TEST(strlen(modulecmd_get_error()) == 0, "Error message should be empty");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user