mongo 0.18.3 → 0.19

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.
Files changed (62) hide show
  1. data/README.rdoc +41 -50
  2. data/Rakefile +14 -4
  3. data/examples/gridfs.rb +25 -70
  4. data/lib/mongo.rb +4 -2
  5. data/lib/mongo/collection.rb +70 -89
  6. data/lib/mongo/connection.rb +203 -43
  7. data/lib/mongo/cursor.rb +7 -7
  8. data/lib/mongo/db.rb +61 -18
  9. data/lib/mongo/exceptions.rb +7 -1
  10. data/lib/mongo/gridfs.rb +8 -1
  11. data/lib/mongo/gridfs/chunk.rb +2 -1
  12. data/lib/mongo/gridfs/grid.rb +90 -0
  13. data/lib/mongo/gridfs/grid_file_system.rb +113 -0
  14. data/lib/mongo/gridfs/grid_io.rb +339 -0
  15. data/lib/mongo/gridfs/grid_store.rb +43 -18
  16. data/lib/mongo/types/binary.rb +5 -1
  17. data/lib/mongo/types/code.rb +1 -1
  18. data/lib/mongo/types/dbref.rb +3 -1
  19. data/lib/mongo/types/min_max_keys.rb +1 -1
  20. data/lib/mongo/types/objectid.rb +16 -55
  21. data/lib/mongo/types/regexp_of_holding.rb +1 -1
  22. data/lib/mongo/util/bson_c.rb +2 -2
  23. data/lib/mongo/util/bson_ruby.rb +22 -11
  24. data/lib/mongo/util/byte_buffer.rb +1 -1
  25. data/lib/mongo/util/conversions.rb +1 -1
  26. data/lib/mongo/util/ordered_hash.rb +6 -1
  27. data/lib/mongo/util/server_version.rb +1 -1
  28. data/lib/mongo/util/support.rb +1 -1
  29. data/mongo-ruby-driver.gemspec +1 -1
  30. data/test/auxillary/authentication_test.rb +68 -0
  31. data/test/auxillary/autoreconnect_test.rb +41 -0
  32. data/test/binary_test.rb +15 -0
  33. data/test/{test_bson.rb → bson_test.rb} +63 -6
  34. data/test/{test_byte_buffer.rb → byte_buffer_test.rb} +0 -0
  35. data/test/{test_chunk.rb → chunk_test.rb} +0 -0
  36. data/test/{test_collection.rb → collection_test.rb} +35 -39
  37. data/test/{test_connection.rb → connection_test.rb} +33 -3
  38. data/test/{test_conversions.rb → conversions_test.rb} +0 -0
  39. data/test/{test_cursor.rb → cursor_test.rb} +0 -7
  40. data/test/{test_db_api.rb → db_api_test.rb} +3 -6
  41. data/test/{test_db_connection.rb → db_connection_test.rb} +0 -0
  42. data/test/{test_db.rb → db_test.rb} +33 -15
  43. data/test/grid_file_system_test.rb +210 -0
  44. data/test/grid_io_test.rb +78 -0
  45. data/test/{test_grid_store.rb → grid_store_test.rb} +33 -2
  46. data/test/grid_test.rb +87 -0
  47. data/test/{test_objectid.rb → objectid_test.rb} +2 -33
  48. data/test/{test_ordered_hash.rb → ordered_hash_test.rb} +4 -0
  49. data/test/{test_slave_connection.rb → slave_connection_test.rb} +0 -0
  50. data/test/test_helper.rb +2 -2
  51. data/test/{test_threading.rb → threading_test.rb} +0 -0
  52. data/test/unit/collection_test.rb +12 -3
  53. data/test/unit/connection_test.rb +85 -24
  54. data/test/unit/cursor_test.rb +1 -2
  55. data/test/unit/db_test.rb +70 -69
  56. metadata +27 -23
  57. data/bin/objectid_benchmark.rb +0 -23
  58. data/bin/perf.rb +0 -30
  59. data/lib/mongo/admin.rb +0 -95
  60. data/lib/mongo/util/xml_to_ruby.rb +0 -112
  61. data/test/test_admin.rb +0 -67
  62. data/test/test_round_trip.rb +0 -114
