Class: LargeObjectStore::RailsWrapper

Inherits:
Object
  • Object
show all
Defined in:
lib/large_object_store.rb

Constant Summary collapse

MAX_OBJECT_SIZE =
1024**2
ITEM_HEADER_SIZE =
100

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(store) ⇒ RailsWrapper

Returns a new instance of RailsWrapper.



16
17
18
# File 'lib/large_object_store.rb', line 16

def initialize(store)
  @store = store
end

Instance Attribute Details

#storeObject (readonly)

Returns the value of attribute store.



11
12
13
# File 'lib/large_object_store.rb', line 11

def store
  @store
end

Instance Method Details

#delete(key) ⇒ Object



83
84
85
# File 'lib/large_object_store.rb', line 83

def delete(key)
  @store.delete("#{key}_0")
end

#fetch(key, options = {}) ⇒ Object



75
76
77
78
79
80
81
# File 'lib/large_object_store.rb', line 75

def fetch(key, options={})
  value = read(key)
  return value unless value.nil?
  value = yield
  write(key, value, options)
  value
end

#read(key) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/large_object_store.rb', line 48

def read(key)
  # read pages
  pages = @store.read("#{key}_0")
  return if pages.nil?

  data = if pages.is_a?(Fixnum)
    # read sliced data
    keys = Array.new(pages).each_with_index.map{|_,i| "#{key}_#{i+1}" }
    slices = @store.read_multi(*keys).values
    return nil if slices.compact.size < pages
    slices.join("")
  else
    pages
  end

  if data.getbyte(0) == 0x78 && [0x01,0x9C,0xDA].include?(data.getbyte(1))
    data = Zlib::Inflate.inflate(data)
  end

  begin
    Marshal.load(data)
  rescue Exception => e
    Rails.logger.error "Cannot read large_object_store key #{key} : #{e.message} #{e.backtrace.inspect}"
    nil
  end
end

#write(key, value, options = {}) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/large_object_store.rb', line 20

def write(key, value, options = {})
  value = Marshal.dump(value)
  value = Zlib::Deflate.deflate(value) if options.delete(:compress)

  # calculate slice size; note that key length is a factor because
  # the key is stored on the same slab page as the value
  slice_size = MAX_OBJECT_SIZE - ITEM_HEADER_SIZE - key.bytesize

  # store number of pages
  pages = (value.size / slice_size.to_f).ceil

  if pages == 1
    @store.write("#{key}_0", value, options)
  else
    # store object
    page = 1
    loop do
      slice = value.slice!(0, slice_size)
      break if slice.size == 0

      return false unless @store.write("#{key}_#{page}", slice, options.merge(raw: true))
      page += 1
    end

    @store.write("#{key}_0", pages, options)
  end
end