diff --git a/qa/750 b/qa/750 index 050eb0c..3511a24 100755 --- a/qa/750 +++ b/qa/750 @@ -1,17 +1,19 @@ #!/bin/sh # PCP QA Test No. 750 -# Exercise the python collectl implementation +# Exercise the RPM PMDA # # Copyright (c) 2012, 2013 Red Hat. # +seq=`basename $0` +echo "QA output created by $seq" + # get standard environment, filters and checks . ./common.product . ./common.filter . ./common.check -seq=`basename $0` -echo "QA output created by $seq" +which rpm >/dev/null 2>&1 || _notrun "rpm not installed" status=0 # success is the default! $sudo rm -fr $tmp.* $seq.full @@ -35,6 +37,9 @@ canonicalize() -e "s|\[[' /A-Za-z0-9\_\.\,\(\)\-]*\]|['/PATH/NAME', /PATH/NAME']|g" } +# TODO: need to conditionally Install and Remove the PMDA (see test 348) +# currently we're assuming its already there. + # real QA test starts here mkdir $tmp.$seq cd $tmp.$seq @@ -47,12 +52,12 @@ pmval -s 1 rpm.dirnames -i python | canonicalize | tee -a $tmp.out 2>&1 # pmval -s 1 rpm.distribution -i python | canonicalize | tee -a $tmp.out 2>&1 pmval -s 1 rpm.evr -i python | canonicalize | tee -a $tmp.out 2>&1 # pmval -s 1 rpm.file.class -i python | canonicalize | tee -a $tmp.out 2>&1 -pmval -s 1 rpm.file.linktos -i python | canonicalize | tee -a $tmp.out 2>&1 -pmval -s 1 rpm.file.md5s -i python | canonicalize | tee -a $tmp.out 2>&1 -pmval -s 1 rpm.file.modes -i python | canonicalize | tee -a $tmp.out 2>&1 -pmval -s 1 rpm.file.names -i python | canonicalize | tee -a $tmp.out 2>&1 -pmval -s 1 rpm.file.require -i python | canonicalize | tee -a $tmp.out 2>&1 -pmval -s 1 rpm.file.sizes -i python | canonicalize | tee -a $tmp.out 2>&1 +# pmval -s 1 rpm.file.linktos -i python | canonicalize | tee -a $tmp.out 2>&1 +# pmval -s 1 rpm.file.md5s -i python | canonicalize | tee -a $tmp.out 2>&1 +# pmval -s 1 rpm.file.modes -i python | canonicalize | tee -a $tmp.out 2>&1 +# pmval -s 1 rpm.file.names -i python | canonicalize | tee -a $tmp.out 2>&1 +# pmval -s 1 rpm.file.require -i python | canonicalize | tee -a $tmp.out 2>&1 +# pmval -s 1 rpm.file.sizes -i python | canonicalize | tee -a $tmp.out 2>&1 pmval -s 1 rpm.group -i python | canonicalize | tee -a $tmp.out 2>&1 pmval -s 1 rpm.instfilenames -i python | canonicalize | tee -a $tmp.out 2>&1 pmval -s 1 rpm.license -i python | canonicalize | tee -a $tmp.out 2>&1 diff --git a/src/pmdas/rpm/.gitignore b/src/pmdas/rpm/.gitignore index 2535099..b98df7c 100644 --- a/src/pmdas/rpm/.gitignore +++ b/src/pmdas/rpm/.gitignore @@ -1 +1,3 @@ -pmdagluster.py +domain.h +pmdarpm +pmda_rpm.so diff --git a/src/pmdas/rpm/GNUmakefile b/src/pmdas/rpm/GNUmakefile index 78ae8cb..a223b1d 100644 --- a/src/pmdas/rpm/GNUmakefile +++ b/src/pmdas/rpm/GNUmakefile @@ -15,32 +15,48 @@ TOPDIR = ../../.. include $(TOPDIR)/src/include/builddefs -CFILES = rpm.c -CMDTARGET = pmdarpm$(EXECSUFFIX) -LIBTARGET = pmda_rpm.so -LLDLIBS = $(PCP_PMDALIB) -lrpm -lpthread - -LCFLAGS = -I. -LSRCFILES = Install Remove pmns root help - IAM = rpm DOMAIN = RPM + +CMDTARGET = pmda$(IAM)$(EXECSUFFIX) +LIBTARGET = pmda_$(IAM).$(DSOSUFFIX) +TARGETS = $(CMDTARGET) $(LIBTARGET) + PMDADIR = $(PCP_PMDAS_DIR)/$(IAM) -LDIRT = domain.h *.o $(IAM).log pmda$(IAM) pmda_$(IAM).so help.dir help.pag +HFILES = timer.h +CFILES = rpm.c timer.c +LSRCFILES = Install Remove pmns root help +LDIRT = $(TARGETS) domain.h *.o $(IAM).log + +# XXX: move these to configure/builddefs +LIB_FOR_RPM = -lrpm +HAVE_RPM_SUPPORT = 1 + +LCFLAGS = -I. +LLDLIBS = $(PCP_PMDALIB) $(LIB_FOR_RPM) $(LIB_FOR_PTHREADS) -default_pcp default: domain.h $(CMDTARGET) $(LIBTARGET) help.dir help.pag +default: build-me include $(BUILDRULES) -help.dir help.pag : help - $(RUN_IN_BUILD_ENV) $(TOPDIR)/src/newhelp/newhelp -n root -v 2 -o help < help +ifeq "$(HAVE_RPM_SUPPORT)" "1" +build-me: domain.h $(CMDTARGET) $(LIBTARGET) -install_pcp install: default +install: default $(INSTALL) -m 755 -d $(PMDADIR) - $(INSTALL) -m 644 root pmns domain.h help help.dir help.pag $(PMDADIR) + $(INSTALL) -m 644 root pmns domain.h help $(PMDADIR) $(INSTALL) -m 755 $(CMDTARGET) $(LIBTARGET) $(PMDADIR) +else +build-me: +install: +endif + +default_pcp : default + +install_pcp : install domain.h: ../../pmns/stdpmid $(DOMAIN_MAKERULE) +rpm.o timer.o: timer.h diff --git a/src/pmdas/rpm/Install b/src/pmdas/rpm/Install index da7c1e0..9ab14bb 100644 --- a/src/pmdas/rpm/Install +++ b/src/pmdas/rpm/Install @@ -19,9 +19,8 @@ . $PCP_SHARE_DIR/lib/pmdaproc.sh iam=rpm -python_opt=true -daemon_opt=false -forced_restart=true +daemon_opt=true +pipe_opt=true pmdaSetup pmdaInstall diff --git a/src/pmdas/rpm/help b/src/pmdas/rpm/help index b85b5ef..0a3c636 100644 --- a/src/pmdas/rpm/help +++ b/src/pmdas/rpm/help @@ -114,3 +114,7 @@ Url of the package. @ rpm.version package version Version of the package. +@ rpm.refresh.count Cumulative count of rpmdb scans performed +@ rpm.refresh.time.user Cumulative count of user mode scan time +@ rpm.refresh.time.kernel Cumulative count of kernel mode scan time +@ rpm.refresh.time.elapsed Cumulative count of elapsed scan time diff --git a/src/pmdas/rpm/pmdarpm.python b/src/pmdas/rpm/pmdarpm.python deleted file mode 100644 index b20ffd0..0000000 --- a/src/pmdas/rpm/pmdarpm.python +++ /dev/null @@ -1,194 +0,0 @@ -''' -Python implementation of the "rpm" Performance Metrics Domain Agent. -''' -# -# Copyright (c) 2013 Red Hat. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# for more details. -# - -from subprocess import Popen, PIPE, STDOUT -from threading import Thread -from posixpath import getmtime -import rpm -from ctypes import c_int, POINTER, cast -import cpmapi as c_api -from pcp.pmda import PMDA, pmdaMetric, pmdaIndom -from pcp.pmapi import pmUnits, pmContext as PCP - - -class setup_indom(Thread): - ''' - Thread to create an indom whose components are the current rpm package list - ''' - - def __init__(self, pmda, name): - Thread.__init__(self) - self.pmda = pmda - self.name = name - - def run(self): - package_list = self.pmda.rpm_handle.dbMatch() - rpms = {} - i = 0 - replace_indom = False - - # Get current package list - for package in package_list: - if replace_indom == False and package not in rpms: - replace_indom = True - rpms[package['name']] = c_int(i) - i += 1 - - # Rebuild if a package was added or a package was removed - if replace_indom == True or len(rpms) != len(self.pmda.rpms_by_n): - self.pmda.log("Updated indom with " + str(i) + " packages") - self.pmda.replace_indom(self.pmda.source_indom, rpms) - - for (k, v) in rpms.iteritems(): - nv = int (v.value) - self.pmda.rpms_by_n[nv] = k - - -class RpmPMDA(PMDA): - ''' - A Performance Metrics Domain Agent for rpm metrics. - ''' - - source = {} - state = {} - - # rpm.numfetch properties - numfetch = 0 - oldfetch = -1 - - - rpm_metrics = ( -# Name, Cluster, Item (assigned), Tag from rpm.py - ['.name', 0, 0, "RPMTAG_NAME"], \ - ['.sourcerpm', 0, 0, "RPMTAG_SOURCERPM"], \ - ['.summary', 0, 0, "RPMTAG_SUMMARY"], \ - ['.size', 0, 0, "RPMTAG_SIZE"], \ - ['.description', 0, 0, "RPMTAG_DESCRIPTION"], \ - ['.arch', 0, 0, "RPMTAG_ARCH"], \ - ['.release', 0, 0, "RPMTAG_RELEASE"], \ - ['.version', 0, 0, "RPMTAG_VERSION"], \ - ['.url', 0, 0, "RPMTAG_URL"], \ - ['.basenames', 0, 0, "RPMTAG_BASENAMES"], \ - ['.dirnames', 0, 0, "RPMTAG_DIRNAMES"], \ - ['.distribution', 0, 0, "RPMTAG_DISTRIBUTION"], \ - ['.evr', 0, 0, "RPMTAG_EVR"], \ - ['.group', 0, 0, "RPMTAG_GROUP"], \ - ['.list', 0, 0, "RPMTAG_FILENAMES"], \ - ['.instfilenames', 0, 0, "RPMTAG_INSTFILENAMES"], \ - ['.license', 0, 0, "RPMTAG_LICENSE"], \ - ['.platform', 0, 0, "RPMTAG_PLATFORM"], \ - ['.obsoletes', 0, 0, "RPMTAG_OBSOLETES"], \ - ['.provides', 0, 0, "RPMTAG_PROVIDES"], \ - ['.requires', 0, 0, "RPMTAG_REQUIRES"], \ - ['.buildtime', 0, 0, "RPMTAG_BUILDTIME"], \ - ['.file.class', 9, 0, "RPMTAG_FILECLASS"], \ - ['.file.linktos', 9, 0, "RPMTAG_FILELINKTOS"], \ - ['.file.names', 9, 0, "RPMTAG_FILENAMES"], \ - ['.file.md5s', 9, 0, "RPMTAG_FILEMD5S"], \ - ['.file.modes', 9, 0, "RPMTAG_FILEMODES"], \ - ['.file.require', 9, 0, "RPMTAG_FILEREQUIRE"], \ - ['.file.sizes', 9, 0, "RPMTAG_FILESIZES"], \ - ) - def rpm_instance(self, serial): - ''' - Called once per instance request; to check if package list has changed. - ''' - - # Wait on setup_indom thread if it is actively updating the indom - if self.updating_indom == True: - self.indom_thread.join() - self.updating_indom = False - - # If the rpm database has changed then reload the package list - rpmdb_mtime = getmtime("/var/lib/rpm/Packages") - if (self.rpmdb_mtime != rpmdb_mtime): - self.rpmdb_mtime = rpmdb_mtime - self.updating_indom = True - self.indom_thread = setup_indom(self, self.myname) - self.indom_thread.start() - - - def rpm_fetch_callback(self, cluster, item, inst): - ''' - Main fetch callback - Get metric rpm.cluster.item for instance inst; - e.g. get the filename list (.list) for the python instance - ''' - - qtype = "" - # Get the metric rpm.cluster.item - for m in self.rpm_metrics: - if (cluster == m[1] and item == m[2]): - qtype = m[3] - if len(qtype) == 0: - return [c_api.PM_ERR_PMID, 0] - - instp = self.inst_lookup(self.source_indom, inst) - if (instp == None) - return [c_api.PM_ERR_INST, 0] - valuep = cast(instp, POINTER(c_int)) - try: - rpm_name = self.rpms_by_n[valuep.contents.value] - except KeyError: - self.log("Key %s/%#x not in rpms list %s/%s/%s" % (str(instp.value),valuep.contents.value,str(cluster),str(item),str(inst))) - return [c_api.PM_ERR_INST, 0] - - # Get the metric for this inst - package_list = self.rpm_handle.dbMatch('name', rpm_name) - for package in package_list: - metric_value = str(package[eval("rpm." + qtype)]) - - return [metric_value, 1] - - - def __init__(self, name, domain): - PMDA.__init__(self, name, domain) - - self.configfile = PCP.pmGetConfig('PCP_PMDAS_DIR') - self.configfile += '/' + name + '/' + name + '.conf' - - self.source_indom = self.indom(0) - self.add_indom(pmdaIndom(self.source_indom, self.source)) - - self.myname = name - self.rpm_handle = rpm.TransactionSet() - - self.rpmdb_mtime = getmtime("/var/lib/rpm/Packages") - self.rpms_by_n = {} - self.indom_thread = setup_indom(self, name) - self.updating_indom = True - self.indom_thread.start() - - cluster = -1 - for m in self.rpm_metrics: - if cluster != m[1]: - cluster = m[1] - item = 0 - item += 1 - m[2] = item - self.add_metric(name + m[0], pmdaMetric(self.pmid(cluster, item), \ - c_api.PM_TYPE_STRING, self.source_indom, \ - c_api.PM_SEM_INSTANT, pmUnits(0, 0, 0, 0, 0, 0))) - - self.set_instance(self.rpm_instance) - self.set_fetch_callback(self.rpm_fetch_callback) - self.set_user(PCP.pmGetConfig('PCP_USER')) - - -if __name__ == '__main__': - - RpmPMDA('rpm', 255).run() diff --git a/src/pmdas/rpm/pmns b/src/pmdas/rpm/pmns index 6e25467..62722c2 100644 --- a/src/pmdas/rpm/pmns +++ b/src/pmdas/rpm/pmns @@ -38,5 +38,11 @@ rpm.file { rpm.refresh { count RPM:0:0 - time RPM:0:1 -} \ No newline at end of file + time +} + +rpm.refresh.time { + user RPM:0:1 + kernel RPM:0:2 + elapsed RPM:0:3 +} diff --git a/src/pmdas/rpm/rpm.c b/src/pmdas/rpm/rpm.c index 77bed01..5e644fe 100644 --- a/src/pmdas/rpm/rpm.c +++ b/src/pmdas/rpm/rpm.c @@ -15,24 +15,18 @@ */ #include -#include -#include #include #include - #include - - #include #include #include #include - #include #include #include - #include "domain.h" +#include "timer.h" // List of metrics corresponding to rpm --querytags @@ -165,7 +159,6 @@ static struct metrics { RPMTAG_VERSION, 0} }; - #define METRICTAB_ENTRY(M,N,T) (&metrics[N].tag), { PMDA_PMID (M, N), T, 0, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, static pmdaMetric metrictab[] = { @@ -173,14 +166,26 @@ static pmdaMetric metrictab[] = { * refresh.count */ {NULL, - {PMDA_PMID(0, 0), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, - PMDA_PMUNITS(0, 0, 0, 0, 0, 0)},}, + {PMDA_PMID(0, 0), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)},}, + /* + * refresh.time.user + */ + {NULL, + {PMDA_PMID(0, 1), PM_TYPE_DOUBLE, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_SEC, 0)},}, + /* + * refresh.time.kernel + */ + {NULL, + {PMDA_PMID(0, 2), PM_TYPE_DOUBLE, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_SEC, 0)},}, /* - * refresh.time + * refresh.time.elapsed */ {NULL, - {PMDA_PMID(0, 1), PM_TYPE_DOUBLE, PM_INDOM_NULL, PM_SEM_INSTANT, - PMDA_PMUNITS(0, 0, 0, 0, 0, 0)},}, + {PMDA_PMID(0, 3), PM_TYPE_DOUBLE, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_SEC, 0)},}, /* * arch */ @@ -319,13 +324,15 @@ cache_entry *current_cache_entry; static pthread_t indom_thread; // To notice when the rpm database changes static pthread_t inotify_thread; -static long numrefresh = 0; +static unsigned long long numrefresh; // hash table info used by hsearch_r #define HASH_HBOUND 5000 struct hsearch_data htab; +// It would be good to have a comment (or struct) showing shared data +// locked by this lock... pthread_rwlock_t indom_lock; // Load the instances dynamically @@ -339,17 +346,8 @@ static pmInDom *rpm_indom = &indomtab[0].it_indom; static int isDSO = 1; static char *username; -#define RPM_BUFSIZE 256 - -static char mypath[MAXPATHLEN]; - -/* - * Callback provided to pmdaFetch to fetch values from rpm db corresponding to metric_querytags - */ - static int -rpm_fetchCallBack(pmdaMetric * mdesc, unsigned int inst, - pmAtomValue * atom) +rpm_fetchCallBack(pmdaMetric * mdesc, unsigned int inst, pmAtomValue * atom) { int ret_type; ENTRY e, @@ -358,6 +356,7 @@ rpm_fetchCallBack(pmdaMetric * mdesc, unsigned int inst, pmAtomValue this_atom; int type; int tag; + // Get the instance name for this instance char *rpm_inst_name; int cacheidx = pmdaCacheLookup(*rpm_indom, inst, &rpm_inst_name, NULL); @@ -368,16 +367,27 @@ rpm_fetchCallBack(pmdaMetric * mdesc, unsigned int inst, } if (idp->cluster == 0) { - if (idp->item == 0) { /* rpm.refresh.count */ - atom->ll = numrefresh; - return PMDA_FETCH_STATIC; -// } else if (idp->item == 1) { /* rpm.refresh.time */ - double usr, - sys; - __pmProcessRunTimes(&usr, &sys); - atom->d = usr + sys; - return PMDA_FETCH_STATIC; + ret_type = PMDA_FETCH_STATIC; + pthread_rwlock_rdlock(&indom_lock); + switch (idp->item) { + case 0: /* rpm.refresh.count */ + atom->ull = numrefresh; + break; + case 1: /* rpm.refresh.time.user */ + atom->d = get_user_timer(); + break; + case 2: /* rpm.refresh.time.kernel */ + atom->d = get_kernel_timer(); + break; + case 3: /* rpm.refresh.time.elapsed */ + atom->d = get_elapsed_timer(); + break; + default: + ret_type = PM_ERR_PMID; + break; } + pthread_rwlock_unlock(&indom_lock); + return ret_type; } type = ((struct metrics *) mdesc->m_user)->type; @@ -394,6 +404,7 @@ rpm_fetchCallBack(pmdaMetric * mdesc, unsigned int inst, e.key = rpm_inst_name; e.data = NULL; if (hsearch_r(e, FIND, &ep, &htab) == 0) +/*BUG... (lock leak here) */ return PM_ERR_INST; // the hash table points to the metrics for this rpm @@ -412,24 +423,41 @@ rpm_fetchCallBack(pmdaMetric * mdesc, unsigned int inst, atom->ll = this_atom.ll; ret_type = PMDA_FETCH_STATIC; break; + default: + ret_type = PM_ERR_TYPE; + break; } pthread_rwlock_unlock(&indom_lock); - return ret_type; } -/* - * Called once for each pmFetch(3) operation. Join the indom loading thread here. - */ - +/* Sync up with the (initial) indom loading thread */ static int -rpm_fetch(int numpmid, pmID pmidlist[], pmResult ** resp, pmdaExt * pmda) +notready(pmdaExt *pmda) { + __pmSendError(pmda->e_outfd, FROM_ANON, PM_ERR_PMDANOTREADY); pthread_join(indom_thread, NULL); + return PM_ERR_PMDAREADY; +} + +/* Called once for each pmFetch(3) operation */ +static int +rpm_fetch(int numpmid, pmID pmidlist[], pmResult **resp, pmdaExt *pmda) +{ + if (numrefresh == 0) + return notready(pmda); return pmdaFetch(numpmid, pmidlist, resp, pmda); } +/* Called once for each pmGetInDom(3) operation */ +static int +rpm_instance(pmInDom id, int i, char *name, __pmInResult **in, pmdaExt *pmda) +{ + if (numrefresh == 0) + return notready(pmda); + return pmdaInstance(id, i, name, in, pmda); +} /* * Load the rpm module names into the instance table @@ -442,15 +470,10 @@ rpm_update_cache(void *ptr) Header h; rpmdbMatchIterator mi; rpmtd td; - double usr1, - usr2, - sys1, - sys2; - - numrefresh++; + int sts = 0; - __pmProcessRunTimes(&usr1, &sys1); pthread_rwlock_wrlock(&indom_lock); + start_timing(); td = rpmtdNew(); ts = rpmtsCreate(); @@ -496,7 +519,8 @@ rpm_update_cache(void *ptr) if (current_cache_entry == NULL) { __pmNotifyErr(LOG_INFO, "strdup(%d) for %d failed", (int) strlen(rpmval), i); - return -ENOMEM; + sts = -ENOMEM; + break; } metrics[i].type = PM_TYPE_STRING; break; @@ -590,20 +614,19 @@ rpm_update_cache(void *ptr) // run through the cache and load the hash table for (this_cache_entry = cache; this_cache_entry != NULL; this_cache_entry = this_cache_entry->next) { - e.key = this_cache_entry->entry[16].cp; + e.key = this_cache_entry->entry[16].cp; // hmm, whats 16?? if (!e.key) continue; e.data = this_cache_entry; - if (hsearch_r(e, ENTER, &ep, &htab) == 0) - return PM_ERR_INST; + if (hsearch_r(e, ENTER, &ep, &htab) == 0) { + sts = PM_ERR_INST; + break; + } } - __pmProcessRunTimes(&usr2, &sys2); - __pmNotifyErr(LOG_NOTICE, "user/%g sys/%g", (usr2 - usr1) / 100, - (sys2 - sys1) / 100); - + stop_timing(); pthread_rwlock_unlock(&indom_lock); - return 0; + return sts; } @@ -616,12 +639,6 @@ rpm_update_indom(void *ptr) { int sts; cache_entry *this_cache_entry; - double usr1, - usr2, - sys1, - sys2; - - numrefresh++; // For rebuilding the hash table hdestroy_r(&htab); @@ -630,8 +647,9 @@ rpm_update_indom(void *ptr) rpm_update_cache(NULL); - __pmProcessRunTimes(&usr1, &sys1); pthread_rwlock_wrlock(&indom_lock); + start_timing(); + sts = pmdaCacheOp(*rpm_indom, PMDA_CACHE_INACTIVE); if (sts < 0) __pmNotifyErr(LOG_ERR, @@ -643,7 +661,7 @@ rpm_update_indom(void *ptr) for (this_cache_entry = cache; this_cache_entry != NULL; this_cache_entry = this_cache_entry->next) { ENTRY e; - e.key = this_cache_entry->entry[16].cp; + e.key = this_cache_entry->entry[16].cp; // hmm, whats 16?? if (!e.key) continue; sts = @@ -654,11 +672,10 @@ rpm_update_indom(void *ptr) pmInDomStr(*rpm_indom), pmErrStr(sts)); } - __pmProcessRunTimes(&usr2, &sys2); - __pmNotifyErr(LOG_NOTICE, "user/%g sys/%g", (usr2 - usr1) / 100, - (sys2 - sys1) / 100); + stop_timing(); pthread_rwlock_unlock(&indom_lock); + numrefresh++; return NULL; } @@ -711,7 +728,8 @@ void rpm_init(pmdaInterface * dp) { if (isDSO) { - pmdaDSO(dp, PMDA_INTERFACE_5, "rpm DSO", mypath); + char helppath[MAXPATHLEN]; + pmdaDSO(dp, PMDA_INTERFACE_5, "rpm DSO", helppath); } else { __pmSetProcessIdentity(username); } @@ -719,18 +737,19 @@ rpm_init(pmdaInterface * dp) if (dp->status != 0) return; + pthread_rwlock_init(&indom_lock, NULL); // Load rpms into instance table pthread_create(&indom_thread, NULL, rpm_update_indom, NULL); // Note changes to the rpm database pthread_create(&inotify_thread, NULL, rpm_inotify, NULL); dp->version.any.fetch = rpm_fetch; + dp->version.any.instance = rpm_instance; pmdaSetFetchCallBack(dp, rpm_fetchCallBack); - - pmdaInit(dp, indomtab, 1, metrictab, - sizeof(metrictab) / sizeof(metrictab[0])); + pmdaInit(dp, indomtab, sizeof(indomtab) / sizeof(indomtab[0]), + metrictab, sizeof(metrictab) / sizeof(metrictab[0])); if (dp->status != 0) __pmNotifyErr(LOG_ERR, "pmdaInit failed %d", dp->status); @@ -764,15 +783,17 @@ main(int argc, char **argv) err = 0; int sep = __pmPathSeparator(); pmdaInterface dispatch; + char helppath[MAXPATHLEN]; isDSO = 0; __pmSetProgname(argv[0]); + __pmProcessDataSize(NULL); __pmGetUsername(&username); - snprintf(mypath, sizeof(mypath), "%s%c" "rpm" "%c" "help", + snprintf(helppath, sizeof(helppath), "%s%c" "rpm" "%c" "help", pmGetConfig("PCP_PMDAS_DIR"), sep, sep); pmdaDaemon(&dispatch, PMDA_INTERFACE_5, pmProgname, RPM, - "rpm.log", mypath); + "rpm.log", helppath); while ((c = pmdaGetOpt(argc, argv, "D:d:i:l:pu:6:U:?", &dispatch, diff --git a/src/pmdas/rpm/timer.c b/src/pmdas/rpm/timer.c new file mode 100644 index 0000000..89cd8aa --- /dev/null +++ b/src/pmdas/rpm/timer.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2013 Red Hat. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include +#include +#include +#include + +static struct rusage start_rsrc, final_rsrc; +static struct timeval start_time, final_time; +static double user, kernel, elapsed; + +double get_user_timer() { return user; } +double get_kernel_timer() { return kernel; } +double get_elapsed_timer() { return elapsed; } + +void +start_timing(void) +{ + getrusage(RUSAGE_SELF, &start_rsrc); + gettimeofday(&start_time, NULL); +} + +void +stop_timing(void) +{ + gettimeofday(&final_time, NULL); + getrusage(RUSAGE_SELF, &final_rsrc); + + /* accumulate the totals as we go */ + user += __pmtimevalSub(&final_rsrc.ru_utime, &start_rsrc.ru_utime); + kernel += __pmtimevalSub(&final_rsrc.ru_stime, &start_rsrc.ru_stime); + elapsed += __pmtimevalSub(&final_time, &start_time); +} diff --git a/src/pmdas/rpm/timer.h b/src/pmdas/rpm/timer.h new file mode 100644 index 0000000..529ca33 --- /dev/null +++ b/src/pmdas/rpm/timer.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2013 Red Hat. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ +#ifndef TIMER_H +#define TIMER_H + +extern void start_timing(void); +extern void stop_timing(void); + +extern double get_user_timer(void); +extern double get_kernel_timer(void); +extern double get_elapsed_timer(void); + +#endif /* TIMER_H */