systemd-journal 2.0.0 → 2.1.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: e5c615cee8de41012105d99aec5b93f8c88f322b67bbf4d97bcb4afbd74cec35
4
- data.tar.gz: 84447c503addd9fc6c3c6564472e7eb1558f6e6a184a98214c604feb2649ecea
3
+ metadata.gz: f33c8fad86b5eee9fa452aefe9b33984383cea940b21075c6394c1a1d4ce85ef
4
+ data.tar.gz: fb07b5691db94be4abb21e7b2ca9a9541be0863e11e3899dcd55c16e52661a43
5
5
  SHA512:
6
- metadata.gz: dd1375594a013f9d237c0a62f5c4aed77f80b54637e1275cf32565905fde72187eb08feefc4d93129a3a942949de93d2f037b0af2893e95f52c006d682e32b39
7
- data.tar.gz: 9debfc4954cc65ddf9fda2d448c30b67c0995cf2ad554dcfb00b067103218a5898d8d9f619e6b04236d184742397d64b5365efbbd90cb0be6f26a25cbeb8887b
6
+ metadata.gz: 2345a7cb623c6998f2f2aee2136e55b6c79278fd9fe5b223f548cbcf3f0b176cbe58e019f19a9a0ee547015a3f0f3b969509eb488f1feb86464412f357f821ea
7
+ data.tar.gz: '09323d66962413d09ebb444d0667d1d3d35cb4208ea388910233bb2a28368de63b97f2cd1a8d046bc205c872cb2f348f4a8fa4bcc41b715012cc7c149937af4a'
@@ -1,20 +1,32 @@
1
1
  name: RSpec Matrix
2
- on: [push]
2
+ on: [push, pull_request]
3
+
3
4
  jobs:
4
5
  test:
5
6
  strategy:
6
7
  fail-fast: false
7
8
  matrix:
8
- os: [ubuntu]
9
- ruby: [3.0, 3.1, 3.2, 3.3]
10
- runs-on: ${{ matrix.os }}-latest
9
+ os: [ubuntu-latest]
10
+ ruby: [3.1, 3.2, 3.3, 3.4]
11
+ runs-on: ${{ matrix.os }}
11
12
  steps:
12
- - uses: actions/checkout@v2
13
+ - uses: actions/checkout@v4
13
14
  - uses: ruby/setup-ruby@v1
14
15
  with:
15
16
  ruby-version: ${{ matrix.ruby }}
17
+ bundler-cache: true
16
18
  - run: sudo apt-get install libjemalloc2 --yes
17
- - run: bundle install
18
19
  - run: bundle exec rake compile
19
20
  - run: bundle exec rake spec
20
21
  - run: LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 bundle exec rake spec
22
+ lint:
23
+ strategy:
24
+ fail-fast: false
25
+ runs-on: ubuntu-latest
26
+ steps:
27
+ - uses: actions/checkout@v4
28
+ - uses: ruby/setup-ruby@v1
29
+ with:
30
+ ruby-version: 3.4
31
+ bundler-cache: true
32
+ - run: bundle exec rake standard
data/Gemfile CHANGED
@@ -1,8 +1,8 @@
1
- source 'https://rubygems.org'
1
+ source "https://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in systemd-journal.gemspec
4
4
  gemspec
5
5
 
6
6
  group :test do
7
- gem 'codeclimate-test-reporter', require: nil
7
+ gem "codeclimate-test-reporter", require: nil
8
8
  end
data/README.md CHANGED
@@ -80,6 +80,16 @@ j.current_entry # get the entry we're currently positioned at
80
80
  j.seek(Time.parse('2013-10-31T12:00:00+04:00:00'))
81
81
  ```
82
82
 
83
+ Re-open the journal automatically to reduce memory usage with moving the journal:
84
+
85
+ ```ruby
86
+ Journal.new(auto_reopen: false) # do not ever re-open the journal.
87
+ # this should be the default for now
88
+
89
+ Journal.new(auto_reopen: true) # re-open the journal after the default ITERATIONS_TO_AUTO_REOPEN
90
+ Journal.new(auto_reopen: 50_000) # re-open the journal after 50k iterations
91
+ ```
92
+
83
93
  Waiting for things to happen:
84
94
 
85
95
  ```ruby