@@ -1,5 +1,5 @@
1
1
  # --
2
- # Copyright (C) 2008-2009 10gen Inc.
2
+ # Copyright (C) 2008-2010 10gen Inc.
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
5
5
  # you may not use this file except in compliance with the License.
@@ -46,12 +46,16 @@ module GridFS
46
46
  # GridStore.open(database, 'filename', 'r') do |f|
47
47
  # puts f.read
48
48
  # end
49
+ #
50
+ # @deprecated
49
51
  class GridStore
52
+ include Enumerable
50
53
 
51
54
  DEFAULT_ROOT_COLLECTION = 'fs'
55
+
52
56
  DEFAULT_CONTENT_TYPE = 'text/plain'
53
57
 
54
- include Enumerable
58
+ DEPRECATION_WARNING = "GridFS::GridStore is deprecated. Use either Grid or GridFileSystem."
55
59
 
56
60
  attr_accessor :filename
57
61
 
@@ -77,6 +81,14 @@ module GridFS
77
81
 
78
82
  attr_reader :md5
79
83
 
84
+ def self.default_root_collection
85
+ @@default_root_collection ||= DEFAULT_ROOT_COLLECTION
86
+ end
87
+
88
+ def self.default_root_collection=(name)
89
+ @@default_root_collection = name
90
+ end
91
+
80
92
  # Determine whether a given file exists in the GridStore.
81
93
  #
82
94
  # @param [Mongo::DB] a MongoDB database.
@@ -84,7 +96,9 @@ module GridFS
84
96
  # @param [String] root_collection the name of the gridfs root collection.
85
97
  #
86
98
  # @return [Boolean]
87
- def self.exist?(db, name, root_collection=DEFAULT_ROOT_COLLECTION)
99
+ # @deprecated
100
+ def self.exist?(db, name, root_collection=GridStore.default_root_collection)
101
+ warn DEPRECATION_WARNING
88
102
  db.collection("#{root_collection}.files").find({'filename' => name}).next_document != nil
89
103
  end
90
104
 
@@ -93,13 +107,14 @@ module GridFS
93
107
  #
94
108
  # @param [Mongo::DB] a MongoDB database.
95
109
  # @param [String] name the filename.
96
- # @param [String] mode one of 'r', 'w', or 'w+' for reading, writing,
110
+ # @param [String] mode one of 'r', 'w', or 'w+' for reading, writing,
97
111
  # and appending, respectively.
98
- # @param [Hash] options any of the options available on
112
+ # @param [Hash] options any of the options available on
99
113
  # GridStore initialization.
100
114
  #
101
115
  # @see GridStore#initialize.
102
116
  # @see The various GridStore class methods, e.g., GridStore.open, GridStore.read etc.
117
+ # @deprecated
103
118
  def self.open(db, name, mode, options={})
104
119
  gs = self.new(db, name, mode, options)
105
120
  result = nil
@@ -120,6 +135,7 @@ module GridFS
120
135
  # beginning of the file to start reading.
121
136
  #
122
137
  # @return [String] the file data
138
+ # @deprecated
123
139
  def self.read(db, name, length=nil, offset=nil)
124
140
  GridStore.open(db, name, 'r') do |gs|
125
141
  gs.seek(offset) if offset
@@ -134,13 +150,15 @@ module GridFS
134
150
  # @param [String] root_collection the name of the root collection.
135
151
  #
136
152
  # @return [Array]
137
- def self.list(db, root_collection=DEFAULT_ROOT_COLLECTION)
153
+ # @deprecated
154
+ def self.list(db, root_collection=GridStore.default_root_collection)
155
+ warn DEPRECATION_WARNING
138
156
  db.collection("#{root_collection}.files").find().map do |f|
