sys-memory 0.2.0 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9c4673911e1763e8282380312020206b04a9fb268572d3b64e8fc0a631befa03
4
- data.tar.gz: 28e0b52dd179b98a4896dab5442bac98beb538fea493d0db5ea113b6148ed70d
3
+ metadata.gz: 457079deac5b71c2aa7827dc99fd05ad3a2096937db1d59d0824fa9d19307fc3
4
+ data.tar.gz: 8d3a0331639955099db7909cace2e596a5972573053ec88f4f7e9013051ae474
5
5
  SHA512:
6
- metadata.gz: f6b1f2cf5a71c94be2dc997fb7e4c3d91a2d32c83af4b7399cba169c8ef36d20382decb1d35e020d7c7b7f7651957d1a1deb105e748db66087f071aae20879a8
7
- data.tar.gz: 0c4f87e99e7b69148c0abcbfed29217a2fac229eff5237a3f632bfd2994dc89d6b432c63169a9e5bef1ab1f432f81330617bddef72f6a3092770fbcaaac49eb6
6
+ metadata.gz: 3e3c784ef9a72e5c8f1a1ed0a8de66355381fb8391744440c621346b965dc45d55276737a9d4417ec8057550bb561ed54285dbf1935b33abbfc723b89cdeaef1
7
+ data.tar.gz: a8910b5ad70f11cea073144e08a9db16b876669ec2611bf75cb8e6624e6ac2d0c88dae07fe28f0ef387e1feca55c57d989dc5e042f79c351072a7137d107f36a
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGES.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## 0.2.1 - 2-Jun-2026
2
+ * Fixed swap for FreeBSD.
3
+ * Rubocop fixes.
4
+ * Some spec updates.
5
+ * Minor Rakefile updates.
6
+
1
7
  ## 0.2.0 - 12-Jun-2024
2
8
  * Added support for DragonflyBSD. Currently the default implementation
3
9
  for all BSD platforms.
data/Rakefile CHANGED
@@ -5,7 +5,10 @@ require 'rubocop/rake_task'
5
5
 
6
6
  CLEAN.include('**/*.gem', '**/*.rbc', '**/*.rbx', '**/*.lock')
7
7
 
8
- RSpec::Core::RakeTask.new(:spec)
8
+ RSpec::Core::RakeTask.new(:spec) do |t|
9
+ t.verbose = false
10
+ t.rspec_opts = '-f documentation -w'
11
+ end
9
12
 
10
13
  namespace 'gem' do
11
14
  desc "Create the sys-memory gem"
@@ -25,4 +28,9 @@ end
25
28
 
26
29
  RuboCop::RakeTask.new
27
30
 
31
+ # Clean up afterwards
32
+ Rake::Task[:spec].enhance do
33
+ Rake::Task[:clean].invoke
34
+ end
35
+
28
36
  task :default => :spec
@@ -7,10 +7,34 @@ module Sys
7
7
  # The Memory module is a house for memory related singleton methods that don't require state.
8
8
  module Memory
9
9
  extend FFI::Library
10
+
10
11
  ffi_lib FFI::Library::LIBC
11
12
 
12
13
  attach_function :sysctlbyname, %i[string pointer pointer pointer size_t], :int
13
14
 
15
+ if RbConfig::CONFIG['host_os'] =~ /freebsd/i
16
+ ffi_lib FFI::Library::LIBC, FFI.map_library_name('kvm')
17
+
18
+ attach_function :kvm_openfiles, %i[string string string int pointer], :pointer
19
+ attach_function :kvm_geterr, [:pointer], :string
20
+ attach_function :kvm_getswapinfo, %i[pointer pointer int int], :int
21
+ attach_function :kvm_close, [:pointer], :int
22
+
23
+ # Private class wrapper for struct kvm_swap
24
+ class KvmSwap < FFI::Struct
25
+ layout(
26
+ :ksw_devname, [:char, 32],
27
+ :ksw_used, :uint,
28
+ :ksw_total, :uint,
29
+ :ksw_flags, :int,
30
+ :ksw_reserved1, :uint,
31
+ :ksw_reserved2, :uint
32
+ )
33
+ end
34
+
35
+ private_constant :KvmSwap
36
+ end
37
+
14
38
  # Obtain detailed memory information about your host in the form of a hash.
