add reference support
This commit is contained in:
parent
e554a35a0e
commit
3e71b0b340
|
@ -48,6 +48,7 @@ typedef enum {
|
||||||
} ptql_value_type_t;
|
} ptql_value_type_t;
|
||||||
|
|
||||||
#define PTQL_OP_FLAG_PARENT 1
|
#define PTQL_OP_FLAG_PARENT 1
|
||||||
|
#define PTQL_OP_FLAG_REF 2
|
||||||
|
|
||||||
struct ptql_parse_branch_t {
|
struct ptql_parse_branch_t {
|
||||||
char *name;
|
char *name;
|
||||||
|
@ -386,7 +387,8 @@ static int ptql_branch_list_destroy(sigar_t *sigar,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (branch->lookup &&
|
if (branch->lookup &&
|
||||||
(branch->lookup->type == PTQL_VALUE_TYPE_STR))
|
(branch->lookup->type == PTQL_VALUE_TYPE_STR) &&
|
||||||
|
!(branch->op_flags & PTQL_OP_FLAG_REF))
|
||||||
{
|
{
|
||||||
if (branch->value.str) {
|
if (branch->value.str) {
|
||||||
free(branch->value.str);
|
free(branch->value.str);
|
||||||
|
@ -430,6 +432,27 @@ static int ptql_branch_match(ptql_branch_t *branch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ptql_branch_match_ref(ptql_branch_t *branch, ptql_branch_t *ref)
|
||||||
|
{
|
||||||
|
switch (branch->lookup->type) {
|
||||||
|
case PTQL_VALUE_TYPE_UI64:
|
||||||
|
return branch->match.ui64(*(sigar_uint64_t *)DATA_PTR(branch),
|
||||||
|
*(sigar_uint64_t *)DATA_PTR(ref));
|
||||||
|
case PTQL_VALUE_TYPE_UI32:
|
||||||
|
return branch->match.ui32(*(sigar_uint32_t *)DATA_PTR(branch),
|
||||||
|
*(sigar_uint32_t *)DATA_PTR(ref));
|
||||||
|
case PTQL_VALUE_TYPE_CHR:
|
||||||
|
return branch->match.chr(*(char *)DATA_PTR(branch),
|
||||||
|
*(char *)DATA_PTR(ref));
|
||||||
|
case PTQL_VALUE_TYPE_STR:
|
||||||
|
case PTQL_VALUE_TYPE_ANY:
|
||||||
|
return branch->match.str((char *)DATA_PTR(branch),
|
||||||
|
(char *)DATA_PTR(ref));
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
PTQL_PID_PID,
|
PTQL_PID_PID,
|
||||||
PTQL_PID_FILE,
|
PTQL_PID_FILE,
|
||||||
|
@ -774,13 +797,17 @@ static int ptql_branch_parse(char *query, ptql_parse_branch_t *branch)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ptql_branch_add(ptql_parse_branch_t *parsed,
|
static int ptql_branch_add(ptql_parse_branch_t *parsed,
|
||||||
ptql_branch_t *branch)
|
ptql_branch_list_t *branches)
|
||||||
{
|
{
|
||||||
|
ptql_branch_t *branch;
|
||||||
ptql_entry_t *entry = NULL;
|
ptql_entry_t *entry = NULL;
|
||||||
ptql_lookup_t *lookup = NULL;
|
ptql_lookup_t *lookup = NULL;
|
||||||
ptql_op_name_t op;
|
ptql_op_name_t op;
|
||||||
int i;
|
int i, is_ref=0;
|
||||||
|
|
||||||
|
PTQL_BRANCH_LIST_GROW(branches);
|
||||||
|
|
||||||
|
branch = &branches->data[branches->number++];
|
||||||
branch->data = NULL;
|
branch->data = NULL;
|
||||||
branch->data_size = 0;
|
branch->data_size = 0;
|
||||||
branch->op_flags = parsed->op_flags;
|
branch->op_flags = parsed->op_flags;
|
||||||
|
@ -833,23 +860,48 @@ static int ptql_branch_add(ptql_parse_branch_t *parsed,
|
||||||
return SIGAR_PTQL_MALFORMED_QUERY;
|
return SIGAR_PTQL_MALFORMED_QUERY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((*parsed->value == '$') &&
|
||||||
|
sigar_isdigit(*(parsed->value+1)))
|
||||||
|
{
|
||||||
|
is_ref = 1;
|
||||||
|
branch->op_flags |= PTQL_OP_FLAG_REF;
|
||||||
|
branch->value.ui32 = atoi(parsed->value+1) - 1;
|
||||||
|
|
||||||
|
if (branch->value.ui32 >= branches->number) {
|
||||||
|
/* out-of-range */
|
||||||
|
return SIGAR_PTQL_MALFORMED_QUERY;
|
||||||
|
}
|
||||||
|
else if (branch->value.ui32 == branches->number-1) {
|
||||||
|
/* self reference */
|
||||||
|
return SIGAR_PTQL_MALFORMED_QUERY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (lookup->type) {
|
switch (lookup->type) {
|
||||||
case PTQL_VALUE_TYPE_UI64:
|
case PTQL_VALUE_TYPE_UI64:
|
||||||
branch->match.ui64 = ptql_op_ui64[op];
|
branch->match.ui64 = ptql_op_ui64[op];
|
||||||
|
if (!is_ref) {
|
||||||
branch->value.ui64 = strtoull(parsed->value, NULL, 10);
|
branch->value.ui64 = strtoull(parsed->value, NULL, 10);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case PTQL_VALUE_TYPE_UI32:
|
case PTQL_VALUE_TYPE_UI32:
|
||||||
branch->match.ui32 = ptql_op_ui32[op];
|
branch->match.ui32 = ptql_op_ui32[op];
|
||||||
|
if (!is_ref) {
|
||||||
branch->value.ui32 = strtoul(parsed->value, NULL, 10);
|
branch->value.ui32 = strtoul(parsed->value, NULL, 10);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case PTQL_VALUE_TYPE_CHR:
|
case PTQL_VALUE_TYPE_CHR:
|
||||||
branch->match.chr = ptql_op_chr[op];
|
branch->match.chr = ptql_op_chr[op];
|
||||||
|
if (!is_ref) {
|
||||||
branch->value.chr[0] = parsed->value[0];
|
branch->value.chr[0] = parsed->value[0];
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case PTQL_VALUE_TYPE_STR:
|
case PTQL_VALUE_TYPE_STR:
|
||||||
case PTQL_VALUE_TYPE_ANY:
|
case PTQL_VALUE_TYPE_ANY:
|
||||||
branch->match.str = ptql_op_str[op];
|
branch->match.str = ptql_op_str[op];
|
||||||
|
if (!is_ref) {
|
||||||
branch->value.str = strdup(parsed->value);
|
branch->value.str = strdup(parsed->value);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -873,7 +925,7 @@ SIGAR_DECLARE(int) sigar_ptql_query_create(sigar_t *sigar,
|
||||||
char *ptr, *ptql_copy = strdup(ptql);
|
char *ptr, *ptql_copy = strdup(ptql);
|
||||||
int status = SIGAR_OK;
|
int status = SIGAR_OK;
|
||||||
sigar_ptql_query_t *query =
|
sigar_ptql_query_t *query =
|
||||||
*queryp = malloc(sizeof(*queryp));
|
*queryp = malloc(sizeof(*query));
|
||||||
|
|
||||||
ptql = ptql_copy;
|
ptql = ptql_copy;
|
||||||
|
|
||||||
|
@ -888,11 +940,8 @@ SIGAR_DECLARE(int) sigar_ptql_query_create(sigar_t *sigar,
|
||||||
|
|
||||||
status = ptql_branch_parse(ptql, &parsed);
|
status = ptql_branch_parse(ptql, &parsed);
|
||||||
if (status == SIGAR_OK) {
|
if (status == SIGAR_OK) {
|
||||||
PTQL_BRANCH_LIST_GROW(&query->branches);
|
|
||||||
|
|
||||||
status =
|
status =
|
||||||
ptql_branch_add(&parsed,
|
ptql_branch_add(&parsed, &query->branches);
|
||||||
&query->branches.data[query->branches.number++]);
|
|
||||||
|
|
||||||
if (status != SIGAR_OK) {
|
if (status != SIGAR_OK) {
|
||||||
break;
|
break;
|
||||||
|
@ -916,8 +965,7 @@ SIGAR_DECLARE(int) sigar_ptql_query_create(sigar_t *sigar,
|
||||||
sigar_ptql_query_destroy(sigar, query);
|
sigar_ptql_query_destroy(sigar, query);
|
||||||
*queryp = NULL;
|
*queryp = NULL;
|
||||||
}
|
}
|
||||||
|
else if (query->branches.number > 1) {
|
||||||
if (query->branches.number > 1) {
|
|
||||||
qsort(query->branches.data,
|
qsort(query->branches.data,
|
||||||
query->branches.number,
|
query->branches.number,
|
||||||
sizeof(query->branches.data[0]),
|
sizeof(query->branches.data[0]),
|
||||||
|
@ -972,12 +1020,18 @@ SIGAR_DECLARE(int) sigar_ptql_query_match(sigar_t *sigar,
|
||||||
branch->data = malloc(branch->data_size);
|
branch->data = malloc(branch->data_size);
|
||||||
}
|
}
|
||||||
status = lookup->get(sigar, pid, branch->data);
|
status = lookup->get(sigar, pid, branch->data);
|
||||||
|
if (status != SIGAR_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
if (status == SIGAR_OK) {
|
if (branch->op_flags & PTQL_OP_FLAG_REF) {
|
||||||
matched = ptql_branch_match(branch);
|
ptql_branch_t *ref =
|
||||||
|
&query->branches.data[branch->value.ui32];
|
||||||
|
|
||||||
|
matched = ptql_branch_match_ref(branch, ref);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
matched = 0;
|
matched = ptql_branch_match(branch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue