diff --git a/README.rdoc b/README.rdoc index c504d87..e456b3b 100644 --- a/README.rdoc +++ b/README.rdoc @@ -70,40 +70,51 @@ Here's how to start MongoDB and run the "simple.rb" example: See also the test code, especially test/test_db_api.rb. -= GridStore += GridFS -The GridStore class is a Ruby implementation of MongoDB's GridFS file storage -system. An instance of GridStore is like an IO object. See the RDocs for -details, and see examples/gridfs.rb for code that uses many of the GridStore -features (metadata, content type, rewind/seek/tell, etc). +Note: The GridStore class has been deprecated. Use either the Grid or GridFileSystem +classes to take advantage of GridFS. -Note that the GridStore class is not automatically required when you require -'mongo'. You also need to require 'mongo/gridfs' +The Ruby driver include two abstractions for storing large files: Grid and GridFileSystem. +The Grid class is a Ruby implementation of MongoDB's GridFS file storage +specification. GridFileSystem is essentailly the same, but provides a more filesystem-like API +and assumes that filenames are unique. -Example code: +An instance of both classes represents an individual file store. See the API reference +for details, and see examples/gridfs.rb for code that uses many of the Grid +features (metadata, content type, seek, tell, etc). - include GridFS +Examples: + include Mongo - # Store the text "Hello, world!" in the grid store. - GridStore.open(database, 'filename', 'w') do |f| - f.puts "Hello, world!" + # Get a database + db = Mongo::Connection.new.db('app-db') + + # GridFileSystem. Store the text "Hello, world!" in the fs. + fs = GridFileSystem.new(db) + fs.open('filename', 'w') do |f| + f.write "Hello, world!" end - # Output "Hello, world!" - GridStore.open(database, 'filename', 'r') do |f| + # GridFileSystem. Output "Hello, world!" + fs = GridFileSystem.new(db) + fs.open('filename', 'r') do |f| puts f.read end - # Add text to the grid store. - GridStore.open(database, 'filename', 'w+') do |f| - f.puts "But wait, there's more!" - end + # Write a file on disk to the Grid + file = File.open('image.jpg') + grid = GridFileSystem.new(db) + id = grid.put(file) - # Retrieve everything, outputting "Hello, world!\nBut wait, there's more!\n" - GridStore.open(database, 'filename', 'r') do |f| - puts f.read - end + # Retrieve the file + file = grid.get(id) + file.read + # Get all the file's metata + file.filename + file.content_type + file.metadata = Notes diff --git a/bin/gridstore_benchmark b/bin/gridstore_benchmark index 873f6bb..6b80457 100755 --- a/bin/gridstore_benchmark +++ b/bin/gridstore_benchmark @@ -7,34 +7,39 @@ include GridFS db = Connection.new['benchmark-gridfs'] sample_data = File.open(File.join(File.dirname(__FILE__), 'sample_file.pdf'), 'r').read -GridStore.delete(db, 'mongodb.pdf') -GridStore.delete(db, 'mongodb-new.pdf') +db['fs.files'].remove +db['fs.chunks'].remove +T = 5 length = sample_data.length -mb = length / 1048576.0 +mb = T * length / 1048576.0 -t1 = Time.now @grid = Grid.new(db) -@id = @grid.put(sample_data, 'mongodb-new.pdf', :safe => true) -puts "Write: #{mb / (Time.now - t1)} mb/s" - t1 = Time.now -GridStore.open(db, 'mongodb.pdf', 'w') do |f| - f.write(sample_data) +ids = [] +T.times do |n| + ids << @grid.put(sample_data, "mongodb-new-#{n}.pdf") end -puts "Write: #{mb / (Time.now - t1)} mb/s" +puts "Grid Write: #{mb / (Time.now - t1)} mb/s" t1 = Time.now -@grid = Grid.new(db) -data = @grid.get(@id).read -puts "Read new: #{mb / (Time.now - t1)} mb/s" -file = db['fs.files'].find_one({:filename => 'mongodb-new.pdf'}) - -t1 = Time.now -old_data = GridStore.open(db, 'mongodb.pdf', 'r') do |f| - f.read +T.times do |n| + GridStore.open(db, "mongodb.pdf-#{n}", 'w') do |f| + f.write(sample_data) + end end -puts "Read: #{mb / (Time.now - t1)} mb/s" +puts "GridStore Write: #{mb / (Time.now - t1)} mb/s" -puts sample_data == old_data -puts sample_data == data +t1 = Time.now +T.times do |n| + data = @grid.get(ids[n]).read +end +puts "Grid Read: #{mb / (Time.now - t1)} mb/s" + +t1 = Time.now +T.times do |n| + old_data = GridStore.open(db, "mongodb.pdf-#{n}", 'r') do |f| + f.read + end +end +puts "GridStore Read: #{mb / (Time.now - t1)} mb/s" diff --git a/examples/gridfs.rb b/examples/gridfs.rb index 55bd601..4a06745 100644 --- a/examples/gridfs.rb +++ b/examples/gridfs.rb @@ -1,10 +1,10 @@ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) +def assert + raise "Failed!" unless yield +end require 'mongo' -require 'mongo/gridfs' - include Mongo -include GridFS host = ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost' port = ENV['MONGO_RUBY_DRIVER_PORT'] || Connection::DEFAULT_PORT @@ -12,77 +12,32 @@ port = ENV['MONGO_RUBY_DRIVER_PORT'] || Connection::DEFAULT_PORT puts "Connecting to #{host}:#{port}" db = Connection.new(host, port).db('ruby-mongo-examples') -def dump(db, fname) - GridStore.open(db, fname, 'r') { |f| puts f.read } -end +data = "hello, world!" -# Write a new file -GridStore.open(db, 'foobar', 'w') { |f| f.write("hello, world!") } +grid = Grid.new(db) + +# Write a new file. data can be a string or an io object responding to #read. +id = grid.put(data, 'hello.txt') # Read it and print out the contents -dump(db, 'foobar') +file = grid.get(id) +puts file.read -# Append more data -GridStore.open(db, 'foobar', 'w+') { |f| f.write("\n"); f.puts "line two" } -dump(db, 'foobar') +# Delete the file +grid.delete(id) -# Overwrite -GridStore.open(db, 'foobar', 'w') { |f| f.puts "hello, sailor!" } -dump(db, 'foobar') - -# File existence tests -puts "File 'foobar' exists: #{GridStore.exist?(db, 'foobar')}" -puts "File 'does-not-exist' exists: #{GridStore.exist?(db, 'does-not-exist')}" - -# Read with offset (uses seek) -puts GridStore.read(db, 'foobar', 6, 7) - -# Rewind/seek/tell -GridStore.open(db, 'foobar', 'w') { |f| - f.write "hello, world!" - f.rewind - f.write "xyzzz" - puts f.tell # => 5 - f.seek(4) - f.write('y') -} -dump(db, 'foobar') # => 'xyzzy' - -# Unlink (delete) -GridStore.unlink(db, 'foobar') -puts "File 'foobar' exists after delete: #{GridStore.exist?(db, 'foobar')}" +begin +grid.get(id) +rescue => e + assert {e.class == Mongo::GridError} +end # Metadata -GridStore.open(db, 'foobar', 'w') { |f| f.write("hello, world!") } -GridStore.open(db, 'foobar', 'r') { |f| - puts f.content_type - puts f.upload_date - puts f.chunk_size - puts f.metadata.inspect -} - -# Add some metadata; change content type -GridStore.open(db, 'foobar', 'w+') { |f| - f.content_type = 'text/xml' - f.metadata = {'a' => 1} -} -# Print it -GridStore.open(db, 'foobar', 'r') { |f| - puts f.content_type - puts f.upload_date - puts f.chunk_size - puts f.metadata.inspect -} - -# You can also set metadata when initially writing the file. Setting :root -# means that the file and its chunks are stored in a different root -# collection: instead of gridfs.files and gridfs.chunks, here we use -# my_files.files and my_files.chunks. -GridStore.open(db, 'foobar', 'w', - :content_type => 'text/plain', - :metadata => {'a' => 1}, - :chunk_size => 1024 * 4, - :root => 'my_files') { |f| - f.puts 'hello, world' -} +id = grid.put(data, 'hello.txt', :content_type => 'text/plain', :metadata => {'name' => 'hello'}) +file = grid.get(id) +p file.content_type +p file.metadata.inspect +p file.chunk_size +p file.file_length +p file.data diff --git a/lib/mongo/gridfs/grid_io.rb b/lib/mongo/gridfs/grid_io.rb index e4a0089..9d72fd1 100644 --- a/lib/mongo/gridfs/grid_io.rb +++ b/lib/mongo/gridfs/grid_io.rb @@ -29,7 +29,7 @@ module Mongo DEFAULT_CONTENT_TYPE = 'binary/octet-stream' attr_reader :content_type, :chunk_size, :upload_date, :files_id, :filename, - :metadata, :server_md5, :client_md5 + :metadata, :server_md5, :client_md5, :file_length # Create a new GridIO object. Note that most users will not need to use this class directly; # the Grid and GridFileSystem classes will instantiate this class