15
39
  # Note that the exact nature of this hash is largely dependent on your
16
40
  # operating system.
@@ -26,8 +50,17 @@ module Sys
26
50
  hash[:free] = get_by_name('vm.stats.vm.v_free_count') * page_size
27
51
  hash[:inactive] = get_by_name('vm.stats.vm.v_inactive_count') * page_size
28
52
  hash[:wire] = get_by_name('vm.stats.vm.v_wire_count') * page_size
29
- hash[:swap_size] = get_by_name('vm.swap_size')
30
- hash[:swap_free] = get_by_name('vm.swap_free')
53
+
54
+ if RbConfig::CONFIG['host_os'] =~ /dragonfly/i
55
+ hash[:swap_size] = get_by_name('vm.swap_size')
56
+ hash[:swap_free] = get_by_name('vm.swap_free')
57
+ elsif RbConfig::CONFIG['host_os'] =~ /freebsd/i
58
+ hash[:swap_size] = get_by_name('vm.swap_total')
59
+ hash[:swap_free] = hash[:swap_size] - get_freebsd_swap_used(page_size)
60
+ else
61
+ hash[:swap_size] = get_by_name('vm.swap_total')
62
+ hash[:swap_free] = hash[:swap_size] - get_by_name('vm.swap_reserved') # Best guess
63
+ end
31
64
 
32
65
  hash
33
66
  end
@@ -79,7 +112,7 @@ module Sys
79
112
  size.write_int(optr.size)
80
113
 
81
114
  if sysctlbyname(mib, optr, size, nil, 0) < 0
82
- raise SystemCallError.new('sysctlbyname', FFI.errno)
115
+ raise SystemCallError.new("sysctlbyname: #{mib}", FFI.errno)
83
116
  end
84
117
 
85
118
  value = optr.read_uint64
@@ -91,6 +124,31 @@ module Sys
91
124
  value
92
125
  end
93
126
 
94
- module_function :get_by_name
127
+ def get_freebsd_swap_used(page_size)
128
+ kd = nil
129
+
130
+ begin
131
+ error = FFI::MemoryPointer.new(:char, 2048)
132
+ kd = kvm_openfiles(nil, File::NULL, nil, 0, error)
133
+
134
+ if kd.null?
135
+ message = error.read_string
136
+ raise SystemCallError, "kvm_openfiles: #{message.empty? ? 'unknown error' : message}"
137
+ end
138
+
139
+ swap = KvmSwap.new
140
+
141
+ if kvm_getswapinfo(kd, swap.pointer, 1, 0) < 0
142
+ raise SystemCallError, "kvm_getswapinfo: #{kvm_geterr(kd)}"
143
+ end
144
+
145
+ swap[:ksw_used] * page_size
146
+ ensure
147
+ kvm_close(kd) if kd && !kd.null?
148
+ error.free if error && !error.null?
149
+ end
150
+ end
151
+
152
+ module_function :get_by_name, :get_freebsd_swap_used
95
153
  end
96
154
  end
@@ -50,7 +50,7 @@ module Sys
50
50
  #
51
51
  def used(extended: false)
52
52
  hash = memory
53
- total(extended: extended) - free(extended: extended) - (hash['Buffers'] + hash['Cached'] + hash['Slab']) * 1024
53
+ total(extended: extended) - free(extended: extended) - ((hash['Buffers'] + hash['Cached'] + hash['Slab']) * 1024)
54
54
  end
55
55
 
56
56
  # A number between 0 and 100 that specifies the approximate percentage of
@@ -7,6 +7,7 @@ module Sys
7
7
  # The Memory module is a house for memory related singleton methods that don't require state.