139
157
  f['filename']
140
158
  end
141
159
  end
142
160
 
143
- # Get each line of data from the specified file
161
+ # Get each line of data from the specified file
144
162
  # as an array of strings.
145
163
  #
146
164
  # @param [Mongo::DB] db a MongoDB database.
@@ -148,6 +166,7 @@ module GridFS
148
166
  # @param [String, Reg] separator
149
167
  #
150
168
  # @return [Array]
169
+ # @deprecated
151
170
  def self.readlines(db, name, separator=$/)
152
171
  GridStore.open(db, name, 'r') do |gs|
153
172
  gs.readlines(separator)
@@ -160,10 +179,11 @@ module GridFS
160
179
  # @param [Array<String>] names the filenames to remove
161
180
  #
162
181
  # @return [True]
182
+ # @deprecated
163
183
  def self.unlink(db, *names)
164
184
  names.each do |name|
165
185
  gs = GridStore.new(db, name)
166
- gs.send(:delete_chunks)
186
+ gs.delete_chunks
167
187
  gs.collection.remove('_id' => gs.files_id)
168
188
  end
169
189
  end
@@ -172,13 +192,16 @@ module GridFS
172
192
  end
173
193
 
174
194
  # Rename a file in this collection. Note that this method uses
175
- # Collection#update, which means that you will not be notified
195
+ # Collection#update, which means that you will not be notified of the
196
+ # success of the operation.
176
197
  #
177
198
  # @param [Mongo::DB] a MongoDB database.
178
199
  # @param [String] src the name of the source file.
179
200
  # @param [String] dest the name of the destination file.
180
201
  # @param [String] root_collection the name of the default root collection.
181
- def self.mv(db, src, dest, root_collection=DEFAULT_ROOT_COLLECTION)
202
+ # @deprecated
203
+ def self.mv(db, src, dest, root_collection=GridStore.default_root_collection)
204
+ warn DEPRECATION_WARNING
182
205
  db.collection("#{root_collection}.files").update({ :filename => src }, { '$set' => { :filename => dest } })
183
206
  end
184
207
 
@@ -197,11 +220,13 @@ module GridFS
197
220
  # @option options [Integer] :chunk_size (Chunk::DEFAULT_CHUNK_SIZE) (w) Sets chunk size for files opened for writing.
198
221
  # See also GridStore#chunk_size=.
199
222
  #
200
- # @option options [String] :content_type ('text/plain') Set the content type stored as the
223
+ # @option options [String] :content_type ('text/plain') Set the content type stored as the
201
224
  # file's metadata. See also GridStore#content_type=.
225
+ # @deprecated
202
226
  def initialize(db, name, mode='r', options={})
227
+ warn DEPRECATION_WARNING
203
228
  @db, @filename, @mode = db, name, mode
204
- @root = options[:root] || DEFAULT_ROOT_COLLECTION
229
+ @root = options[:root] || GridStore.default_root_collection
205
230
 
206
231
  doc = collection.find({'filename' => @filename}).next_document
207
232
  if doc
@@ -488,6 +513,11 @@ module GridFS
488
513
  @db == nil
489
514
  end
490
515
 
516
+ def delete_chunks
517
+ chunk_collection.remove({'files_id' => @files_id}) if @files_id
518
+ @curr_chunk = nil
519
+ end
520
+
491
521
  #---
492
522
  # ================ protected ================
493
523
  #+++
@@ -537,12 +567,7 @@ module GridFS
537
567
  buf
538
568
  end
539
569
 
540
- def delete_chunks
541
- chunk_collection.remove({'files_id' => @files_id}) if @files_id
542
- @curr_chunk = nil
543
- end
544
-
545
- def nth_chunk(n)
570
+ def nth_chunk(n)
546
571
  mongo_chunk = chunk_collection.find({'files_id' => @files_id, 'n' => n}).next_document
