Hi, Stan -
scox wrote:
> [...]
v2 looks pretty good. Some suggestions:
> [...]
> --- a/src/libpcp_pmcd/src/trace.c
> +++ b/src/libpcp_pmcd/src/trace.c
> @@ -17,6 +17,12 @@
> */
>
> #include "pmcd.h"
> +#include "config.h"
> +#if ENABLE_DTRACE
> +#include "probes.h"
> +#else
> +#include "probes_nodtrace.h"
> +#endif
Instead of a separate probes_nodtrace.h file, how about just
adding the
#define PROBE_PMCD(a,b,c,d)
inline instead?
> [...]
> diff --git a/dev/null b/src/pmcd/src/pmcd.stp
> --- /dev/null 2013-07-18 08:12:04.174028131 -0400
> +++ ../pmcd.stp 2013-08-21 16:21:37.179388001 -0400
It's not clear what this script wants to be. If a single-purpose
end-user script, no problem. If something for the
/usr/share/systemtap/tapset, then it needs to be split into reusable
library bits and a sample 'probe pmcd.* { trace stuff }' script.
> @@ -0,0 +1,214 @@
> +%{
> + /* From impl.h */
> +typedef struct {
> +#ifdef HAVE_BITFIELDS_LTOR
> + unsigned int flag : 1;
> + unsigned int domain : 9;
> + unsigned int cluster : 12;
> + unsigned int item : 10;
> +#else
> + unsigned int item : 10;
> + unsigned int cluster : 12;
> + unsigned int domain : 9;
> + unsigned int flag : 1;
> +#endif
> +
> +} __pmID_int;
> +
> +typedef struct {
> +#ifdef HAVE_BITFIELDS_LTOR
> + int flag : 1;
> + unsigned int domain : 9;
> + unsigned int serial : 22;
> +#else
> + unsigned int serial : 22;
> + unsigned int domain : 9;
> + int flag : 1;
> +#endif
> +} __pmInDom_int;
> +
> +%}
> +
> +
> +# function _pcp_indom_domain:long (sp_offset:long) %{ /* pure */
> +# __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
> +# STAP_RETVALUE = ((long) CONTEXT->kregs) + STAP_ARG_sp_offset;
> +# %}
> +
> +function pmid_item:long (id:long) %{
> + STAP_RETVALUE = ((__pmID_int*)(&STAP_ARG_id))->item;
> +%}
> +
> +function pmid_cluster:long (id:long) %{
> + STAP_RETVALUE = ((__pmID_int*)(&STAP_ARG_id))->cluster;
> +%}
> +
> +function pmid_domain:long (id:long) %{
> + STAP_RETVALUE = ((__pmID_int*)(&STAP_ARG_id))->domain;
> +%}
> +
> +function pmInDom_domain:long (id:long) %{
> + STAP_RETVALUE = ((__pmInDom_int*)(&STAP_ARG_id))->domain;
> +%}
> +
> +function pmInDom_serial:long (id:long) %{
> + STAP_RETVALUE = ((__pmInDom_int*)(&STAP_ARG_id))->serial;
> +%}
(FWIW, instead of inline-c code, could use script level binary
rotate/mask operators here, perhaps with a twist of %( arch = ... %)
conditionalizing for the LTOR vs RTOL kind.
> +function pdu_type:string (type:long)
> +{
> + if (type == PDU_ERROR) res = "ERROR";
> + else if (type == PDU_RESULT) res = "RESULT";
> + else if (type == PDU_PROFILE) res = "PROFILE";
> [...]
> + else if (type == PDU_LOG_REQUEST) res = "LOG_REQUEST";
> + else if (type == PDU_AUTH) res = "AUTH";
> + else if (type == -1) res = "NO";
> + if (res == "")
> + return sprint ("TYPE-",type,"?");
> + else
> + return res
> +}
(Why not a lookup table, initialized in a probe begin?)
> +probe process("/usr/local/libexec/pcp/bin/pmcd").mark("PMCD")
That kind of path specificity and hard-coded action hallmarks an
end-user script rather than a tapset fragment.
> + # Use the same naming scheme as trace.c::tracebuf
> + t_type = $arg1
> + t_who = $arg2
> + t_p1 = $arg3
> + t_p2 = $arg4
> +
> + if (t_type == TR_ADD_CLIENT)
> + printf("New client: [%d]\n", t_who)
> + else if (t_type == TR_DEL_CLIENT)
> + printf("End client: fd=%d err=%d\n", t_who, t_p1)
> + else if (t_type == TR_ADD_AGENT)
> + {
> + printf("Add PMDA: domain=%d ", t_who)
> + if ($arg2 == -1 && $arg3 == -1)
> + printf("DSO\n")
> + else
> + printf("infd=%d, outfd=%d\n", t_p1, t_p2)
> + }
> + else if (t_type == TR_DEL_AGENT)
> + {
> + printf("Drop PMDA: domain=%d ", t_who)
> + if (t_p1 == -1 && t_p2 == -1)
> + printf("DSO\n")
> + else
> + printf("infd=%d, outfd=%d\n", t_p1, t_p2)
> + }
> + else if (t_type == TR_EOF)
> + printf("Premature EOF: expecting %s PDU, fd=%d\n", pdu_type(t_p1), t_who)
> + else if (t_type == TR_WRONG_PDU)
> + {
> + printf("Wrong PDU type: expecting %s PDU, fd=%d, ", pdu_type(t_p1),
> t_who)
> + if ($arg3 > 0)
> + printf("got %s PDU\n", pdu_type(t_p2))
> + else if ($arg3 == 0)
> + printf("got EOF\n")
> + else
> + printf("got err=%d\n", t_p2)
> + }
> + else if (t_type == TR_XMIT_ERR)
> + printf("Send %s PDU failed: fd=%d, err=%d\n", pdu_type(t_p1), t_who,
> t_p2)
> + else if (t_type == TR_RECV_TIMEOUT)
> + printf("Recv timeout: expecting %s PDU, fd=%d\n", pdu_type(t_p1), t_who)
> + else if (t_type == TR_RECV_ERR)
> + printf("Recv error: expecting %s PDU, fd=%d, err=%d", pdu_type(t_p1),
> t_who, t_p2)
> + else if (t_type == TR_XMIT_PDU)
> + {
> + printf("Xmit: %s PDU, fd=%d, ", pdu_type(t_p1), t_who)
> + if (t_p1 == PDU_ERROR)
> + printf(" err=%d", t_p2)
> + else if (t_p1 == PDU_RESULT)
> + printf("numpmid=%d", t_p2)
> + else if (t_p1 == PDU_TEXT || t_p1 == PDU_TEXT_REQ)
> + printf("id=%#lx", t_p2)
> + else if (t_p1 == PDU_DESC || t_p1 == PDU_DESC_REQ)
> + {
> + domain = pmid_domain (t_p2)
> + cluster = pmid_cluster (t_p2)
> + item = pmid_item (t_p2)
> + if (t_p2 == PM_ID_NULL)
> + printf("pmid=PM_ID_NULL")
> + else if (domain == DYNAMIC_PMID && item == 0)
> + printf("pmid=%d.*.*", t_p2)
> + else
> + printf("pmid=%d.%d.%d", domain, cluster, item)
> + }
> + else if (t_p1 == PDU_INSTANCE_REQ || t_p1 == PDU_INSTANCE)
> + {
> + domain = pmInDom_domain (t_p2);
> + serial = pmInDom_serial (t_p2);
> + if (t_p2 == PM_INDOM_NULL)
> + printf("pmid=PM_INDOM_NULL")
> + else
> + printf("indom=%d.%d", domain, serial)
> + }
> + else if (t_who == PDU_PMNS_NAMES)
> + printf("numpmid=%d", t_p2)
> + else if (t_who == PDU_PMNS_IDS)
> + printf("numpmid=%d", t_p2)
> + else if (t_who == PDU_CREDS)
> + printf("numcreds=%d", t_p2)
> + printf("\n")
> + }
> + else if (t_type == TR_RECV_PDU)
> + printf("Recv: %s PDU, fd=%d, pdubuf=%#x\n", pdu_type(t_p1), t_who, t_p2)
> +}
BTW, the logic encoded in these nested ifs could be represented within
a tapset as a family of probe aliases:
probe pmcd.add_client = process("/PATH/to/pmcd").mark("pmcd") {
if ($arg1 != TR_ADD_CLIENT) next;
fd = $arg2
description = sprintf("Add client [%d]", $arg2)
}
probe pmcd.del_client = process("/PATH/to/pmcd").mark("pmcd") {
if ($arg1 != TR_DEL_CLIENT) next;
name = "End client"
fd = $arg2
err = $arg3
argstr = sprintf("fd=%d err=%d", $arg2, $arg3)
}
...etc...
Then a basic end-user script can look thus:
probe pmcd.* { println(name," ",argstr) }
- FChE
|