large_object_store 1.1.0 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 61880698dc7a3f62cc1eb51390815aa9166e8aa9
4
- data.tar.gz: a76a3eb5076124cdf839fa99a5b4afcaf6ac51b7
3
+ metadata.gz: d47e0ee45bc6fbe4d657974b55acde2b1ed6052e
4
+ data.tar.gz: 461403d43371d4d95d432b2cf695b0f74d0e070a
5
5
  SHA512:
6
- metadata.gz: fc8d52947cd7313d49a3135042b1e832574d86f57b9e6bfc262eb8134a9a73c37bbfaa28dbf828bba404611ea4e734bc09dfd685183cf307ba74ec842bf8bf36
7
- data.tar.gz: 59bf1b2aac7827f387f672e97da33218ed00ae35f3bf92cea3c3aaddbd9e316adb2d68f25d3cd3b06ada7deb12f49a8873603df26cd3a75137832cf7977bd6c0
6
+ metadata.gz: 9ee0ca3c5bbae29874718241d39f7dfecbfb1492503928285f3fe2e1aa4dead61d0744c0c68ca4c92b00bff645cc32dbb4a6138c956a55b06ef373dd6bd8fcfc
7
+ data.tar.gz: 58834c45621095c238af2d3e8f3f291a62fcbb15a83ce8ad32e17aea4664588db926fd9b535a7e3c30b84720cd7738bf8e450d18aeb37f82c397f6e7a344bcce
@@ -1,3 +1,3 @@
1
1
  module LargeObjectStore
2
- VERSION = "1.1.0"
2
+ VERSION = "1.1.1"
3
3
  end
@@ -1,4 +1,5 @@
1
1
  require "large_object_store/version"
2
+ require "zlib"
2
3
 
3
4
  module LargeObjectStore
4
5
 
@@ -9,7 +10,8 @@ module LargeObjectStore
9
10
  class RailsWrapper
10
11
  attr_reader :store
11
12
 
12
- LIMIT = 1024**2 - 100
13
+ MAX_OBJECT_SIZE = 1024**2
14
+ ITEM_HEADER_SIZE = 100
13
15
 
14
16
  def initialize(store)
15
17
  @store = store
@@ -17,26 +19,30 @@ module LargeObjectStore
17
19
 
18
20
  def write(key, value, options = {})
19
21
  value = Marshal.dump(value)
22
+ value = Zlib::Deflate.deflate(value) if options.delete(:compress)
23
+
24
+ # calculate slice size; note that key length is a factor because
25
+ # the key is stored on the same slab page as the value
26
+ slice_size = MAX_OBJECT_SIZE - ITEM_HEADER_SIZE - key.bytesize
20
27
 
21
28
  # store number of pages
22
- pages = (value.size / LIMIT.to_f).ceil
29
+ pages = (value.size / slice_size.to_f).ceil
23
30
 
24
31
  if pages == 1
25
32
  @store.write("#{key}_0", value, options)
26
33
  else
27
- @store.write("#{key}_0", pages, options)
28
-
29
34
  # store object
30
35
  page = 1
31
36
  loop do
32
- slice = value.slice!(0, LIMIT)
37
+ slice = value.slice!(0, slice_size)
33
38
  break if slice.size == 0
34
39
 
35
- @store.write("#{key}_#{page}", slice, options)
40
+ return false unless @store.write("#{key}_#{page}", slice, options.merge(raw: true))
36
41
  page += 1
37
42
  end
43
+
44
+ @store.write("#{key}_0", pages, options)
38
45
  end
39
- true
40
46
  end
41
47
 
42
48
  def read(key)
@@ -44,16 +50,26 @@ module LargeObjectStore
44
50
  pages = @store.read("#{key}_0")
45
51
  return if pages.nil?
46
52
 
47
- data = if pages.is_a?(String)
48
- pages
49
- else
53
+ data = if pages.is_a?(Fixnum)
50
54
  # read sliced data
51
55
  keys = Array.new(pages).each_with_index.map{|_,i| "#{key}_#{i+1}" }
