jonbell-mongo 1.3.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE.txt +190 -0
 - data/README.md +333 -0
 - data/Rakefile +215 -0
 - data/bin/mongo_console +21 -0
 - data/docs/CREDITS.md +123 -0
 - data/docs/FAQ.md +116 -0
 - data/docs/GridFS.md +158 -0
 - data/docs/HISTORY.md +263 -0
 - data/docs/RELEASES.md +33 -0
 - data/docs/REPLICA_SETS.md +72 -0
 - data/docs/TUTORIAL.md +247 -0
 - data/docs/WRITE_CONCERN.md +28 -0
 - data/lib/mongo.rb +97 -0
 - data/lib/mongo/collection.rb +895 -0
 - data/lib/mongo/connection.rb +926 -0
 - data/lib/mongo/cursor.rb +474 -0
 - data/lib/mongo/db.rb +617 -0
 - data/lib/mongo/exceptions.rb +71 -0
 - data/lib/mongo/gridfs/grid.rb +107 -0
 - data/lib/mongo/gridfs/grid_ext.rb +57 -0
 - data/lib/mongo/gridfs/grid_file_system.rb +146 -0
 - data/lib/mongo/gridfs/grid_io.rb +485 -0
 - data/lib/mongo/gridfs/grid_io_fix.rb +38 -0
 - data/lib/mongo/repl_set_connection.rb +356 -0
 - data/lib/mongo/util/conversions.rb +89 -0
 - data/lib/mongo/util/core_ext.rb +60 -0
 - data/lib/mongo/util/pool.rb +177 -0
 - data/lib/mongo/util/server_version.rb +71 -0
 - data/lib/mongo/util/support.rb +82 -0
 - data/lib/mongo/util/uri_parser.rb +185 -0
 - data/mongo.gemspec +34 -0
 - data/test/auxillary/1.4_features.rb +166 -0
 - data/test/auxillary/authentication_test.rb +68 -0
 - data/test/auxillary/autoreconnect_test.rb +41 -0
 - data/test/auxillary/fork_test.rb +30 -0
 - data/test/auxillary/repl_set_auth_test.rb +58 -0
 - data/test/auxillary/slave_connection_test.rb +36 -0
 - data/test/auxillary/threaded_authentication_test.rb +101 -0
 - data/test/bson/binary_test.rb +15 -0
 - data/test/bson/bson_test.rb +654 -0
 - data/test/bson/byte_buffer_test.rb +208 -0
 - data/test/bson/hash_with_indifferent_access_test.rb +38 -0
 - data/test/bson/json_test.rb +17 -0
 - data/test/bson/object_id_test.rb +154 -0
 - data/test/bson/ordered_hash_test.rb +210 -0
 - data/test/bson/timestamp_test.rb +24 -0
 - data/test/collection_test.rb +910 -0
 - data/test/connection_test.rb +324 -0
 - data/test/conversions_test.rb +119 -0
 - data/test/cursor_fail_test.rb +75 -0
 - data/test/cursor_message_test.rb +43 -0
 - data/test/cursor_test.rb +483 -0
 - data/test/db_api_test.rb +738 -0
 - data/test/db_connection_test.rb +15 -0
 - data/test/db_test.rb +315 -0
 - data/test/grid_file_system_test.rb +259 -0
 - data/test/grid_io_test.rb +209 -0
 - data/test/grid_test.rb +258 -0
 - data/test/load/thin/load.rb +24 -0
 - data/test/load/unicorn/load.rb +23 -0
 - data/test/replica_sets/connect_test.rb +112 -0
 - data/test/replica_sets/connection_string_test.rb +32 -0
 - data/test/replica_sets/count_test.rb +35 -0
 - data/test/replica_sets/insert_test.rb +53 -0
 - data/test/replica_sets/pooled_insert_test.rb +55 -0
 - data/test/replica_sets/query_secondaries.rb +108 -0
 - data/test/replica_sets/query_test.rb +51 -0
 - data/test/replica_sets/replication_ack_test.rb +66 -0
 - data/test/replica_sets/rs_test_helper.rb +27 -0
 - data/test/safe_test.rb +68 -0
 - data/test/support/hash_with_indifferent_access.rb +186 -0
 - data/test/support/keys.rb +45 -0
 - data/test/support_test.rb +18 -0
 - data/test/test_helper.rb +102 -0
 - data/test/threading/threading_with_large_pool_test.rb +90 -0
 - data/test/threading_test.rb +87 -0
 - data/test/tools/auth_repl_set_manager.rb +14 -0
 - data/test/tools/repl_set_manager.rb +266 -0
 - data/test/unit/collection_test.rb +130 -0
 - data/test/unit/connection_test.rb +85 -0
 - data/test/unit/cursor_test.rb +109 -0
 - data/test/unit/db_test.rb +94 -0
 - data/test/unit/grid_test.rb +49 -0
 - data/test/unit/pool_test.rb +9 -0
 - data/test/unit/repl_set_connection_test.rb +59 -0
 - data/test/unit/safe_test.rb +125 -0
 - data/test/uri_test.rb +91 -0
 - metadata +224 -0
 
| 
         @@ -0,0 +1,60 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # encoding: UTF-8
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            # --
         
     | 
| 
      
 4 
     | 
    
         
            +
            # Copyright (C) 2008-2011 10gen Inc.
         
     | 
| 
      
 5 
     | 
    
         
            +
            #
         
     | 
| 
      
 6 
     | 
    
         
            +
            # Licensed under the Apache License, Version 2.0 (the "License");
         
     | 
| 
      
 7 
     | 
    
         
            +
            # you may not use this file except in compliance with the License.
         
     | 
| 
      
 8 
     | 
    
         
            +
            # You may obtain a copy of the License at
         
     | 
| 
      
 9 
     | 
    
         
            +
            #
         
     | 
| 
      
 10 
     | 
    
         
            +
            #     http://www.apache.org/licenses/LICENSE-2.0
         
     | 
| 
      
 11 
     | 
    
         
            +
            #
         
     | 
| 
      
 12 
     | 
    
         
            +
            # Unless required by applicable law or agreed to in writing, software
         
     | 
