cache_lib 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,98 @@
1
+ require 'monitor'
2
+
3
+ module CacheLib
4
+ module SafeSync
5
+ include MonitorMixin
6
+
7
+ def initialize(*args)
8
+ super(*args)
9
+ end
10
+
11
+ def limit
12
+ synchronize do
13
+ super
14
+ end
15
+ end
16
+
17
+ def limit=(*args)
18
+ synchronize do
19
+ super(*args)
20
+ end
21
+ end
22
+
23
+ def get(key)
24
+ synchronize do
25
+ super(key)
26
+ end
27
+ end
28
+
29
+ def store(key, value)
30
+ synchronize do
31
+ super(key, value)
32
+ end
33
+ end
34
+
35
+ def lookup(key)
36
+ synchronize do
37
+ super(key)
38
+ end
39
+ end
40
+
41
+ def fetch(key)
42
+ synchronize do
43
+ super(key)
44
+ end
45
+ end
46
+
47
+ def evict(key)
48
+ synchronize do
49
+ super(key)
50
+ end
51
+ end
52
+
53
+ def clear
54
+ synchronize do
55
+ super
56
+ end
57
+ end
58
+
59
+ def each
60
+ synchronize do
61
+ super
62
+ end
63
+ end
64
+
65
+ def key?(key)
66
+ synchronize do
67
+ super(key)
68
+ end
69
+ end
70
+
71
+ def to_a
72
+ synchronize do
73
+ super
74
+ end
75
+ end
76
+
77
+ def size
78
+ synchronize do
79
+ super
80
+ end
81
+ end
82
+
83
+ def raw
84
+ synchronize do
85
+ super
86
+ end
87
+ end
88
+
89
+ def inspect
90
+ synchronize do
91
+ super
92
+ end
93
+ end
94
+
95
+ alias_method :[], :lookup
96
+ alias_method :[]=, :store
97
+ end
98
+ end
@@ -0,0 +1,29 @@
1
+ module CacheLib
2
+ class UtilHash < Hash
3
+ def head
4
+ keys.last
5
+ end
6
+
7
+ def tail
8
+ first[0]
9
+ end
10
+
11
+ def set_head(key, value)
12
+ delete(key)
13
+ self[key] = value
14
+ end
15
+
16
+ def set_tail(key, value)
17
+ replace(Hash[key, value].merge(self))
18
+ end
19
+
20
+ def pop_tail
21
+ delete(tail)
22
+ end
23
+
24
+ def refresh(key)
25
+ value = delete(key)
26
+ self[key] = value
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,3 @@
1
+ module CacheLib
2
+ VERSION = '0.0.1'
3
+ end
data/lib/cache_lib.rb ADDED
@@ -0,0 +1,32 @@
1
+ require_relative 'cache_lib/util_hash'
2
+ require_relative 'cache_lib/basic_cache'
3
+ require_relative 'cache_lib/fifo_cache'
4
+ require_relative 'cache_lib/lru_cache'
5
+ require_relative 'cache_lib/lirs_cache'
6
+ require_relative 'cache_lib/safe_basic_cache'
7
+ require_relative 'cache_lib/safe_fifo_cache'
8
+ require_relative 'cache_lib/safe_lru_cache'
9
+ require_relative 'cache_lib/safe_lirs_cache'
10
+ require_relative 'cache_lib/version'
11
+
12
+ module CacheLib
13
+ def self.create(type, *args)
14
+ case type
15
+ when :basic then BasicCache.new(*args)
16
+ when :fifo then FifoCache.new(*args)
17
+ when :lru then LruCache.new(*args)
18
+ when :lirs then LirsCache.new(*args)
19
+ else fail ArgumentError "Cache type not recognized: #{type}"
20
+ end
21
+ end
22
+
23
+ def self.safe_create(type, *args)
24
+ case type
25
+ when :basic then SafeBasicCache.new(*args)
26
+ when :fifo then SafeFifoCache.new(*args)
27
+ when :lru then SafeLruCache.new(*args)
28
+ when :lirs then SafeLirsCache.new(*args)
29
+ else fail ArgumentError "Cache type not recognized: #{type}"
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,131 @@
1
+ require 'cache_lib'
2
+ require 'minitest/autorun'
3
+
4
+ class TestBasicCache < MiniTest::Test
5
+ def setup
6
+ @cache = CacheLib.create :basic
7
+ end
8
+
9
+ def test_limit
10
+ assert_equal nil, @cache.limit
11
+ end
12
+
13
+ def test_set_limit
14
+ @cache.limit = 90
15
+
16
+ assert_equal nil, @cache.limit
17
+ end
18
+
19
+ def test_get
20
+ assert_equal 1, @cache.get(:a) { 1 }
21
+ assert_equal 1, @cache.get(:a) { 2 }
22
+ assert_equal 2, @cache.get(:b) { 2 }
23
+ end
24
+
25
+ def test_store
26
+ assert_equal 1, @cache.store(:a, 1)
27
+ assert_equal 2, @cache.store(:a, 2)
28
+ assert_equal 2, @cache.store(:b, 2)
29
+
30
+ assert_equal 3, @cache[:a] = 3
31
+ assert_equal 4, @cache[:b] = 4
32
+ end
33
+
34
+ def test_lookup
35
+ @cache.store(:a, 1)
36
+ @cache.store(:b, 2)
37
+
38
+ assert_equal 1, @cache.lookup(:a)
39
+ assert_equal nil, @cache.lookup(:z)
40
+
41
+ assert_equal 2, @cache[:b]
42
+ assert_equal nil, @cache[:z]
43
+ end
44
+
45
+ def test_fetch
46
+ @cache.store(:a, 1)
47
+ @cache.store(:b, 2)
48
+
49
+ assert_equal 1, @cache.fetch(:a)
50
+ assert_equal 2, @cache.fetch(:b) { 'b' }
51
+ assert_equal nil, @cache.fetch(:y)
52
+ assert_equal 26, @cache.fetch(:z) { 26 }
53
+
54
+ assert_equal 2, @cache[:b]
55
+ assert_equal nil, @cache[:z]
56
+ end
57
+
58
+ def test_evict
59
+ @cache.store(:a, 1)
60
+ @cache.store(:b, 2)
61
+
62
+ assert_equal 1, @cache.evict(:a)
63
+ assert_equal nil, @cache.evict(:z)
64
+
65
+ assert_equal nil, @cache.lookup(:a)
66
+ end
67
+
68
+ def test_clear
69
+ @cache.store(:a, 1)
70
+ @cache.store(:b, 2)
71
+
72
+ assert_equal(nil, @cache.clear)
73
+
74
+ assert_equal nil, @cache.lookup(:a)
75
+ assert_equal nil, @cache.lookup(:b)
76
+ end
77
+
78
+ def test_key?
79
+ @cache.store(:a, 1)
80
+
81
+ assert_equal true, @cache.key?(:a)
82
+ assert_equal false, @cache.key?(:z)
83
+ end
84
+
85
+ def test_to_a
86
+ @cache.store(:a, 1)
87
+ @cache.store(:b, 2)
88
+
89
+ assert_equal [[:b, 2], [:a, 1]], @cache.to_a
90
+ end
91
+
92
+ def test_keys
93
+ @cache.store(:a, 1)
94
+ @cache.store(:b, 2)
95
+
96
+ assert_equal [:b, :a], @cache.keys
97
+ end
98
+
99
+ def test_values
100
+ @cache.store(:a, 1)
101
+ @cache.store(:b, 2)
102
+
103
+ assert_equal [2, 1], @cache.values
104
+ end
105
+
106
+ def test_size
107
+ @cache.store(:a, 1)
108
+
109
+ assert_equal 1, @cache.size
110
+
111
+ @cache.store(:b, 2)
112
+
113
+ assert_equal 2, @cache.size
114
+ end
115
+
116
+ def test_raw
117
+ @cache.store(:a, 1)
118
+ @cache.store(:b, 2)
119
+
120
+ assert_equal({ a: 1, b: 2 }, @cache.raw[:cache])
121
+ assert_equal CacheLib::UtilHash, @cache.raw[:cache].class
122
+ end
123
+
124
+ def test_inspect
125
+ @cache.store(:a, 1)
126
+ @cache.store(:b, 2)
127
+
128
+ assert_equal "#{@cache.class} currently caching 2 items.",
129
+ @cache.inspect
130
+ end
131
+ end
@@ -0,0 +1,38 @@
1
+ require 'cache_lib'
2
+ require 'minitest/autorun'
3
+
4
+ class TestCacheLib < MiniTest::Test
5
+ def test_create
6
+ basic = CacheLib.create :basic
7
+ fifo = CacheLib.create :fifo, 1_000
8
+ lru = CacheLib.create :lru, 1_000
9
+ lirs = CacheLib.create :lirs, 950, 50
10
+
11
+ assert_equal basic.class, CacheLib::BasicCache
12
+ assert_equal fifo.class, CacheLib::FifoCache
13
+ assert_equal lru.class, CacheLib::LruCache
14
+ assert_equal lirs.class, CacheLib::LirsCache
15
+
16
+ assert_equal basic.limit, nil
17
+ assert_equal fifo.limit, 1_000
18
+ assert_equal lru.limit, 1_000
19
+ assert_equal lirs.limit, 1_000
20
+ end
21
+
22
+ def test_safe_create
23
+ basic = CacheLib.safe_create :basic
24
+ fifo = CacheLib.safe_create :fifo, 1_000
25
+ lru = CacheLib.safe_create :lru, 1_000
26
+ lirs = CacheLib.safe_create :lirs, 950, 50
27
+
28
+ assert_equal basic.class, CacheLib::SafeBasicCache
29
+ assert_equal fifo.class, CacheLib::SafeFifoCache
30
+ assert_equal lru.class, CacheLib::SafeLruCache
31
+ assert_equal lirs.class, CacheLib::SafeLirsCache
32
+
33
+ assert_equal basic.limit, nil
34
+ assert_equal fifo.limit, 1_000
35
+ assert_equal lru.limit, 1_000
36
+ assert_equal lirs.limit, 1_000
37
+ end
38
+ end
@@ -0,0 +1,56 @@
1
+ require 'cache_lib'
2
+ require 'minitest/autorun'
3
+
4
+ require_relative 'test_basic_cache'
5
+
6
+ class TestFifoCache < TestBasicCache
7
+ def setup
8
+ @cache = CacheLib.create :fifo, 5
9
+ end
10
+
11
+ def test_limit
12
+ assert_equal 5, @cache.limit
13
+ end
14
+
15
+ def test_set_limit
16
+ @cache.limit = 90
17
+
18
+ assert_equal 90, @cache.limit
19
+ end
20
+
21
+ def test_inspect
22
+ @cache.store(:a, 1)
23
+ @cache.store(:b, 2)
24
+
25
+ assert_equal "#{@cache.class} with a limit of 5 "\
26
+ "currently caching 2 items.",
27
+ @cache.inspect
28
+ end
29
+
30
+ def test_fifo_eviction
31
+ (1..6).each { |i| @cache.store(i, i) }
32
+
33
+ assert_equal 5, @cache.size
34
+ assert_equal({ 2 => 2, 3 => 3, 4 => 4, 5 => 5, 6 => 6 },
35
+ @cache.raw[:cache])
36
+ end
37
+
38
+ def test_upsize
39
+ (1..5).each { |i| @cache.store(i, i) }
40
+ @cache.limit = 7
41
+ (6..8).each { |i| @cache.store(i, i) }
42
+
43
+ assert_equal 7, @cache.size
44
+ assert_equal({ 2 => 2, 3 => 3, 4 => 4, 5 => 5,
45
+ 6 => 6, 7 => 7, 8 => 8 },
46
+ @cache.raw[:cache])
47
+ end
48
+
49
+ def test_downsize
50
+ (1..5).each { |i| @cache.store(i, i) }
51
+ @cache.limit = 3
52
+
53
+ assert_equal 3, @cache.size
54
+ assert_equal({ 3 => 3, 4 => 4, 5 => 5 }, @cache.raw[:cache])
55
+ end
56
+ end
@@ -0,0 +1,106 @@
1
+ require 'cache_lib'
2
+ require 'minitest/autorun'
3
+
4
+ require_relative 'test_basic_cache'
5
+
6
+ class TestLirsCache < TestBasicCache
7
+ def setup
8
+ @cache = CacheLib.create :lirs, 3, 2
9
+ end
10
+
11
+ def test_limit
12
+ assert_equal 5, @cache.limit
13
+ end
14
+
15
+ def test_set_limit
16
+ @cache.limit = 95, 5
17
+
18
+ assert_equal 100, @cache.limit
19
+ end
20
+
21
+ def test_inspect
22
+ @cache.store(:a, 1)
23
+ @cache.store(:b, 2)
24
+
25
+ assert_equal "#{@cache.class} with a limit of 5, "\
26
+ "s_limit of 3 and q_limit of 2 "\
27
+ "currently caching 2 items.",
28
+ @cache.inspect
29
+ end
30
+
31
+ def test_raw
32
+ @cache.store(:a, 1)
33
+ @cache.store(:b, 2)
34
+
35
+ raw_cache = @cache.raw
36
+
37
+ assert_equal({ a: 1, b: 2 }, raw_cache[:cache])
38
+ assert_equal({ a: nil, b: nil }, raw_cache[:stack])
39
+ assert_equal({}, raw_cache[:queue])
40
+
41
+ assert_equal CacheLib::UtilHash, raw_cache[:cache].class
42
+ assert_equal CacheLib::UtilHash, raw_cache[:stack].class
43
+ assert_equal CacheLib::UtilHash, raw_cache[:queue].class
44
+ end
45
+
46
+ def test_lirs_promotion
47
+ (1..5).each { |i| @cache.store(i, i) }
48
+ @cache.lookup(4)
49
+ @cache.lookup(1)
50
+
51
+ raw_cache = @cache.raw
52
+
53
+ assert_equal({ 1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5 },
54
+ raw_cache[:cache])
55
+ assert_equal({ 2 => nil, 3 => nil, 5 => nil, 4 => nil, 1 => nil },
56
+ raw_cache[:stack])
57
+ assert_equal({ 5 => nil, 1 => nil }, raw_cache[:queue])
58
+ end
59
+
60
+ def test_lirs_eviction
61
+ (1..5).each { |i| @cache.store(i, i) }
62
+ @cache.lookup(4)
63
+ @cache.lookup(1)
64
+ @cache.store(6, 6)
65
+
66
+ raw_cache = @cache.raw
67
+
68
+ assert_equal 5, @cache.size
69
+ assert_equal({ 1 => 1, 2 => 2, 3 => 3, 4 => 4, 6 => 6 },
70
+ raw_cache[:cache])
71
+ assert_equal({ 2 => nil, 3 => nil, 5 => nil,
72
+ 4 => nil, 1 => nil, 6 => nil },
73
+ raw_cache[:stack])
74
+ assert_equal({ 1 => nil, 6 => nil }, raw_cache[:queue])
75
+ end
76
+
77
+ def test_upsize
78
+ (1..5).each { |i| @cache.store(i, i) }
79
+ @cache.limit = 5, 2
80
+ (6..8).each { |i| @cache.store(i, i) }
81
+
82
+ raw_cache = @cache.raw
83
+
84
+ assert_equal 7, @cache.size
85
+ assert_equal({ 1 => 1, 2 => 2, 3 => 3, 4 => 4,
86
+ 5 => 5, 7 => 7, 8 => 8 },
87
+ raw_cache[:cache])
88
+ assert_equal({ 1 => nil, 2 => nil, 3 => nil, 4 => nil,
89
+ 5 => nil, 6 => nil, 7 => nil, 8 => nil },
90
+ raw_cache[:stack])
91
+ assert_equal({ 7 => nil, 8 => nil }, raw_cache[:queue])
92
+ end
93
+
94
+ def test_downsize
95
+ (1..5).each { |i| @cache.store(i, i) }
96
+ @cache.limit = 2, 1
97
+
98
+ raw_cache = @cache.raw
99
+
100
+ assert_equal 3, @cache.size
101
+ assert_equal({ 1 => 1, 2 => 2, 3 => 3 }, raw_cache[:cache])
102
+ assert_equal({ 2 => nil, 3 => nil, 4 => nil, 5 => nil },
103
+ raw_cache[:stack])
104
+ assert_equal({ 1 => nil }, raw_cache[:queue])
105
+ end
106
+ end
@@ -0,0 +1,68 @@
1
+ require 'cache_lib'
2
+ require 'minitest/autorun'
3
+
4
+ require_relative 'test_basic_cache'
5
+
6
+ class TestLruCache < TestBasicCache
7
+ def setup
8
+ @cache = CacheLib.create :lru, 5
9
+ end
10
+
11
+ def test_limit
12
+ assert_equal 5, @cache.limit
13
+ end
14
+
15
+ def test_set_limit
16
+ @cache.limit = 90
17
+
18
+ assert_equal 90, @cache.limit
19
+ end
20
+
21
+ def test_inspect
22
+ @cache.store(:a, 1)
23
+ @cache.store(:b, 2)
24
+
25
+ assert_equal "#{@cache.class} with a limit of 5 "\
26
+ "currently caching 2 items.",
27
+ @cache.inspect
28
+ end
29
+
30
+ def test_lru_promotion
31
+ (1..5).each { |i| @cache.store(i, i) }
32
+ @cache.lookup(3)
33
+ @cache.lookup(1)
34
+
35
+ assert_equal({ 2 => 2, 4 => 4, 5 => 5, 3 => 3, 1 => 1 },
36
+ @cache.raw[:cache])
37
+ end
38
+
39
+ def test_lru_eviction
40
+ (1..5).each { |i| @cache.store(i, i) }
41
+ @cache.lookup(3)
42
+ @cache.lookup(1)
43
+ @cache.store(6, 6)
44
+
45
+ assert_equal 5, @cache.size
46
+ assert_equal({ 4 => 4, 5 => 5, 3 => 3, 1 => 1, 6 => 6 },
47
+ @cache.raw[:cache])
48
+ end
49
+
50
+ def test_upsize
51
+ (1..5).each { |i| @cache.store(i, i) }
52
+ @cache.limit = 7
53
+ (6..8).each { |i| @cache.store(i, i) }
54
+
55
+ assert_equal 7, @cache.size
56
+ assert_equal({ 2 => 2, 3 => 3, 4 => 4, 5 => 5,
57
+ 6 => 6, 7 => 7, 8 => 8 },
58
+ @cache.raw[:cache])
59
+ end
60
+
61
+ def test_downsize
62
+ (1..5).each { |i| @cache.store(i, i) }
63
+ @cache.limit = 3
64
+
65
+ assert_equal 3, @cache.size
66
+ assert_equal({ 3 => 3, 4 => 4, 5 => 5 }, @cache.raw[:cache])
67
+ end
68
+ end
@@ -0,0 +1,10 @@
1
+ require 'cache_lib'
2
+ require 'minitest/autorun'
3
+
4
+ require_relative 'test_basic_cache'
5
+
6
+ class TestSafeBasicCache < TestBasicCache
7
+ def setup
8
+ @cache = CacheLib.safe_create :basic
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ require 'cache_lib'
2
+ require 'minitest/autorun'
3
+
4
+ require_relative 'test_fifo_cache'
5
+
6
+ class TestSafeFifoCache < TestFifoCache
7
+ def setup
8
+ @cache = CacheLib.safe_create :fifo, 5
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ require 'cache_lib'
2
+ require 'minitest/autorun'
3
+
4
+ require_relative 'test_lirs_cache'
5
+
6
+ class TestSafeLirsCache < TestLirsCache
7
+ def setup
8
+ @cache = CacheLib.safe_create :lirs, 3, 2
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ require 'cache_lib'
2
+ require 'minitest/autorun'
3
+
4
+ require_relative 'test_lru_cache'
5
+
6
+ class TestSafeLruCache < TestLruCache
7
+ def setup
8
+ @cache = CacheLib.safe_create :lru, 5
9
+ end
10
+ end