diff --git a/src/pmdas/root/docker.c b/src/pmdas/root/docker.c index d665a73..ce24ef4 100644 --- a/src/pmdas/root/docker.c +++ b/src/pmdas/root/docker.c @@ -174,8 +174,6 @@ docker_values_changed(const char *path, container_t *values) return 1; } -static int State; - static int docker_values_extract(const char *js, jsmntok_t *t, size_t count, int key, container_t *values) @@ -198,22 +196,27 @@ docker_values_extract(const char *js, jsmntok_t *t, size_t count, jsmntok_t *value = t + 1; if (t->parent == 0) { /* top-level: look for Name & State */ - if (jsmneq(js, t, "Name") == 0) + if (jsmneq(js, t, "Name") == 0) { jsmnstrdup(js, value, &values->name); - if (jsmneq(js, t, "State") == 0) - State = (value->type == JSMN_OBJECT); + values->uptodate++; + } + if (jsmneq(js, t, "State") == 0) { + values->state = (value->type == JSMN_OBJECT); + values->uptodate++; + } } - else if (State != 0) { /* pick out various stateful values */ - int *flag = &values->status; + else if (values->state) { /* pick out various stateful values */ + int flag = values->flags; if (pmDebug & DBG_TRACE_ATTR) __pmNotifyErr(LOG_DEBUG, "docker_values_parse: state\n"); + if (jsmneq(js, t, "Running") == 0) - jsmnflag(js, value, flag, CONTAINER_FLAG_RUNNING); + jsmnflag(js, value, &flag, CONTAINER_FLAG_RUNNING); else if (jsmneq(js, t, "Paused") == 0) - jsmnflag(js, value, flag, CONTAINER_FLAG_PAUSED); + jsmnflag(js, value, &flag, CONTAINER_FLAG_PAUSED); else if (jsmneq(js, t, "Restarting") == 0) - jsmnflag(js, value, flag, CONTAINER_FLAG_RESTARTING); + jsmnflag(js, value, &flag, CONTAINER_FLAG_RESTARTING); else if (jsmneq(js, t, "Pid") == 0) { if (jsmnint(js, value, &values->pid) < 0) values->pid = -1; @@ -221,6 +224,7 @@ docker_values_extract(const char *js, jsmntok_t *t, size_t count, __pmNotifyErr(LOG_DEBUG, "docker_value PID=%d\n", values->pid); } + values->flags = flag; } } return 1; @@ -229,7 +233,7 @@ docker_values_extract(const char *js, jsmntok_t *t, size_t count, j += docker_values_extract(js, t+1+j, count-j, 1, values); /* key */ j += docker_values_extract(js, t+1+j, count-j, 0, values); /*value*/ } - State = 0; + values->state = 0; return j + 1; case JSMN_ARRAY: for (i = j = 0; i < t->size; i++) @@ -264,7 +268,8 @@ docker_values_parse(FILE *fp, const char *name, container_t *values) jslen = 0; jsmn_init(&p); - State = -1; /* reset State key marker for this iteration */ + values->uptodate = 0; /* values for this container not yet visible */ + values->state = -1; /* reset State key marker for this iteration */ for (;;) { /* Read another chunk */ @@ -337,7 +342,9 @@ docker_value_refresh(container_engine_t *dp, return -oserror(); sts = docker_values_parse(fp, name, values); fclose(fp); - return sts; + if (sts < 0) + return sts; + return values->uptodate == NUM_UPTODATE ? 0 : PM_ERR_AGAIN; } /* diff --git a/src/pmdas/root/lxc.c b/src/pmdas/root/lxc.c index 6e79fd0..53c9554 100644 --- a/src/pmdas/root/lxc.c +++ b/src/pmdas/root/lxc.c @@ -120,7 +120,7 @@ lxc_values_parse(FILE *pp, const char *name, container_t *values) char buffer[256]; char *s, *key, *value; - values->pid = values->status = 0; + values->pid = values->flags = 0; while ((s = fgets(buffer, sizeof(buffer)-1, pp)) != NULL) { key = s; @@ -135,13 +135,14 @@ lxc_values_parse(FILE *pp, const char *name, container_t *values) if (strncmp(value, "RUNNING", 7) == 0 || strncmp(value, "STOPPING", 8) == 0 || strncmp(value, "ABORTING", 8) == 0) - values->status |= CONTAINER_FLAG_RUNNING; + values->flags |= CONTAINER_FLAG_RUNNING; if (strncmp(value, "STOPPED", 7) == 0) - values->status |= CONTAINER_FLAG_PAUSED; + values->flags |= CONTAINER_FLAG_PAUSED; if (strncmp(value, "STARTING", 7) == 0) - values->status |= CONTAINER_FLAG_RESTARTING; + values->flags |= CONTAINER_FLAG_RESTARTING; } } + values->uptodate = NUM_UPTODATE; return 0; } diff --git a/src/pmdas/root/root.c b/src/pmdas/root/root.c index da96742..1d7208a 100644 --- a/src/pmdas/root/root.c +++ b/src/pmdas/root/root.c @@ -112,14 +112,17 @@ root_refresh_container_indom(void) dp->insts_refresh(dp, indom); } -static void +static int root_refresh_container_values(char *container, container_t *values) { container_engine_t *dp; - for (dp = &engines[0]; dp->name != NULL; dp++) - if (values->engine == dp) - dp->value_refresh(dp, container, values); + for (dp = &engines[0]; dp->name != NULL; dp++) { + if (values->engine != dp) + continue; + return dp->value_refresh(dp, container, values); + } + return PM_ERR_INST; } container_t * @@ -136,7 +139,8 @@ root_container_search(const char *query) break; if (!pmdaCacheLookup(indom, inst, &name, (void **)&cp) || !cp) continue; - root_refresh_container_values(name, cp); + if (root_refresh_container_values(name, cp) < 0) + continue; for (dp = &engines[0]; dp->name != NULL; dp++) { if ((fuzzy = dp->name_matching(dp, query, cp->name, name)) <= best) continue; @@ -193,7 +197,8 @@ root_fetchCallBack(pmdaMetric *mdesc, unsigned int inst, pmAtomValue *atom) return sts; if (sts != PMDA_CACHE_ACTIVE) return PM_ERR_INST; - root_refresh_container_values(name, cp); + if (root_refresh_container_values(name, cp) < 0) + return PM_ERR_INST; switch (idp->item) { case 0: /* containers.engine */ atom->cp = cp->engine->name; @@ -205,13 +210,13 @@ root_fetchCallBack(pmdaMetric *mdesc, unsigned int inst, pmAtomValue *atom) atom->ul = cp->pid; break; case 3: /* containers.state.running */ - atom->ul = (cp->status & CONTAINER_FLAG_RUNNING) != 0; + atom->ul = (cp->flags & CONTAINER_FLAG_RUNNING) != 0; break; case 4: /* containers.state.paused */ - atom->ul = (cp->status & CONTAINER_FLAG_PAUSED) != 0; + atom->ul = (cp->flags & CONTAINER_FLAG_PAUSED) != 0; break; case 5: /* containers.state.restarting */ - atom->ul = (cp->status & CONTAINER_FLAG_RESTARTING) != 0; + atom->ul = (cp->flags & CONTAINER_FLAG_RESTARTING) != 0; break; default: return PM_ERR_PMID; diff --git a/src/pmdas/root/root.h b/src/pmdas/root/root.h index 2fe3224..9ac0363 100644 --- a/src/pmdas/root/root.h +++ b/src/pmdas/root/root.h @@ -29,6 +29,12 @@ enum { NUM_METRICS }; +enum { + CONTAINERS_UPTODATE_NAME, + CONTAINERS_UPTODATE_STATE, + NUM_UPTODATE +}; + /* * General container services, abstracting individual implementations into * "engines" which are then instantiated one-per-container-technology. @@ -59,8 +65,11 @@ typedef struct container_engine { typedef struct container { int pid; - int status; - char *name; + int flags : 8; /* CONTAINER_FLAG bitwise */ + int state : 8; /* internal driver states */ + int uptodate : 8; /* refreshed values count */ + int padding : 8; + char *name; /* human-presentable name */ char cgroup[128]; struct stat stat; container_engine_t *engine;