solaris-kstat 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES CHANGED
@@ -1,3 +1,16 @@
1
+ == 1.0.2 - 29-Jul-2011
2
+ * Fixed a bug where the name hash keys could potentially be overwritten if there
3
+ were multiple statistics for the same name. Thanks go to Jens Deppe for the
4
+ spot and the patch.
5
+ * Added the "class" information to the statistics hash.
6
+ * Rakefile refactored. The old style of library installation has been removed.
7
+ Use the 'gem' tasks now. In addition, gem creation is now handled via a Rake
8
+ task now.
9
+ * Some minor modifications to the gemspec to reflect the changes in the
10
+ Rakefile, as well as a change required due to the switch from CVS to git.
11
+ * Added a .gitignore file.
12
+ * Changed license to Artistic 2.0.
13
+
1
14
  == 1.0.1 - 27-Aug-2009
2
15
  * Changed the license to Artistic 2.0.
3
16
  * Fixed warnings that could occur if the @module, @name, or @instance
data/README CHANGED
@@ -1,18 +1,11 @@
1
1
  == Description
2
- Ruby extension for the Solaris kstat library.
2
+ A Ruby interface for the Solaris kstat library.
3
3
 
4
4
  == Prerequisites
5
- Solaris 8 (2.8) or later.
6
- Ruby 1.8.x
5
+ Solaris 8 (SunOS 2.8) or later.
7
6
 
8
7
  == Installation
9
- === Manual Installation
10
- rake test (optional)
11
- rake install
12
-
13
- === Gem Installation
14
- rake test (optional)
15
- rake install_gem
8
+ gem install solaris-kstat
16
9
 
17
10
  == Synopsis
18
11
  require 'solaris/kstat'
@@ -20,7 +13,7 @@
20
13
  include Solaris
21
14
 
22
15
  k = Kstat.new('cpu_info', 0, 'cpu_info0')
23
- pp k
16
+ pp k.record
24
17
 