8
8
  module Memory
9
9
  extend FFI::Library
10
+
10
11
  ffi_lib FFI::Library::LIBC
11
12
 
12
13
  HOST_VM_INFO64 = 4
@@ -25,6 +26,7 @@ module Sys
25
26
 
26
27
  typedef :uint, :natural_t
27
28
 
29
+ # Private class wrapper for struct swap
28
30
  class Swap < FFI::Struct
29
31
  layout(
30
32
  :xsu_total, :uint64_t,
@@ -37,6 +39,7 @@ module Sys
37
39
 
38
40
  private_constant :Swap
39
41
 
42
+ # Private class wrapper for struct vmstat
40
43
  class VmStat < FFI::Struct
41
44
  layout(
42
45
  :free_count, :natural_t, # of pages free
data/lib/sys/version.rb CHANGED
@@ -3,6 +3,6 @@
3
3
  module Sys
4
4
  module Memory
5
5
  # The version of the sys-memory library.
6
- VERSION = '0.2.0'
6
+ VERSION = '0.2.1'
7
7
  end
8
8
  end
@@ -7,11 +7,13 @@ module Sys
7
7
  module Memory
8
8
  require 'ffi'
9
9
  extend FFI::Library
10
+
10
11
  ffi_lib 'kernel32'
11
12
 
12
13
  typedef :uint32, :dword
13
14
  typedef :uint64, :dwordlong
14
15
 
16
+ # Private wrapper class for the MEMORYSTATUSEX struct
15
17
  class MemoryStatusEx < FFI::Struct
16
18
  layout(
17
19
  :dwLength, :dword,
@@ -33,6 +35,7 @@ module Sys
33
35
 
34
36
  ffi_lib 'psapi'
35
37
 
38
+ # Private wrapper class for the PERFORMANCE_INFORMATION struct
36
39
  class PerformanceInformation < FFI::Struct
37
40
  layout(
38
41
  :cb, :dword,
@@ -4,9 +4,20 @@ require 'active_support/core_ext/numeric/bytes'
4
4
  require 'sys-memory'
5
5
 
6
6
  RSpec.describe Sys::Memory do
7
+ let(:memory) { described_class.memory }
8
+
9
+ let(:swap_keys) do
10
+ [
11
+ %i[swap_size swap_free],
12
+ %i[swap_total swap_available],
13
+ %w[SwapTotal SwapFree],
14
+ %w[TotalPageFile AvailPageFile]
15
+ ].find { |total_key, free_key| memory.key?(total_key) && memory.key?(free_key) }
16
+ end
17
+
7
18
  context 'Sys::Memory::VERSION' do
8
19
  example 'the version constant is set to the expected value' do
9
- expect(described_class::VERSION).to eq('0.2.0')
20
+ expect(described_class::VERSION).to eq('0.2.1')
10
21
  expect(described_class::VERSION).to be_frozen
11
22
  end
12
23
  end
@@ -17,9 +28,24 @@ RSpec.describe Sys::Memory do
17
28
  end
18
29
 
19
30
  example 'the memory singleton method returns the expected hash' do
20
- expect(described_class.memory).to be_kind_of(Hash)
31
+ expect(described_class.memory).to be_a(Hash)
21
32
  expect(described_class.memory.size).to be > 4
22
33
  end
34
+
35
+ example 'the memory singleton method returns non-negative numeric values' do
36
+ described_class.memory.each do |key, value|
37
+ expect(value).to be_a(Numeric), "#{key.inspect} should be numeric"
38
+ expect(value).to be >= 0
39
+ end
40
+ end
41
+
42
+ example 'the memory singleton method returns sane swap values' do
43
+ swap_total, swap_free = swap_keys
44
+ skip 'no swap values reported on this platform' unless swap_total && swap_free
45
+
46
+ expect(memory[swap_total]).to be >= 0
47
+ expect(memory[swap_free]).to be_between(0, memory[swap_total]).inclusive
48
+ end
23
49
  end
24
50
 
25
51
  context 'Sys::Memory.total' do
data/sys-memory.gemspec CHANGED
@@ -2,7 +2,7 @@ require 'rubygems'
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = 'sys-memory'
5
- spec.version = '0.2.0'
5
+ spec.version = '0.2.1'
6
6
  spec.author = 'Daniel J. Berger'
7
7
  spec.email = 'djberg96@gmail.com'
8
8
  spec.license = 'Apache-2.0'
@@ -13,7 +13,7 @@ Gem::Specification.new do |spec|
13
13
  spec.cert_chain = ['certs/djberg96_pub.pem']
14
14
 
15
15
  spec.add_dependency('ffi', '~> 1.1')
16
- spec.add_development_dependency('activesupport', '~> 6.0')
16
+ spec.add_development_dependency('activesupport', '>= 6.0')
17
17
  spec.add_development_dependency('rspec', '~> 3.9')
18
18
  spec.add_development_dependency('rake', '~> 13.0')
19
19
  spec.add_development_dependency('rubocop')
@@ -27,7 +27,8 @@ Gem::Specification.new do |spec|
27
27
  'source_code_uri' => 'https://github.com/djberg96/sys-memory',
28
28
  'wiki_uri' => 'https://github.com/djberg96/sys-memory/wiki',
29
29
  'rubygems_mfa_required' => 'true',
30
- 'github_repo' => 'https://github.com/djberg96/sys-memory'
30
+ 'github_repo' => 'https://github.com/djberg96/sys-memory',
31
+ 'funding_uri' => 'https://github.com/sponsors/djberg96'
31
32
  }
32
33
 
33
34
  spec.description = <<-EOF
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,11 +1,10 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sys-memory
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel J. Berger
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain:
11
10
  - |
@@ -35,7 +34,7 @@ cert_chain:
35
34
  ORVCZpRuCPpmC8qmqxUnARDArzucjaclkxjLWvCVHeFa9UP7K3Nl9oTjJNv+7/jM
36
35
  WZs4eecIcUc4tKdHxcAJ0MO/Dkqq7hGaiHpwKY76wQ1+8xAh
37
36
  -----END CERTIFICATE-----
38
- date: 2024-06-12 00:00:00.000000000 Z
37
+ date: 1980-01-02 00:00:00.000000000 Z
39
38
  dependencies:
40
39
  - !ruby/object:Gem::Dependency
41
40
  name: ffi
@@ -55,14 +54,14 @@ dependencies:
55
54
  name: activesupport
56
55
  requirement: !ruby/object:Gem::Requirement
57
56
  requirements:
58
- - - "~>"
57
+ - - ">="
59
58
  - !ruby/object:Gem::Version
60
59
  version: '6.0'
61
60
  type: :development
62
61
  prerelease: false
63
62
  version_requirements: !ruby/object:Gem::Requirement
64
63
  requirements:
65
- - - "~>"
64
+ - - ">="
66
65
  - !ruby/object:Gem::Version
67
66
  version: '6.0'
68
67
  - !ruby/object:Gem::Dependency
@@ -158,7 +157,7 @@ metadata:
158
157
  wiki_uri: https://github.com/djberg96/sys-memory/wiki
159
158
  rubygems_mfa_required: 'true'
160
159
  github_repo: https://github.com/djberg96/sys-memory
161
- post_install_message:
160
+ funding_uri: https://github.com/sponsors/djberg96
162
161
  rdoc_options: []
163
162
  require_paths:
164
163
  - lib
@@ -173,8 +172,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
173
172
  - !ruby/object:Gem::Version
174
173
  version: '0'
175
174
  requirements: []
176
- rubygems_version: 3.3.26
177
- signing_key:
175
+ rubygems_version: 4.0.6
178
176
  specification_version: 4
179
177
  summary: A Ruby interface for providing memory information
180
178
  test_files:
metadata.gz.sig CHANGED
Binary file