Class: Pipemaster::Client
- Inherits:
-
Object
- Object
- Pipemaster::Client
- Defined in:
- lib/pipemaster/client.rb
Overview
Pipemaster client. Use this to send commands to the Pipemaster server.
For example:
c = Pipemaster::Client.new
c.run :motd
puts c.output.string
=> "Toilet out of order please use floor below."
c = Pipemaster::Client.new(9988)
c.input = File.open("image.png")
c.output = File.open("thumbnail.png", "w")
c.run :transform, "thumbnail"
Constant Summary collapse
- BUFFER_SIZE =
16 * 1024
Class Attribute Summary collapse
-
.address ⇒ Object
Address to use by default for new clients.
Instance Attribute Summary collapse
-
#input ⇒ Object
Set this to supply an input stream (for commands that read from $stdin).
-
#output ⇒ Object
Set this to supply an output stream, or read the output (defaults to StringIO).
Class Method Summary collapse
-
.pipe(command, *args) ⇒ Object
Pipe stdin/stdout into the command.
Instance Method Summary collapse
-
#capture(input, output) ⇒ Object
Captures input and output.
-
#initialize(address = nil) ⇒ Client
constructor
Creates a new client.
-
#run(command, *args) ⇒ Object
Make a request.
Constructor Details
#initialize(address = nil) ⇒ Client
Creates a new client. Accepts optional address. If missing, uses the global address (see Pipemaster::Client::address). Address can be port number, hostname (default port), “host:port” or socket file name.
Examples:
Pipemaster::Client.new 7890
Pipemaster::Client.new "localhost:7890"
Pipemaster::Client.new
40 41 42 |
# File 'lib/pipemaster/client.rb', line 40 def initialize(address = nil) @address = (address || Client.address || DEFAULT_LISTEN) end |
Class Attribute Details
.address ⇒ Object
Address to use by default for new clients. Leave as nil to use the default (Pipemaster::DEFAULT_LISTEN).
29 30 31 |
# File 'lib/pipemaster/client.rb', line 29 def address @address end |
Instance Attribute Details
#input ⇒ Object
Set this to supply an input stream (for commands that read from $stdin).
45 46 47 |
# File 'lib/pipemaster/client.rb', line 45 def input @input end |
#output ⇒ Object
Set this to supply an output stream, or read the output (defaults to StringIO).
49 50 51 |
# File 'lib/pipemaster/client.rb', line 49 def output @output end |
Class Method Details
.pipe(command, *args) ⇒ Object
Pipe stdin/stdout into the command. For example:
exit Pipemaster.pipe(:echo)
23 24 25 |
# File 'lib/pipemaster/client.rb', line 23 def pipe(command, *args) new.capture($stdin, $stdout).run(command, *args) end |
Instance Method Details
#capture(input, output) ⇒ Object
Captures input and output. For example:
Pipemaster.new(7890).capture($stdin, $stdout).run(:echo)
53 54 55 56 |
# File 'lib/pipemaster/client.rb', line 53 def capture(input, output) self.input, self.output = input, output self end |
#run(command, *args) ⇒ Object
Make a request. First argument is the command name. All other arguments are optional. Returns the exit code (usually 0). Will raise IOError if it can’t talk to the server, or the server closed the connection prematurely.
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 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 |
# File 'lib/pipemaster/client.rb', line 62 def run(command, *args) # Connect and send arguments. socket = connect(@address) socket.sync = true header = ([command] + args).join("\0") socket << [header.size].pack("N") << header socket.flush @output ||= StringIO.new # If there's input, stream it over to the socket, while streaming the # response back. inputbuf, stdoutbuf = "", "" if @input while selected = select([@input, socket]) begin if selected.first.include?(@input) @input.readpartial(BUFFER_SIZE, inputbuf) socket.write inputbuf elsif selected.first.include?(socket) raise IOError, "Server closed socket" if socket.eof? @output.write stdoutbuf if stdoutbuf stdoutbuf = socket.readpartial(BUFFER_SIZE) end rescue EOFError break end end end socket.close_write # tell other side there's no more input # Read remaining response and stream to output. Remember that very last # byte is return code. while selected = select([socket]) break if socket.eof? @output.write stdoutbuf if stdoutbuf stdoutbuf = socket.readpartial(BUFFER_SIZE) end if stdoutbuf && stdoutbuf.size > 0 status = stdoutbuf[-1] @output.write stdoutbuf[0..-2] return status.ord else raise IOError, "Server closed socket" if socket.eof? end ensure socket.close rescue nil end |