linux_stat 2.2.3 → 2.5.1
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.
- checksums.yaml +4 -4
- data/README.md +41 -8
- data/exe/linuxstat.rb +152 -102
- data/ext/fs_stat/disk_stat.h +25 -0
- data/ext/fs_stat/extconf.rb +2 -1
- data/ext/fs_stat/fs_stat.c +10 -1
- data/ext/fs_stat/sector_size.h +13 -0
- data/ext/misc/integer/extconf.rb +2 -0
- data/ext/misc/integer/integer?.c +63 -0
- data/ext/nproc/nproc.c +1 -1
- data/ext/procfs/loadavg_pid.h +1 -1
- data/ext/procfs/procfs.c +6 -0
- data/ext/procfs/stat.h +69 -3
- data/ext/procfs/statm.h +5 -5
- data/ext/procfs/uptime.h +1 -1
- data/ext/sysconf/sysconf.c +17 -17
- data/ext/sysinfo/sysinfo.c +11 -11
- data/ext/utsname/utsname.c +5 -5
- data/lib/linux_stat/battery.rb +1 -1
- data/lib/linux_stat/cpu.rb +121 -12
- data/lib/linux_stat/filesystem.rb +45 -0
- data/lib/linux_stat/mounts.rb +3 -3
- data/lib/linux_stat/net.rb +2 -2
- data/lib/linux_stat/os.rb +2 -1
- data/lib/linux_stat/pci.rb +9 -9
- data/lib/linux_stat/process.rb +14 -24
- data/lib/linux_stat/process_info.rb +1 -1
- data/lib/linux_stat/swap.rb +2 -1
- data/lib/linux_stat/thermal.rb +4 -4
- data/lib/linux_stat/usb.rb +10 -10
- data/lib/linux_stat/user.rb +10 -4
- data/lib/linux_stat/version.rb +1 -1
- data/lib/linux_stat.rb +1 -0
- metadata +8 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2fd7fd4cae80d13f9e3004928809ada275053cffc32630d05f7ab3f1fb9c2514
|
4
|
+
data.tar.gz: 36f07d5f2f149979466a30d63d6d8cc31e77a028454be0bbe25b2af0513e1bb4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2ef9b96aacee268b4c0d74a8093d4161a0d21fea3165533c0d0f993c6cda302f1e96f51a1292192b18ffed35b2a0f6e83fdb2ac03583da8e088e97ec2c230f19
|
7
|
+
data.tar.gz: 82c397f568ebfd7f578b401ec245b10971412931b06df1433e6637848f506a642eb68046025ad3c3a66bafe678aea1b4845507cbc9a2a13d80f107ec93d667c4
|
data/README.md
CHANGED
@@ -38,18 +38,36 @@ It only works on Linux, and detecting the OS is upto the user of this gem.
|
|
38
38
|
2. Ruby: Ruby 2.3.0 and above.
|
39
39
|
|
40
40
|
## Build Dependencies:
|
41
|
-
|
42
|
-
|
41
|
+
#### You need to have the C compiler installed to be able to compile the C extensions.
|
42
|
+
|
43
|
+
+ On Arch Linux / Manjaro / Archlabs / Other Arch Based Distributions
|
44
|
+
```
|
45
|
+
# pacman -S gcc make ruby
|
46
|
+
```
|
47
|
+
|
48
|
+
+ On Debian / Ubuntu / Linux Mint / Pop!_OS / Raspberry Pi OS / Other Debian Based Distributions
|
49
|
+
```
|
50
|
+
# apt install gcc build-essential ruby ruby-dev build-essential
|
51
|
+
```
|
52
|
+
|
53
|
+
+ Gentoo / Gentoo Based Distributions
|
54
|
+
```
|
55
|
+
# emerge --ask dev-lang/ruby
|
56
|
+
```
|
57
|
+
|
58
|
+
+ Fedora / AmazonLinux* / CentOS* / Other RedHat Based Distributions
|
43
59
|
```
|
44
|
-
#
|
60
|
+
# yum install gcc ruby-devel ruby make
|
45
61
|
```
|
46
62
|
|
47
|
-
|
63
|
+
You can run linux_stat on *AmazonLinux and *CentOS if you have Ruby 2.3.0+.
|
64
|
+
|
65
|
+
+ OpenSUSE
|
48
66
|
```
|
49
|
-
#
|
67
|
+
# zypper install gcc ruby ruby-devel make
|
50
68
|
```
|
51
69
|
|
52
|
-
+ You can remove the packages once the
|
70
|
+
+ You can remove the above packages once the gem is installed.
|
53
71
|
|
54
72
|
---
|
55
73
|
|
@@ -62,13 +80,28 @@ You can install hwdata simply.
|
|
62
80
|
+ Arch:
|
63
81
|
|
64
82
|
```
|
65
|
-
|
83
|
+
# pacman -S hwids
|
66
84
|
```
|
67
85
|
|
68
86
|
+ Debian based systems:
|
69
87
|
|
70
88
|
```
|
71
|
-
|
89
|
+
# apt install hwdata
|
90
|
+
```
|
91
|
+
|
92
|
+
+ Gentoo / Gentoo Based Distributions
|
93
|
+
```
|
94
|
+
# emerge --ask sys-apps/hwids
|
95
|
+
```
|
96
|
+
|
97
|
+
+ Fedora / Amazon Linux / CentOS
|
98
|
+
```
|
99
|
+
# yum install hwdata
|
100
|
+
```
|
101
|
+
|
102
|
+
+ OpenSUSE
|
103
|
+
```
|
104
|
+
zypper install hwdata
|
72
105
|
```
|
73
106
|
|
74
107
|
But without hwdata, it won't show such information.
|
data/exe/linuxstat.rb
CHANGED
@@ -7,6 +7,12 @@ rescue LoadError
|
|
7
7
|
abort "The Gem needs to be installed before this test can be run!"
|
8
8
|
end
|
9
9
|
|
10
|
+
# Time reporting format
|
11
|
+
T_FMT = '%d'.freeze
|
12
|
+
|
13
|
+
# Check the number of iterations
|
14
|
+
iterations = (ARGV.find { |x| LinuxStat::Misc.integer?(x) } || 1).to_i
|
15
|
+
|
10
16
|
Integer.class_exec do
|
11
17
|
define_method(:clamp) { |min, max|
|
12
18
|
self < min ? min : self > max ? max : self
|
@@ -67,14 +73,14 @@ conflicting.each do |x, y, z|
|
|
67
73
|
rev = ARGV.reverse
|
68
74
|
|
69
75
|
if rev.index { |_x| _x[y] } < rev.index { |_x| _x[z] }
|
70
|
-
hash.
|
76
|
+
hash.store(o1, true)
|
71
77
|
else
|
72
|
-
hash.
|
78
|
+
hash.store(o2, true)
|
73
79
|
end
|
74
80
|
elsif m1
|
75
|
-
hash.
|
81
|
+
hash.store(o1, true)
|
76
82
|
elsif m2
|
77
|
-
hash.
|
83
|
+
hash.store(o2, true)
|
78
84
|
end
|
79
85
|
end
|
80
86
|
|
@@ -100,122 +106,166 @@ execute = constants.map(&:downcase).map.with_index { |x, i|
|
|
100
106
|
execute.replace(constants) if execute.empty?
|
101
107
|
HEXAGONS = %W(\u2b22 \u2b23 \u2B53 \u2B1F)
|
102
108
|
|
103
|
-
|
104
|
-
|
109
|
+
puts " #{HEXAGONS.rotate![0]} LinuxStat: #{LinuxStat::VERSION}"
|
110
|
+
puts " #{HEXAGONS.rotate![0]} Test Modules: #{execute.size}"
|
111
|
+
puts " #{HEXAGONS.rotate![0]} Iterations: #{iterations}"
|
105
112
|
|
106
|
-
|
113
|
+
puts " #{HEXAGONS.rotate![0]} Format: Markdown" if MARKDOWN
|
114
|
+
puts " #{HEXAGONS.rotate![0]} Format: HTML" if HTML
|
107
115
|
|
108
|
-
|
116
|
+
sleep 2
|
117
|
+
puts
|
109
118
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
end
|
119
|
+
def get_colour(n)
|
120
|
+
if n > 10_000
|
121
|
+
"\e[1;38;2;255;50;50m"
|
122
|
+
elsif n > 5_000
|
123
|
+
"\e[1;38;2;255;170;0m"
|
124
|
+
else
|
125
|
+
"\e[1;38;2;0;170;0m"
|
118
126
|
end
|
127
|
+
end
|
128
|
+
|
129
|
+
total_real_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
130
|
+
total_cpu_time = Process.times
|
131
|
+
|
132
|
+
iterations.times do
|
133
|
+
execute.sort.each do |c|
|
134
|
+
e = eval("LinuxStat::#{c}")
|
135
|
+
|
136
|
+
next if e.class != Module && e.class != Class
|
119
137
|
|
120
|
-
|
121
|
-
arg = nil
|
138
|
+
meths = e.methods(false).sort
|
122
139
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
arg = '/'
|
140
|
+
if meths.length > 0
|
141
|
+
if MARKDOWN
|
142
|
+
puts "### LinuxStat::#{c}\n```"
|
143
|
+
elsif HTML
|
144
|
+
puts "<h3>LinuxStat::#{c}</h3>\n<pre>"
|
129
145
|
else
|
130
|
-
|
146
|
+
puts "\e[1;4;38;2;255;240;0mLinuxStat::#{c}\e[0m"
|
131
147
|
end
|
132
148
|
end
|
133
149
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
150
|
+
meths.each do |meth|
|
151
|
+
arg = nil
|
152
|
+
|
153
|
+
arity = e.method(meth).arity
|
154
|
+
if arity > 0 || arity == -2
|
155
|
+
if c == :PrettifyBytes
|
156
|
+
arg = rand(10 ** 15)
|
157
|
+
elsif c == :FS
|
158
|
+
arg = '/'
|
159
|
+
else
|
160
|
+
next
|
161
|
+
end
|
145
162
|
end
|
146
|
-
end
|
147
163
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
source = e.singleton_method(meth).source_location.to_a
|
162
|
-
src, src_meth, src_ret = '', '', ''
|
163
|
-
|
164
|
-
unless source.empty?
|
165
|
-
src << " File:\t\t#{File.split(source[0])[-1]} | Line: #{source[1]}\n"
|
166
|
-
src_meth << " Definition:\t#{IO.foreach(source[0]).first(source[1])[-1].strip}\n"
|
167
|
-
|
168
|
-
src_ret << " Returns:\t" << case ret
|
169
|
-
when Array then 'Array | Empty Array'
|
170
|
-
when Complex then 'Complex | nil'
|
171
|
-
when Float then 'Float | nil'
|
172
|
-
when Hash then 'Hash | Empty Hash'
|
173
|
-
when Integer then 'Integer | nil'
|
174
|
-
when Rational then 'Rational | nil'
|
175
|
-
when String then "String | (Frozen) Empty String"
|
176
|
-
when Time then 'Time | nil'
|
177
|
-
when true, false then 'True or False | nil'
|
178
|
-
when nil then 'nil'
|
179
|
-
else ''
|
180
|
-
end << ?\n.freeze if PRINT_TYPE
|
181
|
-
|
182
|
-
if MARKDOWN || HTML
|
183
|
-
src.prepend('#'.freeze)
|
184
|
-
src_meth.prepend('#'.freeze)
|
185
|
-
src_ret.prepend(?#.freeze) if PRINT_TYPE
|
186
|
-
else
|
187
|
-
src.prepend(HEXAGONS.rotate![0].freeze)
|
188
|
-
src_meth.prepend(HEXAGONS.rotate![0].freeze)
|
189
|
-
src_ret.prepend(HEXAGONS.rotate![0].freeze) if PRINT_TYPE
|
164
|
+
params = e.method(meth).parameters
|
165
|
+
param = ''
|
166
|
+
params.each do |p|
|
167
|
+
case p[0]
|
168
|
+
when :opt
|
169
|
+
param << "#{p[1]}, "
|
170
|
+
when :key
|
171
|
+
param << "#{p[1]}:, "
|
172
|
+
when :req
|
173
|
+
_arg = arg ? " = #{arg.inspect}" : ''.freeze
|
174
|
+
param << "#{p[1] || 'arg'}#{_arg}, "
|
175
|
+
end
|
190
176
|
end
|
191
|
-
end
|
192
177
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
178
|
+
param.chomp!(", ")
|
179
|
+
|
180
|
+
disp_meth = "#{meth}"
|
181
|
+
disp_meth.concat(arg ? "(#{param})" : "(#{param})")
|
182
|
+
|
183
|
+
time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
184
|
+
cputime = Process.times
|
185
|
+
|
186
|
+
ret = arg ? e.send(meth, arg) : e.send(meth)
|
187
|
+
|
188
|
+
time2 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
189
|
+
cputime2 = Process.times
|
190
|
+
|
191
|
+
time = time2.-(time).*(1_000_000)
|
192
|
+
cputime = cputime2.stime.+(cputime2.utime).-(cputime.stime + cputime.utime).*(1_000_000)
|
193
|
+
|
194
|
+
v = ret.inspect
|
195
|
+
dis = v.length > 253 ? v[0..250].strip + '...'.freeze : v
|
196
|
+
|
197
|
+
source = e.singleton_method(meth).source_location.to_a
|
198
|
+
src, src_meth, src_ret = '', '', ''
|
199
|
+
|
200
|
+
unless source.empty?
|
201
|
+
src << " File:\t\t#{File.split(source[0])[-1]} | Line: #{source[1]}\n"
|
202
|
+
src_meth << " Definition:\t#{IO.foreach(source[0]).first(source[1])[-1].strip}\n"
|
203
|
+
|
204
|
+
src_ret << " Returns:\t" << case ret
|
205
|
+
when Array then 'Array | Empty Array'
|
206
|
+
when Complex then 'Complex | nil'
|
207
|
+
when Float then 'Float | nil'
|
208
|
+
when Hash then 'Hash | Empty Hash'
|
209
|
+
when Integer then 'Integer | nil'
|
210
|
+
when Rational then 'Rational | nil'
|
211
|
+
when String then "String | (Frozen) Empty String"
|
212
|
+
when Time then 'Time | nil'
|
213
|
+
when true, false then 'True or False | nil'
|
214
|
+
when nil then 'nil'
|
215
|
+
else ''
|
216
|
+
end << ?\n.freeze if PRINT_TYPE
|
217
|
+
|
218
|
+
if MARKDOWN || HTML
|
219
|
+
src.prepend('#'.freeze)
|
220
|
+
src_meth.prepend('#'.freeze)
|
221
|
+
src_ret.prepend(?#.freeze) if PRINT_TYPE
|
222
|
+
else
|
223
|
+
src.prepend(HEXAGONS.rotate![0].freeze)
|
224
|
+
src_meth.prepend(HEXAGONS.rotate![0].freeze)
|
225
|
+
src_ret.prepend(HEXAGONS.rotate![0].freeze) if PRINT_TYPE
|
226
|
+
end
|
227
|
+
end
|
200
228
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
"\e[1;38;2;255;170;0m"
|
229
|
+
if MARKDOWN
|
230
|
+
puts "#{src}#{src_meth}#{src_ret}#{e}.#{disp_meth}\n=> #{dis}"
|
231
|
+
elsif HTML
|
232
|
+
puts "#{src}#{src_meth}#{src_ret}#{e}.#{disp_meth}\n=> #{dis}"
|
206
233
|
else
|
207
|
-
"\e[1;38;2;
|
208
|
-
end
|
209
|
-
) if PRINT_TIME
|
234
|
+
puts "\e[1m#{src.colourize}\e[1m#{src_meth.colourize(6)}\e[1m#{src_ret.colourize(1)}\e[0m\e[1;38;2;80;80;255m#{e}.#{disp_meth}\e[0m\n=> #{dis}"
|
235
|
+
end
|
210
236
|
|
211
|
-
|
212
|
-
|
237
|
+
if PRINT_TIME
|
238
|
+
time_colour = get_colour(time)
|
239
|
+
cputime_colour = get_colour(cputime)
|
240
|
+
|
241
|
+
puts "[Real Time: #{time_colour}#{T_FMT % time}\u03BCs\e[0m, "\
|
242
|
+
"CPU Time: #{cputime_colour}#{T_FMT % cputime}\u03BCs\e[0m]"
|
243
|
+
end
|
244
|
+
|
245
|
+
puts
|
246
|
+
end
|
213
247
|
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
248
|
+
if meths.length > 0
|
249
|
+
if MARKDOWN
|
250
|
+
puts "```\n\n"
|
251
|
+
elsif HTML
|
252
|
+
puts "</pre>"
|
253
|
+
end
|
219
254
|
end
|
220
255
|
end
|
221
256
|
end
|
257
|
+
|
258
|
+
if PRINT_TIME
|
259
|
+
total_real_time2 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
260
|
+
total_cpu_time2 = Process.times
|
261
|
+
|
262
|
+
total_real_t = total_real_time2.-(total_real_time).*(1_000_000)
|
263
|
+
|
264
|
+
total_cpu_t = total_cpu_time2.stime.+(total_cpu_time2.utime).-(
|
265
|
+
total_cpu_time.stime + total_cpu_time.utime
|
266
|
+
).*(1_000_000)
|
267
|
+
|
268
|
+
puts "\e[38;2;255;255;0m:: Warning total time also depends on your terminal speed!\e[0m"
|
269
|
+
puts "Total Real Time: #{T_FMT % total_real_t}\u03BCs"
|
270
|
+
puts "Total CPU Time: #{T_FMT % total_cpu_t}\u03BCs"
|
271
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
static VALUE getDiskStats (volatile VALUE obj, volatile VALUE path) {
|
2
|
+
FILE *file = fopen("/proc/diskstats", "r") ;
|
3
|
+
if(!file) return rb_ary_new() ;
|
4
|
+
|
5
|
+
char lines[120] ;
|
6
|
+
unsigned long long read, write ;
|
7
|
+
char *p = StringValuePtr(path) ;
|
8
|
+
|
9
|
+
while(fgets(lines, 119, file)) {
|
10
|
+
sscanf(lines, "%*s %*s %s %*s %*s %llu %*s %*s %*s %llu", lines, &read, &write) ;
|
11
|
+
|
12
|
+
if(strcmp(lines, p) == 0) {
|
13
|
+
fclose(file) ;
|
14
|
+
|
15
|
+
return rb_ary_new_from_args(
|
16
|
+
2,
|
17
|
+
ULL2NUM(read),
|
18
|
+
ULL2NUM(write)
|
19
|
+
) ;
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
23
|
+
fclose(file) ;
|
24
|
+
return rb_ary_new() ;
|
25
|
+
}
|
data/ext/fs_stat/extconf.rb
CHANGED
@@ -4,7 +4,8 @@ unless have_const('linux') || RbConfig::CONFIG['arch'].to_s[/linux/]
|
|
4
4
|
abort('Platform is not linux')
|
5
5
|
end
|
6
6
|
|
7
|
-
unless have_header('sys/statvfs.h') && have_header('
|
7
|
+
unless have_header('sys/statvfs.h') && have_header('sys/ioctl.h') &&
|
8
|
+
have_header('fcntl.h') && have_header('linux/fs.h') && have_header('unistd.h')
|
8
9
|
abort('Missing header')
|
9
10
|
end
|
10
11
|
|
data/ext/fs_stat/fs_stat.c
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
#include <sys/statvfs.h>
|
2
|
+
#include <sys/ioctl.h>
|
3
|
+
#include <fcntl.h>
|
4
|
+
#include <linux/fs.h>
|
5
|
+
#include <unistd.h>
|
6
|
+
|
2
7
|
#include "ruby.h"
|
8
|
+
#include "sector_size.h"
|
9
|
+
#include "disk_stat.h"
|
3
10
|
|
4
11
|
#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER)
|
5
12
|
#pragma GCC optimize ("O3")
|
@@ -11,7 +18,7 @@
|
|
11
18
|
#pragma intel optimization_level 3
|
12
19
|
#endif
|
13
20
|
|
14
|
-
static VALUE statfs(VALUE obj, VALUE dir) {
|
21
|
+
static VALUE statfs(volatile VALUE obj, volatile VALUE dir) {
|
15
22
|
struct statvfs buf ;
|
16
23
|
char *d = StringValuePtr(dir) ;
|
17
24
|
VALUE hash = rb_hash_new() ;
|
@@ -36,4 +43,6 @@ void Init_fs_stat() {
|
|
36
43
|
VALUE _linux_stat = rb_define_module("LinuxStat") ;
|
37
44
|
VALUE fs = rb_define_module_under(_linux_stat, "FS") ;
|
38
45
|
rb_define_module_function(fs, "stat", statfs, 1) ;
|
46
|
+
rb_define_module_function(fs, "sectors", getSectorSize, 1) ;
|
47
|
+
rb_define_module_function(fs, "total_io", getDiskStats, 1) ;
|
39
48
|
}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
static VALUE getSectorSize(volatile VALUE obj, volatile VALUE path) {
|
2
|
+
char *dev = StringValuePtr(path) ;
|
3
|
+
|
4
|
+
unsigned int fd = open(dev, O_RDONLY | O_NONBLOCK) ;
|
5
|
+
if(fd < 0) return Qnil ;
|
6
|
+
|
7
|
+
unsigned int sSize = 0 ;
|
8
|
+
short status = ioctl(fd, BLKSSZGET, &sSize) ;
|
9
|
+
close(fd) ;
|
10
|
+
if(status < 0) return Qnil ;
|
11
|
+
|
12
|
+
return UINT2NUM(sSize) ;
|
13
|
+
}
|
@@ -0,0 +1,63 @@
|
|
1
|
+
/*
|
2
|
+
Validates if a String is integer or not.
|
3
|
+
|
4
|
+
Conditions:
|
5
|
+
- The String can start with - (negative)
|
6
|
+
- If the Argument is a BigInt or Integer, or anything else, return false
|
7
|
+
- The String cannot have anything other than 0 to 9
|
8
|
+
- The String can have leading zeroes and negative sign:
|
9
|
+
Example 1: "-00999" which translates to Ruby's -999 (decimal)
|
10
|
+
Example 2: "000999" translates to 999
|
11
|
+
- If it fails to determine, it returns nil instead of false
|
12
|
+
- It doesn't raise any error. Handing nil is enough to indicate that it failed.
|
13
|
+
*/
|
14
|
+
|
15
|
+
#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER)
|
16
|
+
#pragma GCC optimize ("O3")
|
17
|
+
#pragma GCC diagnostic warning "-Wall"
|
18
|
+
#elif defined(__clang__)
|
19
|
+
#pragma clang optimize on
|
20
|
+
#pragma clang diagnostic warning "-Wall"
|
21
|
+
#elif defined(__INTEL_COMPILER)
|
22
|
+
#pragma intel optimization_level 3
|
23
|
+
#endif
|
24
|
+
|
25
|
+
#include <limits.h>
|
26
|
+
#include "ruby.h"
|
27
|
+
|
28
|
+
VALUE isNumber(volatile VALUE obj, volatile VALUE val) {
|
29
|
+
// But we don't expect anything other than String though as Argument.
|
30
|
+
// Note that raising ArgumentError or any kind of Error shouldn't be done here
|
31
|
+
// Otherwise Integer(n) is the best method in Ruby.
|
32
|
+
if (!RB_TYPE_P(val, T_STRING))
|
33
|
+
return Qnil ;
|
34
|
+
|
35
|
+
char *str = StringValuePtr(val) ;
|
36
|
+
char ch = str[0] ;
|
37
|
+
|
38
|
+
// If the string is empty, return false
|
39
|
+
if (!ch) return Qfalse ;
|
40
|
+
|
41
|
+
unsigned char i = ch == '-' ? 1 : 0 ;
|
42
|
+
if (!str[i]) return Qfalse ;
|
43
|
+
|
44
|
+
unsigned char max = UCHAR_MAX ;
|
45
|
+
|
46
|
+
# pragma GCC unroll 4
|
47
|
+
while((ch = str[i++])) {
|
48
|
+
if (ch < 48 || ch > 57)
|
49
|
+
return Qfalse ;
|
50
|
+
|
51
|
+
if (i == max)
|
52
|
+
return Qnil ;
|
53
|
+
}
|
54
|
+
|
55
|
+
return Qtrue ;
|
56
|
+
}
|
57
|
+
|
58
|
+
void Init_integer() {
|
59
|
+
VALUE linuxStat = rb_define_module("LinuxStat") ;
|
60
|
+
VALUE misc = rb_define_module_under(linuxStat, "Misc") ;
|
61
|
+
|
62
|
+
rb_define_module_function(misc, "integer?", isNumber, 1) ;
|
63
|
+
}
|
data/ext/nproc/nproc.c
CHANGED
@@ -15,7 +15,7 @@
|
|
15
15
|
#pragma intel optimization_level 3
|
16
16
|
#endif
|
17
17
|
|
18
|
-
static VALUE count_cpu_for_pid(VALUE obj, VALUE pid) {
|
18
|
+
static VALUE count_cpu_for_pid(volatile VALUE obj, volatile VALUE pid) {
|
19
19
|
cpu_set_t set ;
|
20
20
|
CPU_ZERO(&set) ;
|
21
21
|
char status = sched_getaffinity(FIX2INT(pid), sizeof(set), &set) ;
|
data/ext/procfs/loadavg_pid.h
CHANGED
data/ext/procfs/procfs.c
CHANGED
@@ -13,6 +13,7 @@
|
|
13
13
|
#include <stdio.h>
|
14
14
|
#include <unistd.h>
|
15
15
|
#include <string.h>
|
16
|
+
#include <glob.h>
|
16
17
|
#include "ruby.h"
|
17
18
|
#include "uptime.h"
|
18
19
|
#include "statm.h"
|
@@ -22,6 +23,8 @@
|
|
22
23
|
int Init_procfs() {
|
23
24
|
VALUE _linux_stat = rb_define_module("LinuxStat") ;
|
24
25
|
VALUE _procfs = rb_define_module_under(_linux_stat, "ProcFS") ;
|
26
|
+
VALUE _cpu = rb_define_module_under(_linux_stat, "CPU") ;
|
27
|
+
VALUE _process = rb_define_module_under(_linux_stat, "Process") ;
|
25
28
|
|
26
29
|
// uptime
|
27
30
|
rb_define_module_function(_procfs, "uptime_f", uptime_f, 0) ;
|
@@ -40,4 +43,7 @@ int Init_procfs() {
|
|
40
43
|
rb_define_module_function(_procfs, "ps_state", ps_state, 1) ;
|
41
44
|
rb_define_module_function(_procfs, "ps_times", ps_times, 1) ;
|
42
45
|
rb_define_module_function(_procfs, "ps_stat", ps_stat, 1) ;
|
46
|
+
rb_define_module_function(_procfs, "cpu_times", cpuTimes, 0) ;
|
47
|
+
rb_define_module_function(_procfs, "list_process", listProcess, 0) ;
|
48
|
+
|
43
49
|
}
|
data/ext/procfs/stat.h
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
VALUE ps_state(VALUE obj, VALUE pid) {
|
1
|
+
static VALUE ps_state(volatile VALUE obj, volatile VALUE pid) {
|
2
2
|
int _pid = FIX2INT(pid) ;
|
3
3
|
if (_pid < 0) return rb_str_new_cstr("") ;
|
4
4
|
|
@@ -17,7 +17,30 @@ VALUE ps_state(VALUE obj, VALUE pid) {
|
|
17
17
|
return rb_str_new_cstr(_s) ;
|
18
18
|
}
|
19
19
|
|
20
|
-
VALUE
|
20
|
+
static VALUE listProcess(volatile VALUE obj) {
|
21
|
+
VALUE ary = rb_ary_new() ;
|
22
|
+
|
23
|
+
glob_t globlist ;
|
24
|
+
int status = glob("/proc/[0-9]*/", GLOB_NOSORT, NULL, &globlist) ;
|
25
|
+
|
26
|
+
if (status == GLOB_NOSPACE || status == GLOB_ABORTED || status == GLOB_NOMATCH) {
|
27
|
+
globfree(&globlist) ;
|
28
|
+
return ary ;
|
29
|
+
}
|
30
|
+
|
31
|
+
char *v, *token ;
|
32
|
+
unsigned int i = 0 ;
|
33
|
+
unsigned int num ;
|
34
|
+
|
35
|
+
while(v = globlist.gl_pathv[i++]) {
|
36
|
+
if (sscanf(v, "/proc/%u", &num) == 1) rb_ary_push(ary, UINT2NUM(num)) ;
|
37
|
+
}
|
38
|
+
|
39
|
+
globfree(&globlist) ;
|
40
|
+
return ary ;
|
41
|
+
}
|
42
|
+
|
43
|
+
static VALUE ps_times(volatile VALUE obj, volatile VALUE pid) {
|
21
44
|
int _pid = FIX2INT(pid) ;
|
22
45
|
if (_pid < 0) return Qnil ;
|
23
46
|
|
@@ -38,7 +61,7 @@ VALUE ps_times(VALUE obj, VALUE pid) {
|
|
38
61
|
return DBL2NUM(total_time) ;
|
39
62
|
}
|
40
63
|
|
41
|
-
VALUE ps_stat(VALUE obj, VALUE pid) {
|
64
|
+
static VALUE ps_stat(volatile VALUE obj, volatile VALUE pid) {
|
42
65
|
int _pid = FIX2INT(pid) ;
|
43
66
|
if (_pid < 0) return rb_str_new_cstr("") ;
|
44
67
|
|
@@ -117,3 +140,46 @@ VALUE ps_stat(VALUE obj, VALUE pid) {
|
|
117
140
|
INT2NUM(exit_code)
|
118
141
|
) ;
|
119
142
|
}
|
143
|
+
|
144
|
+
static VALUE cpuTimes(volatile VALUE obj) {
|
145
|
+
VALUE ary = rb_ary_new() ;
|
146
|
+
FILE *f = fopen("/proc/stat", "r") ;
|
147
|
+
|
148
|
+
if (!f) return ary ;
|
149
|
+
|
150
|
+
unsigned long user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice ;
|
151
|
+
char line[1024] ;
|
152
|
+
char cpuCode[7] ;
|
153
|
+
float ticks = sysconf(_SC_CLK_TCK) ;
|
154
|
+
char scanStatus ;
|
155
|
+
|
156
|
+
while(fgets(line, 1023, f)) {
|
157
|
+
if (!(line[0] == 'c' && line[1] == 'p' && line[2] == 'u')) break ;
|
158
|
+
|
159
|
+
scanStatus = sscanf(line,
|
160
|
+
"%7[cpu0-9] %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu",
|
161
|
+
cpuCode, &user, &nice, &system, &idle, &iowait, &irq, &softirq, &steal, &guest, &guest_nice
|
162
|
+
) ;
|
163
|
+
|
164
|
+
if (scanStatus != 11) break ;
|
165
|
+
|
166
|
+
VALUE innerHash = rb_hash_new() ;
|
167
|
+
rb_hash_aset(innerHash, ID2SYM(rb_intern("cpu")), rb_str_new_cstr(cpuCode)) ;
|
168
|
+
rb_hash_aset(innerHash, ID2SYM(rb_intern("user")), rb_float_new(user / ticks)) ;
|
169
|
+
rb_hash_aset(innerHash, ID2SYM(rb_intern("nice")), rb_float_new(nice / ticks)) ;
|
170
|
+
rb_hash_aset(innerHash, ID2SYM(rb_intern("system")), rb_float_new(system / ticks)) ;
|
171
|
+
rb_hash_aset(innerHash, ID2SYM(rb_intern("idle")), rb_float_new(idle / ticks)) ;
|
172
|
+
rb_hash_aset(innerHash, ID2SYM(rb_intern("iowait")), rb_float_new(iowait / ticks)) ;
|
173
|
+
rb_hash_aset(innerHash, ID2SYM(rb_intern("irq")), rb_float_new(irq / ticks)) ;
|
174
|
+
rb_hash_aset(innerHash, ID2SYM(rb_intern("softirq")), rb_float_new(softirq / ticks)) ;
|
175
|
+
rb_hash_aset(innerHash, ID2SYM(rb_intern("steal")), rb_float_new(steal / ticks)) ;
|
176
|
+
rb_hash_aset(innerHash, ID2SYM(rb_intern("guest")), rb_float_new(guest / ticks)) ;
|
177
|
+
rb_hash_aset(innerHash, ID2SYM(rb_intern("guest_nice")), rb_float_new(guest_nice / ticks)) ;
|
178
|
+
|
179
|
+
rb_ary_push(ary, innerHash) ;
|
180
|
+
}
|
181
|
+
|
182
|
+
fclose(f) ;
|
183
|
+
|
184
|
+
return ary ;
|
185
|
+
}
|