25
18
  {'cpu_info'=>
26
19
  {0=>
@@ -64,7 +57,7 @@ Kstat::Error < StandardError
64
57
  * sfmmu_percpu_stat
65
58
 
66
59
  == Known Bugs
67
- You will receive a couple warnings during the build process. You
60
+ You may receive a couple warnings during the build process. You
68
61
  can ignore these.
69
62
 
70
63
  == Designer's Notes
@@ -81,13 +74,13 @@ Kstat::Error < StandardError
81
74
  Thanks go to Charlie Mills for help with the 'volatile' issue.
82
75
 
83
76
  == Future Plans
84
- Eliminate warnings that occur during the build process, if possible.
77
+ Add snaptime and crtime information to the statistics hash.
85
78
 
86
79
  == License
87
- Ruby's
80
+ Artistic 2.0
88
81
 
89
82
  == Copyright
90
- (C) 2003-2008 Daniel J. Berger
83
+ (C) 2003-2011 Daniel J. Berger
91
84
  All Rights Reserved
92
85
 
93
86
  == Warranty
@@ -97,8 +90,6 @@ Kstat::Error < StandardError
97
90
 
98
91
  == Author
99
92
  Daniel J. Berger
100
- djberg96 at nospam at gmail dot com
101
- imperator on IRC (freenode)
102
93
 
103
94
  == See Also
104
95
  kstat(1M)
data/Rakefile CHANGED
@@ -4,56 +4,50 @@ require 'rake/testtask'
4
4
  require 'rbconfig'
5
5
  include Config
6
6
 
7
- desc "Clean the build files for the solaris-kstat source"
8
- task :clean do
9
- FileUtils.rm_rf('solaris') if File.exists?('solaris')
10
-
11
- Dir.chdir('ext') do
12
- FileUtils.rm_rf('rkstat.c') if File.exists?('rkstat.c')
13
- FileUtils.rm_rf('rkstat.h') if File.exists?('rkstat.h')
14
- sh 'make distclean' if File.exists?('kstat.so')
15
- FileUtils.rm_rf('solaris/kstat.so') if File.exists?('solaris/kstat.so')
16
- end
17
- end
18
-
19
- desc "Build the solaris-kstat package (but don't install it)"
20
- task :build => [:clean] do
21
- Dir.chdir('ext') do
22
- ruby 'extconf.rb'
23
- sh 'make'
24
- Dir.mkdir('solaris') unless File.exists?('solaris')
25
- FileUtils.cp('kstat.so', 'solaris')
26
- end
27
- end
28
-
29
- desc "Install the solaris-kstat package (non-gem)"
30
- task :install => [:build] do
31
- Dir.chdir('ext') do
32
- sh 'make install'
33
- end
34
- end
35
-
36
- desc "Install the solaris-kstat package as a gem"
37
- task :install_gem do
38
- ruby 'solaris-kstat.gemspec'
39
- file = Dir["*.gem"].first
40
- sh "gem install #{file}"
7
+ CLEAN.include(
8
+ '**/*.gem', # Gem files
9
+ '**/*.rbc', # Rubinius
10
+ '**/*.o', # C object file
11
+ '**/*.log', # Ruby extension build log
12
+ '**/Makefile', # C Makefile
13
+ '**/conftest.dSYM', # OS X build directory
14
+ "**/*.#{CONFIG['DLEXT']}" # C shared object
15
+ )
16
+
17
+ desc "Build the solaris-kstat source"
18
+ task :build do
19
+ Dir.chdir('ext') do
20
+ ruby 'extconf.rb'
21
+ sh 'make'
22
+ cp 'kstat.so', 'solaris'
23
+ end
41
24
  end
42
25
 
43
- desc "Uninstall the solaris-kstat package. Use 'gem uninstall' for gem installs"
44
- task :uninstall => [:clean] do
45
- file = File.join(CONFIG['sitearchdir'], 'solaris', 'kstat.so')
46
- FileUtils.rm_rf(file) if File.exists?(file)
26
+ namespace :gem do
27
+ desc "Create the solaris-kstat gem"
28
+ task :create => [:clean] do
29
+ spec = eval(IO.read('solaris-kstat.gemspec'))
30
+ Gem::Builder.new(spec).build
31
+ end
32
+
33
+ desc "Install the solaris-kstat gem"
34
+ task :install => [:build] do
35
+ ruby 'solaris-kstat.gemspec'
36
+ file = Dir["*.gem"].first
37
+ sh "gem install #{file}"
38
+ end
47
39
  end
48
40
 
49
41
  desc "Run the example program"
50
42
  task :example => [:build] do
51
- ruby "-Iext examples/example_kstat.rb"
43
+ ruby "-Iext examples/example_kstat.rb"
52
44
  end
53
45
 
54
46
  Rake::TestTask.new do |t|
55
- task :test => :build
56
- t.libs << 'ext'
57
- t.verbose = true
58
- t.warning = true
47
+ task :test => [:build]
48
+ t.libs << 'ext'
49
+ t.verbose = true
50
+ t.warning = true
59
51
  end
52
+
53
+ task :default => :test
@@ -20,8 +20,8 @@ extern "C" {
20
20
  VALUE cKstatError;
21
21
 
22
22
  static VALUE ks_allocate(VALUE klass){
23
- KstatStruct* ptr;
24
- return Data_Make_Struct(klass, KstatStruct, 0, ks_free, ptr);
23
+ KstatStruct* ptr;
24
+ return Data_Make_Struct(klass, KstatStruct, 0, ks_free, ptr);
25
25
  }
26
26
 
27
27
  /*
@@ -37,36 +37,53 @@ static VALUE ks_allocate(VALUE klass){
37
37
  * name defaults to nil (all names).
38
38
  */
39
39
  VALUE ks_init(int argc, VALUE* argv, VALUE self){
40
- KstatStruct* ptr;
41
- VALUE v_module, v_instance, v_name;
42
-
43
- Data_Get_Struct(self,KstatStruct,ptr);
44
-
45
- rb_scan_args(argc, argv, "03", &v_module, &v_instance, &v_name);
46
-
40
+ KstatStruct* ptr;
41
+ VALUE v_module, v_instance, v_name;
42
+
43
+ Data_Get_Struct(self,KstatStruct,ptr);
44
+
45
+ rb_scan_args(argc, argv, "03", &v_module, &v_instance, &v_name);
46
+
47
+ if(!NIL_P(v_module)){
48
+ SafeStringValue(v_module);
49
+ rb_iv_set(self, "@module", v_module);
50
+ }
51
+ else{
52
+ rb_iv_set(self, "@module", Qnil);
53
+ }
54
+
55
+ if(!NIL_P(v_name)){
56
+ SafeStringValue(v_name);
57
+ rb_iv_set(self, "@name", v_name);
58
+ }
59
+ else{
60
+ rb_iv_set(self, "@name", Qnil);
61
+ }
62
+
63
+ if(!NIL_P(v_instance))
64
+ rb_iv_set(self, "@instance", v_instance);
65
+ else
66
+ rb_iv_set(self, "@instance", Qnil);
67
+
68
+ return self;
69
+ }
47
70
 
48
- if(!NIL_P(v_module)){
49
- SafeStringValue(v_module);
50
- rb_iv_set(self, "@module", v_module);
51
- }
52
- else{
53
- rb_iv_set(self, "@module", Qnil);
54
- }
71
+ /*
72
+ * Helper function ks_record which will either return an existing value for
73
+ * the given key, or assign that key a new empty hash if it has no value
74
+ * associated with it.
75
+ */
76
+ VALUE get_hash_for_key(VALUE v_hash, VALUE v_key){
77
+ volatile VALUE v_new_hash;
55
78
 
56
- if(!NIL_P(v_name)){
57
- SafeStringValue(v_name);
58
- rb_iv_set(self, "@name", v_name);
59
- }
60
- else{
61
- rb_iv_set(self, "@name", Qnil);
62
- }
79
+ v_new_hash = rb_hash_aref(v_hash, v_key);
63
80
 
64
- if(!NIL_P(v_instance))
65
- rb_iv_set(self, "@instance", v_instance);
66
- else
67
- rb_iv_set(self, "@instance", Qnil);
81
+ if(NIL_P(v_new_hash)){
82
+ v_new_hash = rb_hash_new();
83
+ rb_hash_aset(v_hash, v_key, v_new_hash);
84
+ }
68
85
 
69
- return self;
86
+ return v_new_hash;
70
87
  }
71
88
 
72
89
  /*
@@ -75,141 +92,146 @@ VALUE ks_init(int argc, VALUE* argv, VALUE self){
75
92
  * The more specific your criterion, the less data you will receive.
76
93
  */
77
94
  VALUE ks_record(VALUE self){
78
- volatile VALUE v_m_hash, v_i_hash, v_n_hash, v_s_hash;
79
- KstatStruct* ptr;
80
- kstat_io_t kio;
81
- kstat_timer_t kt;
82
-
83
- char* module;
84
- char* name;
85
- int instance = -1; /* -1 represents all instances (the default) */
86
-
87
- VALUE v_module, v_instance, v_name;
88
-
89
- Data_Get_Struct(self,KstatStruct,ptr);
90
-
91
- v_m_hash = rb_hash_new(); /* Module name is key, holds v_i_hashes */
92
- v_i_hash = rb_hash_new(); /* Instance name is key, holds v_n_hashes */
93
- v_n_hash = rb_hash_new(); /* Name is key, holds v_s_hashes */
94
-
95
- v_module = rb_iv_get(self, "@module");
96
- v_instance = rb_iv_get(self, "@instance");
97
- v_name = rb_iv_get(self, "@name");
98
-
99
- /* Module is NULL by default (i.e. all modules are returned) */
100
- if(NIL_P(v_module))
101
- module = NULL;
102
- else
103
- module = StringValuePtr(v_module);
104
-
105
- /* Instance defaults to -1 (i.e. all instances are returned) */
106
- if(!NIL_P(v_instance))
107
- instance = NUM2INT(v_instance);
108
-
109
- /* Name is NULL by default (i.e. all names are returned) */
110
- if(NIL_P(v_name))
111
- name = NULL;
112
- else
113
- name = StringValuePtr(v_name);
114
-
115
- /* A failure probably means the module, instance or name doesn't exist */
116
- if((ptr->kc = kstat_open()) == NULL)
117
- rb_raise(cKstatError,"kstat_open() failure: %s", strerror(errno));
118
-
119
- /*
120
- * Traverse the kstat chain, looking for matches based on supplied data.
121
- * A failure likely means a non-existant module or name was provided.
122
- */
123
- if((ptr->ksp = kstat_lookup(ptr->kc, module, instance, name)) == NULL)
124
- rb_raise(cKstatError,"kstat_lookup() failure: %s", strerror(errno));
125
-
126
- /* Sync the chain with the kernel */
127
- kstat_chain_update(ptr->kc);
128
-
129
- while(ptr->ksp){
130
-
131
- /* If a module is specified, ignore modules that don't match */
132
- if( (module) && (strcmp(module,ptr->ksp->ks_module)) ){
133
- ptr->ksp = ptr->ksp->ks_next;
134
- continue;
135
- }
136
-
137
- /* If an instance is specified, ignore instances that don't match */
138
- if( (instance != -1) && (instance != ptr->ksp->ks_instance) ){
139
- ptr->ksp = ptr->ksp->ks_next;
140
- continue;
141
- }
142
-
143
- /* If a name is specified, ignore names that don't match */
144
- if( (name) && (strcmp(name,ptr->ksp->ks_name)) ){
145
- ptr->ksp = ptr->ksp->ks_next;
146
- continue;
147
- }
148
-
149
- /* Call the appropriate data mapper based on ks_type */
150
- switch(ptr->ksp->ks_type){
151
- case KSTAT_TYPE_NAMED:
152
- kstat_read(ptr->kc, ptr->ksp, NULL);
153
- v_s_hash = map_named_data_type(ptr->ksp);
154
- break;
155
- case KSTAT_TYPE_IO:
156
- kstat_read(ptr->kc, ptr->ksp, &kio);
157
- v_s_hash = map_io_data_type(&kio);
158
- break;
159
- case KSTAT_TYPE_TIMER:
160
- kstat_read(ptr->kc, ptr->ksp, &kt);
161
- v_s_hash = map_timer_data_type(&kt);
162
- case KSTAT_TYPE_INTR:
163
- kstat_read(ptr->kc, ptr->ksp, NULL);
164
- v_s_hash = map_intr_data_type(ptr->ksp);
165
- break;
166
- case KSTAT_TYPE_RAW:
167
- kstat_read(ptr->kc, ptr->ksp, NULL);
168
- v_s_hash = map_raw_data_type(ptr->ksp);
169
- break;
170
- default:
171
- rb_raise(cKstatError,"Unknown data record type");
172
- }
173
-
174
- rb_hash_aset(v_n_hash, rb_str_new2(ptr->ksp->ks_name), v_s_hash);
175
- rb_hash_aset(v_i_hash, INT2FIX(ptr->ksp->ks_instance), v_n_hash);
176
- rb_hash_aset(v_m_hash, rb_str_new2(ptr->ksp->ks_module), v_i_hash);
95
+ volatile VALUE v_m_hash, v_i_hash, v_n_hash, v_s_hash;
96
+ KstatStruct* ptr;
97
+ kstat_io_t kio;
98
+ kstat_timer_t kt;
99
+ char* module;
100
+ char* name;
101
+ int instance = -1; // -1 represents all instances (the default)
102
+
103
+ VALUE v_module, v_instance, v_name;
104
+
105
+ Data_Get_Struct(self,KstatStruct,ptr);
106
+
107
+ v_m_hash = rb_hash_new(); // Module name is key, holds v_i_hashes
108
+
109
+ v_module = rb_iv_get(self, "@module");
110
+ v_instance = rb_iv_get(self, "@instance");
111
+ v_name = rb_iv_get(self, "@name");
112
+
113
+ // Module is NULL by default (i.e. all modules are returned)
114
+ if(NIL_P(v_module))
115
+ module = NULL;
116
+ else
117
+ module = StringValuePtr(v_module);
118
+
119
+ // Instance defaults to -1 (i.e. all instances are returned)
120
+ if(!NIL_P(v_instance))
121
+ instance = NUM2INT(v_instance);
122
+
123
+ // Name is NULL by default (i.e. all names are returned)
124
+ if(NIL_P(v_name))
125
+ name = NULL;
126
+ else
127
+ name = StringValuePtr(v_name);
128
+
129
+ // A failure probably means the module, instance or name doesn't exist
130
+ if((ptr->kc = kstat_open()) == NULL)
131
+ rb_raise(cKstatError, "kstat_open() failure: %s", strerror(errno));
132
+
133
+ /*
134
+ * Traverse the kstat chain, looking for matches based on supplied data.
135
+ * A failure likely means a non-existant module or name was provided.
136
+ */
137
+ if((ptr->ksp = kstat_lookup(ptr->kc, module, instance, name)) == NULL)
138
+ rb_raise(cKstatError, "kstat_lookup() failure: %s", strerror(errno));
139
+
140
+ // Sync the chain with the kernel
141
+ if(kstat_chain_update(ptr->kc) == -1)
142
+ rb_raise(cKstatError, "kstat_chain_update() failure: %s", strerror(errno));
143
+
144
+ while(ptr->ksp){
145
+ // If a module is specified, ignore modules that don't match
146
+ if((module) && (strcmp(module,ptr->ksp->ks_module))){
147
+ ptr->ksp = ptr->ksp->ks_next;
148
+ continue;
149
+ }
177
150
 
151
+ // If an instance is specified, ignore instances that don't match
152
+ if((instance != -1) && (instance != ptr->ksp->ks_instance)){
178
153
  ptr->ksp = ptr->ksp->ks_next;
179
- }
154
+ continue;
155
+ }
180
156
 
181
- return v_m_hash;
157
+ // If a name is specified, ignore names that don't match
158
+ if((name) && (strcmp(name,ptr->ksp->ks_name))){
159
+ ptr->ksp = ptr->ksp->ks_next;
160
+ continue;
161
+ }
162
+
163
+ // Call the appropriate data mapper based on ks_type
164
+ switch(ptr->ksp->ks_type){
165
+ case KSTAT_TYPE_NAMED:
166
+ kstat_read(ptr->kc, ptr->ksp, NULL);
167
+ v_s_hash = map_named_data_type(ptr->ksp);
168
+ break;
169
+ case KSTAT_TYPE_IO:
170
+ kstat_read(ptr->kc, ptr->ksp, &kio);
171
+ v_s_hash = map_io_data_type(&kio);
172
+ break;
173
+ case KSTAT_TYPE_TIMER:
174
+ kstat_read(ptr->kc, ptr->ksp, &kt);
175
+ v_s_hash = map_timer_data_type(&kt);
176
+ case KSTAT_TYPE_INTR:
177
+ kstat_read(ptr->kc, ptr->ksp, NULL);
178
+ v_s_hash = map_intr_data_type(ptr->ksp);
179
+ break;
180
+ case KSTAT_TYPE_RAW:
181
+ kstat_read(ptr->kc, ptr->ksp, NULL);
182
+ v_s_hash = map_raw_data_type(ptr->ksp);
183
+ break;
184
+ default:
185
+ rb_raise(cKstatError,"Unknown data record type");
186
+ }
187
+
188
+ /* Set the class for this set of statistics */
189
+ if(ptr->ksp->ks_class)
190
+ rb_hash_aset(v_s_hash, rb_str_new2("class"), rb_str_new2(ptr->ksp->ks_class));
191
+
192
+ v_i_hash = get_hash_for_key(v_m_hash, rb_str_new2(ptr->ksp->ks_module));
193
+ v_n_hash = get_hash_for_key(v_i_hash, INT2FIX(ptr->ksp->ks_instance));
194
+
195
+ rb_hash_aset(v_n_hash, rb_str_new2(ptr->ksp->ks_name), v_s_hash);
196
+ rb_hash_aset(v_i_hash, INT2FIX(ptr->ksp->ks_instance), v_n_hash);
197
+ rb_hash_aset(v_m_hash, rb_str_new2(ptr->ksp->ks_module), v_i_hash);
198
+
199
+ ptr->ksp = ptr->ksp->ks_next;
200
+ }
201
+
202
+ return v_m_hash;
182
203
  }
183
204
 
184
205
  void Init_kstat(){
185
- VALUE mSolaris, cKstat;
206
+ VALUE mSolaris, cKstat;
207
+
208
+ /* The Solaris module only serves as a toplevel namespace */
209
+ mSolaris = rb_define_module("Solaris");
186
210
 
187
- /* The Solaris module only serves as a toplevel namespace */
188
- mSolaris = rb_define_module("Solaris");
211
+ /* The Kstat class encapsulates kstat (kernel statistics) information */
212
+ cKstat = rb_define_class_under(mSolaris, "Kstat", rb_cObject);
189
213
 
190
- /* The Kstat class encapsulates kstat (kernel statistics) information */
191
- cKstat = rb_define_class_under(mSolaris, "Kstat", rb_cObject);
214
+ /* The Kstat::Error class is raised if any of the Kstat methods fail */
215
+ cKstatError = rb_define_class_under(cKstat, "Error", rb_eStandardError);
192
216
 
193
- /* The Kstat::Error class is raised if any of the Kstat methods fail */
194
- cKstatError = rb_define_class_under(cKstat, "Error", rb_eStandardError);
217
+ rb_define_alloc_func(cKstat, ks_allocate);
195
218
 
196
- rb_define_alloc_func(cKstat, ks_allocate);
219
+ // Instance Methods
197
220
 
198
- /* Instance Methods */
199
- rb_define_method(cKstat, "initialize", ks_init, -1);
200
- rb_define_method(cKstat, "record", ks_record, 0);
221
+ rb_define_method(cKstat, "initialize", ks_init, -1);
222
+ rb_define_method(cKstat, "record", ks_record, 0);
201
223
 
202
- /* Kernel module */
203
- rb_define_attr(cKstat, "module", 1, 1);
224
+ // Kernel module
225
+ rb_define_attr(cKstat, "module", 1, 1);
204
226
 
205
- /* Index of module entity */
206
- rb_define_attr(cKstat, "instance", 1, 1);
227
+ // Index of module entity
228
+ rb_define_attr(cKstat, "instance", 1, 1);
207
229
 
208
- /* Unique name within module */
209
- rb_define_attr(cKstat, "name", 1, 1);
230
+ // Unique name within module
231
+ rb_define_attr(cKstat, "name", 1, 1);
210
232
 
211
- /* 1.0.1: The version of the solaris-kstat library */
212
- rb_define_const(cKstat, "VERSION", rb_str_new2(SOLARIS_KSTAT_VERSION));
233
+ /* 1.0.2: The version of the solaris-kstat library */
234
+ rb_define_const(cKstat, "VERSION", rb_str_new2(SOLARIS_KSTAT_VERSION));
213
235
  }
214
236
 
215
237
  #ifdef __cplusplus