tddium-sys-proctable 0.9.2-x86-darwin-10

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.
@@ -0,0 +1,21 @@
1
+ ########################################################################
2
+ # bench_ps.rb
3
+ #
4
+ # Benchmark program to show overall speed and compare the block form
5
+ # versus the non-block form. You should run this benchmark via the
6
+ # 'rake bench' Rake task.
7
+ ########################################################################
8
+ require 'benchmark'
9
+ require 'sys/proctable'
10
+
11
+ MAX = 10
12
+
13
+ Benchmark.bm do |bench|
14
+ bench.report("Block form"){
15
+ MAX.times{ Sys::ProcTable.ps{} }
16
+ }
17
+
18
+ bench.report("Non-block form"){
19
+ MAX.times{ Sys::ProcTable.ps }
20
+ }
21
+ end
@@ -0,0 +1,47 @@
1
+ = Description
2
+ A simple 'top' interface for Ruby
3
+
4
+ = Prerequisites
5
+ Requires the "sys/proctable" package (which should be installed along
6
+ with this package).
7
+
8
+ = Synopsis
9
+ require "sys/top"
10
+
11
+ Sys::Top.top(5).each{ |ps|
12
+ p ps
13
+ }
14
+
15
+ = Constants
16
+ VERSION
17
+ Returns the version number of this package as a String.
18
+
19
+ = Class Methods
20
+ Sys::Top.top(number=10, field="pctcpu")
21
+ Returns an array of ProcTableStruct's. The size of the array (i.e. the
22
+ number of processes) that it returns is based on +number+, and sorted by
23
+ +pctcpu+. By default, the size and field values are 10 and "pctcpu",
24
+ respectively.
25
+
26
+ = Notes
27
+ Not all fields are available on all platforms. Please check your
28
+ platform specific documentation for which fields are available.
29
+
30
+ = Bugs
31
+ None that I'm aware of. Please log bug reports on the project page at
32
+ http://www.rubyforge.org/projects/sysutils
33
+
34
+ = License
35
+ Artistic 2.0
36
+
37
+ = Copyright
38
+ (C) 2004-2009 Daniel J. Berger
39
+ All Rights Reserved.
40
+
41
+ = Warranty
42
+ This package is provided "as is" and without any express or
43
+ implied warranties, including, without limitation, the implied
44
+ warranties of merchantability and fitness for a particular purpose.
45
+
46
+ = Author
47
+ Daniel J. Berger
@@ -0,0 +1,20 @@
1
+ #######################################################################
2
+ # example_ps.rb
3
+ #
4
+ # Generic test program that demonstrates the use of ProcTable.ps. You
5
+ # can run this via the 'rake example' task.
6
+ #
7
+ # Modify as you see fit
8
+ #######################################################################
9
+ require 'sys/proctable'
10
+ include Sys
11
+
12
+ puts "VERSION: " + ProcTable::VERSION
13
+ sleep 2
14
+
15
+ ProcTable.ps{ |s|
16
+ ProcTable.fields.each{ |field|
17
+ puts "#{field}: " + s.send(field).to_s
18
+ }
19
+ puts '=' * 30
20
+ }
@@ -0,0 +1,4 @@
1
+ require 'mkmf'
2
+
3
+ have_type('rb_pid_t', 'ruby.h')
4
+ create_makefile('sys/proctable', 'sys')
@@ -0,0 +1,256 @@
1
+ /**********************************************************************
2
+ * Mac OS X code for sys-proctable Ruby library. *
3
+ * *
4
+ * Date: 3-Mar-2006 (original submission date) *
5
+ * Author: David Felstead (david.felstead at gmail dot com) *
6
+ * Based on bsd.c by Daniel J. Berger (djberg96 at gmail dot com) *
7
+ *********************************************************************/
8
+ #include "ruby.h"
9
+ #include <sys/param.h>
10
+ #include <sys/stat.h>
11
+ #include <sys/sysctl.h>
12
+ #include <sys/types.h>
13
+ #include <sys/user.h>
14
+ #include <errno.h>
15
+
16
+ #define SYS_PROCTABLE_VERSION "0.9.1"
17
+
18
+ #define PROC_MIB_LEN 4
19
+ #define ARGS_MIB_LEN 3
20
+ #define ARGS_MAX_LEN 4096
21
+ VALUE cProcTableError, sProcStruct;
22
+
23
+ const char* fields[] = {
24
+ "pid", "ppid", "pgid", "ruid", "rgid", "comm", "state", "pctcpu", "oncpu",
25
+ "tnum", "tdev", "wmesg", "rtime", "priority", "usrpri", "nice", "cmdline",
26
+ "starttime", "maxrss", "ixrss", "idrss", "isrss", "minflt", "majflt",
27
+ "nswap", "inblock", "oublock", "msgsnd", "msgrcv", "nsignals", "nvcsw",
28
+ "nivcsw", "utime", "stime"
29
+ };
30
+
31
+ /*
32
+ * call-seq:
33
+ * ProcTable.ps(pid=nil)
34
+ * ProcTable.ps(pid=nil){ |ps| ... }
35
+ *
36
+ * In block form, yields a ProcTableStruct for each process entry that you
37
+ * have rights to. This method returns an array of ProcTableStruct's in
38
+ * non-block form.
39
+ *
40
+ * If a +pid+ is provided, then only a single ProcTableStruct is yielded or
41
+ * returned, or nil if no process information is found for that +pid+.
42
+ */
43
+ static VALUE pt_ps(int argc, VALUE* argv, VALUE klass){
44
+ int err;
45
+ char state[8];
46
+ struct kinfo_proc* procs;
47
+ int count; /* Holds total number of processes */
48
+ int i = 0;
49
+ VALUE v_pid, v_tty_num, v_tty_dev, v_start_time;
50
+ VALUE v_pstruct = Qnil;
51
+ VALUE v_array = rb_ary_new();
52
+ size_t length;
53
+ char args[ARGS_MAX_LEN+1];
54
+
55
+ // Passed into sysctl call
56
+ static const int name_mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0};
57
+
58
+ rb_scan_args(argc, argv, "01", &v_pid);
59
+
60
+ // Get size of proc kproc buffer
61
+ err = sysctl( (int *) name_mib, PROC_MIB_LEN, NULL, &length, NULL, 0);
62
+
63
+ if(err == -1)
64
+ rb_raise(cProcTableError, strerror(errno));
65
+
66
+ // Populate the kproc buffer
67
+ procs = malloc(length);
68
+
69
+ if(procs == NULL)
70
+ rb_raise(cProcTableError, strerror(errno));
71
+
72
+ err = sysctl( (int *) name_mib, PROC_MIB_LEN, procs, &length, NULL, 0);
73
+
74
+ if(err == -1)
75
+ rb_raise(cProcTableError, strerror(errno));
76
+
77
+ // If we're here, we got our list
78
+ count = length / sizeof(struct kinfo_proc);
79
+
80
+ for(i = 0; i < count; i++) {
81
+ v_tty_num = Qnil;
82
+ v_tty_dev = Qnil;
83
+ v_start_time = Qnil;
84
+
85
+ // If a PID is provided, skip unless the PID matches
86
+ if( (!NIL_P(v_pid)) && (procs[i].kp_proc.p_pid != NUM2INT(v_pid)) )
87
+ continue;
88
+
89
+ *args = '\0';
90
+
91
+ /* Query the command line args */
92
+ /* TODO: Cmd line not working for now - fix */
93
+
94
+ /*args_mib[ARGS_MIB_LEN - 1] = procs[i].kp_proc.p_pid;
95
+ args_err = sysctl( (int *) args_mib, ARGS_MIB_LEN, args, &args_size, NULL, 0);
96
+
97
+ if(args_err >= 0) {
98
+ fprintf(stderr, "Ret: %d LEN: %d\n", err, args_size);
99
+ char *c;
100
+ for(c = args; c < args+args_size; c++)
101
+ if(*c == '\0') *c = ' ';
102
+ args[args_size] = '\0';
103
+ } else {
104
+ fprintf(stderr, "err: %s LEN: %d\n", strerror(errno), args_size);
105
+ }*/
106
+
107
+ // Get the start time of the process
108
+ v_start_time = rb_time_new(
109
+ procs[i].kp_proc.p_un.__p_starttime.tv_sec,
110
+ procs[i].kp_proc.p_un.__p_starttime.tv_usec
111
+ );
112
+
113
+ // Get the state of the process
114
+ switch(procs[i].kp_proc.p_stat)
115
+ {
116
+ case SIDL:
117
+ strcpy(state, "idle");
118
+ break;
119
+ case SRUN:
120
+ strcpy(state, "run");
121
+ break;
122
+ case SSLEEP:
123
+ strcpy(state, "sleep");
124
+ break;
125
+ case SSTOP:
126
+ strcpy(state, "stop");
127
+ break;
128
+ case SZOMB:
129
+ strcpy(state, "zombie");
130
+ break;
131
+ default:
132
+ strcpy(state, "unknown");
133
+ break;
134
+ }
135
+
136
+ // Get ttynum and ttydev. If ttynum is -1, there is no tty.
137
+ if(procs[i].kp_eproc.e_tdev != -1){
138
+ v_tty_num = INT2FIX(procs[i].kp_eproc.e_tdev),
139
+ v_tty_dev = rb_str_new2(devname(procs[i].kp_eproc.e_tdev, S_IFCHR));
140
+ }
141
+
142
+ v_pstruct = rb_struct_new(
143
+ sProcStruct,
144
+ INT2FIX(procs[i].kp_proc.p_pid),
145
+ INT2FIX(procs[i].kp_eproc.e_ppid),
146
+ INT2FIX(procs[i].kp_eproc.e_pgid),
147
+ INT2FIX(procs[i].kp_eproc.e_pcred.p_ruid),
148
+ INT2FIX(procs[i].kp_eproc.e_pcred.p_rgid),
149
+ rb_str_new2(procs[i].kp_proc.p_comm),
150
+ rb_str_new2(state),
151
+ rb_float_new(procs[i].kp_proc.p_pctcpu),
152
+ Qnil,
153
+ v_tty_num,
154
+ v_tty_dev,
155
+ rb_str_new2(procs[i].kp_eproc.e_wmesg),
156
+ INT2FIX(procs[i].kp_proc.p_rtime.tv_sec),
157
+ INT2FIX(procs[i].kp_proc.p_priority),
158
+ INT2FIX(procs[i].kp_proc.p_usrpri),
159
+ INT2FIX(procs[i].kp_proc.p_nice),
160
+ rb_str_new2(args),
161
+ v_start_time,
162
+ (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_maxrss) : Qnil,
163
+ (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_ixrss) : Qnil,
164
+ (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_idrss) : Qnil,
165
+ (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_isrss) : Qnil,
166
+ (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_minflt) : Qnil,
167
+ (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_majflt) : Qnil,
168
+ (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_nswap) : Qnil,
169
+ (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_inblock) : Qnil,
170
+ (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_oublock) : Qnil,
171
+ (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_msgsnd) : Qnil,
172
+ (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_msgrcv) : Qnil,
173
+ (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_nsignals) : Qnil,
174
+ (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_nvcsw) : Qnil,
175
+ (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_nivcsw) : Qnil,
176
+ (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_utime.tv_sec) : Qnil,
177
+ (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_stime.tv_sec) : Qnil
178
+ );
179
+
180
+ OBJ_FREEZE(v_pstruct); // This is read-only data
181
+
182
+ if(rb_block_given_p())
183
+ rb_yield(v_pstruct);
184
+ else
185
+ rb_ary_push(v_array, v_pstruct);
186
+ }
187
+
188
+ if(procs) free(procs);
189
+
190
+ if(!rb_block_given_p()){
191
+ if(NIL_P(v_pid))
192
+ return v_array;
193
+ else
194
+ return v_pstruct;
195
+ }
196
+
197
+ return Qnil;
198
+ }
199
+
200
+ /*
201
+ * call-seq:
202
+ * ProcTable.fields
203
+ *
204
+ * Returns an array of fields that each ProcTableStruct will contain. This
205
+ * may be useful if you want to know in advance what fields are available
206
+ * without having to perform at least one read of the /proc table.
207
+ */
208
+ static VALUE pt_fields(VALUE klass){
209
+ VALUE v_array = rb_ary_new();
210
+ int size = sizeof(fields) / sizeof(fields[0]);
211
+ int i;
212
+
213
+ for(i = 0; i < size; i++)
214
+ rb_ary_push(v_array, rb_str_new2(fields[i]));
215
+
216
+ return v_array;
217
+ }
218
+
219
+ /*
220
+ * A Ruby interface for gathering process table information.
221
+ */
222
+ void Init_proctable(){
223
+ VALUE mSys, cProcTable;
224
+
225
+ /* The Sys module serves as a namespace only */
226
+ mSys = rb_define_module("Sys");
227
+
228
+ /* The ProcTable class encapsulates process table information */
229
+ cProcTable = rb_define_class_under(mSys, "ProcTable", rb_cObject);
230
+
231
+ /* The Error class typically raised if any of the ProcTable methods fail */
232
+ cProcTableError = rb_define_class_under(cProcTable, "Error", rb_eStandardError);
233
+
234
+ /* Singleton methods */
235
+
236
+ rb_define_singleton_method(cProcTable, "ps", pt_ps, -1);
237
+ rb_define_singleton_method(cProcTable, "fields", pt_fields, 0);
238
+
239
+ /* There is no constructor */
240
+ rb_funcall(cProcTable, rb_intern("private_class_method"), 1, ID2SYM(rb_intern("new")));
241
+
242
+ /* Constants */
243
+
244
+ /* 0.9.1: The version of the sys-proctable library */
245
+ rb_define_const(cProcTable, "VERSION", rb_str_new2(SYS_PROCTABLE_VERSION));
246
+
247
+ /* Structs */
248
+
249
+ sProcStruct = rb_struct_define("ProcTableStruct","pid","ppid","pgid","ruid",
250
+ "rgid","comm","state","pctcpu","oncpu","tnum","tdev","wmesg",
251
+ "rtime", "priority","usrpri","nice","cmdline","starttime",
252
+ "maxrss","ixrss","idrss","isrss","minflt","majflt","nswap",
253
+ "inblock","oublock","msgsnd","msgrcv","nsignals","nvcsw","nivcsw",
254
+ "utime","stime", NULL
255
+ );
256
+ }
@@ -0,0 +1,32 @@
1
+ require 'sys/proctable'
2
+ require 'rbconfig'
3
+
4
+ # The Sys module serves as a namespace only
5
+ module Sys
6
+
7
+ # The Top class serves as a toplevel name for the 'top' method.
8
+ class Top
9
+
10
+ # The version of the sys-top library
11
+ VERSION = '1.0.3'
12
+
13
+ # Returns an array of Struct::ProcTableStruct elements containing up
14
+ # to +num+ elements, sorted by +field+. The default number of elements
15
+ # is 10, while the default field is 'pctcpu'.
16
+ #
17
+ # Exception: the default sort field is 'pid' on Linux and Windows.
18
+ #
19
+ def self.top(num=10, field='pctcpu')
20
+ field = field.to_s if field.is_a?(Symbol)
21
+
22
+ windows = /mswin|win32|windows|dos|cygwin|mingw/i
23
+
24
+ # Sort by pid on Windows by default
25
+ if Config::CONFIG['host_os'].match(windows) && field == 'pctcpu'
26
+ field = 'pid'
27
+ end
28
+
29
+ Sys::ProcTable.ps.sort_by{ |obj| obj.send(field) || '' }[0..num-1]
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,42 @@
1
+ require 'rubygems'
2
+ require 'rbconfig'
3
+
4
+ Gem::Specification.new do |spec|
5
+ spec.name = 'tddium-sys-proctable'
6
+ spec.version = '0.9.2'
7
+ spec.author = 'Daniel J. Berger'
8
+ spec.license = 'Artistic 2.0'
9
+ spec.email = 'info@tddium.com'
10
+ spec.homepage = 'http://www.rubyforge.org/projects/sysutils'
11
+ spec.platform = Gem::Platform::CURRENT
12
+ spec.summary = 'An interface for providing process table information'
13
+ spec.has_rdoc = true
14
+ spec.test_files = ['test/test_sys_proctable_all.rb']
15
+
16
+ # Additional files for your platform are added by the 'rake gem' task.
17
+ spec.files = [
18
+ 'benchmarks/bench_ps.rb',
19
+ 'examples/example_ps.rb',
20
+ 'lib/sys/top.rb',
21
+ 'CHANGES',
22
+ 'MANIFEST',
23
+ 'Rakefile',
24
+ 'README',
25
+ 'sys-proctable.gemspec'
26
+ ]
27
+
28
+ spec.rubyforge_project = 'sysutils'
29
+ spec.extra_rdoc_files = ['CHANGES', 'README', 'MANIFEST', 'doc/top.txt']
30
+
31
+ spec.add_development_dependency('test-unit', '>= 2.1.2')
32
+
33
+ spec.description = <<-EOF
34
+ Testing a separate publish to see if I can get the mac install to work with bundler.
35
+
36
+ The sys-proctable library provides an interface for gathering information
37
+ about processes on your system, i.e. the process table. Most major
38
+ platforms are supported and, while different platforms may return
39
+ different information, the external interface is identical across
40
+ platforms.
41
+ EOF
42
+ end
@@ -0,0 +1,85 @@
1
+ #######################################################################
2
+ # test_sys_proctable_all.rb
3
+ #
4
+ # Test suite for methods common to all platforms. Generally speaking
5
+ # you should run this test case using the 'rake test' task.
6
+ #######################################################################
7
+ require 'rubygems'
8
+ gem 'test-unit'
9
+
10
+ require 'test/unit'
11
+ require 'sys/proctable'
12
+ require 'rbconfig'
13
+ require 'test/test_sys_top'
14
+ include Sys
15
+
16
+ class TC_ProcTable_All < Test::Unit::TestCase
17
+ def self.startup
18
+ @@windows = Config::CONFIG['host_os'] =~ /windows|win32|msdos|mswin32|mingw|cygwin/i
19
+ end
20
+
21
+ def setup
22
+ @pid = @@windows ? 0 : 1
23
+ end
24
+
25
+ def test_version
26
+ assert_equal('0.9.1', ProcTable::VERSION)
27
+ end
28
+
29
+ def test_fields
30
+ assert_respond_to(ProcTable, :fields)
31
+ assert_nothing_raised{ ProcTable.fields }
32
+ assert_kind_of(Array, ProcTable.fields)
33
+ assert_kind_of(String, ProcTable.fields.first)
34
+ end
35
+
36
+ def test_ps
37
+ assert_respond_to(ProcTable, :ps)
38
+ assert_nothing_raised{ ProcTable.ps }
39
+ assert_nothing_raised{ ProcTable.ps{} }
40
+ end
41
+
42
+ def test_ps_with_pid
43
+ assert_nothing_raised{ ProcTable.ps(0) }
44
+ end
45
+
46
+ def test_ps_with_explicit_nil
47
+ assert_nothing_raised{ ProcTable.ps(nil) }
48
+ assert_kind_of(Array, ProcTable.ps(nil))
49
+ end
50
+
51
+ def test_ps_return_value
52
+ assert_kind_of(Array, ProcTable.ps)
53
+ assert_kind_of(Struct::ProcTableStruct, ProcTable.ps(@pid))
54
+ assert_equal(nil, ProcTable.ps(999999999))
55
+ assert_equal(nil, ProcTable.ps(999999999){})
56
+ assert_equal(nil, ProcTable.ps{})
57
+ end
58
+
59
+ def test_ps_returned_struct_is_frozen
60
+ assert_true(ProcTable.ps.first.frozen?)
61
+ end
62
+
63
+ def test_ps_expected_errors
64
+ assert_raises(TypeError){ ProcTable.ps('vim') }
65
+ omit_if(@@windows, 'ArgumentError check skipped on MS Windows')
66
+ assert_raises(ArgumentError){ ProcTable.ps(0, 'localhost') }
67
+ end
68
+
69
+ def test_new_not_allowed
70
+ assert_raise(NoMethodError){ Sys::ProcTable.new }
71
+ end
72
+
73
+ def test_error_class_defined
74
+ assert_not_nil(Sys::ProcTable::Error)
75
+ assert_kind_of(StandardError, Sys::ProcTable::Error.new)
76
+ end
77
+
78
+ def teardown
79
+ @pid = nil
80
+ end
81
+
82
+ def self.teardown
83
+ @@windows = nil
84
+ end
85
+ end