Filename | /usr/local/lib/perl/5.14.2/MongoDB/MongoClient.pm |
Statements | Executed 80 statements in 3.12ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
4 | 1 | 1 | 13.4s | 13.4s | recv (xsub) | MongoDB::MongoClient::
1 | 1 | 1 | 2.73ms | 5.70ms | BEGIN@34 | MongoDB::MongoClient::
1 | 1 | 1 | 738µs | 1.01ms | BEGIN@29 | MongoDB::MongoClient::
1 | 1 | 1 | 381µs | 398µs | connect (xsub) | MongoDB::MongoClient::
1 | 1 | 1 | 249µs | 6.96ms | BEGIN@28 | MongoDB::MongoClient::
1 | 1 | 1 | 200µs | 8.96ms | BUILD | MongoDB::MongoClient::
4 | 1 | 1 | 75µs | 75µs | send (xsub) | MongoDB::MongoClient::
1 | 1 | 1 | 25µs | 32µs | _init_conn (xsub) | MongoDB::MongoClient::
1 | 1 | 1 | 21µs | 891µs | _get_max_bson_size | MongoDB::MongoClient::
3 | 3 | 3 | 14µs | 85µs | get_database | MongoDB::MongoClient::
1 | 1 | 1 | 13µs | 3.03ms | BEGIN@24 | MongoDB::MongoClient::
1 | 1 | 1 | 12µs | 12µs | __ANON__[:114] | MongoDB::MongoClient::
1 | 1 | 1 | 10µs | 42µs | BEGIN@33 | MongoDB::MongoClient::
1 | 1 | 1 | 10µs | 1.55ms | BEGIN@25 | MongoDB::MongoClient::
3 | 3 | 1 | 7µs | 7µs | CORE:match (opcode) | MongoDB::MongoClient::
1 | 1 | 1 | 7µs | 39µs | BEGIN@32 | MongoDB::MongoClient::
1 | 1 | 1 | 7µs | 39µs | BEGIN@31 | MongoDB::MongoClient::
1 | 1 | 1 | 6µs | 8µs | __ANON__[:148] | MongoDB::MongoClient::
1 | 1 | 1 | 5µs | 5µs | BEGIN@30 | MongoDB::MongoClient::
1 | 1 | 1 | 5µs | 5µs | BEGIN@26 | MongoDB::MongoClient::
1 | 1 | 1 | 4µs | 4µs | BEGIN@27 | MongoDB::MongoClient::
1 | 1 | 1 | 3µs | 3µs | __ANON__[:158] | MongoDB::MongoClient::
0 | 0 | 0 | 0s | 0s | _get_a_specific_connection | MongoDB::MongoClient::
0 | 0 | 0 | 0s | 0s | _get_any_connection | MongoDB::MongoClient::
0 | 0 | 0 | 0s | 0s | _sasl_check | MongoDB::MongoClient::
0 | 0 | 0 | 0s | 0s | _sasl_continue | MongoDB::MongoClient::
0 | 0 | 0 | 0s | 0s | _sasl_plain_authenticate | MongoDB::MongoClient::
0 | 0 | 0 | 0s | 0s | _sasl_start | MongoDB::MongoClient::
0 | 0 | 0 | 0s | 0s | _w_want_safe | MongoDB::MongoClient::
0 | 0 | 0 | 0s | 0s | authenticate | MongoDB::MongoClient::
0 | 0 | 0 | 0s | 0s | database_names | MongoDB::MongoClient::
0 | 0 | 0 | 0s | 0s | fsync | MongoDB::MongoClient::
0 | 0 | 0 | 0s | 0s | fsync_unlock | MongoDB::MongoClient::
0 | 0 | 0 | 0s | 0s | get_master | MongoDB::MongoClient::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | # | ||||
2 | # Copyright 2009-2013 MongoDB, Inc. | ||||
3 | # | ||||
4 | # Licensed under the Apache License, Version 2.0 (the "License"); | ||||
5 | # you may not use this file except in compliance with the License. | ||||
6 | # You may obtain a copy of the License at | ||||
7 | # | ||||
8 | # http://www.apache.org/licenses/LICENSE-2.0 | ||||
9 | # | ||||
10 | # Unless required by applicable law or agreed to in writing, software | ||||
11 | # distributed under the License is distributed on an "AS IS" BASIS, | ||||
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
13 | # See the License for the specific language governing permissions and | ||||
14 | # limitations under the License. | ||||
15 | # | ||||
16 | |||||
17 | package MongoDB::MongoClient; | ||||
18 | { | ||||
19 | 2 | 1µs | $MongoDB::MongoClient::VERSION = '0.702.2'; | ||
20 | } | ||||
21 | |||||
22 | # ABSTRACT: A connection to a MongoDB server | ||||
23 | |||||
24 | 2 | 35µs | 2 | 6.04ms | # spent 3.03ms (13µs+3.01) within MongoDB::MongoClient::BEGIN@24 which was called:
# once (13µs+3.01ms) by MongoDB::Connection::BEGIN@28 at line 24 # spent 3.03ms making 1 call to MongoDB::MongoClient::BEGIN@24
# spent 3.01ms making 1 call to Moose::Exporter::__ANON__[Moose/Exporter.pm:519] |
25 | 2 | 31µs | 2 | 3.10ms | # spent 1.55ms (10µs+1.55) within MongoDB::MongoClient::BEGIN@25 which was called:
# once (10µs+1.55ms) by MongoDB::Connection::BEGIN@28 at line 25 # spent 1.55ms making 1 call to MongoDB::MongoClient::BEGIN@25
# spent 1.55ms making 1 call to Moose::Exporter::__ANON__[Moose/Exporter.pm:519] |
26 | 2 | 20µs | 1 | 5µs | # spent 5µs within MongoDB::MongoClient::BEGIN@26 which was called:
# once (5µs+0s) by MongoDB::Connection::BEGIN@28 at line 26 # spent 5µs making 1 call to MongoDB::MongoClient::BEGIN@26 |
27 | 2 | 20µs | 1 | 4µs | # spent 4µs within MongoDB::MongoClient::BEGIN@27 which was called:
# once (4µs+0s) by MongoDB::Connection::BEGIN@28 at line 27 # spent 4µs making 1 call to MongoDB::MongoClient::BEGIN@27 |
28 | 2 | 135µs | 1 | 6.96ms | # spent 6.96ms (249µs+6.71) within MongoDB::MongoClient::BEGIN@28 which was called:
# once (249µs+6.71ms) by MongoDB::Connection::BEGIN@28 at line 28 # spent 6.96ms making 1 call to MongoDB::MongoClient::BEGIN@28 |
29 | 2 | 136µs | 2 | 1.03ms | # spent 1.01ms (738µs+273µs) within MongoDB::MongoClient::BEGIN@29 which was called:
# once (738µs+273µs) by MongoDB::Connection::BEGIN@28 at line 29 # spent 1.01ms making 1 call to MongoDB::MongoClient::BEGIN@29
# spent 18µs making 1 call to Exporter::import |
30 | 2 | 24µs | 1 | 5µs | # spent 5µs within MongoDB::MongoClient::BEGIN@30 which was called:
# once (5µs+0s) by MongoDB::Connection::BEGIN@28 at line 30 # spent 5µs making 1 call to MongoDB::MongoClient::BEGIN@30 |
31 | 2 | 24µs | 2 | 71µs | # spent 39µs (7+32) within MongoDB::MongoClient::BEGIN@31 which was called:
# once (7µs+32µs) by MongoDB::Connection::BEGIN@28 at line 31 # spent 39µs making 1 call to MongoDB::MongoClient::BEGIN@31
# spent 32µs making 1 call to Exporter::import |
32 | 2 | 23µs | 2 | 70µs | # spent 39µs (7+32) within MongoDB::MongoClient::BEGIN@32 which was called:
# once (7µs+32µs) by MongoDB::Connection::BEGIN@28 at line 32 # spent 39µs making 1 call to MongoDB::MongoClient::BEGIN@32
# spent 32µs making 1 call to Exporter::import |
33 | 2 | 22µs | 2 | 47µs | # spent 42µs (10+32) within MongoDB::MongoClient::BEGIN@33 which was called:
# once (10µs+32µs) by MongoDB::Connection::BEGIN@28 at line 33 # spent 42µs making 1 call to MongoDB::MongoClient::BEGIN@33
# spent 5µs making 1 call to boolean::import |
34 | 2 | 1.94ms | 2 | 5.75ms | # spent 5.70ms (2.73+2.97) within MongoDB::MongoClient::BEGIN@34 which was called:
# once (2.73ms+2.97ms) by MongoDB::Connection::BEGIN@28 at line 34 # spent 5.70ms making 1 call to MongoDB::MongoClient::BEGIN@34
# spent 52µs making 1 call to Exporter::import |
35 | |||||
36 | 1 | 2µs | 1 | 1.55ms | has host => ( # spent 1.55ms making 1 call to Moose::has |
37 | is => 'ro', | ||||
38 | isa => 'Str', | ||||
39 | required => 1, | ||||
40 | default => 'mongodb://localhost:27017', | ||||
41 | ); | ||||
42 | |||||
43 | 1 | 2µs | 1 | 2.44ms | has w => ( # spent 2.44ms making 1 call to Moose::has |
44 | is => 'rw', | ||||
45 | isa => 'Int|Str', | ||||
46 | default => 1, | ||||
47 | ); | ||||
48 | |||||
49 | 1 | 2µs | 1 | 1.73ms | has wtimeout => ( # spent 1.73ms making 1 call to Moose::has |
50 | is => 'rw', | ||||
51 | isa => 'Int', | ||||
52 | default => 1000, | ||||
53 | ); | ||||
54 | |||||
55 | 1 | 2µs | 1 | 1.80ms | has j => ( # spent 1.80ms making 1 call to Moose::has |
56 | is => 'rw', | ||||
57 | isa => 'Bool', | ||||
58 | default => 0 | ||||
59 | ); | ||||
60 | |||||
61 | |||||
62 | 1 | 2µs | 1 | 1.52ms | has port => ( # spent 1.52ms making 1 call to Moose::has |
63 | is => 'ro', | ||||
64 | isa => 'Int', | ||||
65 | required => 1, | ||||
66 | default => 27017, | ||||
67 | ); | ||||
68 | |||||
69 | |||||
70 | 1 | 2µs | 1 | 1.49ms | has auto_reconnect => ( # spent 1.49ms making 1 call to Moose::has |
71 | is => 'ro', | ||||
72 | isa => 'Bool', | ||||
73 | required => 1, | ||||
74 | default => 1, | ||||
75 | ); | ||||
76 | |||||
77 | 1 | 2µs | 1 | 1.59ms | has auto_connect => ( # spent 1.59ms making 1 call to Moose::has |
78 | is => 'ro', | ||||
79 | isa => 'Bool', | ||||
80 | required => 1, | ||||
81 | default => 1, | ||||
82 | ); | ||||
83 | |||||
84 | 1 | 2µs | 1 | 1.55ms | has timeout => ( # spent 1.55ms making 1 call to Moose::has |
85 | is => 'ro', | ||||
86 | isa => 'Int', | ||||
87 | required => 1, | ||||
88 | default => 20000, | ||||
89 | ); | ||||
90 | |||||
91 | 1 | 2µs | 1 | 1.77ms | has username => ( # spent 1.77ms making 1 call to Moose::has |
92 | is => 'rw', | ||||
93 | isa => 'Str', | ||||
94 | required => 0, | ||||
95 | ); | ||||
96 | |||||
97 | 1 | 2µs | 1 | 1.79ms | has password => ( # spent 1.79ms making 1 call to Moose::has |
98 | is => 'rw', | ||||
99 | isa => 'Str', | ||||
100 | required => 0, | ||||
101 | ); | ||||
102 | |||||
103 | 1 | 1µs | 1 | 1.88ms | has db_name => ( # spent 1.88ms making 1 call to Moose::has |
104 | is => 'rw', | ||||
105 | isa => 'Str', | ||||
106 | required => 1, | ||||
107 | default => 'admin', | ||||
108 | ); | ||||
109 | |||||
110 | has query_timeout => ( | ||||
111 | is => 'rw', | ||||
112 | isa => 'Int', | ||||
113 | required => 1, | ||||
114 | 1 | 6µs | # spent 12µs within MongoDB::MongoClient::__ANON__[/usr/local/lib/perl/5.14.2/MongoDB/MongoClient.pm:114] which was called:
# once (12µs+0s) by MongoDB::MongoClient::new at line 203 of (eval 62)[Eval/Closure.pm:144] | ||
115 | 1 | 3µs | 1 | 1.93ms | ); # spent 1.93ms making 1 call to Moose::has |
116 | |||||
117 | 1 | 1µs | 1 | 1.87ms | has max_bson_size => ( # spent 1.87ms making 1 call to Moose::has |
118 | is => 'rw', | ||||
119 | isa => 'Int', | ||||
120 | required => 1, | ||||
121 | default => 4194304 | ||||
122 | ); | ||||
123 | |||||
124 | 1 | 2µs | 1 | 1.61ms | has find_master => ( # spent 1.61ms making 1 call to Moose::has |
125 | is => 'ro', | ||||
126 | isa => 'Bool', | ||||
127 | required => 1, | ||||
128 | default => 0, | ||||
129 | ); | ||||
130 | |||||
131 | |||||
132 | 1 | 1µs | 1 | 1.56ms | has ssl => ( # spent 1.56ms making 1 call to Moose::has |
133 | is => 'ro', | ||||
134 | isa => 'Bool', | ||||
135 | required => 1, | ||||
136 | default => 0, | ||||
137 | ); | ||||
138 | |||||
139 | 1 | 2µs | 1 | 1.62ms | has sasl => ( # spent 1.62ms making 1 call to Moose::has |
140 | is => 'ro', | ||||
141 | isa => 'Bool', | ||||
142 | required => 1, | ||||
143 | default => 0 | ||||
144 | ); | ||||
145 | |||||
146 | has sasl_mechanism => ( | ||||
147 | is => 'ro', | ||||
148 | 2 | 21µs | 4 | 2.08ms | # spent 8µs (6+2) within MongoDB::MongoClient::__ANON__[/usr/local/lib/perl/5.14.2/MongoDB/MongoClient.pm:148] which was called:
# once (6µs+2µs) by Moose::Meta::TypeConstraint::__ANON__ at line 388 of Moose/Meta/TypeConstraint.pm # spent 1.75ms making 1 call to Moose::has
# spent 313µs making 1 call to Moose::Util::TypeConstraints::subtype
# spent 7µs making 1 call to Moose::Util::TypeConstraints::where
# spent 2µs making 1 call to MongoDB::MongoClient::CORE:match |
149 | required => 1, | ||||
150 | default => 'GSSAPI', | ||||
151 | ); | ||||
152 | |||||
153 | # hash of servers in a set | ||||
154 | # call connected() to determine if a connection is enabled | ||||
155 | has _servers => ( | ||||
156 | is => 'rw', | ||||
157 | isa => 'HashRef', | ||||
158 | 1 | 4µs | # spent 3µs within MongoDB::MongoClient::__ANON__[/usr/local/lib/perl/5.14.2/MongoDB/MongoClient.pm:158] which was called:
# once (3µs+0s) by MongoDB::MongoClient::new at line 48 of (eval 62)[Eval/Closure.pm:144] | ||
159 | 1 | 3µs | 1 | 1.72ms | ); # spent 1.72ms making 1 call to Moose::has |
160 | |||||
161 | # actual connection to a server in the set | ||||
162 | 1 | 1µs | 1 | 1.40ms | has _master => ( # spent 1.40ms making 1 call to Moose::has |
163 | is => 'rw', | ||||
164 | # isa => 'MongoDB::Connection', | ||||
165 | required => 0, | ||||
166 | ); | ||||
167 | |||||
168 | 1 | 2µs | 1 | 1.82ms | has ts => ( # spent 1.82ms making 1 call to Moose::has |
169 | is => 'rw', | ||||
170 | isa => 'Int', | ||||
171 | default => 0 | ||||
172 | ); | ||||
173 | |||||
174 | |||||
175 | 1 | 2µs | 1 | 1.43ms | has dt_type => ( # spent 1.43ms making 1 call to Moose::has |
176 | is => 'rw', | ||||
177 | required => 0, | ||||
178 | default => 'DateTime' | ||||
179 | ); | ||||
180 | |||||
181 | 1 | 2µs | 1 | 1.75ms | has inflate_dbrefs => ( # spent 1.75ms making 1 call to Moose::has |
182 | is => 'rw', | ||||
183 | isa => 'Bool', | ||||
184 | required => 0, | ||||
185 | default => 1 | ||||
186 | ); | ||||
187 | |||||
188 | # spent 8.96ms (200µs+8.76) within MongoDB::MongoClient::BUILD which was called:
# once (200µs+8.76ms) by MongoDB::MongoClient::new at line 314 of (eval 62)[Eval/Closure.pm:144] | ||||
189 | 1 | 1µs | my ($self, $opts) = @_; | ||
190 | eval "use ${_}" # no Any::Moose::load_class becase the namespaces already have symbols from the xs bootstrap | ||||
191 | 1 | 124µs | for qw/MongoDB::Database MongoDB::Cursor MongoDB::OID MongoDB::Timestamp/; # spent 103µs executing statements in string eval # includes 159µs spent executing 1 call to 1 sub defined therein. # spent 14µs executing statements in string eval # includes 9µs spent executing 1 call to 1 sub defined therein. # spent 12µs executing statements in string eval # includes 8µs spent executing 1 call to 1 sub defined therein. # spent 11µs executing statements in string eval # includes 8µs spent executing 1 call to 1 sub defined therein. | ||
192 | |||||
193 | 1 | 900ns | my @pairs; | ||
194 | |||||
195 | # supported syntax (see http://docs.mongodb.org/manual/reference/connection-string/) | ||||
196 | 1 | 10µs | 2 | 8µs | if ($self->host =~ m{ ^ # spent 4µs making 1 call to MongoDB::MongoClient::CORE:match
# spent 4µs making 1 call to MongoDB::MongoClient::host |
197 | mongodb:// | ||||
198 | (?: ([^:]*) : ([^@]*) @ )? # [username:password@] | ||||
199 | ([^/]*) # host1[:port1][,host2[:port2],...[,hostN[:portN]]] | ||||
200 | (?: | ||||
201 | / ([^?]*) # /[database] | ||||
202 | (?: [?] (.*) )? # [?options] | ||||
203 | )? | ||||
204 | $ }x ) { | ||||
205 | 1 | 6µs | my ($username, $password, $hostpairs, $database, $options) = ($1, $2, $3, $4, $5); | ||
206 | |||||
207 | # we add these things to $opts as well as self so that they get propagated when we recurse for multiple servers | ||||
208 | 1 | 400ns | $self->username($opts->{username} = $username) if $username; | ||
209 | 1 | 200ns | $self->password($opts->{password} = $password) if $password; | ||
210 | 1 | 400ns | $self->db_name($opts->{db_name} = $database) if $database; | ||
211 | |||||
212 | 1 | 400ns | $hostpairs = 'localhost' unless $hostpairs; | ||
213 | 3 | 8µs | 1 | 1µs | @pairs = map { $_ .= ':27017' unless $_ =~ /:/ ; $_ } split ',', $hostpairs; # spent 1µs making 1 call to MongoDB::MongoClient::CORE:match |
214 | |||||
215 | # TODO handle standard options from $options | ||||
216 | } | ||||
217 | # deprecated syntax | ||||
218 | else { | ||||
219 | push @pairs, $self->host.":".$self->port; | ||||
220 | } | ||||
221 | |||||
222 | # a simple single server is special-cased (so we don't recurse forever) | ||||
223 | 1 | 4µs | 1 | 4µs | if (@pairs == 1 && !$self->find_master) { # spent 4µs making 1 call to MongoDB::MongoClient::find_master |
224 | 1 | 3µs | my @hp = split ":", $pairs[0]; | ||
225 | |||||
226 | 1 | 31µs | 4 | 44µs | $self->_init_conn($hp[0], $hp[1], $self->ssl); # spent 32µs making 1 call to MongoDB::MongoClient::_init_conn
# spent 4µs making 1 call to MongoDB::MongoClient::auto_reconnect
# spent 4µs making 1 call to MongoDB::MongoClient::ssl
# spent 3µs making 1 call to MongoDB::MongoClient::timeout |
227 | 1 | 3µs | 1 | 4µs | if ($self->auto_connect) { # spent 4µs making 1 call to MongoDB::MongoClient::auto_connect |
228 | 1 | 377µs | 7 | 416µs | $self->connect; # spent 398µs making 1 call to MongoDB::MongoClient::connect
# spent 10µs making 4 calls to MongoDB::MongoClient::sasl, avg 3µs/call
# spent 4µs making 1 call to MongoDB::MongoClient::username
# spent 4µs making 1 call to MongoDB::MongoClient::password |
229 | 1 | 6µs | 2 | 910µs | $self->max_bson_size($self->_get_max_bson_size); # spent 891µs making 1 call to MongoDB::MongoClient::_get_max_bson_size
# spent 18µs making 1 call to MongoDB::MongoClient::max_bson_size |
230 | } | ||||
231 | 1 | 4µs | return; | ||
232 | } | ||||
233 | |||||
234 | # multiple servers | ||||
235 | my $connected = 0; | ||||
236 | $opts->{find_master} = 0; | ||||
237 | $opts->{auto_connect} = 0; | ||||
238 | foreach (@pairs) { | ||||
239 | $opts->{host} = "mongodb://$_"; | ||||
240 | |||||
241 | $self->_servers->{$_} = MongoDB::MongoClient->new($opts); | ||||
242 | |||||
243 | next unless $self->auto_connect; | ||||
244 | |||||
245 | # it's okay if we can't connect, so long as someone can | ||||
246 | eval { | ||||
247 | $self->_servers->{$_}->connect; | ||||
248 | $self->_servers->{$_}->max_bson_size($self->_servers->{$_}->_get_max_bson_size); | ||||
249 | }; | ||||
250 | |||||
251 | # at least one connection worked | ||||
252 | if (!$@) { | ||||
253 | $connected = 1; | ||||
254 | } | ||||
255 | } | ||||
256 | |||||
257 | my $master; | ||||
258 | |||||
259 | if ($self->auto_connect) { | ||||
260 | |||||
261 | # if we still aren't connected to anyone, give up | ||||
262 | if (!$connected) { | ||||
263 | die "couldn't connect to any servers listed: ".join(",", @pairs); | ||||
264 | } | ||||
265 | |||||
266 | $master = $self->get_master; | ||||
267 | if ($master == -1) { | ||||
268 | die "couldn't find master"; | ||||
269 | } | ||||
270 | else { | ||||
271 | $self->max_bson_size($master->max_bson_size); | ||||
272 | } | ||||
273 | } | ||||
274 | else { | ||||
275 | # no auto-connect so just pick one. if auto-reconnect is set then it will connect as needed | ||||
276 | ($master) = values %{$self->_servers}; | ||||
277 | } | ||||
278 | |||||
279 | # create a struct that just points to the master's connection | ||||
280 | $self->_init_conn_holder($master); | ||||
281 | } | ||||
282 | |||||
283 | # spent 891µs (21+870) within MongoDB::MongoClient::_get_max_bson_size which was called:
# once (21µs+870µs) by MongoDB::MongoClient::BUILD at line 229 | ||||
284 | 1 | 1µs | my $self = shift; | ||
285 | 1 | 9µs | 2 | 865µs | my $buildinfo = $self->get_database('admin')->run_command({buildinfo => 1}); # spent 822µs making 1 call to MongoDB::Database::run_command
# spent 43µs making 1 call to MongoDB::MongoClient::get_database |
286 | 1 | 3µs | 1 | 6µs | if (ref($buildinfo) eq 'HASH' && exists $buildinfo->{'maxBsonObjectSize'}) { # spent 6µs making 1 call to MongoDB::Database::DESTROY |
287 | 1 | 5µs | return $buildinfo->{'maxBsonObjectSize'}; | ||
288 | } | ||||
289 | # default: 4MB | ||||
290 | return 4194304; | ||||
291 | } | ||||
292 | |||||
293 | |||||
294 | sub database_names { | ||||
295 | my ($self) = @_; | ||||
296 | my $ret = $self->get_database('admin')->run_command({ listDatabases => 1 }); | ||||
297 | if (ref($ret) eq 'HASH' && exists $ret->{databases}) { | ||||
298 | return map { $_->{name} } @{ $ret->{databases} }; | ||||
299 | } | ||||
300 | else { | ||||
301 | die ($ret); | ||||
302 | } | ||||
303 | } | ||||
304 | |||||
305 | # spent 85µs (14+72) within MongoDB::MongoClient::get_database which was called 3 times, avg 28µs/call:
# once (7µs+36µs) by MongoDB::MongoClient::_get_max_bson_size at line 285
# once (4µs+18µs) by MongoDB::Connection::get_database at line 110 of Moose/Meta/Method/Delegation.pm
# once (3µs+17µs) by MongoDB::Cursor::count at line 286 of MongoDB/Cursor.pm | ||||
306 | 3 | 3µs | my ($self, $database_name) = @_; | ||
307 | 3 | 13µs | 3 | 72µs | return MongoDB::Database->new( # spent 72µs making 3 calls to MongoDB::Database::new, avg 24µs/call |
308 | _client => $self, | ||||
309 | name => $database_name, | ||||
310 | ); | ||||
311 | } | ||||
312 | |||||
313 | sub _get_a_specific_connection { | ||||
314 | my ($self, $host) = @_; | ||||
315 | |||||
316 | if ($self->_servers->{$host}->connected) { | ||||
317 | return $self->_servers->{$host}; | ||||
318 | } | ||||
319 | |||||
320 | eval { | ||||
321 | $self->_servers->{$host}->connect; | ||||
322 | }; | ||||
323 | |||||
324 | if (!$@) { | ||||
325 | return $self->_servers->{$host}; | ||||
326 | } | ||||
327 | return 0; | ||||
328 | } | ||||
329 | |||||
330 | sub _get_any_connection { | ||||
331 | my ($self) = @_; | ||||
332 | |||||
333 | while ((my $key, my $value) = each(%{$self->_servers})) { | ||||
334 | my $conn = $self->_get_a_specific_connection($key); | ||||
335 | if ($conn) { | ||||
336 | return $conn; | ||||
337 | } | ||||
338 | } | ||||
339 | |||||
340 | return 0; | ||||
341 | } | ||||
342 | |||||
343 | |||||
344 | sub get_master { | ||||
345 | my ($self) = @_; | ||||
346 | |||||
347 | my $conn = $self->_get_any_connection(); | ||||
348 | # if we couldn't connect to anything, just return | ||||
349 | if (!$conn) { | ||||
350 | return -1; | ||||
351 | } | ||||
352 | |||||
353 | # a single server or list of servers | ||||
354 | if (!$self->find_master) { | ||||
355 | $self->_master($conn); | ||||
356 | return $self->_master; | ||||
357 | } | ||||
358 | # auto-detect master | ||||
359 | else { | ||||
360 | my $master = $conn->get_database($self->db_name)->run_command({"ismaster" => 1}); | ||||
361 | |||||
362 | # check for errors | ||||
363 | if (ref($master) eq 'SCALAR') { | ||||
364 | return -1; | ||||
365 | } | ||||
366 | |||||
367 | # if this is a replica set & we haven't renewed the host list in 1 sec | ||||
368 | if ($master->{'hosts'} && time() > $self->ts) { | ||||
369 | # update (or set) rs list | ||||
370 | my %opts = ( auto_connect => 0 ); | ||||
371 | if ($self->username && $self->password) { | ||||
372 | $opts{username} = $self->username; | ||||
373 | $opts{password} = $self->password; | ||||
374 | $opts{db_name} = $self->db_name; | ||||
375 | } | ||||
376 | for (@{$master->{'hosts'}}) { | ||||
377 | if (!$self->_servers->{$_}) { | ||||
378 | $self->_servers->{$_} = MongoDB::MongoClient->new("host" => "mongodb://$_", %opts); | ||||
379 | } | ||||
380 | } | ||||
381 | $self->ts(time()); | ||||
382 | } | ||||
383 | |||||
384 | # if this is the master, whether or not it's a replica set, return it | ||||
385 | if ($master->{'ismaster'}) { | ||||
386 | $self->_master($conn); | ||||
387 | return $self->_master; | ||||
388 | } | ||||
389 | elsif ($self->find_master && exists $master->{'primary'}) { | ||||
390 | my $primary = $self->_get_a_specific_connection($master->{'primary'}); | ||||
391 | if (!$primary) { | ||||
392 | return -1; | ||||
393 | } | ||||
394 | |||||
395 | # double-check that this is master | ||||
396 | my $result = $primary->get_database("admin")->run_command({"ismaster" => 1}); | ||||
397 | if ($result->{'ismaster'}) { | ||||
398 | $self->_master($primary); | ||||
399 | return $self->_master; | ||||
400 | } | ||||
401 | } | ||||
402 | } | ||||
403 | |||||
404 | return -1; | ||||
405 | } | ||||
406 | |||||
407 | |||||
408 | sub authenticate { | ||||
409 | my ($self, $dbname, $username, $password, $is_digest) = @_; | ||||
410 | my $hash = $password; | ||||
411 | |||||
412 | # create a hash if the password isn't yet encrypted | ||||
413 | if (!$is_digest) { | ||||
414 | $hash = Digest::MD5::md5_hex("${username}:mongo:${password}"); | ||||
415 | } | ||||
416 | |||||
417 | # get the nonce | ||||
418 | my $db = $self->get_database($dbname); | ||||
419 | my $result = $db->run_command({getnonce => 1}); | ||||
420 | if (!$result->{'ok'}) { | ||||
421 | return $result; | ||||
422 | } | ||||
423 | |||||
424 | my $nonce = $result->{'nonce'}; | ||||
425 | my $digest = Digest::MD5::md5_hex($nonce.$username.$hash); | ||||
426 | |||||
427 | # run the login command | ||||
428 | my $login = tie(my %hash, 'Tie::IxHash'); | ||||
429 | %hash = (authenticate => 1, | ||||
430 | user => $username, | ||||
431 | nonce => $nonce, | ||||
432 | key => $digest); | ||||
433 | $result = $db->run_command($login); | ||||
434 | |||||
435 | return $result; | ||||
436 | } | ||||
437 | |||||
438 | |||||
439 | sub fsync { | ||||
440 | my ($self, $args) = @_; | ||||
441 | |||||
442 | $args ||= {}; | ||||
443 | |||||
444 | # Pass this in as array-ref to ensure that 'fsync => 1' is the first argument. | ||||
445 | return $self->get_database('admin')->run_command([fsync => 1, %$args]); | ||||
446 | } | ||||
447 | |||||
448 | sub fsync_unlock { | ||||
449 | my ($self) = @_; | ||||
450 | |||||
451 | # Have to fetch from a special collection to unlock. | ||||
452 | return $self->get_database('admin')->get_collection('$cmd.sys.unlock')->find_one(); | ||||
453 | } | ||||
454 | |||||
455 | sub _w_want_safe { | ||||
456 | my ( $self ) = @_; | ||||
457 | |||||
458 | my $w = $self->w; | ||||
459 | |||||
460 | return 0 if $w =~ /^-?\d+$/ && $w <= 0; | ||||
461 | return 1; | ||||
462 | } | ||||
463 | |||||
464 | sub _sasl_check { | ||||
465 | my ( $self, $res ) = @_; | ||||
466 | |||||
467 | die "Invalid SASL response document from server:" | ||||
468 | unless reftype $res eq reftype { }; | ||||
469 | |||||
470 | if ( $res->{ok} != 1 ) { | ||||
471 | die "SASL authentication error: $res->{errmsg}"; | ||||
472 | } | ||||
473 | |||||
474 | return $res->{conversationId}; | ||||
475 | } | ||||
476 | |||||
477 | sub _sasl_start { | ||||
478 | my ( $self, $payload, $mechanism ) = @_; | ||||
479 | |||||
480 | # warn "SASL start, payload = [$payload], mechanism = [$mechanism]\n"; | ||||
481 | |||||
482 | my $res = $self->get_database( '$external' )->run_command( [ | ||||
483 | saslStart => 1, | ||||
484 | mechanism => $mechanism, | ||||
485 | payload => $payload, | ||||
486 | autoAuthorize => 1 ] ); | ||||
487 | |||||
488 | $self->_sasl_check( $res ); | ||||
489 | return $res; | ||||
490 | } | ||||
491 | |||||
492 | |||||
493 | sub _sasl_continue { | ||||
494 | my ( $self, $payload, $conv_id ) = @_; | ||||
495 | |||||
496 | # warn "SASL continue, payload = [$payload], conv ID = [$conv_id]"; | ||||
497 | |||||
498 | my $res = $self->get_database( '$external' )->run_command( [ | ||||
499 | saslContinue => 1, | ||||
500 | conversationId => $conv_id, | ||||
501 | payload => $payload | ||||
502 | ] ); | ||||
503 | |||||
504 | $self->_sasl_check( $res ); | ||||
505 | return $res; | ||||
506 | } | ||||
507 | |||||
508 | |||||
509 | sub _sasl_plain_authenticate { | ||||
510 | my ( $self ) = @_; | ||||
511 | |||||
512 | my $username = defined $self->username ? $self->username : ""; | ||||
513 | my $password = defined $self->password ? $self->password : ""; | ||||
514 | |||||
515 | my $auth_bytes = encode( "UTF-8", "\x00" . $username . "\x00" . $password ); | ||||
516 | my $payload = MongoDB::BSON::Binary->new( data => $auth_bytes ); | ||||
517 | |||||
518 | $self->_sasl_start( $payload, "PLAIN" ); | ||||
519 | } | ||||
520 | |||||
521 | 1 | 3µs | 2 | 17.0ms | __PACKAGE__->meta->make_immutable( inline_destructor => 0 ); # spent 17.0ms making 1 call to Class::MOP::Class::make_immutable
# spent 15µs making 1 call to MongoDB::MongoClient::meta |
522 | |||||
523 | 1 | 29µs | 1; | ||
524 | |||||
525 | __END__ | ||||
# spent 7µs within MongoDB::MongoClient::CORE:match which was called 3 times, avg 2µs/call:
# once (4µs+0s) by MongoDB::MongoClient::BUILD at line 196
# once (2µs+0s) by MongoDB::MongoClient::__ANON__[/usr/local/lib/perl/5.14.2/MongoDB/MongoClient.pm:148] at line 148
# once (1µs+0s) by MongoDB::MongoClient::BUILD at line 213 | |||||
# spent 32µs (25+7) within MongoDB::MongoClient::_init_conn which was called:
# once (25µs+7µs) by MongoDB::MongoClient::BUILD at line 226 | |||||
# spent 398µs (381+18) within MongoDB::MongoClient::connect which was called:
# once (381µs+18µs) by MongoDB::MongoClient::BUILD at line 228 | |||||
# spent 13.4s (13.4+54µs) within MongoDB::MongoClient::recv which was called 4 times, avg 3.35s/call:
# 4 times (13.4s+54µs) by MongoDB::Cursor::_do_query at line 160 of MongoDB/Cursor.pm, avg 3.35s/call | |||||
# spent 75µs within MongoDB::MongoClient::send which was called 4 times, avg 19µs/call:
# 4 times (75µs+0s) by MongoDB::Cursor::_do_query at line 159 of MongoDB/Cursor.pm, avg 19µs/call |