Forum: Ruby DRb::DRbBadScheme when using drbunix sockets, why?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Db524516a64318b0e937d41357c729eb?d=identicon&s=25 John Stoffel (johnstoffel)
on 2009-02-13 23:06
Hi,

I've been slowly hacking on my parallel recursive readdir()
implementation using a limited number of parallel processes, since as
you all know, Ruby threads are not truly parallel.

Anyway, I'm now getting wierd errors like the following:

  Starting DRb on server
  Exception `DRb::DRbBadScheme' at /usr/lib/ruby/1.8/drb/drb.rb:814 -
drbunix:///tmp/stoffj-test_17986
  Exception `DRb::DRbBadScheme' at /usr/lib/ruby/1.8/drb/drb.rb:814 -
drbunix:///tmp/stoffj-test_17986
  Exception `DRb::DRbBadScheme' at /usr/lib/ruby/1.8/drb/drb.rb:814 -
drbunix:///tmp/stoffj-test_17986
  counter.count=1

And it's not really clear to my *why* I'm getting these errors, or how I
can trap them so I'm not bothered by them.  The basic code uses both DRb
and Slave libraries to make the interprocess communication simpler, and
to have a central counting server to regulate the number of
sub-processes I'll be using at any one point in time.

So, first off, here's a full set of output of my code on a test
directory.

Thanks for any hints or suggestions.  I *think* I need to use begin ...
rescue ... end blocks possibly, but it's not clear where.  Oh yeah, I'm
running this all on a CentOS 5.2 (RHEL5.2) Final system, against a small
350Mb test directory tree.

Thanks,
John

------------------------------- log ----------------------------------

$ ./readdir-drb.rb tmp
Starting DRb on server
Exception `DRb::DRbBadScheme' at /usr/lib/ruby/1.8/drb/drb.rb:814 -
drbunix:///tmp/stoffj-test_17986
Exception `DRb::DRbBadScheme' at /usr/lib/ruby/1.8/drb/drb.rb:814 -
drbunix:///tmp/stoffj-test_17986
Exception `DRb::DRbBadScheme' at /usr/lib/ruby/1.8/drb/drb.rb:814 -
drbunix:///tmp/stoffj-test_17986
counter.count=1
 Threaded!
Exception `DRb::DRbBadScheme' at /usr/lib/ruby/1.8/drb/drb.rb:814 -
drbunix:///tmp/slave_proc_537506070_17986_17988_0_0.125356081811465
Exception `DRb::DRbBadScheme' at /usr/lib/ruby/1.8/drb/drb.rb:814 -
drbunix:///tmp/slave_proc_537506070_17986_17988_0_0.125356081811465
Exception `DRb::DRbBadScheme' at /usr/lib/ruby/1.8/drb/drb.rb:814 -
drbunix:///tmp/slave_proc_537506070_17986_17988_0_0.125356081811465
 Threaded!
Exception `DRb::DRbBadScheme' at /usr/lib/ruby/1.8/drb/drb.rb:814 -
drbunix:///tmp/slave_proc_537512250_17988_17989_0_0.20115187038118
Exception `DRb::DRbBadScheme' at /usr/lib/ruby/1.8/drb/drb.rb:814 -
drbunix:///tmp/slave_proc_537512250_17988_17989_0_0.20115187038118
Exception `DRb::DRbBadScheme' at /usr/lib/ruby/1.8/drb/drb.rb:814 -
drbunix:///tmp/slave_proc_537512250_17988_17989_0_0.20115187038118
size = 372104960
size = 373477128
Exception `NameError' at /usr/lib/ruby/site_ruby/1.8/slave.rb:409 -
uninitialized constant Slave::DBb
Exception `RuntimeError' at /usr/lib/ruby/site_ruby/1.8/slave.rb:519 -
already shutdown
exit (SystemExit)
/usr/lib/ruby/site_ruby/1.8/slave.rb:265:in `exit'
/usr/lib/ruby/site_ruby/1.8/slave.rb:265:in `cling'
/usr/lib/ruby/site_ruby/1.8/slave.rb:259:in `call'
/usr/lib/ruby/site_ruby/1.8/slave.rb:259:in `on_cut'
/usr/lib/ruby/site_ruby/1.8/slave.rb:251:in `initialize'
/usr/lib/ruby/site_ruby/1.8/slave.rb:251:in `new'
/usr/lib/ruby/site_ruby/1.8/slave.rb:251:in `on_cut'
/usr/lib/ruby/site_ruby/1.8/slave.rb:265:in `cling'
/usr/lib/ruby/site_ruby/1.8/slave.rb:415:in `initialize'
/usr/lib/ruby/site_ruby/1.8/slave.rb:593:in `new'
/usr/lib/ruby/site_ruby/1.8/slave.rb:593:in `object'
./readdir-drb.rb:114:in `readdir'
./readdir-drb.rb:86:in `foreach'
./readdir-drb.rb:86:in `readdir'
./readdir-drb.rb:207

