solaris-kstat 1.0.1 → 1.0.2

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/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