linux_stat 0.9.0 → 1.0.3

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.
@@ -12,55 +12,94 @@
12
12
  #endif
13
13
 
14
14
  static VALUE getTick(VALUE obj) {
15
- return INT2FIX(sysconf(_SC_CLK_TCK)) ;
15
+ short int val = sysconf(_SC_CLK_TCK) ;
16
+ if (val < 0) return Qnil ;
17
+
18
+ return INT2FIX(val) ;
16
19
  }
17
20
 
18
21
  static VALUE getChildMax(VALUE obj) {
19
- return INT2FIX(sysconf(_SC_CHILD_MAX)) ;
22
+ long long int val = sysconf(_SC_CHILD_MAX) ;
23
+ if (val < 0) return Qnil ;
24
+
25
+ return INT2FIX(val) ;
20
26
  }
21
27
 
22
28
  static VALUE getHostnameMax(VALUE obj) {
23
- return INT2FIX(sysconf(_SC_HOST_NAME_MAX)) ;
29
+ int val = sysconf(_SC_HOST_NAME_MAX) ;
30
+ if (val < 0) return Qnil ;
31
+
32
+ return INT2FIX(val) ;
24
33
  }
25
34
 
26
35
  static VALUE getLoginNameMax(VALUE obj) {
27
- return INT2FIX(sysconf(_SC_LOGIN_NAME_MAX)) ;
36
+ int val = sysconf(_SC_LOGIN_NAME_MAX) ;
37
+ if (val < 0) return Qnil ;
38
+
39
+ return INT2FIX(val) ;
28
40
  }
29
41
 
30
42
  static VALUE getOpenMax(VALUE obj) {
31
- return INT2FIX(sysconf(_SC_OPEN_MAX)) ;
43
+ int val = sysconf(_SC_OPEN_MAX) ;
44
+ if (val < 0) return Qnil ;
45
+
46
+ return INT2FIX(val) ;
32
47
  }
33
48
 
34
49
  static VALUE getPageSize(VALUE obj) {
35
- return INT2FIX(sysconf(_SC_PAGESIZE)) ;
50
+ short int val = sysconf(_SC_PAGESIZE) ;
51
+ if (val < 0) return Qnil ;
52
+
53
+ return INT2FIX(val) ;
36
54
  }
37
55
 
38
56
  static VALUE getStreamMax(VALUE obj) {
39
- return INT2FIX(sysconf(_SC_STREAM_MAX)) ;
57
+ int val = sysconf(_SC_STREAM_MAX) ;
58
+ if (val < 0) return Qnil ;
59
+
60
+ return INT2FIX(val) ;
40
61
  }
41
62
 
42
63
  static VALUE getTTYNameMax(VALUE obj) {
43
- return INT2FIX(sysconf(_SC_TTY_NAME_MAX)) ;
64
+ int val = sysconf(_SC_TTY_NAME_MAX) ;
65
+ if (val < 0) return Qnil ;
66
+
67
+ return INT2FIX(val) ;
44
68
  }
45
69
 
46
70
  static VALUE getPosixVersion(VALUE obj) {
47
- return INT2FIX(sysconf(_SC_VERSION)) ;
71
+ int val = sysconf(_SC_VERSION) ;
72
+ if (val < 0) return Qnil ;
73
+
74
+ return INT2FIX(val) ;
48
75
  }
49
76
 
50
77
  static VALUE getLineMax(VALUE obj) {
51
- return INT2FIX(sysconf(_SC_LINE_MAX)) ;
78
+ int val = sysconf(_SC_LINE_MAX) ;
79
+ if (val < 0) return Qnil ;
80
+
81
+ return INT2FIX(val) ;
52
82
  }
53
83
 
54
84
  static VALUE getExprNestMax(VALUE obj) {
55
- return INT2FIX(sysconf(_SC_EXPR_NEST_MAX)) ;
85
+ int val = sysconf(_SC_EXPR_NEST_MAX) ;
86
+ if (val < 0) return Qnil ;
87
+
88
+ return INT2FIX(val) ;
56
89
  }
57
90
 
58
91
  static VALUE getProcessorConfigured(VALUE obj) {
59
- return INT2FIX(sysconf(_SC_NPROCESSORS_CONF)) ;
92
+ short int val = sysconf(_SC_NPROCESSORS_CONF) ;
93
+ if (val < 0) return Qnil ;
94
+
95
+ return INT2FIX(val) ;
60
96
  }
