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