[SIGAR-90] PTQL enhancements for Windows Services
This commit is contained in:
parent
dceb82802d
commit
b74e11d769
|
@ -69,7 +69,8 @@ public class TestPTQL extends SigarTestCase {
|
|||
THIS_PROCESS,
|
||||
"Pid.Service.eq=Eventlog",
|
||||
"Pid.Service.eq=NOSUCHSERVICE",
|
||||
"Pid.Service.eq=Hyperic HQ Agent",
|
||||
"Pid.Service.ct=Oracle",
|
||||
"Pid.ServiceDisplay.re=DHCP|DNS",
|
||||
OTHER_JAVA_PROCESS, //all java procs cept this one
|
||||
"Cpu.Percent.ge=0.2",
|
||||
"State.Name.sw=java,Args.*.eq=org.jboss.Main", //jboss
|
||||
|
@ -146,6 +147,9 @@ public class TestPTQL extends SigarTestCase {
|
|||
return pids.length;
|
||||
} catch (SigarNotImplementedException e) {
|
||||
return 0;
|
||||
} catch (SigarException e) {
|
||||
traceln("Failed query: " + qs);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
212
src/sigar_ptql.c
212
src/sigar_ptql.c
|
@ -645,7 +645,8 @@ static int ptql_branch_match_ref(ptql_branch_t *branch, ptql_branch_t *ref)
|
|||
enum {
|
||||
PTQL_PID_PID,
|
||||
PTQL_PID_FILE,
|
||||
PTQL_PID_SERVICE
|
||||
PTQL_PID_SERVICE,
|
||||
PTQL_PID_SERVICE_DISPLAY
|
||||
};
|
||||
|
||||
#ifdef SIGAR_64BIT
|
||||
|
@ -664,6 +665,9 @@ enum {
|
|||
|
||||
#endif
|
||||
|
||||
#define PID_SERVICE_ATTR "Service"
|
||||
#define PID_SERVICE_ATTR_LEN (sizeof(PID_SERVICE_ATTR)-1)
|
||||
|
||||
static int ptql_branch_init_pid(ptql_parse_branch_t *parsed,
|
||||
ptql_branch_t *branch,
|
||||
sigar_ptql_error_t *error)
|
||||
|
@ -690,20 +694,84 @@ static int ptql_branch_init_pid(ptql_parse_branch_t *parsed,
|
|||
branch->data_size = strlen(parsed->value);
|
||||
return SIGAR_OK;
|
||||
}
|
||||
else if (strEQ(parsed->attr, "Service")) {
|
||||
branch->flags = PTQL_PID_SERVICE;
|
||||
else if (strnEQ(parsed->attr,
|
||||
PID_SERVICE_ATTR, PID_SERVICE_ATTR_LEN))
|
||||
{
|
||||
char *attr = parsed->attr + PID_SERVICE_ATTR_LEN;
|
||||
branch->flags = 0;
|
||||
if (*attr) {
|
||||
if (strEQ(attr, "Display")) {
|
||||
branch->flags = PTQL_PID_SERVICE_DISPLAY;
|
||||
}
|
||||
}
|
||||
else {
|
||||
branch->flags = PTQL_PID_SERVICE;
|
||||
}
|
||||
if (branch->flags) {
|
||||
#ifdef WIN32
|
||||
branch->data.str = sigar_strdup(parsed->value);
|
||||
branch->data_size = strlen(parsed->value);
|
||||
branch->data.str = sigar_strdup(parsed->value);
|
||||
branch->data_size = strlen(parsed->value);
|
||||
#endif
|
||||
return SIGAR_OK;
|
||||
}
|
||||
else {
|
||||
return ptql_error(error, "Unsupported %s attribute: %s",
|
||||
parsed->name, parsed->attr);
|
||||
return SIGAR_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return ptql_error(error, "Unsupported %s attribute: %s",
|
||||
parsed->name, parsed->attr);
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
static int ptql_pid_service_list_get(sigar_t *sigar,
|
||||
ptql_branch_t *branch,
|
||||
sigar_proc_list_t *proclist)
|
||||
{
|
||||
SC_HANDLE handle =
|
||||
OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
|
||||
ENUM_SERVICE_STATUS services[4096];
|
||||
BOOL retval;
|
||||
DWORD bytes, count, resume=0, i;
|
||||
|
||||
if (handle == NULL) {
|
||||
return GetLastError();
|
||||
}
|
||||
|
||||
retval = EnumServicesStatus(handle,
|
||||
SERVICE_WIN32,
|
||||
SERVICE_ACTIVE,
|
||||
&services[0], sizeof(services),
|
||||
&bytes, &count, &resume);
|
||||
|
||||
for (i=0; i<count; i++) {
|
||||
char *value;
|
||||
|
||||
switch (branch->flags) {
|
||||
case PTQL_PID_SERVICE_DISPLAY:
|
||||
value = services[i].lpDisplayName;
|
||||
break;
|
||||
case PTQL_PID_SERVICE:
|
||||
default:
|
||||
value = services[i].lpServiceName;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ptql_str_match(sigar, branch, value)) {
|
||||
sigar_pid_t service_pid;
|
||||
int status =
|
||||
sigar_service_pid_get(sigar,
|
||||
services[i].lpServiceName,
|
||||
&service_pid);
|
||||
|
||||
if (status == SIGAR_OK) {
|
||||
SIGAR_PROC_LIST_GROW(proclist);
|
||||
proclist->data[proclist->number++] = service_pid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SIGAR_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int ptql_pid_get(sigar_t *sigar,
|
||||
ptql_branch_t *branch,
|
||||
sigar_pid_t *pid)
|
||||
|
@ -742,24 +810,51 @@ static int ptql_pid_get(sigar_t *sigar,
|
|||
return SIGAR_OK;
|
||||
}
|
||||
|
||||
static int ptql_pid_list_get(sigar_t *sigar,
|
||||
ptql_branch_t *branch,
|
||||
sigar_proc_list_t *proclist)
|
||||
{
|
||||
int status, i;
|
||||
sigar_pid_t match_pid;
|
||||
|
||||
#ifdef WIN32
|
||||
if (branch->flags >= PTQL_PID_SERVICE) {
|
||||
if ((branch->flags > PTQL_PID_SERVICE) ||
|
||||
(branch->op_name != PTQL_OP_EQ))
|
||||
{
|
||||
return ptql_pid_service_list_get(sigar, branch, proclist);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
status = ptql_pid_get(sigar, branch, &match_pid);
|
||||
|
||||
if (status != SIGAR_OK) {
|
||||
/* XXX treated as non-match but would be nice to propagate */
|
||||
return SIGAR_OK;
|
||||
}
|
||||
|
||||
status = sigar_proc_list_get(sigar, NULL);
|
||||
if (status != SIGAR_OK) {
|
||||
return status;
|
||||
}
|
||||
for (i=0; i<sigar->pids->number; i++) {
|
||||
sigar_pid_t pid = sigar->pids->data[i];
|
||||
if (pid_branch_match(branch, pid, match_pid)) {
|
||||
SIGAR_PROC_LIST_GROW(proclist);
|
||||
proclist->data[proclist->number++] = pid;
|
||||
}
|
||||
}
|
||||
|
||||
return SIGAR_OK;
|
||||
}
|
||||
|
||||
static int SIGAPI ptql_pid_match(sigar_t *sigar,
|
||||
sigar_pid_t pid,
|
||||
void *data)
|
||||
{
|
||||
ptql_branch_t *branch =
|
||||
(ptql_branch_t *)data;
|
||||
sigar_pid_t match_pid;
|
||||
int matched;
|
||||
int status =
|
||||
ptql_pid_get(sigar, branch, &match_pid);
|
||||
|
||||
if (status != SIGAR_OK) {
|
||||
return status;
|
||||
}
|
||||
|
||||
matched = pid_branch_match(branch, pid, match_pid);
|
||||
|
||||
return matched ? SIGAR_OK : 1;
|
||||
/* query already used to filter proc_list */
|
||||
return SIGAR_OK;
|
||||
}
|
||||
|
||||
static int ptql_args_branch_init(ptql_parse_branch_t *parsed,
|
||||
|
@ -1430,6 +1525,58 @@ SIGAR_DECLARE(int) sigar_ptql_query_match(sigar_t *sigar,
|
|||
return SIGAR_OK;
|
||||
}
|
||||
|
||||
static int ptql_proc_list_get(sigar_t *sigar,
|
||||
sigar_ptql_query_t *query,
|
||||
sigar_proc_list_t **proclist)
|
||||
{
|
||||
int status;
|
||||
int i;
|
||||
|
||||
*proclist = NULL;
|
||||
|
||||
for (i=0; i<query->branches.number; i++) {
|
||||
ptql_branch_t *branch = &query->branches.data[i];
|
||||
|
||||
if (branch->op_flags & PTQL_OP_FLAG_PID) {
|
||||
/* pre-filter pid list for Pid.* queries */
|
||||
/* XXX multiple Pid.* may result in dups */
|
||||
if (*proclist == NULL) {
|
||||
*proclist = malloc(sizeof(**proclist));
|
||||
SIGAR_ZERO(*proclist);
|
||||
sigar_proc_list_create(*proclist);
|
||||
}
|
||||
status = ptql_pid_list_get(sigar, branch, *proclist);
|
||||
if (status != SIGAR_OK) {
|
||||
sigar_proc_list_destroy(sigar, *proclist);
|
||||
free(*proclist);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (*proclist) {
|
||||
return SIGAR_OK;
|
||||
}
|
||||
|
||||
status = sigar_proc_list_get(sigar, NULL);
|
||||
if (status != SIGAR_OK) {
|
||||
return status;
|
||||
}
|
||||
*proclist = sigar->pids;
|
||||
return SIGAR_OK;
|
||||
}
|
||||
|
||||
static int ptql_proc_list_destroy(sigar_t *sigar,
|
||||
sigar_proc_list_t *proclist)
|
||||
{
|
||||
if (proclist != sigar->pids) {
|
||||
sigar_proc_list_destroy(sigar, proclist);
|
||||
free(proclist);
|
||||
}
|
||||
|
||||
return SIGAR_OK;
|
||||
}
|
||||
|
||||
SIGAR_DECLARE(int) sigar_ptql_query_find_process(sigar_t *sigar,
|
||||
sigar_ptql_query_t *query,
|
||||
sigar_pid_t *pid)
|
||||
|
@ -1438,18 +1585,10 @@ SIGAR_DECLARE(int) sigar_ptql_query_find_process(sigar_t *sigar,
|
|||
int i, matches=0;
|
||||
sigar_proc_list_t *pids;
|
||||
|
||||
if ((query->branches.number == 1) &&
|
||||
(query->branches.data[0].op_flags & PTQL_OP_FLAG_PID))
|
||||
{
|
||||
/* avoid scanning the process list for single Pid.* queries */
|
||||
return ptql_pid_get(sigar, &query->branches.data[0], pid);
|
||||
}
|
||||
|
||||
status = sigar_proc_list_get(sigar, NULL);
|
||||
status = ptql_proc_list_get(sigar, query, &pids);
|
||||
if (status != SIGAR_OK) {
|
||||
return status;
|
||||
}
|
||||
pids = sigar->pids;
|
||||
|
||||
for (i=0; i<pids->number; i++) {
|
||||
int query_status =
|
||||
|
@ -1466,6 +1605,8 @@ SIGAR_DECLARE(int) sigar_ptql_query_find_process(sigar_t *sigar,
|
|||
} /* else ok, e.g. permission denied */
|
||||
}
|
||||
|
||||
ptql_proc_list_destroy(sigar, pids);
|
||||
|
||||
if (status != SIGAR_OK) {
|
||||
return status;
|
||||
}
|
||||
|
@ -1494,11 +1635,10 @@ SIGAR_DECLARE(int) sigar_ptql_query_find(sigar_t *sigar,
|
|||
int i;
|
||||
sigar_proc_list_t *pids;
|
||||
|
||||
status = sigar_proc_list_get(sigar, NULL);
|
||||
status = ptql_proc_list_get(sigar, query, &pids);
|
||||
if (status != SIGAR_OK) {
|
||||
return status;
|
||||
}
|
||||
pids = sigar->pids;
|
||||
|
||||
sigar_proc_list_create(proclist);
|
||||
|
||||
|
@ -1517,6 +1657,8 @@ SIGAR_DECLARE(int) sigar_ptql_query_find(sigar_t *sigar,
|
|||
}
|
||||
}
|
||||
|
||||
ptql_proc_list_destroy(sigar, pids);
|
||||
|
||||
if (status != SIGAR_OK) {
|
||||
sigar_proc_list_destroy(sigar, proclist);
|
||||
return status;
|
||||
|
|
Loading…
Reference in New Issue