ruby-dtrace 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,3 @@
1
+ == 0.0.1 / 2007-12-01
2
+
3
+ * Initial public release.
data/Manifest.txt ADDED
@@ -0,0 +1,28 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ ext/dtrace_aggregate.c
6
+ ext/dtrace_api.c
7
+ ext/dtrace_api.h
8
+ ext/dtrace_hdl.c
9
+ ext/dtrace_probe.c
10
+ ext/dtrace_program.c
11
+ ext/dtrace_programinfo.c
12
+ ext/dtrace_recdesc.c
13
+ ext/extconf.rb
14
+ lib/dtrace.rb
15
+ plugin/dtrace/README
16
+ plugin/dtrace/Rakefile
17
+ plugin/dtrace/bin/dtracer.rb
18
+ plugin/dtrace/init.rb
19
+ plugin/dtrace/lib/dtrace_helper.rb
20
+ plugin/dtrace/lib/dtrace_report.rb
21
+ plugin/dtrace/lib/dtrace_tracer.rb
22
+ plugin/dtrace/lib/dtracer.rb
23
+ plugin/dtrace/lib/dtracer_client.rb
24
+ plugin/dtrace/public/stylesheets/dtrace.css
25
+ plugin/dtrace/tasks/dtrace.rake
26
+ plugin/dtrace/test/dtrace_test.rb
27
+ plugin/dtrace/views/dtrace/_report.rhtml
28
+ test/test_dtrace.rb
data/README.txt ADDED
@@ -0,0 +1,60 @@
1
+ ruby-dtrace is Ruby bindings for Dtrace, which lets you write D-based
2
+ programs in Ruby. It doesn't provide D probes for Ruby, but you can
3
+ use it with the probes found in the Joyent and Apple builds of Ruby.
4
+
5
+ == FEATURES
6
+
7
+ * Access to the D API
8
+ * Probe metadata
9
+ * Run D programs
10
+ * Access aggregates
11
+
12
+ == SYNOPSIS
13
+
14
+ t = Dtrace.new
15
+ dprog = "ruby*:::function-entry{ @[copyinstr(arg1)] = count(); }"
16
+ prog = t.compile dprog
17
+ prog.execute
18
+ t.go
19
+
20
+ [...]
21
+
22
+ t.stop
23
+ t.aggregate_snap
24
+ t.each_aggregate do |agg|
25
+ (0..(agg.num_records - 1)).each do |i|
26
+ rec = agg[i]
27
+ end
28
+ end
29
+
30
+ == REQUIREMENTS
31
+
32
+ * A platform with Dtrace support (OpenSolaris, Mac OS X 10.5 Leopard tested, possibly also FreeBSD).
33
+ * root, or some/all of the dtrace privileges on Solaris: dtrace_user, dtrace_proc and dtrace_kernel.
34
+
35
+ == INSTALL
36
+
37
+ $ sudo gem install ruby-dtrace
38
+
39
+ == LICENSE
40
+
41
+ Copyright (c) 2007 Chris Andrews <chris@nodnol.org>
42
+
43
+ Permission is hereby granted, free of charge, to any person obtaining
44
+ a copy of this software and associated documentation files (the
45
+ 'Software'), to deal in the Software without restriction, including
46
+ without limitation the rights to use, copy, modify, merge, publish,
47
+ distribute, sublicense, and/or sell copies of the Software, and to
48
+ permit persons to whom the Software is furnished to do so, subject to
49
+ the following conditions:
50
+
51
+ The above copyright notice and this permission notice shall be
52
+ included in all copies or substantial portions of the Software.
53
+
54
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
55
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
56
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
57
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
58
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
59
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
60
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,30 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ require './lib/dtrace'
6
+
7
+ Hoe.new('ruby-dtrace', Dtrace::VERSION) do |p|
8
+ p.rubyforge_name = 'ruby-dtrace'
9
+ p.author = 'Chris Andrews'
10
+ p.email = 'chris@nodnol.org'
11
+ p.summary = 'Ruby bindings for libdtrace'
12
+ p.description = <<EOD
13
+ ruby-dtrace is Ruby bindings for Dtrace, which lets you write D-based
14
+ programs in Ruby. It doesn't provide D probes for Ruby, but you can
15
+ use it with the probes found in the Joyent and Apple builds of Ruby.
16
+ EOD
17
+ p.spec_extras = {:extensions => ['ext/extconf.rb']}
18
+ p.url = "http://ruby-dtrace.rubyforge.org/"
19
+ p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
20
+ end
21
+
22
+ desc "Uses extconf.rb and make to build the extension"
23
+ task :extensions do
24
+ Dir.chdir('ext')
25
+ system("ruby extconf.rb")
26
+ system("make")
27
+ Dir.chdir('..')
28
+ end
29
+
30
+ # vim: syntax=Ruby
@@ -0,0 +1,150 @@
1
+ /* Ruby-Dtrace
2
+ * (c) 2007 Chris Andrews <chris@nodnol.org>
3
+ */
4
+
5
+ #include "dtrace_api.h"
6
+
7
+ RUBY_EXTERN VALUE cDtraceProbe;
8
+ RUBY_EXTERN VALUE cDtraceRecDesc;
9
+
10
+ /* :nodoc: */
11
+ VALUE dtraceaggdata_init(VALUE self)
12
+ {
13
+ dtrace_aggdata_t *aggdata;
14
+
15
+ Data_Get_Struct(self, dtrace_aggdata_t, aggdata);
16
+ return self;
17
+ }
18
+
19
+ /*
20
+ * Returns the description of this aggregate.
21
+ */
22
+ VALUE dtraceaggdata_desc(VALUE self)
23
+ {
24
+ VALUE string;
25
+ dtrace_aggdata_t *aggdata;
26
+ dtrace_aggdesc_t *aggdesc;
27
+ dtrace_recdesc_t *nrec, *irec;
28
+ char *name, c[256];
29
+
30
+ Data_Get_Struct(self, dtrace_aggdata_t, aggdata);
31
+
32
+ aggdesc = aggdata->dtada_desc;
33
+ nrec = &aggdesc->dtagd_rec[1];
34
+ irec = &aggdesc->dtagd_rec[2];
35
+
36
+ name = aggdata->dtada_data + nrec->dtrd_offset;
37
+ string = rb_str_new2(name);
38
+ return string;
39
+ }
40
+
41
+ /*
42
+ * Returns the value of this aggregate.
43
+ */
44
+ VALUE dtraceaggdata_value(VALUE self)
45
+ {
46
+ dtrace_aggdata_t *aggdata;
47
+ dtrace_aggdesc_t *aggdesc;
48
+ dtrace_recdesc_t *nrec, *irec;
49
+
50
+ Data_Get_Struct(self, dtrace_aggdata_t, aggdata);
51
+
52
+ aggdesc = aggdata->dtada_desc;
53
+ nrec = &aggdesc->dtagd_rec[1];
54
+ irec = &aggdesc->dtagd_rec[2];
55
+
56
+ uint64_t n = *((uint64_t *)(aggdata->dtada_data + irec->dtrd_offset));
57
+
58
+ return INT2FIX(n);
59
+ }
60
+
61
+ /*
62
+ * Returns the size of this aggregate.
63
+ */
64
+ VALUE dtraceaggdata_size(VALUE self)
65
+ {
66
+ dtrace_aggdata_t *aggdata;
67
+
68
+ Data_Get_Struct(self, dtrace_aggdata_t, aggdata);
69
+
70
+ return INT2FIX(aggdata->dtada_size);
71
+ }
72
+
73
+ /*
74
+ * Yields each record for this aggregate.
75
+ */
76
+ VALUE dtraceaggdata_each_record(VALUE self)
77
+ {
78
+ VALUE dtracerecdesc;
79
+ dtrace_aggdata_t *aggdata;
80
+ dtrace_aggdesc_t *aggdesc;
81
+ dtrace_recdesc_t *rec;
82
+ int i;
83
+ caddr_t data;
84
+
85
+ Data_Get_Struct(self, dtrace_aggdata_t, aggdata);
86
+ aggdesc = aggdata->dtada_desc;
87
+
88
+ for (i = 0; i < aggdesc->dtagd_nrecs; i++) {
89
+ rec = &aggdesc->dtagd_rec[i];
90
+ dtracerecdesc = Data_Wrap_Struct(cDtraceRecDesc, 0, NULL, rec);
91
+ rb_iv_set(dtracerecdesc, "@aggdata", self);
92
+ rb_yield(dtracerecdesc);
93
+ }
94
+
95
+ return Qnil;
96
+ }
97
+
98
+ /*
99
+ * Return the number of records in this aggregate.
100
+ */
101
+ VALUE dtraceaggdata_num_records(VALUE self)
102
+ {
103
+ VALUE dtracerecdesc;
104
+ dtrace_aggdata_t *aggdata;
105
+ dtrace_aggdesc_t *aggdesc;
106
+
107
+ Data_Get_Struct(self, dtrace_aggdata_t, aggdata);
108
+ aggdesc = aggdata->dtada_desc;
109
+
110
+ return INT2FIX(aggdesc->dtagd_nrecs);
111
+ }
112
+
113
+ /*
114
+ * Access the array of records in this aggregate.
115
+ */
116
+ VALUE dtraceaggdata_record(VALUE self, VALUE index)
117
+ {
118
+ VALUE dtracerecdesc;
119
+ dtrace_aggdata_t *aggdata;
120
+ dtrace_aggdesc_t *aggdesc;
121
+ dtrace_recdesc_t *rec;
122
+ int i;
123
+
124
+ Data_Get_Struct(self, dtrace_aggdata_t, aggdata);
125
+ aggdesc = aggdata->dtada_desc;
126
+
127
+ i = FIX2INT(index);
128
+ if (i >= aggdesc->dtagd_nrecs)
129
+ return Qnil;
130
+ else {
131
+ rec = &aggdesc->dtagd_rec[i];
132
+ dtracerecdesc = Data_Wrap_Struct(cDtraceRecDesc, 0, NULL, rec);
133
+ rb_iv_set(dtracerecdesc, "@aggdata", self);
134
+ return dtracerecdesc;
135
+ }
136
+ }
137
+
138
+ /*
139
+ * Return the probe associated with this aggregate.
140
+ */
141
+ VALUE dtraceaggdata_probe(VALUE self)
142
+ {
143
+ VALUE probe;
144
+ dtrace_aggdata_t *aggdata;
145
+
146
+ Data_Get_Struct(self, dtrace_aggdata_t, aggdata);
147
+ probe = Data_Wrap_Struct(cDtraceProbe, 0, NULL, (dtrace_probedesc_t *)aggdata->dtada_pdesc);
148
+
149
+ return probe;
150
+ }
data/ext/dtrace_api.c ADDED
@@ -0,0 +1,69 @@
1
+ /* Ruby-Dtrace
2
+ * (c) 2007 Chris Andrews <chris@nodnol.org>
3
+ */
4
+
5
+ #include "dtrace_api.h"
6
+
7
+ VALUE cDtrace;
8
+ VALUE cDtraceProbe;
9
+ VALUE cDtraceProgram;
10
+ VALUE cDtraceProgramInfo;
11
+ VALUE cDtraceAggData;
12
+ VALUE cDtraceRecDesc;
13
+
14
+ VALUE eDtraceException;
15
+
16
+ void Init_dtrace_api() {
17
+
18
+ cDtrace = rb_define_class("Dtrace", rb_cObject);
19
+ rb_define_method(cDtrace, "initialize", dtrace_init, 0); // in dtrace_hdl.c
20
+ rb_define_method(cDtrace, "each_probe", dtrace_each_probe, 0); // in dtrace_hdl.c
21
+ rb_define_method(cDtrace, "compile", dtrace_strcompile, -1); // in dtrace_hdl.c
22
+ rb_define_method(cDtrace, "stop", dtrace_hdl_stop, 0); // in dtrace_hdl.c
23
+ rb_define_method(cDtrace, "status", dtrace_hdl_status, 0); // in dtrace_hdl.c
24
+ rb_define_method(cDtrace, "go", dtrace_hdl_go, 0); // in dtrace_hdl.c
25
+ rb_define_method(cDtrace, "each_aggregate", dtrace_hdl_each_aggregate, 0); // in dtrace_hdl.c
26
+ rb_define_method(cDtrace, "aggregate_print", dtrace_hdl_aggregate_print, 0); // in dtrace_hdl.c
27
+ rb_define_method(cDtrace, "aggregate_snap", dtrace_hdl_aggregate_snap, 0); // in dtrace_hdl.c
28
+ rb_define_method(cDtrace, "aggregate_clear", dtrace_hdl_aggregate_clear, 0); // in dtrace_hdl.c
29
+ rb_define_method(cDtrace, "error", dtrace_hdl_error, 0); // in dtrace_hdl.c
30
+ rb_define_method(cDtrace, "setopt", dtrace_hdl_setopt, 2); // in dtrace_hdl.c
31
+ rb_define_alloc_func(cDtrace, dtrace_hdl_alloc);
32
+
33
+ cDtraceProbe = rb_define_class("DtraceProbe", rb_cObject);
34
+ rb_define_method(cDtraceProbe, "initialize", dtraceprobe_init, 0); // in dtrace_probe.c
35
+ rb_define_method(cDtraceProbe, "probe_id", dtraceprobe_probe_id, 0); // in dtrace_probe.c
36
+ rb_define_method(cDtraceProbe, "provider", dtraceprobe_provider, 0); // in dtrace_probe.c
37
+ rb_define_method(cDtraceProbe, "mod", dtraceprobe_mod, 0); // in dtrace_probe.c
38
+ rb_define_method(cDtraceProbe, "func", dtraceprobe_func, 0); // in dtrace_probe.c
39
+ rb_define_method(cDtraceProbe, "name", dtraceprobe_name, 0); // in dtrace_probe.c
40
+
41
+ cDtraceProgram = rb_define_class("DtraceProgram", rb_cObject);
42
+ rb_define_method(cDtraceProgram, "initialize", dtraceprogram_init, 0); // in dtrace_program.c
43
+ rb_define_method(cDtraceProgram, "execute", dtraceprogram_exec, 0); // in dtrace_program.c
44
+ rb_define_method(cDtraceProgram, "info", dtraceprogram_info, 0); // in dtrace_program.c
45
+
46
+ cDtraceProgramInfo = rb_define_class("DtraceProgramInfo", rb_cObject);
47
+ rb_define_method(cDtraceProgramInfo, "initialize", dtraceprograminfo_init, 0); // in dtrace_programinfo.c
48
+ rb_define_method(cDtraceProgramInfo, "aggregates_count", dtraceprograminfo_aggregates_count, 0); // in dtrace_programinfo.c
49
+ rb_define_method(cDtraceProgramInfo, "recgens_count", dtraceprograminfo_recgens_count, 0); // in dtrace_programinfo.c
50
+ rb_define_method(cDtraceProgramInfo, "matches_count", dtraceprograminfo_matches_count, 0); // in dtrace_programinfo.c
51
+ rb_define_method(cDtraceProgramInfo, "speculations_count", dtraceprograminfo_speculations_count, 0); // in dtrace_programinfo.c
52
+
53
+ cDtraceAggData = rb_define_class("DtraceAggData", rb_cObject);
54
+ rb_define_method(cDtraceAggData, "initialize", dtraceaggdata_init, 0); // in dtrace_aggregate.c
55
+ rb_define_method(cDtraceAggData, "desc", dtraceaggdata_desc, 0); // in dtrace_aggregate.c
56
+ rb_define_method(cDtraceAggData, "value", dtraceaggdata_value, 0); // in dtrace_aggregate.c
57
+ rb_define_method(cDtraceAggData, "size", dtraceaggdata_size, 0); // in dtrace_aggregate.c
58
+ rb_define_method(cDtraceAggData, "each_record", dtraceaggdata_each_record, 0); // in dtrace_aggregate.c
59
+ rb_define_method(cDtraceAggData, "num_records", dtraceaggdata_num_records, 0); // in dtrace_aggregate.c
60
+ rb_define_method(cDtraceAggData, "[]", dtraceaggdata_record, 1); // in dtrace_aggregate.c
61
+ rb_define_method(cDtraceAggData, "probe", dtraceaggdata_probe, 0); // in dtrace_aggregate.c
62
+
63
+ cDtraceRecDesc = rb_define_class("DtraceRecDesc", rb_cObject);
64
+ rb_define_method(cDtraceRecDesc, "initialize", dtracerecdesc_init, 0); // in dtrace_recdesc.c
65
+ rb_define_method(cDtraceRecDesc, "data", dtracerecdesc_data, 0); // in dtrace_recdesc.c
66
+
67
+ eDtraceException = rb_define_class("DtraceException", rb_eStandardError);
68
+ }
69
+
data/ext/dtrace_api.h ADDED
@@ -0,0 +1,53 @@
1
+ /* Ruby-Dtrace
2
+ * (c) 2007 Chris Andrews <chris@nodnol.org>
3
+ */
4
+
5
+ /* this is a full path because the ruby-dtrace probes add a "dtrace.h"
6
+ * in the same directory as ruby.h, and we must avoid loading that...
7
+ */
8
+ #include "/usr/include/dtrace.h"
9
+ #include "ruby.h"
10
+
11
+ VALUE dtraceaggdata_init(VALUE self);
12
+ VALUE dtraceaggdata_desc(VALUE self);
13
+ VALUE dtraceaggdata_value(VALUE self);
14
+ VALUE dtraceaggdata_size(VALUE self);
15
+ VALUE dtraceaggdata_each_record(VALUE self);
16
+ VALUE dtraceaggdata_num_records(VALUE self);
17
+ VALUE dtraceaggdata_record(VALUE self, VALUE index);
18
+ VALUE dtraceaggdata_probe(VALUE self);
19
+
20
+ void dtrace_hdl_free (void *handle);
21
+ VALUE dtrace_hdl_alloc(VALUE klass);
22
+ VALUE dtrace_init(VALUE self);
23
+ VALUE dtrace_each_probe(VALUE self);
24
+ VALUE dtrace_strcompile(int argc, VALUE *argv, VALUE self);
25
+ VALUE dtrace_hdl_go(VALUE self);
26
+ VALUE dtrace_hdl_status(VALUE self);
27
+ VALUE dtrace_hdl_setopt(VALUE self, VALUE key, VALUE value);
28
+ VALUE dtrace_hdl_stop(VALUE self);
29
+ VALUE dtrace_hdl_each_aggregate(VALUE self);
30
+ VALUE dtrace_hdl_aggregate_print(VALUE self);
31
+ VALUE dtrace_hdl_aggregate_snap(VALUE self);
32
+ VALUE dtrace_hdl_aggregate_clear(VALUE self);
33
+ VALUE dtrace_hdl_error(VALUE self);
34
+
35
+ VALUE dtraceprobe_init(VALUE self);
36
+ VALUE dtraceprobe_probe_id(VALUE self);
37
+ VALUE dtraceprobe_provider(VALUE self);
38
+ VALUE dtraceprobe_mod(VALUE self);
39
+ VALUE dtraceprobe_func(VALUE self);
40
+ VALUE dtraceprobe_name(VALUE self);
41
+
42
+ VALUE dtraceprogram_init(VALUE self);
43
+ VALUE dtraceprogram_exec(VALUE self);
44
+ VALUE dtraceprogram_info(VALUE self);
45
+
46
+ VALUE dtraceprograminfo_init(VALUE self);
47
+ VALUE dtraceprograminfo_aggregates_count(VALUE self);
48
+ VALUE dtraceprograminfo_recgens_count(VALUE self);
49
+ VALUE dtraceprograminfo_matches_count(VALUE self);
50
+ VALUE dtraceprograminfo_speculations_count(VALUE self);
51
+
52
+ VALUE dtracerecdesc_init(VALUE self);
53
+ VALUE dtracerecdesc_data(VALUE self);
data/ext/dtrace_hdl.c ADDED
@@ -0,0 +1,280 @@
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
+ RUBY_EXTERN VALUE cDtraceProbe;
9
+ RUBY_EXTERN VALUE cDtraceProgram;
10
+ RUBY_EXTERN VALUE cDtraceAggData;
11
+
12
+ void dtrace_hdl_free (void *handle)
13
+ {
14
+ dtrace_close(handle);
15
+ }
16
+
17
+ VALUE dtrace_hdl_alloc(VALUE klass)
18
+ {
19
+ dtrace_hdl_t *handle;
20
+ int err;
21
+ VALUE obj;
22
+
23
+ handle = dtrace_open(DTRACE_VERSION, 0, &err);
24
+
25
+ if (handle) {
26
+ obj = Data_Wrap_Struct(klass, 0, dtrace_hdl_free, handle);
27
+ return obj;
28
+ }
29
+ else {
30
+ rb_raise(eDtraceException, "unable to open dtrace (not root?)");
31
+ }
32
+ }
33
+
34
+ /* :nodoc: */
35
+ VALUE dtrace_init(VALUE self)
36
+ {
37
+ dtrace_hdl_t *handle;
38
+
39
+ Data_Get_Struct(self, dtrace_hdl_t, handle);
40
+ if (handle)
41
+ return self;
42
+ else
43
+ return Qnil;
44
+ }
45
+
46
+ int _dtrace_next_probe(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp, void *arg)
47
+ {
48
+ VALUE probe;
49
+
50
+ probe = Data_Wrap_Struct(cDtraceProbe, 0, NULL, (dtrace_probedesc_t *)pdp);
51
+
52
+ rb_yield(probe);
53
+ return 0;
54
+ }
55
+
56
+ /*
57
+ * Yields each probe found on the system.
58
+ * (equivalent to dtrace -l)
59
+ *
60
+ * Each probe is represented by a DtraceProbe object
61
+ */
62
+ VALUE dtrace_each_probe(VALUE self)
63
+ {
64
+ dtrace_hdl_t *handle;
65
+
66
+ Data_Get_Struct(self, dtrace_hdl_t, handle);
67
+ (void) dtrace_probe_iter(handle, NULL, _dtrace_next_probe, NULL);
68
+
69
+ return self;
70
+ }
71
+
72
+ /*
73
+ * Compile a D program.
74
+ *
75
+ * Arguments:
76
+ * * The program text to compile
77
+ * * (Optionally) any arguments required by the program
78
+ *
79
+ * Raises a DtraceException if the program cannot be compiled.
80
+ */
81
+ VALUE dtrace_strcompile(int argc, VALUE *argv, VALUE self)
82
+ {
83
+ dtrace_hdl_t *handle;
84
+ dtrace_prog_t *program;
85
+ VALUE dtrace_program;
86
+
87
+ VALUE dtrace_text;
88
+ int dtrace_argc;
89
+ VALUE dtrace_argv_array;
90
+
91
+ char **dtrace_argv;
92
+ int i;
93
+
94
+ rb_scan_args(argc, argv, "1*", &dtrace_text, &dtrace_argv_array);
95
+
96
+ dtrace_argc = FIX2INT(rb_funcall(dtrace_argv_array, rb_intern("length"), 0));
97
+ dtrace_argv = ALLOC_N(char *, dtrace_argc + 1);
98
+ for (i = 0; i < dtrace_argc; i++) {
99
+ dtrace_argv[i + 1] = STR2CSTR(rb_ary_entry(dtrace_argv_array, i));
100
+ }
101
+
102
+ dtrace_argv[0] = "ruby";
103
+ dtrace_argc++;
104
+
105
+ Data_Get_Struct(self, dtrace_hdl_t, handle);
106
+ program = dtrace_program_strcompile(handle, STR2CSTR(dtrace_text),
107
+ DTRACE_PROBESPEC_NAME, DTRACE_C_PSPEC,
108
+ dtrace_argc, dtrace_argv);
109
+
110
+ if (!program) {
111
+ rb_raise(eDtraceException, dtrace_errmsg(handle, dtrace_errno(handle)));
112
+ return Qnil;
113
+ }
114
+ else {
115
+ dtrace_program = Data_Wrap_Struct(cDtraceProgram, 0, NULL, program);
116
+ rb_iv_set(dtrace_program, "@dtrace", self);
117
+ return dtrace_program;
118
+ }
119
+ }
120
+
121
+ /*
122
+ * Start tracing. Must be called once a program has been successfully
123
+ * compiled and executed.
124
+ *
125
+ * Raises a DtraceException on any error.
126
+ */
127
+ VALUE dtrace_hdl_go(VALUE self)
128
+ {
129
+ dtrace_hdl_t *handle;
130
+
131
+ Data_Get_Struct(self, dtrace_hdl_t, handle);
132
+ if (dtrace_go(handle) < 0)
133
+ rb_raise(eDtraceException, dtrace_errmsg(handle, dtrace_errno(handle)));
134
+
135
+ return Qnil;
136
+ }
137
+
138
+ /*
139
+ * Returns the status of the DTrace handle.
140
+ *
141
+ * Status values are defined as:
142
+ *
143
+ * * 0 - none
144
+ * * 1 - ok
145
+ * * 4 - stopped
146
+ */
147
+ VALUE dtrace_hdl_status(VALUE self)
148
+ {
149
+ dtrace_hdl_t *handle;
150
+ int status;
151
+
152
+ Data_Get_Struct(self, dtrace_hdl_t, handle);
153
+ if ((status = dtrace_status(handle)) < 0)
154
+ rb_raise(eDtraceException, dtrace_errmsg(handle, dtrace_errno(handle)));
155
+
156
+ return INT2FIX(status);
157
+ }
158
+
159
+ /*
160
+ * Set an option on the DTrace handle.
161
+ *
162
+ * Options which may be set:
163
+ *
164
+ * * aggsize
165
+ * * bufsize
166
+ */
167
+ VALUE dtrace_hdl_setopt(VALUE self, VALUE key, VALUE value)
168
+ {
169
+ dtrace_hdl_t *handle;
170
+ int ret;
171
+
172
+ Data_Get_Struct(self, dtrace_hdl_t, handle);
173
+
174
+ if (NIL_P(value)) {
175
+ ret = dtrace_setopt(handle, STR2CSTR(key), 0);
176
+ }
177
+ else {
178
+ ret = dtrace_setopt(handle, STR2CSTR(key), STR2CSTR(value));
179
+ }
180
+
181
+ if (ret < 0)
182
+ rb_raise(eDtraceException, dtrace_errmsg(handle, dtrace_errno(handle)));
183
+
184
+ return Qnil;
185
+ }
186
+
187
+ /* Stop tracing.
188
+ *
189
+ * Must be called after go has been called to start tracing.
190
+ */
191
+ VALUE dtrace_hdl_stop(VALUE self)
192
+ {
193
+ dtrace_hdl_t *handle;
194
+
195
+ Data_Get_Struct(self, dtrace_hdl_t, handle);
196
+ if (dtrace_stop(handle) < 0)
197
+ rb_raise(eDtraceException, dtrace_errmsg(handle, dtrace_errno(handle)));
198
+
199
+ return Qnil;
200
+ }
201
+
202
+ int _agg_walk_yield(const dtrace_aggdata_t *data, void *arg)
203
+ {
204
+ VALUE aggdata;
205
+
206
+ aggdata = Data_Wrap_Struct(cDtraceAggData, 0, NULL, (dtrace_aggdata_t *)data);
207
+
208
+ rb_yield(aggdata);
209
+ return (DTRACE_AGGWALK_NEXT);
210
+ }
211
+
212
+ /*
213
+ * Yields each aggregate in turn.
214
+ *
215
+ * Aggregates are represented by a DtraceAggregate object.
216
+ */
217
+ VALUE dtrace_hdl_each_aggregate(VALUE self)
218
+ {
219
+ dtrace_hdl_t *handle;
220
+
221
+ Data_Get_Struct(self, dtrace_hdl_t, handle);
222
+ if (dtrace_aggregate_walk_keyvarsorted(handle, _agg_walk_yield, NULL) < 0)
223
+ rb_raise(eDtraceException, dtrace_errmsg(handle, dtrace_errno(handle)));
224
+
225
+ return Qnil;
226
+ }
227
+
228
+ /*
229
+ * Uses libdtrace to print a summary of aggregates to STDERR.
230
+ */
231
+ VALUE dtrace_hdl_aggregate_print(VALUE self)
232
+ {
233
+ dtrace_hdl_t *handle;
234
+
235
+ Data_Get_Struct(self, dtrace_hdl_t, handle);
236
+ if (dtrace_aggregate_print(handle, stderr, NULL) < 0)
237
+ rb_raise(eDtraceException, dtrace_errmsg(handle, dtrace_errno(handle)));
238
+
239
+ return Qnil;
240
+ }
241
+
242
+ /*
243
+ * Take a snapshot of the current aggregate values.
244
+ */
245
+ VALUE dtrace_hdl_aggregate_snap(VALUE self)
246
+ {
247
+ dtrace_hdl_t *handle;
248
+
249
+ Data_Get_Struct(self, dtrace_hdl_t, handle);
250
+ if (dtrace_aggregate_snap(handle) < 0)
251
+ rb_raise(eDtraceException, dtrace_errmsg(handle, dtrace_errno(handle)));
252
+
253
+ return Qnil;
254
+ }
255
+
256
+ /*
257
+ * Clear the current aggregate snapshot.
258
+ */
259
+ VALUE dtrace_hdl_aggregate_clear(VALUE self)
260
+ {
261
+ dtrace_hdl_t *handle;
262
+
263
+ Data_Get_Struct(self, dtrace_hdl_t, handle);
264
+ dtrace_aggregate_clear(handle);
265
+ return Qnil;
266
+ }
267
+
268
+ /*
269
+ * Return the most recent DTrace error.
270
+ */
271
+ VALUE dtrace_hdl_error(VALUE self)
272
+ {
273
+ dtrace_hdl_t *handle;
274
+ const char *error_string;
275
+
276
+ Data_Get_Struct(self, dtrace_hdl_t, handle);
277
+ error_string = dtrace_errmsg(handle, dtrace_errno(handle));
278
+ return rb_str_new2(error_string);
279
+ }
280
+