| 
      
 13 
     | 
    
         
            +
            # distributed under the License is distributed on an "AS IS" BASIS,
         
     | 
| 
      
 14 
     | 
    
         
            +
            # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
         
     | 
| 
      
 15 
     | 
    
         
            +
            # See the License for the specific language governing permissions and
         
     | 
| 
      
 16 
     | 
    
         
            +
            # limitations under the License.
         
     | 
| 
      
 17 
     | 
    
         
            +
            # ++
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            #:nodoc:
         
     | 
| 
      
 20 
     | 
    
         
            +
            class Object
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
              #:nodoc:
         
     | 
| 
      
 23 
     | 
    
         
            +
              def tap
         
     | 
| 
      
 24 
     | 
    
         
            +
                yield self
         
     | 
| 
      
 25 
     | 
    
         
            +
                self
         
     | 
| 
      
 26 
     | 
    
         
            +
              end unless respond_to? :tap
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
            end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
            #:nodoc:
         
     | 
| 
      
 31 
     | 
    
         
            +
            module Enumerable
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
              #:nodoc:
         
     | 
| 
      
 34 
     | 
    
         
            +
              def each_with_object(memo)
         
     | 
| 
      
 35 
     | 
    
         
            +
                each { |element| yield(element, memo) }
         
     | 
| 
      
 36 
     | 
    
         
            +
                memo
         
     | 
| 
      
 37 
     | 
    
         
            +
              end unless [].respond_to?(:each_with_object)
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
            end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
            #:nodoc:
         
     | 
| 
      
 42 
     | 
    
         
            +
            class Hash
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
              #:nodoc:
         
     | 
| 
      
 45 
     | 
    
         
            +
              def assert_valid_keys(*valid_keys)
         
     | 
| 
      
 46 
     | 
    
         
            +
                unknown_keys = keys - [valid_keys].flatten
         
     | 
| 
      
 47 
     | 
    
         
            +
                raise(ArgumentError, "Unknown key(s): #{unknown_keys.join(", ")}") unless unknown_keys.empty?
         
     | 
| 
      
 48 
     | 
    
         
            +
              end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
            end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
            #:nodoc:
         
     | 
| 
      
 53 
     | 
    
         
            +
            class String
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
              #:nodoc:
         
     | 
| 
      
 56 
     | 
    
         
            +
              def to_bson_code
         
     | 
| 
      
 57 
     | 
    
         
            +
                BSON::Code.new(self)
         
     | 
| 
      
 58 
     | 
    
         
            +
              end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,177 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # encoding: UTF-8
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            # --
         
     | 
| 
      
 4 
     | 
    
         
            +
            # Copyright (C) 2008-2011 10gen Inc.
         
     | 
| 
      
 5 
     | 
    
         
            +
            #
         
     | 
| 
      
 6 
     | 
    
         
            +
            # Licensed under the Apache License, Version 2.0 (the "License");
         
     | 
| 
      
 7 
     | 
    
         
            +
            # you may not use this file except in compliance with the License.
         
     | 
| 
      
 8 
     | 
    
         
            +
            # You may obtain a copy of the License at
         
     | 
| 
      
 9 
     | 
    
         
            +
            #
         
     | 
| 
      
 10 
     | 
    
         
            +
            #     http://www.apache.org/licenses/LICENSE-2.0
         
     | 
| 
      
 11 
     | 
    
         
            +
            #
         
     | 
| 
      
 12 
     | 
    
         
            +
            # Unless required by applicable law or agreed to in writing, software
         
     | 
| 
      
 13 
     | 
    
         
            +
            # distributed under the License is distributed on an "AS IS" BASIS,
         
     | 
| 
      
 14 
     | 
    
         
            +
            # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
         
     | 
| 
      
 15 
     | 
    
         
            +
            # See the License for the specific language governing permissions and
         
     | 
| 
      
 16 
     | 
    
         
            +
            # limitations under the License.
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            module Mongo
         
     | 
| 
      
 19 
     | 
    
         
            +
              class Pool
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                attr_accessor :host, :port, :size, :timeout, :safe, :checked_out
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                # Create a new pool of connections.
         
     | 
| 
      
 24 
     | 
    
         
            +
                #
         
     | 
| 
      
 25 
     | 
    
         
            +
                def initialize(connection, host, port, opts={})
         
     | 
| 
      
 26 
     | 
    
         
            +
                  @connection  = connection
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                  @host, @port = host, port
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  # Pool size and timeout.
         
     | 
| 
      
 31 
     | 
    
         
            +
                  @size      = opts[:size] || 1
         
     | 
| 
      
 32 
     | 
    
         
            +
                  @timeout   = opts[:timeout]   || 5.0
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                  # Mutex for synchronizing pool access
         
     | 
| 
      
 35 
     | 
    
         
            +
                  @connection_mutex = Mutex.new
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  # Condition variable for signal and wait
         
     | 
| 
      
 38 
     | 
    
         
            +
                  @queue = ConditionVariable.new
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                  # Operations to perform on a socket
         
     | 
| 
      
 41 
     | 
    
         
            +
                  @socket_ops = Hash.new { |h, k| h[k] = [] }
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                  @sockets      = []
         
     | 
| 
      
 44 
     | 
    
         
            +
                  @pids         = {}
         
     | 
| 
      
 45 
     | 
    
         
            +
                  @checked_out  = []
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                def close
         
     | 
| 
      
 49 
     | 
    
         
            +
                  @sockets.each do |sock|
         
     | 
| 
      
 50 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 51 
     | 
    
         
            +
                      sock.close
         
     | 
| 
      
 52 
     | 
    
         
            +
                    rescue IOError => ex
         
     | 
| 
      
 53 
     | 
    
         
            +
                      warn "IOError when attempting to close socket connected to #{@host}:#{@port}: #{ex.inspect}"
         
     | 
| 
      
 54 
     | 
    
         
            +
                    end
         
     | 
| 
      
 55 
     | 
    
         
            +
                  end
         
     | 
| 
      
 56 
     | 
    
         
            +
                  @host = @port = nil
         
     | 
| 
      
 57 
     | 
    
         
            +
                  @sockets.clear
         
     | 
