ruby-dtrace 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|