mongo 0.19.3 → 0.20
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 +7 -3
- data/Rakefile +16 -6
- data/bin/bson_benchmark.rb +2 -2
- data/examples/gridfs.rb +3 -2
- data/lib/mongo.rb +3 -26
- data/lib/mongo/collection.rb +69 -50
- data/lib/mongo/connection.rb +16 -41
- data/lib/mongo/cursor.rb +22 -32
- data/lib/mongo/db.rb +13 -5
- data/lib/mongo/exceptions.rb +11 -15
- data/lib/mongo/gridfs/grid.rb +14 -3
- data/lib/mongo/gridfs/grid_file_system.rb +28 -5
- data/lib/mongo/gridfs/grid_io.rb +42 -24
- data/lib/mongo/util/support.rb +13 -2
- data/mongo-ruby-driver.gemspec +3 -1
- data/test/collection_test.rb +62 -9
- data/test/connection_test.rb +21 -32
- data/test/conversions_test.rb +1 -1
- data/test/cursor_test.rb +2 -2
- data/test/db_api_test.rb +28 -27
- data/test/db_connection_test.rb +1 -1
- data/test/db_test.rb +23 -13
- data/test/grid_file_system_test.rb +30 -4
- data/test/grid_io_test.rb +14 -1
- data/test/grid_test.rb +59 -3
- data/test/test_helper.rb +4 -1
- data/test/threading/test_threading_large_pool.rb +1 -1
- data/test/threading_test.rb +1 -1
- data/test/unit/collection_test.rb +2 -2
- data/test/unit/cursor_test.rb +7 -0
- data/test/unit/db_test.rb +8 -8
- metadata +6 -46
- data/bin/gr.rb +0 -14
- data/lib/bson.rb +0 -46
- data/lib/bson/bson_c.rb +0 -20
- data/lib/bson/bson_ruby.rb +0 -601
- data/lib/bson/byte_buffer.rb +0 -224
- data/lib/bson/exceptions.rb +0 -39
- data/lib/bson/ordered_hash.rb +0 -140
- data/lib/bson/types/binary.rb +0 -54
- data/lib/bson/types/code.rb +0 -36
- data/lib/bson/types/dbref.rb +0 -40
- data/lib/bson/types/min_max_keys.rb +0 -58
- data/lib/bson/types/objectid.rb +0 -180
- data/lib/bson/types/regexp_of_holding.rb +0 -45
- data/lib/mongo/gridfs.rb +0 -29
- data/lib/mongo/gridfs/chunk.rb +0 -91
- data/lib/mongo/gridfs/grid_store.rb +0 -580
- data/lib/mongo/types/binary.rb +0 -52
- data/lib/mongo/types/code.rb +0 -36
- data/lib/mongo/types/dbref.rb +0 -40
- data/lib/mongo/types/min_max_keys.rb +0 -58
- data/lib/mongo/types/objectid.rb +0 -180
- data/lib/mongo/types/regexp_of_holding.rb +0 -45
- data/lib/mongo/util/bson_c.rb +0 -18
- data/lib/mongo/util/bson_ruby.rb +0 -606
- data/lib/mongo/util/byte_buffer.rb +0 -222
- data/lib/mongo/util/ordered_hash.rb +0 -140
- data/test/binary_test.rb +0 -15
- data/test/bson_test.rb +0 -459
- data/test/byte_buffer_test.rb +0 -81
- data/test/chunk_test.rb +0 -82
- data/test/grid_store_test.rb +0 -337
- data/test/objectid_test.rb +0 -125
- data/test/ordered_hash_test.rb +0 -172
data/lib/mongo/cursor.rb
CHANGED
@@ -227,7 +227,7 @@ module Mongo
|
|
227
227
|
# @return [True]
|
228
228
|
def close
|
229
229
|
if @cursor_id
|
230
|
-
message = ByteBuffer.new([0, 0, 0, 0])
|
230
|
+
message = BSON::ByteBuffer.new([0, 0, 0, 0])
|
231
231
|
message.put_int(1)
|
232
232
|
message.put_long(@cursor_id)
|
233
233
|
@connection.send_message(Mongo::Constants::OP_KILL_CURSORS, message, "cursor.close")
|
@@ -282,6 +282,8 @@ module Mongo
|
|
282
282
|
returning({}) do |hash|
|
283
283
|
fields.each { |field| hash[field] = 1 }
|
284
284
|
end
|
285
|
+
when Hash
|
286
|
+
return fields
|
285
287
|
end
|
286
288
|
end
|
287
289
|
|
@@ -301,11 +303,6 @@ module Mongo
|
|
301
303
|
end
|
302
304
|
end
|
303
305
|
|
304
|
-
# Returns true if the query contains order, explain, hint, or snapshot.
|
305
|
-
def query_contains_special_fields?
|
306
|
-
@order || @explain || @hint || @snapshot
|
307
|
-
end
|
308
|
-
|
309
306
|
# Return a number of documents remaining for this cursor.
|
310
307
|
def num_remaining
|
311
308
|
refill_via_get_more if @cache.length == 0
|
@@ -314,11 +311,11 @@ module Mongo
|
|
314
311
|
|
315
312
|
def refill_via_get_more
|
316
313
|
return if send_initial_query || @cursor_id.zero?
|
317
|
-
message = ByteBuffer.new([0, 0, 0, 0])
|
314
|
+
message = BSON::ByteBuffer.new([0, 0, 0, 0])
|
318
315
|
|
319
316
|
# DB name.
|
320
317
|
db_name = @admin ? 'admin' : @db.name
|
321
|
-
BSON_RUBY.serialize_cstr(message, "#{db_name}.#{@collection.name}")
|
318
|
+
BSON::BSON_RUBY.serialize_cstr(message, "#{db_name}.#{@collection.name}")
|
322
319
|
|
323
320
|
# Number of results to return; db decides for now.
|
324
321
|
message.put_int(0)
|
@@ -346,18 +343,15 @@ module Mongo
|
|
346
343
|
end
|
347
344
|
|
348
345
|
def construct_query_message
|
349
|
-
message = ByteBuffer.new
|
346
|
+
message = BSON::ByteBuffer.new
|
350
347
|
message.put_int(query_opts)
|
351
348
|
db_name = @admin ? 'admin' : @db.name
|
352
|
-
BSON_RUBY.serialize_cstr(message, "#{db_name}.#{@collection.name}")
|
349
|
+
BSON::BSON_RUBY.serialize_cstr(message, "#{db_name}.#{@collection.name}")
|
353
350
|
message.put_int(@skip)
|
354
351
|
message.put_int(@limit)
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
end
|
359
|
-
message.put_array(BSON.serialize(selector, false).to_a)
|
360
|
-
message.put_array(BSON.serialize(@fields, false).to_a) if @fields
|
352
|
+
spec = query_contains_special_fields? ? construct_query_spec : @selector
|
353
|
+
message.put_array(BSON::BSON_CODER.serialize(spec, false).to_a)
|
354
|
+
message.put_array(BSON::BSON_CODER.serialize(@fields, false).to_a) if @fields
|
361
355
|
message
|
362
356
|
end
|
363
357
|
|
@@ -367,24 +361,20 @@ module Mongo
|
|
367
361
|
"#{@order ? ('.sort(' + @order.inspect + ')') : ''}"
|
368
362
|
end
|
369
363
|
|
370
|
-
def
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
364
|
+
def construct_query_spec
|
365
|
+
return @selector if @selector.has_key?('$query')
|
366
|
+
spec = OrderedHash.new
|
367
|
+
spec['$query'] = @selector
|
368
|
+
spec['$orderby'] = Mongo::Support.format_order_clause(@order) if @order
|
369
|
+
spec['$hint'] = @hint if @hint && @hint.length > 0
|
370
|
+
spec['$explain'] = true if @explain
|
371
|
+
spec['$snapshot'] = true if @snapshot
|
372
|
+
spec
|
378
373
|
end
|
379
374
|
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
when Array then array_as_sort_parameters(@order)
|
384
|
-
else
|
385
|
-
raise InvalidSortValueError, "Illegal sort clause, '#{@order.class.name}'; must be of the form " +
|
386
|
-
"[['field1', '(ascending|descending)'], ['field2', '(ascending|descending)']]"
|
387
|
-
end
|
375
|
+
# Returns true if the query contains order, explain, hint, or snapshot.
|
376
|
+
def query_contains_special_fields?
|
377
|
+
@order || @explain || @hint || @snapshot
|
388
378
|
end
|
389
379
|
|
390
380
|
def to_s
|
data/lib/mongo/db.rb
CHANGED
@@ -54,10 +54,10 @@ module Mongo
|
|
54
54
|
# @param [Mongo::Connection] connection a connection object pointing to MongoDB. Note
|
55
55
|
# that databases are usually instantiated via the Connection class. See the examples below.
|
56
56
|
#
|
57
|
-
# @option options [Boolean] strict (False) If true, collections must exist to be accessed and must
|
57
|
+
# @option options [Boolean] :strict (False) If true, collections must exist to be accessed and must
|
58
58
|
# not exist to be created. See DB#collection and DB#create_collection.
|
59
59
|
#
|
60
|
-
# @option options [Object, #create_pk(doc)] pk (Mongo::ObjectID) A primary key factory object,
|
60
|
+
# @option options [Object, #create_pk(doc)] :pk (Mongo::ObjectID) A primary key factory object,
|
61
61
|
# which should take a hash and return a hash which merges the original hash with any primary key
|
62
62
|
# fields the factory wishes to inject. (NOTE: if the object already has a primary key,
|
63
63
|
# the factory should not inject a new key).
|
@@ -229,7 +229,7 @@ module Mongo
|
|
229
229
|
# @return [Mongo::Collection]
|
230
230
|
def collection(name)
|
231
231
|
return Collection.new(self, name, @pk_factory) if !strict? || collection_names.include?(name)
|
232
|
-
raise MongoDBError, "Collection #{name} doesn't exist. Currently in strict mode."
|
232
|
+
raise Mongo::MongoDBError, "Collection #{name} doesn't exist. Currently in strict mode."
|
233
233
|
end
|
234
234
|
alias_method :[], :collection
|
235
235
|
|
@@ -325,8 +325,8 @@ module Mongo
|
|
325
325
|
#
|
326
326
|
# @return [String] the return value of the function.
|
327
327
|
def eval(code, *args)
|
328
|
-
if not code.is_a? Code
|
329
|
-
code = Code.new(code)
|
328
|
+
if not code.is_a? BSON::Code
|
329
|
+
code = BSON::Code.new(code)
|
330
330
|
end
|
331
331
|
|
332
332
|
oh = OrderedHash.new
|
@@ -386,6 +386,14 @@ module Mongo
|
|
386
386
|
info
|
387
387
|
end
|
388
388
|
|
389
|
+
|
390
|
+
# Return stats on this database. Uses MongoDB's dbstats command.
|
391
|
+
#
|
392
|
+
# @return [Hash]
|
393
|
+
def stats
|
394
|
+
self.command({:dbstats => 1})
|
395
|
+
end
|
396
|
+
|
389
397
|
# Create a new index on the given collection.
|
390
398
|
# Normally called by Collection#create_index.
|
391
399
|
#
|
data/lib/mongo/exceptions.rb
CHANGED
@@ -24,17 +24,17 @@ module Mongo
|
|
24
24
|
# Raised when configuration options cause connections, queries, etc., to fail.
|
25
25
|
class ConfigurationError < MongoRubyError; end
|
26
26
|
|
27
|
-
# Raised
|
27
|
+
# Raised on fatal errors to GridFS.
|
28
28
|
class GridError < MongoRubyError; end
|
29
29
|
|
30
|
-
# Raised
|
31
|
-
class
|
30
|
+
# Raised on fatal errors to GridFS.
|
31
|
+
class GridFileNotFound < GridError; end
|
32
32
|
|
33
|
-
# Raised
|
34
|
-
class
|
33
|
+
# Raised on fatal errors to GridFS.
|
34
|
+
class GridMD5Failure < GridError; end
|
35
35
|
|
36
|
-
# Raised when
|
37
|
-
class
|
36
|
+
# Raised when invalid arguments are sent to Mongo Ruby methods.
|
37
|
+
class MongoArgumentError < MongoRubyError; end
|
38
38
|
|
39
39
|
# Raised on failures in connection to the database server.
|
40
40
|
class ConnectionError < MongoRubyError; end
|
@@ -42,9 +42,8 @@ module Mongo
|
|
42
42
|
# Raised on failures in connection to the database server.
|
43
43
|
class ConnectionTimeoutError < MongoRubyError; end
|
44
44
|
|
45
|
-
# Raised when
|
46
|
-
|
47
|
-
class InvalidDocument < MongoDBError; end
|
45
|
+
# Raised when a connection operation fails.
|
46
|
+
class ConnectionFailure < MongoDBError; end
|
48
47
|
|
49
48
|
# Raised when authentication fails.
|
50
49
|
class AuthenticationError < MongoDBError; end
|
@@ -52,14 +51,11 @@ module Mongo
|
|
52
51
|
# Raised when a database operation fails.
|
53
52
|
class OperationFailure < MongoDBError; end
|
54
53
|
|
55
|
-
# Raised when a connection operation fails.
|
56
|
-
class ConnectionFailure < MongoDBError; end
|
57
|
-
|
58
54
|
# Raised when a client attempts to perform an invalid operation.
|
59
55
|
class InvalidOperation < MongoDBError; end
|
60
56
|
|
61
|
-
# Raised when an invalid name is used.
|
62
|
-
class
|
57
|
+
# Raised when an invalid collection or database name is used (invalid namespace name).
|
58
|
+
class InvalidNSName < RuntimeError; end
|
63
59
|
|
64
60
|
# Raised when the client supplies an invalid value to sort by.
|
65
61
|
class InvalidSortValueError < MongoRubyError; end
|
data/lib/mongo/gridfs/grid.rb
CHANGED
@@ -34,14 +34,14 @@ module Mongo
|
|
34
34
|
@chunks = @db["#{fs_name}.chunks"]
|
35
35
|
@fs_name = fs_name
|
36
36
|
|
37
|
-
@chunks.create_index([['files_id', Mongo::ASCENDING], ['n', Mongo::ASCENDING]])
|
37
|
+
@chunks.create_index([['files_id', Mongo::ASCENDING], ['n', Mongo::ASCENDING]], :unique => true)
|
38
38
|
end
|
39
39
|
|
40
40
|
# Store a file in the file store.
|
41
41
|
#
|
42
42
|
# @param [String, #read] data a string or io-like object to store.
|
43
|
-
# @param [String] filename a name for the file.
|
44
43
|
#
|
44
|
+
# @options opts [String] :filename (nil) a name for the file.
|
45
45
|
# @options opts [Hash] :metadata ({}) any additional data to store with the file.
|
46
46
|
# @options opts [ObjectID] :_id (ObjectID) a unique id for
|
47
47
|
# the file to be use in lieu of an automatically generated one.
|
@@ -53,7 +53,14 @@ module Mongo
|
|
53
53
|
# will be validated using an md5 hash. If validation fails, an exception will be raised.
|
54
54
|
#
|
55
55
|
# @return [Mongo::ObjectID] the file's id.
|
56
|
-
def put(data,
|
56
|
+
def put(data, opts={}, old_opts={})
|
57
|
+
if opts.is_a?(String)
|
58
|
+
warn "The filename is now optional. Please pass the filename as a hash option: Grid#put(data, :filename => 'file.jpg')."
|
59
|
+
filename = opts
|
60
|
+
opts = old_opts
|
61
|
+
else
|
62
|
+
filename = opts[:filename]
|
63
|
+
end
|
57
64
|
opts.merge!(default_grid_io_opts)
|
58
65
|
file = GridIO.new(@files, @chunks, filename, 'w', opts=opts)
|
59
66
|
file.write(data)
|
@@ -73,6 +80,10 @@ module Mongo
|
|
73
80
|
|
74
81
|
# Delete a file from the store.
|
75
82
|
#
|
83
|
+
# Note that deleting a GridFS file can result in read errors if another process
|
84
|
+
# is attempting to read a file while it's being deleted. While the odds for this
|
85
|
+
# kind of race condition are small, it's important to be aware of.
|
86
|
+
#
|
76
87
|
# @param [] id
|
77
88
|
#
|
78
89
|
# @return [Boolean]
|
@@ -34,8 +34,10 @@ module Mongo
|
|
34
34
|
@chunks = @db["#{fs_name}.chunks"]
|
35
35
|
@fs_name = fs_name
|
36
36
|
|
37
|
-
@files.create_index([['filename', 1], ['uploadDate', -1]])
|
38
37
|
@default_query_opts = {:sort => [['filename', 1], ['uploadDate', -1]], :limit => 1}
|
38
|
+
|
39
|
+
@files.create_index([['filename', 1], ['uploadDate', -1]])
|
40
|
+
@chunks.create_index([['files_id', Mongo::ASCENDING], ['n', Mongo::ASCENDING]], :unique => true)
|
39
41
|
end
|
40
42
|
|
41
43
|
# Open a file for reading or writing. Note that the options for this method only apply
|
@@ -53,6 +55,9 @@ module Mongo
|
|
53
55
|
# the content type will may be inferred from the filename extension if the mime-types gem can be
|
54
56
|
# loaded. Otherwise, the content type 'binary/octet-stream' will be used.
|
55
57
|
# @options opts [Integer] (262144) :chunk_size size of file chunks in bytes.
|
58
|
+
# @options opts [Boolean] :delete_old (false) ensure that old versions of the file are deleted. This option
|
59
|
+
# only work in 'w' mode. Certain precautions must be taken when deleting GridFS files. See the notes under
|
60
|
+
# GridFileSystem#delete.
|
56
61
|
# @options opts [Boolean] :safe (false) When safe mode is enabled, the chunks sent to the server
|
57
62
|
# will be validated using an md5 hash. If validation fails, an exception will be raised.
|
58
63
|
#
|
@@ -76,15 +81,23 @@ module Mongo
|
|
76
81
|
# @grid.open('image.jpg, 'w') do |f|
|
77
82
|
# f.write @file
|
78
83
|
# end
|
84
|
+
#
|
85
|
+
# @return [Mongo::GridIO]
|
79
86
|
def open(filename, mode, opts={})
|
80
87
|
opts.merge!(default_grid_io_opts(filename))
|
81
|
-
|
88
|
+
del = opts.delete(:delete_old) && mode == 'w'
|
89
|
+
file = GridIO.new(@files, @chunks, filename, mode, opts)
|
82
90
|
return file unless block_given?
|
83
91
|
result = nil
|
84
92
|
begin
|
85
93
|
result = yield file
|
86
94
|
ensure
|
87
|
-
file.close
|
95
|
+
id = file.close
|
96
|
+
if del
|
97
|
+
self.delete do
|
98
|
+
@files.find({'filename' => filename, '_id' => {'$ne' => id}}, :fields => ['_id'])
|
99
|
+
end
|
100
|
+
end
|
88
101
|
end
|
89
102
|
result
|
90
103
|
end
|
@@ -92,11 +105,21 @@ module Mongo
|
|
92
105
|
# Delete the file with the given filename. Note that this will delete
|
93
106
|
# all versions of the file.
|
94
107
|
#
|
108
|
+
# Note that deleting a GridFS file can result in read errors if another process
|
109
|
+
# is attempting to read a file while it's being deleted. While the odds for this
|
110
|
+
# kind of race condition are small, it's important to be aware of.
|
111
|
+
#
|
95
112
|
# @param [String] filename
|
96
113
|
#
|
114
|
+
# @yield [] pass a block that returns an array of documents to be deleted.
|
115
|
+
#
|
97
116
|
# @return [Boolean]
|
98
|
-
def delete(filename)
|
99
|
-
|
117
|
+
def delete(filename=nil)
|
118
|
+
if block_given?
|
119
|
+
files = yield
|
120
|
+
else
|
121
|
+
files = @files.find({'filename' => filename}, :fields => ['_id'])
|
122
|
+
end
|
100
123
|
files.each do |file|
|
101
124
|
@files.remove({'_id' => file['_id']})
|
102
125
|
@chunks.remove({'files_id' => file['_id']})
|
data/lib/mongo/gridfs/grid_io.rb
CHANGED
@@ -27,6 +27,7 @@ module Mongo
|
|
27
27
|
class GridIO
|
28
28
|
DEFAULT_CHUNK_SIZE = 256 * 1024
|
29
29
|
DEFAULT_CONTENT_TYPE = 'binary/octet-stream'
|
30
|
+
PROTECTED_ATTRS = [:files_id, :file_length, :client_md5, :server_md5]
|
30
31
|
|
31
32
|
attr_reader :content_type, :chunk_size, :upload_date, :files_id, :filename,
|
32
33
|
:metadata, :server_md5, :client_md5, :file_length
|
@@ -52,15 +53,16 @@ module Mongo
|
|
52
53
|
# @options opts [Boolean] :safe (false) When safe mode is enabled, the chunks sent to the server
|
53
54
|
# will be validated using an md5 hash. If validation fails, an exception will be raised.
|
54
55
|
def initialize(files, chunks, filename, mode, opts={})
|
55
|
-
@files
|
56
|
-
@chunks
|
57
|
-
@filename
|
58
|
-
@mode
|
59
|
-
@query
|
60
|
-
@query_opts
|
61
|
-
@fs_name
|
62
|
-
@safe
|
63
|
-
@local_md5
|
56
|
+
@files = files
|
57
|
+
@chunks = chunks
|
58
|
+
@filename = filename
|
59
|
+
@mode = mode
|
60
|
+
@query = opts.delete(:query) || {}
|
61
|
+
@query_opts = opts.delete(:query_opts) || {}
|
62
|
+
@fs_name = opts.delete(:fs_name) || Grid::DEFAULT_FS_NAME
|
63
|
+
@safe = opts.delete(:safe) || false
|
64
|
+
@local_md5 = Digest::MD5.new if @safe
|
65
|
+
@custom_attrs = {}
|
64
66
|
|
65
67
|
case @mode
|
66
68
|
when 'r' then init_read
|
@@ -70,6 +72,19 @@ module Mongo
|
|
70
72
|
end
|
71
73
|
end
|
72
74
|
|
75
|
+
def [](key)
|
76
|
+
@custom_attrs[key] || instance_variable_get("@#{key.to_s}")
|
77
|
+
end
|
78
|
+
|
79
|
+
def []=(key, value)
|
80
|
+
if PROTECTED_ATTRS.include?(key.to_sym)
|
81
|
+
warn "Attempting to overwrite protected value."
|
82
|
+
return nil
|
83
|
+
else
|
84
|
+
@custom_attrs[key] = value
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
73
88
|
# Read the data from the file. If a length if specified, will read from the
|
74
89
|
# current file position.
|
75
90
|
#
|
@@ -163,16 +178,16 @@ module Mongo
|
|
163
178
|
# This method will be invoked automatically when
|
164
179
|
# on GridIO#open is passed a block. Otherwise, it must be called manually.
|
165
180
|
#
|
166
|
-
# @return [
|
181
|
+
# @return [BSON::ObjectID]
|
167
182
|
def close
|
168
183
|
if @mode[0] == ?w
|
169
184
|
if @current_chunk['n'].zero? && @chunk_position.zero?
|
170
185
|
warn "Warning: Storing a file with zero length."
|
171
186
|
end
|
172
187
|
@upload_date = Time.now.utc
|
173
|
-
@files.insert(to_mongo_object)
|
188
|
+
id = @files.insert(to_mongo_object)
|
174
189
|
end
|
175
|
-
|
190
|
+
id
|
176
191
|
end
|
177
192
|
|
178
193
|
def inspect
|
@@ -183,7 +198,7 @@ module Mongo
|
|
183
198
|
|
184
199
|
def create_chunk(n)
|
185
200
|
chunk = OrderedHash.new
|
186
|
-
chunk['_id'] =
|
201
|
+
chunk['_id'] = BSON::ObjectID.new
|
187
202
|
chunk['n'] = n
|
188
203
|
chunk['files_id'] = @files_id
|
189
204
|
chunk['data'] = ''
|
@@ -261,7 +276,7 @@ module Mongo
|
|
261
276
|
end
|
262
277
|
chunk_available = @chunk_size - @chunk_position
|
263
278
|
step_size = (to_write > chunk_available) ? chunk_available : to_write
|
264
|
-
@current_chunk['data'] = Binary.new((@current_chunk['data'].to_s << string[-to_write, step_size]).unpack("c*"))
|
279
|
+
@current_chunk['data'] = BSON::Binary.new((@current_chunk['data'].to_s << string[-to_write, step_size]).unpack("c*"))
|
265
280
|
@chunk_position += step_size
|
266
281
|
to_write -= step_size
|
267
282
|
save_chunk(@current_chunk)
|
@@ -272,7 +287,7 @@ module Mongo
|
|
272
287
|
# Initialize the class for reading a file.
|
273
288
|
def init_read
|
274
289
|
doc = @files.find(@query, @query_opts).next_document
|
275
|
-
raise
|
290
|
+
raise GridFileNotFound, "Could not open file matching #{@query.inspect} #{@query_opts.inspect}" unless doc
|
276
291
|
|
277
292
|
@files_id = doc['_id']
|
278
293
|
@content_type = doc['contentType']
|
@@ -283,6 +298,7 @@ module Mongo
|
|
283
298
|
@metadata = doc['metadata']
|
284
299
|
@md5 = doc['md5']
|
285
300
|
@filename = doc['filename']
|
301
|
+
@custom_attrs = doc
|
286
302
|
|
287
303
|
@current_chunk = get_chunk(0)
|
288
304
|
@file_position = 0
|
@@ -290,12 +306,13 @@ module Mongo
|
|
290
306
|
|
291
307
|
# Initialize the class for writing a file.
|
292
308
|
def init_write(opts)
|
293
|
-
@files_id = opts
|
294
|
-
@content_type = opts
|
295
|
-
@chunk_size = opts
|
296
|
-
@metadata = opts
|
297
|
-
@aliases = opts
|
309
|
+
@files_id = opts.delete(:_id) || BSON::ObjectID.new
|
310
|
+
@content_type = opts.delete(:content_type) || (defined? MIME) && get_content_type || DEFAULT_CONTENT_TYPE
|
311
|
+
@chunk_size = opts.delete(:chunk_size) || DEFAULT_CHUNK_SIZE
|
312
|
+
@metadata = opts.delete(:metadata) if opts[:metadata]
|
313
|
+
@aliases = opts.delete(:aliases) if opts[:aliases]
|
298
314
|
@file_length = 0
|
315
|
+
opts.each {|k, v| self[k] = v}
|
299
316
|
|
300
317
|
@current_chunk = create_chunk(0)
|
301
318
|
@file_position = 0
|
@@ -304,14 +321,15 @@ module Mongo
|
|
304
321
|
def to_mongo_object
|
305
322
|
h = OrderedHash.new
|
306
323
|
h['_id'] = @files_id
|
307
|
-
h['filename'] = @filename
|
324
|
+
h['filename'] = @filename if @filename
|
308
325
|
h['contentType'] = @content_type
|
309
326
|
h['length'] = @current_chunk ? @current_chunk['n'] * @chunk_size + @chunk_position : 0
|
310
327
|
h['chunkSize'] = @chunk_size
|
311
328
|
h['uploadDate'] = @upload_date
|
312
|
-
h['aliases'] = @aliases
|
313
|
-
h['metadata'] = @metadata
|
329
|
+
h['aliases'] = @aliases if @aliases
|
330
|
+
h['metadata'] = @metadata if @metadata
|
314
331
|
h['md5'] = get_md5
|
332
|
+
h.merge!(@custom_attrs)
|
315
333
|
h
|
316
334
|
end
|
317
335
|
|
@@ -324,7 +342,7 @@ module Mongo
|
|
324
342
|
if @safe
|
325
343
|
@client_md5 = @local_md5.hexdigest
|
326
344
|
if @local_md5 != @server_md5
|
327
|
-
raise
|
345
|
+
raise GridMD5Failure, "File on server failed MD5 check"
|
328
346
|
end
|
329
347
|
else
|
330
348
|
@server_md5
|