547
572
  Chunk.new(self, mongo_chunk || {})
548
573
  end
@@ -1,5 +1,5 @@
1
1
  # --
2
- # Copyright (C) 2008-2009 10gen Inc.
2
+ # Copyright (C) 2008-2010 10gen Inc.
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
5
5
  # you may not use this file except in compliance with the License.
@@ -44,5 +44,9 @@ module Mongo
44
44
  @subtype = subtype
45
45
  end
46
46
 
47
+ def inspect
48
+ "<Mongo::Binary:#{object_id}>"
49
+ end
50
+
47
51
  end
48
52
  end
@@ -1,5 +1,5 @@
1
1
  # --
2
- # Copyright (C) 2008-2009 10gen Inc.
2
+ # Copyright (C) 2008-2010 10gen Inc.
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
5
5
  # you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
1
1
  # --
2
- # Copyright (C) 2008-2009 10gen Inc.
2
+ # Copyright (C) 2008-2010 10gen Inc.
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
5
5
  # you may not use this file except in compliance with the License.
@@ -25,6 +25,8 @@ module Mongo
25
25
  #
26
26
  # @param [String] a collection name
27
27
  # @param [ObjectID] an object id
28
+ #
29
+ # @core dbrefs constructor_details
28
30
  def initialize(namespace, object_id)
29
31
  @namespace = namespace
30
32
  @object_id = object_id
@@ -1,5 +1,5 @@
1
1
  # --
2
- # Copyright (C) 2008-2009 10gen Inc.
2
+ # Copyright (C) 2008-2010 10gen Inc.
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
5
5
  # you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
1
1
  # --
2
- # Copyright (C) 2008-2009 10gen Inc.
2
+ # Copyright (C) 2008-2010 10gen Inc.
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
5
5
  # you may not use this file except in compliance with the License.
@@ -20,21 +20,15 @@ require 'digest/md5'
20
20
 
21
21
  module Mongo
22
22
 
23
- # ObjectID class for documents in MongoDB.
23
+ # Generates MongoDB object ids.
24
+ #
25
+ # @core objectids
24
26
  class ObjectID
25
- # This is the legacy byte ordering for Babble. Versions of the Ruby
26
- # driver prior to 0.14 used this byte ordering when converting ObjectID
27
- # instances to and from strings. If you have string representations of
28
- # ObjectIDs using the legacy byte ordering make sure to use the
29
- # to_s_legacy and from_string_legacy methods, or convert your strings
30
- # with ObjectID#legacy_string_convert
31
- BYTE_ORDER = [7, 6, 5, 4, 3, 2, 1, 0, 11, 10, 9, 8]
32
-
33
27
  @@lock = Mutex.new
34
28
  @@index = 0
35
29
 
36
30
  # Create a new object id. If no parameter is given, an id corresponding
37
- # to the ObjectID BSON data type will be created. This is a 12-byte value
31
+ # to the ObjectID BSON data type will be created. This is a 12-byte value
38
32
  # consisting of a 4-byte timestamp, a 3-byte machine id, a 2-byte process id,
39
33
  # and a 3-byte counter.
40
34
  #
@@ -44,8 +38,14 @@ module Mongo
44
38
  @data = data || generate
45
39
  end
46
40
 
41
+ # Determine if the supplied string is legal. Legal strings will
42
+ # consist of 24 hexadecimal characters.
43
+ #
44
+ # @param [String] str
45
+ #
46
+ # @return [Boolean]
47
47
  def self.legal?(str)
48
- len = BYTE_ORDER.length * 2
48
+ len = 24
49
49
  str =~ /([0-9a-f]+)/i
50
50
  match = $1
51
51
  str && str.length == len && match == str
@@ -115,21 +115,6 @@ module Mongo
115
115
  self.new(data)
116
116
  end
