mongo 1.9.2 → 1.10.0.rc0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/LICENSE +1 -1
- data/README.md +94 -334
- data/Rakefile +6 -4
- data/VERSION +1 -1
- data/bin/mongo_console +13 -6
- data/lib/mongo.rb +22 -27
- data/lib/mongo/bulk_write_collection_view.rb +352 -0
- data/lib/mongo/collection.rb +128 -188
- data/lib/mongo/collection_writer.rb +348 -0
- data/lib/mongo/connection.rb +19 -0
- data/lib/mongo/{util → connection}/node.rb +15 -1
- data/lib/mongo/{util → connection}/pool.rb +34 -19
- data/lib/mongo/{util → connection}/pool_manager.rb +8 -2
- data/lib/mongo/{util → connection}/sharding_pool_manager.rb +1 -1
- data/lib/mongo/connection/socket.rb +18 -0
- data/lib/mongo/{util → connection/socket}/socket_util.rb +5 -2
- data/lib/mongo/{util → connection/socket}/ssl_socket.rb +3 -4
- data/lib/mongo/{util → connection/socket}/tcp_socket.rb +25 -15
- data/lib/mongo/{util → connection/socket}/unix_socket.rb +6 -4
- data/lib/mongo/cursor.rb +113 -47
- data/lib/mongo/db.rb +203 -131
- data/lib/mongo/{exceptions.rb → exception.rb} +7 -1
- data/lib/mongo/functional.rb +19 -0
- data/lib/mongo/functional/authentication.rb +303 -0
- data/lib/mongo/{util → functional}/logging.rb +1 -1
- data/lib/mongo/{util → functional}/read_preference.rb +49 -1
- data/lib/mongo/{util → functional}/uri_parser.rb +81 -69
- data/lib/mongo/{util → functional}/write_concern.rb +2 -1
- data/{test/unit/pool_test.rb → lib/mongo/gridfs.rb} +5 -10
- data/lib/mongo/gridfs/grid.rb +1 -3
- data/lib/mongo/gridfs/grid_ext.rb +1 -1
- data/lib/mongo/gridfs/grid_file_system.rb +1 -1
- data/lib/mongo/gridfs/grid_io.rb +1 -1
- data/lib/mongo/legacy.rb +63 -8
- data/lib/mongo/mongo_client.rb +128 -154
- data/lib/mongo/mongo_replica_set_client.rb +17 -11
- data/lib/mongo/mongo_sharded_client.rb +2 -1
- data/lib/mongo/networking.rb +19 -10
- data/lib/mongo/utils.rb +19 -0
- data/lib/mongo/{util → utils}/conversions.rb +1 -1
- data/lib/mongo/{util → utils}/core_ext.rb +1 -1
- data/lib/mongo/{util → utils}/server_version.rb +1 -1
- data/lib/mongo/{util → utils}/support.rb +10 -57
- data/lib/mongo/{util → utils}/thread_local_variable_manager.rb +1 -1
- data/test/functional/authentication_test.rb +8 -21
- data/test/functional/bulk_write_collection_view_test.rb +782 -0
- data/test/functional/{connection_test.rb → client_test.rb} +153 -78
- data/test/functional/collection_test.rb +343 -97
- data/test/functional/collection_writer_test.rb +83 -0
- data/test/functional/conversions_test.rb +1 -3
- data/test/functional/cursor_fail_test.rb +3 -3
- data/test/functional/cursor_message_test.rb +3 -3
- data/test/functional/cursor_test.rb +38 -3
- data/test/functional/db_api_test.rb +5 -5
- data/test/functional/db_connection_test.rb +2 -2
- data/test/functional/db_test.rb +35 -11
- data/test/functional/grid_file_system_test.rb +2 -2
- data/test/functional/grid_io_test.rb +2 -2
- data/test/functional/grid_test.rb +2 -2
- data/test/functional/pool_test.rb +2 -3
- data/test/functional/safe_test.rb +5 -5
- data/test/functional/ssl_test.rb +22 -102
- data/test/functional/support_test.rb +1 -1
- data/test/functional/timeout_test.rb +6 -22
- data/test/functional/uri_test.rb +113 -12
- data/test/functional/write_concern_test.rb +6 -6
- data/test/helpers/general.rb +50 -0
- data/test/helpers/test_unit.rb +309 -0
- data/test/replica_set/authentication_test.rb +8 -23
- data/test/replica_set/basic_test.rb +41 -14
- data/test/replica_set/client_test.rb +179 -117
- data/test/replica_set/complex_connect_test.rb +6 -7
- data/test/replica_set/connection_test.rb +46 -38
- data/test/replica_set/count_test.rb +2 -2
- data/test/replica_set/cursor_test.rb +8 -8
- data/test/replica_set/insert_test.rb +64 -2
- data/test/replica_set/max_values_test.rb +59 -10
- data/test/replica_set/pinning_test.rb +2 -2
- data/test/replica_set/query_test.rb +2 -2
- data/test/replica_set/read_preference_test.rb +6 -6
- data/test/replica_set/refresh_test.rb +7 -7
- data/test/replica_set/replication_ack_test.rb +5 -5
- data/test/replica_set/ssl_test.rb +24 -106
- data/test/sharded_cluster/basic_test.rb +43 -15
- data/test/shared/authentication/basic_auth_shared.rb +215 -0
- data/test/shared/authentication/sasl_plain_shared.rb +96 -0
- data/test/shared/ssl_shared.rb +173 -0
- data/test/test_helper.rb +31 -199
- data/test/threading/basic_test.rb +29 -3
- data/test/tools/mongo_config.rb +45 -20
- data/test/tools/mongo_config_test.rb +1 -1
- data/test/unit/client_test.rb +136 -57
- data/test/unit/collection_test.rb +31 -55
- data/test/unit/connection_test.rb +135 -72
- data/test/unit/cursor_test.rb +2 -2
- data/test/unit/db_test.rb +19 -15
- data/test/unit/grid_test.rb +2 -2
- data/test/unit/mongo_sharded_client_test.rb +17 -15
- data/test/unit/node_test.rb +2 -2
- data/test/unit/pool_manager_test.rb +7 -5
- data/test/unit/read_pref_test.rb +82 -2
- data/test/unit/read_test.rb +14 -14
- data/test/unit/safe_test.rb +9 -9
- data/test/unit/sharding_pool_manager_test.rb +11 -5
- data/test/unit/write_concern_test.rb +9 -9
- metadata +71 -56
- metadata.gz.sig +0 -0
- data/test/functional/threading_test.rb +0 -109
- data/test/shared/authentication.rb +0 -121
- data/test/unit/util_test.rb +0 -69
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2013
|
1
|
+
# Copyright (C) 2009-2013 MongoDB, Inc.
|
2
2
|
#
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
4
|
# you may not use this file except in compliance with the License.
|
@@ -26,7 +26,9 @@ module Mongo
|
|
26
26
|
:seeds,
|
27
27
|
:pools,
|
28
28
|
:max_bson_size,
|
29
|
-
:max_message_size
|
29
|
+
:max_message_size,
|
30
|
+
:max_wire_version,
|
31
|
+
:min_wire_version
|
30
32
|
|
31
33
|
# Create a new set of connection pools.
|
32
34
|
#
|
@@ -49,6 +51,8 @@ module Mongo
|
|
49
51
|
@refresh_required = false
|
50
52
|
@max_bson_size = DEFAULT_MAX_BSON_SIZE
|
51
53
|
@max_message_size = @max_bson_size * MESSAGE_SIZE_FACTOR
|
54
|
+
@max_wire_version = 0
|
55
|
+
@min_wire_version = 0
|
52
56
|
@connect_mutex = Mutex.new
|
53
57
|
thread_local[:locks][:connecting_manager] = false
|
54
58
|
end
|
@@ -147,6 +151,8 @@ module Mongo
|
|
147
151
|
unless @members.size == 0
|
148
152
|
@max_bson_size = @members.map(&:max_bson_size).min
|
149
153
|
@max_message_size = @members.map(&:max_message_size).min
|
154
|
+
@max_wire_version = @members.map(&:max_wire_version).min
|
155
|
+
@min_wire_version = @members.map(&:min_wire_version).max
|
150
156
|
end
|
151
157
|
end
|
152
158
|
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# Copyright (C) 2009-2013 MongoDB, Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require 'mongo/connection/socket/socket_util.rb'
|
16
|
+
require 'mongo/connection/socket/ssl_socket.rb'
|
17
|
+
require 'mongo/connection/socket/tcp_socket.rb'
|
18
|
+
require 'mongo/connection/socket/unix_socket.rb'
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2013
|
1
|
+
# Copyright (C) 2009-2013 MongoDB, Inc.
|
2
2
|
#
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
4
|
# you may not use this file except in compliance with the License.
|
@@ -12,9 +12,12 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
+
require 'socket'
|
16
|
+
require 'timeout'
|
17
|
+
|
15
18
|
module SocketUtil
|
16
19
|
|
17
|
-
attr_accessor :pool, :pid
|
20
|
+
attr_accessor :pool, :pid, :auths
|
18
21
|
|
19
22
|
def checkout
|
20
23
|
@pool.checkout if @pool
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2013
|
1
|
+
# Copyright (C) 2009-2013 MongoDB, Inc.
|
2
2
|
#
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
4
|
# you may not use this file except in compliance with the License.
|
@@ -12,9 +12,7 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
-
require 'socket'
|
16
15
|
require 'openssl'
|
17
|
-
require 'timeout'
|
18
16
|
|
19
17
|
module Mongo
|
20
18
|
|
@@ -25,9 +23,10 @@ module Mongo
|
|
25
23
|
include SocketUtil
|
26
24
|
|
27
25
|
def initialize(host, port, op_timeout=nil, connect_timeout=nil, opts={})
|
28
|
-
@pid = Process.pid
|
29
26
|
@op_timeout = op_timeout
|
30
27
|
@connect_timeout = connect_timeout
|
28
|
+
@pid = Process.pid
|
29
|
+
@auths = Set.new
|
31
30
|
|
32
31
|
@tcp_socket = ::TCPSocket.new(host, port)
|
33
32
|
@tcp_socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2013
|
1
|
+
# Copyright (C) 2009-2013 MongoDB, Inc.
|
2
2
|
#
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
4
|
# you may not use this file except in compliance with the License.
|
@@ -12,9 +12,6 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
-
require 'socket'
|
16
|
-
require 'timeout'
|
17
|
-
|
18
15
|
module Mongo
|
19
16
|
# Wrapper class for Socket
|
20
17
|
#
|
@@ -28,25 +25,38 @@ module Mongo
|
|
28
25
|
@op_timeout = op_timeout
|
29
26
|
@connect_timeout = connect_timeout
|
30
27
|
@pid = Process.pid
|
28
|
+
@auths = Set.new
|
31
29
|
|
32
|
-
|
33
|
-
|
34
|
-
@port = port
|
35
|
-
|
36
|
-
@socket_address = Socket.pack_sockaddr_in(@port, @address)
|
37
|
-
@socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
|
38
|
-
@socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
|
30
|
+
@socket = handle_connect(host, port)
|
31
|
+
end
|
39
32
|
|
40
|
-
|
33
|
+
def handle_connect(host, port)
|
34
|
+
error = nil
|
35
|
+
# Following python's lead (see PYTHON-356)
|
36
|
+
family = host == 'localhost' ? Socket::AF_INET : Socket::AF_UNSPEC
|
37
|
+
addr_info = Socket.getaddrinfo(host, nil, family, Socket::SOCK_STREAM)
|
38
|
+
addr_info.each do |info|
|
39
|
+
begin
|
40
|
+
sock = Socket.new(info[4], Socket::SOCK_STREAM, 0)
|
41
|
+
sock.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
|
42
|
+
socket_address = Socket.pack_sockaddr_in(port, info[3])
|
43
|
+
connect(sock, socket_address)
|
44
|
+
return sock
|
45
|
+
rescue IOError, SystemCallError => e
|
46
|
+
error = e
|
47
|
+
sock.close if sock
|
48
|
+
end
|
49
|
+
end
|
50
|
+
raise error
|
41
51
|
end
|
42
52
|
|
43
|
-
def connect
|
53
|
+
def connect(socket, socket_address)
|
44
54
|
if @connect_timeout
|
45
55
|
Timeout::timeout(@connect_timeout, ConnectionTimeoutError) do
|
46
|
-
|
56
|
+
socket.connect(socket_address)
|
47
57
|
end
|
48
58
|
else
|
49
|
-
|
59
|
+
socket.connect(socket_address)
|
50
60
|
end
|
51
61
|
end
|
52
62
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2013
|
1
|
+
# Copyright (C) 2009-2013 MongoDB, Inc.
|
2
2
|
#
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
4
|
# you may not use this file except in compliance with the License.
|
@@ -12,9 +12,10 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
-
require 'socket'
|
16
|
-
|
17
15
|
module Mongo
|
16
|
+
|
17
|
+
attr_accessor :auths
|
18
|
+
|
18
19
|
# Wrapper class for Socket
|
19
20
|
#
|
20
21
|
# Emulates UNIXSocket with operation and connection timeout
|
@@ -24,6 +25,8 @@ module Mongo
|
|
24
25
|
def initialize(socket_path, port=:socket, op_timeout=nil, connect_timeout=nil, opts={})
|
25
26
|
@op_timeout = op_timeout
|
26
27
|
@connect_timeout = connect_timeout
|
28
|
+
@pid = Process.pid
|
29
|
+
@auths = Set.new
|
27
30
|
|
28
31
|
@address = socket_path
|
29
32
|
@port = :socket # purposely override input
|
@@ -34,4 +37,3 @@ module Mongo
|
|
34
37
|
end
|
35
38
|
end
|
36
39
|
end
|
37
|
-
|
data/lib/mongo/cursor.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2013
|
1
|
+
# Copyright (C) 2009-2013 MongoDB, Inc.
|
2
2
|
#
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
4
|
# you may not use this file except in compliance with the License.
|
@@ -26,7 +26,8 @@ module Mongo
|
|
26
26
|
:order, :hint, :snapshot, :timeout,
|
27
27
|
:full_collection_name, :transformer,
|
28
28
|
:options, :cursor_id, :show_disk_loc,
|
29
|
-
:comment, :read, :tag_sets,
|
29
|
+
:comment, :compile_regex, :read, :tag_sets,
|
30
|
+
:acceptable_latency
|
30
31
|
|
31
32
|
# Create a new cursor.
|
32
33
|
#
|
@@ -34,54 +35,57 @@ module Mongo
|
|
34
35
|
# similar methods. Application developers shouldn't have to create cursors manually.
|
35
36
|
#
|
36
37
|
# @return [Cursor]
|
37
|
-
#
|
38
|
-
# @core cursors constructor_details
|
39
38
|
def initialize(collection, opts={})
|
40
|
-
|
39
|
+
opts = opts.dup
|
40
|
+
@cursor_id = opts.delete(:cursor_id)
|
41
41
|
@db = collection.db
|
42
42
|
@collection = collection
|
43
43
|
@connection = @db.connection
|
44
44
|
@logger = @connection.logger
|
45
45
|
|
46
46
|
# Query selector
|
47
|
-
@selector = opts
|
47
|
+
@selector = opts.delete(:selector) || {}
|
48
|
+
|
49
|
+
# Query pre-serialized bson to append
|
50
|
+
@bson = @selector.delete(:bson)
|
48
51
|
|
49
52
|
# Special operators that form part of $query
|
50
|
-
@order
|
51
|
-
@explain
|
52
|
-
@hint
|
53
|
-
@snapshot
|
54
|
-
@max_scan
|
55
|
-
@return_key
|
56
|
-
@show_disk_loc = opts.
|
57
|
-
@comment
|
53
|
+
@order = opts.delete(:order)
|
54
|
+
@explain = opts.delete(:explain)
|
55
|
+
@hint = opts.delete(:hint)
|
56
|
+
@snapshot = opts.delete(:snapshot)
|
57
|
+
@max_scan = opts.delete(:max_scan)
|
58
|
+
@return_key = opts.delete(:return_key)
|
59
|
+
@show_disk_loc = opts.delete(:show_disk_loc)
|
60
|
+
@comment = opts.delete(:comment)
|
61
|
+
@compile_regex = opts.key?(:compile_regex) ? opts.delete(:compile_regex) : true
|
58
62
|
|
59
63
|
# Wire-protocol settings
|
60
|
-
@fields
|
61
|
-
@skip
|
62
|
-
@limit
|
63
|
-
@tailable
|
64
|
-
@timeout
|
65
|
-
@options
|
64
|
+
@fields = convert_fields_for_query(opts.delete(:fields))
|
65
|
+
@skip = opts.delete(:skip) || 0
|
66
|
+
@limit = opts.delete(:limit) || 0
|
67
|
+
@tailable = opts.delete(:tailable)
|
68
|
+
@timeout = opts.key?(:timeout) ? opts.delete(:timeout) : true
|
69
|
+
@options = 0
|
66
70
|
|
67
71
|
# Use this socket for the query
|
68
|
-
@socket = opts
|
69
|
-
@pool =
|
72
|
+
@socket = opts.delete(:socket)
|
73
|
+
@pool = opts.delete(:pool)
|
70
74
|
|
71
|
-
@closed
|
72
|
-
@query_run
|
75
|
+
@closed = false
|
76
|
+
@query_run = false
|
73
77
|
|
74
|
-
@transformer
|
75
|
-
@read
|
78
|
+
@transformer = opts.delete(:transformer)
|
79
|
+
@read = opts.delete(:read) || @collection.read
|
76
80
|
Mongo::ReadPreference::validate(@read)
|
77
|
-
@tag_sets
|
78
|
-
@acceptable_latency = opts
|
81
|
+
@tag_sets = opts.delete(:tag_sets) || @collection.tag_sets
|
82
|
+
@acceptable_latency = opts.delete(:acceptable_latency) || @collection.acceptable_latency
|
79
83
|
|
80
|
-
batch_size(opts
|
84
|
+
batch_size(opts.delete(:batch_size) || 0)
|
81
85
|
|
82
86
|
@full_collection_name = "#{@collection.db.name}.#{@collection.name}"
|
83
|
-
@cache
|
84
|
-
@returned
|
87
|
+
@cache = opts.delete(:first_batch) || []
|
88
|
+
@returned = 0
|
85
89
|
|
86
90
|
if(!@timeout)
|
87
91
|
add_option(OP_QUERY_NO_CURSOR_TIMEOUT)
|
@@ -93,11 +97,19 @@ module Mongo
|
|
93
97
|
add_option(OP_QUERY_TAILABLE)
|
94
98
|
end
|
95
99
|
|
100
|
+
# If a cursor_id is provided, this is a cursor for a command
|
101
|
+
if @cursor_id
|
102
|
+
@command_cursor = true
|
103
|
+
@query_run = true
|
104
|
+
end
|
105
|
+
|
96
106
|
if @collection.name =~ /^\$cmd/ || @collection.name =~ /^system/
|
97
107
|
@command = true
|
98
108
|
else
|
99
109
|
@command = false
|
100
110
|
end
|
111
|
+
|
112
|
+
@opts = opts
|
101
113
|
end
|
102
114
|
|
103
115
|
# Guess whether the cursor is alive on the server.
|
@@ -126,18 +138,25 @@ module Mongo
|
|
126
138
|
end
|
127
139
|
doc = @cache.shift
|
128
140
|
|
129
|
-
if doc && doc['$err']
|
130
|
-
|
141
|
+
if doc && (err = doc['errmsg'] || doc['$err']) # assignment
|
142
|
+
code = doc['code']
|
131
143
|
|
132
144
|
# If the server has stopped being the master (e.g., it's one of a
|
133
145
|
# pair but it has died or something like that) then we close that
|
134
146
|
# connection. The next request will re-open on master server.
|
135
147
|
if err.include?("not master")
|
136
148
|
@connection.close
|
137
|
-
raise ConnectionFailure.new(err,
|
149
|
+
raise ConnectionFailure.new(err, code, doc)
|
138
150
|
end
|
139
151
|
|
140
|
-
|
152
|
+
# Handle server side operation execution timeout
|
153
|
+
if code == 50
|
154
|
+
raise ExecutionTimeout.new(err, code, doc)
|
155
|
+
end
|
156
|
+
|
157
|
+
raise OperationFailure.new(err, code, doc)
|
158
|
+
elsif doc && (writeConcernError = doc['writeConcernError']) && writeConcernError['errInfo'] == {"wtimeout" => true} # assignment
|
159
|
+
raise OperationFailure.new('timeout ' + writeConcernError['errmsg'], writeConcernError['code'], doc)
|
141
160
|
end
|
142
161
|
|
143
162
|
if @transformer.nil?
|
@@ -151,6 +170,7 @@ module Mongo
|
|
151
170
|
# Reset this cursor on the server. Cursor options, such as the
|
152
171
|
# query string and the values for skip and limit, are preserved.
|
153
172
|
def rewind!
|
173
|
+
check_command_cursor
|
154
174
|
close
|
155
175
|
@cache.clear
|
156
176
|
@cursor_id = nil
|
@@ -175,6 +195,7 @@ module Mongo
|
|
175
195
|
#
|
176
196
|
# @raise [OperationFailure] on a database error.
|
177
197
|
def count(skip_and_limit = false)
|
198
|
+
check_command_cursor
|
178
199
|
command = BSON::OrderedHash["count", @collection.name, "query", @selector]
|
179
200
|
|
180
201
|
if skip_and_limit
|
@@ -219,8 +240,6 @@ module Mongo
|
|
219
240
|
# @return [Integer] the current number_to_return if no parameter is given.
|
220
241
|
#
|
221
242
|
# @raise [InvalidOperation] if this cursor has already been used.
|
222
|
-
#
|
223
|
-
# @core limit limit-instance_method
|
224
243
|
def limit(number_to_return=nil)
|
225
244
|
return @limit unless number_to_return
|
226
245
|
check_modifiable
|
@@ -250,6 +269,31 @@ module Mongo
|
|
250
269
|
self
|
251
270
|
end
|
252
271
|
|
272
|
+
# Instruct the server to abort queries after they exceed the specified
|
273
|
+
# wall-clock execution time.
|
274
|
+
#
|
275
|
+
# A query that completes in under its time limit will "roll over"
|
276
|
+
# remaining time to the first getmore op (which will then "roll over"
|
277
|
+
# its remaining time to the second getmore op and so on, until the
|
278
|
+
# time limit is hit).
|
279
|
+
#
|
280
|
+
# Cursors returned by successful time-limited queries will still obey
|
281
|
+
# the default cursor idle timeout (unless the "no cursor idle timeout"
|
282
|
+
# flag has been set).
|
283
|
+
#
|
284
|
+
# @note This will only have an effect in MongoDB 2.5+
|
285
|
+
#
|
286
|
+
# @param max_time_ms [Fixnum] max execution time (in milliseconds)
|
287
|
+
#
|
288
|
+
# @return [Fixnum, Cursor] either the current max_time_ms or cursor
|
289
|
+
def max_time_ms(max_time_ms=nil)
|
290
|
+
return @max_time_ms unless max_time_ms
|
291
|
+
check_modifiable
|
292
|
+
|
293
|
+
@max_time_ms = max_time_ms
|
294
|
+
self
|
295
|
+
end
|
296
|
+
|
253
297
|
# Set the batch size for server responses.
|
254
298
|
#
|
255
299
|
# Note that the batch size will take effect only on queries
|
@@ -317,9 +361,8 @@ module Mongo
|
|
317
361
|
# Get the explain plan for this cursor.
|
318
362
|
#
|
319
363
|
# @return [Hash] a document containing the explain plan for this cursor.
|
320
|
-
#
|
321
|
-
# @core explain explain-instance_method
|
322
364
|
def explain
|
365
|
+
check_command_cursor
|
323
366
|
c = Cursor.new(@collection,
|
324
367
|
query_options_hash.merge(:limit => -@limit.abs, :explain => true))
|
325
368
|
explanation = c.next_document
|
@@ -496,13 +539,13 @@ module Mongo
|
|
496
539
|
socket = @socket || checkout_socket_from_connection
|
497
540
|
results, @n_received, @cursor_id = @connection.receive_message(
|
498
541
|
Mongo::Constants::OP_QUERY, message, nil, socket, @command,
|
499
|
-
nil, exhaust?)
|
542
|
+
nil, exhaust?, compile_regex?)
|
500
543
|
rescue ConnectionFailure => ex
|
501
544
|
socket.close if socket
|
502
545
|
@pool = nil
|
503
546
|
@connection.unpin_pool
|
504
547
|
@connection.refresh
|
505
|
-
if tries < 3 && !@socket && (!@command || Mongo::
|
548
|
+
if tries < 3 && !@socket && (!@command || Mongo::ReadPreference::secondary_ok?(@selector))
|
506
549
|
tries += 1
|
507
550
|
retry
|
508
551
|
else
|
@@ -548,7 +591,8 @@ module Mongo
|
|
548
591
|
|
549
592
|
begin
|
550
593
|
results, @n_received, @cursor_id = @connection.receive_message(
|
551
|
-
Mongo::Constants::OP_GET_MORE, message, nil, socket, @command,
|
594
|
+
Mongo::Constants::OP_GET_MORE, message, nil, socket, @command,
|
595
|
+
nil, exhaust?, compile_regex?)
|
552
596
|
ensure
|
553
597
|
socket.checkin
|
554
598
|
end
|
@@ -562,7 +606,7 @@ module Mongo
|
|
562
606
|
begin
|
563
607
|
if @pool
|
564
608
|
socket = @pool.checkout
|
565
|
-
elsif @command && !Mongo::
|
609
|
+
elsif @command && !Mongo::ReadPreference::secondary_ok?(@selector)
|
566
610
|
socket = @connection.checkout_reader({:mode => :primary})
|
567
611
|
else
|
568
612
|
socket = @connection.checkout_reader(read_preference)
|
@@ -580,13 +624,24 @@ module Mongo
|
|
580
624
|
end
|
581
625
|
|
582
626
|
def construct_query_message
|
583
|
-
message = BSON::ByteBuffer.new("", @connection.
|
627
|
+
message = BSON::ByteBuffer.new("", @connection.max_bson_size + MongoClient::COMMAND_HEADROOM)
|
584
628
|
message.put_int(@options)
|
585
629
|
BSON::BSON_RUBY.serialize_cstr(message, "#{@db.name}.#{@collection.name}")
|
586
630
|
message.put_int(@skip)
|
587
631
|
@batch_size > 1 ? message.put_int(@batch_size) : message.put_int(@limit)
|
588
|
-
|
589
|
-
|
632
|
+
if query_contains_special_fields? && @bson # costs two serialize calls
|
633
|
+
query_message = BSON::BSON_CODER.serialize(@selector, false, false, @connection.max_bson_size + MongoClient::APPEND_HEADROOM)
|
634
|
+
query_message.grow(@bson)
|
635
|
+
query_spec = construct_query_spec
|
636
|
+
query_spec.delete('$query')
|
637
|
+
query_message.grow(BSON::BSON_CODER.serialize(query_spec, false, false, @connection.max_bson_size))
|
638
|
+
else # costs only one serialize call
|
639
|
+
spec = query_contains_special_fields? ? construct_query_spec : @selector
|
640
|
+
spec.merge!(@opts)
|
641
|
+
query_message = BSON::BSON_CODER.serialize(spec, false, false, @connection.max_bson_size + MongoClient::APPEND_HEADROOM)
|
642
|
+
query_message.grow(@bson) if @bson
|
643
|
+
end
|
644
|
+
message.put_binary(query_message.to_s)
|
590
645
|
message.put_binary(BSON::BSON_CODER.serialize(@fields, false, false, @connection.max_bson_size).to_s) if @fields
|
591
646
|
message
|
592
647
|
end
|
@@ -612,6 +667,7 @@ module Mongo
|
|
612
667
|
spec['$returnKey'] = true if @return_key
|
613
668
|
spec['$showDiskLoc'] = true if @show_disk_loc
|
614
669
|
spec['$comment'] = @comment if @comment
|
670
|
+
spec['$maxTimeMS'] = @max_time_ms if @max_time_ms
|
615
671
|
if needs_read_pref?
|
616
672
|
read_pref = Mongo::ReadPreference::mongos(@read, @tag_sets)
|
617
673
|
spec['$readPreference'] = read_pref if read_pref
|
@@ -625,7 +681,7 @@ module Mongo
|
|
625
681
|
|
626
682
|
def query_contains_special_fields?
|
627
683
|
@order || @explain || @hint || @snapshot || @show_disk_loc ||
|
628
|
-
@max_scan || @return_key || @comment || needs_read_pref?
|
684
|
+
@max_scan || @return_key || @comment || @max_time_ms || needs_read_pref?
|
629
685
|
end
|
630
686
|
|
631
687
|
def close_cursor_if_query_complete
|
@@ -646,5 +702,15 @@ module Mongo
|
|
646
702
|
raise InvalidOperation, "Cannot modify the query once it has been run or closed."
|
647
703
|
end
|
648
704
|
end
|
705
|
+
|
706
|
+
def check_command_cursor
|
707
|
+
if @command_cursor
|
708
|
+
raise InvalidOperation, "Cannot call #{caller.first} on command cursors"
|
709
|
+
end
|
710
|
+
end
|
711
|
+
|
712
|
+
def compile_regex?
|
713
|
+
@compile_regex
|
714
|
+
end
|
649
715
|
end
|
650
716
|
end
|