Class: XGen::Mongo::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 =
'gridfs'
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=



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/mongo/gridfs/grid_store.rb', line 116

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']
    @metadata = doc['metadata']
  else
    @files_id = XGen::Mongo::Driver::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("chunk_index", ['files_id', 'n'])
    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]
    @metadata = options[:metadata] if options[:metadata]
    @position = 0
  when 'w+'
    chunk_collection.create_index("chunk_index", ['files_id', 'n'])
    @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
    @metadata = 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



38
39
40
# File 'lib/mongo/gridfs/grid_store.rb', line 38

def aliases
  @aliases
end

#chunk_sizeObject

Returns the value of attribute chunk_size.



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

def chunk_size
  @chunk_size
end

#content_typeObject

Default is DEFAULT_CONTENT_TYPE



41
42
43
# File 'lib/mongo/gridfs/grid_store.rb', line 41

def content_type
  @content_type
end

#filenameObject

Returns the value of attribute filename.



35
36
37
# File 'lib/mongo/gridfs/grid_store.rb', line 35

def filename
  @filename
end

#files_idObject (readonly)

Returns the value of attribute files_id.



45
46
47
# File 'lib/mongo/gridfs/grid_store.rb', line 45

def files_id
  @files_id
end

#linenoObject

Returns the value of attribute lineno.



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

def lineno
  @lineno
end

#metadataObject

Returns the value of attribute metadata.



43
44
45
# File 'lib/mongo/gridfs/grid_store.rb', line 43

def 
  @metadata
end

#upload_dateObject (readonly)

Time that the file was first saved.



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

def upload_date
  @upload_date
end

Class Method Details

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

Returns:

  • (Boolean)


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

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

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



60
61
62
63
64
65
66
67
68
69
# File 'lib/mongo/gridfs/grid_store.rb', line 60

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



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

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



78
79
80
81
82
# File 'lib/mongo/gridfs/grid_store.rb', line 78

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


84
85
86
87
88
89
90
# File 'lib/mongo/gridfs/grid_store.rb', line 84

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



301
302
303
# File 'lib/mongo/gridfs/grid_store.rb', line 301

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

#chunk_collectionObject

Returns collection used for storing chunks. Depends on value of



168
169
170
# File 'lib/mongo/gridfs/grid_store.rb', line 168

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

#closeObject


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

+++



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

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)


393
394
395
# File 'lib/mongo/gridfs/grid_store.rb', line 393

def closed?
  @db == nil
end

#collectionObject



162
163
164
# File 'lib/mongo/gridfs/grid_store.rb', line 162

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

#eachObject Also known as: each_line



243
244
245
246
247
248
249
# File 'lib/mongo/gridfs/grid_store.rb', line 243

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

#each_byteObject



252
253
254
255
256
257
258
# File 'lib/mongo/gridfs/grid_store.rb', line 252

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

#eofObject Also known as: eof?


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

+++

Raises:

  • (IOError)


324
325
326
327
# File 'lib/mongo/gridfs/grid_store.rb', line 324

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

#flushObject

A no-op.



317
318
# File 'lib/mongo/gridfs/grid_store.rb', line 317

def flush
end

#getcObject


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

+++



185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/mongo/gridfs/grid_store.rb', line 185

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



202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/mongo/gridfs/grid_store.rb', line 202

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


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

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 ================

+++



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

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



288
289
290
291
292
293
294
295
296
297
298
299
# File 'lib/mongo/gridfs/grid_store.rb', line 288

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



216
217
218
219
220
221
222
223
224
225
# File 'lib/mongo/gridfs/grid_store.rb', line 216

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)


227
228
229
230
231
# File 'lib/mongo/gridfs/grid_store.rb', line 227

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

#readline(separator = $/) ⇒ Object

Raises:

  • (EOFError)


233
234
235
236
237
# File 'lib/mongo/gridfs/grid_store.rb', line 233

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

#readlines(separator = $/) ⇒ Object



239
240
241
# File 'lib/mongo/gridfs/grid_store.rb', line 239

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

#rewindObject


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

+++



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

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



348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
# File 'lib/mongo/gridfs/grid_store.rb', line 348

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



368
369
370
# File 'lib/mongo/gridfs/grid_store.rb', line 368

def tell
 @position
end

#ungetc(byte) ⇒ Object



260
261
262
263
# File 'lib/mongo/gridfs/grid_store.rb', line 260

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

#write(string) ⇒ Object

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



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

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