Class: GridFS::GridStore

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/mongo/gridfs/grid_store.rb

Overview

GridStore is an IO-like object that provides input and output for streams of data to Mongo. See Mongo’s documentation about GridFS for storage implementation details.

Example code:

require 'mongo/gridfs'
GridStore.open(database, 'filename', 'w') { |f|
  f.puts "Hello, world!"
}
GridStore.open(database, 'filename, 'r') { |f|
  puts f.read         # => Hello, world!\n
}
GridStore.open(database, 'filename', 'w+') { |f|
  f.puts "But wait, there's more!"
}
GridStore.open(database, 'filename, 'r') { |f|
  puts f.read         # => Hello, world!\nBut wait, there's more!\n
}

Constant Summary collapse

DEFAULT_ROOT_COLLECTION =
'fs'
DEFAULT_CONTENT_TYPE =
'text/plain'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(db, name, mode = 'r', options = {}) ⇒ GridStore

Mode may only be ‘r’, ‘w’, or ‘w+’.

Options. Descriptions start with a list of the modes for which that option is legitimate.

:root

(r, w, w+) Name of root collection to use, instead of DEFAULT_ROOT_COLLECTION.

:metadata

(w, w+) A hash containing any data you want persisted as

this file's metadata. See also metadata=
:chunk_size

(w) Sets chunk size for files opened for writing See also chunk_size= which may only be called before any data is written.

:content_type

(w) Default value is DEFAULT_CONTENT_TYPE. See also #content_type=



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/mongo/gridfs/grid_store.rb', line 144

def initialize(db, name, mode='r', options={})
  @db, @filename, @mode = db, name, mode
  @root = options[:root] || DEFAULT_ROOT_COLLECTION

  doc = collection.find({'filename' => @filename}).next_object
  if doc
    @files_id = doc['_id']
    @content_type = doc['contentType']
    @chunk_size = doc['chunkSize']
    @upload_date = doc['uploadDate']
    @aliases = doc['aliases']
    @length = doc['length']
     = doc['metadata']
    @md5 = doc['md5']
  else
    @files_id = Mongo::ObjectID.new
    @content_type = DEFAULT_CONTENT_TYPE
    @chunk_size = Chunk::DEFAULT_CHUNK_SIZE
    @length = 0
  end

  case mode
  when 'r'
    @curr_chunk = nth_chunk(0)
    @position = 0
  when 'w'
    chunk_collection.create_index([['files_id', Mongo::ASCENDING], ['n', Mongo::ASCENDING]])
    delete_chunks
    @curr_chunk = Chunk.new(self, 'n' => 0)
    @content_type = options[:content_type] if options[:content_type]
    @chunk_size = options[:chunk_size] if options[:chunk_size]
     = options[:metadata] if options[:metadata]
    @position = 0
  when 'w+'
    chunk_collection.create_index([['files_id', Mongo::ASCENDING], ['n', Mongo::ASCENDING]])
    @curr_chunk = nth_chunk(last_chunk_number) || Chunk.new(self, 'n' => 0) # might be empty
    @curr_chunk.pos = @curr_chunk.data.length if @curr_chunk
     = options[:metadata] if options[:metadata]
    @position = @length
  else
    raise "error: illegal mode #{mode}"
  end

  @lineno = 0
  @pushback_byte = nil
end

Instance Attribute Details

#aliasesObject

Array of strings; may be nil



52
53
54
# File 'lib/mongo/gridfs/grid_store.rb', line 52

def aliases
  @aliases
end

#chunk_sizeObject

Returns the value of attribute chunk_size.



64
65
66
# File 'lib/mongo/gridfs/grid_store.rb', line 64

def chunk_size
  @chunk_size
end

#content_typeObject

Default is DEFAULT_CONTENT_TYPE



55
56
57
# File 'lib/mongo/gridfs/grid_store.rb', line 55

def content_type
  @content_type
end

#filenameObject

Returns the value of attribute filename.



49
50
51
# File 'lib/mongo/gridfs/grid_store.rb', line 49

def filename
  @filename
end

#files_idObject (readonly)

Returns the value of attribute files_id.



59
60
61
# File 'lib/mongo/gridfs/grid_store.rb', line 59

def files_id
  @files_id
end

#linenoObject

Returns the value of attribute lineno.



66
67
68
# File 'lib/mongo/gridfs/grid_store.rb', line 66

def lineno
  @lineno
end

#md5Object (readonly)

Returns the value of attribute md5.



68
69
70
# File 'lib/mongo/gridfs/grid_store.rb', line 68

def md5
  @md5
end

#metadataObject

Returns the value of attribute metadata.



57
58
59
# File 'lib/mongo/gridfs/grid_store.rb', line 57

def 
  
end

#upload_dateObject (readonly)

Time that the file was first saved.



