class MultiMovingsign::Server
MultiMovingsign
server command line interface
Public Instance Methods
add_page()
click to toggle source
# File lib/multi_movingsign/server.rb, line 264 def add_page exit send_socket_command_expect_ok ['v1', 'add page', options[:name], File.read(options[:page])] end
alert()
click to toggle source
# File lib/multi_movingsign/server.rb, line 276 def alert exit send_socket_command_expect_ok ['v1', 'alert', File.read(options[:page])] end
delete_page()
click to toggle source
# File lib/multi_movingsign/server.rb, line 270 def delete_page exit send_socket_command_expect_ok ['v1', 'delete page', options[:name]] end
start()
click to toggle source
# File lib/multi_movingsign/server.rb, line 36 def start TestRCLoader.load(options['testrc']) if options['testrc'] # This impl is a hacky mess... FYI! FileUtils.mkdir_p server_settings_path lock_path = File.join(server_settings_path, "server.lock") File.open(lock_path, 'w') do |lock| raise "Cannot acquire lock! Is a server already running?" unless lock.flock(File::LOCK_EX | File::LOCK_NB) lock.puts $$ lock.flush mutex = Mutex.new # setup logging log_path = File.join(server_settings_path, "server.log") log = File.new(log_path, "a") $stdout = TeeIO.new($stdout, log) $stderr = TeeIO.new($stderr, log) signs = [] page_keys = [] page_solutions = {} page_index = 0 alert = nil stop = nil Thread.new do begin Socket.unix_server_loop(server_socket_path) do |socket, address| puts "SOCKET LOOP!" begin msg = nil begin msg, = socket.recvmsg_nonblock rescue IO::WaitReadable if IO.select([socket], [], [], 5) retry else raise TimeoutError, "Timeout in recvmsg_nonblock" end end unless msg $stderr.puts "Bogus unix_server_loop?" next end lines = msg.lines.map { |l| l.rstrip } puts "Got UNIX message: #{lines.inspect}" version = lines.delete_at 0 case command = lines.delete_at(0) when 'add page' name = lines.delete_at(0) yaml = lines.join "\n" solution = PageRenderer.new.render YAML.load(yaml), :count => signs.length page_path = File.join(server_pages_path, "#{name}.yml") File.open(page_path, "w") { |f| f.puts yaml } mutex.synchronize do page_solutions[name] = solution page_keys << name unless page_keys.include? name puts "Added #{name}!" page_keys.delete 'nada' page_solutions.delete 'nada' end socket.puts "okay" when 'delete page' name = lines.delete_at(0) mutex.synchronize do page_path = File.join(server_pages_path, "#{name}.yml") FileUtils.rm(page_path, :force => true) if File.exists? page_path page_keys.delete name page_solutions.delete name end puts "Deleted #{name}" socket.puts "okay" when 'alert' page_yaml = lines.join("\n") mutex.synchronize do condition_variable = ConditionVariable.new alert = {"solution" => PageRenderer.new.render(YAML.load(page_yaml), :count => signs.length), 'condition_variable' => condition_variable} puts "Signaling alert..." condition_variable.wait mutex end socket.puts "okay" when 'stop' mutex.synchronize do cv = ConditionVariable.new stop = {'condition_variable' => cv} cv.wait mutex end socket.puts "okay" else $stderr.puts "Unknown command '#{command}'" end rescue => e $stderr.puts "Exception in unix server loop" $stderr.puts e.message $stderr.puts e.backtrace.join "\n" ensure socket.close puts "SOCKET CLOSED" end end rescue => e $stderr.puts "UNIX socket loop raised!" $stderr.puts e.message $stderr.puts e.backtrace.join '\n' Thread::current.pi end end # Loop to allow reloaded loop do if stop puts "Outter loop stopping..." break end puts "Starting/Reloading!" # load sign configuration settings = Settings.load settings_path raise_no_signs unless settings.signs? mutex.synchronize do page_keys = [] page_solutions = {} signs = Signs.new settings.signs # Load pages and solutions FileUtils.mkdir_p server_pages_path Dir.glob(File.join(server_pages_path, '*.yml')).sort.each do |path| puts "Loading #{path}" key = File.basename(path, File.extname(path)) page_keys << key page_solutions[key] = PageRenderer.new.render YAML.load(File.read(path)), :count => signs.length end if page_keys.empty? page_keys << 'nada' page_solutions['nada'] = PageRenderer.new.render({'lines' => [{'prefix' => '', 'content' => ['No Pages']}, {'prefix' => '', 'content' => ['Configured']}]}, :count => signs.length) end end # Loop through pages loop do if stop puts "Inner loop stopping..." break end page_key = nil page_solution = nil mutex.synchronize do page_index = 0 if page_index >= page_keys.length || page_index < 0 # check for alert if alert page_key = 'ALERT' page_solution = alert['solution'] page_index -= 1 # extract condition_variable condition_variable = alert['condition_variable'] # clear alert alert = nil # signal that we got it! condition_variable.signal else page_key = page_keys[page_index] page_solution = page_solutions[page_key] end end puts "Sending page #{page_key}" signs.show_page_solution page_solution sleep_amount = page_solution['lines'] && page_solution['lines'] * 3 * 2 || 20 sleep_amount = 20 if sleep_amount < 2 sleep sleep_amount page_index += 1 end end if cv = stop && stop['condition_variable'] cv.signal sleep 1 # wait a bit for the CV recipient to finish before we do. end end end
stop()
click to toggle source
# File lib/multi_movingsign/server.rb, line 281 def stop exit send_socket_command_expect_ok ['v1', 'stop'] end
Private Instance Methods
send_socket_command(socket, args)
click to toggle source
# File lib/multi_movingsign/server.rb, line 296 def send_socket_command(socket, args) socket.sendmsg args.join "\n" socket.flush end
send_socket_command_expect_ok(args)
click to toggle source
# File lib/multi_movingsign/server.rb, line 287 def send_socket_command_expect_ok(args) UNIXSocket.open server_socket_path do |socket| send_socket_command(socket, args) puts "Sent message...awaiting reply..." (got = socket.gets) && got.strip == "okay" || false end end
server_pages_path()
click to toggle source
# File lib/multi_movingsign/server.rb, line 309 def server_pages_path File.join(server_settings_path, 'pages') end
server_settings_path()
click to toggle source
# File lib/multi_movingsign/server.rb, line 305 def server_settings_path options[:serverrc] || File.join(ENV['HOME'], '.multi_movingsign', 'server') end
server_socket_path()
click to toggle source
# File lib/multi_movingsign/server.rb, line 301 def server_socket_path File.join(server_settings_path, 'server.sock') end
settings_path()
click to toggle source
# File lib/multi_movingsign/server.rb, line 313 def settings_path options[:rc] || Settings.default_settings_path end