Class: PcaprLocal::Xtractr::Instance
- Inherits:
-
Object
- Object
- PcaprLocal::Xtractr::Instance
- Defined in:
- lib/pcapr_local/xtractr/instance.rb
Defined Under Namespace
Classes: XtractrStartupException
Constant Summary collapse
- MAX_START_TIME =
Start xtractr
30
- RE_STARTED =
/starting on http:/i
Instance Attribute Summary collapse
-
#last_use ⇒ Object
readonly
Returns the value of attribute last_use.
-
#lock ⇒ Object
readonly
Returns the value of attribute lock.
-
#pid ⇒ Object
readonly
Returns the value of attribute pid.
-
#port ⇒ Object
readonly
Returns the value of attribute port.
Class Method Summary collapse
-
.free_local_port ⇒ Object
Pick a random port over 10000 and verify that it can be bound to (on localhost).
Instance Method Summary collapse
- #do_start ⇒ Object
-
#get(path_and_params) ⇒ Object
Does GET request and returns response headers and body.
-
#initialize(index_dir, xtractr_path) ⇒ Instance
constructor
A new instance of Instance.
-
#kind_kill(pid, wait = 1) ⇒ Object
Sends SIGTERM and waits for process to exit.
-
#post(path_and_params, post_body) ⇒ Object
Does POST request and returns response headers and body.
-
#start ⇒ Object
Starts underlying process.
-
#stop ⇒ Object
Kills underlying xtractr process.
Constructor Details
#initialize(index_dir, xtractr_path) ⇒ Instance
Returns a new instance of Instance.
14 15 16 17 18 19 20 21 |
# File 'lib/pcapr_local/xtractr/instance.rb', line 14 def initialize index_dir, xtractr_path @index_dir = index_dir @xtractr_path = xtractr_path @lock = Mutex.new @last_use = Time.new.to_f # for idle timeouts @pid = nil @port = nil end |
Instance Attribute Details
#last_use ⇒ Object (readonly)
Returns the value of attribute last_use.
12 13 14 |
# File 'lib/pcapr_local/xtractr/instance.rb', line 12 def last_use @last_use end |
#lock ⇒ Object (readonly)
Returns the value of attribute lock.
12 13 14 |
# File 'lib/pcapr_local/xtractr/instance.rb', line 12 def lock @lock end |
#pid ⇒ Object (readonly)
Returns the value of attribute pid.
12 13 14 |
# File 'lib/pcapr_local/xtractr/instance.rb', line 12 def pid @pid end |
#port ⇒ Object (readonly)
Returns the value of attribute port.
12 13 14 |
# File 'lib/pcapr_local/xtractr/instance.rb', line 12 def port @port end |
Class Method Details
.free_local_port ⇒ Object
Pick a random port over 10000 and verify that it can be bound to (on localhost)
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/pcapr_local/xtractr/instance.rb', line 151 def self.free_local_port while true port = rand(0xffff-10000) + 10000 socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0) socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1) addr = Socket.pack_sockaddr_in(port, '127.0.0.1') begin socket.bind addr return port rescue Errno::EADDRINUSE next # port in use ensure socket.close end end end |
Instance Method Details
#do_start ⇒ Object
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/pcapr_local/xtractr/instance.rb', line 81 def do_start port = Instance.free_local_port command = [@xtractr_path, 'browse', @index_dir, '--port', port.to_s] Logger.debug "running: #{command.inspect}" xtractr_out = Tempfile.new "xtractr_out" pid = fork do # Xtractr forks a child process. Set process group so we # can send signal to all processes in a group. Process.setpgid $$, $$ STDOUT.reopen xtractr_out STDERR.reopen xtractr_out Dir.chdir @index_dir exec *command end begin Timeout.timeout MAX_START_TIME do # Wait for "starting" line. while xtractr_out.grep(/starting on http:\/\/127\.0\.0\.1:#{port}/i).empty? xtractr_out.rewind sleep 0.01 end # Sanity check that server is up. Net::HTTP.start('127.0.0.1', port) do |http| http.("/") end end rescue Timeout::Error, SystemCallError Logger.error "Xtractr failed to start on port #{port}" xtractr_out.rewind Logger.error "Xtractr output: #{xtractr_out.read.inspect}" kind_kill -pid raise XtractrStartupException, "Timeout waiting for xtractr to startup" end @last_use = Time.new.to_f @pid = pid @port = port end |
#get(path_and_params) ⇒ Object
Does GET request and returns response headers and body.
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/pcapr_local/xtractr/instance.rb', line 24 def get path_and_params start if not @pid @lock.synchronize do @last_use = Time.new.to_f # Make request to xtractr uri = URI.parse("http://127.0.0.1:#{@port}/#{path_and_params}") response = Net::HTTP.get_response(uri) # Copy headers from response headers = {} response.each_header {|name,val| headers[name] = val} return response.code.to_i, headers, response.body end end |
#kind_kill(pid, wait = 1) ⇒ Object
Sends SIGTERM and waits for process to exit. If process does not exit within wait period, sends SIGKILL. Use a negative pid to kill all members of a process group.
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/pcapr_local/xtractr/instance.rb', line 132 def kind_kill pid, wait=1 begin Process.kill 15, pid # Wait for process (or all group members) to # exit. Timeout.timeout wait do loop { Process.wait(pid) } end rescue Errno::ECHILD, Errno::ESRCH # Processes is dead or group has no members. return rescue Timeout::Error, StandardError # Process did not shutdown in time (or there # was an unexpected error). Process.kill(9, pid) rescue nil end end |
#post(path_and_params, post_body) ⇒ Object
Does POST request and returns response headers and body.
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/pcapr_local/xtractr/instance.rb', line 42 def post path_and_params, post_body start if not @pid @lock.synchronize do @last_use = Time.new.to_f # Make request to xtractr Net::HTTP.start('localhost', @port) do |http| http.request_post "/#{path_and_params}", post_body do |response| headers = {} response.each_header {|name,val| headers[name] = val} return response.code.to_i, headers, response.body end end end end |
#start ⇒ Object
Starts underlying process.
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/pcapr_local/xtractr/instance.rb', line 59 def start @lock.synchronize do return if @pid err = nil # There is a remote possibility that the random port we pick will be # in use at the moment we try to bind to it. Thus the retries. 3.times do |n| begin do_start return rescue => err end end raise err end end |
#stop ⇒ Object
Kills underlying xtractr process.
122 123 124 125 126 127 |
# File 'lib/pcapr_local/xtractr/instance.rb', line 122 def stop if @pid kind_kill -@pid @pid = nil end end |