62
63
64
# File 'lib/mongo/gridfs/grid_store.rb', line 62

def upload_date
  @upload_date
end

Class Method Details

.exist?(db, name, root_collection = DEFAULT_ROOT_COLLECTION) ⇒ Boolean

Returns:

  • (Boolean)


72
73
74
# File 'lib/mongo/gridfs/grid_store.rb', line 72

def exist?(db, name, root_collection=DEFAULT_ROOT_COLLECTION)
  db.collection("#{root_collection}.files").find({'filename' => name}).next_object != nil
end

.list(db, root_collection = DEFAULT_ROOT_COLLECTION) ⇒ Object

List the contains of all GridFS files stored in the given db and root collection.

:db

the database to use

:root_collection

the root collection to use



100
101
102
103
104
# File 'lib/mongo/gridfs/grid_store.rb', line 100

def list(db, root_collection=DEFAULT_ROOT_COLLECTION)
  db.collection("#{root_collection}.files").find().map { |f|
    f['filename']
  }
end

.open(db, name, mode, options = {}) ⇒ Object



76
77
78
79
80
81
82
83
84
85
# File 'lib/mongo/gridfs/grid_store.rb', line 76

def open(db, name, mode, options={})
  gs = self.new(db, name, mode, options)
  result = nil
  begin
    result = yield gs if block_given?
  ensure
    gs.close
  end
  result
end

.read(db, name, length = nil, offset = nil) ⇒ Object



87
88
89
90
91
92
# File 'lib/mongo/gridfs/grid_store.rb', line 87

def read(db, name, length=nil, offset=nil)
  GridStore.open(db, name, 'r') { |gs|
    gs.seek(offset) if offset
    gs.read(length)
  }
end

.readlines(db, name, separator = $/) ⇒ Object



106
107
108
109
110
# File 'lib/mongo/gridfs/grid_store.rb', line 106

def readlines(db, name, separator=$/)
  GridStore.open(db, name, 'r') { |gs|
    gs.readlines(separator)
  }
end


112
113
114
115
116
117
118
# File 'lib/mongo/gridfs/grid_store.rb', line 112

def unlink(db, *names)
  names.each { |name|
    gs = GridStore.new(db, name)
    gs.send(:delete_chunks)
    gs.collection.remove('_id' => gs.files_id)
  }
end

Instance Method Details

#<<(obj) ⇒ Object



330
331
332
# File 'lib/mongo/gridfs/grid_store.rb', line 330

def <<(obj)
  write(obj.to_s)
end

#chunk_collectionObject

Returns collection used for storing chunks. Depends on value of



197
198
199
# File 'lib/mongo/gridfs/grid_store.rb', line 197

def chunk_collection
  @db.collection("#{@root}.chunks")
end

#closeObject


closing ================

+++



405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
# File 'lib/mongo/gridfs/grid_store.rb', line 405

def close
  if @mode[0] == ?w
    if @curr_chunk
      @curr_chunk.truncate
      @curr_chunk.save if @curr_chunk.pos > 0
    end
    files = collection
    if @upload_date
      files.remove('_id' => @files_id)
    else
      @upload_date = Time.now
    end
    files.insert(to_mongo_object)
  end
  @db = nil
end

#closed?Boolean

Returns:

  • (Boolean)


422
423
424
# File 'lib/mongo/gridfs/grid_store.rb', line 422

def closed?
  @db == nil
end

#collectionObject



191
192
193
# File 'lib/mongo/gridfs/grid_store.rb', line 191

def collection
  @db.collection("#{@root}.files")
end

#eachObject Also known as: each_line



272
273
274
275
276
277
278
# File 'lib/mongo/gridfs/grid_store.rb', line 272

def each
  line = gets
  while line
    yield line
    line = gets
  end
end

#each_byteObject



281
282
283
284
285
286
287
# File 'lib/mongo/gridfs/grid_store.rb', line 281

def each_byte
  byte = self.getc
  while byte
    yield byte
    byte = self.getc
  end
end

#eofObject Also known as: eof?


status ================

+++

Raises:

  • (IOError)


353
354
355
356
# File 'lib/mongo/gridfs/grid_store.rb', line 353

def eof
  raise IOError.new("stream not open for reading") unless @mode[0] == ?r
  @position >= @length
end

#flushObject

A no-op.



346
347
# File 'lib/mongo/gridfs/grid_store.rb', line 346

def flush
end

#getcObject


reading ================

+++



214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
# File 'lib/mongo/gridfs/grid_store.rb', line 214

def getc
  if @pushback_byte
    byte = @pushback_byte
    @pushback_byte = nil
    @position += 1
    byte
  elsif eof?
    nil
  else
    if @curr_chunk.eof?
      @curr_chunk = nth_chunk(@curr_chunk.chunk_number + 1)
    end
    @position += 1
    @curr_chunk.getc
  end
