Class: Iyyov::Context

Inherits:
Object
  • Object
show all
Defined in:
lib/iyyov/context.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize {|_self| ... } ⇒ Context

Returns a new instance of Context.

Yields:

  • (_self)

Yield Parameters:



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/iyyov/context.rb', line 58

def initialize
  super

  @base_dir     = "/opt/var"
  @make_run_dir = true
  @stop_on_exit = false
  @stop_delay   = 30.0
  @watch_files  = true

  #FIXME: Support other gem home than ours?

  @rotators  = {}
  @daemons   = {}
  @state     = :begin
  @log = RJack::SLF4J[ self.class ]
  @scheduler = Scheduler.new
  @scheduler.on_exit { do_shutdown }
  @files     = {}
  @root_files = []

  # By default with potential for override
  iyyov_log_rotate

  yield self if block_given?
end

Instance Attribute Details

#base_dirObject

Default base directory under which Daemon run directories are found

~to_s (default: /opt/var)



32
33
34
# File 'lib/iyyov/context.rb', line 32

def base_dir
  @base_dir
end

#daemonsObject (readonly)

Returns the value of attribute daemons.



56
57
58
# File 'lib/iyyov/context.rb', line 56

def daemons
  @daemons
end

#make_run_dirObject

Default whether to make Daemon run directories if not already present.

Boolean (default: true)



37
38
39
# File 'lib/iyyov/context.rb', line 37

def make_run_dir
  @make_run_dir
end

#schedulerObject (readonly)

Returns the value of attribute scheduler.



55
56
57
# File 'lib/iyyov/context.rb', line 55

def scheduler
  @scheduler
end

#stop_delayObject

Default duration in seconds between SIGTERM and final SIGKILL when stopping Daemons.

Numeric (default: 30.0)



48
49
50
# File 'lib/iyyov/context.rb', line 48

def stop_delay
  @stop_delay
end

#stop_on_exitObject

Default whether to stop Daemons on Iyyov exit.

Boolean (default: false)



42
43
44
# File 'lib/iyyov/context.rb', line 42

def stop_on_exit
  @stop_on_exit
end

#watch_filesObject

Watch loaded config files for changes?

Boolean (default: true)



53
54
55
# File 'lib/iyyov/context.rb', line 53

def watch_files
  @watch_files
end

Instance Method Details

#define_daemon(&block) ⇒ Object



118
119
120
121
122
123
124
125
126
# File 'lib/iyyov/context.rb', line 118

def define_daemon( &block )
  d = Daemon.new( self, &block )
  if @daemons.has_key?( d.full_name )
    raise( SetupError,
           "Can't define daemon with duplicate full_name = #{d.full_name}" )
  end
  @daemons[ d.full_name ] = d
  nil
end

#do_shutdownObject



89
90
91
92
93
94
95
# File 'lib/iyyov/context.rb', line 89

def do_shutdown
  unless @state == :shutdown
    @log.info "Shutting down"
    @daemons.values.each { |d| d.do_exit }
    @state = :shutdown
  end
end

#event_loopObject



218
219
220
221
222
223
224
225
226
227
228
229
230
# File 'lib/iyyov/context.rb', line 218

def event_loop
  @state = :starting
  start_and_register_daemons
  register_rotator_tasks
  register_files_watch_task

  @log.debug "Event loop starting"
  @state = :running
  rc = @scheduler.event_loop
  @state = :exit
  @log.debug { "Event loop exited: #{rc.inspect}" }
  rc
end

#iyyov_log_rotate(&block) ⇒ Object

Setup log rotation for the iyyov daemon itself



104
105
106
107
108
109
110
111
# File 'lib/iyyov/context.rb', line 104

def iyyov_log_rotate( &block )
  rf = Java::java.lang.System.get_property( "hashdot.io_redirect.file" )
  if rf && File.exist?( rf )
    lr = LogRotator.new( rf, &block )
    lr.pid = 0
    @rotators[ lr.log ] = lr
  end
end

#load_directory(dir) ⇒ Object

Load all executable *.rb files in the specified directory. Non-executable *.rb files are assumed temporarily disabled and are still watched for a ctime change. The directory itself is also watched for an mtime change (as in adding a new file).



133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/iyyov/context.rb', line 133

def load_directory( dir )
  @files[ dir ] = [ File.stat( dir ).mtime, nil ]

  Dir.glob( File.join( dir, '*.rb' ) ) do |file|
    fstat = File.stat( file )
    if fstat.executable?
      load_file( file )
    else
      # Still watch ctime on this file, so if it changes to executable
      # we reload.
      @files[ file ] = [ nil, fstat.ctime ]
    end
  end
end

#load_file(file, is_root = false) ⇒ Object



148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/iyyov/context.rb', line 148

def load_file( file, is_root = false )
  @log.info { "Loading #{file}" }
  begin
    fstat = File.stat( file )
    @files[ file ] = [ fstat.mtime, fstat.ctime ]
    load file
    @root_files << file if is_root
    true
  rescue SetupError, ScriptError, StandardError => e
    @log.error( "On load of #{file}", e )
    false
  end
end

#log_rotate(&block) ⇒ Object

Setup log rotation not associated with a daemon



98
99
100
101
# File 'lib/iyyov/context.rb', line 98

def log_rotate( &block )
  lr = LogRotator.new( nil, &block )
  @rotators[ lr.log ] = lr
end

#register_files_watch_taskObject



175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
# File 'lib/iyyov/context.rb', line 175

def register_files_watch_task
  return unless @watch_files && ! @files.empty?
  t = Task.new( :name => "watch-files", :period => 11.0 ) do
    reload = false
    @files.each do |fname, (last_mtime, last_ctime)|
      begin
        fstat = File.stat( fname )
        if last_mtime && ( last_mtime != fstat.mtime )
          @log.info { "#{fname} has new modification time, reloading." }
          reload = true
          break
        end
        if last_ctime && ( last_ctime != fstat.ctime )
          @log.info { "#{fname} has new change time, reloading." }
          reload = true
          break
        end
      rescue Errno::ENOENT, Errno::EACCES => e
        @log.error( e.to_s )
      end
    end
    rc = :continue
    if reload
      @log.info { "Rescaning gems." }
      Gem.clear_paths
      if Iyyov.load_root_files( @root_files )
        @log.info "Load passed, shutdown"
        rc = :shutdown
      end
    end
    rc
  end
  @scheduler.add( t )
end

#register_rotator_tasksObject



162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/iyyov/context.rb', line 162

def register_rotator_tasks
  @rotators.values.each do |lr|
    t = Task.new( :name => rotate_name( lr.log ),
                  :mode => :async,
                  :period => lr.check_period ) do
      lr.check_rotate do |rlog|
        @log.info { "Rotating log #{rlog}" }
      end
    end
    @scheduler.add( t )
  end
end

#rotate_name(log_file) ⇒ Object



214
215
216
# File 'lib/iyyov/context.rb', line 214

def rotate_name( log_file )
  "#{ File.basename( log_file, ".log" ) }.rotate"
end

#schedule_at(opts = {}, &block) ⇒ Object



113
114
115
116
# File 'lib/iyyov/context.rb', line 113

def schedule_at( opts = {}, &block )
  t = Task.new( opts, &block )
  @scheduler.add( t )
end

#shutdownObject



84
85
86
87
# File 'lib/iyyov/context.rb', line 84

def shutdown
  do_shutdown
  @scheduler.off_exit
end

#start_and_register_daemonsObject



210
211
212
# File 'lib/iyyov/context.rb', line 210

def start_and_register_daemons
  @daemons.values.each { |d| d.do_first( @scheduler ) }
end