<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -1,9 +1,16 @@
 CHANGELOG.rdoc
 lib/net/ssh/multi/channel.rb
+lib/net/ssh/multi/channel_proxy.rb
+lib/net/ssh/multi/dynamic_server.rb
+lib/net/ssh/multi/pending_connection.rb
 lib/net/ssh/multi/server.rb
+lib/net/ssh/multi/server_list.rb
 lib/net/ssh/multi/session.rb
+lib/net/ssh/multi/session_actions.rb
+lib/net/ssh/multi/subsession.rb
 lib/net/ssh/multi/version.rb
 lib/net/ssh/multi.rb
+Manifest
 Rakefile
 README.rdoc
 setup.rb
@@ -11,6 +18,7 @@ test/channel_test.rb
 test/common.rb
 test/multi_test.rb
 test/server_test.rb
+test/session_actions_test.rb
 test/session_test.rb
 test/test_all.rb
-Manifest
+x.rb</diff>
      <filename>Manifest</filename>
    </modified>
    <modified>
      <diff>@@ -11,7 +11,9 @@ This library is particularly useful for automating repetitive tasks that must be
 == FEATURES:
 
 * Easily manage multiple connections
-* Open channels, spawn processes, etc. on multiple connections in parallel.
+* Open channels, spawn processes, etc. on multiple connections in parallel
+* Transparently limit concurrent connections when dealing with large numbers of servers (Net::SSH::Multi::Session#concurrent_connections)
+* Specify a default gateway machine through which connections should be tunneled, or even specify a different gateway machine for each server
 
 == SYNOPSIS:
 </diff>
      <filename>README.rdoc</filename>
    </modified>
    <modified>
      <diff>@@ -37,7 +37,7 @@ module Net; module SSH; module Multi
     # Returns the value for the given +key+ in the :properties hash of the
     # +options+. If no :properties hash exists in +options+, this returns +nil+.
     def [](key)
-      (options[:properties] || {})[key]
+      (options[:properties] ||= {})[key]
     end
 
     # Iterates over every instantiated server record in this dynamic server.</diff>
      <filename>lib/net/ssh/multi/dynamic_server.rb</filename>
    </modified>
    <modified>
      <diff>@@ -61,7 +61,7 @@ module Net; module SSH; module Multi
     # properties are described via the +:properties+ key in the options hash
     # when defining the Server.
     def [](key)
-      (options[:properties] || {})[key]
+      (options[:properties] ||= {})[key]
     end
 
     # Returns the port number to use for this connection.</diff>
      <filename>lib/net/ssh/multi/server.rb</filename>
    </modified>
    <modified>
      <diff>@@ -44,6 +44,81 @@ module Net; module SSH; module Multi
   # Note that connections are established lazily, as soon as they are needed.
   # You can force the connections to be opened immediately, though, using the
   # #connect! method.
+  #
+  # == Concurrent Connection Limiting
+  #
+  # Sometimes you may be dealing with a large number of servers, and if you
+  # try to have connections open to all of them simultaneously you'll run into
+  # open file handle limitations and such. If this happens to you, you can set
+  # the #concurrent_connections property of the session. Net::SSH::Multi will
+  # then ensure that no more than this number of connections are ever open
+  # simultaneously.
+  #
+  #   Net::SSH::Multi.start(:concurrent_connections =&gt; 5) do |session|
+  #     # ...
+  #   end
+  #
+  # Opening channels and executing commands will still work exactly as before,
+  # but Net::SSH::Multi will transparently close finished connections and open
+  # pending ones.
+  #
+  # == Controlling Connection Errors
+  #
+  # By default, Net::SSH::Multi will raise an exception if a connection error
+  # occurs when connecting to a server. This will typically bubble up and abort
+  # the entire connection process. Sometimes, however, you might wish to ignore
+  # connection errors, for instance when starting a daemon on a large number of
+  # boxes and you know that some of the boxes are going to be unavailable.
+  #
+  # To do this, simply set the #on_error property of the session to :ignore
+  # (or to :warn, if you want a warning message when a connection attempt
+  # fails):
+  #
+  #   Net::SSH::Multi.start(:on_error =&gt; :ignore) do |session|
+  #     # ...
+  #   end
+  #
+  # The default is :fail, which causes the exception to bubble up. Additionally,
+  # you can specify a Proc object as the value for #on_error, which will be
+  # invoked with the server in question if the connection attempt fails. You
+  # can force the connection attempt to retry by throwing the :go symbol, with
+  # :retry as the payload, or force the exception to be reraised by throwing
+  # :go with :raise as the payload:
+  #
+  #   handler = Proc.new do |server|
+  #     server[:connection_attempts] ||= 0
+  #     if server[:connection_attempts] &lt; 3
+  #       server[:connection_attempts] += 1
+  #       throw :go, :retry
+  #     else
+  #       throw :go, :raise
+  #     end
+  #   end
+  #
+  #   Net::SSH::Multi.start(:on_error =&gt; handler) do |session|
+  #     # ...
+  #   end
+  #
+  # Any other thrown value (or no thrown value at all) will result in the
+  # failure being ignored.
+  #
+  # == Lazily Evaluated Server Definitions
+  #
+  # Sometimes you might be dealing with an environment where you don't know the
+  # names or addresses of the servers until runtime. You can certainly dynamically
+  # build server names and pass them to #use, but if the operation to determine
+  # the server names is expensive, you might want to defer it until the server
+  # is actually needed (especially if the logic of your program is such that
+  # you might not even need to connect to that server every time the program
+  # runs).
+  #
+  # You can do this by passing a block to #use:
+  #
+  #   session.use do |opt|
+  #     lookup_ip_address_of_remote_host
+  #   end
+  #
+  # See #use for more information about this usage.
   class Session
     include SessionActions
 
@@ -189,6 +264,13 @@ module Net; module SSH; module Multi
     # server instances will be returned.
     #
     #   server1, server2 = session.use &quot;host1&quot;, &quot;host2&quot;
+    #
+    # If given a block, this will save the block as a Net::SSH::Multi::DynamicServer
+    # definition, to be evaluated lazily the first time the server is needed.
+    # The block will recive any options hash given to #use, and should return
+    # +nil+ (if no servers are to be added), a String or an array of Strings
+    # (to be interpreted as a connection specification), or a Server or an
+    # array of Servers.
     def use(*hosts, &amp;block)
       options = hosts.last.is_a?(Hash) ? hosts.pop : {}
       options = { :via =&gt; default_gateway }.merge(options)</diff>
      <filename>lib/net/ssh/multi/session.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>b58b29794855c7d70a3488c5bf122172ce2cfb85</id>
    </parent>
  </parents>
  <author>
    <name>Jamis Buck</name>
    <email>jamis@37signals.com</email>
  </author>
  <url>http://github.com/jamis/net-ssh-multi/commit/95429c249bfd39c7016f037242753f45fc0fd55d</url>
  <id>95429c249bfd39c7016f037242753f45fc0fd55d</id>
  <committed-date>2008-04-09T20:13:49-07:00</committed-date>
  <authored-date>2008-04-09T20:13:49-07:00</authored-date>
  <message>update documentation to include lazy server evaluation, concurrent connection limiting, and connection error control. Also updated manifest file</message>
  <tree>69e8913d1c29ec9ad68fc77e098ccccaefdb0a42</tree>
  <committer>
    <name>Jamis Buck</name>
    <email>jamis@37signals.com</email>
  </committer>
</commit>
