add ptql error messages

This commit is contained in:
Doug MacEachern 2007-11-06 03:40:32 +00:00
parent b3d43367ef
commit c2f6979c7e
4 changed files with 97 additions and 47 deletions

View File

@ -1226,23 +1226,16 @@ JNIEXPORT void SIGAR_JNI(ptql_SigarProcessQuery_create)
jboolean is_copy; jboolean is_copy;
const char *ptql; const char *ptql;
sigar_ptql_query_t *query; sigar_ptql_query_t *query;
sigar_ptql_error_t error;
ptql = JENV->GetStringUTFChars(env, jptql, &is_copy); ptql = JENV->GetStringUTFChars(env, jptql, &is_copy);
status = sigar_ptql_query_create(&query, (char *)ptql); status = sigar_ptql_query_create(&query, (char *)ptql, &error);
if (is_copy) { if (is_copy) {
JENV->ReleaseStringUTFChars(env, jptql, ptql); JENV->ReleaseStringUTFChars(env, jptql, ptql);
} }
if (status != SIGAR_OK) { if (status != SIGAR_OK) {
char buf[1024], *msg=buf; sigar_throw_ptql_malformed(env, error.message);
if (status == SIGAR_PTQL_MALFORMED_QUERY) {
msg = "Malformed query";
}
else {
sigar_strerror_get(status, buf, sizeof(buf));
}
sigar_throw_ptql_malformed(env, msg);
} }
else { else {
sigar_set_pointer(env, obj, query); sigar_set_pointer(env, obj, query);

View File

@ -94,7 +94,8 @@ public class TestPTQL extends SigarTestCase {
"Statex.Name.eq=foo", "Statex.Name.eq=foo",
"State.Name.eqx=foo", "State.Name.eqx=foo",
"State.Name.Xeq=foo", "State.Name.Xeq=foo",
"State.Name.eq=$2", "State.Name.eq=foo,Args.*.eq=$3",
"State.Name.eq=$1",
"State.State.eq=read", "State.State.eq=read",
"Args.x.eq=foo", "Args.x.eq=foo",
"Time.Sys.gt=x", "Time.Sys.gt=x",
@ -102,6 +103,7 @@ public class TestPTQL extends SigarTestCase {
"Cpu.Percent.ge=x", "Cpu.Percent.ge=x",
"Port.foo.eq=8080", "Port.foo.eq=8080",
"Port.tcp.gt=8080", "Port.tcp.gt=8080",
"Port.tcp.eq=http",
"Cpu.Sys.ew=lots", "Cpu.Sys.ew=lots",
"", "",
null, null,

View File

@ -23,13 +23,20 @@
typedef struct sigar_ptql_query_t sigar_ptql_query_t; typedef struct sigar_ptql_query_t sigar_ptql_query_t;
#define SIGAR_PTQL_ERRMSG_SIZE 1024
typedef struct {
char message[SIGAR_PTQL_ERRMSG_SIZE];
} sigar_ptql_error_t;
typedef int (*sigar_ptql_re_impl_t)(void *, char *, char *); typedef int (*sigar_ptql_re_impl_t)(void *, char *, char *);
SIGAR_DECLARE(void) sigar_ptql_re_impl_set(sigar_t *sigar, void *data, SIGAR_DECLARE(void) sigar_ptql_re_impl_set(sigar_t *sigar, void *data,
sigar_ptql_re_impl_t impl); sigar_ptql_re_impl_t impl);
SIGAR_DECLARE(int) sigar_ptql_query_create(sigar_ptql_query_t **query, SIGAR_DECLARE(int) sigar_ptql_query_create(sigar_ptql_query_t **query,
char *ptql); char *ptql,
sigar_ptql_error_t *error);
SIGAR_DECLARE(int) sigar_ptql_query_match(sigar_t *sigar, SIGAR_DECLARE(int) sigar_ptql_query_match(sigar_t *sigar,
sigar_ptql_query_t *query, sigar_ptql_query_t *query,

View File

@ -22,6 +22,8 @@
#include "sigar_ptql.h" #include "sigar_ptql.h"
#include "sigar_os.h" #include "sigar_os.h"
#include <stdio.h>
#ifdef SIGAR_HAS_PCRE #ifdef SIGAR_HAS_PCRE
#include "pcre.h" #include "pcre.h"
#endif #endif
@ -49,7 +51,8 @@ typedef struct ptql_branch_t ptql_branch_t;
#endif #endif
typedef int (SIGAPI *ptql_get_t)(sigar_t *sigar, sigar_pid_t pid, void *data); typedef int (SIGAPI *ptql_get_t)(sigar_t *sigar, sigar_pid_t pid, void *data);
typedef int (*ptql_branch_init_t)(ptql_parse_branch_t *parsed, ptql_branch_t *branch); typedef int (*ptql_branch_init_t)(ptql_parse_branch_t *parsed, ptql_branch_t *branch,
sigar_ptql_error_t *error);
typedef int (*ptql_op_ui64_t)(ptql_branch_t *branch, typedef int (*ptql_op_ui64_t)(ptql_branch_t *branch,
sigar_uint64_t haystack, sigar_uint64_t haystack,
@ -535,8 +538,29 @@ static int ptql_branch_list_destroy(ptql_branch_list_t *branches)
return SIGAR_OK; return SIGAR_OK;
} }
#ifdef WIN32
#define vsnprintf _vsnprintf
#endif
#define PTQL_ERRNAN \
ptql_error(error, "Query value '%s' is not a number", parsed->value)
static int ptql_error(sigar_ptql_error_t *error, const char *format, ...)
{
va_list args;
if (error != NULL) {
va_start(args, format);
vsnprintf(error->message, sizeof(error->message), format, args);
va_end(args);
}
return SIGAR_PTQL_MALFORMED_QUERY;
}
static int ptql_branch_init_any(ptql_parse_branch_t *parsed, static int ptql_branch_init_any(ptql_parse_branch_t *parsed,
ptql_branch_t *branch) ptql_branch_t *branch,
sigar_ptql_error_t *error)
{ {
branch->data.str = sigar_strdup(parsed->attr); branch->data.str = sigar_strdup(parsed->attr);
branch->data_size = strlen(parsed->attr); branch->data_size = strlen(parsed->attr);
@ -641,7 +665,8 @@ enum {
#endif #endif
static int ptql_branch_init_pid(ptql_parse_branch_t *parsed, static int ptql_branch_init_pid(ptql_parse_branch_t *parsed,
ptql_branch_t *branch) ptql_branch_t *branch,
sigar_ptql_error_t *error)
{ {
branch->op_flags |= PTQL_OP_FLAG_PID; branch->op_flags |= PTQL_OP_FLAG_PID;
@ -654,7 +679,7 @@ static int ptql_branch_init_pid(ptql_parse_branch_t *parsed,
char *ptr; char *ptr;
branch->data.pid = str2pid(parsed->value, ptr); branch->data.pid = str2pid(parsed->value, ptr);
if (strtonum_failed(parsed->value, ptr)) { if (strtonum_failed(parsed->value, ptr)) {
return EINVAL; return PTQL_ERRNAN;
} }
} }
return SIGAR_OK; return SIGAR_OK;
@ -672,10 +697,10 @@ static int ptql_branch_init_pid(ptql_parse_branch_t *parsed,
branch->data_size = strlen(parsed->value); branch->data_size = strlen(parsed->value);
#endif #endif
return SIGAR_OK; return SIGAR_OK;
} }
else { else {
return EINVAL; return ptql_error(error, "Unsupported %s attribute: %s",
parsed->name, parsed->attr);
} }
} }
@ -738,7 +763,8 @@ static int SIGAPI ptql_pid_match(sigar_t *sigar,
} }
static int ptql_args_branch_init(ptql_parse_branch_t *parsed, static int ptql_args_branch_init(ptql_parse_branch_t *parsed,
ptql_branch_t *branch) ptql_branch_t *branch,
sigar_ptql_error_t *error)
{ {
if (strEQ(parsed->attr, "*")) { if (strEQ(parsed->attr, "*")) {
branch->op_flags |= PTQL_OP_FLAG_GLOB; branch->op_flags |= PTQL_OP_FLAG_GLOB;
@ -751,7 +777,7 @@ static int ptql_args_branch_init(ptql_parse_branch_t *parsed,
if (strtonum_failed(parsed->attr, end)) { if (strtonum_failed(parsed->attr, end)) {
/* conversion failed */ /* conversion failed */
return errno; return ptql_error(error, "%s is not a number", parsed->attr);
} }
} }
return SIGAR_OK; return SIGAR_OK;
@ -861,11 +887,15 @@ static int SIGAPI ptql_env_match(sigar_t *sigar,
} }
static int ptql_branch_init_port(ptql_parse_branch_t *parsed, static int ptql_branch_init_port(ptql_parse_branch_t *parsed,
ptql_branch_t *branch) ptql_branch_t *branch,
sigar_ptql_error_t *error)
{ {
char *ptr;
/* only 'eq' is supported here */ /* only 'eq' is supported here */
if (branch->op_name != PTQL_OP_EQ) { if (branch->op_name != PTQL_OP_EQ) {
return SIGAR_PTQL_MALFORMED_QUERY; return ptql_error(error, "%s requires 'eq' operator",
parsed->name);
} }
if (strEQ(parsed->attr, "tcp")) { if (strEQ(parsed->attr, "tcp")) {
@ -875,10 +905,14 @@ static int ptql_branch_init_port(ptql_parse_branch_t *parsed,
branch->flags = SIGAR_NETCONN_UDP; branch->flags = SIGAR_NETCONN_UDP;
} }
else { else {
return EINVAL; return ptql_error(error, "Unsupported %s protocol: %s",
parsed->name, parsed->attr);
} }
branch->data.ui32 = atoi(parsed->value); /*XXX*/ branch->data.ui32 = strtoul(parsed->value, &ptr, 10);
if (strtonum_failed(parsed->value, ptr)) {
return PTQL_ERRNAN;
}
return SIGAR_OK; return SIGAR_OK;
} }
@ -1011,11 +1045,12 @@ static ptql_entry_t ptql_map[] = {
{ NULL } { NULL }
}; };
static int ptql_branch_parse(char *query, ptql_parse_branch_t *branch) static int ptql_branch_parse(char *query, ptql_parse_branch_t *branch,
sigar_ptql_error_t *error)
{ {
char *ptr = strchr(query, '='); char *ptr = strchr(query, '=');
if (!ptr) { if (!ptr) {
return SIGAR_PTQL_MALFORMED_QUERY; return ptql_error(error, "Missing '='");
} }
branch->op_flags = 0; branch->op_flags = 0;
@ -1029,7 +1064,7 @@ static int ptql_branch_parse(char *query, ptql_parse_branch_t *branch)
query = ++ptr; query = ++ptr;
} }
else { else {
return SIGAR_PTQL_MALFORMED_QUERY; return ptql_error(error, "Missing '.'");
} }
if ((ptr = strchr(query, '.'))) { if ((ptr = strchr(query, '.'))) {
@ -1038,7 +1073,7 @@ static int ptql_branch_parse(char *query, ptql_parse_branch_t *branch)
query = ++ptr; query = ++ptr;
} }
else { else {
return SIGAR_PTQL_MALFORMED_QUERY; return ptql_error(error, "Missing '.'");
} }
if (*query) { if (*query) {
@ -1050,7 +1085,7 @@ static int ptql_branch_parse(char *query, ptql_parse_branch_t *branch)
branch->op_flags |= PTQL_OP_FLAG_PARENT; branch->op_flags |= PTQL_OP_FLAG_PARENT;
break; break;
default: default:
return EINVAL; return ptql_error(error, "Unsupported modifier: %c", flag);
} }
++query; ++query;
@ -1059,14 +1094,15 @@ static int ptql_branch_parse(char *query, ptql_parse_branch_t *branch)
branch->op = query; branch->op = query;
} }
else { else {
return SIGAR_PTQL_MALFORMED_QUERY; return ptql_error(error, "Missing query");
} }
return SIGAR_OK; return SIGAR_OK;
} }
static int ptql_branch_add(ptql_parse_branch_t *parsed, static int ptql_branch_add(ptql_parse_branch_t *parsed,
ptql_branch_list_t *branches) ptql_branch_list_t *branches,
sigar_ptql_error_t *error)
{ {
ptql_branch_t *branch; ptql_branch_t *branch;
ptql_entry_t *entry = NULL; ptql_entry_t *entry = NULL;
@ -1084,7 +1120,7 @@ static int ptql_branch_add(ptql_parse_branch_t *parsed,
branch->op_name = ptql_op_code_get(parsed->op); branch->op_name = ptql_op_code_get(parsed->op);
if (branch->op_name == PTQL_OP_MAX) { if (branch->op_name == PTQL_OP_MAX) {
return SIGAR_PTQL_MALFORMED_QUERY; return ptql_error(error, "Unsupported operator: %s", parsed->op);
} }
for (i=0; ptql_map[i].name; i++) { for (i=0; ptql_map[i].name; i++) {
@ -1095,7 +1131,7 @@ static int ptql_branch_add(ptql_parse_branch_t *parsed,
} }
if (!entry) { if (!entry) {
return SIGAR_PTQL_MALFORMED_QUERY; return ptql_error(error, "Unsupported method: %s", parsed->name);
} }
for (i=0; entry->members[i].name; i++) { for (i=0; entry->members[i].name; i++) {
@ -1111,12 +1147,13 @@ static int ptql_branch_add(ptql_parse_branch_t *parsed,
lookup = &entry->members[0]; lookup = &entry->members[0];
} }
else { else {
return SIGAR_PTQL_MALFORMED_QUERY; return ptql_error(error, "Unsupported %s attribute: %s",
parsed->name, parsed->attr);
} }
} }
if (lookup->init) { if (lookup->init) {
int status = lookup->init(parsed, branch); int status = lookup->init(parsed, branch, error);
if (status != SIGAR_OK) { if (status != SIGAR_OK) {
return status; return status;
} }
@ -1127,7 +1164,8 @@ static int ptql_branch_add(ptql_parse_branch_t *parsed,
if ((lookup->type < PTQL_VALUE_TYPE_STR) && if ((lookup->type < PTQL_VALUE_TYPE_STR) &&
(branch->op_name > PTQL_OP_MAX_NSTR)) (branch->op_name > PTQL_OP_MAX_NSTR))
{ {
return SIGAR_PTQL_MALFORMED_QUERY; return ptql_error(error, "Unsupported operator '%s' for %s.%s",
parsed->op, parsed->name, parsed->attr);
} }
if (*parsed->value == '$') { if (*parsed->value == '$') {
@ -1135,7 +1173,8 @@ static int ptql_branch_add(ptql_parse_branch_t *parsed,
if (branch->op_name == PTQL_OP_RE) { if (branch->op_name == PTQL_OP_RE) {
/* not for use with .re */ /* not for use with .re */
return SIGAR_PTQL_MALFORMED_QUERY; return ptql_error(error, "Unsupported operator '%s' with variable %s",
parsed->op, parsed->value);
} }
if (sigar_isdigit(*(parsed->value+1))) { if (sigar_isdigit(*(parsed->value+1))) {
@ -1145,11 +1184,13 @@ static int ptql_branch_add(ptql_parse_branch_t *parsed,
if (branch->value.ui32 >= branches->number) { if (branch->value.ui32 >= branches->number) {
/* out-of-range */ /* out-of-range */
return SIGAR_PTQL_MALFORMED_QUERY; return ptql_error(error, "Variable %s out of range (%d)",
parsed->value, branches->number);
} }
else if (branch->value.ui32 == branches->number-1) { else if (branch->value.ui32 == branches->number-1) {
/* self reference */ /* self reference */
return SIGAR_PTQL_MALFORMED_QUERY; return ptql_error(error, "Variable %s self reference",
parsed->value);
} }
} }
else { else {
@ -1169,7 +1210,8 @@ static int ptql_branch_add(ptql_parse_branch_t *parsed,
pcre_compile(parsed->value, 0, pcre_compile(parsed->value, 0,
&error, &offset, NULL); &error, &offset, NULL);
if (!re) { if (!re) {
return SIGAR_PTQL_MALFORMED_QUERY; /* XXX pcre_error ? */
return ptql_error(error, "Invalid regex");
} }
is_set = 1; is_set = 1;
branch->value.ptr = re; branch->value.ptr = re;
@ -1183,7 +1225,7 @@ static int ptql_branch_add(ptql_parse_branch_t *parsed,
if (!is_set) { if (!is_set) {
branch->value.ui64 = strtoull(parsed->value, &ptr, 10); branch->value.ui64 = strtoull(parsed->value, &ptr, 10);
if (strtonum_failed(parsed->value, ptr)) { if (strtonum_failed(parsed->value, ptr)) {
return errno; return PTQL_ERRNAN;
} }
} }
break; break;
@ -1192,7 +1234,7 @@ static int ptql_branch_add(ptql_parse_branch_t *parsed,
if (!is_set) { if (!is_set) {
branch->value.ui32 = strtoul(parsed->value, &ptr, 10); branch->value.ui32 = strtoul(parsed->value, &ptr, 10);
if (strtonum_failed(parsed->value, ptr)) { if (strtonum_failed(parsed->value, ptr)) {
return errno; return PTQL_ERRNAN;
} }
} }
break; break;
@ -1201,7 +1243,7 @@ static int ptql_branch_add(ptql_parse_branch_t *parsed,
if (!is_set) { if (!is_set) {
branch->value.dbl = strtod(parsed->value, &ptr); branch->value.dbl = strtod(parsed->value, &ptr);
if (strtonum_failed(parsed->value, ptr)) { if (strtonum_failed(parsed->value, ptr)) {
return errno; return PTQL_ERRNAN;
} }
} }
break; break;
@ -1209,7 +1251,7 @@ static int ptql_branch_add(ptql_parse_branch_t *parsed,
branch->match.chr = ptql_op_chr[branch->op_name]; branch->match.chr = ptql_op_chr[branch->op_name];
if (!is_set) { if (!is_set) {
if (strlen(parsed->value) != 1) { if (strlen(parsed->value) != 1) {
return SIGAR_PTQL_MALFORMED_QUERY; return ptql_error(error, "%s is not a char", parsed->value);
} }
branch->value.chr[0] = parsed->value[0]; branch->value.chr[0] = parsed->value[0];
} }
@ -1237,7 +1279,8 @@ static int ptql_branch_compare(const void *b1, const void *b2)
} }
SIGAR_DECLARE(int) sigar_ptql_query_create(sigar_ptql_query_t **queryp, SIGAR_DECLARE(int) sigar_ptql_query_create(sigar_ptql_query_t **queryp,
char *ptql) char *ptql,
sigar_ptql_error_t *error)
{ {
char *ptr, *ptql_copy = sigar_strdup(ptql); char *ptr, *ptql_copy = sigar_strdup(ptql);
int status = SIGAR_OK; int status = SIGAR_OK;
@ -1245,6 +1288,8 @@ SIGAR_DECLARE(int) sigar_ptql_query_create(sigar_ptql_query_t **queryp,
sigar_ptql_query_t *query = sigar_ptql_query_t *query =
*queryp = malloc(sizeof(*query)); *queryp = malloc(sizeof(*query));
(void)ptql_error(error, "Malformed query");
#ifdef PTQL_DEBUG #ifdef PTQL_DEBUG
query->ptql = sigar_strdup(ptql); query->ptql = sigar_strdup(ptql);
#endif #endif
@ -1260,10 +1305,10 @@ SIGAR_DECLARE(int) sigar_ptql_query_create(sigar_ptql_query_t **queryp,
*ptr = '\0'; *ptr = '\0';
} }
status = ptql_branch_parse(ptql, &parsed); status = ptql_branch_parse(ptql, &parsed, error);
if (status == SIGAR_OK) { if (status == SIGAR_OK) {
status = status =
ptql_branch_add(&parsed, &query->branches); ptql_branch_add(&parsed, &query->branches, error);
if (status != SIGAR_OK) { if (status != SIGAR_OK) {
break; break;
@ -1297,6 +1342,9 @@ SIGAR_DECLARE(int) sigar_ptql_query_create(sigar_ptql_query_t **queryp,
ptql_branch_compare); ptql_branch_compare);
} }
if (status == SIGAR_OK) {
(void)ptql_error(error, "OK");
}
return status; return status;
} }