Total size: 373477128 B
Total size: 364723 KB
Total size: 356 MB
Total size: 0 GB
Exception `Errno::ENOENT' at /usr/lib/ruby/1.8/fileutils.rb:1281 - No
such file or directory -
/tmp/slave_proc_537506070_17986_17988_0_0.125356081811465
Exception `RuntimeError' at /usr/lib/ruby/site_ruby/1.8/slave.rb:519 -
already shutdown
rt3.taec.com:~/src/Tools/philesight-20081120$ Exception `NameError' at
/usr/lib/ruby/site_ruby/1.8/slave.rb:409 - uninitialized constant
Slave::DBb
Exception `Errno::ENOENT' at /usr/lib/ruby/1.8/fileutils.rb:1281 - No
such file or directory -
/tmp/slave_proc_537512250_17988_17989_0_0.20115187038118
Exception `IOError' at /usr/lib/ruby/1.8/drb/unix.rb:92 - stream closed
Exception `Errno::EBADF' at /usr/lib/ruby/1.8/drb/unix.rb:92 - Bad file
descriptor - ///tmp/slave_proc_537512250_17988_17989_0_0.20115187038118
/usr/lib/ruby/1.8/drb/unix.rb:92:in `close': Bad file descriptor -
///tmp/slave_proc_537512250_17988_17989_0_0.20115187038118
(Errno::EBADF)
        from /usr/lib/ruby/1.8/drb/unix.rb:92:in `close'
        from /usr/lib/ruby/1.8/drb/drb.rb:1433:in `run'
        from /usr/lib/ruby/1.8/drb/drb.rb:1427:in `start'
        from /usr/lib/ruby/1.8/drb/drb.rb:1427:in `run'
        from /usr/lib/ruby/1.8/drb/drb.rb:1347:in `initialize'
        from /usr/lib/ruby/1.8/drb/drb.rb:1627:in `new'
        from /usr/lib/ruby/1.8/drb/drb.rb:1627:in `start_service'
        from /usr/lib/ruby/site_ruby/1.8/slave.rb:396:in `initialize'
         ... 28 levels...
        from ./readdir-drb.rb:114:in `readdir'
        from ./readdir-drb.rb:86:in `foreach'
        from ./readdir-drb.rb:86:in `readdir'
        from ./readdir-drb.rb:207


--------------------------- source
--------------------------------------

And here's my source code, excuse my lack of Ruby knowledge, I'm a newb
to Ruby, though not to programming.  Hopefully that is shown.  :]

#!/usr/bin/ruby

require 'getoptlong'
require 'thread'
require 'slave'
require 'drb'
require 'drb/unix'

$VERSION = "v1.0";
$max_slaves = 3
$count = 50

# Local Socket - need to worry about multiple runs of this script, so
add on
# unique PID.
$URI = "drbunix:///tmp/stoffj-test_" + Process.pid.to_s

slave_cnt_mutex = Mutex.new

opts = GetoptLong.new(
                      [ "--help", "-h", GetoptLong::NO_ARGUMENT],
                      [ "--kids", "-k", GetoptLong::REQUIRED_ARGUMENT]
                      )

#---------------------------------------------------------------------
class Counter
  def initialize(max=1)
    @slaves = []
    @max = max
    @count = 1
    @count_mutex = Mutex.new
  end

  def count
    @count
  end

  def max
    @max
  end

  # Increment the count of slaves, returning 1 if incremented, 0 if not.
  def increment
    ok = nil
    @count_mutex.synchronize do
      if (@count < @max) then
        @count += 1
        ok = 1
      end
    end
    ok
  end

  # Decrement the count of slaves
  def decrement
    @count_mutex.synchronize do
      if (@count > 1) then
        @count -= 1
      end
    end
    @count
  end
end

#---------------------------------------------------------------------
class ReadDir
  def initialize(server)
    @server = server

    # Slave pool for this level of readdir() recursion.
    @kids = []

  end

  def readdir(dir)

    #puts "readdir(#{dir})"

    size_file = {}
    size_dir = {}
    size_total = 0

    # Traverse the directory and collect the size of all files and
    # directories

    begin
      Dir.foreach(dir) do |f|
        #print " #{f},"
        if(f != "." && f != "..") then
          f_full = addpath(dir, f)
          stat = File.lstat(f_full)

          if(!stat.symlink?) then

            if(stat.file?) then
              #puts "  File: #{f}"
              size = File.size(f_full)
              size_file[f] = size
              size_total += size
            end

            if(stat.directory?) then
              #puts "DIR= #{f}"
              if (@server.max <= 1) then
                puts " no threads."
                size = readdir(f_full)
                if (size > 0) then
                  size_dir[f] = size
                  size_total += size
                end
              else
                ok = @server.increment
                if (ok)
                  puts " Threaded!"
                  @kids << Slave.object(:async => true) {
                    size = readdir(f_full)
                    puts "size = #{size}"
                    # Duh... return the size from the slave properly
                    size
                  }
                else
                  #puts " no free threads, do anyway"
                  size = readdir(f_full)
                  if(size > 0) then
                    size_dir[f] = size
                    size_total += size
                  end
                end
              end
            end
          end
        end
      end
    end

    @kids.each { |kid|
      size_total += kid.value
    }

    #Puts "Dir: #{dir} = #{size_total}"
    return size_total
  end