| 
      
 58 
     | 
    
         
            +
                  @pids.clear
         
     | 
| 
      
 59 
     | 
    
         
            +
                  @checked_out.clear
         
     | 
| 
      
 60 
     | 
    
         
            +
                end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                # Return a socket to the pool.
         
     | 
| 
      
 63 
     | 
    
         
            +
                def checkin(socket)
         
     | 
| 
      
 64 
     | 
    
         
            +
                  @connection_mutex.synchronize do
         
     | 
| 
      
 65 
     | 
    
         
            +
                    @checked_out.delete(socket)
         
     | 
| 
      
 66 
     | 
    
         
            +
                    @queue.signal
         
     | 
| 
      
 67 
     | 
    
         
            +
                  end
         
     | 
| 
      
 68 
     | 
    
         
            +
                  true
         
     | 
| 
      
 69 
     | 
    
         
            +
                end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                # Adds a new socket to the pool and checks it out.
         
     | 
| 
      
 72 
     | 
    
         
            +
                #
         
     | 
| 
      
 73 
     | 
    
         
            +
                # This method is called exclusively from #checkout;
         
     | 
| 
      
 74 
     | 
    
         
            +
                # therefore, it runs within a mutex.
         
     | 
| 
      
 75 
     | 
    
         
            +
                def checkout_new_socket
         
     | 
| 
      
 76 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 77 
     | 
    
         
            +
                  socket = TCPSocket.new(@host, @port)
         
     | 
| 
      
 78 
     | 
    
         
            +
                  socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
         
     | 
| 
      
 79 
     | 
    
         
            +
                  rescue => ex
         
     | 
| 
      
 80 
     | 
    
         
            +
                    raise ConnectionFailure, "Failed to connect to host #{@host} and port #{@port}: #{ex}"
         
     | 
| 
      
 81 
     | 
    
         
            +
                  end
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
                  # If any saved authentications exist, we want to apply those
         
     | 
| 
      
 84 
     | 
    
         
            +
                  # when creating new sockets.
         
     | 
| 
      
 85 
     | 
    
         
            +
                  @connection.apply_saved_authentication(:socket => socket)
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                  @sockets << socket
         
     | 
| 
      
 88 
     | 
    
         
            +
                  @pids[socket] = Process.pid
         
     | 
| 
      
 89 
     | 
    
         
            +
                  @checked_out << socket
         
     | 
| 
      
 90 
     | 
    
         
            +
                  socket
         
     | 
| 
      
 91 
     | 
    
         
            +
                end
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
                # If a user calls DB#authenticate, and several sockets exist,
         
     | 
| 
      
 94 
     | 
    
         
            +
                # then we need a way to apply the authentication on each socket.
         
     | 
| 
      
 95 
     | 
    
         
            +
                # So we store the apply_authentication method, and this will be
         
     | 
| 
      
 96 
     | 
    
         
            +
                # applied right before the next use of each socket.
         
     | 
| 
      
 97 
     | 
    
         
            +
                def authenticate_existing
         
     | 
| 
      
 98 
     | 
    
         
            +
                  @connection_mutex.synchronize do
         
     | 
| 
      
 99 
     | 
    
         
            +
                    @sockets.each do |socket|
         
     | 
| 
      
 100 
     | 
    
         
            +
                      @socket_ops[socket] << Proc.new do
         
     | 
| 
      
 101 
     | 
    
         
            +
                        @connection.apply_saved_authentication(:socket => socket)
         
     | 
| 
      
 102 
     | 
    
         
            +
                      end
         
     | 
| 
      
 103 
     | 
    
         
            +
                    end
         
     | 
| 
      
 104 
     | 
    
         
            +
                  end
         
     | 
| 
      
 105 
     | 
    
         
            +
                end
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
      
 107 
     | 
    
         
            +
                # Store the logout op for each existing socket to be applied before
         
     | 
| 
      
 108 
     | 
    
         
            +
                # the next use of each socket.
         
     | 
| 
      
 109 
     | 
    
         
            +
                def logout_existing(db)
         
     | 
| 
      
 110 
     | 
    
         
            +
                  @connection_mutex.synchronize do
         
     | 
| 
      
 111 
     | 
    
         
            +
                    @sockets.each do |socket|
         
     | 
| 
      
 112 
     | 
    
         
            +
                      @socket_ops[socket] << Proc.new do
         
     | 
| 
      
 113 
     | 
    
         
            +
                        @connection.db(db).issue_logout(:socket => socket)
         
     | 
| 
      
 114 
     | 
    
         
            +
                      end
         
     | 
| 
      
 115 
     | 
    
         
            +
                    end
         
     | 
| 
      
 116 
     | 
    
         
            +
                  end
         
     | 
| 
      
 117 
     | 
    
         
            +
                end
         
     | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
      
 119 
     | 
    
         
            +
                # Checks out the first available socket from the pool.
         
     | 
| 
      
 120 
     | 
    
         
            +
                #
         
     | 
| 
      
 121 
     | 
    
         
            +
                # If the pid has changed, remove the socket and check out
         
     | 
| 
      
 122 
     | 
    
         
            +
                # new one.
         
     | 
| 
      
 123 
     | 
    
         
            +
                #
         
     | 
| 
      
 124 
     | 
    
         
            +
                # This method is called exclusively from #checkout;
         
     | 
| 
      
 125 
     | 
    
         
            +
                # therefore, it runs within a mutex.
         
     | 
| 
      
 126 
     | 
    
         
            +
                def checkout_existing_socket
         
     | 
| 
      
 127 
     | 
    
         
            +
                  socket = (@sockets - @checked_out).first
         
     | 
| 
      
 128 
     | 
    
         
            +
                  if @pids[socket] != Process.pid
         
     | 
| 
      
 129 
     | 
    
         
            +
                     @pids[socket] = nil
         
     | 
| 
      
 130 
     | 
    
         
            +
                     @sockets.delete(socket)
         
     | 
| 
      
 131 
     | 
    
         
            +
                     socket.close
         
     | 
| 
      
 132 
     | 
    
         
            +
                     checkout_new_socket
         
     | 
