diff options
Diffstat (limited to 'src/libpcp_pmcd')
-rw-r--r-- | src/libpcp_pmcd/GNUlocaldefs.32 | 4 | ||||
-rw-r--r-- | src/libpcp_pmcd/GNUmakefile | 35 | ||||
-rw-r--r-- | src/libpcp_pmcd/src/GNUmakefile | 88 | ||||
-rw-r--r-- | src/libpcp_pmcd/src/client.c | 61 | ||||
-rw-r--r-- | src/libpcp_pmcd/src/data.c | 43 | ||||
-rw-r--r-- | src/libpcp_pmcd/src/pmcd.stp.in | 304 | ||||
-rw-r--r-- | src/libpcp_pmcd/src/probes.d | 4 | ||||
-rw-r--r-- | src/libpcp_pmcd/src/trace.c | 289 |
8 files changed, 828 insertions, 0 deletions
diff --git a/src/libpcp_pmcd/GNUlocaldefs.32 b/src/libpcp_pmcd/GNUlocaldefs.32 new file mode 100644 index 0000000..38bc43e --- /dev/null +++ b/src/libpcp_pmcd/GNUlocaldefs.32 @@ -0,0 +1,4 @@ +LCFLAGS += -m32 -march=i386 +LLDFLAGS += -m32 -march=i386 +PCP_LIB_DIR=$(PCP_LIB32_DIR) +LIBPCP_ABIDIR=32 diff --git a/src/libpcp_pmcd/GNUmakefile b/src/libpcp_pmcd/GNUmakefile new file mode 100644 index 0000000..936948f --- /dev/null +++ b/src/libpcp_pmcd/GNUmakefile @@ -0,0 +1,35 @@ +# +# Copyright (c) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# This library 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 Lesser General Public +# License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +TOPDIR = ../.. + +include $(TOPDIR)/src/include/builddefs + +LSRCFILES = GNUlocaldefs.32 + +SUBDIRS = src $(PCP_ALTLIBS) + +default install : $(SUBDIRS) + $(SUBDIRS_MAKERULE) + +include $(BUILDRULES) + +default_pcp : default + +install_pcp : install + diff --git a/src/libpcp_pmcd/src/GNUmakefile b/src/libpcp_pmcd/src/GNUmakefile new file mode 100644 index 0000000..1242269 --- /dev/null +++ b/src/libpcp_pmcd/src/GNUmakefile @@ -0,0 +1,88 @@ +# +# Copyright (c) 2013 Red Hat. +# Copyright (c) 2008 Aconex. All Rights Reserved. +# Copyright (c) 2000,2003,2004 Silicon Graphics, Inc. All Rights Reserved. +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# This library 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 Lesser General Public +# License for more details. +# + +TOPDIR = ../../.. +include $(TOPDIR)/src/include/builddefs +-include ./GNUlocaldefs + +CFILES = data.c trace.c client.c +LSRCFILES = pmcd.stp.in probes.d + +LCFLAGS = -I$(TOPDIR)/src/pmcd/src -I$(TOPDIR)/src/libpcp/src -DPMCD_INTERNAL +LLDLIBS = -lpcp + +ifeq "$(ENABLE_SECURE)" "true" +LCFLAGS += $(NSSCFLAGS) $(NSPRCFLAGS) +endif + +ifeq "$(ENABLE_PROBES)" "true" +ifeq "$(TARGET_OS)" "linux" +OBJECTS += probes.o +endif +LDIRT += probes.h pmcd.stp +endif + +ifeq "$(TARGET_OS)" "mingw" +LIBTARGET = libpcp_pmcd.$(DSOSUFFIX) +LDIRT += libpcp_pmcd.a +else +STATICLIBTARGET = libpcp_pmcd.a +LDIRT += libpcp_pmcd.$(DSOSUFFIX) +endif + +default : $(LIBTARGET) $(STATICLIBTARGET) + +# Static probing for Linux, Mac OS X and Solaris. +ifeq "$(ENABLE_PROBES)" "true" +ifneq "$(findstring $(TARGET_OS),linux darwin freebsd)" "" +trace.o: probes.h +probes.h: probes.d pmcd.stp + $(DTRACE) -h -s $< -o $@ +probes.o: probes.d + $(DTRACE) -G -s $< -o $@ +endif +ifeq "$(TARGET_OS)" "solaris" +$(STATICLIBTARGET): rewrite +trace.o: probes.h +probes.h: probes.d + $(DTRACE) -h -s $< -o $@ +rewrite: trace.o + $(DTRACE) -G -s probes.d trace.o + touch rewrite +LDIRT += rewrite +endif +endif + +pmcd.stp : pmcd.stp.in + $(SED) -e 's;@path@;'$(PCP_BINADM_DIR)/pmcd';' $< > $@ + +include $(BUILDRULES) + +install : default +ifeq "$(TARGET_OS)" "mingw" + $(INSTALL) -m 755 $(LIBTARGET) $(PCP_LIB_DIR)/$(LIBTARGET) +endif + +ifeq "$(ENABLE_PROBES)" "true" +ifeq "$(TARGET_OS)" "linux" + $(INSTALL) -m 755 -d $(PCP_SHARE_DIR)/../systemtap/tapset + $(INSTALL) -m 444 pmcd.stp $(PCP_SHARE_DIR)/../systemtap/tapset/pmcd.stp +endif +endif + +default_pcp : default + +install_pcp : install diff --git a/src/libpcp_pmcd/src/client.c b/src/libpcp_pmcd/src/client.c new file mode 100644 index 0000000..be941a2 --- /dev/null +++ b/src/libpcp_pmcd/src/client.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2012-2013 Red Hat. + * Copyright (c) 1995-2001,2004 Silicon Graphics, Inc. All Rights Reserved. + * + * 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 "pmapi.h" +#include "impl.h" +#include "pmcd.h" + +PMCD_INTERN ClientInfo *client; +PMCD_INTERN int nClients; /* Number in array, (not all in use) */ +PMCD_INTERN int this_client_id; + +void +ShowClients(FILE *f) +{ + int i; + char *sbuf; + char *hostName; + + fprintf(f, " fd client connection from ipc ver operations denied\n"); + fprintf(f, " == ======================================== ======= =================\n"); + for (i = 0; i < nClients; i++) { + if (client[i].status.connected == 0) + continue; + + fprintf(f, " %3d ", client[i].fd); + + hostName = __pmGetNameInfo(client[i].addr); + if (hostName == NULL) { + sbuf = __pmSockAddrToString(client[i].addr); + fprintf(f, "%s", sbuf); + free(sbuf); + } else { + fprintf(f, "%-40.40s", hostName); + free(hostName); + } + fprintf(f, " %7d", __pmVersionIPC(client[i].fd)); + + if (client[i].denyOps != 0) { + fprintf(f, " "); + if (client[i].denyOps & PMCD_OP_FETCH) + fprintf(f, "fetch "); + if (client[i].denyOps & PMCD_OP_STORE) + fprintf(f, "store "); + } + + fputc('\n', f); + } + fputc('\n', f); +} diff --git a/src/libpcp_pmcd/src/data.c b/src/libpcp_pmcd/src/data.c new file mode 100644 index 0000000..ca257b0 --- /dev/null +++ b/src/libpcp_pmcd/src/data.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2012 Red Hat. + * Copyright (c) 1995-2001,2004 Silicon Graphics, Inc. All Rights Reserved. + * + * 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 "pmcd.h" + +/* + * Global data shared by pmcd and the pmcd PMDA DSO must reside + * in a DSO as well, due to linkage oddities with Windows DLLs. + */ + +PMCD_INTERN int pmcd_hi_openfds = -1; /* Highest open pmcd file descriptor */ +PMCD_INTERN int _pmcd_done; /* flag from pmcd pmda */ +PMCD_INTERN int _pmcd_timeout = 5; /* Timeout for hung agents */ + +PMCD_INTERN int nAgents; /* Number of active agents */ +PMCD_INTERN AgentInfo *agent; /* Array of agent info structs */ + +PMCD_INTERN char *_pmcd_hostname; /* Explicitly requested hostname */ +/* + * File descriptors are used as an internal index with the advent + * of NSPR in libpcp. We (may) need to first decode the index to + * an internal representation and lookup the real file descriptor. + * Note the use of on-stack fd overwrite, avoiding local variable. + */ + +void +pmcd_openfds_sethi(int fd) +{ + if ((fd = __pmFD(fd)) > pmcd_hi_openfds) + pmcd_hi_openfds = fd; +} diff --git a/src/libpcp_pmcd/src/pmcd.stp.in b/src/libpcp_pmcd/src/pmcd.stp.in new file mode 100644 index 0000000..83864b3 --- /dev/null +++ b/src/libpcp_pmcd/src/pmcd.stp.in @@ -0,0 +1,304 @@ +// Performance CoPilot pmcd tapset +// Copyright (C) 2013 Red Hat Inc. +// +// This file is part of SystemTap, and is free software. You can +// redistribute it and/or modify it under the terms of the GNU General +// Public License (GPL); either version 2, or (at your option) any +// later version. + + +global pmid_domain[2] +global pmid_cluster[2] +global pmid_item[2] +global pmindom_domain[2] +global pmindom_serial[2] +global pdu_types[25] + +# from impl.h +global PDU_ERROR = 0x7000 +global PDU_RESULT = 0x7001 +global PDU_PROFILE = 0x7002 +global PDU_FETCH = 0x7003 +global PDU_DESC_REQ = 0x7004 +global PDU_DESC = 0x7005 +global PDU_INSTANCE_REQ = 0x7006 +global PDU_INSTANCE = 0x7007 +global PDU_TEXT_REQ = 0x7008 +global PDU_TEXT = 0x7009 +global PDU_CONTROL_REQ = 0x700a +global PDU_CREDS = 0x700c +global PDU_PMNS_IDS = 0x700d +global PDU_PMNS_NAMES = 0x700e +global PDU_PMNS_CHILD = 0x700f +global PDU_PMNS_TRAVERSE = 0x7010 +global PDU_AUTH = 0x7011 +global PDU_LOG_CONTROL = 0x8000 +global PDU_LOG_STATUS = 0x8001 +global PDU_LOG_REQUEST = 0x8002 +global DYNAMIC_PMID = 511 +global PM_INDOM_NULL = 0xffffffff +global PM_ID_NULL = 0xffffffff + +# from pmcd.h +global TR_ADD_CLIENT = 1 +global TR_DEL_CLIENT = 2 +global TR_ADD_AGENT = 3 +global TR_DEL_AGENT = 4 +global TR_EOF = 5 +global TR_XMIT_PDU = 7 +global TR_RECV_PDU = 8 +global TR_WRONG_PDU = 9 +global TR_XMIT_ERR = 10 +global TR_RECV_TIMEOUT = 11 +global TR_RECV_ERR = 12 + +# Use the same naming scheme as trace.c::tracebuf +# We sadly eschew stap 2.0+ feature to make $argN more symbolic: +# @define t_type %( $arg1 %) +# @define t_who %( $arg2 %) +# @define t_p1 %( $arg3 %) +# @define t_p2 %( $arg4 %) + + +probe begin { + // [0]=bit start position [1]=bit length + pmid_item[0] = 0 + pmid_item[1] = 10 + pmid_cluster[0] = 10 + pmid_cluster[1] = 12 + pmid_domain[0] = 22 + pmid_domain[1] = 9 + pmindom_serial[0] = 0 + pmindom_serial[1] = 22 + pmindom_domain[0] = 22 + pmindom_domain[1] = 9 + + pdu_types[PDU_ERROR] = "ERROR"; + pdu_types[PDU_RESULT] = "RESULT"; + pdu_types[PDU_PROFILE] = "PROFILE"; + pdu_types[PDU_FETCH] = "FETCH"; + pdu_types[PDU_DESC_REQ] = "DESC_REQ"; + pdu_types[PDU_DESC] = "DESC"; + pdu_types[PDU_INSTANCE_REQ] = "INSTANCE_REQ"; + pdu_types[PDU_INSTANCE] = "INSTANCE"; + pdu_types[PDU_TEXT_REQ] = "TEXT_REQ"; + pdu_types[PDU_TEXT] = "TEXT"; + pdu_types[PDU_CONTROL_REQ] = "CONTROL_REQ"; + pdu_types[PDU_CREDS] = "CREDS"; + pdu_types[PDU_PMNS_IDS] = "PMNS_IDS"; + pdu_types[PDU_PMNS_NAMES] = "PMNS_NAMES"; + pdu_types[PDU_PMNS_CHILD] = "PMNS_CHILD"; + pdu_types[PDU_PMNS_TRAVERSE] = "PMNS_TRAVERSE"; + pdu_types[PDU_LOG_CONTROL] = "LOG_CONTROL"; + pdu_types[PDU_LOG_STATUS] = "LOG_STATUS"; + pdu_types[PDU_LOG_REQUEST] = "LOG_REQUEST"; + pdu_types[PDU_AUTH] = "AUTH"; + pdu_types[-1] = "NO"; +} + + +function bitextract (bits, start, length) +{ + // HAVE_BITFIELDS_LTOR ? + %( arch != "i386" && arch != "x86_64" %? + // HAVE_BITFIELDS_RTOL + start = 32 - start - length; + %) + return ((bits >> start) & ((1 << length) - 1)); +} + +function pdu_type:string (type:long) +{ + if (type in pdu_types) + return pdu_types[type] + else + return sprint ("TYPE-",type,"?"); +} + + +/** + * probe pmcd.* - Indicates the type of the pmcd trace + * + * @t_desc: Description of the trace + * @t_type: Type of tracing that occurred + * @t_who: File descriptor + * @t_p1: Trace argument 1 + * @t_p2: Trace argument 2 + */ + + +probe pmcd.add_client = process("@path@").mark("PMCD") +{ + t_desc = "" + + if ($arg1 != TR_ADD_CLIENT) + next + t_desc = sprintf("New client: [%d]", $arg2) +} + + +probe pmcd.del_client = process("@path@").mark("PMCD") +{ + t_desc = "" + + if ($arg1 != TR_DEL_CLIENT) + next + t_desc = sprintf("End client: fd=%d err=%d", $arg2, $arg3) +} + + +probe pmcd.add_agent = process("@path@").mark("PMCD") +{ + t_desc = "" + + if ($arg1 != TR_ADD_AGENT) + next + t_desc = sprintf("Add PMDA: domain=%d ", $arg2) + if ($arg3 == -1 && $arg4 == -1) + t_desc = t_desc . "DSO" + else + t_desc = t_desc . sprintf("infd=%d, outfd=%d", $arg3, $arg4) +} + + +probe pmcd.del_agent = process("@path@").mark("PMCD") +{ + t_desc = "" + + if ($arg1 != TR_DEL_AGENT) + next + + t_desc = sprintf("Drop PMDA: domain=%d ", $arg2) + if ($arg3 == -1 && $arg4 == -1) + t_desc = t_desc . "DSO" + else + t_desc = t_desc . sprintf("infd=%d, outfd=%d", $arg3, $arg4) +} + + +probe pmcd.eof = process("@path@").mark("PMCD") +{ + t_desc = "" + + if ($arg1 != TR_EOF) + next; + + t_desc = sprintf("Premature EOF: expecting %s PDU, fd=%d", pdu_type($arg3), $arg2) +} + + +probe pmcd.wrong_pdu = process("@path@").mark("PMCD") +{ + t_desc = "" + + if ($arg1 != TR_WRONG_PDU) + next + + t_desc = sprintf("Wrong PDU type: expecting %s PDU, fd=%d, ", pdu_type($arg3), $arg2) + if ($arg3 > 0) + t_desc = t_desc . sprintf("got %s PDU", pdu_type($arg4)) + else if ($arg3 == 0) + t_desc = t_desc . "got EOF" + else + t_desc = t_desc . sprintf("got err=%d", $arg4) +} + + +probe pmcd.xmit_err = process("@path@").mark("PMCD") +{ + t_desc = "" + + if ($arg1 != TR_XMIT_ERR) + next + + t_desc = sprintf("Send %s PDU failed: fd=%d, err=%d", pdu_type($arg3), $arg2, $arg4) +} + + +probe pmcd.recv_timeout = process("@path@").mark("PMCD") +{ + t_desc = "" + + if ($arg1 != TR_RECV_TIMEOUT) + next + + t_desc = sprintf("Recv timeout: expecting %s PDU, fd=%d", pdu_type($arg3), $arg2) +} + + +probe pmcd.recv_err = process("@path@").mark("PMCD") +{ + t_desc = "" + + if ($arg1 != TR_RECV_ERR) + next; + + t_desc = sprintf("Recv error: expecting %s PDU, fd=%d, err=%d", pdu_type($arg3), $arg2, $arg4) +} + + +probe pmcd.pdu.xmit = process("@path@").mark("PMCD_PDU") +{ + t_desc = "" + + if ($arg1 != TR_XMIT_PDU) + next + + t_desc = sprintf("Xmit: %s PDU, fd=%d, ", pdu_type($arg3), $arg2) + if ($arg3 == PDU_ERROR) + t_desc = t_desc . sprintf(" err=%d", $arg4) + else if ($arg3 == PDU_RESULT) + t_desc = t_desc . sprintf("numpmid=%d", $arg4) + else if ($arg3 == PDU_TEXT || $arg3 == PDU_TEXT_REQ) + t_desc = t_desc . sprintf("id=%#lx", $arg4) + else if ($arg3 == PDU_DESC || $arg3 == PDU_DESC_REQ) + { + domain = bitextract ($arg4, pmid_domain[0],pmid_domain[1]) + cluster = bitextract ($arg4, pmid_cluster[0],pmid_cluster[1]) + item = bitextract ($arg4, pmid_item[0],pmid_item[1]) + if ($arg4 == PM_ID_NULL) + t_desc = t_desc . sprintf("pmid=PM_ID_NULL") + else if (domain == DYNAMIC_PMID && item == 0) + t_desc = t_desc . sprintf("pmid=%d.*.*", $arg4) + else + t_desc = t_desc . sprintf("pmid=%d.%d.%d", domain, cluster, item) + } + else if ($arg3 == PDU_INSTANCE_REQ || $arg3 == PDU_INSTANCE) + { + domain = bitextract ($arg4, pmindom_domain[0],pmindom_domain[1]) + serial = bitextract ($arg4, pmindom_serial[0],pmindom_serial[1]) + if ($arg4 == PM_INDOM_NULL) + t_desc = t_desc . sprintf("pmid=PM_INDOM_NULL") + else + t_desc = t_desc . sprintf("indom=%d.%d", domain, serial) + } + else if ($arg2 == PDU_PMNS_NAMES) + t_desc = t_desc . sprintf("numpmid=%d", $arg4) + else if ($arg2 == PDU_PMNS_IDS) + t_desc = t_desc . sprintf("numpmid=%d", $arg4) + else if ($arg2 == PDU_CREDS) + t_desc = t_desc . sprintf("numcreds=%d", $arg4) +} + + +probe pmcd.pdu.recv = process("@path@").mark("PMCD_PDU") +{ + t_desc = "" + + if ($arg1 != TR_RECV_PDU) + next; + + t_desc = sprintf("Recv: %s PDU, fd=%d, pdubuf=%#x", pdu_type($arg3), $arg2, $arg4) +} + + +// Example Use +# probe pmcd.* +# { +# println(t_desc) +# } + +# probe pmcd.pdu.* +# { +# println(t_desc) +# } diff --git a/src/libpcp_pmcd/src/probes.d b/src/libpcp_pmcd/src/probes.d new file mode 100644 index 0000000..97bdae8 --- /dev/null +++ b/src/libpcp_pmcd/src/probes.d @@ -0,0 +1,4 @@ +provider pcp_probe { + probe PMCD_PDU(int, int, int, int); + probe PMCD(int, int, int, int); +}; diff --git a/src/libpcp_pmcd/src/trace.c b/src/libpcp_pmcd/src/trace.c new file mode 100644 index 0000000..ed0ebaf --- /dev/null +++ b/src/libpcp_pmcd/src/trace.c @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2013 Red Hat. + * Copyright (c) 1995-2000,2003 Silicon Graphics, Inc. All Rights Reserved. + * + * 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 <time.h> +#include "pmcd.h" +#include "config.h" +#if HAVE_STATIC_PROBES +#include "probes.h" +#else +#define PCP_PROBE_PMCD_PDU(type,who,p1,p2) +#define PCP_PROBE_PMCD(type,who,p1,p2) +#endif + +/* + * Diagnostic event tracing support + */ + +typedef struct { + time_t t_stamp; /* timestamp */ + int t_type; /* event type */ + int t_who; /* originator or principal identifier */ + int t_p1; /* optional event parameters */ + int t_p2; +} tracebuf; + +static tracebuf *trace; +static unsigned int next; + +/* + * by default, circular buffer last 20 events -- change by modify + * pmcd.control.tracebufs + * by default, tracing is disabled -- change by setting the following + * to 1, pmcd.control.traceconn (trace connections) and/or + * pmcd.control.tracepdu (trace PDUs) + */ +PMCD_INTERN int _pmcd_trace_nbufs = 20; +PMCD_INTERN int _pmcd_trace_mask; + +void +pmcd_init_trace(int n) +{ + if (trace != NULL) + free(trace); + if ((trace = (tracebuf *)malloc(n * sizeof(tracebuf))) == NULL) { + __pmNoMem("pmcd_init_trace", n * sizeof(tracebuf), PM_RECOV_ERR); + return; + } + _pmcd_trace_nbufs = n; + next = 0; +} + +void +pmcd_trace(int type, int who, int p1, int p2) +{ + int p; + + switch (type) { + case TR_XMIT_PDU: + case TR_RECV_PDU: + PCP_PROBE_PMCD_PDU(type, who, p1, p2); + if ((_pmcd_trace_mask & TR_MASK_PDU) == 0) + return; + break; + default: + PCP_PROBE_PMCD(type, who, p1, p2); + if ((_pmcd_trace_mask & TR_MASK_CONN) == 0) + return; + break; + } + + if (trace == NULL) { + pmcd_init_trace(_pmcd_trace_nbufs); + if (trace == NULL) + return; + } + + p = (next++) % _pmcd_trace_nbufs; + + time(&trace[p].t_stamp); + trace[p].t_type = type; + trace[p].t_who = who; + trace[p].t_p1 = p1; + trace[p].t_p2 = p2; + + if (_pmcd_trace_mask & TR_MASK_NOBUF) + /* unbuffered, dump it now */ + pmcd_dump_trace(stderr); +} + +void +pmcd_dump_trace(FILE *f) +{ + int i; + int p; + struct tm last = { 0, 0 }; + struct tm *this; + char strbuf[20]; + + if ((_pmcd_trace_mask & TR_MASK_NOBUF) == 0) + fprintf(f, "\n->PMCD event trace: "); + if (trace != NULL && next != 0) { + if (next < _pmcd_trace_nbufs) + i = 0; + else + i = next - _pmcd_trace_nbufs; + if ((_pmcd_trace_mask & TR_MASK_NOBUF) == 0) { + fprintf(f, "starting at %s", ctime(&trace[i % _pmcd_trace_nbufs].t_stamp)); + last.tm_hour = -1; + } + else + last.tm_hour = -2; + + for ( ; i < next; i++) { + fprintf(f, "->"); + p = i % _pmcd_trace_nbufs; + this = localtime(&trace[p].t_stamp); + if (this->tm_hour != last.tm_hour || + this->tm_min != last.tm_min || + this->tm_sec != last.tm_sec) { + if (last.tm_hour == -1) + fprintf(f, " "); + else + fprintf(f, "%02d:%02d:%02d ", this->tm_hour, this->tm_min, this->tm_sec); + last = *this; /* struct assignment */ + } + else + fprintf(f, " "); + + switch (trace[p].t_type) { + + case TR_ADD_CLIENT: + { + ClientInfo *cip; + + fprintf(f, "New client: [%d] ", trace[p].t_who); + cip = GetClient(trace[p].t_who); + if (cip == NULL) { + fprintf(f, "-- unknown?\n"); + } + else { + __pmSockAddr *saddr = (__pmSockAddr *)cip->addr; + char *addrbuf; + + addrbuf = __pmSockAddrToString(saddr); + if (addrbuf == NULL) + fprintf(f, "invalid socket address"); + else { + fprintf(f, "addr=%s", addrbuf); + free(addrbuf); + } + fprintf(f, ", fd=%d, seq=%u\n", cip->fd, cip->seq); + } + } + break; + + case TR_DEL_CLIENT: + fprintf(f, "End client: fd=%d", trace[p].t_who); + if (trace[p].t_p1 != 0) + fprintf(f, ", err=%d: %s", trace[p].t_p1, pmErrStr(trace[p].t_p1)); + fputc('\n', f); + break; + + case TR_ADD_AGENT: + fprintf(f, "Add PMDA: domain=%d, ", trace[p].t_who); + if (trace[p].t_p1 == -1 && trace[p].t_p2 == -1) + fprintf(f, "DSO\n"); + else + fprintf(f, "infd=%d, outfd=%d\n", trace[p].t_p1, trace[p].t_p2); + break; + + case TR_DEL_AGENT: + fprintf(f, "Drop PMDA: domain=%d, ", trace[p].t_who); + if (trace[p].t_p1 == -1 && trace[p].t_p2 == -1) + fprintf(f, "DSO\n"); + else + fprintf(f, "infd=%d, outfd=%d\n", trace[p].t_p1, trace[p].t_p2); + break; + + case TR_EOF: + fprintf(f, "Premature EOF: expecting %s PDU, fd=%d\n", + trace[p].t_p1 == -1 ? "NO" : __pmPDUTypeStr_r(trace[p].t_p1, strbuf, sizeof(strbuf)), + trace[p].t_who); + break; + + case TR_WRONG_PDU: + if (trace[p].t_p2 > 0) { + fprintf(f, "Wrong PDU type: expecting %s PDU, fd=%d, got %s PDU\n", + trace[p].t_p1 == -1 ? "NO" : __pmPDUTypeStr_r(trace[p].t_p1, strbuf, sizeof(strbuf)), + trace[p].t_who, + trace[p].t_p2 == -1 ? "NO" : __pmPDUTypeStr_r(trace[p].t_p2, strbuf, sizeof(strbuf))); + } + else if (trace[p].t_p2 == 0) { + fprintf(f, "Wrong PDU type: expecting %s PDU, fd=%d, got EOF\n", + trace[p].t_p1 == -1 ? "NO" : __pmPDUTypeStr_r(trace[p].t_p1, strbuf, sizeof(strbuf)), + trace[p].t_who); + } + else { + fprintf(f, "Wrong PDU type: expecting %s PDU, fd=%d, got err=%d: %s\n", + trace[p].t_p1 == -1 ? "NO" : __pmPDUTypeStr_r(trace[p].t_p1, strbuf, sizeof(strbuf)), + trace[p].t_who, + trace[p].t_p2, pmErrStr(trace[p].t_p2)); + + } + break; + + case TR_XMIT_ERR: + fprintf(f, "Send %s PDU failed: fd=%d, err=%d: %s\n", + __pmPDUTypeStr_r(trace[p].t_p1, strbuf, sizeof(strbuf)), trace[p].t_who, + trace[p].t_p2, pmErrStr(trace[p].t_p2)); + break; + + case TR_RECV_TIMEOUT: + fprintf(f, "Recv timeout: expecting %s PDU, fd=%d\n", + __pmPDUTypeStr_r(trace[p].t_p1, strbuf, sizeof(strbuf)), trace[p].t_who); + break; + + case TR_RECV_ERR: + fprintf(f, "Recv error: expecting %s PDU, fd=%d, err=%d: %s\n", + __pmPDUTypeStr_r(trace[p].t_p1, strbuf, sizeof(strbuf)), trace[p].t_who, + trace[p].t_p2, pmErrStr(trace[p].t_p2)); + break; + + case TR_XMIT_PDU: + fprintf(f, "Xmit: %s PDU, fd=%d", + __pmPDUTypeStr_r(trace[p].t_p1, strbuf, sizeof(strbuf)), trace[p].t_who); + if (trace[p].t_p1 == PDU_ERROR) + fprintf(f, ", err=%d: %s", + trace[p].t_p2, pmErrStr(trace[p].t_p2)); + else if (trace[p].t_p1 == PDU_RESULT) + fprintf(f, ", numpmid=%d", trace[p].t_p2); + else if (trace[p].t_p1 == PDU_TEXT_REQ || + trace[p].t_p1 == PDU_TEXT) + fprintf(f, ", id=0x%x", trace[p].t_p2); + else if (trace[p].t_p1 == PDU_DESC_REQ || + trace[p].t_p1 == PDU_DESC) + fprintf(f, ", pmid=%s", pmIDStr_r((pmID)trace[p].t_p2, strbuf, sizeof(strbuf))); + else if (trace[p].t_p1 == PDU_INSTANCE_REQ || + trace[p].t_p1 == PDU_INSTANCE) + fprintf(f, ", indom=%s", pmInDomStr_r((pmInDom)trace[p].t_p2, strbuf, sizeof(strbuf))); + else if (trace[p].t_p1 == PDU_PMNS_NAMES) + fprintf(f, ", numpmid=%d", trace[p].t_p2); + else if (trace[p].t_p1 == PDU_PMNS_IDS) + fprintf(f, ", numpmid=%d", trace[p].t_p2); + else if (trace[p].t_p1 == PDU_CREDS) + fprintf(f, ", numcreds=%d", trace[p].t_p2); + fputc('\n', f); + break; + + case TR_RECV_PDU: + fprintf(f, "Recv: %s PDU, fd=%d, pdubuf=0x", + __pmPDUTypeStr_r(trace[p].t_p1, strbuf, sizeof(strbuf)), trace[p].t_who); + /* This will only work if sizeof (int) == sizeof (ptr). + * On MIPS int is always 32 bits regardless the ABI, + * and on Linux we're checking in configure if an int is + * anything else but 32 bits, so if pointer is not + * 32 bit, then .... */ +#ifndef HAVE_32BIT_PTR + fprintf(f, "..."); +#endif + fprintf(f, "%x\n", trace[p].t_p2); + break; + + default: + fprintf(f, "Type=%d who=%d p1=%d p2=%d\n", + trace[p].t_type, trace[p].t_who, trace[p].t_p1, + trace[p].t_p2); + break; + } + } + } + else + fprintf(f, "<empty>\n"); + + if ((_pmcd_trace_mask & TR_MASK_NOBUF) == 0) + fputc('\n', f); + next = 0; /* empty the circular buffer */ +} |