dtrace_aggregate_walk, dtrace_aggregate_print, dtrace_aggregate_walk_sorted, dtrace_aggregate_walk_keysorted, dtrace_aggregate_walk_valsorted, dtrace_aggregate_walk_keyvarsorted, dtrace_aggregate_walk_valvarsorted, dtrace_aggregate_walk_keyrevsorted, dtrace_aggregate_walk_valrevsorted, dtrace_aggregate_walk_keyvarrevsorted, dtrace_aggregate_walk_valvarrevsorted, dtrace_aggregate_walk_joined - Process aggregation data
cc [ flag... ] file... -ldtrace [ library... ] #include <dtrace.h> typedef int dtrace_aggregate_f(const dtrace_aggdata_t *, void *); typedef int dtrace_aggregate_walk_f(dtrace_hdl_t *, dtrace_aggregate_f *, void *); typedef int dtrace_aggregate_walk_joined_f(const dtrace_aggdata_t **, const int, void *); int dtrace_aggregate_print(dtrace_hdl_t *dtp, FILE *fp, dtrace_aggregate_walk_f *func); int dtrace_aggregate_walk(dtrace_hdl_t *dtp, dtrace_aggregate_f *func, void *arg); int dtrace_aggregate_walk_sorted(dtrace_hdl_t *dtp, dtrace_aggregate_f *func, void *arg); int dtrace_aggregate_walk_keysorted(dtrace_hdl_t *dtp, dtrace_aggregate_f *func, void *arg); int dtrace_aggregate_walk_valsorted(dtrace_hdl_t *dtp, dtrace_aggregate_f *func, void *arg); int dtrace_aggregate_walk_keyvarsorted(dtrace_hdl_t *dtp, dtrace_aggregate_f *func, void *arg); int dtrace_aggregate_walk_valvarsorted(dtrace_hdl_t *dtp, dtrace_aggregate_f *func, void *arg); int dtrace_aggregate_walk_keyrevsorted(dtrace_hdl_t *dtp, dtrace_aggregate_f *func, void *arg); int dtrace_aggregate_walk_valrevsorted(dtrace_hdl_t *dtp, dtrace_aggregate_f *func, void *arg); int dtrace_aggregate_walk_keyvarrevsorted(dtrace_hdl_t *dtp, dtrace_aggregate_f *func, void *arg); int dtrace_aggregate_walk_valvarrevsorted(dtrace_hdl_t *dtp, dtrace_aggregate_f *func, void *arg); int dtrace_aggregate_walk_joined(dtrace_hdl_t *dtp, dtrace_aggvarid_t *aggvars, int naggvars, dtrace_aggregate_walk_joined_f *func, void *arg);
You can use the dtrace_aggregate_print() function to print DTrace aggregate data. The function can be passed a specific walk() function (as those described below). If passed NULL, it defaults to the dtrace_aggregate_walk_sorted() function, and the callback function passed to the walk() function is the default function that the libdtrace library uses to print aggregate data.
You can use the dtrace_aggregate_walk() and dtrace_aggregate_walk_sorted() functions to process aggregate data with sorting functions as described below. For each aggregate buffer, the callback function, func() is called. This callback function can extract and process the keys and value for this entry.
The following section illustrates how you can use the functions to process the aggregate data in a D script. This section consists of a sample D script containing aggregate data, followed by information on how each function would process this data.
BEGIN { @a["bravo"] = sum(3); @b["alpha"] = sum(4); @a["delta"] = sum(1); @b["charlie"] = sum(2); @a["echo"] = sum(6); @b["echo"] = sum(5); exit(0); }Using dtrace_aggregate_walk()to Process Aggregate Data
The dtrace_aggregate_walk() function processes the aggregate data with no sorting. The data remains the same as it appears in the buffer. The order is random. For the sample D script given above, the output of the dtrace_aggregate_walk() function might appear as follows:
echo 5 echo 6 charlie 2 delta 1 alpha 4 bravo 3Using dtrace_aggregate_walk_sorted() to Process Aggregate Data
The dtrace_aggregate_walk_sorted() function processes the aggregate data sorted first by variable name if multiple aggregations are processed. The function then sorts the data within each aggregation by ascending value.
For the D sample script, the dtrace_aggregate_walk_sorted() function sorts the aggregate data by variable first, so @a comes before @b. Note that this is by variable ID, not variable name. IDs are assigned in the order in which the aggregation appears in the script. In this case, @a has aggregation ID 1 and @b has aggregation ID 2.
Entries in aggregation @a, the bravo, delta, and echo values are printed first. Then, within each aggregation, the entries are sorted by value. Thus, in the aggregation, @a, delta comes before bravo, and charlie comes before alpha. The output of the D sample script is as follows:
delta 1 bravo 3 echo 6 charlie 2 alpha 4 echo 5Using dtrace_aggregate_walk_keysorted() to Process Aggregate Data
The dtrace_aggregate_walk_keysorted() function processes the aggregate data sorted first by variable name if there are multiple aggregations. The function then sorts the data within each aggregation by key. For the D sample script, the function sorts @a first. The function then sorts by key, so bravo comes before delta, and alpha comes before charlie. The output of the sample D script is as follows:
bravo 3 delta 1 echo 6 alpha 4 charlie 2 echo 5Using dtrace_aggregate_walk_valsorted() to Process Aggregate Data
The dtrace_aggregate_walk_valsorted() function processes the aggregate data sorted first by variable name if there are multiple aggregations. The function then sorts the data within each aggregation by value, which is the same as the default behavior.
Using dtrace_aggregate_walk_keyvarsorted() to Process Aggregate DataThe dtrace_aggregate_walk_keyvarsorted() function processes the aggregate data sorted first by key. If the same key occurs in two different aggregations, the function then sorts by variable (aggregation ID). Thus, the function prints echo from the aggregate, @a before echo from the aggregate, @b. The output of the sample D script is as follows:
alpha 4 bravo 3 charlie 2 delta 1 echo 6 echo 5Using dtrace_aggregate_walk_valvarsorted() to Process Aggregate Data
The dtrace_aggregate_walk_valvarsorted() function processes the aggregate data sorted first by value and then by variable (i.e., aggregation ID). The output of the sample D script is as follows:
delta 1 charlie 2 bravo 3 alpha 4 echo 5 echo 6Using dtrace_aggregate_walk_keyrevsorted() to Process Aggregate Data
The dtrace_aggregate_walk_keyrevsorted() function sorts the aggregate data in an order reverse to that of the dtrace_aggregate_walk_keysorted() function. Thus, the dtrace_aggregate_walk_keyrevsorted() function first sorts the data in reverse order by variable (aggregation ID) and then in reverse order by key. Thus . The output of the sample D script is as follows:
echo 5 charlie 2 alpha 4 echo 6 delta 1 bravo 3Using dtrace_aggregate_walk_valrevsorted() to Process Aggregate Data
The dtrace_aggregate_walk_valrevsorted() function processes the aggregate data in the reverse order as the dtrace_aggregate_walk_valsorted() function. Thus, the dtrace_aggregate_walk_valrevsorted() function first sorts the data in reverse order by variable (aggregation ID) and then in reverse order by value. The output of the sample D script is as follows:
echo 5 alpha 4 charlie 2 echo 6 bravo 3 delta 1Using dtrace_aggregate_walk_keyvarrevsorted() to Process Aggregate Data
The dtrace_aggregate_walk_keyvarrevsorted() function processes the aggregate data in the reverse order as the dtrace_aggregate_walk_keyvarsorted() function. Thus, the dtrace_aggregate_walk_keyvarrevsorted() function first sorts the data in reverse order by key and then, If the same key occurs in two different aggregations, in reverse order by variable (aggregation ID). The output of the sample D script is as follows:
echo 5 echo 6 delta 1 charlie 2 bravo 3 alpha 4Using dtrace_aggregate_walk_valvarrevsorted() to Process Aggregate Data
The dtrace_aggregate_walk_valvarrevsorted() function processes the aggregate data in the reverse order as the dtrace_aggregate_walk_valvarsorted() function. Thus, the dtrace_aggregate_walk_valvarrevsorted() first sorts the data in reverse order by value and then in reverse order by variable (aggregation ID). The output of the sample D script is as follows:
echo 6 echo 5 alpha 4 bravo 3 charlie 2 delta 1Using dtrace_aggregate_walk_joined() to Process Aggregate Data
The dtrace_aggregate_walk_joined() function allows you to process multiple aggregations at the same time, similar to a database join operation. The callback function, func() is passed an array, aggvars, of aggregation entries to be joined, and the number of elements in that array, naggvars. The aggvars array consists of aggregation entries from the multiple aggregations that have the same key or set of keys.
On successful completion, the functions return 0. On failure, the functions return -1 and set the DTrace error number to indicate the reason for the failure. See the dtrace_errno(3DTRACE) man page for more information.
All the functions will fail if:
The system was unable to allocate memory while processing this function.
The dtrace_aggregate_print() function will fail if:
dtp is NULL.
fp is NULL and there is no buffer handler installed. See the dtrace_handle_buffered(3DTRACE) man page for more information.
The dtrace_aggregate_walk(), dtrace_aggregate_walk_sorted(), dtrace_aggregate_walk_keysorted(), dtrace_aggregate_walk_valsorted(), dtrace_aggregate_walk_keyvarsorted(), dtrace_aggregate_walk_valvarsorted(), dtrace_aggregate_walk_keyrevsorted(), dtrace_aggregate_walk_valrevsorted(), dtrace_aggregate_walk_keyvarrevsorted(), and dtrace_aggregate_walk_valvarrevsorted() functions will fail if:
dtp or func is NULL.
func returned the value, DTRACE_AGGWALK_ABORT while processing an entry in the aggregation buffer. See the Usage section for more information.
func returned the value, DTRACE_AGGWALK_NORMALIZE when the normalization value was 0. See the Usage section for more information.
func returned an invalid value. An invalid value is a value that is not one of the DTRACE_AGGWALK_* constants mentioned in the Usage section.
The dtrace_aggregate_walk_joined() function will fail if:
dtp, aggvars or func is NULL, or naggvars < 0.
The callback function, passed to dtrace_aggregate_walk() and other functions, is used to process a single aggregation record. The data in the aggregation is described by the dtrace_aggdata_t argument to the callback. The dtrace_aggdata_t structure is defined as follows:
struct dtrace_aggdata { dtrace_hdl_t *dtada_handle; /* handle to DTrace library */ dtrace_aggdesc_t *dtada_desc; /* aggregation description */ dtrace_eprobedesc_t *dtada_edesc; /* enabled probe description */ dtrace_probedesc_t *dtada_pdesc; /* probe description */ caddr_t dtada_data; /* pointer to raw data */ uint64_t dtada_normal; /* the normal -- 1 for denorm */ size_t dtada_size; /* total size of the data */ caddr_t dtada_delta; /* delta data, if available */ caddr_t *dtada_percpu; /* per CPU data, if avail */ caddr_t *dtada_percpu_delta; /* per CPU delta, if avail */ };
The dtada_data member of this structure references the raw data for the aggregation record. The dtada_desc member contains the description for the aggregation record. The type of this member, dtrace_aggdesc_t, is defined as follows:
typedef struct dtrace_aggdesc { DTRACE_PTR(char, dtagd_name); /* not filled in by kernel */ dtrace_aggvarid_t dtagd_varid; /* not filled in by kernel */ int dtagd_flags; /* not filled in by kernel */ dtrace_aggid_t dtagd_id; /* aggregation ID */ dtrace_epid_t dtagd_epid; /* enabled probe ID */ uint32_t dtagd_size; /* size in bytes */ int dtagd_nrecs; /* number of records */ uint32_t dtagd_pad; /* explicit padding */ dtrace_recdesc_t dtagd_rec[1]; /* record descriptions */ } dtrace_aggdesc_t;
The dtagd_nrecs member of this structure stores the number of individual records associated with this aggregation record. The dtagd_rec array stores the individual records, which represent, the keys and the value, in that order, for the aggregation record. The members of the dtagd_rec array are of the dtrace_recdesc_t type, defined as follows:
typedef struct dtrace_recdesc { dtrace_actkind_t dtrd_action; /* kind of action */ uint32_t dtrd_size; /* size of record */ uint32_t dtrd_offset; /* offset in ECB's data */ uint16_t dtrd_alignment; /* required alignment */ uint16_t dtrd_format; /* format, if any */ uint64_t dtrd_arg; /* action argument */ uint64_t dtrd_uarg; /* user argument */ } dtrace_recdesc_t;
For example, the following code shows how to extract a pointer to a particular record and the size of that record:
void *record; size_t size; record = aggdata->dtada_data + aggdesc->dtagd_rec[index].dtrd_offset; size = aggdesc->dtagd_rec[index].dtrd_size;
The callback function passed to dtrace_aggregate_walk() and other functions is expected to return one of the following set of values:
DTRACE_AGGWALK_ERROR DTRACE_AGGWALK_NEXT DTRACE_AGGWALK_ABORT DTRACE_AGGWALK_CLEAR DTRACE_AGGWALK_NORMALIZE DTRACE_AGGWALK_DENORMALIZE DTRACE_AGGWALK_REMOVE
These values are documented in the /usr/include/dtrace.h ?.
The following example demonstrates the use of the dtrace_aggregate_walk() function to process the data from a simple DTrace script:
#include <dtrace.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> static dtrace_hdl_t *g_dtp; char *g_prog = "" "syscall:::entry" "{" " @[probefunc] = count();" "}" "tick-1s" "{" " exit(0);" "}" ""; static void fatal(const char *fmt, ...) { va_list ap; va_start(ap, fmt); (void) vfprintf(stderr, fmt, ap); if (fmt[strlen(fmt) - 1] != '\n') (void) fprintf(stderr, ": %s\n", dtrace_errmsg(g_dtp, dtrace_errno(g_dtp))); exit(EXIT_FAILURE); } static int walk(const dtrace_aggdata_t *aggdata, void *arg) { dtrace_aggdesc_t *aggdesc; char *key; uint64_t value; if (aggdata == NULL) fatal("No aggdata\n"); if ((aggdesc = aggdata->dtada_desc) == NULL) fatal("No aggdesc\n"); key = dtrace_extract_aggregate_string(aggdata, aggdesc, 1); value = dtrace_extract_aggregate_value(aggdata, aggdesc, 2); printf("%s\t%llu\n", key, value); return (DTRACE_AGGWALK_NEXT); } static int chewrec(const dtrace_probedata_t *data, const dtrace_recdesc_t *rec, void *arg) { dtrace_actkind_t act; if (rec == NULL) return (DTRACE_CONSUME_NEXT); act = rec->dtrd_action; if (act == DTRACEACT_EXIT) return (DTRACE_CONSUME_NEXT); return (DTRACE_CONSUME_NEXT); } static int chew(const dtrace_probedata_t *data, void *arg) { return (DTRACE_CONSUME_THIS); } int main() { dtrace_prog_t *prog; dtrace_proginfo_t info; int err; if ((g_dtp = dtrace_open(DTRACE_VERSION, 0, &err)) == NULL) fatal("cannot open dtrace library: %s\n", dtrace_errmsg(NULL, err)); if ((prog = dtrace_program_strcompile(g_dtp, g_prog, DTRACE_PROBESPEC_NAME, 0, 0, NULL)) == NULL) fatal("invalid program"); if (dtrace_program_exec(g_dtp, prog, &info) == -1) fatal("failed to enable probes"); if (dtrace_setopt(g_dtp, "bufsize", "512k") == -1) fatal("failed to set bufsize"); if (dtrace_setopt(g_dtp, "aggsize", "512k") == -1) fatal("failed to set aggsize"); if (dtrace_go(g_dtp) != 0) fatal("dtrace_go()"); while (1) { int done = 0; dtrace_sleep(g_dtp); switch (dtrace_work(g_dtp, stdout, chew, chewrec, NULL)) { case DTRACE_WORKSTATUS_DONE: done = 1; break; case DTRACE_WORKSTATUS_OKAY: break; default: fatal("processing aborted"); } if (done) break; } if (dtrace_aggregate_walk(g_dtp, walk, NULL) != 0) fatal("dtrace_aggregate_walk failed"); printf("\n"); if (dtrace_stop(g_dtp) == -1) fatal("dtrace_stop()"); dtrace_close(g_dtp); return (0); }
See attributes(7) for descriptions of the following attributes:
|
libdtrace(3LIB), dtrace_errno(3DTRACE), dtrace_aggregate_clear(3DTRACE), dtrace_aggregate_snap(3DTRACE)