| 
      
 133 
     | 
    
         
            +
                  else
         
     | 
| 
      
 134 
     | 
    
         
            +
                    @checked_out << socket
         
     | 
| 
      
 135 
     | 
    
         
            +
                    socket
         
     | 
| 
      
 136 
     | 
    
         
            +
                  end
         
     | 
| 
      
 137 
     | 
    
         
            +
                end
         
     | 
| 
      
 138 
     | 
    
         
            +
             
     | 
| 
      
 139 
     | 
    
         
            +
                # Check out an existing socket or create a new socket if the maximum
         
     | 
| 
      
 140 
     | 
    
         
            +
                # pool size has not been exceeded. Otherwise, wait for the next
         
     | 
| 
      
 141 
     | 
    
         
            +
                # available socket.
         
     | 
| 
      
 142 
     | 
    
         
            +
                def checkout
         
     | 
| 
      
 143 
     | 
    
         
            +
                  @connection.connect if !@connection.connected?
         
     | 
| 
      
 144 
     | 
    
         
            +
                  start_time = Time.now
         
     | 
| 
      
 145 
     | 
    
         
            +
                  loop do
         
     | 
| 
      
 146 
     | 
    
         
            +
                    if (Time.now - start_time) > @timeout
         
     | 
| 
      
 147 
     | 
    
         
            +
                        raise ConnectionTimeoutError, "could not obtain connection within " +
         
     | 
| 
      
 148 
     | 
    
         
            +
                          "#{@timeout} seconds. The max pool size is currently #{@size}; " +
         
     | 
| 
      
 149 
     | 
    
         
            +
                          "consider increasing the pool size or timeout."
         
     | 
| 
      
 150 
     | 
    
         
            +
                    end
         
     | 
| 
      
 151 
     | 
    
         
            +
             
     | 
| 
      
 152 
     | 
    
         
            +
                    @connection_mutex.synchronize do
         
     | 
| 
      
 153 
     | 
    
         
            +
                      socket = if @checked_out.size < @sockets.size
         
     | 
| 
      
 154 
     | 
    
         
            +
                                 checkout_existing_socket
         
     | 
| 
      
 155 
     | 
    
         
            +
                               elsif @sockets.size < @size
         
     | 
| 
      
 156 
     | 
    
         
            +
                                 checkout_new_socket
         
     | 
| 
      
 157 
     | 
    
         
            +
                               end
         
     | 
| 
      
 158 
     | 
    
         
            +
             
     | 
| 
      
 159 
     | 
    
         
            +
                      if socket
         
     | 
| 
      
 160 
     | 
    
         
            +
             
     | 
| 
      
 161 
     | 
    
         
            +
                      # This calls all procs, in order, scoped to existing sockets.
         
     | 
| 
      
 162 
     | 
    
         
            +
                      # At the moment, we use this to lazily authenticate and
         
     | 
| 
      
 163 
     | 
    
         
            +
                      # logout existing socket connections.
         
     | 
| 
      
 164 
     | 
    
         
            +
                      @socket_ops[socket].reject! do |op|
         
     | 
| 
      
 165 
     | 
    
         
            +
                        op.call
         
     | 
| 
      
 166 
     | 
    
         
            +
                      end
         
     | 
| 
      
 167 
     | 
    
         
            +
             
     | 
| 
      
 168 
     | 
    
         
            +
                        return socket
         
     | 
| 
      
 169 
     | 
    
         
            +
                      else
         
     | 
| 
      
 170 
     | 
    
         
            +
                        # Otherwise, wait
         
     | 
| 
      
 171 
     | 
    
         
            +
                        @queue.wait(@connection_mutex)
         
     | 
| 
      
 172 
     | 
    
         
            +
                      end
         
     | 
| 
      
 173 
     | 
    
         
            +
                    end
         
     | 
| 
      
 174 
     | 
    
         
            +
                  end
         
     | 
| 
      
 175 
     | 
    
         
            +
                end
         
     | 
| 
      
 176 
     | 
    
         
            +
              end
         
     | 
| 
      
 177 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,71 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # encoding: UTF-8
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            # --
         
     | 
| 
      
 4 
     | 
    
         
            +
            # Copyright (C) 2008-2011 10gen Inc.
         
     | 
| 
      
 5 
     | 
    
         
            +
            #
         
     | 
| 
      
 6 
     | 
    
         
            +
            # Licensed under the Apache License, Version 2.0 (the "License");
         
     | 
| 
      
 7 
     | 
    
         
            +
            # you may not use this file except in compliance with the License.
         
     | 
| 
      
 8 
     | 
    
         
            +
            # You may obtain a copy of the License at
         
     | 
| 
      
 9 
     | 
    
         
            +
            #
         
     | 
| 
      
 10 
     | 
    
         
            +
            #     http://www.apache.org/licenses/LICENSE-2.0
         
     | 
| 
      
 11 
     | 
    
         
            +
            #
         
     | 
| 
      
 12 
     | 
    
         
            +
            # Unless required by applicable law or agreed to in writing, software
         
     | 
| 
      
 13 
     | 
    
         
            +
            # distributed under the License is distributed on an "AS IS" BASIS,
         
     | 
| 
      
 14 
     | 
    
         
            +
            # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
         
     | 
| 
      
 15 
     | 
    
         
            +
            # See the License for the specific language governing permissions and
         
     | 
| 
      
 16 
     | 
    
         
            +
            # limitations under the License.
         
     | 
| 
      
 17 
     | 
    
         
            +
            # ++
         
     | 
| 
      
 18 
     | 
    
         
            +
            module Mongo
         
     | 
| 
      
 19 
     | 
    
         
            +
              # Simple class for comparing server versions.
         
     | 
| 
      
 20 
     | 
    
         
            +
              class ServerVersion
         
     | 
| 
      
 21 
     | 
    
         
            +
                include Comparable
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                def initialize(version)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  @version = version
         
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                # Implements comparable.
         
     | 
| 
      
 28 
     | 
    
         
            +
                def <=>(new)
         
     | 
| 
      
 29 
     | 
    
         
            +
                  local, new  = self.to_a, to_array(new)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  for n in 0...local.size do
         
     | 