117
117
 
118
- # @deprecated
119
- # Create a new ObjectID given a string representation of an ObjectID
120
- # using the legacy byte ordering. This method may eventually be
121
- # removed. If you are not sure that you need this method you should be
122
- # using the regular from_string.
123
- def self.from_string_legacy(str)
124
- warn "Support for legacy object ids has been DEPRECATED."
125
- raise InvalidObjectID, "illegal ObjectID format" unless legal?(str)
126
- data = []
127
- BYTE_ORDER.each_with_index { |string_position, data_index|
128
- data[data_index] = str[string_position * 2, 2].to_i(16)
129
- }
130
- self.new(data)
131
- end
132
-
133
118
  # Get a string representation of this object id.
134
119
  #
135
120
  # @return [String]
@@ -140,7 +125,10 @@ module Mongo
140
125
  end
141
126
  str
142
127
  end
143
- alias_method :inspect, :to_s
128
+
129
+ def inspect
130
+ "ObjectID('#{to_s}')"
131
+ end
144
132
 
145
133
  # Convert to MongoDB extended JSON format. Since JSON includes type information,
146
134
  # but lacks an ObjectID type, this JSON format encodes the type using an $id key.
@@ -150,33 +138,6 @@ module Mongo
150
138
  "{\"$oid\": \"#{to_s}\"}"
151
139
  end
152
140
 
153
- # @deprecated
154
- # Get a string representation of this ObjectID using the legacy byte
155
- # ordering. This method may eventually be removed. If you are not sure
156
- # that you need this method you should be using the regular to_s.
157
- def to_s_legacy
158
- warn "Support for legacy object ids has been DEPRECATED."
159
- str = ' ' * 24
160
- BYTE_ORDER.each_with_index { |string_position, data_index|
161
- str[string_position * 2, 2] = '%02x' % @data[data_index]
162
- }
163
- str
164
- end
165
-
166
- # @deprecated
167
- # Convert a string representation of an ObjectID using the legacy byte
168
- # ordering to the proper byte ordering. This method may eventually be
169
- # removed. If you are not sure that you need this method it is probably
170
- # unnecessary.
171
- def self.legacy_string_convert(str)
172
- warn "Support for legacy object ids has been DEPRECATED."
173
- legacy = ' ' * 24
174
- BYTE_ORDER.each_with_index do |legacy_pos, pos|
175
- legacy[legacy_pos * 2, 2] = str[pos * 2, 2]
176
- end
177
- legacy
178
- end
179
-
180
141
  # Return the UTC time at which this ObjectID was generated. This may
181
142
  # be used in lieu of a created_at timestamp since this information
182
143
  # is always encoded in the object id.
@@ -1,5 +1,5 @@
1
1
  # --
2
- # Copyright (C) 2008-2009 10gen Inc.
2
+ # Copyright (C) 2008-2010 10gen Inc.
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
5
5
  # you may not use this file except in compliance with the License.
@@ -1,8 +1,8 @@
1
1
  # A thin wrapper for the CBson class
2
2
  class BSON_C
3
3
 
4
- def self.serialize(obj, check_keys=false)
5
- ByteBuffer.new(CBson.serialize(obj, check_keys))
4
+ def self.serialize(obj, check_keys=false, move_id=false)
5
+ ByteBuffer.new(CBson.serialize(obj, check_keys, move_id))
6
6
  end
7
7
 
8
8
  def self.deserialize(buf=nil)
@@ -1,5 +1,5 @@
1
1
  # --
2
- # Copyright (C) 2008-2009 10gen Inc.
2
+ # Copyright (C) 2008-2010 10gen Inc.
3
3
  #
4
4
  # This program is free software: you can redistribute it and/or modify it
5
5
  # under the terms of the GNU Affero General Public License, version 3, as
@@ -87,15 +87,15 @@ class BSON_RUBY
87
87
 
88
88
  # Serializes an object.