data/Rakefile CHANGED
@@ -1,29 +1,21 @@
1
- require 'bundler/gem_tasks'
2
- require 'yard'
3
- require 'rspec/core/rake_task'
1
+ require "bundler/gem_tasks"
2
+ require "yard"
3
+ require "rspec/core/rake_task"
4
4
  require "rake/extensiontask"
5
+ require "standard/rake"
5
6
 
6
- unless ENV['RUBOCOP'] == 'false'
7
- require 'rubocop/rake_task'
8
-
9
- RuboCop::RakeTask.new(:rubocop) do |task|
10
- task.patterns = ['lib/**/*.rb', 'spec/**/*.rb']
11
- task.fail_on_error = false
12
- end
13
- end
14
-
15
- desc 'open a console with systemd/journal required'
7
+ desc "open a console with systemd/journal required"
16
8
  task :console do
17
- exec 'pry -I./lib -r systemd/journal'
9
+ exec "pry -I./lib -r systemd/journal"
18
10
  end
19
11
 
20
12
  YARD::Rake::YardocTask.new do |t|
21
- t.files = ['lib/**/*.rb']
22
- t.options = ['--no-private', '--markup=markdown']
13
+ t.files = ["lib/**/*.rb"]
14
+ t.options = ["--no-private", "--markup=markdown"]
23
15
  end
24
16
 
25
17
  RSpec::Core::RakeTask.new(:spec) do |t|
26
- t.rspec_opts = %w(--color)
18
+ t.rspec_opts = %w[--color]
27
19
  end
28
20
 
29
21
  GEMSPEC = Gem::Specification.load("systemd-journal.gemspec")
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'systemd/journal'
3
+ require "systemd/journal"
4
4
 
5
5
  if ARGV.length == 0
6
6
  puts "usage: ./#{File.basename(__FILE__)} /var/log/journal/{machine-id}"
@@ -1,23 +1,23 @@
1
1
  #!/usr/bin/env ruby
2
- require 'systemd/journal'
3
- require 'date'
2
+ require "systemd/journal"
3
+ require "date"
4
4
 
5
5
  class SSHWatcher
6
+ LOGIN_REGEXP = /Accepted\s+(?<auth_method>[^\s]+)\s+for\s+(?<user>[^\s]+)\s+from\s+(?<address>[^\s]+)/
7
+
6
8
  def initialize
7
9
  @journal = Systemd::Journal.new(flags: Systemd::Journal::Flags::SYSTEM_ONLY)
8
10
  end
9
11
 
10
12
  def run
11
- @journal.filter(_exe: '/usr/bin/sshd')
13
+ @journal.filter(_exe: "/usr/bin/sshd")
12
14
  @journal.seek(:tail)
13
15
  @journal.move_previous
14
- @journal.watch{ |entry| process_event(entry) }
16
+ @journal.watch { |entry| process_event(entry) }
15
17
  end
16
18
 
17
19
  private
18
20
 
19
- LOGIN_REGEXP = /Accepted\s+(?<auth_method>[^\s]+)\s+for\s+(?<user>[^\s]+)\s+from\s+(?<address>[^\s]+)/
20
-
21
21
  def process_event(entry)
22
22
  if (m = entry.message.match(LOGIN_REGEXP))
