void setup_blkio(void) { refresh_cgroup_devices(); pmdaCacheOp(INDOM(CGROUP_BLKIO_INDOM), PMDA_CACHE_INACTIVE); pmdaCacheOp(INDOM(CGROUP_PERDEVBLKIO_INDOM), PMDA_CACHE_INACTIVE); }
void setup_cpuacct(void) { refresh_cgroup_cpus(); pmdaCacheOp(INDOM(CGROUP_CPUACCT_INDOM), PMDA_CACHE_INACTIVE); pmdaCacheOp(INDOM(CGROUP_PERCPUACCT_INDOM), PMDA_CACHE_INACTIVE); }
void netlink_refresh(void) { pmdaCacheOp(indomtab[NETLINK_INDOM].it_indom, PMDA_CACHE_INACTIVE); netlink_update_stats(1); pmdaCacheOp(indomtab[NETLINK_INDOM].it_indom, PMDA_CACHE_SAVE); }
void netlink_init(int first) { pmdaCacheOp(indomtab[NETLINK_INDOM].it_indom, PMDA_CACHE_LOAD); netlink_update_stats(0); pmdaCacheOp(indomtab[NETLINK_INDOM].it_indom, PMDA_CACHE_SAVE); }
int cgroup_mounts_subsys(const char *system, char *buffer, int length) { pmInDom mounts = INDOM(CGROUP_MOUNTS_INDOM); pmInDom subsys = INDOM(CGROUP_SUBSYS_INDOM); filesys_t *fs; char *name; int sts; /* Iterate over cgroup.mounts.subsys indom, comparing the value * with the given subsys - if a match is found, return the inst * name, else NULL. */ pmdaCacheOp(mounts, PMDA_CACHE_WALK_REWIND); while ((sts = pmdaCacheOp(mounts, PMDA_CACHE_WALK_NEXT)) != -1) { if (!pmdaCacheLookup(mounts, sts, &name, (void **)&fs)) continue; if (strcmp(system, cgroup_find_subsys(subsys, fs)) != 0) continue; snprintf(buffer, length, "%s%s/", proc_statspath, name); buffer[length-1] = '\0'; return strlen(buffer); } return 0; }
int __pmdaCntInst(pmInDom indom, pmdaExt *pmda) { int i; int sts = 0; if (indom == PM_INDOM_NULL) return 1; if (pmdaCacheOp(indom, PMDA_CACHE_CHECK)) { sts = pmdaCacheOp(indom, PMDA_CACHE_SIZE_ACTIVE); } else { for (i = 0; i < pmda->e_nindoms; i++) { if (pmda->e_indoms[i].it_indom == indom) { sts = pmda->e_indoms[i].it_numinst; break; } } if (i == pmda->e_nindoms) { char strbuf[20]; __pmNotifyErr(LOG_WARNING, "cntinst: unknown indom %s", pmInDomStr_r(indom, strbuf, sizeof(strbuf))); } } #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_INDOM) { char strbuf[20]; fprintf(stderr, "__pmdaCntInst(indom=%s) -> %d\n", pmInDomStr_r(indom, strbuf, sizeof(strbuf)), sts); } #endif return sts; }
int refresh_jbd2(const char *path, pmInDom jbd2_indom) { DIR *dirp; struct dirent *dent; int indom_changes = 0; static int first = 1; if (first) { /* initialize the instance domain caches */ pmdaCacheOp(jbd2_indom, PMDA_CACHE_LOAD); indom_changes = 1; first = 0; } pmdaCacheOp(jbd2_indom, PMDA_CACHE_INACTIVE); if ((dirp = opendir(path)) == NULL) return -ENOENT; while ((dent = readdir(dirp)) != NULL) indom_changes |= refresh_journal(path, dent->d_name, jbd2_indom); closedir(dirp); if (indom_changes) pmdaCacheOp(jbd2_indom, PMDA_CACHE_SAVE); return 0; }
static void _e(int since) { int i; int j; int sts; int inst; indomp->domain = 123; indomp->serial = 11; sts = pmdaCacheOp(indom, PMDA_CACHE_LOAD); if (sts < 0) { fprintf(stderr, "PMDA_CACHE_LOAD failed: %s\n", pmErrStr(sts)); return; } j = 1; for (i = 0; i < 10; i++) { sprintf(nbuf, "boring-instance-%03d", i); inst = pmdaCacheStore(indom, PMDA_CACHE_ADD, nbuf, (void *)((__psint_t)(0xcaffe000+i))); if (inst < 0) fprintf(stderr, "PMDA_CACHE_ADD failed for \"%s\": %s\n", nbuf, pmErrStr(inst)); if (i == j) { j <<= 1; inst = pmdaCacheStore(indom, PMDA_CACHE_HIDE, nbuf, NULL); if (inst < 0) fprintf(stderr, "PMDA_CACHE_HIDE failed for \"%s\": %s\n", nbuf, pmErrStr(inst)); } } sts = pmdaCacheOp(indom, PMDA_CACHE_SAVE); fprintf(stderr, "Save -> %d\n", sts); fprintf(stderr, "Before purge ...\n"); __pmdaCacheDump(stderr, indom, 0); sleep(1); sts = pmdaCachePurge(indom, since); if (sts < 0) { fprintf(stderr, "pmdaCachePurge failed: %s\n", pmErrStr(sts)); return; } fprintf(stderr, "Purged %d entries\nAfter purge ...\n", sts); sts = pmdaCacheOp(indom, PMDA_CACHE_SAVE); fprintf(stderr, "Save -> %d\n", sts); __pmdaCacheDump(stderr, indom, 0); }
static void _h(void) { int sts; int inst; int i; indom = pmInDom_build(FORQA, 17); sts = pmdaCacheOp(indom, PMDA_CACHE_LOAD); if (sts < 0) { fprintf(stderr, "PMDA_CACHE_LOAD failed: %s\n", pmErrStr(sts)); return; } for (i = 0; h_tab[i] != NULL; i++) { fprintf(stderr, "[%s]\n", h_tab[i]); inst = pmdaCacheStore(indom, PMDA_CACHE_ADD, h_tab[i], NULL); if (inst < 0) { fprintf(stderr, "ADD failed: %s\n", pmErrStr(inst)); continue; } fprintf(stderr, "ADD -> %d\n", inst); inst = pmdaCacheStore(indom, PMDA_CACHE_HIDE, h_tab[i], NULL); if (inst < 0) { fprintf(stderr, "HIDE failed: %s\n", pmErrStr(inst)); continue; } fprintf(stderr, "HIDE -> %d\n", inst); } }
int refresh_net_ioctl(pmInDom indom, linux_container_t *cp, int *need_refresh) { net_interface_t *netip; char *p; int sts = 0; for (pmdaCacheOp(indom, PMDA_CACHE_WALK_REWIND);;) { if ((sts = pmdaCacheOp(indom, PMDA_CACHE_WALK_NEXT)) < 0) break; if (!pmdaCacheLookup(indom, sts, &p, (void **)&netip) || !p) continue; refresh_net_dev_ioctl(p, netip, cp, need_refresh); } return sts; }
/* * For block devices we have one instance domain for dev_t * based lookup, and another for (real) name lookup. * The reason we need this is that the blkio cgroup stats * are exported using the major:minor numbers, and not the * device names - we must perform that mapping ourselves. * In some places (value refresh) we need to lookup the blk * name from device major/minor, in other places (instances * refresh) we need the usual external instid:name lookup. */ static void refresh_cgroup_devices(void) { pmInDom diskindom = INDOM(DISK_INDOM); pmInDom devtindom = INDOM(DEVT_INDOM); char buf[MAXPATHLEN]; FILE *fp; pmdaCacheOp(devtindom, PMDA_CACHE_INACTIVE); pmdaCacheOp(diskindom, PMDA_CACHE_INACTIVE); if ((fp = proc_statsfile("/proc/diskstats", buf, sizeof(buf))) == NULL) return; while (fgets(buf, sizeof(buf), fp) != NULL) { unsigned int major, minor, unused; device_t *dev = NULL; char namebuf[1024]; int inst; if (sscanf(buf, "%u %u %s %u", &major, &minor, namebuf, &unused) != 4) continue; if (_pm_isloop(namebuf) || _pm_isramdisk(namebuf)) continue; if (pmdaCacheLookupName(diskindom, namebuf, &inst, (void **)&dev) < 0 || dev == NULL) { if (!(dev = (device_t *)malloc(sizeof(device_t)))) { __pmNoMem("device", sizeof(device_t), PM_RECOV_ERR); continue; } dev->major = major; dev->minor = minor; } /* keeping track of all fields (major/minor/inst/name) */ pmdaCacheStore(diskindom, PMDA_CACHE_ADD, namebuf, dev); (void)pmdaCacheLookupName(diskindom, namebuf, &dev->inst, NULL); (void)pmdaCacheLookup(diskindom, dev->inst, &dev->name, NULL); snprintf(buf, sizeof(buf), "%u:%u", major, minor); pmdaCacheStore(devtindom, PMDA_CACHE_ADD, buf, (void *)dev); if (pmDebug & DBG_TRACE_APPL0) fprintf(stderr, "refresh_devices: \"%s\" \"%d:%d\" inst=%d\n", dev->name, dev->major, dev->minor, dev->inst); } fclose(fp); }
/** * @brief Perform additional operations on the cache. * * This is a very simple wrapper for PCP's pmdaCacheOp function. * * @param indom Instance domain to operate on. * @param operation Operation to perform. Should be one of the PMDA_CACHE_* * constants. * * @throw pcp::exception On errors. * * @return The result of the pmdaCacheOp function. See pmdaCacheOp for details. * * @see pmdaCacheOp */ inline int perform(const pmInDom indom, const int operation) { const int result = pmdaCacheOp(indom, operation); if (result < 0) { throw pcp::exception(result); } return result; }
/* * This separate indom provides the addresses for all interfaces including * aliases (e.g. eth0, eth0:0, eth0:1, etc) - this is what ifconfig does. */ void clear_net_addr_indom(pmInDom indom) { net_addr_t *p; int inst; for (pmdaCacheOp(indom, PMDA_CACHE_WALK_REWIND);;) { if ((inst = pmdaCacheOp(indom, PMDA_CACHE_WALK_NEXT)) < 0) break; if (!pmdaCacheLookup(indom, inst, NULL, (void **)&p) || !p) continue; p->has_inet = 0; p->has_ipv6 = 0; p->has_hw = 0; } pmdaCacheOp(indom, PMDA_CACHE_INACTIVE); }
/* * Primary driver interface - finds any/all mount points for a given * cgroup subsystem and iteratively expands all of the cgroups below * them. The setup callback inactivates each indoms contents, while * the refresh callback is called once per cgroup (with path/name) - * its role is to refresh the values for that one named cgroup. */ void refresh_cgroups(const char *subsys, const char *container, int length, cgroup_setup_t setup, cgroup_refresh_t refresh) { int sts; filesys_t *fs; pmInDom mounts = INDOM(CGROUP_MOUNTS_INDOM); pmdaCacheOp(mounts, PMDA_CACHE_WALK_REWIND); while ((sts = pmdaCacheOp(mounts, PMDA_CACHE_WALK_NEXT)) != -1) { if (!pmdaCacheLookup(mounts, sts, NULL, (void **)&fs)) continue; if (scan_filesys_options(fs->options, subsys) == NULL) continue; setup(); cgroup_scan(fs->path, "", refresh, container, length); } }
int __pmdaNextInst(int *inst, pmdaExt *pmda) { int j; int myinst; if (pmda->e_singular == 0) { /* PM_INDOM_NULL ... just the one value */ *inst = 0; pmda->e_singular = -1; return 1; } if (pmda->e_ordinal >= 0) { /* scan for next value in the profile */ if (pmda->e_idp == &last) { /* cache-driven */ while ((myinst = pmdaCacheOp(pmda->e_idp->it_indom, PMDA_CACHE_WALK_NEXT)) != -1) { pmda->e_ordinal++; if (__pmInProfile(pmda->e_idp->it_indom, pmda->e_prof, myinst)) { *inst = myinst; #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_INDOM) { char strbuf[20]; fprintf(stderr, "__pmdaNextInst(indom=%s) -> %d e_ordinal=%d (cache)\n", pmInDomStr_r(pmda->e_idp->it_indom, strbuf, sizeof(strbuf)), myinst, pmda->e_ordinal); } #endif return 1; } } } else { /* indomtab[]-driven */ for (j = pmda->e_ordinal; j < pmda->e_idp->it_numinst; j++) { if (__pmInProfile(pmda->e_idp->it_indom, pmda->e_prof, pmda->e_idp->it_set[j].i_inst)) { *inst = pmda->e_idp->it_set[j].i_inst; pmda->e_ordinal = j+1; #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_INDOM) { char strbuf[20]; fprintf(stderr, "__pmdaNextInst(indom=%s) -> %d e_ordinal=%d\n", pmInDomStr_r(pmda->e_idp->it_indom, strbuf, sizeof(strbuf)), *inst, pmda->e_ordinal); } #endif return 1; } } } pmda->e_ordinal = -1; } return 0; }
static void _j(void) { int inst; int sts; int i; indomp->domain = 123; indomp->serial = 10; fprintf(stderr, "\nPopulate the instance domain ...\n"); for (i = 0; i < 20; i++) { strncpy(nbuf, xxx, ncount+3); sprintf(nbuf, "%03d", ncount); ncount++; inst = pmdaCacheStore(indom, PMDA_CACHE_ADD, nbuf, (void *)((__psint_t)(0xbeef0000+ncount))); if (inst < 0) fprintf(stderr, "PMDA_CACHE_ADD failed for \"%s\": %s\n", nbuf, pmErrStr(inst)); } sts = pmdaCacheOp(indom, PMDA_CACHE_SAVE); fprintf(stderr, "Save -> %d\n", sts); __pmdaCacheDump(stderr, indom, 0); /* We've now got a cache with 20 items. Try to resize the cache. */ sts = pmdaCacheResize(indom, 1234); fprintf(stderr, "Resize (good) -> %d", sts); if (sts < 0) fprintf(stderr, ": %s", pmErrStr(sts)); fputc('\n', stderr); /* This should fail, since we've got more than 10 items in this cache. */ sts = pmdaCacheResize(indom, 10); fprintf(stderr, "Resize (bad) -> %d", sts); if (sts < 0) fprintf(stderr, ": %s", pmErrStr(sts)); fputc('\n', stderr); /* Since we've changed the max, we'll need to save again. PMDA_CACHE_SAVE won't resave the cache with just a dirty cache header, but PMDA_CACHE_SYNC will. */ sts = pmdaCacheOp(indom, PMDA_CACHE_SYNC); fprintf(stderr, "Sync -> %d\n", sts); }
/* * State between here and __pmdaNextInst is a little strange * * for the classical method, * - pmda->e_idp is set here (points into indomtab[]) and * pmda->e_idp->it_indom is used in __pmdaNextInst * * for the cache method * - pmda->e_idp is set here (points into last) which is also set * up with the it_indom field (other fields in last are not used), * and pmda->e_idp->it_indom in __pmdaNextInst * * In both cases, pmda->e_ordinal and pmda->e_singular are set here * and updated in __pmdaNextInst. * * As in most other places, this is not thread-safe and we assume we * call __pmdaStartInst and then repeatedly call __pmdaNextInst all * for the same indom, before calling __pmdaStartInst again. * * If we could do this again, adding an indom argument to __pmdaNextInst * would be a better design, but the API to __pmdaNextInst has escaped. */ void __pmdaStartInst(pmInDom indom, pmdaExt *pmda) { int i; pmda->e_ordinal = pmda->e_singular = -1; if (indom == PM_INDOM_NULL) { /* singular value */ pmda->e_singular = 0; } else { if (pmdaCacheOp(indom, PMDA_CACHE_CHECK)) { pmdaCacheOp(indom, PMDA_CACHE_WALK_REWIND); last.it_indom = indom; pmda->e_idp = &last; pmda->e_ordinal = 0; } else { for (i = 0; i < pmda->e_nindoms; i++) { if (pmda->e_indoms[i].it_indom == indom) { /* multiple values are possible */ pmda->e_idp = &pmda->e_indoms[i]; pmda->e_ordinal = 0; break; } } } } #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_INDOM) { char strbuf[20]; fprintf(stderr, "__pmdaStartInst(indom=%s) e_ordinal=%d\n", pmInDomStr_r(indom, strbuf, sizeof(strbuf)), pmda->e_ordinal); } #endif return; }
static void _c(void) { int inst; int sts; indomp->domain = 123; indomp->serial = 13; fprintf(stderr, "Load the instance domain ...\n"); sts = pmdaCacheOp(indom, PMDA_CACHE_LOAD); if (sts < 0) { fprintf(stderr, "PMDA_CACHE_LOAD failed: %s\n", pmErrStr(sts)); return; } inst = pmdaCacheStore(indom, PMDA_CACHE_HIDE, "fubar-001", NULL); if (inst < 0) fprintf(stderr, "PMDA_CACHE_HIDE failed for \"fubar-001\": %s\n", pmErrStr(inst)); inst = pmdaCacheStore(indom, PMDA_CACHE_ADD, "fubar-002", NULL); if (inst < 0) fprintf(stderr, "PMDA_CACHE_ADD failed for \"fubar-002\": %s\n", pmErrStr(inst)); inst = pmdaCacheStore(indom, PMDA_CACHE_CULL, "fubar-003", NULL); if (inst < 0) fprintf(stderr, "PMDA_CACHE_CULL failed for \"fubar-003\": %s\n", pmErrStr(inst)); inst = pmdaCacheStore(indom, PMDA_CACHE_ADD, "fubar-009", NULL); if (inst < 0) fprintf(stderr, "PMDA_CACHE_ADD failed for \"fubar-009\": %s\n", pmErrStr(inst)); __pmdaCacheDump(stderr, indom, 0); sts = pmdaCacheOp(indom, PMDA_CACHE_SAVE); if (sts < 0) { fprintf(stderr, "PMDA_CACHE_SAVE failed: %s\n", pmErrStr(sts)); return; } }
void refresh_cgroup_filesys(void) { pmInDom mounts = INDOM(CGROUP_MOUNTS_INDOM); char buf[MAXPATHLEN]; filesys_t *fs; FILE *fp; char *path, *device, *type, *options; int sts; pmdaCacheOp(mounts, PMDA_CACHE_INACTIVE); if ((fp = proc_statsfile("/proc/mounts", buf, sizeof(buf))) == NULL) return; while (fgets(buf, sizeof(buf), fp) != NULL) { device = strtok(buf, " "); path = strtok(NULL, " "); type = strtok(NULL, " "); options = strtok(NULL, " "); if (strcmp(type, "cgroup") != 0) continue; sts = pmdaCacheLookupName(mounts, path, NULL, (void **)&fs); if (sts == PMDA_CACHE_ACTIVE) /* repeated line in /proc/mounts? */ continue; if (sts == PMDA_CACHE_INACTIVE) { /* re-activate an old mount */ pmdaCacheStore(mounts, PMDA_CACHE_ADD, path, fs); if (strcmp(path, fs->path) != 0) { /* old device, new path */ free(fs->path); fs->path = strdup(path); } if (strcmp(options, fs->options) != 0) { /* old device, new opts */ free(fs->options); fs->options = strdup(options); } } else { /* new mount */ if ((fs = malloc(sizeof(filesys_t))) == NULL) continue; fs->path = strdup(path); fs->options = strdup(options); if (pmDebug & DBG_TRACE_APPL0) fprintf(stderr, "refresh_filesys: add \"%s\" \"%s\"\n", fs->path, device); pmdaCacheStore(mounts, PMDA_CACHE_ADD, path, fs); } } fclose(fp); }
/* * Allocate instance identifiers for all CPUs. Note there is a * need to deal with CPUs/nodes going online and offline during * the life of the PMDA - usually we're only able to get values * for online resources (/proc/stat reports online CPUs only). * * We must create a direct mapping of CPU ID to instance ID, for * historical reasons. So initially all have a NULL private data * pointer associated with them, which we'll subsequently fill in * if/when the CPU/node is discovered to be online (later). */ static void setup_cpu_indom(pmInDom cpus) { char name[64]; int i; if (_pm_ncpus < 1) _pm_ncpus = 1; /* sanity, surely there must be at least one CPU */ pmdaCacheOp(cpus, PMDA_CACHE_CULL); for (i = 0; i < _pm_ncpus; i++) { snprintf(name, sizeof(name)-1, "cpu%u", i); pmdaCacheStore(cpus, PMDA_CACHE_ADD, name, NULL); } }
static void refresh_cgroup_cpus(void) { pmInDom cpus = INDOM(CPU_INDOM); char buf[MAXPATHLEN]; char *space; FILE *fp; pmdaCacheOp(cpus, PMDA_CACHE_INACTIVE); if ((fp = proc_statsfile("/proc/stat", buf, sizeof(buf))) == NULL) return; while (fgets(buf, sizeof(buf), fp) != NULL) { if (strncmp(buf, "cpu", 3) == 0 && isdigit((int)buf[3])) { if ((space = strchr(buf, ' ')) != NULL) { *space = '\0'; pmdaCacheStore(cpus, PMDA_CACHE_ADD, buf, NULL); } } } fclose(fp); }
void refresh_cgroup_subsys(void) { pmInDom subsys = INDOM(CGROUP_SUBSYS_INDOM); char buf[4096]; FILE *fp; pmdaCacheOp(subsys, PMDA_CACHE_INACTIVE); if ((fp = proc_statsfile("/proc/cgroups", buf, sizeof(buf))) == NULL) return; while (fgets(buf, sizeof(buf), fp) != NULL) { unsigned int hierarchy, num_cgroups, enabled; char name[MAXPATHLEN]; subsys_t *ssp; int sts; /* skip lines starting with hash (header) */ if (buf[0] == '#') continue; if (sscanf(buf, "%s %u %u %u", &name[0], &hierarchy, &num_cgroups, &enabled) < 4) continue; sts = pmdaCacheLookupName(subsys, name, NULL, (void **)&ssp); if (sts != PMDA_CACHE_INACTIVE) { if ((ssp = (subsys_t *)malloc(sizeof(subsys_t))) == NULL) continue; } ssp->hierarchy = hierarchy; ssp->num_cgroups = num_cgroups; ssp->enabled = enabled; pmdaCacheStore(subsys, PMDA_CACHE_ADD, name, (void *)ssp); if (pmDebug & DBG_TRACE_APPL0) fprintf(stderr, "refresh_subsys: \"%s\" h=%u nc=%u on=%u\n", name, hierarchy, num_cgroups, enabled); } fclose(fp); }
int proc_partitions_fetch(pmdaMetric *mdesc, unsigned int inst, pmAtomValue *atom) { __pmID_int *idp = (__pmID_int *)&(mdesc->m_desc.pmid); int i; partitions_entry_t *p = NULL; if (inst != PM_IN_NULL) { if (pmdaCacheLookup(mdesc->m_desc.indom, inst, NULL, (void **)&p) < 0) return PM_ERR_INST; } switch (idp->cluster) { case CLUSTER_STAT: /* * disk.{dev,all} remain in CLUSTER_STAT for backward compatibility */ switch(idp->item) { case 4: /* disk.dev.read */ if (p == NULL) return PM_ERR_INST; _pm_assign_ulong(atom, p->rd_ios); break; case 5: /* disk.dev.write */ if (p == NULL) return PM_ERR_INST; _pm_assign_ulong(atom, p->wr_ios); break; case 6: /* disk.dev.blkread */ if (p == NULL) return PM_ERR_INST; atom->ull = p->rd_sectors; break; case 7: /* disk.dev.blkwrite */ if (p == NULL) return PM_ERR_INST; atom->ull = p->wr_sectors; break; case 28: /* disk.dev.total */ if (p == NULL) return PM_ERR_INST; atom->ull = p->rd_ios + p->wr_ios; break; case 36: /* disk.dev.blktotal */ if (p == NULL) return PM_ERR_INST; atom->ull = p->rd_sectors + p->wr_sectors; break; case 38: /* disk.dev.read_bytes */ if (p == NULL) return PM_ERR_INST; atom->ull = p->rd_sectors / 2; break; case 39: /* disk.dev.write_bytes */ if (p == NULL) return PM_ERR_INST; atom->ull = p->wr_sectors / 2; break; case 40: /* disk.dev.total_bytes */ if (p == NULL) return PM_ERR_INST; atom->ull = (p->rd_sectors + p->wr_sectors) / 2; break; case 46: /* disk.dev.avactive ... already msec from /proc/diskstats */ if (p == NULL) return PM_ERR_INST; atom->ul = p->io_ticks; break; case 47: /* disk.dev.aveq ... already msec from /proc/diskstats */ if (p == NULL) return PM_ERR_INST; atom->ul = p->aveq; break; case 49: /* disk.dev.read_merge */ if (p == NULL) return PM_ERR_INST; _pm_assign_ulong(atom, p->rd_merges); break; case 50: /* disk.dev.write_merge */ if (p == NULL) return PM_ERR_INST; _pm_assign_ulong(atom, p->wr_merges); break; case 59: /* disk.dev.scheduler */ if (p == NULL) return PM_ERR_INST; atom->cp = _pm_ioscheduler(p->namebuf); break; case 72: /* disk.dev.read_rawactive already ms from /proc/diskstats */ if (p == NULL) return PM_ERR_INST; atom->ul = p->rd_ticks; break; case 73: /* disk.dev.write_rawactive already ms from /proc/diskstats */ if (p == NULL) return PM_ERR_INST; atom->ul = p->wr_ticks; break; default: /* disk.all.* is a singular instance domain */ atom->ull = 0; for (pmdaCacheOp(INDOM(DISK_INDOM), PMDA_CACHE_WALK_REWIND);;) { if ((i = pmdaCacheOp(INDOM(DISK_INDOM), PMDA_CACHE_WALK_NEXT)) < 0) break; if (!pmdaCacheLookup(INDOM(DISK_INDOM), i, NULL, (void **)&p) || !p) continue; switch (idp->item) { case 24: /* disk.all.read */ atom->ull += p->rd_ios; break; case 25: /* disk.all.write */ atom->ull += p->wr_ios; break; case 26: /* disk.all.blkread */ atom->ull += p->rd_sectors; break; case 27: /* disk.all.blkwrite */ atom->ull += p->wr_sectors; break; case 29: /* disk.all.total */ atom->ull += p->rd_ios + p->wr_ios; break; case 37: /* disk.all.blktotal */ atom->ull += p->rd_sectors + p->wr_sectors; break; case 41: /* disk.all.read_bytes */ atom->ull += p->rd_sectors / 2; break; case 42: /* disk.all.write_bytes */ atom->ull += p->wr_sectors / 2; break; case 43: /* disk.all.total_bytes */ atom->ull += (p->rd_sectors + p->wr_sectors) / 2; break; case 44: /* disk.all.avactive ... already msec from /proc/diskstats */ atom->ull += p->io_ticks; break; case 45: /* disk.all.aveq ... already msec from /proc/diskstats */ atom->ull += p->aveq; break; case 51: /* disk.all.read_merge */ atom->ull += p->rd_merges; break; case 52: /* disk.all.write_merge */ atom->ull += p->wr_merges; break; case 74: /* disk.all.read_rawactive ... already msec from /proc/diskstats */ atom->ull += p->rd_ticks; break; case 75: /* disk.all.write_rawactive ... already msec from /proc/diskstats */ atom->ull += p->wr_ticks; break; default: return PM_ERR_PMID; } } /* loop */ } break; case CLUSTER_PARTITIONS: if (p == NULL) return PM_ERR_INST; switch(idp->item) { /* disk.partitions */ case 0: /* disk.partitions.read */ atom->ul = p->rd_ios; break; case 1: /* disk.partitions.write */ atom->ul = p->wr_ios; break; case 2: /* disk.partitions.total */ atom->ul = p->wr_ios + p->rd_ios; break; case 3: /* disk.partitions.blkread */ atom->ul = p->rd_sectors; break; case 4: /* disk.partitions.blkwrite */ atom->ul = p->wr_sectors; break; case 5: /* disk.partitions.blktotal */ atom->ul = p->rd_sectors + p->wr_sectors; break; case 6: /* disk.partitions.read_bytes */ atom->ul = p->rd_sectors / 2; break; case 7: /* disk.partitions.write_bytes */ atom->ul = p->wr_sectors / 2; break; case 8: /* disk.partitions.total_bytes */ atom->ul = (p->rd_sectors + p->wr_sectors) / 2; break; default: return PM_ERR_PMID; } break; case CLUSTER_DM: if (p == NULL) return PM_ERR_INST; switch(idp->item) { case 0: /* disk.dm.read */ atom->ull = p->rd_ios; break; case 1: /* disk.dm.write */ atom->ull = p->wr_ios; break; case 2: /* disk.dm.total */ atom->ull = p->rd_ios + p->wr_ios; break; case 3: /* disk.dm.blkread */ atom->ull = p->rd_sectors; break; case 4: /* disk.dm.blkwrite */ atom->ull = p->wr_sectors; break; case 5: /* disk.dm.blktotal */ atom->ull = p->rd_sectors + p->wr_sectors; break; case 6: /* disk.dm.read_bytes */ atom->ull = p->rd_sectors / 2; break; case 7: /* disk.dm.write_bytes */ atom->ull = p->wr_sectors / 2; break; case 8: /* disk.dm.total_bytes */ atom->ull = (p->rd_sectors + p->wr_sectors) / 2; break; case 9: /* disk.dm.read_merge */ atom->ull = p->rd_merges; break; case 10: /* disk.dm.write_merge */ atom->ull = p->wr_merges; break; case 11: /* disk.dm.avactive */ atom->ull = p->io_ticks; break; case 12: /* disk.dm.aveq */ atom->ull = p->aveq; break; case 13: /* hinv.map.dmname */ atom->cp = p->dmname; break; case 14: /* disk.dm.read_rawactive */ atom->ul = p->rd_ticks; break; case 15: /* disk.dm.write_rawactive */ atom->ul = p->wr_ticks; break; default: return PM_ERR_PMID; } break; default: /* switch cluster */ return PM_ERR_PMID; } return 1; }
int refresh_proc_partitions(pmInDom disk_indom, pmInDom partitions_indom, pmInDom dm_indom) { FILE *fp; int devmin; int devmaj; int n; int indom; int have_proc_diskstats; int inst; unsigned long long blocks; partitions_entry_t *p; int indom_changes = 0; char *dmname; char buf[MAXPATHLEN]; char namebuf[MAXPATHLEN]; static int first = 1; if (first) { /* initialize the instance domain caches */ pmdaCacheOp(disk_indom, PMDA_CACHE_LOAD); pmdaCacheOp(partitions_indom, PMDA_CACHE_LOAD); pmdaCacheOp(dm_indom, PMDA_CACHE_LOAD); first = 0; indom_changes = 1; } pmdaCacheOp(disk_indom, PMDA_CACHE_INACTIVE); pmdaCacheOp(partitions_indom, PMDA_CACHE_INACTIVE); pmdaCacheOp(dm_indom, PMDA_CACHE_INACTIVE); if ((fp = linux_statsfile("/proc/diskstats", buf, sizeof(buf))) != NULL) /* 2.6 style disk stats */ have_proc_diskstats = 1; else { if ((fp = linux_statsfile("/proc/partitions", buf, sizeof(buf))) != NULL) have_proc_diskstats = 0; else return -oserror(); } while (fgets(buf, sizeof(buf), fp) != NULL) { dmname = NULL; if (buf[0] != ' ' || buf[0] == '\n') { /* skip heading */ continue; } if (have_proc_diskstats) { if ((n = sscanf(buf, "%d %d %s", &devmaj, &devmin, namebuf)) != 3) continue; } else { /* /proc/partitions */ if ((n = sscanf(buf, "%d %d %llu %s", &devmaj, &devmin, &blocks, namebuf)) != 4) continue; } if (_pm_isdm(namebuf)) { indom = dm_indom; dmname = strdup(namebuf); } else if (_pm_ispartition(namebuf)) indom = partitions_indom; else if (_pm_isdisk(namebuf)) indom = disk_indom; else continue; if (indom == dm_indom) { /* replace dm-[0-9]* with the persistent name from /dev/mapper */ if (!map_persistent_dm_name(namebuf, sizeof(namebuf), devmaj, devmin)) { /* skip dm devices that have no persistent name mapping */ free(dmname); continue; } } p = NULL; if (pmdaCacheLookupName(indom, namebuf, &inst, (void **)&p) < 0 || !p) { /* not found: allocate and add a new entry */ p = (partitions_entry_t *)malloc(sizeof(partitions_entry_t)); memset(p, 0, sizeof(partitions_entry_t)); indom_changes++; } if (p->dmname) free(p->dmname); p->dmname = dmname; /* NULL if not a dm device */ if (!p->namebuf) p->namebuf = strdup(namebuf); else if (strcmp(namebuf, p->namebuf) != 0) { free(p->namebuf); p->namebuf = strdup(namebuf); } /* activate this entry */ if (p->udevnamebuf) /* long xscsi name */ inst = pmdaCacheStore(indom, PMDA_CACHE_ADD, p->udevnamebuf, p); else /* short /proc/diskstats or /proc/partitions name */ inst = pmdaCacheStore(indom, PMDA_CACHE_ADD, namebuf, p); if (have_proc_diskstats) { /* 2.6 style /proc/diskstats */ p->nr_blocks = 0; namebuf[0] = '\0'; /* Linux source: block/genhd.c::diskstats_show(1) */ n = sscanf(buf, "%u %u %s %lu %lu %llu %u %lu %lu %llu %u %u %u %u", &p->major, &p->minor, namebuf, &p->rd_ios, &p->rd_merges, &p->rd_sectors, &p->rd_ticks, &p->wr_ios, &p->wr_merges, &p->wr_sectors, &p->wr_ticks, &p->ios_in_flight, &p->io_ticks, &p->aveq); if (n != 14) { p->rd_merges = p->wr_merges = p->wr_ticks = p->ios_in_flight = p->io_ticks = p->aveq = 0; /* Linux source: block/genhd.c::diskstats_show(2) */ n = sscanf(buf, "%u %u %s %u %u %u %u\n", &p->major, &p->minor, namebuf, (unsigned int *)&p->rd_ios, (unsigned int *)&p->rd_sectors, (unsigned int *)&p->wr_ios, (unsigned int *)&p->wr_sectors); } } else { /* 2.4 style /proc/partitions */ namebuf[0] = '\0'; n = sscanf(buf, "%u %u %lu %s %lu %lu %llu %u %lu %lu %llu %u %u %u %u", &p->major, &p->minor, &p->nr_blocks, namebuf, &p->rd_ios, &p->rd_merges, &p->rd_sectors, &p->rd_ticks, &p->wr_ios, &p->wr_merges, &p->wr_sectors, &p->wr_ticks, &p->ios_in_flight, &p->io_ticks, &p->aveq); } } /* * If any new disks or partitions have appeared then we * we need to remap the long device names (if /dev/xscsi * exists) and then flush the pmda cache. * * We just let inactive instances rot in the inactive state * (this doesn't happen very often, so is only a minor leak). */ if (indom_changes) { refresh_udev(disk_indom, partitions_indom); pmdaCacheOp(disk_indom, PMDA_CACHE_SAVE); pmdaCacheOp(partitions_indom, PMDA_CACHE_SAVE); pmdaCacheOp(dm_indom, PMDA_CACHE_SAVE); } /* * success */ if (fp) fclose(fp); return 0; }
static void _b(void) { int i; int j; int inst; int sts; char cmd[2*MAXPATHLEN+30]; indom = pmInDom_build(FORQA, 8); pmsprintf(cmd, sizeof(cmd), "rm -f %s/config/pmda/%s", pmGetConfig("PCP_VAR_DIR"), pmInDomStr(indom)); sts = system(cmd); if (sts != 0) fprintf(stderr, "Warning: %s: exit status %d\n", cmd, sts); pmsprintf(cmd, sizeof(cmd), "[ -f %s/config/pmda/%s ] || exit 0; cat %s/config/pmda/%s", pmGetConfig("PCP_VAR_DIR"), pmInDomStr(indom), pmGetConfig("PCP_VAR_DIR"), pmInDomStr(indom)); fprintf(stderr, "\nPopulate the instance domain ...\n"); j = 1; for (i = 0; i < 20; i++) { strncpy(nbuf, xxx, ncount+3); pmsprintf(nbuf, sizeof(nbuf), "%03d", ncount); ncount++; inst = pmdaCacheStore(indom, PMDA_CACHE_ADD, nbuf, (void *)((__psint_t)(0xbeef0000+ncount))); if (inst < 0) fprintf(stderr, "PMDA_CACHE_ADD failed for \"%s\": %s\n", nbuf, pmErrStr(inst)); else if (i > 14) { sts = pmdaCacheOp(indom, PMDA_CACHE_SAVE); fprintf(stderr, "Save -> %d\n", sts); } if (i == j) { j <<= 1; inst = pmdaCacheStore(indom, PMDA_CACHE_HIDE, nbuf, NULL); if (inst < 0) fprintf(stderr, "PMDA_CACHE_HIDE failed for \"%s\": %s\n", nbuf, pmErrStr(inst)); } if (i == 6 || i == 13) { fprintf(stderr, "Save ...\n"); fprintf(stderr, "Before:\n"); sts = system(cmd); if (sts != 0) fprintf(stderr, "Warning: _b:1: %s: exit status %d\n", cmd, sts); sts = pmdaCacheOp(indom, PMDA_CACHE_SAVE); fprintf(stderr, "return -> %d", sts); if (sts < 0) fprintf(stderr, ": %s", pmErrStr(sts)); fputc('\n', stderr); fprintf(stderr, "After:\n"); sts = system(cmd); if (sts != 0) fprintf(stderr, "Warning: _b:2: %s: exit status %d\n", cmd, sts); } if (i == 14) { fprintf(stderr, "Start save after changes ...\n"); } if (i > 14) { sts = system(cmd); if (sts != 0) fprintf(stderr, "Warning: _b:3: %s: exit status %d\n", cmd, sts); } } __pmdaCacheDump(stderr, indom, 0); strncpy(nbuf, xxx, 11+3); pmsprintf(nbuf, sizeof(nbuf), "%03d", 11); fprintf(stderr, "\nHide %s ...\n", nbuf); inst = pmdaCacheStore(indom, PMDA_CACHE_HIDE, nbuf, NULL); if (inst < 0) fprintf(stderr, "PMDA_CACHE_HIDE failed for \"%s\": %s\n", nbuf, pmErrStr(inst)); sts = pmdaCacheOp(indom, PMDA_CACHE_SAVE); fprintf(stderr, "Save -> %d\n", sts); sts = system(cmd); if (sts != 0) fprintf(stderr, "Warning: _b:4: %s: exit status %d\n", cmd, sts); fprintf(stderr, "Add %s ...\n", nbuf); inst = pmdaCacheStore(indom, PMDA_CACHE_ADD, nbuf, (void *)((__psint_t)0xdeadbeef)); if (inst < 0) fprintf(stderr, "PMDA_CACHE_ADD failed for \"%s\": %s\n", nbuf, pmErrStr(inst)); sts = pmdaCacheOp(indom, PMDA_CACHE_SAVE); fprintf(stderr, "Save -> %d\n", sts); sts = system(cmd); if (sts != 0) fprintf(stderr, "Warning: _b:5: %s: exit status %d\n", cmd, sts); fprintf(stderr, "Cull %s ...\n", nbuf); inst = pmdaCacheStore(indom, PMDA_CACHE_CULL, nbuf, NULL); if (inst < 0) fprintf(stderr, "PMDA_CACHE_CULL failed for \"%s\": %s\n", nbuf, pmErrStr(inst)); sts = pmdaCacheOp(indom, PMDA_CACHE_SAVE); fprintf(stderr, "Save -> %d\n", sts); sts = system(cmd); if (sts != 0) fprintf(stderr, "Warning: _b:6: %s: exit status %d\n", cmd, sts); fprintf(stderr, "Add %s ...\n", nbuf); inst = pmdaCacheStore(indom, PMDA_CACHE_ADD, nbuf, (void *)((__psint_t)0xdeadbeef)); if (inst < 0) fprintf(stderr, "PMDA_CACHE_ADD failed for \"%s\": %s\n", nbuf, pmErrStr(inst)); sts = pmdaCacheOp(indom, PMDA_CACHE_SAVE); fprintf(stderr, "Save -> %d\n", sts); sts = system(cmd); if (sts != 0) fprintf(stderr, "Warning: _b:7: %s: exit status %d\n", cmd, sts); }
int pmdaInstance(pmInDom indom, int inst, char *name, __pmInResult **result, pmdaExt *pmda) { int i; int namelen; int err = 0; __pmInResult *res; pmdaIndom *idp = NULL; /* initialize to pander to gcc */ int have_cache = 0; int myinst; char *np; if (pmdaCacheOp(indom, PMDA_CACHE_CHECK)) { have_cache = 1; } else { /* * check this is an instance domain we know about -- code below * assumes this test is complete */ for (i = 0; i < pmda->e_nindoms; i++) { if (pmda->e_indoms[i].it_indom == indom) break; } if (i >= pmda->e_nindoms) return PM_ERR_INDOM; idp = &pmda->e_indoms[i]; } if ((res = (__pmInResult *)malloc(sizeof(*res))) == NULL) return -oserror(); res->indom = indom; if (name == NULL && inst == PM_IN_NULL) res->numinst = __pmdaCntInst(indom, pmda); else res->numinst = 1; if (inst == PM_IN_NULL) { if ((res->instlist = (int *)malloc(res->numinst * sizeof(res->instlist[0]))) == NULL) { free(res); return -oserror(); } } else res->instlist = NULL; if (name == NULL) { if ((res->namelist = (char **)malloc(res->numinst * sizeof(res->namelist[0]))) == NULL) { __pmFreeInResult(res); return -oserror(); } for (i = 0; i < res->numinst; i++) res->namelist[0] = NULL; } else res->namelist = NULL; if (name == NULL && inst == PM_IN_NULL) { /* return inst and name for everything */ if (have_cache) { pmdaCacheOp(indom, PMDA_CACHE_WALK_REWIND); i = 0; while (i < res->numinst && (myinst = pmdaCacheOp(indom, PMDA_CACHE_WALK_NEXT)) != -1) { if (pmdaCacheLookup(indom, myinst, &np, NULL) != PMDA_CACHE_ACTIVE) continue; res->instlist[i] = myinst; if ((res->namelist[i++] = strdup(np)) == NULL) { __pmFreeInResult(res); return -oserror(); } } } else { for (i = 0; i < res->numinst; i++) { res->instlist[i] = idp->it_set[i].i_inst; if ((res->namelist[i] = strdup(idp->it_set[i].i_name)) == NULL) { __pmFreeInResult(res); return -oserror(); } } } } else if (name == NULL) { /* given an inst, return the name */ if (have_cache) { if (pmdaCacheLookup(indom, inst, &np, NULL) == PMDA_CACHE_ACTIVE) { if ((res->namelist[0] = strdup(np)) == NULL) { __pmFreeInResult(res); return -oserror(); } } else err = 1; } else { for (i = 0; i < idp->it_numinst; i++) { if (inst == idp->it_set[i].i_inst) { if ((res->namelist[0] = strdup(idp->it_set[i].i_name)) == NULL) { __pmFreeInResult(res); return -oserror(); } break; } } if (i == idp->it_numinst) err = 1; } } else if (inst == PM_IN_NULL && (namelen = (int)strlen(name)) > 0) { if (have_cache) { if (pmdaCacheLookupName(indom, name, &myinst, NULL) == PMDA_CACHE_ACTIVE) res->instlist[0] = myinst; else err = 1; } else { /* given a name, return an inst. If the name contains spaces, * only exact matches are good enough for us, otherwise, we're * prepared to accept a match upto the first space in the * instance name on the assumption that pmdas will play by the * rules and guarantee the first "word" in the instance name * is unique. That allows for the things like "1 5 15" to match * instances for kernel.all.load["1 minute","5 minute","15 minutes"] */ char * nspace = strchr (name, ' '); for (i = 0; i < idp->it_numinst; i++) { char *instname = idp->it_set[i].i_name; if (strcmp(name, instname) == 0) { /* accept an exact match */ #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_LIBPMDA) { fprintf(stderr, "pmdaInstance: exact match name=%s id=%d\n", name, idp->it_set[i].i_inst); } #endif res->instlist[0] = idp->it_set[i].i_inst; break; } else if (nspace == NULL) { /* all of name must match instname up to the the first * space in instname. */ char *p = strchr(instname, ' '); if (p != NULL) { int len = (int)(p - instname); if (namelen == len && strncmp(name, instname, len) == 0) { #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_LIBPMDA) { fprintf(stderr, "pmdaInstance: matched argument name=\"%s\" with indom id=%d name=\"%s\" len=%d\n", name, idp->it_set[i].i_inst, instname, len); } #endif res->instlist[0] = idp->it_set[i].i_inst; break; } } } } if (i == idp->it_numinst) err = 1; } } else err = 1; if (err == 1) { /* bogus arguments or instance id/name */ __pmFreeInResult(res); return PM_ERR_INST; } *result = res; return 0; }
/* * revised dirty cache semantics * style & 1 => SAVE * style & 2 => SYNC */ static void _i(int style) { int sts; int inst; int i; static int first = 1; indom = pmInDom_build(FORQA, 15); if (first) { sts = pmdaCacheOp(indom, PMDA_CACHE_LOAD); if (sts < 0) { fprintf(stderr, "PMDA_CACHE_LOAD failed: %s\n", pmErrStr(sts)); } first = 0; } for (i = 0; i_tab[i] != NULL; i++) { fprintf(stderr, "[%s]\n", i_tab[i]); inst = pmdaCacheStore(indom, PMDA_CACHE_ADD, i_tab[i], NULL); if (inst < 0) { fprintf(stderr, "ADD failed: %s\n", pmErrStr(inst)); continue; } fprintf(stderr, "ADD -> %d\n", inst); sts = pmdaCacheOp(indom, PMDA_CACHE_SAVE); if (sts < 0) { fprintf(stderr, "PMDA_CACHE_SAVE failed: %s\n", pmErrStr(sts)); } else fprintf(stderr, "SAVE -> %d\n", sts); if (i == 0) { /* last one -> INACTIVE */ inst = pmdaCacheStore(indom, PMDA_CACHE_HIDE, i_tab[i], NULL); if (inst < 0) { fprintf(stderr, "HIDE failed: %s\n", pmErrStr(inst)); continue; } fprintf(stderr, "HIDE -> %d\n", inst); } else if (i == 1) { /* last one -> INACTIVE -> ACTIVE */ inst = pmdaCacheStore(indom, PMDA_CACHE_HIDE, i_tab[i], NULL); if (inst < 0) { fprintf(stderr, "HIDE failed: %s\n", pmErrStr(inst)); continue; } fprintf(stderr, "HIDE -> %d\n", inst); inst = pmdaCacheStore(indom, PMDA_CACHE_ADD, i_tab[i], NULL); if (inst < 0) { fprintf(stderr, "ADD failed: %s\n", pmErrStr(inst)); continue; } fprintf(stderr, "ADD -> %d\n", inst); } else if (i == 2) { /* last one -> EMPTY */ inst = pmdaCacheStore(indom, PMDA_CACHE_CULL, i_tab[i], NULL); if (inst < 0) { fprintf(stderr, "CULL failed: %s\n", pmErrStr(inst)); continue; } fprintf(stderr, "CULL -> %d\n", inst); } else if (i == 3) { /* add another one */ fprintf(stderr, "extra [%s]\n", "felix-the-cat"); inst = pmdaCacheStore(indom, PMDA_CACHE_ADD, "felix-the-cat", NULL); if (inst < 0) { fprintf(stderr, "ADD failed: %s\n", pmErrStr(inst)); continue; } fprintf(stderr, "ADD -> %d\n", inst); } else if (i == 4) { /* do nothing! */ ; } else { /* empty cache */ sts = pmdaCacheOp(indom, PMDA_CACHE_CULL); if (sts < 0) { fprintf(stderr, "PMDA_CACHE_CULL failed: %s\n", pmErrStr(sts)); return; } fprintf(stderr, "CULL ALL -> %d\n", inst); } if (style & 1) { sts = pmdaCacheOp(indom, PMDA_CACHE_SAVE); if (sts < 0) { fprintf(stderr, "PMDA_CACHE_SAVE failed: %s\n", pmErrStr(sts)); } else fprintf(stderr, "SAVE -> %d\n", sts); } if (style & 2) { sts = pmdaCacheOp(indom, PMDA_CACHE_SYNC); if (sts < 0) { fprintf(stderr, "PMDA_CACHE_SYNC failed: %s\n", pmErrStr(sts)); } else fprintf(stderr, "SYNC -> %d\n", sts); } } }
void store_net_addr_indom(pmInDom indom, linux_container_t *container) { if (!container) pmdaCacheOp(indom, PMDA_CACHE_SAVE); }
int refresh_proc_slabinfo(pmInDom slab_indom, proc_slabinfo_t *slabinfo) { slab_cache_t sbuf, *s; char buf[BUFSIZ]; char name[128]; char *w, *p; FILE *fp; int i, sts = 0, indom_change = 0; static int major_version = -1; static int minor_version = 0; for (pmdaCacheOp(slab_indom, PMDA_CACHE_WALK_REWIND);;) { if ((i = pmdaCacheOp(slab_indom, PMDA_CACHE_WALK_NEXT)) < 0) break; if (!pmdaCacheLookup(slab_indom, i, NULL, (void **)&s) || !s) continue; s->seen = 0; } pmdaCacheOp(slab_indom, PMDA_CACHE_INACTIVE); if ((fp = linux_statsfile("/proc/slabinfo", buf, sizeof(buf))) == NULL) return -oserror(); /* skip header */ if (fgets(buf, sizeof(buf), fp) == NULL) { /* oops, no header! */ fclose(fp); return -oserror(); } if (major_version < 0) { major_version = minor_version = 0; if (strstr(buf, "slabinfo - version:")) { for (p = buf; *p; p++) { if (isdigit((int)*p)) { sscanf(p, "%d.%d", &major_version, &minor_version); break; } } } } while (fgets(buf, sizeof(buf), fp) != NULL) { /* try to convert whitespace in cache names to underscores, */ /* by looking for alphabetic chars which follow whitespace. */ if (buf[0] == '#') continue; for (w = NULL, p = buf; *p != '\0'; p++) { if (isspace((int)*p)) w = p; else if (isdigit((int)*p)) break; else if (isalpha((int)*p) && w) { for (; w && w != p; w++) *w = '_'; w = NULL; } } memset(&sbuf, 0, sizeof(slab_cache_t)); if (major_version == 1 && minor_version == 0) { /* * <name> <active_objs> <num_objs> * (generally 2.2 kernels) */ i = sscanf(buf, "%s %lu %lu", name, (unsigned long *)&sbuf.num_active_objs, (unsigned long *)&sbuf.total_objs); if (i != 3) { sts = PM_ERR_APPVERSION; break; } } else if (major_version == 1 && minor_version == 1) { /* * <name> <active_objs> <num_objs> <objsize> <active_slabs> <num_slabs> <pagesperslab> * (generally 2.4 kernels) */ i = sscanf(buf, "%s %lu %lu %u %u %u %u", name, (unsigned long *)&sbuf.num_active_objs, (unsigned long *)&sbuf.total_objs, &sbuf.object_size, &sbuf.num_active_slabs, &sbuf.total_slabs, &sbuf.pages_per_slab); if (i != 7) { sts = PM_ERR_APPVERSION; break; } sbuf.total_size = sbuf.pages_per_slab * sbuf.num_active_slabs; sbuf.total_size <<= _pm_pageshift; } else if (major_version == 2 && minor_version >= 0 && minor_version <= 1) { /* * <name> <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab> .. and more * (generally for kernels up to at least 2.6.11) */ i = sscanf(buf, "%s %lu %lu %u %u %u", name, (unsigned long *)&sbuf.num_active_objs, (unsigned long *)&sbuf.total_objs, &sbuf.object_size, &sbuf.objects_per_slab, &sbuf.pages_per_slab); if (i != 6) { sts = PM_ERR_APPVERSION; break; } sbuf.total_size = sbuf.pages_per_slab * sbuf.num_active_objs; sbuf.total_size <<= _pm_pageshift; sbuf.total_size /= sbuf.objects_per_slab; } else { /* no support */ sts = PM_ERR_APPVERSION; break; } sts = pmdaCacheLookupName(slab_indom, name, &i, (void **)&s); if (sts < 0 || !s) { /* new cache has appeared */ if ((s = calloc(1, sizeof(*s))) == NULL) continue; #if PCP_DEBUG if (pmDebug & DBG_TRACE_LIBPMDA) fprintf(stderr, "refresh_slabinfo: added \"%s\"\n", name); #endif indom_change++; } s->num_active_objs = sbuf.num_active_objs; s->total_objs = sbuf.total_objs; s->object_size = sbuf.object_size; s->num_active_slabs = sbuf.num_active_slabs; s->total_slabs = sbuf.total_slabs; s->pages_per_slab = sbuf.pages_per_slab; s->objects_per_slab = sbuf.objects_per_slab; s->total_size = sbuf.total_size; s->seen = major_version * 10 + minor_version; pmdaCacheStore(slab_indom, PMDA_CACHE_ADD, name, s); } fclose(fp); if (indom_change) pmdaCacheOp(slab_indom, PMDA_CACHE_SAVE); return sts; }
int refresh_proc_net_dev(pmInDom indom, linux_container_t *container) { static uint32_t gen; /* refresh generation number */ static uint32_t cache_err; /* throttle messages */ char buf[1024]; FILE *fp; char *p, *v; int j, sts; net_interface_t *netip; if ((fp = linux_statsfile("/proc/net/dev", buf, sizeof(buf))) == NULL) return -oserror(); if (gen == 0) { /* * first time, reload cache from external file, and force any * subsequent changes to be saved */ pmdaCacheOp(indom, PMDA_CACHE_LOAD); gen++; } /* Inter-| Receive | Transmit face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed lo: 4060748 39057 0 0 0 0 0 0 4060748 39057 0 0 0 0 0 0 eth0: 0 337614 0 0 0 0 0 0 0 267537 0 0 0 27346 62 0 */ pmdaCacheOp(indom, PMDA_CACHE_INACTIVE); while (fgets(buf, sizeof(buf), fp) != NULL) { if ((p = v = strchr(buf, ':')) == NULL) continue; *p = '\0'; for (p=buf; *p && isspace((int)*p); p++) {;} sts = pmdaCacheLookupName(indom, p, NULL, (void **)&netip); if (sts == PM_ERR_INST || (sts >= 0 && netip == NULL)) { /* first time since re-loaded, else new one */ netip = (net_interface_t *)calloc(1, sizeof(net_interface_t)); #if PCP_DEBUG if (pmDebug & DBG_TRACE_LIBPMDA) { fprintf(stderr, "refresh_proc_net_dev: initialize \"%s\"\n", p); } #endif } else if (sts < 0) { if (cache_err++ < 10) { fprintf(stderr, "refresh_proc_net_dev: pmdaCacheLookupName(%s, %s, ...) failed: %s\n", pmInDomStr(indom), p, pmErrStr(sts)); } continue; } if ((sts = pmdaCacheStore(indom, PMDA_CACHE_ADD, p, (void *)netip)) < 0) { if (cache_err++ < 10) { fprintf(stderr, "refresh_proc_net_dev: pmdaCacheStore(%s, PMDA_CACHE_ADD, %s, " PRINTF_P_PFX "%p) failed: %s\n", pmInDomStr(indom), p, netip, pmErrStr(sts)); } continue; } memset(&netip->ioc, 0, sizeof(netip->ioc)); for (p=v, j=0; j < PROC_DEV_COUNTERS_PER_LINE; j++) { for (; !isdigit((int)*p); p++) {;} sscanf(p, "%llu", (long long unsigned int *)&netip->counters[j]); for (; !isspace((int)*p); p++) {;} } } /* success */ fclose(fp); if (!container) pmdaCacheOp(indom, PMDA_CACHE_SAVE); return 0; }