Class: FSEvent

Inherits:
Object
  • Object
show all
Includes:
Util
Defined in:
lib/fsevent/framework.rb,
lib/fsevent.rb

Overview

framework.rb — fail safe event driven framework

Copyright © 2014 National Institute of Advanced Industrial Science and Technology (AIST)

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see <www.gnu.org/licenses/>.

Defined Under Namespace

Modules: Util Classes: AbstractDevice, DebugDumper, FSEventError, FailSafeDevice, PeriodicSchedule, ProcessDevice, ProcessDeviceC, ScheduleMerger, SimpleDevice, WatchSet

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Util

nested_hash, nonempty_hash, prefixpat_match, reaction_immediate_at_beginning?, reaction_immediate_at_subsequent?, valid_device_name_for_read?, valid_device_name_for_write?, valid_device_name_pat_for_read?, valid_status_name_for_read?, valid_status_name_for_write?, valid_status_name_pat_for_read?

Constructor Details

#initialize(initial_time = Time.now) ⇒ FSEvent

Returns a new instance of FSEvent.



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/fsevent/framework.rb', line 21

def initialize(initial_time=Time.now)
  @current_time = initial_time
  @current_count = 0

  @devices = {} # device_name -> device
  @device_last_run_count = {} # device_name -> count

  # special status:
  #   _fsevent : _device_registered_DEVICE_NAME       => time
  #   _fsevent : _device_unregistered_DEVICE_NAME     => time
  #   DEVICE_NAME : _status_defined_STATUS_NAME       => time
  #   DEVICE_NAME : _status_undefined_STATUS_NAME     => time
  #
  @status_value = { "_fsevent" => {} } # device_name -> status_name -> value
  @status_time = { "_fsevent" => {} } # device_name -> status_name -> time
  @status_count = { "_fsevent" => {} } # device_name -> status_name -> count

  @watchset = FSEvent::WatchSet.new

  @clock_proc = nil

  @q = Depq.new
  @schedule_locator = {} # device_name -> locator
end

Instance Attribute Details

#clock_procObject

Returns the value of attribute clock_proc.



46
47
48
# File 'lib/fsevent/framework.rb', line 46

def clock_proc
  @clock_proc
end

#current_timeObject (readonly)

Returns the value of attribute current_time.



45
46
47
# File 'lib/fsevent/framework.rb', line 45

def current_time
  @current_time
end

Instance Method Details

#add_watch(watchee_device_name_pat, status_name_pat, reaction = :immediate) ⇒ Object

Called from a device. (mainly from registered().)



94
95
96
97
98
99
100
101
102
# File 'lib/fsevent/framework.rb', line 94

def add_watch(watchee_device_name_pat, status_name_pat, reaction = :immediate)
  if !valid_device_name_pat_for_read?(watchee_device_name_pat)
    raise ArgumentError, "invalid device name pattern: #{watchee_device_name_pat.inspect}"
  end
  if !valid_status_name_pat_for_read?(status_name_pat)
    raise ArgumentError, "invalid status name pattern: #{status_name_pat.inspect}"
  end
  Thread.current[:fsevent_buffer] << [:add_watch, watchee_device_name_pat, status_name_pat, reaction]
end

#define_status(status_name, value) ⇒ Object

Called from a device to define the status.



116
117
118
119
120
121
# File 'lib/fsevent/framework.rb', line 116

def define_status(status_name, value)
  if !valid_status_name_for_write?(status_name)
    raise ArgumentError, "invalid status name: #{status_name.inspect}"
  end
  Thread.current[:fsevent_buffer] << [:define_status, status_name, value]
end

#del_watch(watchee_device_name_pat, status_name_pat) ⇒ Object

Called from a device. (mainly from registered().)



105
106
107
108
109
110
111
112
113
# File 'lib/fsevent/framework.rb', line 105

