ruby-dtrace 0.0.4 → 0.0.5
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 +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);
|