| 
      
 31 
     | 
    
         
            +
                    break if elements_include_mods?(local[n], new[n])
         
     | 
| 
      
 32 
     | 
    
         
            +
                    if local[n] < new[n].to_i
         
     | 
| 
      
 33 
     | 
    
         
            +
                      result = -1
         
     | 
| 
      
 34 
     | 
    
         
            +
                      break;
         
     | 
| 
      
 35 
     | 
    
         
            +
                    elsif local[n] > new[n].to_i
         
     | 
| 
      
 36 
     | 
    
         
            +
                      result = 1
         
     | 
| 
      
 37 
     | 
    
         
            +
                      break;
         
     | 
| 
      
 38 
     | 
    
         
            +
                    end
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
                  result || 0
         
     | 
| 
      
 41 
     | 
    
         
            +
                end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                # Return an array representation of this server version.
         
     | 
| 
      
 44 
     | 
    
         
            +
                def to_a
         
     | 
| 
      
 45 
     | 
    
         
            +
                  to_array(@version)
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                # Return a string representation of this server version.
         
     | 
| 
      
 49 
     | 
    
         
            +
                def to_s
         
     | 
| 
      
 50 
     | 
    
         
            +
                  @version
         
     | 
| 
      
 51 
     | 
    
         
            +
                end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                private
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                # Returns true if any elements include mod symbols (-, +)
         
     | 
| 
      
 56 
     | 
    
         
            +
                def elements_include_mods?(*elements)
         
     | 
| 
      
 57 
     | 
    
         
            +
                  elements.any? { |n| n =~ /[\-\+]/ }
         
     | 
| 
      
 58 
     | 
    
         
            +
                end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                # Converts argument to an array of integers,
         
     | 
| 
      
 61 
     | 
    
         
            +
                # appending any mods as the final element.
         
     | 
| 
      
 62 
     | 
    
         
            +
                def to_array(version)
         
     | 
| 
      
 63 
     | 
    
         
            +
                  array = version.split(".").map {|n| (n =~ /^\d+$/) ? n.to_i : n }
         
     | 
| 
      
 64 
     | 
    
         
            +
                  if array.last =~ /(\d+)([\-\+])/
         
     | 
| 
      
 65 
     | 
    
         
            +
                    array[array.length-1] = $1.to_i
         
     | 
| 
      
 66 
     | 
    
         
            +
                    array << $2
         
     | 
| 
      
 67 
     | 
    
         
            +
                  end
         
     | 
| 
      
 68 
     | 
    
         
            +
                  array
         
     | 
| 
      
 69 
     | 
    
         
            +
                end
         
     | 
| 
      
 70 
     | 
    
         
            +
              end
         
     | 
| 
      
 71 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,82 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # encoding: UTF-8
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            # --
         
     | 
| 
      
 4 
     | 
    
         
            +
            # Copyright (C) 2008-2011 10gen Inc.
         
     | 
| 
      
 5 
     | 
    
         
            +
            #
         
     | 
| 
      
 6 
     | 
    
         
            +
            # Licensed under the Apache License, Version 2.0 (the "License");
         
     | 
| 
      
 7 
     | 
    
         
            +
            # you may not use this file except in compliance with the License.
         
     | 
| 
      
 8 
     | 
    
         
            +
            # You may obtain a copy of the License at
         
     | 
| 
      
 9 
     | 
    
         
            +
            #
         
     | 
| 
      
 10 
     | 
    
         
            +
            #     http://www.apache.org/licenses/LICENSE-2.0
         
     | 
| 
      
 11 
     | 
    
         
            +
            #
         
     | 
| 
      
 12 
     | 
    
         
            +
            # Unless required by applicable law or agreed to in writing, software
         
     | 
| 
      
 13 
     | 
    
         
            +
            # distributed under the License is distributed on an "AS IS" BASIS,
         
     | 
| 
      
 14 
     | 
    
         
            +
            # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
         
     | 
| 
      
 15 
     | 
    
         
            +
            # See the License for the specific language governing permissions and
         
     | 
| 
      
 16 
     | 
    
         
            +
            # limitations under the License.
         
     | 
| 
      
 17 
     | 
    
         
            +
            # ++
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            require 'digest/md5'
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
            module Mongo
         
     | 
| 
      
 22 
     | 
    
         
            +
              module Support
         
     | 
| 
      
 23 
     | 
    
         
            +
                include Mongo::Conversions
         
     | 
| 
      
 24 
     | 
    
         
            +
                extend self
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                # Generate an MD5 for authentication.
         
     | 
| 
      
 27 
     | 
    
         
            +
                #
         
     | 
| 
      
 28 
     | 
    
         
            +
                # @param [String] username
         
     | 
| 
      
 29 
     | 
    
         
            +
                # @param [String] password
         
     | 
| 
      
 30 
     | 
    
         
            +
                # @param [String] nonce
         
     | 
| 
      
 31 
     | 
    
         
            +
                #
         
     | 
| 
      
 32 
     | 
    
         
            +
                # @return [String] a key for db authentication.
         
     | 
| 
      
 33 
     | 
    
         
            +
                def auth_key(username, password, nonce)
         
     | 
| 
      
 34 
     | 
    
         
            +
                  Digest::MD5.hexdigest("#{nonce}#{username}#{hash_password(username, password)}")
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                # Return a hashed password for auth.
         
     | 
| 
      
 38 
     | 
    
         
            +
                #
         
     | 
| 
      
 39 
     | 
    
         
            +
                # @param [String] username
         
     | 
| 
      
 40 
     | 
    
         
            +
                # @param [String] plaintext
         
     | 
| 
      
 41 
     | 
    
         
            +
                #
         
     | 
| 
      
 42 
     | 
    
         
            +
                # @return [String]
         
     | 
| 
      
 43 
     | 
    
         
            +
                def hash_password(username, plaintext)
         
     | 
| 
      
 44 
     | 
    
         
            +
                  Digest::MD5.hexdigest("#{username}:mongo:#{plaintext}")
         
     | 
| 
      
 45 
     | 
    
         
            +
                end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                def validate_db_name(db_name)
         
     | 