def del_watch(watchee_device_name_pat, status_name_pat)
  if !valid_device_name_pat_for_read?(watchee_device_name_pat)
    raise ArgumentError, "invalid device name pattern: #{watchee_device_name_pat.inspect}"
  end
  if !valid_status_name_pat_for_read?(status_name_pat)
    raise ArgumentError, "invalid status name pattern: #{status_name_pat.inspect}"
  end
  Thread.current[:fsevent_buffer] << [:del_watch, watchee_device_name_pat, status_name_pat]
end

#internal_undefine_status(device_name, run_end_time, status_name) ⇒ Object



330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
# File 'lib/fsevent/framework.rb', line 330

def internal_undefine_status(device_name, run_end_time, status_name)
  unless @status_value.has_key? device_name
    raise ArgumentError, "device not defined: #{device_name}"
  end
  unless @status_value[device_name].has_key? status_name
    raise ArgumentError, "device status not defined: #{device_name} #{status_name}"
  end
  @status_value[device_name].delete status_name
  @status_time[device_name][status_name] = @current_time
  @status_count[device_name][status_name] = @current_count
  lookup_watchers(device_name, status_name).each {|watcher_device_name, reaction|
    if watcher_device_name != device_name
      if reaction_immediate_at_subsequent? reaction
        set_wakeup_if_possible(watcher_device_name, run_end_time)
      end
    end
  }
  internal_update_status(device_name, run_end_time, "_status_undefined_#{status_name}", run_end_time)
end

#modify_status(status_name, value) ⇒ Object

Called from a device to notify the status.



124
125
126
127
128
129
# File 'lib/fsevent/framework.rb', line 124

def modify_status(status_name, value)
  if !valid_status_name_for_write?(status_name)
    raise ArgumentError, "invalid status name: #{status_name.inspect}"
  end
  Thread.current[:fsevent_buffer] << [:modify_status, status_name, value]
end

#register_device(device) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/fsevent/framework.rb', line 48

def register_device(device)
  device_name = device.name
  if !valid_device_name_for_write?(device_name)
    raise ArgumentError, "invalid device name: #{device_name.inspect}"
  end
  if !Thread.current[:fsevent_buffer]
    internal_register_device(device_name, device)
  else
    value = [:register_device, device_name, device]
    Thread.current[:fsevent_buffer] << value
  end
end

#set_elapsed_time(t) ⇒ Object

Called from a device to set the elapsed time.

Raises:

  • (ArgumentError)


148
149
150
151
# File 'lib/fsevent/framework.rb', line 148

def set_elapsed_time(t)
  raise ArgumentError, "negative elapsed time given: #{t}" if t < 0
  Thread.current[:fsevent_device_elapsed_time] = t
end

#startObject



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/fsevent/framework.rb', line 61

def start
  until @q.empty?
    loc = @q.delete_min_locator
    event_type, *args = loc.value
    @clock_proc.call(@current_time, loc.priority) if @clock_proc && @current_time != loc.priority
    @current_time = loc.priority
    @current_count += 1
    case event_type
    when :register_start; at_register_start(loc, *args)
    when :register_end; at_register_end(loc, *args)
    when :run_start; at_run_start(loc, *args)
    when :run_end; at_run_end(loc, *args)
    else
      raise FSEvent::FSEventError, "unexpected event type: #{event_type}"
    end
  end
end

#undefine_status(status_name) ⇒ Object

Called from a device to define the status.



132
133
134
135
136
137
# File 'lib/fsevent/framework.rb', line 132

def undefine_status(status_name)
  if !valid_status_name_for_write?(status_name)
    raise ArgumentError, "invalid status name: #{status_name.inspect}"
  end
  Thread.current[:fsevent_buffer] << [:undefine_status, status_name]
end

#unregister_device(device_name) ⇒ Object

Called from a device.



140
141
142
143
144
145
# File 'lib/fsevent/framework.rb', line 140

def unregister_device(device_name)
  if !valid_device_name_for_write?(device_name)
    raise ArgumentError, "invalid device name: #{device_name.inspect}"
  end
  Thread.current[:fsevent_buffer] << [:unregister_device, device_name]
end