lib/rumai/ixp/transport.rb in rumai-3.2.0 vs lib/rumai/ixp/transport.rb in rumai-3.2.1
- old
+ new
@@ -1,10 +1,6 @@
# Transport layer for 9P2000 protocol.
-#--
-# Copyright protects this work.
-# See LICENSE file for details.
-#++
require 'rumai/ixp/message'
require 'thread' # for Mutex and Queue
module Rumai
@@ -18,11 +14,11 @@
#
class Agent
attr_reader :msize
##
- # [stream]
+ # @param stream
# I/O stream on which a 9P2000 server is listening.
#
def initialize stream
@stream = stream
@@ -103,11 +99,11 @@
@pool << member
end
end
##
- # Sends the given request (Rumai::IXP::Fcall) and returns
+ # Sends the given request {Rumai::IXP::Fcall} and returns
# a ticket that you can use later to receive the reply.
#
def send request
tag = @tag_pool.obtain
@@ -117,29 +113,42 @@
tag
end
##
# Returns the reply for the given ticket, which was previously given
- # to you when you sent the corresponding request (Rumai::IXP::Fcall).
+ # to you when you sent the corresponding request {Rumai::IXP::Fcall}.
#
def recv tag
loop do
reply = @recv_lock.synchronize do
if @recv_buf.key? tag
@recv_buf.delete tag
else
- # reply was not in the receive buffer, so wait
- # for the next reply... hoping that it is ours
- msg = Fcall.from_9p(@stream)
+ # reply was not in receive buffer, so read
+ # the next reply... hoping that it is ours
- if msg.tag == tag
- msg
- else
- # we got someone else's reply, so buffer
- # it (for them to receive) and try again
- @recv_buf[msg.tag] = msg
- nil
+ next_reply_available =
+ @recv_buf.empty? || begin
+ # check (in a non-blocking fashion) if
+ # the stream has reply for us right now
+ @stream.ungetc @stream.read_nonblock(1)
+ true
+ rescue Errno::EAGAIN
+ # the stream is empty
+ end
+
+ if next_reply_available
+ msg = Fcall.from_9p(@stream)
+
+ if msg.tag == tag
+ msg
+ else
+ # we got someone else's reply, so buffer
+ # it (for them to receive) and try again
+ @recv_buf[msg.tag] = msg
+ nil
+ end
end
end
end
if reply
@@ -156,11 +165,11 @@
end
end
end
##
- # Sends the given request (Rumai::IXP::Fcall) and returns its reply.
+ # Sends the given request {Rumai::IXP::Fcall} and returns its reply.
#
def talk request
tag = send(request)
begin
@@ -188,17 +197,17 @@
mode.to_i
end
end
##
- # Opens the given path for I/O access through a FidStream
+ # Opens the given path for I/O access through a {FidStream}
# object. If a block is given, it is invoked with a
- # FidStream object and the stream is closed afterwards.
+ # {FidStream} object and the stream is closed afterwards.
#
- # See File::open in the Ruby documentation.
+ # @see File::open
#
- def open path, mode = 'r' # :yields: FidStream
+ def open path, mode = 'r'
mode = MODES.parse(mode)
# open the file
path_fid = walk(path)
@@ -222,11 +231,11 @@
end
##
# Encapsulates I/O access over a file handle (fid).
#
- # NOTE: this class is NOT thread safe!
+ # @note this class is NOT thread safe!
#
class FidStream
attr_reader :fid, :stat
attr_reader :eof
@@ -270,21 +279,21 @@
@closed
end
##
# Reads some data from this stream at the current position.
+ # If this stream corresponds to a directory, then an Array of
+ # Stat (one for each file in the directory) will be returned.
#
- # [partial]
+ # @param [Boolean] partial
+ #
# When false, the entire content of
# this stream is read and returned.
#
# When true, the maximum amount of content that can fit
# inside a single 9P2000 message is read and returned.
#
- # If this stream corresponds to a directory, then an Array of
- # Stat (one for each file in the directory) will be returned.
- #
def read partial = false
raise 'cannot read from a closed stream' if @closed
content = ''
begin
@@ -353,11 +362,11 @@
##
# Returns the basenames of all files
# inside the directory at the given path.
#
- # See Dir::entries in the Ruby documentation.
+ # @see Dir::entries
#
def entries path
unless stat(path).directory?
raise ArgumentError, "#{path.inspect} is not a directory"
end
@@ -476,10 +485,10 @@
private
##
# Invokes the given block with a temporary FID.
#
- def with_fid # :yields: fid
+ def with_fid
begin
fid = @fid_pool.obtain
yield fid
ensure
clunk fid