mongo 0.18.3 → 0.19

Sign up to get free protection for your applications and to get access to all the features.
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