23
23
  timestamp = DateTime.strptime(
@@ -1,21 +1,21 @@
1
- require 'ffi'
1
+ require "ffi"
2
2
 
3
3
  # @private
4
4
  class FFI::MemoryPointer
5
5
  # monkey patch a read_size_t and write_size_t method onto FFI::MemoryPointer.
6
6
  # see https://github.com/ffi/ffi/issues/118
7
7
  def self.monkey_patch_type_i_need!(which)
8
- return if self.respond_to?("read_#{which}")
8
+ return if respond_to?(:"read_#{which}")
9
9
 
10
10
  type = FFI.find_type(which)
11
11
  type, _ = FFI::TypeDefs.find do |(name, t)|
12
- method_defined?("read_#{name}") if t == type
12
+ method_defined?(:"read_#{name}") if t == type
13
13
  end
14
14
 
15
15
  raise "Unable to patch in reader/writer for #{which}" if type.nil?
16
16
 
17
- alias_method "read_#{which}", "read_#{type}"
18
- alias_method "write_#{which}", "write_#{type}"
17
+ alias_method :"read_#{which}", :"read_#{type}"
18
+ alias_method :"write_#{which}", :"write_#{type}"
19
19
  end
20
20
  end
21
21
 
data/lib/systemd/id128.rb CHANGED
@@ -1,4 +1,4 @@
1
- require 'ffi'
1
+ require "ffi"
2
2
 
3
3
  module Systemd
4
4
  # Provides access to the 128-bit IDs for various items in the systemd
@@ -32,9 +32,7 @@ module Systemd
32
32
  read_id128(:sd_id128_randomize)
33
33
  end
34
34
 
35
- private
36
-
37
- def self.read_id128(func)
35
+ private_class_method def self.read_id128(func)
38
36
  ptr = FFI::MemoryPointer.new(Native::Id128, 1)
39
37
  rc = Native.send(func, ptr)
40
38
  raise JournalError, rc if rc < 0
@@ -43,28 +41,28 @@ module Systemd
43
41
 
44
42
  # providing bindings to the systemd-id128 library.
45
43
  module Native
46
- require 'ffi'
44
+ require "ffi"
47
45
  extend FFI::Library
48
- ffi_lib %w( libsystemd.so.0 libsystemd.so
49
- libsystemd-id128.so.0 libsystemd-id128.so )
46
+ ffi_lib %w[ libsystemd.so.0 libsystemd.so
47
+ libsystemd-id128.so.0 libsystemd-id128.so ]
50
48
 
51
49
  attach_function :sd_id128_get_machine, [:pointer], :int
52
- attach_function :sd_id128_get_boot, [:pointer], :int
53
- attach_function :sd_id128_randomize, [:pointer], :int
50
+ attach_function :sd_id128_get_boot, [:pointer], :int
51
+ attach_function :sd_id128_randomize, [:pointer], :int
54
52
 
55
53
  # @private
56
54
  class Id128 < FFI::Union
57
- layout :bytes, [:uint8, 16],
58
- :dwords, [:uint32, 4],
59
- :qwords, [:uint64, 2]
55
+ layout :bytes, [:uint8, 16],
56
+ :dwords, [:uint32, 4],
57
+ :qwords, [:uint64, 2]
60
58
 
61
59
  def to_s
62
- format('%02x' * 16, *self[:bytes].to_a)
60
+ format("%02x" * 16, *self[:bytes].to_a)
63
61
  end
64
62
 
65
63
  def self.from_s(str)
66
64
  r = Id128.new
67
- [str].pack('H*').bytes.each_with_index do |b, i|
65
+ [str].pack("H*").bytes.each_with_index do |b, i|
68
66
  r[:bytes][i] = b
69
67
  end
70
68
 
@@ -1,18 +1,18 @@
1
1
  module Systemd
2
2
  class Journal
3
3
  # Fields directly passed by client programs and stored in the journal.
4
- USER_FIELDS = %w( MESSAGE MESSAGE_ID PRIORITY CODE_FILE CODE_LINE CODE_FUNC
5
- ERRNO SYSLOG_FACILITY SYSLOG_IDENTIFIER SYSLOG_PID )
4
+ USER_FIELDS = %w[ MESSAGE MESSAGE_ID PRIORITY CODE_FILE CODE_LINE CODE_FUNC
5
+ ERRNO SYSLOG_FACILITY SYSLOG_IDENTIFIER SYSLOG_PID ]
6
6
 
7
7
  # Fields generated by the journal and added to each event.
8
- TRUSTED_FIELDS = %w( _PID _UID _GID _COMM _EXE _CMDLINE _AUDIT_SESSION
9
- _AUDIT_LOGINUID _SYSTEMD_CGROUP _SYSTEMD_SESSION
10
- _SYSTEMD_UNIT _SYSTEMD_USER_UNIT _SYSTEMD_OWNER_UID
11
- _SELINUX_CONTEXT _SOURCE_REALTIME_TIMESTAMP _BOOT_ID
12
- _MACHINE_ID _HOSTNAME _TRANSPORT )
8
+ TRUSTED_FIELDS = %w[ _PID _UID _GID _COMM _EXE _CMDLINE _AUDIT_SESSION
9
+ _AUDIT_LOGINUID _SYSTEMD_CGROUP _SYSTEMD_SESSION
10
+ _SYSTEMD_UNIT _SYSTEMD_USER_UNIT _SYSTEMD_OWNER_UID
11
+ _SELINUX_CONTEXT _SOURCE_REALTIME_TIMESTAMP _BOOT_ID
12
+ _MACHINE_ID _HOSTNAME _TRANSPORT ]
13
13
 
14
14
  # Fields used in messages originating from the kernel.
15
- KERNEL_FIELDS = %w( _KERNEL_DEVICE _KERNEL_SUBSYSTEM _UDEV_SYSNAME
16
- _UDEV_DEVNODE _UDEV_DEVLINK )
15
+ KERNEL_FIELDS = %w[ _KERNEL_DEVICE _KERNEL_SUBSYSTEM _UDEV_SYSNAME
16
+ _UDEV_DEVNODE _UDEV_DEVLINK ]
17
17
  end
18
18
  end
@@ -36,6 +36,8 @@ module Systemd
36
36
  # @param [String] value the match to search for, e.g. '/usr/bin/sshd'
37
37
  # @return [nil]
38
38
  def add_filter(field, value)
39
+ @reopen_filter_conditions << {field => value}
40
+
39
41
  match = "#{field.to_s.upcase}=#{value}"
40
42
  rc = Native.sd_journal_add_match(@ptr, match, match.length)
41
43
  raise JournalError, rc if rc < 0
@@ -70,6 +72,8 @@ module Systemd
70
72
  # # has priority 5
71
73
  # end
72
74
  def add_disjunction
75
+ @reopen_filter_conditions << :disjunction
76
+
73
77
  rc = Native.sd_journal_add_disjunction(@ptr)
74
78
  raise JournalError, rc if rc < 0
75
79
  end
@@ -88,6 +92,8 @@ module Systemd
88
92
  # # current_entry is an sshd event with priority 5
89
93
  # end
90
94
  def add_conjunction
95
+ @reopen_filter_conditions << :conjunction
96
+
91
97
  rc = Native.sd_journal_add_conjunction(@ptr)
92
98
  raise JournalError, rc if rc < 0
93
99
  end
@@ -95,8 +101,31 @@ module Systemd
95
101
  # Remove all filters and conjunctions/disjunctions.
96
102
  # @return [nil]
97
103
  def clear_filters
104
+ @reopen_filter_conditions = []
105
+
98
106
  Native.sd_journal_flush_matches(@ptr)
99
107
  end
108
+
109
+ private
110
+
111
+ # Restore filters from a previously saved set of conditions.
112
+ # Note that this cannot be a reference to the existing @reopen_filter_conditions
113
+ # as they will be cleared when this method is called.
114
+ # # @param [Array] conditions an array of conditions to restore.
115
+ def restore_filters(conditions)
116
+ clear_filters
117
+
118
+ conditions.each do |condition|
119
+ case condition
120
+ when :disjunction
121
+ add_disjunction
122
+ when :conjunction
123
+ add_conjunction
124
+ else
125
+ add_filters(condition)
126
+ end
127
+ end
128
+ end
100
129
  end
101
130
  end
102
131
  end
@@ -6,11 +6,11 @@ module Systemd
6
6
  # Systemd::Journal.new(flags: Systemd::Journal::Flags::LOCAL_ONLY)
7
7
  module Flags
8
8
  # Only open journal files generated on the local machine.
9
- LOCAL_ONLY = 1
9
+ LOCAL_ONLY = 1
10
10
  # Only open non-persistent journal files.
11
- RUNTIME_ONLY = 2
11
+ RUNTIME_ONLY = 2
12
12
  # Only open kernel and system service journal files.
13
- SYSTEM_ONLY = 4
13
+ SYSTEM_ONLY = 4
14
14
  end
15
15
  end
16
16
  end
@@ -1,15 +1,15 @@
1
- require 'systemd/id128'
1
+ require "systemd/id128"
2
2
 
3
3
  module Systemd
4
4
  class Journal
5
5
  # Provides the FFI bindings to the native `libsystemd-journal` shared
6
6
  # library.
7
7
  module Native
8
- # rubocop:disable LineLength
9
- require 'ffi'
8
+ # rubocop:disable Layout/LineLength
9
+ require "ffi"
10
10
  extend FFI::Library
11
- ffi_lib %w( libsystemd.so.0 libsystemd.so
12
- libsystemd-journal.so.0 libsystemd-journal.so)
11
+ ffi_lib %w[ libsystemd.so.0 libsystemd.so
12
+ libsystemd-journal.so.0 libsystemd-journal.so]
13
13
 
14
14
  @has_open_container = true
15
15
 
@@ -18,11 +18,11 @@ module Systemd
18
18
  end
19
19
 
20
20
  # setup/teardown
21
- attach_function :sd_journal_open, [:pointer, :int], :int
21
+ attach_function :sd_journal_open, [:pointer, :int], :int
22
22
  attach_function :sd_journal_open_directory, [:pointer, :string, :int], :int
23
- attach_function :sd_journal_close, [:pointer], :void
23
+ attach_function :sd_journal_close, [:pointer], :void
24
24
 
25
- attach_function :sd_journal_open_files, [:pointer, :pointer, :int], :int
25
+ attach_function :sd_journal_open_files, [:pointer, :pointer, :int], :int
26
26
 
27
27
  # not available in 208
28
28
  begin
@@ -32,53 +32,53 @@ module Systemd
32
32
  end
33
33
 
34
34
  # navigation
35
- attach_function :sd_journal_next, [:pointer], :int
36
- attach_function :sd_journal_next_skip, [:pointer, :uint64], :int
37
- attach_function :sd_journal_previous, [:pointer], :int
35
+ attach_function :sd_journal_next, [:pointer], :int
36
+ attach_function :sd_journal_next_skip, [:pointer, :uint64], :int
37
+ attach_function :sd_journal_previous, [:pointer], :int
38
38
  attach_function :sd_journal_previous_skip, [:pointer, :uint64], :int
39
39
 
40
- attach_function :sd_journal_seek_head, [:pointer], :int
41
- attach_function :sd_journal_seek_tail, [:pointer], :int
40
+ attach_function :sd_journal_seek_head, [:pointer], :int
41
+ attach_function :sd_journal_seek_tail, [:pointer], :int
42
42
  attach_function :sd_journal_seek_realtime_usec, [:pointer, :uint64], :int
43
43
 
44
- attach_function :sd_journal_get_cursor, [:pointer, :pointer], :int
45
- attach_function :sd_journal_seek_cursor, [:pointer, :string], :int
46
- attach_function :sd_journal_test_cursor, [:pointer, :string], :int
44
+ attach_function :sd_journal_get_cursor, [:pointer, :pointer], :int
45
+ attach_function :sd_journal_seek_cursor, [:pointer, :string], :int
46
+ attach_function :sd_journal_test_cursor, [:pointer, :string], :int
47
47
 
48
48
  # data reading
49
- attach_function :sd_journal_get_data, [:pointer, :string, :pointer, :pointer], :int
50
- attach_function :sd_journal_restart_data, [:pointer], :void
49
+ attach_function :sd_journal_get_data, [:pointer, :string, :pointer, :pointer], :int
50
+ attach_function :sd_journal_restart_data, [:pointer], :void
51
51
  attach_function :sd_journal_enumerate_data, [:pointer, :pointer, :pointer], :int
52
- attach_function :sd_journal_get_catalog, [:pointer, :pointer], :int
52
+ attach_function :sd_journal_get_catalog, [:pointer, :pointer], :int
53
53
  attach_function :sd_journal_get_catalog_for_message_id, [Systemd::Id128::Native::Id128.by_value, :pointer], :int
54
54
 
55
- attach_function :sd_journal_get_realtime_usec, [:pointer, :pointer], :int
55
+ attach_function :sd_journal_get_realtime_usec, [:pointer, :pointer], :int
56
56
  attach_function :sd_journal_get_monotonic_usec, [:pointer, :pointer, :pointer], :int
57
57
 
58
58
  attach_function :sd_journal_get_data_threshold, [:pointer, :pointer], :int
59
- attach_function :sd_journal_set_data_threshold, [:pointer, :size_t], :int
59
+ attach_function :sd_journal_set_data_threshold, [:pointer, :size_t], :int
60
60
 
61
61
  # querying
62
- attach_function :sd_journal_query_unique, [:pointer, :string], :int
62
+ attach_function :sd_journal_query_unique, [:pointer, :string], :int
63
63
  attach_function :sd_journal_enumerate_unique, [:pointer, :pointer, :pointer], :int
64
- attach_function :sd_journal_restart_unique, [:pointer], :void
64
+ attach_function :sd_journal_restart_unique, [:pointer], :void
65
65
 
66
66
  # event notification
67
67
  enum :wake_reason, [:nop, :append, :invalidate]
68
- attach_function :sd_journal_wait, [:pointer, :uint64], :wake_reason, blocking: true
69
- attach_function :sd_journal_get_fd, [:pointer], :int
70
- attach_function :sd_journal_process, [:pointer], :wake_reason
68
+ attach_function :sd_journal_wait, [:pointer, :uint64], :wake_reason, blocking: true
69
+ attach_function :sd_journal_get_fd, [:pointer], :int
70
+ attach_function :sd_journal_process, [:pointer], :wake_reason
71
71
  attach_function :sd_journal_reliable_fd, [:pointer], :int
72
72
 
73
73
  # filtering
74
- attach_function :sd_journal_add_match, [:pointer, :string, :size_t], :int
75
- attach_function :sd_journal_flush_matches, [:pointer], :void
74
+ attach_function :sd_journal_add_match, [:pointer, :string, :size_t], :int
75
+ attach_function :sd_journal_flush_matches, [:pointer], :void
76
76
  attach_function :sd_journal_add_disjunction, [:pointer], :int
77
77
  attach_function :sd_journal_add_conjunction, [:pointer], :int
78
78
 
79
79
  # writing
80
- attach_function :sd_journal_print, [:int, :string], :int
81
- attach_function :sd_journal_send, [:varargs], :int
80
+ attach_function :sd_journal_print, [:int, :string], :int
81
+ attach_function :sd_journal_send, [:varargs], :int
82
82
  attach_function :sd_journal_perror, [:string], :int
83
83
  attach_function :sd_journal_stream_fd, [:string, :int, :bool], :int
84
84
 
@@ -1,6 +1,9 @@
1
1
  module Systemd
2
2
  class Journal
3
3
  module Navigable
4
+ ITERATIONS_TO_AUTO_REOPEN = 10_000
5
+ private_constant :ITERATIONS_TO_AUTO_REOPEN
6
+
4
7
  # returns a string representing the current read position.
5
8
  # This string can be passed to {#seek} or {#cursor?}.
6
9
  # @return [String] a cursor token.
@@ -32,7 +35,7 @@ module Systemd
32
35
  # it moves backwards. Defaults to moving forward one entry.
33
36
  # @return [Integer] number of entries the read pointer actually moved.
34
37
  def move(offset = 1)
35
- offset > 0 ? move_next_skip(offset) : move_previous_skip(-offset)
38
+ (offset > 0) ? move_next_skip(offset) : move_previous_skip(-offset)
36
39
  end
37
40
 
38
41
  # Move the read pointer to the next entry in the journal.
@@ -40,9 +43,11 @@ module Systemd
40
43
  # @return [Boolean] False if unable to move to the next entry, indicating
41
44
  # that the pointer has reached the end of the journal.
42
45
  def move_next
43
- rc = Native.sd_journal_next(@ptr)
44
- raise JournalError, rc if rc < 0
45
- rc > 0
46
+ with_auto_reopen {
47
+ rc = Native.sd_journal_next(@ptr)
48
+ raise JournalError, rc if rc < 0
49
+ rc > 0
50
+ }
46
51
  end
47
52
 
48
53
  # Move the read pointer forward by `amount` entries.
@@ -50,9 +55,11 @@ module Systemd
50
55
  # moved. If this number is less than the requested amount, the read
51
56
  # pointer has reached the end of the journal.
52
57
  def move_next_skip(amount)
53
- rc = Native.sd_journal_next_skip(@ptr, amount)
54
- raise JournalError, rc if rc < 0
55
- rc
58
+ with_auto_reopen {
59
+ rc = Native.sd_journal_next_skip(@ptr, amount)
60
+ raise JournalError, rc if rc < 0
61
+ rc
62
+ }
56
63
  end
57
64
 
58
65
  # Move the read pointer to the previous entry in the journal.
@@ -60,9 +67,11 @@ module Systemd
60
67
  # @return [Boolean] False if unable to move to the previous entry,
61
68
  # indicating that the pointer has reached the beginning of the journal.
62
69
  def move_previous
63
- rc = Native.sd_journal_previous(@ptr)
64
- raise JournalError, rc if rc < 0
65
- rc > 0
70
+ with_auto_reopen {
71
+ rc = Native.sd_journal_previous(@ptr)
72
+ raise JournalError, rc if rc < 0
73
+ rc > 0
74
+ }
66
75
  end
67
76
 
68
77
  # Move the read pointer backwards by `amount` entries.
@@ -70,9 +79,11 @@ module Systemd
70
79
  # was moved. If this number is less than the requested amount, the
71
80
  # read pointer has reached the beginning of the journal.
72
81
  def move_previous_skip(amount)
73
- rc = Native.sd_journal_previous_skip(@ptr, amount)
74
- raise JournalError, rc if rc < 0
75
- rc
82
+ with_auto_reopen {
83
+ rc = Native.sd_journal_previous_skip(@ptr, amount)
84
+ raise JournalError, rc if rc < 0
85
+ rc
86
+ }
76
87
  end
77
88
 
78
89
  # Seek to a position in the journal.
@@ -90,31 +101,69 @@ module Systemd
90
101
  # and seek to that entry.
91
102
  # @return [True]
92
103
  # @example Read last journal entry
93
- # j = Systemd::Joural.new
104
+ # j = Systemd::Journal.new
94
105
  # j.seek(:tail)
95
106
  # j.move_previous
96
107
  # puts j.current_entry
97
108
  def seek(where)
98
- rc = case
99
- when [:head, :start].include?(where)
100
- Native.sd_journal_seek_head(@ptr)
101
- when [:tail, :end].include?(where)
102
- Native.sd_journal_seek_tail(@ptr)
103
- when where.is_a?(Time)
104
- Native.sd_journal_seek_realtime_usec(
105
- @ptr,
106
- where.to_i * 1_000_000
107
- )
108
- when where.is_a?(String)
109
- Native.sd_journal_seek_cursor(@ptr, where)
110
- else
111
- raise ArgumentError, "Unknown seek type: #{where.class}"
112
- end
109
+ rc = if [:head, :start].include?(where)
110
+ Native.sd_journal_seek_head(@ptr)
111
+ elsif [:tail, :end].include?(where)
112
+ Native.sd_journal_seek_tail(@ptr)
113
+ elsif where.is_a?(Time)
114
+ Native.sd_journal_seek_realtime_usec(
115
+ @ptr,
116
+ where.to_i * 1_000_000
117
+ )
118
+ elsif where.is_a?(String)
119
+ Native.sd_journal_seek_cursor(@ptr, where)
120
+ else
121
+ raise ArgumentError, "Unknown seek type: #{where.class}"
122
+ end
113
123
 
114
124
  raise JournalError, rc if rc < 0
115
125
 
116
126
  true
117
127
  end
128
+
129
+ private
130
+
131
+ # reopen the journal automatically due to reduce memory usage
132
+ def with_auto_reopen
133
+ @sd_call_count ||= 0
134
+
135
+ ret = yield
136
+
137
+ if auto_reopen
138
+ @sd_call_count += 1
139
+ if @sd_call_count >= auto_reopen
140
+ begin
141
+ cursor = self.cursor
142
+ rescue
143
+ # Cancel the reopen process if cursor method causes 'Cannot assign requested address' error
144
+ @sd_call_count = 0
145
+ return
146
+ end
147
+
148
+ filter_conditions = @reopen_filter_conditions.dup
149
+
150
+ close
151
+ initialize(@reopen_options)
152
+
153
+ restore_filters(filter_conditions)
154
+
155
+ seek(cursor)
156
+ # To avoid 'Cannot assign requested address' error
157
+ # It invokes native API directly to avoid nest with_auto_reopen calls
158
+ rc = Native.sd_journal_next_skip(@ptr, 0)
159
+ raise JournalError, rc if rc < 0
160
+
161
+ @sd_call_count = 0
162
+ end
163
+ end
164
+
165
+ ret
166
+ end
118
167
  end
119
168
  end
120
169
  end
@@ -1,6 +1,6 @@
1
1
  module Systemd
2
2
  class Journal
3
3
  # The version of the systemd-journal gem.
4
- VERSION = '2.0.0'.freeze
4
+ VERSION = "2.1.1".freeze
5
5
  end
6
6
  end
@@ -1,7 +1,7 @@
1
1
  module Systemd
2
2
  class Journal
3
3
  module Waitable
4
- IS_JRUBY = (RUBY_ENGINE == 'jruby')
4
+ IS_JRUBY = (RUBY_ENGINE == "jruby")
5
5
 
6
6
  # Block until the journal is changed.
7
7
  # @param timeout_usec [Integer] maximum number of microseconds to wait
@@ -21,7 +21,7 @@ module Systemd
21
21
  else
22
22
  rc = Native.sd_journal_wait(@ptr, timeout_usec)
23
23
  raise JournalError, rc if rc.is_a?(Integer) && rc < 0
24
- rc == :nop ? nil : rc
24
+ (rc == :nop) ? nil : rc
25
25
  end
26
26
  end
27
27
 
@@ -50,7 +50,7 @@ module Systemd
50
50
  private
51
51
 
52
52
  def wait_select(timeout_usec)
53
- timeout_sec = (timeout_usec == -1 ? nil : timeout_usec / 1e6)
53
+ timeout_sec = ((timeout_usec == -1) ? nil : timeout_usec / 1e6)
54
54
  r, *_ = IO.select([io_object], [], [], timeout_sec)
55
55
  r ? reason_for_wakeup : nil
56
56
  end
@@ -68,7 +68,7 @@ module Systemd
68
68
  def reason_for_wakeup
69
69
  rc = Native.sd_journal_process(@ptr)
70
70
  raise JournalError, rc if rc.is_a?(Integer) && rc < 0
71
- rc == :nop ? nil : rc
71
+ (rc == :nop) ? nil : rc
72
72
  end
73
73
  end
74
74
  end