| 
      
 49 
     | 
    
         
            +
                  unless [String, Symbol].include?(db_name.class)
         
     | 
| 
      
 50 
     | 
    
         
            +
                    raise TypeError, "db_name must be a string or symbol"
         
     | 
| 
      
 51 
     | 
    
         
            +
                  end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                  [" ", ".", "$", "/", "\\"].each do |invalid_char|
         
     | 
| 
      
 54 
     | 
    
         
            +
                    if db_name.include? invalid_char
         
     | 
| 
      
 55 
     | 
    
         
            +
                      raise Mongo::InvalidNSName, "database names cannot contain the character '#{invalid_char}'"
         
     | 
| 
      
 56 
     | 
    
         
            +
                    end
         
     | 
| 
      
 57 
     | 
    
         
            +
                  end
         
     | 
| 
      
 58 
     | 
    
         
            +
                  raise Mongo::InvalidNSName, "database name cannot be the empty string" if db_name.empty?
         
     | 
| 
      
 59 
     | 
    
         
            +
                  db_name
         
     | 
| 
      
 60 
     | 
    
         
            +
                end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                def format_order_clause(order)
         
     | 
| 
      
 63 
     | 
    
         
            +
                  case order
         
     | 
| 
      
 64 
     | 
    
         
            +
                    when String, Symbol then string_as_sort_parameters(order)
         
     | 
| 
      
 65 
     | 
    
         
            +
                    when Array then array_as_sort_parameters(order)
         
     | 
| 
      
 66 
     | 
    
         
            +
                    else
         
     | 
| 
      
 67 
     | 
    
         
            +
                      raise InvalidSortValueError, "Illegal sort clause, '#{order.class.name}'; must be of the form " +
         
     | 
| 
      
 68 
     | 
    
         
            +
                        "[['field1', '(ascending|descending)'], ['field2', '(ascending|descending)']]"
         
     | 
| 
      
 69 
     | 
    
         
            +
                  end
         
     | 
| 
      
 70 
     | 
    
         
            +
                end
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                # Determine if a database command has succeeded by
         
     | 
| 
      
 73 
     | 
    
         
            +
                # checking the document response.
         
     | 
| 
      
 74 
     | 
    
         
            +
                #
         
     | 
| 
      
 75 
     | 
    
         
            +
                # @param [Hash] doc
         
     | 
| 
      
 76 
     | 
    
         
            +
                #
         
     | 
| 
      
 77 
     | 
    
         
            +
                # @return [Boolean] true if the 'ok' key is either 1 or *true*.
         
     | 
| 
      
 78 
     | 
    
         
            +
                def ok?(doc)
         
     | 
| 
      
 79 
     | 
    
         
            +
                  doc['ok'] == 1.0 || doc['ok'] == true
         
     | 
| 
      
 80 
     | 
    
         
            +
                end
         
     | 
| 
      
 81 
     | 
    
         
            +
              end
         
     | 
| 
      
 82 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,185 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # encoding: UTF-8
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            # --
         
     | 
| 
      
 4 
     | 
    
         
            +
            # Copyright (C) 2008-2011 10gen Inc.
         
     | 
| 
      
 5 
     | 
    
         
            +
            #
         
     | 
| 
      
 6 
     | 
    
         
            +
            # Licensed under the Apache License, Version 2.0 (the "License");
         
     | 
| 
      
 7 
     | 
    
         
            +
            # you may not use this file except in compliance with the License.
         
     | 
| 
      
 8 
     | 
    
         
            +
            # You may obtain a copy of the License at
         
     | 
| 
      
 9 
     | 
    
         
            +
            #
         
     | 
| 
      
 10 
     | 
    
         
            +
            #     http://www.apache.org/licenses/LICENSE-2.0
         
     | 
| 
      
 11 
     | 
    
         
            +
            #
         
     | 
| 
      
 12 
     | 
    
         
            +
            # Unless required by applicable law or agreed to in writing, software
         
     | 
| 
      
 13 
     | 
    
         
            +
            # distributed under the License is distributed on an "AS IS" BASIS,
         
     | 
| 
      
 14 
     | 
    
         
            +
            # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
         
     | 
| 
      
 15 
     | 
    
         
            +
            # See the License for the specific language governing permissions and
         
     | 
| 
      
 16 
     | 
    
         
            +
            # limitations under the License.
         
     | 
| 
      
 17 
     | 
    
         
            +
            # ++
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            module Mongo
         
     | 
| 
      
 20 
     | 
    
         
            +
              class URIParser
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                DEFAULT_PORT = 27017
         
     | 
| 
      
 23 
     | 
    
         
            +
                MONGODB_URI_MATCHER = /(([-.\w]+):([^@]+)@)?([-.\w]+)(:([\w]+))?(\/([-\w]+))?/
         
     | 
| 
      
 24 
     | 
    
         
            +
                MONGODB_URI_SPEC = "mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/database]"
         
     | 
| 
      
 25 
     | 
    
         
            +
                SPEC_ATTRS = [:nodes, :auths]
         
     | 
