animehunter-mongo 0.9
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/README.rdoc +311 -0
- data/Rakefile +62 -0
- data/bin/bson_benchmark.rb +59 -0
- data/bin/mongo_console +21 -0
- data/bin/run_test_script +19 -0
- data/bin/standard_benchmark +109 -0
- data/examples/admin.rb +41 -0
- data/examples/benchmarks.rb +42 -0
- data/examples/blog.rb +76 -0
- data/examples/capped.rb +23 -0
- data/examples/cursor.rb +47 -0
- data/examples/gridfs.rb +87 -0
- data/examples/index_test.rb +125 -0
- data/examples/info.rb +30 -0
- data/examples/queries.rb +69 -0
- data/examples/simple.rb +23 -0
- data/examples/strict.rb +34 -0
- data/examples/types.rb +40 -0
- data/lib/mongo.rb +19 -0
- data/lib/mongo/admin.rb +87 -0
- data/lib/mongo/collection.rb +235 -0
- data/lib/mongo/cursor.rb +227 -0
- data/lib/mongo/db.rb +538 -0
- data/lib/mongo/gridfs.rb +16 -0
- data/lib/mongo/gridfs/chunk.rb +96 -0
- data/lib/mongo/gridfs/grid_store.rb +468 -0
- data/lib/mongo/message.rb +20 -0
- data/lib/mongo/message/get_more_message.rb +37 -0
- data/lib/mongo/message/insert_message.rb +35 -0
- data/lib/mongo/message/kill_cursors_message.rb +36 -0
- data/lib/mongo/message/message.rb +84 -0
- data/lib/mongo/message/message_header.rb +50 -0
- data/lib/mongo/message/msg_message.rb +33 -0
- data/lib/mongo/message/opcodes.rb +32 -0
- data/lib/mongo/message/query_message.rb +77 -0
- data/lib/mongo/message/remove_message.rb +36 -0
- data/lib/mongo/message/update_message.rb +37 -0
- data/lib/mongo/mongo.rb +164 -0
- data/lib/mongo/query.rb +119 -0
- data/lib/mongo/types/binary.rb +42 -0
- data/lib/mongo/types/code.rb +34 -0
- data/lib/mongo/types/dbref.rb +37 -0
- data/lib/mongo/types/objectid.rb +137 -0
- data/lib/mongo/types/regexp_of_holding.rb +44 -0
- data/lib/mongo/types/undefined.rb +31 -0
- data/lib/mongo/util/bson.rb +534 -0
- data/lib/mongo/util/byte_buffer.rb +167 -0
- data/lib/mongo/util/ordered_hash.rb +96 -0
- data/lib/mongo/util/xml_to_ruby.rb +107 -0
- data/mongo-ruby-driver.gemspec +99 -0
- data/tests/mongo-qa/_common.rb +8 -0
- data/tests/mongo-qa/admin +26 -0
- data/tests/mongo-qa/capped +22 -0
- data/tests/mongo-qa/count1 +18 -0
- data/tests/mongo-qa/dbs +22 -0
- data/tests/mongo-qa/find +10 -0
- data/tests/mongo-qa/find1 +15 -0
- data/tests/mongo-qa/gridfs_in +16 -0
- data/tests/mongo-qa/gridfs_out +17 -0
- data/tests/mongo-qa/indices +49 -0
- data/tests/mongo-qa/remove +25 -0
- data/tests/mongo-qa/stress1 +35 -0
- data/tests/mongo-qa/test1 +11 -0
- data/tests/mongo-qa/update +18 -0
- data/tests/test_admin.rb +69 -0
- data/tests/test_bson.rb +246 -0
- data/tests/test_byte_buffer.rb +69 -0
- data/tests/test_chunk.rb +84 -0
- data/tests/test_cursor.rb +121 -0
- data/tests/test_db.rb +160 -0
- data/tests/test_db_api.rb +701 -0
- data/tests/test_db_connection.rb +18 -0
- data/tests/test_grid_store.rb +284 -0
- data/tests/test_message.rb +35 -0
- data/tests/test_mongo.rb +78 -0
- data/tests/test_objectid.rb +98 -0
- data/tests/test_ordered_hash.rb +129 -0
- data/tests/test_round_trip.rb +116 -0
- metadata +133 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# --
|
|
2
|
+
# Copyright (C) 2008-2009 10gen 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
|
+
require 'mongo/message/message'
|
|
18
|
+
require 'mongo/message/opcodes'
|
|
19
|
+
|
|
20
|
+
module XGen
|
|
21
|
+
module Mongo
|
|
22
|
+
module Driver
|
|
23
|
+
|
|
24
|
+
class UpdateMessage < Message
|
|
25
|
+
|
|
26
|
+
def initialize(db_name, collection_name, sel, obj, repsert)
|
|
27
|
+
super(OP_UPDATE)
|
|
28
|
+
write_int(0)
|
|
29
|
+
write_string("#{db_name}.#{collection_name}")
|
|
30
|
+
write_int(repsert ? 1 : 0) # 1 if a repsert operation (upsert)
|
|
31
|
+
write_doc(sel)
|
|
32
|
+
write_doc(obj)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
data/lib/mongo/mongo.rb
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# --
|
|
2
|
+
# Copyright (C) 2008-2009 10gen 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
|
+
require 'mongo/db'
|
|
18
|
+
|
|
19
|
+
module XGen
|
|
20
|
+
module Mongo
|
|
21
|
+
module Driver
|
|
22
|
+
|
|
23
|
+
# Represents a Mongo database server.
|
|
24
|
+
class Mongo
|
|
25
|
+
|
|
26
|
+
DEFAULT_PORT = 27017
|
|
27
|
+
|
|
28
|
+
# Create a Mongo database server instance. You specify either one or a
|
|
29
|
+
# pair of servers. If one, you also say if connecting to a slave is
|
|
30
|
+
# OK. In either case, the host default is "localhost" and port default
|
|
31
|
+
# is DEFAULT_PORT.
|
|
32
|
+
#
|
|
33
|
+
# If you specify a pair, pair_or_host is a hash with two keys :left
|
|
34
|
+
# and :right. Each key maps to either
|
|
35
|
+
# * a server name, in which case port is DEFAULT_PORT
|
|
36
|
+
# * a port number, in which case server is "localhost"
|
|
37
|
+
# * an array containing a server name and a port number in that order
|
|
38
|
+
#
|
|
39
|
+
# +options+ are passed on to each DB instance:
|
|
40
|
+
#
|
|
41
|
+
# :slave_ok :: Only used if one host is specified. If false, when
|
|
42
|
+
# connecting to that host/port a DB object will check to
|
|
43
|
+
# see if the server is the master. If it is not, an error
|
|
44
|
+
# is thrown.
|
|
45
|
+
#
|
|
46
|
+
# :auto_reconnect :: If a DB connection gets closed (for example, we
|
|
47
|
+
# have a server pair and saw the "not master"
|
|
48
|
+
# error, which closes the connection), then
|
|
49
|
+
# automatically try to reconnect to the master or
|
|
50
|
+
# to the single server we have been given. Defaults
|
|
51
|
+
# to +false+.
|
|
52
|
+
#
|
|
53
|
+
# Since that's so confusing, here are a few examples:
|
|
54
|
+
#
|
|
55
|
+
# Mongo.new # localhost, DEFAULT_PORT, !slave
|
|
56
|
+
# Mongo.new("localhost") # localhost, DEFAULT_PORT, !slave
|
|
57
|
+
# Mongo.new("localhost", 3000) # localhost, 3000, slave not ok
|
|
58
|
+
# # localhost, 3000, slave ok
|
|
59
|
+
# Mongo.new("localhost", 3000, :slave_ok => true)
|
|
60
|
+
# # localhost, DEFAULT_PORT, auto reconnect
|
|
61
|
+
# Mongo.new(nil, nil, :auto_reconnect => true)
|
|
62
|
+
#
|
|
63
|
+
# # A pair of servers. DB will always talk to the master. On socket
|
|
64
|
+
# # error or "not master" error, we will auto-reconnect to the
|
|
65
|
+
# # current master.
|
|
66
|
+
# Mongo.new({:left => ["db1.example.com", 3000],
|
|
67
|
+
# :right => "db2.example.com"}, # DEFAULT_PORT
|
|
68
|
+
# nil, :auto_reconnect => true)
|
|
69
|
+
#
|
|
70
|
+
# # Here, :right is localhost/DEFAULT_PORT. No auto-reconnect.
|
|
71
|
+
# Mongo.new({:left => ["db1.example.com", 3000]})
|
|
72
|
+
#
|
|
73
|
+
# When a DB object first connects to a pair, it will find the master
|
|
74
|
+
# instance and connect to that one.
|
|
75
|
+
def initialize(pair_or_host=nil, port=nil, options={})
|
|
76
|
+
@pair = case pair_or_host
|
|
77
|
+
when String
|
|
78
|
+
[[pair_or_host, port ? port.to_i : DEFAULT_PORT]]
|
|
79
|
+
when Hash
|
|
80
|
+
connections = []
|
|
81
|
+
connections << pair_val_to_connection(pair_or_host[:left])
|
|
82
|
+
connections << pair_val_to_connection(pair_or_host[:right])
|
|
83
|
+
connections
|
|
84
|
+
when nil
|
|
85
|
+
[['localhost', DEFAULT_PORT]]
|
|
86
|
+
end
|
|
87
|
+
@options = options
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Return the XGen::Mongo::Driver::DB named +db_name+. The slave_ok and
|
|
91
|
+
# auto_reconnect options passed in via #new may be overridden here.
|
|
92
|
+
# See DB#new for other options you can pass in.
|
|
93
|
+
def db(db_name, options={})
|
|
94
|
+
XGen::Mongo::Driver::DB.new(db_name, @pair, @options.merge(options))
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Returns a hash containing database names as keys and disk space for
|
|
98
|
+
# each as values.
|
|
99
|
+
def database_info
|
|
100
|
+
doc = single_db_command('admin', :listDatabases => 1)
|
|
101
|
+
h = {}
|
|
102
|
+
doc['databases'].each { |db|
|
|
103
|
+
h[db['name']] = db['sizeOnDisk'].to_i
|
|
104
|
+
}
|
|
105
|
+
h
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Returns an array of database names.
|
|
109
|
+
def database_names
|
|
110
|
+
database_info.keys
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Not implemented.
|
|
114
|
+
def clone_database(from)
|
|
115
|
+
raise "not implemented"
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Not implemented.
|
|
119
|
+
def copy_database(from_host, from_db, to_db)
|
|
120
|
+
raise "not implemented"
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Drops the database +name+.
|
|
124
|
+
def drop_database(name)
|
|
125
|
+
single_db_command(name, :dropDatabase => 1)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
protected
|
|
129
|
+
|
|
130
|
+
# Turns an array containing a host name string and a
|
|
131
|
+
# port number integer into a [host, port] pair array.
|
|
132
|
+
def pair_val_to_connection(a)
|
|
133
|
+
case a
|
|
134
|
+
when nil
|
|
135
|
+
['localhost', DEFAULT_PORT]
|
|
136
|
+
when String
|
|
137
|
+
[a, DEFAULT_PORT]
|
|
138
|
+
when Integer
|
|
139
|
+
['localhost', a]
|
|
140
|
+
when Array
|
|
141
|
+
a
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# Send cmd (a hash, possibly ordered) to the admin database and return
|
|
146
|
+
# the answer. Raises an error unless the return is "ok" (DB#ok?
|
|
147
|
+
# returns +true+).
|
|
148
|
+
def single_db_command(db_name, cmd)
|
|
149
|
+
db = nil
|
|
150
|
+
begin
|
|
151
|
+
db = db(db_name)
|
|
152
|
+
doc = db.db_command(cmd)
|
|
153
|
+
raise "error retrieving database info: #{doc.inspect}" unless db.ok?(doc)
|
|
154
|
+
doc
|
|
155
|
+
ensure
|
|
156
|
+
db.close if db
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
data/lib/mongo/query.rb
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# --
|
|
2
|
+
# Copyright (C) 2008-2009 10gen 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
|
+
require 'mongo/collection'
|
|
18
|
+
require 'mongo/message'
|
|
19
|
+
require 'mongo/types/code'
|
|
20
|
+
|
|
21
|
+
module XGen
|
|
22
|
+
module Mongo
|
|
23
|
+
module Driver
|
|
24
|
+
|
|
25
|
+
# A query against a collection. A query's selector is a hash. See the
|
|
26
|
+
# Mongo documentation for query details.
|
|
27
|
+
class Query
|
|
28
|
+
|
|
29
|
+
attr_accessor :number_to_skip, :number_to_return, :order_by
|
|
30
|
+
# If true, $explain will be set in QueryMessage that uses this query.
|
|
31
|
+
attr_accessor :explain
|
|
32
|
+
# Either +nil+ or a hash (preferably an OrderedHash).
|
|
33
|
+
attr_accessor :hint
|
|
34
|
+
attr_reader :selector # writer defined below
|
|
35
|
+
|
|
36
|
+
# sel :: A hash describing the query. See the Mongo docs for details.
|
|
37
|
+
#
|
|
38
|
+
# return_fields :: If not +nil+, a single field name or an array of
|
|
39
|
+
# field names. Only those fields will be returned.
|
|
40
|
+
# (Called :fields in calls to Collection#find.)
|
|
41
|
+
#
|
|
42
|
+
# number_to_skip :: Number of records to skip before returning
|
|
43
|
+
# records. (Called :offset in calls to
|
|
44
|
+
# Collection#find.) Default is 0.
|
|
45
|
+
#
|
|
46
|
+
# number_to_return :: Max number of records to return. (Called :limit
|
|
47
|
+
# in calls to Collection#find.) Default is 0 (all
|
|
48
|
+
# records).
|
|
49
|
+
#
|
|
50
|
+
# order_by :: If not +nil+, specifies record sort order. May be a
|
|
51
|
+
# String, Hash, OrderedHash, or Array. If a string, the
|
|
52
|
+
# results will be ordered by that field in ascending
|
|
53
|
+
# order. If an array, it should be an array of field names
|
|
54
|
+
# which will all be sorted in ascending order. If a hash,
|
|
55
|
+
# it may be either a regular Hash or an OrderedHash. The
|
|
56
|
+
# keys should be field names, and the values should be 1
|
|
57
|
+
# (ascending) or -1 (descending). Note that if it is a
|
|
58
|
+
# regular Hash then sorting by more than one field
|
|
59
|
+
# probably will not be what you intend because key order
|
|
60
|
+
# is not preserved. (order_by is called :sort in calls to
|
|
61
|
+
# Collection#find.)
|
|
62
|
+
#
|
|
63
|
+
# hint :: If not +nil+, specifies query hint fields. Must be either
|
|
64
|
+
# +nil+ or a hash (preferably an OrderedHash). See
|
|
65
|
+
# Collection#hint.
|
|
66
|
+
def initialize(sel={}, return_fields=nil, number_to_skip=0, number_to_return=0, order_by=nil, hint=nil)
|
|
67
|
+
@number_to_skip, @number_to_return, @order_by, @hint =
|
|
68
|
+
number_to_skip, number_to_return, order_by, hint
|
|
69
|
+
@explain = nil
|
|
70
|
+
self.selector = sel
|
|
71
|
+
self.fields = return_fields
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Set query selector hash. If sel is Code/string, it will be used as a
|
|
75
|
+
# $where clause. (See Mongo docs for details.)
|
|
76
|
+
def selector=(sel)
|
|
77
|
+
@selector = case sel
|
|
78
|
+
when nil
|
|
79
|
+
{}
|
|
80
|
+
when Code
|
|
81
|
+
{"$where" => sel}
|
|
82
|
+
when String
|
|
83
|
+
{"$where" => Code.new(sel)}
|
|
84
|
+
when Hash
|
|
85
|
+
sel
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Set fields to return. If +val+ is +nil+ or empty, all fields will be
|
|
90
|
+
# returned.
|
|
91
|
+
def fields=(val)
|
|
92
|
+
@fields = val
|
|
93
|
+
@fields = nil if @fields && @fields.empty?
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def fields
|
|
97
|
+
case @fields
|
|
98
|
+
when String
|
|
99
|
+
{@fields => 1}
|
|
100
|
+
when Array
|
|
101
|
+
if @fields.length == 0
|
|
102
|
+
nil
|
|
103
|
+
else
|
|
104
|
+
h = {}
|
|
105
|
+
@fields.each { |field| h[field] = 1 }
|
|
106
|
+
h
|
|
107
|
+
end
|
|
108
|
+
else # nil, anything else
|
|
109
|
+
nil
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def contains_special_fields
|
|
114
|
+
(@order_by != nil && @order_by.length > 0) || @explain || @hint
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# --
|
|
2
|
+
# Copyright (C) 2008-2009 10gen 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
|
+
require 'mongo/util/byte_buffer'
|
|
18
|
+
|
|
19
|
+
module XGen
|
|
20
|
+
module Mongo
|
|
21
|
+
module Driver
|
|
22
|
+
|
|
23
|
+
# An array of binary bytes with a Mongo subtype value.
|
|
24
|
+
class Binary < ByteBuffer
|
|
25
|
+
|
|
26
|
+
SUBTYPE_BYTES = 0x02
|
|
27
|
+
SUBTYPE_UUID = 0x03
|
|
28
|
+
SUBTYPE_MD5 = 0x05
|
|
29
|
+
SUBTYPE_USER_DEFINED = 0x80
|
|
30
|
+
|
|
31
|
+
# One of the SUBTYPE_* constants. Default is SUBTYPE_BYTES.
|
|
32
|
+
attr_accessor :subtype
|
|
33
|
+
|
|
34
|
+
def initialize(initial_data=[], subtype=SUBTYPE_BYTES)
|
|
35
|
+
super(initial_data)
|
|
36
|
+
@subtype = subtype
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# --
|
|
2
|
+
# Copyright (C) 2008-2009 10gen 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
|
+
module XGen
|
|
18
|
+
module Mongo
|
|
19
|
+
module Driver
|
|
20
|
+
|
|
21
|
+
# JavaScript code to be evaluated by MongoDB
|
|
22
|
+
class Code < String
|
|
23
|
+
# Hash mapping identifiers to their values
|
|
24
|
+
attr_accessor :scope
|
|
25
|
+
|
|
26
|
+
def initialize(code, scope={})
|
|
27
|
+
super(code)
|
|
28
|
+
@scope = scope
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# --
|
|
2
|
+
# Copyright (C) 2008-2009 10gen 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
|
+
module XGen
|
|
18
|
+
module Mongo
|
|
19
|
+
module Driver
|
|
20
|
+
|
|
21
|
+
class DBRef
|
|
22
|
+
|
|
23
|
+
attr_reader :namespace, :object_id
|
|
24
|
+
|
|
25
|
+
def initialize(namespace, object_id)
|
|
26
|
+
@namespace, @object_id =
|
|
27
|
+
namespace, object_id
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def to_s
|
|
31
|
+
"ns: #{namespace}, id: #{object_id}"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# --
|
|
2
|
+
# Copyright (C) 2008-2009 10gen 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
|
+
require 'mutex_m'
|
|
18
|
+
require 'mongo/util/byte_buffer'
|
|
19
|
+
|
|
20
|
+
module XGen
|
|
21
|
+
module Mongo
|
|
22
|
+
module Driver
|
|
23
|
+
|
|
24
|
+
# Implementation of the Babble OID. Object ids are not required by
|
|
25
|
+
# Mongo, but they make certain operations more efficient.
|
|
26
|
+
#
|
|
27
|
+
# The driver does not automatically assign ids to records that are
|
|
28
|
+
# inserted. (An upcoming feature will allow you to give an id "factory"
|
|
29
|
+
# to a database and/or a collection.)
|
|
30
|
+
#
|
|
31
|
+
# 12 bytes
|
|
32
|
+
# ---
|
|
33
|
+
# 0 time
|
|
34
|
+
# 1
|
|
35
|
+
# 2
|
|
36
|
+
# 3
|
|
37
|
+
# 4 machine
|
|
38
|
+
# 5
|
|
39
|
+
# 6
|
|
40
|
+
# 7 pid
|
|
41
|
+
# 8
|
|
42
|
+
# 9 inc
|
|
43
|
+
# 10
|
|
44
|
+
# 11
|
|
45
|
+
class ObjectID
|
|
46
|
+
|
|
47
|
+
MACHINE = ( val = rand(0x1000000); [val & 0xff, (val >> 8) & 0xff, (val >> 16) & 0xff] )
|
|
48
|
+
PID = ( val = rand(0x10000); [val & 0xff, (val >> 8) & 0xff]; )
|
|
49
|
+
|
|
50
|
+
# The string representation of an OID is different than its internal
|
|
51
|
+
# and BSON byte representations. The BYTE_ORDER here maps
|
|
52
|
+
# internal/BSON byte position (the index in BYTE_ORDER) to the
|
|
53
|
+
# position of the two hex characters representing that byte in the
|
|
54
|
+
# string representation. For example, the 0th BSON byte corresponds to
|
|
55
|
+
# the (0-based) 7th pair of hex chars in the string.
|
|
56
|
+
BYTE_ORDER = [7, 6, 5, 4, 3, 2, 1, 0, 11, 10, 9, 8]
|
|
57
|
+
|
|
58
|
+
LOCK = Object.new
|
|
59
|
+
LOCK.extend Mutex_m
|
|
60
|
+
|
|
61
|
+
@@index_time = Time.new.to_i
|
|
62
|
+
@@index = 0
|
|
63
|
+
|
|
64
|
+
# Given a string representation of an ObjectID, return a new ObjectID
|
|
65
|
+
# with that value.
|
|
66
|
+
def self.from_string(str)
|
|
67
|
+
raise "illegal ObjectID format" unless legal?(str)
|
|
68
|
+
data = []
|
|
69
|
+
BYTE_ORDER.each_with_index { |string_position, data_index|
|
|
70
|
+
data[data_index] = str[string_position * 2, 2].to_i(16)
|
|
71
|
+
}
|
|
72
|
+
self.new(data)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def self.legal?(str)
|
|
76
|
+
len = BYTE_ORDER.length * 2
|
|
77
|
+
str =~ /([0-9a-f]+)/i
|
|
78
|
+
match = $1
|
|
79
|
+
str && str.length == len && match == str
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# +data+ is an array of bytes. If nil, a new id will be generated.
|
|
83
|
+
# The time +t+ is only used for testing; leave it nil.
|
|
84
|
+
def initialize(data=nil, t=nil)
|
|
85
|
+
@data = data || generate_id(t)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def eql?(other)
|
|
89
|
+
@data == other.instance_variable_get("@data")
|
|
90
|
+
end
|
|
91
|
+
alias_method :==, :eql?
|
|
92
|
+
|
|
93
|
+
def to_a
|
|
94
|
+
@data.dup
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def to_s
|
|
98
|
+
str = ' ' * 24
|
|
99
|
+
BYTE_ORDER.each_with_index { |string_position, data_index|
|
|
100
|
+
str[string_position * 2, 2] = '%02x' % @data[data_index]
|
|
101
|
+
}
|
|
102
|
+
str
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# (Would normally be private, but isn't so we can test it.)
|
|
106
|
+
def generate_id(t=nil)
|
|
107
|
+
t ||= Time.new.to_i
|
|
108
|
+
buf = ByteBuffer.new
|
|
109
|
+
buf.put_int(t & 0xffffffff)
|
|
110
|
+
buf.put_array(MACHINE)
|
|
111
|
+
buf.put_array(PID)
|
|
112
|
+
i = index_for_time(t)
|
|
113
|
+
buf.put(i & 0xff)
|
|
114
|
+
buf.put((i >> 8) & 0xff)
|
|
115
|
+
buf.put((i >> 16) & 0xff)
|
|
116
|
+
|
|
117
|
+
buf.rewind
|
|
118
|
+
buf.to_a.dup
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# (Would normally be private, but isn't so we can test it.)
|
|
122
|
+
def index_for_time(t)
|
|
123
|
+
LOCK.mu_synchronize {
|
|
124
|
+
if t != @@index_time
|
|
125
|
+
@@index = 0
|
|
126
|
+
@@index_time = t
|
|
127
|
+
end
|
|
128
|
+
retval = @@index
|
|
129
|
+
@@index += 1
|
|
130
|
+
retval
|
|
131
|
+
}
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|