52
56
  slices = @store.read_multi(*keys).values
53
57
  return nil if slices.compact.size < pages
54
58
  slices.join("")
59
+ else
60
+ pages
61
+ end
62
+
63
+ if data.getbyte(0) == 0x78 && [0x01,0x9C,0xDA].include?(data.getbyte(1))
64
+ data = Zlib::Inflate.inflate(data)
65
+ end
66
+
67
+ begin
68
+ Marshal.load(data)
69
+ rescue Exception => e
70
+ Rails.logger.error "Cannot read large_object_store key #{key} : #{e.message} #{e.backtrace.inspect}"
71
+ nil
55
72
  end
56
- Marshal.load(data)
57
73
  end
58
74
 
59
75
  def fetch(key, options={})
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: large_object_store
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ana Martinez
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-06 00:00:00.000000000 Z
11
+ date: 2015-11-17 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email: acemacu@gmail.com
@@ -16,18 +16,10 @@ executables: []
16
16
  extensions: []
17
17
  extra_rdoc_files: []
18
18
  files:
19
- - .travis.yml
20
- - Gemfile
21
- - Gemfile.lock
22
- - Rakefile
23
19
  - Readme.md
24
- - gem-public_cert.pem
25
- - large_object_store.gemspec
26
20
  - lib/large_object_store.rb
27
21
  - lib/large_object_store/version.rb
28
- - spec/large_object_store_spec.rb
29
- - spec/spec_helper.rb
30
- homepage: http://github.com/anamartinez/large_object_store
22
+ homepage: https://github.com/anamartinez/large_object_store
31
23
  licenses:
32
24
  - MIT
33
25
  metadata: {}
@@ -37,17 +29,17 @@ require_paths:
37
29
  - lib
38
30
  required_ruby_version: !ruby/object:Gem::Requirement
39
31
  requirements:
40
- - - '>='
32
+ - - ">="
41
33
  - !ruby/object:Gem::Version
42
34
  version: '0'
43
35
  required_rubygems_version: !ruby/object:Gem::Requirement
44
36
  requirements:
45
- - - '>='
37
+ - - ">="
46
38
  - !ruby/object:Gem::Version
47
39
  version: '0'
48
40
  requirements: []
49
41
  rubyforge_project:
50
- rubygems_version: 2.2.2
42
+ rubygems_version: 2.4.5.1
51
43
  signing_key:
52
44
  specification_version: 4
53
45
  summary: Store large objects in memcache or others