| 
      
 26 
     | 
    
         
            +
                OPT_ATTRS  = [:connect, :replicaset, :slaveok, :safe, :w, :wtimeout, :fsync]
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                OPT_VALID  = {:connect    => lambda {|arg| ['direct', 'replicaset'].include?(arg)},
         
     | 
| 
      
 29 
     | 
    
         
            +
                              :replicaset => lambda {|arg| arg.length > 0},
         
     | 
| 
      
 30 
     | 
    
         
            +
                              :slaveok    => lambda {|arg| ['true', 'false'].include?(arg)},
         
     | 
| 
      
 31 
     | 
    
         
            +
                              :safe       => lambda {|arg| ['true', 'false'].include?(arg)},
         
     | 
| 
      
 32 
     | 
    
         
            +
                              :w          => lambda {|arg| arg =~ /^\d+$/ },
         
     | 
| 
      
 33 
     | 
    
         
            +
                              :wtimeout   => lambda {|arg| arg =~ /^\d+$/ },
         
     | 
| 
      
 34 
     | 
    
         
            +
                              :fsync      => lambda {|arg| ['true', 'false'].include?(arg)}
         
     | 
| 
      
 35 
     | 
    
         
            +
                             }
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                OPT_ERR    = {:connect    => "must be 'direct' or 'replicaset'",
         
     | 
| 
      
 38 
     | 
    
         
            +
                              :replicaset => "must be a string containing the name of the replica set to connect to",
         
     | 
| 
      
 39 
     | 
    
         
            +
                              :slaveok    => "must be 'true' or 'false'",
         
     | 
| 
      
 40 
     | 
    
         
            +
                              :safe       => "must be 'true' or 'false'",
         
     | 
| 
      
 41 
     | 
    
         
            +
                              :w          => "must be an integer specifying number of nodes to replica to",
         
     | 
| 
      
 42 
     | 
    
         
            +
                              :wtimeout   => "must be an integer specifying milliseconds",
         
     | 
| 
      
 43 
     | 
    
         
            +
                              :fsync      => "must be 'true' or 'false'"
         
     | 
| 
      
 44 
     | 
    
         
            +
                             }
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                OPT_CONV   = {:connect    => lambda {|arg| arg},
         
     | 
| 
      
 47 
     | 
    
         
            +
                              :replicaset => lambda {|arg| arg},
         
     | 
| 
      
 48 
     | 
    
         
            +
                              :slaveok    => lambda {|arg| arg == 'true' ? true : false},
         
     | 
| 
      
 49 
     | 
    
         
            +
                              :safe       => lambda {|arg| arg == 'true' ? true : false},
         
     | 
| 
      
 50 
     | 
    
         
            +
                              :w          => lambda {|arg| arg.to_i},
         
     | 
| 
      
 51 
     | 
    
         
            +
                              :wtimeout   => lambda {|arg| arg.to_i},
         
     | 
| 
      
 52 
     | 
    
         
            +
                              :fsync      => lambda {|arg| arg == 'true' ? true : false}
         
     | 
| 
      
 53 
     | 
    
         
            +
                             }
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                attr_reader :nodes, :auths, :connect, :replicaset, :slaveok, :safe, :w, :wtimeout, :fsync
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                # Parse a MongoDB URI. This method is used by Connection.from_uri.
         
     | 
| 
      
 58 
     | 
    
         
            +
                # Returns an array of nodes and an array of db authorizations, if applicable.
         
     | 
| 
      
 59 
     | 
    
         
            +
                #
         
     | 
| 
      
 60 
     | 
    
         
            +
                # Note: passwords can contain any character except for a ','.
         
     | 
| 
      
 61 
     | 
    
         
            +
                #
         
     | 
| 
      
 62 
     | 
    
         
            +
                # @core connections
         
     | 
| 
      
 63 
     | 
    
         
            +
                def initialize(string)
         
     | 
| 
      
 64 
     | 
    
         
            +
                  if string =~ /^mongodb:\/\//
         
     | 
| 
      
 65 
     | 
    
         
            +
                    string = string[10..-1]
         
     | 
| 
      
 66 
     | 
    
         
            +
                  else
         
     | 
| 
      
 67 
     | 
    
         
            +
                    raise MongoArgumentError, "MongoDB URI must match this spec: #{MONGODB_URI_SPEC}"
         
     | 
| 
      
 68 
     | 
    
         
            +
                  end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                  hosts, opts = string.split('?')
         
     | 
| 
      
 71 
     | 
    
         
            +
                  parse_hosts(hosts)
         
     | 
| 
      
 72 
     | 
    
         
            +
                  parse_options(opts)
         
     | 
| 
      
 73 
     | 
    
         
            +
                  configure_connect
         
     | 
| 
      
 74 
     | 
    
         
            +
                end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                def connection_options
         
     | 
| 
      
 77 
     | 
    
         
            +
                  opts = {}
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                  if (@w || @wtimeout || @fsync) && !@safe
         
     | 
| 
      
 80 
     | 
    
         
            +
                    raise MongoArgumentError, "Safe must be true if w, wtimeout, or fsync is specified"
         
     | 
| 
      
 81 
     | 
    
         
            +
                  end
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
                  if @safe
         
     | 
| 
      
 84 
     | 
    
         
            +
                    if @w || @wtimeout || @fsync
         
     | 
| 
      
 85 
     | 
    
         
            +
                      safe_opts = {}
         
     | 
| 
      
 86 
     | 
    
         
            +
                      safe_opts[:w] = @w if @w
         
     | 
| 
      
 87 
     | 
    
         
            +
                      safe_opts[:wtimeout] = @wtimeout if @wtimeout
         
     | 
| 
      
 88 
     | 
    
         
            +
                      safe_opts[:fsync] = @fsync if @fsync
         
     | 
| 
      
 89 
     | 
    
         
            +
                    else
         
     | 
| 
      
 90 
     | 
    
         
            +
                      safe_opts = true
         
     | 
| 
      
 91 
     | 
    
         
            +
                    end
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
                    opts[:safe] = safe_opts
         
     | 
| 
      
 94 
     | 
    
         
            +
                  end
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
                  if @slaveok
         
     | 
| 
      
 97 
     | 
    
         
            +
                    if @connect == 'direct'
         
     | 
| 
      
 98 
     | 
    
         
            +
                      opts[:slave_ok] = true
         
     | 
| 
      
 99 
     | 
    
         
            +
                    else
         
     | 
| 
      
 100 
     | 
    
         
            +
                      opts[:read_secondary] = true
         
     | 
| 
      
 101 
     | 
    
         
            +
                    end
         
     | 
| 
      
 102 
     | 
    
         
            +
                  end
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
                  opts[:rs_name] = @replicaset if @replicaset
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
                  opts
         
     | 
| 
      
 107 
     | 
    
         
            +
                end
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
                private
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
                def parse_hosts(hosts)
         
     | 
| 
      
 112 
     | 
    
         
            +
                  @nodes = []
         
     | 
| 
      
 113 
     | 
    
         
            +
                  @auths = []
         
     | 
| 
      
 114 
     | 
    
         
            +
                  specs = hosts.split(',')
         
     | 
| 
      
 115 
     | 
    
         
            +
                  specs.each do |spec|
         
     | 
