ruby-dtrace 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +7 -0
- data/Manifest.txt +4 -0
- data/ext/dtrace_api.c +21 -0
- data/ext/dtrace_api.h +29 -1
- data/ext/dtrace_dropdata.c +131 -0
- data/ext/dtrace_errdata.c +110 -0
- data/ext/dtrace_hdl.c +212 -67
- data/ext/dtrace_probedata.c +6 -6
- data/ext/dtrace_program.c +10 -5
- data/lib/dtrace.rb +1 -1
- data/lib/dtraceconsumer.rb +54 -4
- data/lib/dtracedata.rb +14 -7
- data/test/test_dtrace_drops_errors.rb +183 -0
- data/test/test_dtrace_typefilter.rb +108 -0
- metadata +8 -2
data/History.txt
CHANGED
data/Manifest.txt
CHANGED
@@ -7,6 +7,8 @@ ext/dtrace_aggdata.c
|
|
7
7
|
ext/dtrace_api.c
|
8
8
|
ext/dtrace_api.h
|
9
9
|
ext/dtrace_bufdata.c
|
10
|
+
ext/dtrace_dropdata.c
|
11
|
+
ext/dtrace_errdata.c
|
10
12
|
ext/dtrace_hdl.c
|
11
13
|
ext/dtrace_probe.c
|
12
14
|
ext/dtrace_probedata.c
|
@@ -42,7 +44,9 @@ plugin/dtrace/test/dtrace_test.rb
|
|
42
44
|
plugin/dtrace/views/dtrace/_report.rhtml
|
43
45
|
test/test_dtrace.rb
|
44
46
|
test/test_dtrace_aggregates.rb
|
47
|
+
test/test_dtrace_drops_errors.rb
|
45
48
|
test/test_dtrace_processes.rb
|
46
49
|
test/test_dtrace_profile.rb
|
47
50
|
test/test_dtrace_repeat.rb
|
48
51
|
test/test_dtrace_rubyprobe.rb
|
52
|
+
test/test_dtrace_typefilter.rb
|
data/ext/dtrace_api.c
CHANGED
@@ -13,6 +13,8 @@ VALUE cDtraceRecDesc;
|
|
13
13
|
VALUE cDtraceProbeData;
|
14
14
|
VALUE cDtraceBufData;
|
15
15
|
VALUE cDtraceProcess;
|
16
|
+
VALUE cDtraceDropData;
|
17
|
+
VALUE cDtraceErrData;
|
16
18
|
|
17
19
|
VALUE eDtraceException;
|
18
20
|
|
@@ -30,6 +32,8 @@ void Init_dtrace_api() {
|
|
30
32
|
rb_define_method(cDtrace, "sleep", dtrace_hdl_sleep, 0); // in dtrace_hdl.c
|
31
33
|
rb_define_method(cDtrace, "work", dtrace_hdl_work, -1); // in dtrace_hdl.c
|
32
34
|
rb_define_method(cDtrace, "buf_consumer", dtrace_hdl_buf_consumer, 1); // in dtrace_hdl.c
|
35
|
+
rb_define_method(cDtrace, "drop_consumer", dtrace_hdl_drop_consumer, 1); // in dtrace_hdl.c
|
36
|
+
rb_define_method(cDtrace, "err_consumer", dtrace_hdl_err_consumer, 1); // in dtrace_hdl.c
|
33
37
|
rb_define_method(cDtrace, "createprocess", dtrace_hdl_createprocess, 1); // in dtrace_hdl.c
|
34
38
|
rb_define_method(cDtrace, "grabprocess", dtrace_hdl_grabprocess, 1); // in dtrace_hdl.c
|
35
39
|
rb_define_alloc_func(cDtrace, dtrace_hdl_alloc);
|
@@ -83,6 +87,23 @@ void Init_dtrace_api() {
|
|
83
87
|
rb_define_method(cDtraceRecDesc, "initialize", dtracerecdesc_init, 0); // in dtrace_recdesc.c
|
84
88
|
rb_define_method(cDtraceRecDesc, "action", dtracerecdesc_action, 0); // in dtrace_recdesc.c
|
85
89
|
|
90
|
+
cDtraceDropData = rb_define_class("DtraceDropData", rb_cObject);
|
91
|
+
rb_define_method(cDtraceDropData, "initialize", dtracedropdata_init, 0); // in dtrace_dropdata.c
|
92
|
+
rb_define_method(cDtraceDropData, "cpu", dtracedropdata_cpu, 0); // in dtrace_dropdata.c
|
93
|
+
rb_define_method(cDtraceDropData, "drops", dtracedropdata_drops, 0); // in dtrace_dropdata.c
|
94
|
+
rb_define_method(cDtraceDropData, "total", dtracedropdata_total, 0); // in dtrace_dropdata.c
|
95
|
+
rb_define_method(cDtraceDropData, "msg", dtracedropdata_msg, 0); // in dtrace_dropdata.c
|
96
|
+
rb_define_method(cDtraceDropData, "kind", dtracedropdata_kind, 0); // in dtrace_dropdata.c
|
97
|
+
|
98
|
+
cDtraceErrData = rb_define_class("DtraceErrData", rb_cObject);
|
99
|
+
rb_define_method(cDtraceErrData, "initialize", dtraceerrdata_init, 0); // in dtrace_errdata.c
|
100
|
+
rb_define_method(cDtraceErrData, "cpu", dtraceerrdata_cpu, 0); // in dtrace_errdata.c
|
101
|
+
rb_define_method(cDtraceErrData, "action", dtraceerrdata_action, 0); // in dtrace_errdata.c
|
102
|
+
rb_define_method(cDtraceErrData, "offset", dtraceerrdata_offset, 0); // in dtrace_errdata.c
|
103
|
+
rb_define_method(cDtraceErrData, "fault", dtraceerrdata_fault, 0); // in dtrace_errdata.c
|
104
|
+
rb_define_method(cDtraceErrData, "addr", dtraceerrdata_addr, 0); // in dtrace_errdata.c
|
105
|
+
rb_define_method(cDtraceErrData, "msg", dtraceerrdata_msg, 0); // in dtrace_errdata.c
|
106
|
+
|
86
107
|
eDtraceException = rb_define_class("DtraceException", rb_eStandardError);
|
87
108
|
}
|
88
109
|
|
data/ext/dtrace_api.h
CHANGED
@@ -26,6 +26,18 @@ typedef struct dtrace_process {
|
|
26
26
|
struct ps_prochandle *proc;
|
27
27
|
} dtrace_process_t;
|
28
28
|
|
29
|
+
/* Used to wrap up the DTrace handle, so we can keep references to the
|
30
|
+
various callbacks: we must mark them from the dtrace_hdl_mark
|
31
|
+
routine, which only gets a pointer to this structure. */
|
32
|
+
typedef struct dtrace_handle {
|
33
|
+
dtrace_hdl_t *hdl;
|
34
|
+
VALUE probe;
|
35
|
+
VALUE rec;
|
36
|
+
VALUE buf;
|
37
|
+
VALUE err;
|
38
|
+
VALUE drop;
|
39
|
+
} dtrace_handle_t;
|
40
|
+
|
29
41
|
/* Handle missing RARRAY_LEN etc */
|
30
42
|
#ifdef RARRAY_LEN
|
31
43
|
static inline long rb_str_len(VALUE s) {return RSTRING_LEN(s);}
|
@@ -49,7 +61,6 @@ VALUE dtraceaggdata_init(VALUE self);
|
|
49
61
|
VALUE dtraceaggdata_value(VALUE self);
|
50
62
|
VALUE dtraceaggdata_aggtype(VALUE self);
|
51
63
|
|
52
|
-
void dtrace_hdl_free (void *handle);
|
53
64
|
VALUE dtrace_init(VALUE self);
|
54
65
|
VALUE dtrace_hdl_alloc(VALUE klass);
|
55
66
|
VALUE dtrace_each_probe(VALUE self);
|
@@ -62,6 +73,8 @@ VALUE dtrace_hdl_error(VALUE self);
|
|
62
73
|
VALUE dtrace_hdl_sleep(VALUE self);
|
63
74
|
VALUE dtrace_hdl_work(int argc, VALUE *argv, VALUE self);
|
64
75
|
VALUE dtrace_hdl_buf_consumer(VALUE self, VALUE buf_consumer_proc);
|
76
|
+
VALUE dtrace_hdl_drop_consumer(VALUE self, VALUE drop_consumer_proc);
|
77
|
+
VALUE dtrace_hdl_err_consumer(VALUE self, VALUE err_consumer_proc);
|
65
78
|
VALUE dtrace_hdl_createprocess(VALUE self, VALUE argv);
|
66
79
|
VALUE dtrace_hdl_grabprocess(VALUE self, VALUE pid);
|
67
80
|
|
@@ -98,3 +111,18 @@ VALUE dtraceprograminfo_speculations_count(VALUE self);
|
|
98
111
|
|
99
112
|
VALUE dtracerecdesc_init(VALUE self);
|
100
113
|
VALUE dtracerecdesc_action(VALUE self);
|
114
|
+
|
115
|
+
VALUE dtracedropdata_init(VALUE self);
|
116
|
+
VALUE dtracedropdata_cpu(VALUE self);
|
117
|
+
VALUE dtracedropdata_drops(VALUE self);
|
118
|
+
VALUE dtracedropdata_total(VALUE self);
|
119
|
+
VALUE dtracedropdata_msg(VALUE self);
|
120
|
+
VALUE dtracedropdata_kind(VALUE self);
|
121
|
+
|
122
|
+
VALUE dtraceerrdata_init(VALUE self);
|
123
|
+
VALUE dtraceerrdata_cpu(VALUE self);
|
124
|
+
VALUE dtraceerrdata_action(VALUE self);
|
125
|
+
VALUE dtraceerrdata_offset(VALUE self);
|
126
|
+
VALUE dtraceerrdata_fault(VALUE self);
|
127
|
+
VALUE dtraceerrdata_addr(VALUE self);
|
128
|
+
VALUE dtraceerrdata_msg(VALUE self);
|
@@ -0,0 +1,131 @@
|
|
1
|
+
/* Ruby-Dtrace
|
2
|
+
* (c) 2007 Chris Andrews <chris@nodnol.org>
|
3
|
+
*/
|
4
|
+
|
5
|
+
#include "dtrace_api.h"
|
6
|
+
|
7
|
+
RUBY_EXTERN VALUE eDtraceException;
|
8
|
+
|
9
|
+
/* :nodoc: */
|
10
|
+
VALUE dtracedropdata_init(VALUE self)
|
11
|
+
{
|
12
|
+
dtrace_dropdata_t *data;
|
13
|
+
|
14
|
+
Data_Get_Struct(self, dtrace_dropdata_t, data);
|
15
|
+
return self;
|
16
|
+
}
|
17
|
+
|
18
|
+
/* Returns the CPU which generated this drop record */
|
19
|
+
VALUE dtracedropdata_cpu(VALUE self)
|
20
|
+
{
|
21
|
+
dtrace_dropdata_t *data;
|
22
|
+
processorid_t cpu;
|
23
|
+
|
24
|
+
Data_Get_Struct(self, dtrace_dropdata_t, data);
|
25
|
+
|
26
|
+
if (data) {
|
27
|
+
cpu = data->dtdda_cpu;
|
28
|
+
return INT2FIX(cpu);
|
29
|
+
}
|
30
|
+
else {
|
31
|
+
return Qnil;
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
/* Returns the number of records dropped in this drop record */
|
36
|
+
VALUE dtracedropdata_drops(VALUE self)
|
37
|
+
{
|
38
|
+
dtrace_dropdata_t *data;
|
39
|
+
|
40
|
+
Data_Get_Struct(self, dtrace_dropdata_t, data);
|
41
|
+
|
42
|
+
if (data) {
|
43
|
+
return INT2FIX(data->dtdda_drops);
|
44
|
+
}
|
45
|
+
else {
|
46
|
+
return Qnil;
|
47
|
+
}
|
48
|
+
}
|
49
|
+
|
50
|
+
/* Returns the number of records dropped in total */
|
51
|
+
VALUE dtracedropdata_total(VALUE self)
|
52
|
+
{
|
53
|
+
dtrace_dropdata_t *data;
|
54
|
+
|
55
|
+
Data_Get_Struct(self, dtrace_dropdata_t, data);
|
56
|
+
|
57
|
+
if (data) {
|
58
|
+
return INT2FIX(data->dtdda_total);
|
59
|
+
}
|
60
|
+
else {
|
61
|
+
return Qnil;
|
62
|
+
}
|
63
|
+
}
|
64
|
+
|
65
|
+
/* Returns a message from the DTrace library describing this drop
|
66
|
+
record. */
|
67
|
+
VALUE dtracedropdata_msg(VALUE self)
|
68
|
+
{
|
69
|
+
dtrace_dropdata_t *data;
|
70
|
+
|
71
|
+
Data_Get_Struct(self, dtrace_dropdata_t, data);
|
72
|
+
|
73
|
+
if (data) {
|
74
|
+
return rb_str_new2(data->dtdda_msg);
|
75
|
+
}
|
76
|
+
else {
|
77
|
+
return Qnil;
|
78
|
+
}
|
79
|
+
}
|
80
|
+
|
81
|
+
/* Returns the reason for the drop (the "drop kind") */
|
82
|
+
VALUE dtracedropdata_kind(VALUE self)
|
83
|
+
{
|
84
|
+
dtrace_dropdata_t *data;
|
85
|
+
VALUE kind;
|
86
|
+
|
87
|
+
Data_Get_Struct(self, dtrace_dropdata_t, data);
|
88
|
+
|
89
|
+
if (data) {
|
90
|
+
switch (data->dtdda_kind) {
|
91
|
+
case DTRACEDROP_PRINCIPAL:
|
92
|
+
kind = rb_str_new2("drop to principal buffer");
|
93
|
+
break;
|
94
|
+
case DTRACEDROP_AGGREGATION:
|
95
|
+
kind = rb_str_new2("drop to aggregation buffer");
|
96
|
+
break;
|
97
|
+
case DTRACEDROP_DYNAMIC:
|
98
|
+
kind = rb_str_new2("dynamic drop");
|
99
|
+
break;
|
100
|
+
case DTRACEDROP_DYNRINSE:
|
101
|
+
kind = rb_str_new2("dyn drop due to rinsing");
|
102
|
+
break;
|
103
|
+
case DTRACEDROP_DYNDIRTY:
|
104
|
+
kind = rb_str_new2("dyn drop due to dirty");
|
105
|
+
break;
|
106
|
+
case DTRACEDROP_SPEC:
|
107
|
+
kind = rb_str_new2("speculative drop");
|
108
|
+
break;
|
109
|
+
case DTRACEDROP_SPECBUSY:
|
110
|
+
kind = rb_str_new2("spec drop due to busy");
|
111
|
+
break;
|
112
|
+
case DTRACEDROP_SPECUNAVAIL:
|
113
|
+
kind = rb_str_new2("spec drop due to unavail");
|
114
|
+
break;
|
115
|
+
case DTRACEDROP_STKSTROVERFLOW:
|
116
|
+
kind = rb_str_new2("stack string tab overflow");
|
117
|
+
break;
|
118
|
+
case DTRACEDROP_DBLERROR:
|
119
|
+
kind = rb_str_new2("error in ERROR probe");
|
120
|
+
break;
|
121
|
+
default:
|
122
|
+
kind = rb_str_new2("unknown");
|
123
|
+
break;
|
124
|
+
}
|
125
|
+
return kind;
|
126
|
+
}
|
127
|
+
else {
|
128
|
+
return Qnil;
|
129
|
+
}
|
130
|
+
}
|
131
|
+
|
@@ -0,0 +1,110 @@
|
|
1
|
+
/* Ruby-Dtrace
|
2
|
+
* (c) 2007 Chris Andrews <chris@nodnol.org>
|
3
|
+
*/
|
4
|
+
|
5
|
+
#include "dtrace_api.h"
|
6
|
+
|
7
|
+
RUBY_EXTERN VALUE eDtraceException;
|
8
|
+
|
9
|
+
/* :nodoc: */
|
10
|
+
VALUE dtraceerrdata_init(VALUE self)
|
11
|
+
{
|
12
|
+
dtrace_errdata_t *data;
|
13
|
+
|
14
|
+
Data_Get_Struct(self, dtrace_errdata_t, data);
|
15
|
+
return self;
|
16
|
+
}
|
17
|
+
|
18
|
+
/* Returns the CPU which generated this err record */
|
19
|
+
VALUE dtraceerrdata_cpu(VALUE self)
|
20
|
+
{
|
21
|
+
dtrace_errdata_t *data;
|
22
|
+
processorid_t cpu;
|
23
|
+
|
24
|
+
Data_Get_Struct(self, dtrace_errdata_t, data);
|
25
|
+
|
26
|
+
if (data) {
|
27
|
+
cpu = data->dteda_cpu;
|
28
|
+
return INT2FIX(cpu);
|
29
|
+
}
|
30
|
+
else {
|
31
|
+
return Qnil;
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
/* Returns a the action producing the error */
|
36
|
+
VALUE dtraceerrdata_action(VALUE self)
|
37
|
+
{
|
38
|
+
dtrace_errdata_t *data;
|
39
|
+
|
40
|
+
Data_Get_Struct(self, dtrace_errdata_t, data);
|
41
|
+
|
42
|
+
if (data) {
|
43
|
+
return INT2FIX(data->dteda_action);
|
44
|
+
}
|
45
|
+
else {
|
46
|
+
return Qnil;
|
47
|
+
}
|
48
|
+
}
|
49
|
+
|
50
|
+
/* Returns the offset of the error */
|
51
|
+
VALUE dtraceerrdata_offset(VALUE self)
|
52
|
+
{
|
53
|
+
dtrace_errdata_t *data;
|
54
|
+
|
55
|
+
Data_Get_Struct(self, dtrace_errdata_t, data);
|
56
|
+
|
57
|
+
if (data) {
|
58
|
+
return INT2FIX(data->dteda_offset);
|
59
|
+
}
|
60
|
+
else {
|
61
|
+
return Qnil;
|
62
|
+
}
|
63
|
+
}
|
64
|
+
|
65
|
+
/* Returns fault represented by the error */
|
66
|
+
VALUE dtraceerrdata_fault(VALUE self)
|
67
|
+
{
|
68
|
+
dtrace_errdata_t *data;
|
69
|
+
|
70
|
+
Data_Get_Struct(self, dtrace_errdata_t, data);
|
71
|
+
|
72
|
+
if (data) {
|
73
|
+
return INT2FIX(data->dteda_fault);
|
74
|
+
}
|
75
|
+
else {
|
76
|
+
return Qnil;
|
77
|
+
}
|
78
|
+
}
|
79
|
+
|
80
|
+
/* Returns the address of the fault if any */
|
81
|
+
VALUE dtraceerrdata_addr(VALUE self)
|
82
|
+
{
|
83
|
+
dtrace_errdata_t *data;
|
84
|
+
|
85
|
+
Data_Get_Struct(self, dtrace_errdata_t, data);
|
86
|
+
|
87
|
+
if (data) {
|
88
|
+
return INT2FIX(data->dteda_addr);
|
89
|
+
}
|
90
|
+
else {
|
91
|
+
return Qnil;
|
92
|
+
}
|
93
|
+
}
|
94
|
+
|
95
|
+
/* Returns a message from the DTrace library describing this err
|
96
|
+
record. */
|
97
|
+
VALUE dtraceerrdata_msg(VALUE self)
|
98
|
+
{
|
99
|
+
dtrace_errdata_t *data;
|
100
|
+
|
101
|
+
Data_Get_Struct(self, dtrace_errdata_t, data);
|
102
|
+
|
103
|
+
if (data) {
|
104
|
+
return rb_str_new2(data->dteda_msg);
|
105
|
+
}
|
106
|
+
else {
|
107
|
+
return Qnil;
|
108
|
+
}
|
109
|
+
}
|
110
|
+
|
data/ext/dtrace_hdl.c
CHANGED
@@ -13,34 +13,67 @@ RUBY_EXTERN VALUE cDtraceRecDesc;
|
|
13
13
|
RUBY_EXTERN VALUE cDtraceProbeData;
|
14
14
|
RUBY_EXTERN VALUE cDtraceBufData;
|
15
15
|
RUBY_EXTERN VALUE cDtraceProcess;
|
16
|
+
RUBY_EXTERN VALUE cDtraceDropData;
|
17
|
+
RUBY_EXTERN VALUE cDtraceErrData;
|
16
18
|
|
17
|
-
void dtrace_hdl_free
|
19
|
+
static void dtrace_hdl_free(void *arg)
|
18
20
|
{
|
19
|
-
|
20
|
-
|
21
|
+
dtrace_handle_t *handle = (dtrace_handle_t *)arg;
|
22
|
+
|
23
|
+
if (handle) {
|
24
|
+
dtrace_close(handle->hdl);
|
25
|
+
free(handle);
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
static void dtrace_hdl_mark(void *arg)
|
30
|
+
{
|
31
|
+
dtrace_handle_t *handle = (dtrace_handle_t *)arg;
|
32
|
+
|
33
|
+
if (handle) {
|
34
|
+
rb_gc_mark(handle->probe);
|
35
|
+
rb_gc_mark(handle->rec);
|
36
|
+
rb_gc_mark(handle->buf);
|
37
|
+
rb_gc_mark(handle->err);
|
38
|
+
rb_gc_mark(handle->drop);
|
39
|
+
}
|
21
40
|
}
|
22
41
|
|
23
42
|
VALUE dtrace_hdl_alloc(VALUE klass)
|
24
43
|
{
|
25
|
-
dtrace_hdl_t *
|
44
|
+
dtrace_hdl_t *hdl;
|
45
|
+
dtrace_handle_t *handle;
|
26
46
|
int err;
|
27
47
|
VALUE obj;
|
28
48
|
|
29
|
-
|
49
|
+
hdl = dtrace_open(DTRACE_VERSION, 0, &err);
|
30
50
|
|
31
|
-
if (
|
51
|
+
if (hdl) {
|
32
52
|
/*
|
33
53
|
* Leopard's DTrace requires symbol resolution to be
|
34
54
|
* switched on explicitly
|
35
55
|
*/
|
36
56
|
#ifdef __APPLE__
|
37
|
-
(void) dtrace_setopt(
|
57
|
+
(void) dtrace_setopt(hdl, "stacksymbols", "enabled");
|
38
58
|
#endif
|
39
59
|
|
40
60
|
/* always request flowindent information */
|
41
|
-
(void) dtrace_setopt(
|
61
|
+
(void) dtrace_setopt(hdl, "flowindent", 0);
|
62
|
+
|
63
|
+
handle = ALLOC(dtrace_handle_t);
|
64
|
+
if (!handle) {
|
65
|
+
rb_raise(eDtraceException, "alloc failed");
|
66
|
+
return Qnil;
|
67
|
+
}
|
42
68
|
|
43
|
-
|
69
|
+
handle->hdl = hdl;
|
70
|
+
handle->probe = Qnil;
|
71
|
+
handle->rec = Qnil;
|
72
|
+
handle->buf = Qnil;
|
73
|
+
handle->err = Qnil;
|
74
|
+
handle->drop = Qnil;
|
75
|
+
|
76
|
+
obj = Data_Wrap_Struct(klass, dtrace_hdl_mark, dtrace_hdl_free, handle);
|
44
77
|
return obj;
|
45
78
|
}
|
46
79
|
else {
|
@@ -51,16 +84,16 @@ VALUE dtrace_hdl_alloc(VALUE klass)
|
|
51
84
|
/* :nodoc: */
|
52
85
|
VALUE dtrace_init(VALUE self)
|
53
86
|
{
|
54
|
-
|
87
|
+
dtrace_handle_t *handle;
|
55
88
|
|
56
|
-
Data_Get_Struct(self,
|
89
|
+
Data_Get_Struct(self, dtrace_handle_t, handle);
|
57
90
|
if (handle)
|
58
91
|
return self;
|
59
92
|
else
|
60
93
|
return Qnil;
|
61
94
|
}
|
62
95
|
|
63
|
-
int _dtrace_next_probe(dtrace_hdl_t *
|
96
|
+
int _dtrace_next_probe(dtrace_hdl_t *hdl, const dtrace_probedesc_t *pdp, void *arg)
|
64
97
|
{
|
65
98
|
VALUE probe;
|
66
99
|
|
@@ -78,10 +111,10 @@ int _dtrace_next_probe(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp, void *a
|
|
78
111
|
*/
|
79
112
|
VALUE dtrace_each_probe(VALUE self)
|
80
113
|
{
|
81
|
-
|
114
|
+
dtrace_handle_t *handle;
|
82
115
|
|
83
|
-
Data_Get_Struct(self,
|
84
|
-
(void) dtrace_probe_iter(handle, NULL, _dtrace_next_probe, NULL);
|
116
|
+
Data_Get_Struct(self, dtrace_handle_t, handle);
|
117
|
+
(void) dtrace_probe_iter(handle->hdl, NULL, _dtrace_next_probe, NULL);
|
85
118
|
|
86
119
|
return self;
|
87
120
|
}
|
@@ -97,7 +130,7 @@ VALUE dtrace_each_probe(VALUE self)
|
|
97
130
|
*/
|
98
131
|
VALUE dtrace_strcompile(int argc, VALUE *argv, VALUE self)
|
99
132
|
{
|
100
|
-
|
133
|
+
dtrace_handle_t *handle;
|
101
134
|
dtrace_prog_t *program;
|
102
135
|
VALUE dtrace_program;
|
103
136
|
|
@@ -112,6 +145,11 @@ VALUE dtrace_strcompile(int argc, VALUE *argv, VALUE self)
|
|
112
145
|
|
113
146
|
dtrace_argc = rb_ary_len(dtrace_argv_array);
|
114
147
|
dtrace_argv = ALLOC_N(char *, dtrace_argc + 1);
|
148
|
+
if (!dtrace_argv) {
|
149
|
+
rb_raise(eDtraceException, "alloc failed");
|
150
|
+
return Qnil;
|
151
|
+
}
|
152
|
+
|
115
153
|
for (i = 0; i < dtrace_argc; i++) {
|
116
154
|
dtrace_argv[i + 1] = STR2CSTR(rb_ary_entry(dtrace_argv_array, i));
|
117
155
|
}
|
@@ -119,18 +157,18 @@ VALUE dtrace_strcompile(int argc, VALUE *argv, VALUE self)
|
|
119
157
|
dtrace_argv[0] = "ruby";
|
120
158
|
dtrace_argc++;
|
121
159
|
|
122
|
-
Data_Get_Struct(self,
|
123
|
-
program = dtrace_program_strcompile(handle, STR2CSTR(dtrace_text),
|
160
|
+
Data_Get_Struct(self, dtrace_handle_t, handle);
|
161
|
+
program = dtrace_program_strcompile(handle->hdl, STR2CSTR(dtrace_text),
|
124
162
|
DTRACE_PROBESPEC_NAME, DTRACE_C_PSPEC,
|
125
163
|
dtrace_argc, dtrace_argv);
|
126
164
|
|
127
165
|
if (!program) {
|
128
|
-
rb_raise(eDtraceException, dtrace_errmsg(handle, dtrace_errno(handle)));
|
166
|
+
rb_raise(eDtraceException, dtrace_errmsg(handle->hdl, dtrace_errno(handle->hdl)));
|
129
167
|
return Qnil;
|
130
168
|
}
|
131
169
|
else {
|
132
170
|
dtrace_program = Data_Wrap_Struct(cDtraceProgram, 0, NULL, program);
|
133
|
-
rb_iv_set(dtrace_program, "@
|
171
|
+
rb_iv_set(dtrace_program, "@handle", self);
|
134
172
|
return dtrace_program;
|
135
173
|
}
|
136
174
|
}
|
@@ -143,11 +181,11 @@ VALUE dtrace_strcompile(int argc, VALUE *argv, VALUE self)
|
|
143
181
|
*/
|
144
182
|
VALUE dtrace_hdl_go(VALUE self)
|
145
183
|
{
|
146
|
-
|
184
|
+
dtrace_handle_t *handle;
|
147
185
|
|
148
|
-
Data_Get_Struct(self,
|
149
|
-
if (dtrace_go(handle) < 0)
|
150
|
-
rb_raise(eDtraceException, dtrace_errmsg(handle, dtrace_errno(handle)));
|
186
|
+
Data_Get_Struct(self, dtrace_handle_t, handle);
|
187
|
+
if (dtrace_go(handle->hdl) < 0)
|
188
|
+
rb_raise(eDtraceException, dtrace_errmsg(handle->hdl, dtrace_errno(handle->hdl)));
|
151
189
|
|
152
190
|
return Qnil;
|
153
191
|
}
|
@@ -163,12 +201,12 @@ VALUE dtrace_hdl_go(VALUE self)
|
|
163
201
|
*/
|
164
202
|
VALUE dtrace_hdl_status(VALUE self)
|
165
203
|
{
|
166
|
-
|
204
|
+
dtrace_handle_t *handle;
|
167
205
|
int status;
|
168
206
|
|
169
|
-
Data_Get_Struct(self,
|
170
|
-
if ((status = dtrace_status(handle)) < 0)
|
171
|
-
rb_raise(eDtraceException, dtrace_errmsg(handle, dtrace_errno(handle)));
|
207
|
+
Data_Get_Struct(self, dtrace_handle_t, handle);
|
208
|
+
if ((status = dtrace_status(handle->hdl)) < 0)
|
209
|
+
rb_raise(eDtraceException, dtrace_errmsg(handle->hdl, dtrace_errno(handle->hdl)));
|
172
210
|
|
173
211
|
return INT2FIX(status);
|
174
212
|
}
|
@@ -183,20 +221,20 @@ VALUE dtrace_hdl_status(VALUE self)
|
|
183
221
|
*/
|
184
222
|
VALUE dtrace_hdl_setopt(VALUE self, VALUE key, VALUE value)
|
185
223
|
{
|
186
|
-
|
224
|
+
dtrace_handle_t *handle;
|
187
225
|
int ret;
|
188
226
|
|
189
|
-
Data_Get_Struct(self,
|
190
|
-
|
227
|
+
Data_Get_Struct(self, dtrace_handle_t, handle);
|
228
|
+
|
191
229
|
if (NIL_P(value)) {
|
192
|
-
ret = dtrace_setopt(handle, STR2CSTR(key), 0);
|
230
|
+
ret = dtrace_setopt(handle->hdl, STR2CSTR(key), 0);
|
193
231
|
}
|
194
232
|
else {
|
195
|
-
ret = dtrace_setopt(handle, STR2CSTR(key), STR2CSTR(value));
|
233
|
+
ret = dtrace_setopt(handle->hdl, STR2CSTR(key), STR2CSTR(value));
|
196
234
|
}
|
197
235
|
|
198
236
|
if (ret < 0)
|
199
|
-
rb_raise(eDtraceException, dtrace_errmsg(handle, dtrace_errno(handle)));
|
237
|
+
rb_raise(eDtraceException, dtrace_errmsg(handle->hdl, dtrace_errno(handle->hdl)));
|
200
238
|
|
201
239
|
return Qnil;
|
202
240
|
}
|
@@ -207,11 +245,11 @@ VALUE dtrace_hdl_setopt(VALUE self, VALUE key, VALUE value)
|
|
207
245
|
*/
|
208
246
|
VALUE dtrace_hdl_stop(VALUE self)
|
209
247
|
{
|
210
|
-
|
248
|
+
dtrace_handle_t *handle;
|
211
249
|
|
212
|
-
Data_Get_Struct(self,
|
213
|
-
if (dtrace_stop(handle) < 0)
|
214
|
-
rb_raise(eDtraceException, dtrace_errmsg(handle, dtrace_errno(handle)));
|
250
|
+
Data_Get_Struct(self, dtrace_handle_t, handle);
|
251
|
+
if (dtrace_stop(handle->hdl) < 0)
|
252
|
+
rb_raise(eDtraceException, dtrace_errmsg(handle->hdl, dtrace_errno(handle->hdl)));
|
215
253
|
|
216
254
|
return Qnil;
|
217
255
|
}
|
@@ -221,11 +259,11 @@ VALUE dtrace_hdl_stop(VALUE self)
|
|
221
259
|
*/
|
222
260
|
VALUE dtrace_hdl_error(VALUE self)
|
223
261
|
{
|
224
|
-
|
262
|
+
dtrace_handle_t *handle;
|
225
263
|
const char *error_string;
|
226
264
|
|
227
|
-
Data_Get_Struct(self,
|
228
|
-
error_string = dtrace_errmsg(handle, dtrace_errno(handle));
|
265
|
+
Data_Get_Struct(self, dtrace_handle_t, handle);
|
266
|
+
error_string = dtrace_errmsg(handle->hdl, dtrace_errno(handle->hdl));
|
229
267
|
return rb_str_new2(error_string);
|
230
268
|
}
|
231
269
|
|
@@ -235,10 +273,10 @@ VALUE dtrace_hdl_error(VALUE self)
|
|
235
273
|
*/
|
236
274
|
VALUE dtrace_hdl_sleep(VALUE self)
|
237
275
|
{
|
238
|
-
|
276
|
+
dtrace_handle_t *handle;
|
239
277
|
|
240
|
-
Data_Get_Struct(self,
|
241
|
-
dtrace_sleep(handle);
|
278
|
+
Data_Get_Struct(self, dtrace_handle_t, handle);
|
279
|
+
dtrace_sleep(handle->hdl);
|
242
280
|
return Qnil;
|
243
281
|
}
|
244
282
|
|
@@ -317,26 +355,31 @@ static int _buf_consumer(const dtrace_bufdata_t *bufdata, void *arg)
|
|
317
355
|
*/
|
318
356
|
VALUE dtrace_hdl_work(int argc, VALUE *argv, VALUE self)
|
319
357
|
{
|
320
|
-
|
358
|
+
dtrace_handle_t *handle;
|
321
359
|
dtrace_workstatus_t status;
|
322
360
|
dtrace_work_handlers_t handlers;
|
323
|
-
VALUE
|
324
|
-
VALUE
|
361
|
+
VALUE probe_consumer;
|
362
|
+
VALUE rec_consumer;
|
325
363
|
|
326
|
-
Data_Get_Struct(self,
|
364
|
+
Data_Get_Struct(self, dtrace_handle_t, handle);
|
327
365
|
|
328
366
|
/* handle args - probe_consumer_proc is mandatory, rec_consumer_proc
|
329
367
|
is optional */
|
330
|
-
rb_scan_args(argc, argv, "11", &
|
368
|
+
rb_scan_args(argc, argv, "11", &probe_consumer, &rec_consumer);
|
369
|
+
|
370
|
+
/* to mark during GC */
|
371
|
+
handle->probe = probe_consumer;
|
372
|
+
if (!NIL_P(rec_consumer))
|
373
|
+
handle->rec = rec_consumer;
|
331
374
|
|
332
375
|
/* fill out the handlers struct */
|
333
|
-
handlers.probe =
|
334
|
-
handlers.rec =
|
376
|
+
handlers.probe = probe_consumer;
|
377
|
+
handlers.rec = rec_consumer;
|
335
378
|
handlers.handle = self;
|
336
379
|
|
337
|
-
status = dtrace_work(handle, NULL, _probe_consumer, _rec_consumer, &handlers);
|
380
|
+
status = dtrace_work(handle->hdl, NULL, _probe_consumer, _rec_consumer, &handlers);
|
338
381
|
if (status < 0)
|
339
|
-
rb_raise(eDtraceException, (dtrace_errmsg(handle, dtrace_errno(handle))));
|
382
|
+
rb_raise(eDtraceException, (dtrace_errmsg(handle->hdl, dtrace_errno(handle->hdl))));
|
340
383
|
|
341
384
|
return INT2FIX(status);
|
342
385
|
}
|
@@ -346,12 +389,100 @@ VALUE dtrace_hdl_work(int argc, VALUE *argv, VALUE self)
|
|
346
389
|
*/
|
347
390
|
VALUE dtrace_hdl_buf_consumer(VALUE self, VALUE buf_consumer)
|
348
391
|
{
|
349
|
-
|
350
|
-
Data_Get_Struct(self,
|
392
|
+
dtrace_handle_t *handle;
|
393
|
+
Data_Get_Struct(self, dtrace_handle_t, handle);
|
394
|
+
|
395
|
+
/* to mark during GC */
|
396
|
+
handle->buf = buf_consumer;
|
351
397
|
|
352
398
|
/* attach the buffered output handler */
|
353
|
-
if (dtrace_handle_buffered(handle, &_buf_consumer, (void *)buf_consumer) == -1) {
|
354
|
-
rb_raise(eDtraceException, "failed to establish buffered handler"
|
399
|
+
if (dtrace_handle_buffered(handle->hdl, &_buf_consumer, (void *)buf_consumer) == -1) {
|
400
|
+
rb_raise(eDtraceException, "failed to establish buffered handler: %s",
|
401
|
+
(dtrace_errmsg(handle->hdl, dtrace_errno(handle->hdl))));
|
402
|
+
}
|
403
|
+
|
404
|
+
return Qnil;
|
405
|
+
}
|
406
|
+
|
407
|
+
static int _drop_consumer(const dtrace_dropdata_t *dropdata, void *arg)
|
408
|
+
{
|
409
|
+
VALUE proc;
|
410
|
+
VALUE dtracedropdata;
|
411
|
+
|
412
|
+
proc = (VALUE)arg;
|
413
|
+
|
414
|
+
if (!NIL_P(proc)) {
|
415
|
+
dtracedropdata = Data_Wrap_Struct(cDtraceDropData, 0, NULL, (dtrace_dropdata_t *)dropdata);
|
416
|
+
rb_funcall(proc, rb_intern("call"), 1, dtracedropdata);
|
417
|
+
}
|
418
|
+
|
419
|
+
return (DTRACE_HANDLE_OK);
|
420
|
+
}
|
421
|
+
|
422
|
+
/*
|
423
|
+
* Set up the drop-record handler for this handle. Takes a block,
|
424
|
+
* which will be called with any drop records returned by DTrace,
|
425
|
+
* represented by DtraceDropData objects.
|
426
|
+
*/
|
427
|
+
VALUE dtrace_hdl_drop_consumer(VALUE self, VALUE drop_consumer)
|
428
|
+
{
|
429
|
+
dtrace_handle_t *handle;
|
430
|
+
Data_Get_Struct(self, dtrace_handle_t, handle);
|
431
|
+
|
432
|
+
/* to mark during GC */
|
433
|
+
handle->drop = drop_consumer;
|
434
|
+
|
435
|
+
/* attach the drop-record handler */
|
436
|
+
if (dtrace_handle_drop(handle->hdl, &_drop_consumer, (void *)drop_consumer) == -1) {
|
437
|
+
rb_raise(eDtraceException, "failed to establish drop-record handler");
|
438
|
+
}
|
439
|
+
|
440
|
+
return Qnil;
|
441
|
+
}
|
442
|
+
|
443
|
+
static int _err_consumer(const dtrace_errdata_t *errdata, void *arg)
|
444
|
+
{
|
445
|
+
VALUE proc;
|
446
|
+
VALUE dtraceerrdata;
|
447
|
+
|
448
|
+
proc = (VALUE)arg;
|
449
|
+
|
450
|
+
/* guard against bad invocations where arg is not what we provided... */
|
451
|
+
if (TYPE(proc) == T_DATA) {
|
452
|
+
dtraceerrdata = Data_Wrap_Struct(cDtraceErrData, 0, NULL, (dtrace_errdata_t *)errdata);
|
453
|
+
rb_funcall(proc, rb_intern("call"), 1, dtraceerrdata);
|
454
|
+
}
|
455
|
+
else {
|
456
|
+
/* arg looked bad, throw an exception */
|
457
|
+
rb_raise(eDtraceException, "bad argument to _err_consumer: %p -> 0x%x type 0x%x\n", arg, proc, TYPE(proc));
|
458
|
+
}
|
459
|
+
|
460
|
+
return (DTRACE_HANDLE_OK);
|
461
|
+
}
|
462
|
+
|
463
|
+
/*
|
464
|
+
* Set up the err-record handler for this handle. Takes a block, which
|
465
|
+
* will be called with any error records returned by DTrace,
|
466
|
+
* represented by DTraceErrData records.
|
467
|
+
*/
|
468
|
+
VALUE dtrace_hdl_err_consumer(VALUE self, VALUE err_consumer)
|
469
|
+
{
|
470
|
+
dtrace_handle_t *handle;
|
471
|
+
void *arg;
|
472
|
+
Data_Get_Struct(self, dtrace_handle_t, handle);
|
473
|
+
|
474
|
+
if (dtrace_status(handle->hdl) != 0) {
|
475
|
+
rb_raise(eDtraceException, "too late to add error handler");
|
476
|
+
return Qnil;
|
477
|
+
}
|
478
|
+
|
479
|
+
/* to mark during GC */
|
480
|
+
handle->err = err_consumer;
|
481
|
+
|
482
|
+
/* attach the err-record handler */
|
483
|
+
if (dtrace_handle_err(handle->hdl, &_err_consumer, (void *)err_consumer) == -1) {
|
484
|
+
rb_raise(eDtraceException, "failed to establish err-record handler: %s",
|
485
|
+
dtrace_errmsg(handle->hdl, dtrace_errno(handle->hdl)));
|
355
486
|
}
|
356
487
|
|
357
488
|
return Qnil;
|
@@ -369,7 +500,7 @@ VALUE dtrace_hdl_buf_consumer(VALUE self, VALUE buf_consumer)
|
|
369
500
|
*/
|
370
501
|
VALUE dtrace_hdl_createprocess(VALUE self, VALUE rb_argv)
|
371
502
|
{
|
372
|
-
|
503
|
+
dtrace_handle_t *handle;
|
373
504
|
struct ps_prochandle *P;
|
374
505
|
char **argv;
|
375
506
|
long len;
|
@@ -377,25 +508,34 @@ VALUE dtrace_hdl_createprocess(VALUE self, VALUE rb_argv)
|
|
377
508
|
VALUE dtraceprocess;
|
378
509
|
dtrace_process_t *process;
|
379
510
|
|
380
|
-
Data_Get_Struct(self,
|
511
|
+
Data_Get_Struct(self, dtrace_handle_t, handle);
|
381
512
|
|
382
513
|
len = rb_ary_len(rb_argv);
|
383
514
|
argv = ALLOC_N(char *, len + 1);
|
515
|
+
if (!argv) {
|
516
|
+
rb_raise(eDtraceException, "alloc failed");
|
517
|
+
return Qnil;
|
518
|
+
}
|
384
519
|
|
385
520
|
for (i = 0; i < len; i++) {
|
386
521
|
argv[i] = STR2CSTR(rb_ary_entry(rb_argv, i));
|
387
522
|
}
|
388
523
|
argv[len] = NULL;
|
389
524
|
|
390
|
-
P = dtrace_proc_create(handle, argv[0], argv);
|
525
|
+
P = dtrace_proc_create(handle->hdl, argv[0], argv);
|
391
526
|
free(argv);
|
392
527
|
|
393
528
|
if (P == NULL) {
|
394
|
-
rb_raise(eDtraceException, dtrace_errmsg(handle, dtrace_errno(handle)));
|
529
|
+
rb_raise(eDtraceException, dtrace_errmsg(handle->hdl, dtrace_errno(handle->hdl)));
|
395
530
|
}
|
396
531
|
|
397
532
|
process = ALLOC(dtrace_process_t);
|
398
|
-
process
|
533
|
+
if (!process) {
|
534
|
+
rb_raise(eDtraceException, "alloc failed");
|
535
|
+
return Qnil;
|
536
|
+
}
|
537
|
+
|
538
|
+
process->handle = handle->hdl;
|
399
539
|
process->proc = P;
|
400
540
|
|
401
541
|
dtraceprocess = Data_Wrap_Struct(cDtraceProcess, 0, dtrace_process_release, (dtrace_process_t *)process);
|
@@ -410,21 +550,26 @@ VALUE dtrace_hdl_createprocess(VALUE self, VALUE rb_argv)
|
|
410
550
|
*/
|
411
551
|
VALUE dtrace_hdl_grabprocess(VALUE self, VALUE pid)
|
412
552
|
{
|
413
|
-
|
553
|
+
dtrace_handle_t *handle;
|
414
554
|
struct ps_prochandle *P;
|
415
555
|
dtrace_process_t *process;
|
416
556
|
VALUE dtraceprocess;
|
417
557
|
|
418
|
-
Data_Get_Struct(self,
|
558
|
+
Data_Get_Struct(self, dtrace_handle_t, handle);
|
419
559
|
|
420
|
-
P = dtrace_proc_grab(handle, FIX2INT(pid), 0);
|
560
|
+
P = dtrace_proc_grab(handle->hdl, FIX2INT(pid), 0);
|
421
561
|
|
422
562
|
if (P == NULL) {
|
423
|
-
rb_raise(eDtraceException, dtrace_errmsg(handle, dtrace_errno(handle)));
|
563
|
+
rb_raise(eDtraceException, dtrace_errmsg(handle->hdl, dtrace_errno(handle->hdl)));
|
424
564
|
}
|
425
565
|
|
426
566
|
process = ALLOC(dtrace_process_t);
|
427
|
-
process
|
567
|
+
if (!process) {
|
568
|
+
rb_raise(eDtraceException, "alloc failed");
|
569
|
+
return Qnil;
|
570
|
+
}
|
571
|
+
|
572
|
+
process->handle = handle->hdl;
|
428
573
|
process->proc = P;
|
429
574
|
|
430
575
|
dtraceprocess = Data_Wrap_Struct(cDtraceProcess, 0, dtrace_process_release, (dtrace_process_t *)process);
|