89
89
  # Implemented to ensure an API compatible with BSON extension.
90
- def self.serialize(obj, check_keys=false)
91
- new.serialize(obj, check_keys)
90
+ def self.serialize(obj, check_keys=false, move_id=false)
91
+ new.serialize(obj, check_keys, move_id)
92
92
  end
93
93
 
94
94
  def self.deserialize(buf=nil)
95
95
  new.deserialize(buf)
96
96
  end
97
97
 
98
- def serialize(obj, check_keys=false)
98
+ def serialize(obj, check_keys=false, move_id=false)
99
99
  raise "Document is null" unless obj
100
100
 
101
101
  @buf.rewind
@@ -103,14 +103,20 @@ class BSON_RUBY
103
103
  @buf.put_int(0)
104
104
 
105
105
  # Write key/value pairs. Always write _id first if it exists.
106
- if obj.has_key? '_id'
107
- serialize_key_value('_id', obj['_id'], check_keys)
108
- elsif obj.has_key? :_id
109
- serialize_key_value('_id', obj[:_id], check_keys)
106
+ if move_id
107
+ if obj.has_key? '_id'
108
+ serialize_key_value('_id', obj['_id'], false)
109
+ elsif obj.has_key? :_id
110
+ serialize_key_value('_id', obj[:_id], false)
111
+ end
112
+ obj.each {|k, v| serialize_key_value(k, v, check_keys) unless k == '_id' || k == :_id }
113
+ else
114
+ if obj.has_key?('_id') && obj.has_key?(:_id)
115
+ obj['_id'] = obj.delete(:_id)
116
+ end
117
+ obj.each {|k, v| serialize_key_value(k, v, check_keys) }
110
118
  end
111
119
 
112
- obj.each {|k, v| serialize_key_value(k, v, check_keys) unless k == '_id' || k == :_id }
113
-
114
120
  serialize_eoo_element(@buf)
115
121
  if @buf.size > 4 * 1024 * 1024
116
122
  raise InvalidDocument, "Document is too large (#{@buf.size}). BSON documents are limited to 4MB (#{4 * 1024 * 1024})."
@@ -323,7 +329,12 @@ class BSON_RUBY
323
329
  options |= Regexp::MULTILINE if options_str.include?('m')
324
330
  options |= Regexp::EXTENDED if options_str.include?('x')
325
331
  options_str.gsub!(/[imx]/, '') # Now remove the three we understand
326
- RegexpOfHolding.new(str, options, options_str)
332
+ if options_str == ''
333
+ Regexp.new(str, options)
334
+ else
335
+ warn("Using deprecated Regexp options #{options_str}; future versions of this MongoDB driver will support only i, m, and x. See deprecated class RegexpOfHolding for more info.")
336
+ RegexpOfHolding.new(str, options, options_str)
337
+ end
327
338
  end
328
339
 
329
340
  def deserialize_string_data(buf)
@@ -1,5 +1,5 @@
1
1
  # --
2
- # Copyright (C) 2008-2009 10gen Inc.
2
+ # Copyright (C) 2008-2010 10gen Inc.
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
5
5
  # you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
1
1
  # --
2
- # Copyright (C) 2008-2009 10gen Inc.
2
+ # Copyright (C) 2008-2010 10gen Inc.
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
5
5
  # you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
1
1
  # --
2
- # Copyright (C) 2008-2009 10gen Inc.
2
+ # Copyright (C) 2008-2010 10gen Inc.
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
5
5
  # you may not use this file except in compliance with the License.
@@ -71,6 +71,11 @@ class OrderedHash < Hash
71
71
  end
72
72
  alias :each_pair :each
73
73
 
74
+ def to_a
75
+ @ordered_keys ||= []
76
+ @ordered_keys.map { |k| [k, self[k]] }
77
+ end
78
+
74
79
  def values
75
80
  collect { |k, v| v }
76
81
  end