data/.travis.yml DELETED
@@ -1,3 +0,0 @@
1
- rvm:
2
- - 1.9.2
3
- - 1.9.3
data/Gemfile DELETED
@@ -1,6 +0,0 @@
1
- source "https://rubygems.org"
2
- gemspec
3
-
4
- gem "bump"
5
- gem "rake"
6
- gem "rspec", "~>2"
data/Gemfile.lock DELETED
@@ -1,28 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- large_object_store (1.1.0)
5
-
6
- GEM
7
- remote: https://rubygems.org/
8
- specs:
9
- bump (0.3.9)
10
- diff-lcs (1.1.3)
11
- rake (10.0.3)
12
- rspec (2.12.0)
13
- rspec-core (~> 2.12.0)
14
- rspec-expectations (~> 2.12.0)
15
- rspec-mocks (~> 2.12.0)
16
- rspec-core (2.12.2)
17
- rspec-expectations (2.12.1)
18
- diff-lcs (~> 1.1.3)
19
- rspec-mocks (2.12.2)
20
-
21
- PLATFORMS
22
- ruby
23
-
24
- DEPENDENCIES
25
- bump
26
- large_object_store!
27
- rake
28
- rspec (~> 2)
data/Rakefile DELETED
@@ -1,6 +0,0 @@
1
- require "bundler/gem_tasks"
2
- require "bump/tasks"
3
-
4
- task :default do
5
- sh "rspec spec/"
6
- end
data/gem-public_cert.pem DELETED
@@ -1,20 +0,0 @@
1
- -----BEGIN CERTIFICATE-----
2
- MIIDMjCCAhqgAwIBAgIBADANBgkqhkiG9w0BAQUFADA/MRAwDgYDVQQDDAdtaWNo
3
- YWVsMRcwFQYKCZImiZPyLGQBGRYHZ3Jvc3NlcjESMBAGCgmSJomT8ixkARkWAml0
4
- MB4XDTEzMDIwMzE4MTMxMVoXDTE0MDIwMzE4MTMxMVowPzEQMA4GA1UEAwwHbWlj
5
- aGFlbDEXMBUGCgmSJomT8ixkARkWB2dyb3NzZXIxEjAQBgoJkiaJk/IsZAEZFgJp
6
- dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMorXo/hgbUq97+kII9H
7
- MsQcLdC/7wQ1ZP2OshVHPkeP0qH8MBHGg6eYisOX2ubNagF9YTCZWnhrdKrwpLOO
8
- cPLaZbjUjljJ3cQR3B8Yn1veV5IhG86QseTBjymzJWsLpqJ1UZGpfB9tXcsFtuxO
9
- 6vHvcIHdzvc/OUkICttLbH+1qb6rsHUceqh+JrH4GrsJ5H4hAfIdyS2XMK7YRKbh
10
- h+IBu6dFWJJByzFsYmV1PDXln3UBmgAt65cmCu4qPfThioCGDzbSJrGDGLmw/pFX
11
- FPpVCm1zgYSb1v6Qnf3cgXa2f2wYGm17+zAVyIDpwryFru9yF/jJxE38z/DRsd9R
12
- /88CAwEAAaM5MDcwCQYDVR0TBAIwADAdBgNVHQ4EFgQUsiNnXHtKeMYYcr4yJVmQ
13
- WONL+IwwCwYDVR0PBAQDAgSwMA0GCSqGSIb3DQEBBQUAA4IBAQAlyN7kKo/NQCQ0
14
- AOzZLZ3WAePvStkCFIJ53tsv5Kyo4pMAllv+BgPzzBt7qi605mFSL6zBd9uLou+W
15
- Co3s48p1dy7CjjAfVQdmVNHF3MwXtfC2OEyvSQPi4xKR8iba8wa3xp9LVo1PuLpw
16
- /6DsrChWw74HfsJN6qJOK684hJeT8lBYAUfiC3wD0owoPSg+XtyAAddisR+KV5Y1
17
- NmVHuLtQcNTZy+gRht3ahJRMuC6QyLmkTsf+6MaenwAMkAgHdswGsJztOnNnBa3F
18
- y0kCSWmK6D+x/SbfS6r7Ke07MRqziJdB9GuE1+0cIRuFh8EQ+LN6HXCKM5pon/GU
19
- ycwMXfl0
20
- -----END CERTIFICATE-----
@@ -1,17 +0,0 @@
1
- $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
2
- name = "large_object_store"
3
- require "#{name.gsub("-","/")}/version"
4
-
5
- Gem::Specification.new name, LargeObjectStore::VERSION do |s|
6
- s.summary = "Store large objects in memcache or others"
7
- s.authors = ["Ana Martinez"]
8
- s.email = "acemacu@gmail.com"
9
- s.homepage = "http://github.com/anamartinez/#{name}"
10
- s.files = `git ls-files`.split("\n")
11
- s.license = "MIT"
12
- cert = File.expand_path("~/.ssh/gem-private_key.pem")
13
- if File.exist?(cert)
14
- s.signing_key = cert
15
- s.cert_chain = ["gem-public_cert.pem"]
16
- end
17
- end
@@ -1,131 +0,0 @@
1
- # encoding: utf-8
2
- require "spec_helper"
3
-
4
- class TestCache
5
- def initialize
6
- @data = {}
7
- end
8
-
9
- def write(k,v, options={})
10
- v = Marshal.dump(v)
11
- return false if v.bytesize > 1024**2
12
- @data[k] = v
13
- true
14
- end
15
-
16
- def read(k)
17
- real_read(k)
18
- end
19
-
20
- def real_read(k)
21
- v = @data[k]
22
- v.nil? ? nil : Marshal.load(v)
23
- end
24
-
25
- def read_multi(*keys)
26
- Hash[keys.map{|k| [k, real_read(k)] }]
27
- end
28
-
29
- def keys
30
- @data.keys
31
- end
32
-
33
- def delete(key)
34
- @data.delete(key)
35
- end
36
- end
37
-
38
- describe LargeObjectStore do
39
- let(:cache) { TestCache.new }
40
- let(:store) { LargeObjectStore.wrap(cache) }
41
-
42
- it "has a VERSION" do
43
- LargeObjectStore::VERSION.should =~ /^[\.\da-z]+$/
44
- end
45
-
46
- it "wraps and returns a wrapper" do
47
- store.class.should == LargeObjectStore::RailsWrapper
48
- end
49
-
50
- it "can write/read big objects" do
51
- store.write("a", "a"*10_000_000).should == true
52
- store.read("a").size.should == 10_000_000
53
- end
54
-
55
- it "passes options when caching small" do
56
- store.store.should_receive(:write).with(anything, anything, :expires_in => 111)
57
- store.write("a", "a", :expires_in => 111)
58
- end
59
-
60
- it "passes options when caching big" do
61
- store.store.should_receive(:write).with(anything, anything, :expires_in => 111).exactly(3).times
62
- store.write("a", "a"*1_200_000, :expires_in => 111)
63
- end
64
-
65
- it "cannot read corrupted objects" do
66
- store.write("a", ["a"*10_000_000]).should == true
67
- store.store.write("a_4", nil)
68
- store.read("a").should == nil
69
- end
70
-
71
- it "can write/read big non-string objects" do
72
- store.write("a", ["a"*10_000_000]).should == true
73
- store.read("a").first.size.should == 10_000_000
74
- end
75
-
76
- it "can read/write objects with encoding" do
77
- store.write("a", "ß"*10_000_000).should == true
78
- store.read("a").size.should == 10_000_000
79
- end
80
-
81
- it "can write/read giant objects" do
82
- store.write("a", "a"*100_000_000).should == true
83
- store.read("a").size.should == 100_000_000
84
- end
85
-
86
- it "uses necessary keys" do
87
- store.write("a", "a"*5_000_000)
88
- store.store.keys.should == ["a_0", "a_1", "a_2", "a_3", "a_4", "a_5"]
89
- end
90
-
91
- it "uses 1 key when value is small enough" do
92
- store.write("a", "a"*500_000)
93
- store.store.keys.should == ["a_0"]
94
- end
95
-
96
- it "uses read_multi" do
97
- store.write("a", "a"*5_000_000)
98
- store.store.should_receive(:read).with("a_0").and_return 5
99
- store.read("a").size.should == 5_000_000
100
- end
101
-
102
- describe "#fetch" do
103
- it "executes the block on miss" do
104
- store.fetch("a"){ 1 }.should == 1
105
- end
106
-
107
- it "does not execute the block on hit" do
108
- store.fetch("a"){ 1 }
109
- store.fetch("a"){ 2 }.should == 1
110
- end
111
-
112
- it "passes the options" do
113
- store.should_receive(:write).with(anything, anything, :expires_in => 111)
114
- store.fetch("a", :expires_in => 111){ 2 }
115
- end
116
-
117
- it "can fetch false" do
118
- store.fetch("a"){ false }.should == false
119
- store.read("a").should == false
120
- end
121
- end
122
-
123
- describe "#delete" do
124
- it "removes all keys" do
125
- store.write("a", "a"*5_000_000)
126
- store.read("a").should_not == nil
127
- store.delete("a")
128
- store.read("a").should == nil
129
- end
130
- end
131
- end
data/spec/spec_helper.rb DELETED
@@ -1 +0,0 @@
1
- require "large_object_store"