Class: Mongo::GridIO

Inherits:
Object show all
Includes:
WriteConcern
Defined in:
lib/mongo/gridfs/grid_io.rb

Overview

GridIO objects represent files in the GridFS specification. This class manages the reading and writing of file chunks and metadata.

Constant Summary collapse

DEFAULT_CHUNK_SIZE =
256 * 1024
DEFAULT_CONTENT_TYPE =
'binary/octet-stream'
PROTECTED_ATTRS =
[:files_id, :file_length, :client_md5, :server_md5]

Instance Attribute Summary collapse

Attributes included from WriteConcern

#legacy_write_concern

Instance Method Summary collapse

Methods included from WriteConcern

#get_write_concern, gle?, #write_concern_from_legacy

Constructor Details

#initialize(files, chunks, filename, mode, opts = {}) ⇒ GridIO

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

Parameters:

  • files (Mongo::Collection)

    a collection for storing file metadata.

  • chunks (Mongo::Collection)

    a collection for storing file chunks.

  • filename (String)

    the name of the file to open or write.

  • mode (String)

    ‘r’ or ‘w’ or reading or creating a file.

  • opts (Hash) (defaults to: {})

    a customizable set of options

Options Hash (opts):

  • :query (Hash)

    a query selector used when opening the file in ‘r’ mode.

  • :query_opts (Hash)

    any query options to be used when opening the file in ‘r’ mode.

  • :fs_name (String)

    the file system prefix.

  • (262144) (Integer)

    :chunk_size size of file chunks in bytes.

  • :metadata (Hash) — default: {}

    any additional data to store with the file.

  • :_id (ObjectId) — default: ObjectId

    a unique id for the file to be use in lieu of an automatically generated one.

  • :content_type (String) — default: 'binary/octet-stream'

    If no content type is specified, the content type will may be inferred from the filename extension if the mime-types gem can be loaded. Otherwise, the content type ‘binary/octet-stream’ will be used.

  • :w (String, Integer, Symbol) — default: 1

    Set the write concern

    Notes on write concern:

    When :w > 0, the chunks sent to the server
    will be validated using an md5 hash. If validation fails, an exception will be raised.
    


58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/mongo/gridfs/grid_io.rb', line 58

def initialize(files, chunks, filename, mode, opts={})
  @files          = files
  @chunks         = chunks
  @filename       = filename
  @mode           = mode
  opts            = opts.dup
  @query          = opts.delete(:query) || {}
  @query_opts     = opts.delete(:query_opts) || {}
  @fs_name        = opts.delete(:fs_name) || Grid::DEFAULT_FS_NAME
  @write_concern  = get_write_concern(opts)
  @local_md5      = Digest::MD5.new if Mongo::WriteConcern.gle?(@write_concern)
  @custom_attrs   = {}

  case @mode
    when 'r' then init_read
    when 'w' then init_write(opts)
    else
      raise GridError, "Invalid file mode #{@mode}. Mode should be 'r' or 'w'."
  end
end

Instance Attribute Details

#chunk_sizeObject (readonly)

Returns the value of attribute chunk_size.



32
33
34
# File 'lib/mongo/gridfs/grid_io.rb', line 32

def chunk_size
  @chunk_size
end

#client_md5Object (readonly)

Returns the value of attribute client_md5.



32
33
34
# File 'lib/mongo/gridfs/grid_io.rb', line 32

def client_md5
  @client_md5
end

#content_typeObject (readonly)

Returns the value of attribute content_type.



32
33
34
# File 'lib/mongo/gridfs/grid_io.rb', line 32

def content_type
  @content_type
end

#file_lengthObject (readonly)

Returns the value of attribute file_length.



32
33
34
# File 'lib/mongo/gridfs/grid_io.rb', line 32

def file_length
  @file_length
end

#file_positionObject (readonly)

Returns the value of attribute file_position.



32
33
34
# File 'lib/mongo/gridfs/grid_io.rb', line 32

def file_position
  @file_position
end

#filenameObject (readonly)

Returns the value of attribute filename.



32
33
34
# File 'lib/mongo/gridfs/grid_io.rb', line 32

def filename
  @filename
end

#files_idObject (readonly)

Returns the value of attribute files_id.



32
33
34
# File 'lib/mongo/gridfs/grid_io.rb', line 32

def files_id
  @files_id
end

#metadataObject (readonly)

Returns the value of attribute metadata.



32
33
34
# File 'lib/mongo/gridfs/grid_io.rb', line 32

def 
  @metadata
end

#server_md5Object (readonly)

Returns the value of attribute server_md5.



32
33
34
# File 'lib/mongo/gridfs/grid_io.rb', line 32

def server_md5
  @server_md5
end

#upload_dateObject (readonly)

Returns the value of attribute upload_date.



32
33
34
# File 'lib/mongo/gridfs/grid_io.rb', line 32

def upload_date
  @upload_date
end

Instance Method Details

#[](key) ⇒ Object



79
80
81
# File 'lib/mongo/gridfs/grid_io.rb', line 79

def [](key)
  @custom_attrs[key] || instance_variable_get("@#{key.to_s}")
end

#[]=(key, value) ⇒ Object



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

def []=(key, value)
  if PROTECTED_ATTRS.include?(key.to_sym)
    warn "Attempting to overwrite protected value."
    return nil
  else
    @custom_attrs[key] = value
  end
end

#closeBSON::ObjectId

Creates or updates the document from the files collection that stores the chunks’ metadata. The file becomes available only after this method has been called.