| 
      
 116 
     | 
    
         
            +
                    matches  = MONGODB_URI_MATCHER.match(spec)
         
     | 
| 
      
 117 
     | 
    
         
            +
                    if !matches
         
     | 
| 
      
 118 
     | 
    
         
            +
                      raise MongoArgumentError, "MongoDB URI must match this spec: #{MONGODB_URI_SPEC}"
         
     | 
| 
      
 119 
     | 
    
         
            +
                    end
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
                    uname = matches[2]
         
     | 
| 
      
 122 
     | 
    
         
            +
                    pwd   = matches[3]
         
     | 
| 
      
 123 
     | 
    
         
            +
                    host  = matches[4]
         
     | 
| 
      
 124 
     | 
    
         
            +
                    port  = matches[6] || DEFAULT_PORT
         
     | 
| 
      
 125 
     | 
    
         
            +
                    if !(port.to_s =~ /^\d+$/)
         
     | 
| 
      
 126 
     | 
    
         
            +
                      raise MongoArgumentError, "Invalid port #{port}; port must be specified as digits."
         
     | 
| 
      
 127 
     | 
    
         
            +
                    end
         
     | 
| 
      
 128 
     | 
    
         
            +
                    port    = port.to_i
         
     | 
| 
      
 129 
     | 
    
         
            +
                    db      = matches[8]
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
                    if uname && pwd && db
         
     | 
| 
      
 132 
     | 
    
         
            +
                      auths << {'db_name' => db, 'username' => uname, 'password' => pwd}
         
     | 
| 
      
 133 
     | 
    
         
            +
                    elsif uname || pwd || db
         
     | 
| 
      
 134 
     | 
    
         
            +
                      raise MongoArgumentError, "MongoDB URI must include all three of username, password, " +
         
     | 
| 
      
 135 
     | 
    
         
            +
                        "and db if any one of these is specified."
         
     | 
| 
      
 136 
     | 
    
         
            +
                    end
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
      
 138 
     | 
    
         
            +
                    @nodes << [host, port]
         
     | 
| 
      
 139 
     | 
    
         
            +
                  end
         
     | 
| 
      
 140 
     | 
    
         
            +
                end
         
     | 
| 
      
 141 
     | 
    
         
            +
             
     | 
| 
      
 142 
     | 
    
         
            +
                # This method uses the lambdas defined in OPT_VALID and OPT_CONV to validate
         
     | 
| 
      
 143 
     | 
    
         
            +
                # and convert the given options.
         
     | 
| 
      
 144 
     | 
    
         
            +
                def parse_options(opts)
         
     | 
| 
      
 145 
     | 
    
         
            +
                  # initialize instance variables for available options
         
     | 
| 
      
 146 
     | 
    
         
            +
                  OPT_VALID.keys.each { |k| instance_variable_set("@#{k}", nil) }
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
      
 148 
     | 
    
         
            +
                  return unless opts
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
                  separator = opts.include?('&') ? '&' : ';'
         
     | 
| 
      
 151 
     | 
    
         
            +
                  opts.split(separator).each do |attr|
         
     | 
| 
      
 152 
     | 
    
         
            +
                    key, value = attr.split('=')
         
     | 
| 
      
 153 
     | 
    
         
            +
                    key   = key.to_sym
         
     | 
| 
      
 154 
     | 
    
         
            +
                    value = value.strip.downcase
         
     | 
| 
      
 155 
     | 
    
         
            +
                    if !OPT_ATTRS.include?(key)
         
     | 
| 
      
 156 
     | 
    
         
            +
                      raise MongoArgumentError, "Invalid Mongo URI option #{key}"
         
     | 
| 
      
 157 
     | 
    
         
            +
                    end
         
     | 
| 
      
 158 
     | 
    
         
            +
             
     | 
| 
      
 159 
     | 
    
         
            +
                    if OPT_VALID[key].call(value)
         
     | 
| 
      
 160 
     | 
    
         
            +
                      instance_variable_set("@#{key}", OPT_CONV[key].call(value))
         
     | 
| 
      
 161 
     | 
    
         
            +
                    else
         
     | 
| 
      
 162 
     | 
    
         
            +
                      raise MongoArgumentError, "Invalid value for #{key}: #{OPT_ERR[key]}"
         
     | 
| 
      
 163 
     | 
    
         
            +
                    end
         
     | 
| 
      
 164 
     | 
    
         
            +
                  end
         
     | 
| 
      
 165 
     | 
    
         
            +
                end
         
     | 
| 
      
 166 
     | 
    
         
            +
             
     | 
| 
      
 167 
     | 
    
         
            +
                def configure_connect
         
     | 
| 
      
 168 
     | 
    
         
            +
                  if @nodes.length > 1 && !@connect
         
     | 
| 
      
 169 
     | 
    
         
            +
                    @connect = 'replicaset'
         
     | 
| 
      
 170 
     | 
    
         
            +
                  end
         
     | 
| 
      
 171 
     | 
    
         
            +
             
     | 
| 
      
 172 
     | 
    
         
            +
                  if !@connect
         
     | 
| 
      
 173 
     | 
    
         
            +
                    if @nodes.length > 1
         
     | 
| 
      
 174 
     | 
    
         
            +
                      @connect = 'replicaset'
         
     | 
| 
      
 175 
     | 
    
         
            +
                    else
         
     | 
| 
      
 176 
     | 
    
         
            +
                      @connect = 'direct'
         
     | 
| 
      
 177 
     | 
    
         
            +
                    end
         
     | 
| 
      
 178 
     | 
    
         
            +
                  end
         
     | 
| 
      
 179 
     | 
    
         
            +
             
     | 
| 
      
 180 
     | 
    
         
            +
                  if @connect == 'direct' && @replicaset
         
     | 
| 
      
 181 
     | 
    
         
            +
                    raise MongoArgumentError, "If specifying a replica set name, please also specify that connect=replicaset"
         
     | 
| 
      
 182 
     | 
    
         
            +
                  end
         
     | 
| 
      
 183 
     | 
    
         
            +
                end
         
     | 
| 
      
 184 
     | 
    
         
            +
              end
         
     | 
| 
      
 185 
     | 
    
         
            +
            end
         
     |