end

#---------------------------------------------------------------------
# Read a directory and add to the database; this function is recursive
# for sub-directories


#---------------------------------------------------------------------
def usage
  puts
  puts "usage: readdir-drb [--kids NUM] <dir>"
  puts "  defaults to #{$max_kids} children"
  puts
  puts "  version: #{$version}"
  puts
end

#---------------------------------------------------------------------
def addpath(a, b)
  return a + b if(a =~ /\/$/)
  return a + "/" + b
end



#---------------------------------------------------------------------
# Main
#---------------------------------------------------------------------
$DEBUG = true

opts.each do |opt,arg|
  case opt
  when "--kids"
    $max_slaves = arg.to_i
  else
    usage
    exit
  end
end

if ARGV.length != 1
  puts "Missing dir argument (try --help)"
  exit 0
end

dir = ARGV.shift

# Start the DRb service.
puts "Starting DRb on server"
DRb.start_service $URI, Counter.new($max_slaves)

# Child
# Fire up the first slave process which will do the work of readdir()

DRb.start_service
counter = DRbObject.new_with_uri $URI

puts "counter.count=#{counter.count}"

# Fire up a new Kid Class readdir.
kid = ReadDir.new(counter)

# Now let's try to do a recursive readdir() algorith with threads.

size = kid.readdir(dir)

sizekb = size / 1024;
sizemb = sizekb / 1024;
sizegb = sizemb / 1024;

puts ""
puts "Total size: #{size} B"
puts "Total size: #{sizekb} KB"
puts "Total size: #{sizemb} MB"
puts "Total size: #{sizegb} GB"
47b1910084592eb77a032bc7d8d1a84e?d=identicon&s=25 Joel VanderWerf (Guest)
on 2009-02-14 00:53
(Received via mailing list)
John Stoffel wrote:
> drbunix:///tmp/stoffj-test_17986
Probably not helpful, but I thought it was more normal to represent that
file uri as:

drbunix:/tmp/stoffj-test_17986
Db524516a64318b0e937d41357c729eb?d=identicon&s=25 John Stoffel (johnstoffel)
on 2009-02-16 01:24
Joel VanderWerf wrote:
> John Stoffel wrote:
>> drbunix:///tmp/stoffj-test_17986
> Probably not helpful, but I thought it was more normal to represent that
> file uri as:
>
> drbunix:/tmp/stoffj-test_17986

Hmmm, decent idea, but when I use this same URI in simpler,
non-recursive code, it works just fine.  I'll give it a whirl though and
let people know.

I was wondering if maybe I need to do some being rescue end blocks when
I open DRb sockets to catch system errors such as filled /tmp, etc?

Oh well... I'm getting back a consistent answer now, just lots of other
warnings and possible errors from DRb and the Slaves.

Cheers,
John
Db524516a64318b0e937d41357c729eb?d=identicon&s=25 John Stoffel (johnstoffel)
on 2009-02-17 17:27
John Stoffel wrote:
> Joel VanderWerf wrote:
>> John Stoffel wrote:
>>> drbunix:///tmp/stoffj-test_17986
>> Probably not helpful, but I thought it was more normal to represent that
>> file uri as:
>>
>> drbunix:/tmp/stoffj-test_17986
>
> Hmmm, decent idea, but when I use this same URI in simpler,
> non-recursive code, it works just fine.  I'll give it a whirl though and
> let people know.
>
> I was wondering if maybe I need to do some being rescue end blocks when
> I open DRb sockets to catch system errors such as filled /tmp, etc?
>
> Oh well... I'm getting back a consistent answer now, just lots of other
> warnings and possible errors from DRb and the Slaves.
>
> Cheers,
> John

Well, I've got more information now.  It struck me that the errors were
NOT from my DRb code, but from the DRb calls made by the 'slave' module
instead!  So I pulled all my own DRb calls and re-configured my code to
just use 'slave' module I found here:

  http://codeforpeople.com/lib/ruby/slave/

using version 1.2.1 on a CentOS 5.2 system, with ruby 1.8.5 (2006-08-25)
[i386-linux] so I suspect it's possibly my Ruby version is too old, or
the Slave module isn't robust enough.

I guess I'll re-post my code with some new ideas and comments.

Thanks,
John
This topic is locked and can not be replied to.