end

#gets(separator = $/) ⇒ Object



231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/mongo/gridfs/grid_store.rb', line 231

def gets(separator=$/)
  str = ''
  byte = self.getc
  return nil if byte == nil # EOF
  while byte != nil
    s = byte.chr
    str << s
    break if s == separator
    byte = self.getc
  end
  @lineno += 1
  str
end


308
309
310
311
312
313
314
315
# File 'lib/mongo/gridfs/grid_store.rb', line 308

def print(*objs)
  objs = [$_] if objs == nil || objs.empty?
  objs.each { |obj|
    str = obj.to_s
    str.each_byte { |byte| self.putc(byte) }
  }
  nil
end

#putc(byte) ⇒ Object


writing ================

+++



298
299
300
301
302
303
304
305
306
# File 'lib/mongo/gridfs/grid_store.rb', line 298

def putc(byte)
  if @curr_chunk.pos == @chunk_size
    prev_chunk_number = @curr_chunk.chunk_number
    @curr_chunk.save
    @curr_chunk = Chunk.new(self, 'n' => prev_chunk_number + 1)
  end
  @position += 1
  @curr_chunk.putc(byte)
end

#puts(*objs) ⇒ Object



317
318
319
320
321
322
323
324
325
326
327
328
# File 'lib/mongo/gridfs/grid_store.rb', line 317

def puts(*objs)
  if objs == nil || objs.empty?
    self.putc(10)
  else
    print(*objs.collect{ |obj|
            str = obj.to_s
            str << "\n" unless str =~ /\n$/
            str
          })
  end
  nil
end

#read(len = nil, buf = nil) ⇒ Object



245
246
247
248
249
250
251
252
253
254
# File 'lib/mongo/gridfs/grid_store.rb', line 245

def read(len=nil, buf=nil)
  buf ||= ''
  byte = self.getc
  while byte != nil && (len == nil || len > 0)
    buf << byte.chr
    len -= 1 if len
    byte = self.getc if (len == nil || len > 0)
  end
  buf
end

#readcharObject

Raises:

  • (EOFError)


256
257
258
259
260
# File 'lib/mongo/gridfs/grid_store.rb', line 256

def readchar
  byte = self.getc
  raise EOFError.new if byte == nil
  byte
end

#readline(separator = $/) ⇒ Object

Raises:

  • (EOFError)


262
263
264
265
266
# File 'lib/mongo/gridfs/grid_store.rb', line 262

def readline(separator=$/)
  line = gets
  raise EOFError.new if line == nil
  line
end

#readlines(separator = $/) ⇒ Object



268
269
270
# File 'lib/mongo/gridfs/grid_store.rb', line 268

def readlines(separator=$/)
  read.split(separator).collect { |line| "#{line}#{separator}" }
end

#rewindObject


positioning ================

+++



363
364
365
366
367
368
369
370
371
372
373
374
375
# File 'lib/mongo/gridfs/grid_store.rb', line 363

def rewind
  if @curr_chunk.chunk_number != 0
    if @mode[0] == ?w
      delete_chunks
      @curr_chunk = Chunk.new(self, 'n' => 0)
    else
      @curr_chunk == nth_chunk(0)
    end
  end
  @curr_chunk.pos = 0
  @lineno = 0
  @position = 0
end

#seek(pos, whence = IO::SEEK_SET) ⇒ Object



377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
# File 'lib/mongo/gridfs/grid_store.rb', line 377

def seek(pos, whence=IO::SEEK_SET)
  target_pos = case whence
               when IO::SEEK_CUR
                 @position + pos
               when IO::SEEK_END
                 @length + pos
               when IO::SEEK_SET
                 pos
               end

  new_chunk_number = (target_pos / @chunk_size).to_i
  if new_chunk_number != @curr_chunk.chunk_number
    @curr_chunk.save if @mode[0] == ?w
    @curr_chunk = nth_chunk(new_chunk_number)
  end
  @position = target_pos
  @curr_chunk.pos = @position % @chunk_size
  0
end

#tellObject



397
398
399
# File 'lib/mongo/gridfs/grid_store.rb', line 397

def tell
 @position
end

#ungetc(byte) ⇒ Object



289
290
291
292
# File 'lib/mongo/gridfs/grid_store.rb', line 289

def ungetc(byte)
  @pushback_byte = byte
  @position -= 1
end

#write(string) ⇒ Object

Writes string as bytes and returns the number of bytes written.



335
336
337
338
339
340
341
342
343
# File 'lib/mongo/gridfs/grid_store.rb', line 335

def write(string)
  raise "#@filename not opened for write" unless @mode[0] == ?w
  count = 0
  string.each_byte { |byte|
    self.putc byte
    count += 1
  }
  count
end