This method will be invoked automatically when on GridIO#open is passed a block. Otherwise, it must be called manually.

Returns:

  • (BSON::ObjectId)


237
238
239
240
241
242
243
244
245
246
# File 'lib/mongo/gridfs/grid_io.rb', line 237

def close
  if @mode[0] == ?w
    if @current_chunk['n'].zero? && @chunk_position.zero?
      warn "Warning: Storing a file with zero length."
    end
    @upload_date = Time.now.utc
    id = @files.insert(to_mongo_object)
  end
  id
end

#each { ... } ⇒ Mongo::GridIO

Read a chunk of the data from the file and yield it to the given block.

Note that this method reads from the current file position.

Yields:

  • Yields on chunk per iteration as defined by this file’s chunk size.

Returns:



257
258
259
260
261
262
263
264
# File 'lib/mongo/gridfs/grid_io.rb', line 257

def each
  return read_all unless block_given?
  while chunk = read(chunk_size) 
    yield chunk
    break if chunk.empty?
  end
  self
end

#eofBoolean Also known as: eof?

Return a boolean indicating whether the position pointer is at the end of the file.

Returns:

  • (Boolean)

Raises:



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

def eof
  raise GridError, "file not opened for read #{@mode}" unless @mode[0] == ?r
  @file_position >= @file_length
end

#getcString

Return the next byte from the GridFS file.

Returns:



225
226
227
# File 'lib/mongo/gridfs/grid_io.rb', line 225

def getc
  read_length(1)
end

#gets(separator = "\n", length = nil) ⇒ String

Return the next line from a GridFS file. This probably makes sense only if you’re storing plain text. This method has a somewhat tricky API, which it inherits from Ruby’s StringIO#gets.

Parameters:

  • separator (String, Integer) (defaults to: "\n")

    or length. If a separator, read up to the separator. If a length, read the length number of bytes. If nil, read the entire file.

  • length (Integer) (defaults to: nil)

    If a separator is provided, then read until either finding the separator or passing over the length number of bytes.

Returns:



210
211
212
213
214
215
216
217
218
219
220
# File 'lib/mongo/gridfs/grid_io.rb', line 210

def gets(separator="\n", length=nil)
  if separator.nil?
    read_all
  elsif separator.is_a?(Integer)
    read_length(separator)
  elsif separator.length > 1
    read_to_string(separator, length)
  else
    read_to_character(separator, length)
  end
end

#inspectObject



266
267
268
# File 'lib/mongo/gridfs/grid_io.rb', line 266

def inspect
  "#<GridIO _id: #{@files_id}>"
end

#read(length = nil) ⇒ String Also known as: data

Read the data from the file. If a length if specified, will read from the current file position.

Parameters:

  • length (Integer) (defaults to: nil)

Returns:

  • (String)

    the data in the file



99
100
101
102
103
104
105
106
107
108
# File 'lib/mongo/gridfs/grid_io.rb', line 99

def read(length=nil)
  return '' if @file_length.zero?
  if length == 0
    return ''
  elsif length.nil? && @file_position.zero?
    read_all
  else
    read_length(length)
  end
end

#rewindInteger

Rewind the file. This is equivalent to seeking to the zeroth position.

Returns:

  • (Integer)

    the position of the file after rewinding (always zero).

Raises:



182
183
184
185
# File 'lib/mongo/gridfs/grid_io.rb', line 182

def rewind
  raise GridError, "file not opened for read" unless @mode[0] == ?r
  seek(0)
end

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

Position the file pointer at the provided location.

Parameters:

  • pos (Integer)

    the number of bytes to advance the file pointer. this can be a negative number.

  • whence (Integer) (defaults to: IO::SEEK_SET)

    one of IO::SEEK_CUR, IO::SEEK_END, or IO::SEEK_SET

Returns:

  • (Integer)

    the new file position

Raises:



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/mongo/gridfs/grid_io.rb', line 150

def seek(pos, whence=IO::SEEK_SET)
  raise GridError, "Seek is only allowed in read mode." unless @mode == 'r'
  target_pos = case whence
               when IO::SEEK_CUR
                 @file_position + pos
               when IO::SEEK_END
                 @file_length + pos
               when IO::SEEK_SET
                 pos
               end

  new_chunk_number = (target_pos / @chunk_size).to_i
  if new_chunk_number != @current_chunk['n']
    save_chunk(@current_chunk) if @mode[0] == ?w
    @current_chunk = get_chunk(new_chunk_number)
  end
  @file_position  = target_pos
  @chunk_position = @file_position % @chunk_size
  @file_position
end

#tellInteger Also known as: pos

The current position of the file.

Returns:

  • (Integer)


174
175
176
# File 'lib/mongo/gridfs/grid_io.rb', line 174

def tell
  @file_position
end

#write(io) ⇒ Integer

Write the given string (binary) data to the file.

Parameters:

  • string (String)

    the data to write

Returns:

  • (Integer)

    the number of bytes written.

Raises:



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/mongo/gridfs/grid_io.rb', line 118

def write(io)
  raise GridError, "file not opened for write" unless @mode[0] == ?w
  if io.is_a? String
    if Mongo::WriteConcern.gle?(@write_concern)
      @local_md5.update(io)
    end
    write_string(io)
  else
    length = 0
    if Mongo::WriteConcern.gle?(@write_concern)
      while(string = io.read(@chunk_size))
        @local_md5.update(string)
        length += write_string(string)
      end
    else
      while(string = io.read(@chunk_size))
        length += write_string(string)
      end
    end
    length
  end
end