Figure out path of plugin process executable.
The plugin process executable is assumed to be installed in the same directory as the maxscale executable.
This commit is contained in:
parent
62aa1ea5d7
commit
1e363b9ad7
@ -35,28 +35,169 @@
|
||||
#define QC_TRACE()
|
||||
#endif
|
||||
|
||||
static QUERY_CLASSIFIER* classifier;
|
||||
static const char qc_mysqlembedded[] = "qc_mysqlembedded";
|
||||
static const char QC_MYSQLEMBEDDED[] = "qc_mysqlembedded"; // The qc plugin we'll temporarily use.
|
||||
static const char MAXPP[] = "maxpp"; // The name of the plugin process executable.
|
||||
|
||||
|
||||
static bool qc_pp_init(void)
|
||||
static struct pp_self
|
||||
{
|
||||
QC_TRACE();
|
||||
ss_dassert(!classifier);
|
||||
QUERY_CLASSIFIER* classifier; // The classifier.
|
||||
char classifier_name[PATH_MAX]; // The name of the classifier.
|
||||
pid_t pp_pid; // The pid of the plugin process.
|
||||
char pp_path[PATH_MAX]; // The path of the plugin process.
|
||||
} *self = 0;
|
||||
|
||||
bool success = false;
|
||||
void* module = load_module(qc_mysqlembedded, MODULE_QUERY_CLASSIFIER);
|
||||
|
||||
static QUERY_CLASSIFIER* load_and_init_classifier(const char* name)
|
||||
{
|
||||
QUERY_CLASSIFIER* classifier = NULL;
|
||||
void* module = load_module(name, MODULE_QUERY_CLASSIFIER);
|
||||
|
||||
if (module)
|
||||
{
|
||||
classifier = (QUERY_CLASSIFIER*) module;
|
||||
MXS_NOTICE("%s loaded.", qc_mysqlembedded);
|
||||
|
||||
success = classifier->qc_init();
|
||||
bool success = classifier->qc_init();
|
||||
|
||||
if (success)
|
||||
{
|
||||
MXS_NOTICE("%s loaded and initialized.", name);
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_ERROR("Could not initialize %s.", name);
|
||||
unload_module(name);
|
||||
classifier = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_ERROR("Could not load %s.", qc_mysqlembedded);
|
||||
MXS_ERROR("Could not load %s.", name);
|
||||
}
|
||||
|
||||
return classifier;
|
||||
}
|
||||
|
||||
static void end_and_unload_classifier(QUERY_CLASSIFIER* classifier, const char* name)
|
||||
{
|
||||
classifier->qc_end();
|
||||
unload_module(name);
|
||||
}
|
||||
|
||||
static bool resolve_pp_path(char* path, int size)
|
||||
{
|
||||
bool success = false;
|
||||
ssize_t sz = readlink("/proc/self/exe", path, size);
|
||||
|
||||
if (sz >= 0)
|
||||
{
|
||||
if (sz == size)
|
||||
{
|
||||
MXS_ERROR("The full path of the current executable does not fit in a "
|
||||
"buffer of %d bytes.", size);
|
||||
}
|
||||
else
|
||||
{
|
||||
char* s = path + sz;
|
||||
|
||||
// Find the last '/'.
|
||||
while ((*s != '/') && (s != path))
|
||||
{
|
||||
--s;
|
||||
--sz;
|
||||
}
|
||||
|
||||
if (*s == '/')
|
||||
{
|
||||
++s;
|
||||
++sz;
|
||||
}
|
||||
|
||||
*s = 0;
|
||||
|
||||
int required_size = sz + sizeof(MAXPP) + 1;
|
||||
|
||||
if (required_size + 1 <= size)
|
||||
{
|
||||
strcat(path, MAXPP);
|
||||
|
||||
MXS_NOTICE("Path of plugin process executable: %s", path);
|
||||
success = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_ERROR("The full path of the plugin process executable does "
|
||||
"not fit into a buffer of %d bytes. ", size);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_ERROR("Could not establish location of current process.");
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static bool is_executable(const char* path)
|
||||
{
|
||||
return access(path, X_OK) == 0;
|
||||
}
|
||||
|
||||
static bool qc_pp_init(void)
|
||||
{
|
||||
QC_TRACE();
|
||||
ss_dassert(!self);
|
||||
|
||||
bool success = false;
|
||||
|
||||
self = malloc(sizeof(*self));
|
||||
|
||||
if (self)
|
||||
{
|
||||
memset(self, 0, sizeof(*self));
|
||||
|
||||
const char* classifier_name = QC_MYSQLEMBEDDED;
|
||||
QUERY_CLASSIFIER* classifier = load_and_init_classifier(classifier_name);
|
||||
|
||||
if (classifier)
|
||||
{
|
||||
char pp_path[PATH_MAX];
|
||||
|
||||
if (resolve_pp_path(pp_path, sizeof(pp_path)))
|
||||
{
|
||||
if (is_executable(pp_path))
|
||||
{
|
||||
self->classifier = classifier;
|
||||
strcpy(self->classifier_name, classifier_name);
|
||||
strcpy(self->pp_path, pp_path);
|
||||
success = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_ERROR("%s does not exist or is not an executable.", pp_path);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_ERROR("Could not resolve the path of the plugin process executable. "
|
||||
"Plugin process will not be launched.");
|
||||
}
|
||||
|
||||
if (!success)
|
||||
{
|
||||
end_and_unload_classifier(classifier, classifier_name);
|
||||
}
|
||||
}
|
||||
|
||||
if (!success)
|
||||
{
|
||||
free(self);
|
||||
self = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_ERROR("Out of memory.");
|
||||
}
|
||||
|
||||
return success;
|
||||
@ -65,114 +206,129 @@ static bool qc_pp_init(void)
|
||||
static void qc_pp_end(void)
|
||||
{
|
||||
QC_TRACE();
|
||||
ss_dassert(classifier);
|
||||
ss_dassert(self);
|
||||
ss_dassert(self->classifier);
|
||||
|
||||
classifier->qc_end();
|
||||
classifier = NULL;
|
||||
end_and_unload_classifier(self->classifier, self->classifier_name);
|
||||
free(self);
|
||||
self = NULL;
|
||||
}
|
||||
|
||||
static bool qc_pp_thread_init(void)
|
||||
{
|
||||
QC_TRACE();
|
||||
ss_dassert(classifier);
|
||||
ss_dassert(self);
|
||||
ss_dassert(self->classifier);
|
||||
|
||||
return classifier->qc_thread_init();
|
||||
return self->classifier->qc_thread_init();
|
||||
}
|
||||
|
||||
static void qc_pp_thread_end(void)
|
||||
{
|
||||
QC_TRACE();
|
||||
ss_dassert(classifier);
|
||||
ss_dassert(self);
|
||||
ss_dassert(self->classifier);
|
||||
|
||||
return classifier->qc_thread_end();
|
||||
return self->classifier->qc_thread_end();
|
||||
}
|
||||
|
||||
static qc_query_type_t qc_pp_get_type(GWBUF* query)
|
||||
{
|
||||
QC_TRACE();
|
||||
ss_dassert(classifier);
|
||||
ss_dassert(self);
|
||||
ss_dassert(self->classifier);
|
||||
|
||||
return classifier->qc_get_type(query);
|
||||
return self->classifier->qc_get_type(query);
|
||||
}
|
||||
|
||||
static qc_query_op_t qc_pp_get_operation(GWBUF* query)
|
||||
{
|
||||
QC_TRACE();
|
||||
ss_dassert(classifier);
|
||||
ss_dassert(self);
|
||||
ss_dassert(self->classifier);
|
||||
|
||||
return classifier->qc_get_operation(query);
|
||||
return self->classifier->qc_get_operation(query);
|
||||
}
|
||||
|
||||
static char* qc_pp_get_created_table_name(GWBUF* query)
|
||||
{
|
||||
QC_TRACE();
|
||||
ss_dassert(classifier);
|
||||
ss_dassert(self);
|
||||
ss_dassert(self->classifier);
|
||||
|
||||
return classifier->qc_get_created_table_name(query);
|
||||
return self->classifier->qc_get_created_table_name(query);
|
||||
}
|
||||
|
||||
static bool qc_pp_is_drop_table_query(GWBUF* query)
|
||||
{
|
||||
QC_TRACE();
|
||||
ss_dassert(classifier);
|
||||
ss_dassert(self);
|
||||
ss_dassert(self->classifier);
|
||||
|
||||
return classifier->qc_is_drop_table_query(query);
|
||||
return self->classifier->qc_is_drop_table_query(query);
|
||||
}
|
||||
|
||||
static bool qc_pp_is_real_query(GWBUF* query)
|
||||
{
|
||||
QC_TRACE();
|
||||
ss_dassert(classifier);
|
||||
ss_dassert(self);
|
||||
ss_dassert(self->classifier);
|
||||
|
||||
return classifier->qc_is_real_query(query);
|
||||
return self->classifier->qc_is_real_query(query);
|
||||
}
|
||||
|
||||
static char** qc_pp_get_table_names(GWBUF* query, int* tblsize, bool fullnames)
|
||||
{
|
||||
QC_TRACE();
|
||||
ss_dassert(classifier);
|
||||
ss_dassert(self);
|
||||
ss_dassert(self->classifier);
|
||||
|
||||
return classifier->qc_get_table_names(query, tblsize, fullnames);
|
||||
return self->classifier->qc_get_table_names(query, tblsize, fullnames);
|
||||
}
|
||||
|
||||
static char* qc_pp_get_canonical(GWBUF* query)
|
||||
{
|
||||
QC_TRACE();
|
||||
ss_dassert(classifier);
|
||||
ss_dassert(self);
|
||||
ss_dassert(self->classifier);
|
||||
|
||||
return classifier->qc_get_canonical(query);
|
||||
return self->classifier->qc_get_canonical(query);
|
||||
}
|
||||
|
||||
static bool qc_pp_query_has_clause(GWBUF* query)
|
||||
{
|
||||
QC_TRACE();
|
||||
ss_dassert(classifier);
|
||||
ss_dassert(self);
|
||||
ss_dassert(self->classifier);
|
||||
|
||||
return classifier->qc_query_has_clause(query);
|
||||
return self->classifier->qc_query_has_clause(query);
|
||||
}
|
||||
|
||||
static char* qc_pp_get_qtype_str(qc_query_type_t qtype)
|
||||
{
|
||||
QC_TRACE();
|
||||
ss_dassert(classifier);
|
||||
ss_dassert(self);
|
||||
ss_dassert(self->classifier);
|
||||
|
||||
return classifier->qc_get_qtype_str(qtype);
|
||||
return self->classifier->qc_get_qtype_str(qtype);
|
||||
}
|
||||
|
||||
static char* qc_pp_get_affected_fields(GWBUF* query)
|
||||
{
|
||||
QC_TRACE();
|
||||
ss_dassert(classifier);
|
||||
ss_dassert(self);
|
||||
ss_dassert(self->classifier);
|
||||
|
||||
return classifier->qc_get_affected_fields(query);
|
||||
return self->classifier->qc_get_affected_fields(query);
|
||||
}
|
||||
|
||||
static char** qc_pp_get_database_names(GWBUF* query, int* sizep)
|
||||
{
|
||||
QC_TRACE();
|
||||
ss_dassert(classifier);
|
||||
ss_dassert(self);
|
||||
ss_dassert(self->classifier);
|
||||
|
||||
return classifier->qc_get_database_names(query, sizep);
|
||||
return self->classifier->qc_get_database_names(query, sizep);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user