Class: Store::Digest

Inherits:
Object
  • Object
show all
Defined in:
lib/store/digest/blob.rb,
lib/store/digest/version.rb,
lib/store/digest.rb

Defined Under Namespace

Modules: Blob, Driver, Meta, Trait Classes: Object, Stats

Constant Summary collapse

VERSION =
"0.3.0"

Instance Method Summary collapse

Constructor Details

#initialize(**options) ⇒ Digest

Initialize a storage

Raises:

  • (ArgumentError)


52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/store/digest.rb', line 52

def initialize **options
  driver = options.delete(:driver) || Store::Digest::Driver::LMDB

  unless driver.is_a? Module
    # coerce to symbol
    driver = driver.to_s.to_sym
    raise ArgumentError,
      "There is no storage driver Store::Digest::Driver::#{driver}" unless
      Store::Digest::Driver.const_defined? driver
    driver = Store::Digest::Driver.const_get driver
  end

  raise ArgumentError,
    "Driver #{driver} is not a Store::Digest::Driver" unless
    driver.ancestors.include? Store::Digest::Driver

  extend driver

  #
  setup(**options)
end

Instance Method Details

#add(obj, type: nil, charset: nil, language: nil, encoding: nil, mtime: nil, strict: true, preserve: false) ⇒ Store::Digest::Object

Note:

Prefabricated Object instances will be rescanned.

Note:

‘:preserve` will cause a noop if object metadata is identical save for `:ctime` and `:mtime` (`:ctime` is always ignored).

Add an object to the store. Takes pretty much anything that makes sense to throw at it.

Parameters:

  • obj (IO, File, Pathname, String, Store::Digest::Object)

    the object

  • type (String) (defaults to: nil)

    the content type

  • charset (String) (defaults to: nil)

    the character set, if applicable

  • language (String) (defaults to: nil)

    the language, if applicable

  • encoding (String) (defaults to: nil)

    the encoding (eg compression) if applicable

  • mtime (Time) (defaults to: nil)

    the modification time, if not “now”

  • strict (true, false) (defaults to: true)

    strict checking on metadata input

  • preserve (false, true) (defaults to: false)

    preserve existing modification time

Returns:



102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
# File 'lib/store/digest.rb', line 102

def add obj, type: nil, charset: nil, language: nil, encoding: nil,
    mtime: nil, strict: true, preserve: false
  return unless obj

  transaction do # |txn|
    obj = coerce_object obj, type: type, charset: charset,
      language: language, encoding: encoding, mtime: mtime, strict: strict
    raise ArgumentError, 'We need something to store!' unless obj.content?

    # this method is helicoptered in
    tmp = temp_blob

    # XXX this is stupid; figure out a better way to do this

    # get our digests
    obj.scan(digests: algorithms, blocksize: 2**20, strict: strict,
      type: type, charset: charset, language: language,
      encoding: encoding, mtime: mtime) do |buf|
      tmp << buf
    end

    # if we are scanning an object it is necessarily not deleted
    obj.dtime = nil

    # set_meta will return nil if there is no difference in what is set
    if h = set_meta(obj, preserve: preserve)
      # warn h.inspect
      # replace the object

      content = obj.content

      # do this to prevent too many open files
      if content.is_a? File
        path = Pathname(content.path).expand_path
        content = -> { path.open('rb') }
      end

      obj = Store::Digest::Object.new content, fresh: true, **h

      # now settle the blob into storage
      settle_blob obj[primary].digest, tmp, mtime: obj.mtime
    else
      tmp.close
      tmp.unlink

      # warn "got here lolol"

      # eh just do this
      obj = get obj
      obj.fresh = false # object is not fresh since we already have it
    end

    obj
  end
end

#forget(obj) ⇒ Object

Remove an object from the store and “forget” it ever existed, i.e., purge it from the metadata.



196
197
198
# File 'lib/store/digest.rb', line 196

def forget obj
  remove obj, forget: true
end

#get(obj) ⇒ Store::Digest::Object?

Retrieve an object from the store.

Parameters:

Returns:



163
164
165
166
167
168
169
170
171
# File 'lib/store/digest.rb', line 163

def get obj
  transaction readonly: true do
    obj = coerce_object obj
    if h = get_meta(obj) # bail if this does not exist
      b = get_blob h[:digests][primary].digest # may be nil
      Store::Digest::Object.new b, **h
    end
  end
end

#remove(obj, forget: false) ⇒ Object

Remove an object from the store, optionally “forgetting” it ever existed.

Parameters:

  • obj


175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/store/digest.rb', line 175

def remove obj, forget: false
  obj  = coerce_object obj
  unless obj.scanned?
    raise ArgumentError,
      'Cannot scan object because there is no content' unless obj.content?
    obj.scan digests: algorithms, blocksize: 2**20
  end

  # remove or mark metadata entry as deleted and remove blob
  transaction do
    if meta = forget ? remove_meta(obj) : mark_meta_deleted(obj)
      if blob = remove_blob(meta[:digests][primary].digest)
        Store::Digest::Object.new blob, **meta
      end
    end
  end
end

#statsObject

Return statistics on the store



201
202
203
# File 'lib/store/digest.rb', line 201

def stats
  Stats.new(**meta_get_stats)
end