ruby-dtrace 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +9 -0
- data/Manifest.txt +11 -1
- data/README.txt +10 -11
- data/examples/scsi.rb +442 -0
- data/ext/dtrace_aggdata.c +4 -1
- data/ext/dtrace_api.c +18 -7
- data/ext/dtrace_api.h +48 -9
- data/ext/dtrace_bufdata.c +52 -4
- data/ext/dtrace_hdl.c +137 -86
- data/ext/dtrace_probedata.c +188 -50
- data/ext/dtrace_process.c +37 -0
- data/ext/dtrace_recdesc.c +31 -0
- data/lib/dtrace.rb +53 -1
- data/lib/dtraceaggregate.rb +25 -1
- data/lib/dtraceaggregateset.rb +17 -0
- data/lib/dtraceconsumer.rb +91 -67
- data/lib/dtracedata.rb +73 -0
- data/lib/dtraceprintfrecord.rb +8 -0
- data/lib/dtraceprobedata.rb +5 -0
- data/lib/dtracerecord.rb +2 -1
- data/lib/dtracestackrecord.rb +29 -0
- data/plugin/dtrace/lib/dtracer.rb +42 -2
- data/plugin/dtrace/views/dtrace/_report.rhtml +48 -3
- data/test/test_dtrace.rb +2 -0
- data/test/test_dtrace_aggregates.rb +56 -0
- data/test/test_dtrace_processes.rb +83 -0
- data/test/test_dtrace_profile.rb +232 -0
- data/test/test_dtrace_repeat.rb +51 -0
- data/test/test_dtrace_rubyprobe.rb +52 -0
- metadata +19 -5
- data/test/test_dtrace_workapi.rb +0 -142
data/ext/dtrace_aggdata.c
CHANGED
@@ -15,7 +15,8 @@ VALUE dtraceaggdata_init(VALUE self)
|
|
15
15
|
return self;
|
16
16
|
}
|
17
17
|
|
18
|
-
|
18
|
+
/* Returns the value of this aggregate, be it the aggregation value,
|
19
|
+
or a member of an aggregation key tuple. */
|
19
20
|
VALUE dtraceaggdata_value(VALUE self)
|
20
21
|
{
|
21
22
|
dtrace_bufdata_t *bufdata;
|
@@ -118,6 +119,8 @@ VALUE dtraceaggdata_value(VALUE self)
|
|
118
119
|
return v;
|
119
120
|
}
|
120
121
|
|
122
|
+
/* Return the type of this DtraceAggData: tuple, value or last. Used
|
123
|
+
to form tuples and values into DtraceAggregate objects. */
|
121
124
|
VALUE dtraceaggdata_aggtype(VALUE self)
|
122
125
|
{
|
123
126
|
dtrace_bufdata_t *bufdata;
|
data/ext/dtrace_api.c
CHANGED
@@ -12,6 +12,7 @@ VALUE cDtraceAggData;
|
|
12
12
|
VALUE cDtraceRecDesc;
|
13
13
|
VALUE cDtraceProbeData;
|
14
14
|
VALUE cDtraceBufData;
|
15
|
+
VALUE cDtraceProcess;
|
15
16
|
|
16
17
|
VALUE eDtraceException;
|
17
18
|
|
@@ -24,17 +25,19 @@ void Init_dtrace_api() {
|
|
24
25
|
rb_define_method(cDtrace, "stop", dtrace_hdl_stop, 0); // in dtrace_hdl.c
|
25
26
|
rb_define_method(cDtrace, "status", dtrace_hdl_status, 0); // in dtrace_hdl.c
|
26
27
|
rb_define_method(cDtrace, "go", dtrace_hdl_go, 0); // in dtrace_hdl.c
|
27
|
-
rb_define_method(cDtrace, "each_aggregate", dtrace_hdl_each_aggregate, 0); // in dtrace_hdl.c
|
28
|
-
rb_define_method(cDtrace, "aggregate_print", dtrace_hdl_aggregate_print, 0); // in dtrace_hdl.c
|
29
|
-
rb_define_method(cDtrace, "aggregate_snap", dtrace_hdl_aggregate_snap, 0); // in dtrace_hdl.c
|
30
|
-
rb_define_method(cDtrace, "aggregate_clear", dtrace_hdl_aggregate_clear, 0); // in dtrace_hdl.c
|
31
28
|
rb_define_method(cDtrace, "error", dtrace_hdl_error, 0); // in dtrace_hdl.c
|
32
29
|
rb_define_method(cDtrace, "setopt", dtrace_hdl_setopt, 2); // in dtrace_hdl.c
|
33
30
|
rb_define_method(cDtrace, "sleep", dtrace_hdl_sleep, 0); // in dtrace_hdl.c
|
34
|
-
rb_define_method(cDtrace, "work", dtrace_hdl_work,
|
31
|
+
rb_define_method(cDtrace, "work", dtrace_hdl_work, -1); // in dtrace_hdl.c
|
35
32
|
rb_define_method(cDtrace, "buf_consumer", dtrace_hdl_buf_consumer, 1); // in dtrace_hdl.c
|
33
|
+
rb_define_method(cDtrace, "createprocess", dtrace_hdl_createprocess, 1); // in dtrace_hdl.c
|
34
|
+
rb_define_method(cDtrace, "grabprocess", dtrace_hdl_grabprocess, 1); // in dtrace_hdl.c
|
36
35
|
rb_define_alloc_func(cDtrace, dtrace_hdl_alloc);
|
37
36
|
|
37
|
+
cDtraceProcess = rb_define_class("DtraceProcess", rb_cObject);
|
38
|
+
rb_define_method(cDtraceProcess, "initialize", dtrace_process_init, 0); // in dtrace_process.c
|
39
|
+
rb_define_method(cDtraceProcess, "continue", dtrace_process_continue, 0); // in dtrace_process.c
|
40
|
+
|
38
41
|
cDtraceProbe = rb_define_class("DtraceProbe", rb_cObject);
|
39
42
|
rb_define_method(cDtraceProbe, "initialize", dtraceprobe_init, 0); // in dtrace_probe.c
|
40
43
|
rb_define_method(cDtraceProbe, "probe_id", dtraceprobe_probe_id, 0); // in dtrace_probe.c
|
@@ -45,11 +48,18 @@ void Init_dtrace_api() {
|
|
45
48
|
|
46
49
|
cDtraceProbeData = rb_define_class("DtraceProbeData", rb_cObject);
|
47
50
|
rb_define_method(cDtraceProbeData, "initialize", dtraceprobedata_init, 0); // in dtrace_probedata.c
|
48
|
-
rb_define_method(cDtraceProbeData, "
|
51
|
+
rb_define_method(cDtraceProbeData, "epid", dtraceprobedata_epid, 0); // in dtrace_probedata.c
|
52
|
+
rb_define_method(cDtraceProbeData, "probe", dtraceprobedata_probe, 0); // in dtrace_probedata.c
|
53
|
+
rb_define_method(cDtraceProbeData, "cpu", dtraceprobedata_cpu, 0); // in dtrace_probedata.c
|
54
|
+
rb_define_method(cDtraceProbeData, "indent", dtraceprobedata_indent, 0); // in dtrace_probedata.c
|
55
|
+
rb_define_method(cDtraceProbeData, "prefix", dtraceprobedata_prefix, 0); // in dtrace_probedata.c
|
56
|
+
rb_define_method(cDtraceProbeData, "flow", dtraceprobedata_flow, 0); // in dtrace_probedata.c
|
49
57
|
rb_define_method(cDtraceProbeData, "each_record", dtraceprobedata_each_record, 0); // in dtrace_probedata.c
|
50
58
|
|
51
59
|
cDtraceBufData = rb_define_class("DtraceBufData", rb_cObject);
|
52
60
|
rb_define_method(cDtraceBufData, "initialize", dtracebufdata_init, 0); // in dtrace_bufdata.c
|
61
|
+
rb_define_method(cDtraceBufData, "epid", dtracebufdata_epid, 0); // in dtrace_bufdata.c
|
62
|
+
rb_define_method(cDtraceBufData, "probe", dtracebufdata_probe, 0); // in dtrace_bufdata.c
|
53
63
|
rb_define_method(cDtraceBufData, "record", dtracebufdata_record, 0); // in dtrace_bufdata.c
|
54
64
|
|
55
65
|
cDtraceProgram = rb_define_class("DtraceProgram", rb_cObject);
|
@@ -70,7 +80,8 @@ void Init_dtrace_api() {
|
|
70
80
|
rb_define_method(cDtraceAggData, "aggtype", dtraceaggdata_aggtype, 0); // in dtrace_aggdata.c
|
71
81
|
|
72
82
|
cDtraceRecDesc = rb_define_class("DtraceRecDesc", rb_cObject);
|
73
|
-
rb_define_method(cDtraceRecDesc, "initialize", dtracerecdesc_init,
|
83
|
+
rb_define_method(cDtraceRecDesc, "initialize", dtracerecdesc_init, 0); // in dtrace_recdesc.c
|
84
|
+
rb_define_method(cDtraceRecDesc, "action", dtracerecdesc_action, 0); // in dtrace_recdesc.c
|
74
85
|
|
75
86
|
eDtraceException = rb_define_class("DtraceException", rb_eStandardError);
|
76
87
|
}
|
data/ext/dtrace_api.h
CHANGED
@@ -8,31 +8,62 @@
|
|
8
8
|
#include "/usr/include/dtrace.h"
|
9
9
|
#include "ruby.h"
|
10
10
|
|
11
|
+
/* Used to pass three Ruby VALUEs as the void *arg of dtrace_work() to
|
12
|
+
its callbacks: the dtrace handle, a Proc for the probe callback,
|
13
|
+
and a Proc for the recdesc callback. */
|
14
|
+
typedef struct dtrace_work_handlers {
|
15
|
+
VALUE handle;
|
16
|
+
VALUE probe;
|
17
|
+
VALUE rec;
|
18
|
+
} dtrace_work_handlers_t;
|
19
|
+
|
20
|
+
/* Used to keep a reference to a struct ps_prochandle and a reference
|
21
|
+
to the DTrace handle in a DtraceProcess object: we need to be able
|
22
|
+
to call dtrace_proc_release() when the DtraceProcess goes away, and
|
23
|
+
that requires the DTrace handle. */
|
24
|
+
typedef struct dtrace_process {
|
25
|
+
dtrace_hdl_t *handle;
|
26
|
+
struct ps_prochandle *proc;
|
27
|
+
} dtrace_process_t;
|
28
|
+
|
29
|
+
/* Handle missing RARRAY_LEN etc */
|
30
|
+
#ifdef RARRAY_LEN
|
31
|
+
static inline long rb_str_len(VALUE s) {return RSTRING_LEN(s);}
|
32
|
+
static inline char *rb_str_ptr(VALUE s) {return RSTRING_PTR(s);}
|
33
|
+
static inline long rb_ary_len(VALUE s) {return RARRAY_LEN(s);}
|
34
|
+
static inline VALUE *rb_ary_ptr(VALUE s) {return RARRAY_PTR(s);}
|
35
|
+
#else
|
36
|
+
static inline long rb_str_len(VALUE s) {return RSTRING(s)->len;}
|
37
|
+
static inline char *rb_str_ptr(VALUE s) {return RSTRING(s)->ptr;}
|
38
|
+
static inline long rb_ary_len(VALUE s) {return RARRAY(s)->len;}
|
39
|
+
static inline VALUE *rb_ary_ptr(VALUE s) {return RARRAY(s)->ptr;}
|
40
|
+
#endif // RARRAY_LEN
|
41
|
+
|
11
42
|
VALUE handle_bytedata(caddr_t addr, uint32_t nbytes);
|
12
43
|
|
44
|
+
VALUE dtrace_process_init(VALUE self);
|
45
|
+
void dtrace_process_release(dtrace_process_t *process);
|
46
|
+
VALUE dtrace_process_continue(VALUE self);
|
47
|
+
|
13
48
|
VALUE dtraceaggdata_init(VALUE self);
|
14
49
|
VALUE dtraceaggdata_value(VALUE self);
|
15
50
|
VALUE dtraceaggdata_aggtype(VALUE self);
|
16
51
|
|
17
52
|
void dtrace_hdl_free (void *handle);
|
18
|
-
VALUE dtrace_hdl_alloc(VALUE klass);
|
19
53
|
VALUE dtrace_init(VALUE self);
|
54
|
+
VALUE dtrace_hdl_alloc(VALUE klass);
|
20
55
|
VALUE dtrace_each_probe(VALUE self);
|
21
56
|
VALUE dtrace_strcompile(int argc, VALUE *argv, VALUE self);
|
22
57
|
VALUE dtrace_hdl_go(VALUE self);
|
23
58
|
VALUE dtrace_hdl_status(VALUE self);
|
24
59
|
VALUE dtrace_hdl_setopt(VALUE self, VALUE key, VALUE value);
|
25
60
|
VALUE dtrace_hdl_stop(VALUE self);
|
26
|
-
VALUE dtrace_hdl_each_aggregate(VALUE self);
|
27
|
-
VALUE dtrace_hdl_aggregate_print(VALUE self);
|
28
|
-
VALUE dtrace_hdl_aggregate_snap(VALUE self);
|
29
|
-
VALUE dtrace_hdl_aggregate_clear(VALUE self);
|
30
61
|
VALUE dtrace_hdl_error(VALUE self);
|
31
62
|
VALUE dtrace_hdl_sleep(VALUE self);
|
32
|
-
VALUE dtrace_hdl_work(VALUE
|
33
|
-
VALUE probe_consumer_proc,
|
34
|
-
VALUE rec_consumer_proc);
|
63
|
+
VALUE dtrace_hdl_work(int argc, VALUE *argv, VALUE self);
|
35
64
|
VALUE dtrace_hdl_buf_consumer(VALUE self, VALUE buf_consumer_proc);
|
65
|
+
VALUE dtrace_hdl_createprocess(VALUE self, VALUE argv);
|
66
|
+
VALUE dtrace_hdl_grabprocess(VALUE self, VALUE pid);
|
36
67
|
|
37
68
|
VALUE dtraceprobe_init(VALUE self);
|
38
69
|
VALUE dtraceprobe_probe_id(VALUE self);
|
@@ -42,10 +73,17 @@ VALUE dtraceprobe_func(VALUE self);
|
|
42
73
|
VALUE dtraceprobe_name(VALUE self);
|
43
74
|
|
44
75
|
VALUE dtraceprobedata_init(VALUE self);
|
45
|
-
VALUE
|
76
|
+
VALUE dtraceprobedata_epid(VALUE self);
|
77
|
+
VALUE dtraceprobedata_probe(VALUE self);
|
78
|
+
VALUE dtraceprobedata_cpu(VALUE self);
|
79
|
+
VALUE dtraceprobedata_indent(VALUE self);
|
80
|
+
VALUE dtraceprobedata_prefix(VALUE self);
|
81
|
+
VALUE dtraceprobedata_flow(VALUE self);
|
46
82
|
VALUE dtraceprobedata_each_record(VALUE self);
|
47
83
|
|
48
84
|
VALUE dtracebufdata_init(VALUE self);
|
85
|
+
VALUE dtracebufdata_epid(VALUE self);
|
86
|
+
VALUE dtracebufdata_probe(VALUE self);
|
49
87
|
VALUE dtracebufdata_record(VALUE self);
|
50
88
|
|
51
89
|
VALUE dtraceprogram_init(VALUE self);
|
@@ -59,3 +97,4 @@ VALUE dtraceprograminfo_matches_count(VALUE self);
|
|
59
97
|
VALUE dtraceprograminfo_speculations_count(VALUE self);
|
60
98
|
|
61
99
|
VALUE dtracerecdesc_init(VALUE self);
|
100
|
+
VALUE dtracerecdesc_action(VALUE self);
|
data/ext/dtrace_bufdata.c
CHANGED
@@ -7,6 +7,7 @@
|
|
7
7
|
RUBY_EXTERN VALUE eDtraceException;
|
8
8
|
RUBY_EXTERN VALUE cDtraceAggData;
|
9
9
|
RUBY_EXTERN VALUE cDtraceRecDesc;
|
10
|
+
RUBY_EXTERN VALUE cDtraceProbe;
|
10
11
|
|
11
12
|
/* :nodoc: */
|
12
13
|
VALUE dtracebufdata_init(VALUE self)
|
@@ -17,6 +18,46 @@ VALUE dtracebufdata_init(VALUE self)
|
|
17
18
|
return self;
|
18
19
|
}
|
19
20
|
|
21
|
+
/*
|
22
|
+
* Returns the enabled probe id which generated this data
|
23
|
+
*/
|
24
|
+
VALUE dtracebufdata_epid(VALUE self)
|
25
|
+
{
|
26
|
+
dtrace_bufdata_t *bufdata;
|
27
|
+
|
28
|
+
Data_Get_Struct(self, dtrace_bufdata_t, bufdata);
|
29
|
+
|
30
|
+
if (bufdata->dtbda_probe) {
|
31
|
+
return INT2FIX(bufdata->dtbda_probe->dtpda_edesc->dtepd_epid);
|
32
|
+
}
|
33
|
+
|
34
|
+
return Qnil;
|
35
|
+
}
|
36
|
+
|
37
|
+
|
38
|
+
/*
|
39
|
+
* Returns the DtraceProbe for the probe which generated this data
|
40
|
+
*/
|
41
|
+
VALUE dtracebufdata_probe(VALUE self)
|
42
|
+
{
|
43
|
+
dtrace_bufdata_t *bufdata;
|
44
|
+
VALUE dtraceprobe;
|
45
|
+
|
46
|
+
Data_Get_Struct(self, dtrace_bufdata_t, bufdata);
|
47
|
+
|
48
|
+
if (bufdata->dtbda_probe) {
|
49
|
+
dtraceprobe = Data_Wrap_Struct(cDtraceProbe, 0, NULL, (dtrace_probedesc_t *)bufdata->dtbda_probe->dtpda_pdesc);
|
50
|
+
return dtraceprobe;
|
51
|
+
}
|
52
|
+
|
53
|
+
return Qnil;
|
54
|
+
}
|
55
|
+
|
56
|
+
/*
|
57
|
+
* Returns the record in this DtraceBufdata. Records are returned as
|
58
|
+
* either DtraceRecords or DtraceStackRecords as appropriate for the
|
59
|
+
* type of action.
|
60
|
+
*/
|
20
61
|
VALUE dtracebufdata_record(VALUE self)
|
21
62
|
{
|
22
63
|
dtrace_bufdata_t *bufdata;
|
@@ -50,17 +91,22 @@ VALUE dtracebufdata_record(VALUE self)
|
|
50
91
|
/* trace() action */
|
51
92
|
break;
|
52
93
|
case DTRACEACT_PRINTF:
|
53
|
-
/*
|
54
|
-
* Only the formatted string was not available to dtj_chewrec(),
|
55
|
-
* so we attach that now.
|
56
|
-
*/
|
94
|
+
/* printf action, not available in probedata */
|
57
95
|
v = rb_str_new2(s);
|
96
|
+
dtracerecord = rb_class_new_instance(0, NULL, rb_path2class("DtracePrintfRecord"));
|
97
|
+
rb_iv_set(dtracerecord, "@from", rb_str_new2("bufdata"));
|
98
|
+
rb_iv_set(dtracerecord, "@value", v);
|
99
|
+
return (dtracerecord);
|
58
100
|
break;
|
59
101
|
case DTRACEACT_STACK:
|
60
102
|
case DTRACEACT_USTACK:
|
61
103
|
case DTRACEACT_JSTACK:
|
62
104
|
/* stand-alone stack(), ustack(), or jstack() action */
|
63
105
|
v = rb_str_new2(s);
|
106
|
+
dtracerecord = rb_class_new_instance(0, NULL, rb_path2class("DtraceStackRecord"));
|
107
|
+
rb_iv_set(dtracerecord, "@from", rb_str_new2("bufdata"));
|
108
|
+
rb_funcall(dtracerecord, rb_intern("parse"), 1, v);
|
109
|
+
return (dtracerecord);
|
64
110
|
break;
|
65
111
|
case DTRACEACT_USYM:
|
66
112
|
case DTRACEACT_UADDR:
|
@@ -83,6 +129,8 @@ VALUE dtracebufdata_record(VALUE self)
|
|
83
129
|
if (!NIL_P(v)) {
|
84
130
|
dtracerecord = rb_class_new_instance(0, NULL, rb_path2class("DtraceRecord"));
|
85
131
|
rb_iv_set(dtracerecord, "@value", v);
|
132
|
+
rb_iv_set(dtracerecord, "@action", INT2FIX(act));
|
133
|
+
rb_iv_set(dtracerecord, "@from", rb_str_new2("bufdata"));
|
86
134
|
return (dtracerecord);
|
87
135
|
}
|
88
136
|
else {
|
data/ext/dtrace_hdl.c
CHANGED
@@ -5,16 +5,19 @@
|
|
5
5
|
#include "dtrace_api.h"
|
6
6
|
|
7
7
|
RUBY_EXTERN VALUE eDtraceException;
|
8
|
+
|
9
|
+
RUBY_EXTERN VALUE cDtrace;
|
8
10
|
RUBY_EXTERN VALUE cDtraceProbe;
|
9
11
|
RUBY_EXTERN VALUE cDtraceProgram;
|
10
|
-
RUBY_EXTERN VALUE cDtraceAggData;
|
11
12
|
RUBY_EXTERN VALUE cDtraceRecDesc;
|
12
13
|
RUBY_EXTERN VALUE cDtraceProbeData;
|
13
14
|
RUBY_EXTERN VALUE cDtraceBufData;
|
15
|
+
RUBY_EXTERN VALUE cDtraceProcess;
|
14
16
|
|
15
17
|
void dtrace_hdl_free (void *handle)
|
16
18
|
{
|
17
|
-
|
19
|
+
if (handle)
|
20
|
+
dtrace_close(handle);
|
18
21
|
}
|
19
22
|
|
20
23
|
VALUE dtrace_hdl_alloc(VALUE klass)
|
@@ -26,6 +29,17 @@ VALUE dtrace_hdl_alloc(VALUE klass)
|
|
26
29
|
handle = dtrace_open(DTRACE_VERSION, 0, &err);
|
27
30
|
|
28
31
|
if (handle) {
|
32
|
+
/*
|
33
|
+
* Leopard's DTrace requires symbol resolution to be
|
34
|
+
* switched on explicitly
|
35
|
+
*/
|
36
|
+
#ifdef __APPLE__
|
37
|
+
(void) dtrace_setopt(handle, "stacksymbols", "enabled");
|
38
|
+
#endif
|
39
|
+
|
40
|
+
/* always request flowindent information */
|
41
|
+
(void) dtrace_setopt(handle, "flowindent", 0);
|
42
|
+
|
29
43
|
obj = Data_Wrap_Struct(klass, 0, dtrace_hdl_free, handle);
|
30
44
|
return obj;
|
31
45
|
}
|
@@ -96,7 +110,7 @@ VALUE dtrace_strcompile(int argc, VALUE *argv, VALUE self)
|
|
96
110
|
|
97
111
|
rb_scan_args(argc, argv, "1*", &dtrace_text, &dtrace_argv_array);
|
98
112
|
|
99
|
-
dtrace_argc =
|
113
|
+
dtrace_argc = rb_ary_len(dtrace_argv_array);
|
100
114
|
dtrace_argv = ALLOC_N(char *, dtrace_argc + 1);
|
101
115
|
for (i = 0; i < dtrace_argc; i++) {
|
102
116
|
dtrace_argv[i + 1] = STR2CSTR(rb_ary_entry(dtrace_argv_array, i));
|
@@ -202,72 +216,6 @@ VALUE dtrace_hdl_stop(VALUE self)
|
|
202
216
|
return Qnil;
|
203
217
|
}
|
204
218
|
|
205
|
-
int _agg_walk_yield(const dtrace_aggdata_t *data, void *arg)
|
206
|
-
{
|
207
|
-
VALUE aggdata;
|
208
|
-
|
209
|
-
aggdata = Data_Wrap_Struct(cDtraceAggData, 0, NULL, (dtrace_aggdata_t *)data);
|
210
|
-
|
211
|
-
rb_yield(aggdata);
|
212
|
-
return (DTRACE_AGGWALK_NEXT);
|
213
|
-
}
|
214
|
-
|
215
|
-
/*
|
216
|
-
* Yields each aggregate in turn.
|
217
|
-
*
|
218
|
-
* Aggregates are represented by a DtraceAggregate object.
|
219
|
-
*/
|
220
|
-
VALUE dtrace_hdl_each_aggregate(VALUE self)
|
221
|
-
{
|
222
|
-
dtrace_hdl_t *handle;
|
223
|
-
|
224
|
-
Data_Get_Struct(self, dtrace_hdl_t, handle);
|
225
|
-
if (dtrace_aggregate_walk_keyvarsorted(handle, _agg_walk_yield, NULL) < 0)
|
226
|
-
rb_raise(eDtraceException, dtrace_errmsg(handle, dtrace_errno(handle)));
|
227
|
-
|
228
|
-
return Qnil;
|
229
|
-
}
|
230
|
-
|
231
|
-
/*
|
232
|
-
* Uses libdtrace to print a summary of aggregates to STDERR.
|
233
|
-
*/
|
234
|
-
VALUE dtrace_hdl_aggregate_print(VALUE self)
|
235
|
-
{
|
236
|
-
dtrace_hdl_t *handle;
|
237
|
-
|
238
|
-
Data_Get_Struct(self, dtrace_hdl_t, handle);
|
239
|
-
if (dtrace_aggregate_print(handle, stderr, NULL) < 0)
|
240
|
-
rb_raise(eDtraceException, dtrace_errmsg(handle, dtrace_errno(handle)));
|
241
|
-
|
242
|
-
return Qnil;
|
243
|
-
}
|
244
|
-
|
245
|
-
/*
|
246
|
-
* Take a snapshot of the current aggregate values.
|
247
|
-
*/
|
248
|
-
VALUE dtrace_hdl_aggregate_snap(VALUE self)
|
249
|
-
{
|
250
|
-
dtrace_hdl_t *handle;
|
251
|
-
|
252
|
-
Data_Get_Struct(self, dtrace_hdl_t, handle);
|
253
|
-
if (dtrace_aggregate_snap(handle) < 0)
|
254
|
-
rb_raise(eDtraceException, dtrace_errmsg(handle, dtrace_errno(handle)));
|
255
|
-
|
256
|
-
return Qnil;
|
257
|
-
}
|
258
|
-
|
259
|
-
/*
|
260
|
-
* Clear the current aggregate snapshot.
|
261
|
-
*/
|
262
|
-
VALUE dtrace_hdl_aggregate_clear(VALUE self)
|
263
|
-
{
|
264
|
-
dtrace_hdl_t *handle;
|
265
|
-
|
266
|
-
Data_Get_Struct(self, dtrace_hdl_t, handle);
|
267
|
-
dtrace_aggregate_clear(handle);
|
268
|
-
return Qnil;
|
269
|
-
}
|
270
|
-
|
271
219
|
/*
|
272
220
|
* Return the most recent DTrace error.
|
273
221
|
*/
|
@@ -294,11 +242,6 @@ VALUE dtrace_hdl_sleep(VALUE self)
|
|
294
242
|
return Qnil;
|
295
243
|
}
|
296
244
|
|
297
|
-
typedef struct dtrace_work_handlers {
|
298
|
-
VALUE probe;
|
299
|
-
VALUE rec;
|
300
|
-
} dtrace_work_handlers_t;
|
301
|
-
|
302
245
|
static int _probe_consumer(const dtrace_probedata_t *data, void *arg)
|
303
246
|
{
|
304
247
|
VALUE proc;
|
@@ -308,9 +251,12 @@ static int _probe_consumer(const dtrace_probedata_t *data, void *arg)
|
|
308
251
|
handlers = *(dtrace_work_handlers_t *) arg;
|
309
252
|
proc = handlers.probe;
|
310
253
|
|
311
|
-
|
312
|
-
|
313
|
-
|
254
|
+
if (!NIL_P(proc)) {
|
255
|
+
probedata = Data_Wrap_Struct(cDtraceProbeData, 0, NULL, (dtrace_probedata_t *)data);
|
256
|
+
rb_iv_set(probedata, "@handle", handlers.handle);
|
257
|
+
rb_funcall(proc, rb_intern("call"), 1, probedata);
|
258
|
+
}
|
259
|
+
|
314
260
|
return (DTRACE_CONSUME_THIS);
|
315
261
|
}
|
316
262
|
|
@@ -319,12 +265,29 @@ static int _rec_consumer(const dtrace_probedata_t *data, const dtrace_recdesc_t
|
|
319
265
|
VALUE proc;
|
320
266
|
dtrace_work_handlers_t handlers;
|
321
267
|
VALUE recdesc;
|
268
|
+
VALUE probedata;
|
269
|
+
|
270
|
+
dtrace_actkind_t act;
|
322
271
|
|
323
272
|
handlers = *(dtrace_work_handlers_t *) arg;
|
324
273
|
proc = handlers.rec;
|
274
|
+
if (!NIL_P(proc)) {
|
275
|
+
if (rec) {
|
276
|
+
recdesc = Data_Wrap_Struct(cDtraceRecDesc, 0, NULL, (dtrace_recdesc_t *)rec);
|
277
|
+
rb_iv_set(recdesc, "@handle", handlers.handle);
|
278
|
+
rb_funcall(proc, rb_intern("call"), 1, recdesc);
|
279
|
+
}
|
280
|
+
else {
|
281
|
+
rb_funcall(proc, rb_intern("call"), 1, Qnil);
|
282
|
+
return (DTRACE_CONSUME_NEXT);
|
283
|
+
}
|
284
|
+
}
|
325
285
|
|
326
|
-
|
327
|
-
|
286
|
+
if (rec) {
|
287
|
+
act = rec->dtrd_action;
|
288
|
+
if (act == DTRACEACT_EXIT)
|
289
|
+
return (DTRACE_CONSUME_NEXT);
|
290
|
+
}
|
328
291
|
|
329
292
|
return (DTRACE_CONSUME_THIS);
|
330
293
|
}
|
@@ -336,30 +299,44 @@ static int _buf_consumer(const dtrace_bufdata_t *bufdata, void *arg)
|
|
336
299
|
|
337
300
|
proc = (VALUE)arg;
|
338
301
|
|
339
|
-
|
340
|
-
|
302
|
+
if (!NIL_P(proc)) {
|
303
|
+
dtracebufdata = Data_Wrap_Struct(cDtraceBufData, 0, NULL, (dtrace_bufdata_t *)bufdata);
|
304
|
+
rb_funcall(proc, rb_intern("call"), 1, dtracebufdata);
|
305
|
+
}
|
341
306
|
|
342
307
|
return (DTRACE_HANDLE_OK);
|
343
308
|
}
|
344
309
|
|
345
310
|
/*
|
346
311
|
* Process any data waiting from the D program.
|
312
|
+
*
|
313
|
+
* Takes a Proc to which DtraceProbeData objects will be yielded, and
|
314
|
+
* an optional second Proc to which DtraceRecDesc objects will be
|
315
|
+
* yielded.
|
316
|
+
*
|
347
317
|
*/
|
348
|
-
VALUE dtrace_hdl_work(VALUE
|
349
|
-
VALUE probe_consumer_proc,
|
350
|
-
VALUE rec_consumer_proc)
|
318
|
+
VALUE dtrace_hdl_work(int argc, VALUE *argv, VALUE self)
|
351
319
|
{
|
352
320
|
dtrace_hdl_t *handle;
|
353
321
|
dtrace_workstatus_t status;
|
354
322
|
dtrace_work_handlers_t handlers;
|
323
|
+
VALUE probe_consumer_proc;
|
324
|
+
VALUE rec_consumer_proc;
|
355
325
|
|
356
326
|
Data_Get_Struct(self, dtrace_hdl_t, handle);
|
357
327
|
|
328
|
+
/* handle args - probe_consumer_proc is mandatory, rec_consumer_proc
|
329
|
+
is optional */
|
330
|
+
rb_scan_args(argc, argv, "11", &probe_consumer_proc, &rec_consumer_proc);
|
331
|
+
|
358
332
|
/* fill out the handlers struct */
|
359
|
-
handlers.probe
|
360
|
-
handlers.rec
|
333
|
+
handlers.probe = probe_consumer_proc;
|
334
|
+
handlers.rec = rec_consumer_proc;
|
335
|
+
handlers.handle = self;
|
361
336
|
|
362
337
|
status = dtrace_work(handle, NULL, _probe_consumer, _rec_consumer, &handlers);
|
338
|
+
if (status < 0)
|
339
|
+
rb_raise(eDtraceException, (dtrace_errmsg(handle, dtrace_errno(handle))));
|
363
340
|
|
364
341
|
return INT2FIX(status);
|
365
342
|
}
|
@@ -379,3 +356,77 @@ VALUE dtrace_hdl_buf_consumer(VALUE self, VALUE buf_consumer)
|
|
379
356
|
|
380
357
|
return Qnil;
|
381
358
|
}
|
359
|
+
|
360
|
+
/*
|
361
|
+
* Start a process which will be traced. The pid of the started
|
362
|
+
* process will be available in D as $target.
|
363
|
+
*
|
364
|
+
* Pass an array, where the first element is the full path to the
|
365
|
+
* program to start, and subsequent elements are its arguments.
|
366
|
+
*
|
367
|
+
* Returns a DtraceProcess object which is used to start the process
|
368
|
+
* once tracing is set up.
|
369
|
+
*/
|
370
|
+
VALUE dtrace_hdl_createprocess(VALUE self, VALUE rb_argv)
|
371
|
+
{
|
372
|
+
dtrace_hdl_t *handle;
|
373
|
+
struct ps_prochandle *P;
|
374
|
+
char **argv;
|
375
|
+
long len;
|
376
|
+
int i;
|
377
|
+
VALUE dtraceprocess;
|
378
|
+
dtrace_process_t *process;
|
379
|
+
|
380
|
+
Data_Get_Struct(self, dtrace_hdl_t, handle);
|
381
|
+
|
382
|
+
len = rb_ary_len(rb_argv);
|
383
|
+
argv = ALLOC_N(char *, len + 1);
|
384
|
+
|
385
|
+
for (i = 0; i < len; i++) {
|
386
|
+
argv[i] = STR2CSTR(rb_ary_entry(rb_argv, i));
|
387
|
+
}
|
388
|
+
argv[len] = NULL;
|
389
|
+
|
390
|
+
P = dtrace_proc_create(handle, argv[0], argv);
|
391
|
+
free(argv);
|
392
|
+
|
393
|
+
if (P == NULL) {
|
394
|
+
rb_raise(eDtraceException, dtrace_errmsg(handle, dtrace_errno(handle)));
|
395
|
+
}
|
396
|
+
|
397
|
+
process = ALLOC(dtrace_process_t);
|
398
|
+
process->handle = handle;
|
399
|
+
process->proc = P;
|
400
|
+
|
401
|
+
dtraceprocess = Data_Wrap_Struct(cDtraceProcess, 0, dtrace_process_release, (dtrace_process_t *)process);
|
402
|
+
return dtraceprocess;
|
403
|
+
}
|
404
|
+
|
405
|
+
/*
|
406
|
+
* Grab a currently-running process by pid.
|
407
|
+
*
|
408
|
+
* Returns a DtraceProcess object which is used to start the process
|
409
|
+
* once tracing is set up.
|
410
|
+
*/
|
411
|
+
VALUE dtrace_hdl_grabprocess(VALUE self, VALUE pid)
|
412
|
+
{
|
413
|
+
dtrace_hdl_t *handle;
|
414
|
+
struct ps_prochandle *P;
|
415
|
+
dtrace_process_t *process;
|
416
|
+
VALUE dtraceprocess;
|
417
|
+
|
418
|
+
Data_Get_Struct(self, dtrace_hdl_t, handle);
|
419
|
+
|
420
|
+
P = dtrace_proc_grab(handle, FIX2INT(pid), 0);
|
421
|
+
|
422
|
+
if (P == NULL) {
|
423
|
+
rb_raise(eDtraceException, dtrace_errmsg(handle, dtrace_errno(handle)));
|
424
|
+
}
|
425
|
+
|
426
|
+
process = ALLOC(dtrace_process_t);
|
427
|
+
process->handle = handle;
|
428
|
+
process->proc = P;
|
429
|
+
|
430
|
+
dtraceprocess = Data_Wrap_Struct(cDtraceProcess, 0, dtrace_process_release, (dtrace_process_t *)process);
|
431
|
+
return dtraceprocess;
|
432
|
+
}
|