61
97
 
62
98
  static VALUE getProcessorOnline(VALUE obj) {
63
- return INT2FIX(sysconf(_SC_NPROCESSORS_ONLN)) ;
99
+ short int val = sysconf(_SC_NPROCESSORS_ONLN) ;
100
+ if (val < 0) return Qnil ;
101
+
102
+ return INT2FIX(val) ;
64
103
  }
65
104
 
66
105
  static VALUE getUser(VALUE obj) {
@@ -27,6 +27,7 @@ require "linux_stat/memory"
27
27
  require "linux_stat/net"
28
28
  require "linux_stat/process"
29
29
  require "linux_stat/swap"
30
+ require "linux_stat/usb"
30
31
 
31
32
  # Dependent Modules
32
33
  # Modules that can have reverse dependency
@@ -1,6 +1,6 @@
1
1
  module LinuxStat
2
2
  module Battery
3
- PATH = "/sys/class/power_supply/BAT0"
3
+ PATH = "/sys/class/power_supply/BAT0".freeze
4
4
 
5
5
  class << self
6
6
  ##
@@ -34,8 +34,10 @@ module LinuxStat
34
34
  #
35
35
  # If the battery is not present or the information isn't available it will return an empty String.
36
36
  def model
37
- return ''.freeze unless model_readable?
38
- IO.read(File.join(PATH, 'model_name')).tap(&:strip!)
37
+ @@mn_file = File.join(PATH, 'model_name')
38
+ return ''.freeze unless File.readable?(@@mn_file)
39
+
40
+ IO.read(@@mn_file).tap(&:strip!)
39
41
  end
40
42
 
41
43
  ##
@@ -43,8 +45,9 @@ module LinuxStat
43
45
  #
44
46
  # If the battery is not present or the information is not available, it will return an empty String.
45
47
  def manufacturer
48
+ @@manufacturer_file ||= File.join(PATH, 'manufacturer')
46
49
  return ''.freeze unless manufacturer_readable?
47
- IO.read(File.join(PATH, 'manufacturer')).tap(&:strip!)
50
+ IO.read(@@manufacturer_file).tap(&:strip!)
48
51
  end
49
52
 
50
53
  ##
@@ -52,8 +55,9 @@ module LinuxStat
52
55
  #
53
56
  # If the battery is not present or the information is not available, it will return an empty String.
54
57
  def technology
58
+ @@technology_file ||= File.join(PATH, 'technology')
55
59
  return ''.freeze unless tech_readable?
56
- IO.read(File.join(PATH, 'technology')).tap(&:strip!)
60
+ IO.read(@@technology_file).tap(&:strip!)
57
61
  end
58
62
 
59
63
  ##
@@ -62,8 +66,9 @@ module LinuxStat
62
66
  #
63
67
  # If the battery is not present or the information is not available, it will return an empty frozen String.
64
68
  def status
69
+ @@status_file ||= File.join(PATH, 'status'.freeze)
65
70
  return ''.freeze unless status_readable?
66
- IO.read(File.join(PATH, 'status')).tap(&:strip!)
71
+ IO.read(@@status_file).tap(&:strip!)
67
72
  end
68
73
 
69
74
  ##
@@ -81,7 +86,7 @@ module LinuxStat
81
86
  # If the battery is not present or the information is not available, it will return nil.
82
87
  def discharging?
83
88
  return nil if status.empty?
84
- status.downcase == 'discharging'
89
+ status.downcase == 'discharging'.freeze
85
90
  end
86
91
 
87
92
  ##
@@ -90,7 +95,7 @@ module LinuxStat
90
95
  # If the battery is not present or the information is not available, it will return nil.
91
96
  def full?
92
97
  return nil if status.empty?
93
- status.downcase == 'full'
98
+ status.downcase == 'full'.freeze
94
99
  end
95
100
 
96
101
  ##
@@ -111,6 +116,47 @@ module LinuxStat
111
116
  percentage > 100 ? 100.0 : percentage < 0 ? 0.0 : percentage
112
117
  end
113
118
 
119
+ ##
120
+ # Returns the charge full design WH of the battery as Integer
121
+ # However if the info isn't available or there's no BAT0 in the system, this will return nil
122
+ def charge_full_design_wh
123
+ # voltage min design
124
+ @@vmd_f ||= File.join(PATH, 'voltage_min_design'.freeze)
125
+ v_m_d = File.readable?(@@vmd_f) ? IO.read(@@vmd_f).to_i : nil
126
+
127
+ # charge full design
128
+ @@cfd_f ||= File.join(PATH, 'charge_full_design'.freeze)
129
+ c_f_d = File.readable?(@@cfd_f) ? IO.read(@@cfd_f).to_i : nil
130
+
131
+ if v_m_d && c_f_d
132
+ v_m_d.fdiv(1_000_000).*(c_f_d.fdiv(1_000_000)).round(2)
133
+ else
134
+ nil
135
+ end
136
+ end
137
+
138
+ ##
139
+ # Returns the charge full WH of the battery as Integer
140
+ # However if the info isn't available or there's no BAT0 in the system, this will return nil
141
+ def charge_full_wh
142
+ # voltage min design
143
+ @@vmd_f ||= File.join(PATH, 'voltage_min_design'.freeze)
144
+ v_m_d = File.readable?(@@vmd_f) ? IO.read(@@vmd_f).to_i : nil
145
+
146
+ # charge full
147
+ @@cf_f ||= File.join(PATH, 'charge_full'.freeze)
148
+ c_f = File.readable?(@@cf_f) ? IO.read(@@cf_f).to_i : nil
149
+
150
+ if v_m_d && c_f
151
+ v_m_d.fdiv(1_000_000).*(c_f.fdiv(1_000_000)).round(2)
152
+ else
153
+ nil
154
+ end
155
+ end
156
+
157
+ ##
158
+ # Returns the voltage of the battery as Integer
159
+ # However if the info isn't available or there's no BAT0 in the system, this will return nil
114
160
  def voltage_now
115
161
  @@voltage_file ||= File.join(PATH, 'voltage_now'.freeze)
116
162
  @@voltage_readable ||= File.readable?(@@voltage_file)
@@ -119,11 +165,120 @@ module LinuxStat
119
165
  IO.read(@@voltage_file, 16).to_f.fdiv(1000000)
120
166
  end
121
167
 
122
- private
123
- def model_readable?
124
- @@model_readable ||= File.readable?(File.join(PATH, 'model_name'))
168
+ ##
169
+ # A linux system can have multiple batteries. This method attempts to
170
+ # find all of them and return a Hash based on the availibility of the
171
+ # information.
172
+ #
173
+ # This method is somewhat slower than other Battery module singleton methods.
174
+ # Because it does various checks and opens various files from /sys/
175
+ #
176
+ # For example, a sample output can be like this (taken on a test system):
177
+ #
178
+ # LinuxStat::Battery.devices_stat
179
+ # => {:AC=>{:type=>"Mains", :online=>1}, :BAT0=>{:model=>"DELL CYMGM77", :manufacturer=>"Samsung SDI", :type=>"Battery", :status=>"Full", :capacity=>100, :voltage_min_design=>11.4, :charge_full_design=>3.684, :charge_full_design_wh=>42.0, :voltage_now=>12.558, :charge_now=>2.087, :charge_now_wh=>26.21, :charge_full_wh=>23.79, :charge_percentage=>100.0}, :hidpp_battery_0=>{:model=>"Wireless Keyboard", :manufacturer=>"Logitech", :type=>"Battery", :status=>"Discharging", :online=>1}}
180
+ #
181
+ # If you need info about lots of batteries, use this method.
182
+ # If the informations are not available, it will return empty Hash for each devices.
183
+ # If the system has no batteries, it will return an empty Hash.
184
+ def devices_stat
185
+ h = {}
186
+ Dir["/sys/class/power_supply/*/".freeze].tap(&:sort!).each do |x|
187
+ # model name
188
+ mn_file = File.join(x, 'model_name'.freeze).freeze
189
+ model_name = File.readable?(mn_file) ? IO.read(mn_file).strip : nil
190
+
191
+ # manufacturer
192
+ m_f = File.join(x, 'manufacturer'.freeze).freeze
193
+ manufacturer = File.readable?(m_f) ? IO.read(m_f).strip : nil
194
+
195
+ # type
196
+ t_f = File.join(x, 'type'.freeze).freeze
197
+ type = File.readable?(t_f) ? IO.read(t_f).strip : nil
198
+
199
+ # capacity
200
+ c_file = File.join(x, 'capacity'.freeze).freeze
201
+ capacity = File.readable?(c_file) ? IO.read(c_file).to_i : nil
202
+
203
+ # voltage now
204
+ vn_f = File.join(x, 'voltage_now'.freeze).freeze
205
+ voltage_now = File.readable?(vn_f) ? IO.read(vn_f).to_i.fdiv(1_000_000) : nil
206
+
207
+ # charge now
208
+ cn_f = File.join(x, 'charge_now'.freeze).freeze
209
+ charge_now = File.readable?(cn_f) ? IO.read(cn_f).to_i.fdiv(1_000_000) : nil
210
+
211
+ # voltage min design
212
+ vmd_f = File.join(x, 'voltage_min_design'.freeze).freeze
213
+ v_m_d = File.readable?(vmd_f) ? IO.read(vmd_f).to_i.fdiv(1_000_000) : nil
214
+
215
+ # charge full design
216
+ cfd_f = File.join(x, 'charge_full_design'.freeze).freeze
217
+ c_f_d = File.readable?(cfd_f) ? IO.read(cfd_f).to_i.fdiv(1_000_000) : nil
218
+
219
+ # charge full
220
+ cf_f = File.join(x, 'charge_full'.freeze).freeze
221
+ charge_full = File.readable?(cf_f) ? IO.read(cf_f).to_i.fdiv(1_000_000) : nil
222
+
223
+ # status
224
+ s_f = File.join(x, 'status'.freeze).freeze
225
+ status = File.readable?(s_f) ? IO.read(s_f).strip : nil
226
+
227
+ # online
228
+ o_f = File.join(x, 'online'.freeze).freeze
229
+ online = File.readable?(o_f) ? IO.read(o_f).to_i : nil
230
+
231
+ charge_percentage = if charge_now && charge_full
232
+ charge_now.*(100).fdiv(charge_full).round(2)
233
+ else
234
+ nil
235
+ end
236
+
237
+ # full_charge_design (WH)
238
+ c_f_d_wh = if c_f_d && v_m_d
239
+ v_m_d.*(c_f_d).round(2)
240
+ else
241
+ nil
242
+ end
243
+
244
+ c_n_wh = if voltage_now && charge_now
245
+ voltage_now.*(charge_now).round(2)
246
+ else
247
+ nil
248
+ end
249
+
250
+ c_f_wh = if v_m_d && charge_full
251
+ v_m_d.*(charge_full).round(2)
252
+ else
253
+ nil
254
+ end
255
+
256
+ ret = {}
257
+ ret[:model] = model_name if model_name
258
+ ret[:manufacturer] = manufacturer if manufacturer
259
+ ret[:type] = type if type
260
+
261
+ ret[:status] = status if status
262
+ ret[:online] = online if online
263
+ ret[:capacity] = capacity if capacity
264
+
265
+ ret[:voltage_min_design] = v_m_d if v_m_d
266
+ ret[:charge_full_design] = c_f_d if c_f_d
267
+ ret[:charge_full_design_wh] = c_f_d_wh if c_f_d_wh
268
+
269
+ ret[:voltage_now] = voltage_now if voltage_now
270
+ ret[:charge_now] = charge_now if charge_now
271
+
272
+ ret[:charge_now_wh] = c_n_wh if c_n_wh
273
+ ret[:charge_full_wh] = c_f_wh if c_f_wh
274
+ ret[:charge_percentage] = charge_percentage if charge_percentage
275
+
276
+ h.merge!(File.split(x)[-1].to_sym => ret)
277
+ end
278
+ h
125
279
  end
126
280
 
281
+ private
127
282
  def manufacturer_readable?
128
283
  @@manufacturer_readable ||= File.readable?(File.join(PATH, 'manufacturer'))
129
284
  end
@@ -63,9 +63,9 @@ module LinuxStat
63
63
  def total_usage(sleep = ticks_to_ms_t5)
64
64
  return nil unless stat?
65
65
 
66
- data = IO.foreach('/proc/stat').first.split.tap(&:shift).map!(&:to_f)
66
+ data = IO.foreach('/proc/stat'.freeze).first.split.tap(&:shift).map!(&:to_f)
67
67
  sleep(sleep)
68
- data2 = IO.foreach('/proc/stat').first.split.tap(&:shift).map!(&:to_f)
68
+ data2 = IO.foreach('/proc/stat'.freeze).first.split.tap(&:shift).map!(&:to_f)
69
69
 
70
70
  user, nice, sys, idle, iowait, irq, softirq, steal = *data
71
71
  user2, nice2, sys2, idle2, iowait2, irq2, softirq2, steal2 = *data2
@@ -82,7 +82,7 @@ module LinuxStat
82
82
  #
83
83
  # It returns an Integer.
84
84
  #
85
- # If the information isn't available, it will return an empty Array.
85
+ # If the information isn't available, it will return nil.
86
86
  def count
87
87
  @@cpu_count ||= LinuxStat::Sysconf.processor_configured
88
88
  end
@@ -90,21 +90,65 @@ module LinuxStat
90
90
  ##
91
91
  # Returns the total number of CPU online in the sysetm.
92
92
  #
93
+ # It first reads /proc/stat, if that fails, it will
94
+ # read /sys/devices/system/cpu/online,
95
+ # if that fails it will open /proc/cpuinfo.
96
+ # If neither of the procedures work, it will get the
97
+ # LinuxStat::Sysconf.processor_online
98
+ #
93
99
  # It opens /sys/devices/system/cpu/offline and
94
100
  # performs various job to get one Ruby array.
95
101
  #
96
102
  # If the information isn't available, it will return an empty Array.
103
+ def count_online
104
+ @@cpuinfo_file ||= '/proc/cpuinfo'.freeze
105
+ @@cpuinfo_readable ||= File.readable?(@@cpuinfo_file)
106
+
107
+ @@stat_file ||= '/proc/stat'.freeze
108
+
109
+ # Not much slow, not blazing fast, somewhat reliable
110
+ get_online = online
111
+
112
+ if !get_online.empty?
113
+ get_online.length
114
+ elsif @@cpuinfo_readable
115
+ # Way slower but reliable!
116
+ IO.readlines(@@cpuinfo_file).count { |x| x.strip[/\Aprocessor.*\d*\z/] }
117
+ else
118
+ # Way faster but absolutely unrealiable!
119
+ LinuxStat::Sysconf.processor_online
120
+ end
121
+ end
122
+
123
+ ##
124
+ # Returns the total number of CPU online in the sysetm.
125
+ #
126
+ # It will read /proc/stat to get the info.
127
+ #
128
+ # If the info isn't available, it reads /sys/devices/system/cpu/onfline and
129
+ # performs various job to get one Ruby array.
130
+ #
131
+ # If the information isn't available, it will return an empty Array.
97
132
  def online
98
133
  @@online_file ||= '/sys/devices/system/cpu/online'.freeze
99
134
  @@online_readable ||= File.readable?(@@online_file)
100
- return [] unless @@online_readable
135
+
136
+ @@stat_file ||= '/proc/stat'.freeze
101
137
 
102
138
  ret = []
103
- IO.read(@@online_file).split(?,.freeze).each { |x|
104
- x.strip!
105
- c = x.split(?-.freeze).map(&:to_i)
106
- ret.concat(c.length == 2 ? Range.new(*c).to_a : c)
107
- }
139
+
140
+ if stat?
141
+ IO.readlines(@@stat_file).map { |x|
142
+ v = x.strip[/\Acpu\d*/] &.[](/\d/)
143
+ ret << v.to_i if v
144
+ }
145
+ elsif @@online_readable
146
+ IO.read(@@online_file).split(?,.freeze).each { |x|
147
+ x.strip!
148
+ c = x.split(?-.freeze).map(&:to_i)
149
+ ret.concat(c.length == 2 ? Range.new(*c).to_a : c)
150
+ }
151
+ end
108
152
 
109
153
  ret
110
154
  end
@@ -269,7 +313,8 @@ module LinuxStat
269
313
  # ticks to ms times 5
270
314
  # If the ticks is 100, it will return 0.05
271
315
  def ticks_to_ms_t5
272
- @@ms_t5 ||= 1.0 / LinuxStat::Sysconf.sc_clk_tck * 5
316
+ @@sc_clk_tck ||= LinuxStat::Sysconf.sc_clk_tck.to_i
317
+ @@ms_t5 ||= 1.0 / (@@sc_clk_tck < 1 ? 100 : @@sc_clk_tck) * 5
273
318
  end
274
319
 
275
320
  def cpus