about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2011-11-02 23:20:58 +0000
committerEric Wong <normalperson@yhbt.net>2011-11-02 23:20:58 +0000
commit93242dbc664409e8bd78f021ba7b527f340fa1d7 (patch)
tree488c4c8d3ca981a5cfd6322a4fea7c678ad5c5d4
parentc5bb0bffe17e7fa924fcca2f5dc85271ac466cea (diff)
downloadmogilefs-client-93242dbc664409e8bd78f021ba7b527f340fa1d7.tar.gz
We're trying to use as much as we can from Ruby 1.9
-rwxr-xr-xbin/mog2
-rw-r--r--lib/mogilefs/mogilefs.rb6
-rw-r--r--lib/mogilefs/socket_common.rb4
-rw-r--r--lib/mogilefs/util.rb71
-rw-r--r--test/test_mogilefs.rb2
5 files changed, 16 insertions, 69 deletions
diff --git a/bin/mog b/bin/mog
index 932e766..c62d818 100755
--- a/bin/mog
+++ b/bin/mog
@@ -129,7 +129,7 @@ begin
       if (!cat[:raw] && key =~ /^_big_info:/)
         mg.bigfile_write(key, STDOUT, {:verify => true})
       else
-        mg.get_file_data(key) { |fp| sysrwloop(fp, STDOUT) }
+        mg.get_file_data(key) { |fp| copy_stream(fp, STDOUT) }
       end
     end
   when 'ls'
diff --git a/lib/mogilefs/mogilefs.rb b/lib/mogilefs/mogilefs.rb
index 6c4220b..f064d43 100644
--- a/lib/mogilefs/mogilefs.rb
+++ b/lib/mogilefs/mogilefs.rb
@@ -139,15 +139,15 @@ class MogileFS::MogileFS < MogileFS::Client
     raise MogileFS::ReadOnlyError if readonly?
 
     new_file key, klass do |mfp|
-      if file.respond_to? :sysread then
-        sysrwloop(file, mfp)
+      if file.respond_to?(:read)
+        copy_stream(file, mfp)
       else
         size = File.size(file)
         if size > 0x10000 # Bigass file, handle differently
           mfp.big_io = file
           size
         else
-          File.open(file, "rb") { |fp| sysrwloop(fp, mfp) }
+          File.open(file, "rb") { |fp| copy_stream(fp, mfp) }
         end
       end
     end
diff --git a/lib/mogilefs/socket_common.rb b/lib/mogilefs/socket_common.rb
index 567e715..e724e8f 100644
--- a/lib/mogilefs/socket_common.rb
+++ b/lib/mogilefs/socket_common.rb
@@ -51,4 +51,8 @@ module MogileFS::SocketCommon
 
     buf # full read
   end
+
+  def readpartial(size, buf = "", timeout = 5)
+    timed_read(size, buf, timeout) or raise EOFError, "end of file reached"
+  end
 end
diff --git a/lib/mogilefs/util.rb b/lib/mogilefs/util.rb
index 8f315aa..ece5645 100644
--- a/lib/mogilefs/util.rb
+++ b/lib/mogilefs/util.rb
@@ -3,9 +3,6 @@ require 'mogilefs'
 require 'socket'
 
 module MogileFS::Util
-
-  CHUNK_SIZE = 65536
-
   # TODO: cleanup
   if IO.respond_to?(:copy_stream)
     def copy_stream(src, dst)
@@ -13,70 +10,16 @@ module MogileFS::Util
     end
   else
     def copy_stream(src, dst)
-      sysrwloop(src, dst)
-    end
-  end
-
-  # for copying large files while avoiding GC thrashing as much as possible
-  # writes the contents of io_rd into io_wr, running through filter if
-  # it is a Proc object.  The filter proc must respond to a string
-  # argument (and return a string) and to nil (possibly returning a
-  # string or nil).  This can be used to filter I/O through an
-  # Zlib::Inflate or Digest::MD5 object
-  def sysrwloop(io_rd, io_wr, filter = nil)
-    copied = 0
-    # avoid making sysread repeatedly allocate a new String
-    # This is not well-documented, but both read/sysread can take
-    # an optional second argument to use as the buffer to avoid
-    # GC overhead of creating new strings in a loop
-    buf = ' ' * CHUNK_SIZE # preallocate to avoid GC thrashing
-    io_rd.flush rescue nil # flush may be needed for sockets/pipes, be safe
-    io_wr.flush
-    io_rd.sync = io_wr.sync = true
-    loop do
-      b = begin
-        io_rd.sysread(CHUNK_SIZE, buf)
-      rescue Errno::EAGAIN, Errno::EINTR
-        IO.select([io_rd], nil, nil, nil)
-        retry
+      buf = ""
+      written = 0
+      begin
+        src.readpartial(0x4000, buf)
+        written += dst.write(buf)
       rescue EOFError
         break
-      end
-      b = filter.call(b) if filter
-      copied += syswrite_full(io_wr, b)
-    end
-
-    # filter must take nil as a possible argument to indicate EOF
-    if filter
-      b = filter.call(nil)
-      copied += syswrite_full(io_wr, b) if b && b.length > 0
-    end
-    copied
-  end # sysrwloop
-
-  # writes the contents of buf to io_wr in full w/o blocking
-  def syswrite_full(io_wr, buf, timeout = nil)
-    written = 0
-    loop do
-      begin
-        w = io_wr.syswrite(buf)
-        written += w
-        return written if w == buf.size
-        buf = buf[w..-1]
-
-        # a short syswrite means the next syswrite will likely block
-        # inside the interpreter.  so force an IO.select on it so we can
-        # timeout there if one was specified
-        raise Errno::EAGAIN if timeout
-      rescue Errno::EAGAIN, Errno::EINTR
-        t0 = Time.now if timeout
-        IO.select(nil, [io_wr], nil, timeout)
-        if timeout && ((timeout -= (Time.now - t0)) < 0)
-          raise MogileFS::Timeout, 'syswrite_full timeout'
-        end
-      end
+      end while true
+      written
     end
-    # should never get here
   end
 
   class StoreContent < Proc
diff --git a/test/test_mogilefs.rb b/test/test_mogilefs.rb
index 1749a97..7fe53e2 100644
--- a/test/test_mogilefs.rb
+++ b/test/test_mogilefs.rb
@@ -103,7 +103,7 @@ class TestMogileFS__MogileFS < TestMogileFS
       readed = client.recv(4096, 0)
       assert(readed =~ \
             %r{\AGET /dev[12]/0/000/000/0000000062\.fid HTTP/1.[01]\r\n\r\n\Z})
-      sysrwloop(tmpfp, client)
+      copy_stream(tmpfp, client)
       client.close
       exit 0
     end