xamplr 1.2.0

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.
Files changed (142) hide show
  1. data/CHANGES.txt +13 -0
  2. data/LICENSE +3 -0
  3. data/README.rdoc +26 -0
  4. data/README.rdoc.orig +118 -0
  5. data/Rakefile +85 -0
  6. data/VERSION.yml +4 -0
  7. data/examples/random-people-shared-addresses/Makefile +16 -0
  8. data/examples/random-people-shared-addresses/batch-load-users.rb +83 -0
  9. data/examples/random-people-shared-addresses/find-mentions.rb +47 -0
  10. data/examples/random-people-shared-addresses/find-people-by-address.rb +104 -0
  11. data/examples/random-people-shared-addresses/optimise.rb +16 -0
  12. data/examples/random-people-shared-addresses/people.rb +35 -0
  13. data/examples/random-people-shared-addresses/query.rb +75 -0
  14. data/examples/random-people-shared-addresses/query2.rb +73 -0
  15. data/examples/random-people-shared-addresses/random-names.csv +10000 -0
  16. data/examples/random-people-shared-addresses/settings.rb +3 -0
  17. data/examples/random-people-shared-addresses/what-to-query-on.rb +82 -0
  18. data/examples/random-people-shared-addresses/xampl-gen.rb +36 -0
  19. data/examples/random-people-shared-addresses/xml/people.xml +14 -0
  20. data/examples/random-people/Makefile +16 -0
  21. data/examples/random-people/batch-load-users.rb +61 -0
  22. data/examples/random-people/optimise.rb +16 -0
  23. data/examples/random-people/people.rb +22 -0
  24. data/examples/random-people/query.rb +73 -0
  25. data/examples/random-people/query2.rb +73 -0
  26. data/examples/random-people/random-names.csv +10000 -0
  27. data/examples/random-people/rawtc.rb +91 -0
  28. data/examples/random-people/settings.rb +3 -0
  29. data/examples/random-people/what-to-query-on.rb +80 -0
  30. data/examples/random-people/xampl-gen.rb +36 -0
  31. data/examples/random-people/xml/people.xml +11 -0
  32. data/examples/read-testing/Makefile +10 -0
  33. data/examples/read-testing/load.rb +65 -0
  34. data/examples/read-testing/read.rb +51 -0
  35. data/examples/read-testing/rrr.rb +87 -0
  36. data/examples/read-testing/settings.rb +2 -0
  37. data/examples/read-testing/xampl-gen.rb +36 -0
  38. data/examples/read-testing/xml/text.xml +8 -0
  39. data/examples/tokyo-cabinet-experimental/expt-query.rb +42 -0
  40. data/examples/tokyo-cabinet-experimental/expt-query2.rb +42 -0
  41. data/examples/tokyo-cabinet-experimental/expt-query3.rb +41 -0
  42. data/examples/tokyo-cabinet-experimental/expt-reader.rb +32 -0
  43. data/examples/tokyo-cabinet-experimental/expt.rb +61 -0
  44. data/examples/tokyo-cabinet-experimental/xampl-gen.rb +36 -0
  45. data/examples/tokyo-cabinet-experimental/xml/tcx.xml +6 -0
  46. data/lib/xampl-generator.rb +3 -0
  47. data/lib/xampl.rb +3 -0
  48. data/lib/xamplr-generator.rb +10 -0
  49. data/lib/xamplr.rb +37 -0
  50. data/lib/xamplr/README-POSSIBLE-PROBLEMS +5 -0
  51. data/lib/xamplr/TODO +1 -0
  52. data/lib/xamplr/exceptions.rb +97 -0
  53. data/lib/xamplr/from-xml-orig.rb +350 -0
  54. data/lib/xamplr/from-xml.rb +439 -0
  55. data/lib/xamplr/gen-elements.xml +6230 -0
  56. data/lib/xamplr/gen.elements.xml +108 -0
  57. data/lib/xamplr/generate-elements.rb +15 -0
  58. data/lib/xamplr/generator.rb +5 -0
  59. data/lib/xamplr/graphml-out.rb +470 -0
  60. data/lib/xamplr/handwritten/example.rb +698 -0
  61. data/lib/xamplr/handwritten/hand-example.rb +533 -0
  62. data/lib/xamplr/handwritten/test-handwritten.rb +873 -0
  63. data/lib/xamplr/indexed-array.rb +115 -0
  64. data/lib/xamplr/mixins.rb +397 -0
  65. data/lib/xamplr/my.gen.elements.xml +461 -0
  66. data/lib/xamplr/notifications.rb +57 -0
  67. data/lib/xamplr/obsolete/fsdb.rb +62 -0
  68. data/lib/xamplr/persist-to-xml.rb +249 -0
  69. data/lib/xamplr/persistence.rb +522 -0
  70. data/lib/xamplr/persistence.rb.more_thread_safe +771 -0
  71. data/lib/xamplr/persistence.rb.partially_thread_safe +763 -0
  72. data/lib/xamplr/persister.rb +310 -0
  73. data/lib/xamplr/persisters/caches.rb +186 -0
  74. data/lib/xamplr/persisters/caching.rb +172 -0
  75. data/lib/xamplr/persisters/filesystem.rb +60 -0
  76. data/lib/xamplr/persisters/in-memory.rb +180 -0
  77. data/lib/xamplr/persisters/simple.rb +59 -0
  78. data/lib/xamplr/persisters/tokyo-cabinet.rb +641 -0
  79. data/lib/xamplr/simpleTemplate/danger.rx +4 -0
  80. data/lib/xamplr/simpleTemplate/obsolete/input-c.r4 +35 -0
  81. data/lib/xamplr/simpleTemplate/obsolete/play.r6.txt +12 -0
  82. data/lib/xamplr/simpleTemplate/obsolete/play_more.r6.txt +20 -0
  83. data/lib/xamplr/simpleTemplate/obsolete/test001.r5 +8 -0
  84. data/lib/xamplr/simpleTemplate/obsolete/test002.r5 +13 -0
  85. data/lib/xamplr/simpleTemplate/obsolete/test003.r5 +37 -0
  86. data/lib/xamplr/simpleTemplate/old/r6.000.rb +122 -0
  87. data/lib/xamplr/simpleTemplate/old/r6.001.rb +145 -0
  88. data/lib/xamplr/simpleTemplate/play.r6 +12 -0
  89. data/lib/xamplr/simpleTemplate/play_more.r6 +20 -0
  90. data/lib/xamplr/simpleTemplate/play_noblanks.r6 +21 -0
  91. data/lib/xamplr/simpleTemplate/playq.r6 +16 -0
  92. data/lib/xamplr/simpleTemplate/r6.rb +87 -0
  93. data/lib/xamplr/simpleTemplate/simple-template.rb +75 -0
  94. data/lib/xamplr/templates/child.template +47 -0
  95. data/lib/xamplr/templates/child_indexed.template +89 -0
  96. data/lib/xamplr/templates/child_modules.template +5 -0
  97. data/lib/xamplr/templates/element_classes.template +11 -0
  98. data/lib/xamplr/templates/element_data.template +282 -0
  99. data/lib/xamplr/templates/element_empty.template +285 -0
  100. data/lib/xamplr/templates/element_mixed.template +277 -0
  101. data/lib/xamplr/templates/element_simple.template +276 -0
  102. data/lib/xamplr/templates/package.template +26 -0
  103. data/lib/xamplr/test-support/Makefile +47 -0
  104. data/lib/xamplr/test-support/bench-cache.rb +80 -0
  105. data/lib/xamplr/test-support/bench-script.rb +21 -0
  106. data/lib/xamplr/test-support/bench.rb +116 -0
  107. data/lib/xamplr/test-support/bench2.rb +132 -0
  108. data/lib/xamplr/test-support/test-cache.rb +147 -0
  109. data/lib/xamplr/test-support/test-data/binding.xml +7 -0
  110. data/lib/xamplr/test-support/test-data/example.xml +14 -0
  111. data/lib/xamplr/test-support/test-data/internationalization-utf8.txt +1 -0
  112. data/lib/xamplr/test-support/test-data/labels.xml +37 -0
  113. data/lib/xamplr/test-support/test-data/labels001.xml +38 -0
  114. data/lib/xamplr/test-support/test-deep-change.rb +135 -0
  115. data/lib/xamplr/test-support/test-elements.rb +109 -0
  116. data/lib/xamplr/test-support/test-indexed-array.rb +169 -0
  117. data/lib/xamplr/test-support/test-misc.rb +73 -0
  118. data/lib/xamplr/test-support/test-names.rb +67 -0
  119. data/lib/xamplr/test-support/test-rollback.rb +106 -0
  120. data/lib/xamplr/test-support/test.rb +1504 -0
  121. data/lib/xamplr/to-ruby.rb +220 -0
  122. data/lib/xamplr/to-xml.rb +158 -0
  123. data/lib/xamplr/version.rb +67 -0
  124. data/lib/xamplr/visitor.rb +140 -0
  125. data/lib/xamplr/visitors.rb +573 -0
  126. data/lib/xamplr/xampl-generator.rb +533 -0
  127. data/lib/xamplr/xampl-hand-generated.rb +1535 -0
  128. data/lib/xamplr/xampl-module.rb +36 -0
  129. data/lib/xamplr/xampl-object-internals.rb +6 -0
  130. data/lib/xamplr/xampl-object.rb +202 -0
  131. data/lib/xamplr/xampl-persisted-object.rb +122 -0
  132. data/lib/xamplr/xml-text.rb +117 -0
  133. data/lib/xamplr/xml/document.xml +7 -0
  134. data/lib/xamplr/xml/elements.xml +101 -0
  135. data/lib/xamplr/xml/elements000.xml +73 -0
  136. data/lib/xamplr/xml/example.xml +23 -0
  137. data/lib/xamplr/xml/options.xml +12 -0
  138. data/lib/xamplr/xml/uche.xml +38 -0
  139. data/lib/xamplr/yEd-sample.graphml +300 -0
  140. data/test/test_helper.rb +10 -0
  141. data/test/xamplr_test.rb +7 -0
  142. metadata +245 -0
@@ -0,0 +1,310 @@
1
+
2
+ require "xamplr/persistence"
3
+
4
+ module Xampl
5
+ class Persister
6
+ attr_accessor :name,
7
+ :automatic,
8
+ :block_changes,
9
+ :read_count, :total_read_count,
10
+ :write_count, :total_write_count,
11
+ :total_sync_count, :total_rollback_count,
12
+ :cache_hits, :total_cache_hits,
13
+ :last_write_count,
14
+ :rolled_back
15
+ attr_reader :syncing, :format
16
+
17
+ def initialize(name=nil, format=nil)
18
+ @name = name
19
+ @format = format
20
+ @automatic = false
21
+ @changed = {}
22
+ @cache_hits = 0
23
+ @total_cache_hits = 0
24
+ @read_count = 0
25
+ @total_read_count = 0
26
+ @write_count = 0
27
+ @total_write_count = 0
28
+ @last_write_count = 0
29
+ @total_sync_count = 0
30
+ @total_rollback_count = 0
31
+ @rolled_back = false
32
+ @syncing = false
33
+
34
+ @busy_count = 0
35
+ end
36
+
37
+ def optimise(opts)
38
+ end
39
+
40
+ def close
41
+ self.sync
42
+ end
43
+
44
+ def busy(yes)
45
+ if yes then
46
+ @busy_count += 1
47
+ elsif 0 < @busy_count then
48
+ @busy_count -= 1
49
+ end
50
+ end
51
+
52
+ def is_busy
53
+ return 0 < @busy_count
54
+ end
55
+
56
+ def introduce(xampl)
57
+ if xampl.introduce_persister(self) then
58
+ cache(xampl)
59
+ end
60
+ has_changed(xampl) if xampl.is_changed
61
+ end
62
+
63
+ def has_changed(xampl)
64
+ #raise XamplException.new(:live_across_rollback) if @rolled_back
65
+ # puts "!!!! has_changed #{xampl} #{xampl.get_the_index} -- persist required: #{xampl.persist_required}"
66
+ if xampl.persist_required && xampl.is_changed then
67
+ unless self == xampl.persister
68
+ raise MixedPersisters.new(xampl.persister, self)
69
+ end
70
+ @changed[xampl] = xampl
71
+ # puts "!!!! change recorded ==> #{@changed.size}/#{count_changed} #{@changed.object_id} !!!!"
72
+ # @changed.each{ | thing, ignore |
73
+ # puts " changed: #{thing}, index: #{thing.get_the_index}, changed: #{thing.is_changed}"
74
+ # }
75
+ end
76
+ end
77
+
78
+ def has_not_changed(xampl)
79
+ # puts "!!!! has_not_changed #{xampl} #{xampl.get_the_index} -- in @changed: #{nil != @changed[xampl]}"
80
+ @changed.delete(xampl) if xampl
81
+ end
82
+
83
+ def count_changed
84
+ # @changed.each{ | thing, ignore |
85
+ # puts "changed: #{thing}, index: #{thing.get_the_index}"
86
+ # }
87
+ return @changed.size
88
+ end
89
+
90
+ def cache(xampl)
91
+ raise XamplException.new(:unimplemented)
92
+ end
93
+
94
+ def uncache(xampl)
95
+ raise XamplException.new(:unimplemented)
96
+ end
97
+
98
+ def clear_cache
99
+ raise XamplException.new(:unimplemented)
100
+ end
101
+
102
+ def Persister.replace(old_xampl, new_xampl)
103
+ pid = old_xampl.get_the_index
104
+ if old_xampl.persister != @@persister then
105
+ raise MixedPersisters.new(@@persister, old_xampl.persister)
106
+ end
107
+ if new_xampl.persister != @@persister then
108
+ raise MixedPersisters.new(@@persister, new_xampl.persister)
109
+ end
110
+
111
+ new_xampl.note_replacing(old_xampl)
112
+
113
+ unless old_xampl.load_needed then
114
+ Xampl.log.warn("Replacing live xampl: #{old_xampl} pid: #{pid}")
115
+ @@persister.uncache(old_xampl)
116
+ old_xampl.invalidate
117
+ end
118
+ new_xampl.pid = nil
119
+ new_xampl.pid = pid
120
+ @@persister.introduce(new_xampl)
121
+ end
122
+
123
+ def represent(xampl, mentions=[])
124
+ #puts "REPRESENT #{xampl} load needed: #{xampl.load_needed}"
125
+ # return nil if xampl.load_needed
126
+ case xampl.default_persister_format || @format
127
+ when nil, :xml_format then
128
+ return xampl.persist("", mentions)
129
+ when :ruby_format then
130
+ return xampl.to_ruby(mentions)
131
+ end
132
+ end
133
+
134
+ def realise(representation, target=nil)
135
+ # Normally we'd expect to see the representation in the @format format, but
136
+ # that isn't necessarily the case. Try to work out what the format might be...
137
+
138
+ if representation =~ /^</ then
139
+ return XamplObject.realise_from_xml_string(representation, target)
140
+ else
141
+ XamplObject.from_ruby(representation, target)
142
+ end
143
+ end
144
+
145
+ def version(stream)
146
+ raise XamplException.new(:unimplemented)
147
+ # catch(:refuse_to_version) do
148
+ # end
149
+ end
150
+
151
+ def write(xampl)
152
+ raise XamplException.new(:unimplemented)
153
+ end
154
+
155
+ def read(klass, pid, target=nil)
156
+ raise XamplException.new(:unimplemented)
157
+ end
158
+
159
+ def query_implemented
160
+ false
161
+ end
162
+
163
+ def find_xampl(hint=false)
164
+ if hint then
165
+ return [], "no query made"
166
+ else
167
+ return []
168
+ end
169
+ end
170
+
171
+ def lookup(klass, pid)
172
+ #raise XamplException.new(:live_across_rollback) if @rolled_back
173
+ #puts "#{File.basename(__FILE__)} #{__LINE__} LOOKUP:: klass: #{klass} pid: #{pid}"
174
+
175
+ begin
176
+ busy(true)
177
+ xampl = read(klass, pid)
178
+ ensure
179
+ busy(false)
180
+ end
181
+
182
+ #puts "#{File.basename(__FILE__)} #{__LINE__} ---> #{ xampl }"
183
+
184
+ return xampl
185
+ end
186
+
187
+ def find_known(klass, pid)
188
+ #raise XamplException.new(:live_across_rollback) if @rolled_back
189
+
190
+ xampl = read_from_cache(klass, pid, nil)
191
+
192
+ return xampl
193
+ end
194
+
195
+ def lazy_load(target, klass, pid)
196
+ # puts "#{File.basename(__FILE__)} #{__LINE__} LAZY_LOAD:: klass: #{klass} pid: #{pid} target: #{target}"
197
+
198
+ xampl = read(klass, pid, target)
199
+
200
+ # puts " LAZY_LOAD --> #{xampl}"
201
+
202
+ return xampl
203
+ end
204
+
205
+ def put_changed(msg="")
206
+ puts "Changed::#{msg}:"
207
+ @changed.each { | xampl, ignore | puts " #{xampl.tag} #{xampl.get_the_index}" }
208
+ end
209
+
210
+ def do_sync_write
211
+ unchanged_in_changed_list = 0
212
+ @changed.each do |xampl, ignore|
213
+ unchanged_in_changed_list += 1 unless xampl.is_changed
214
+ unless xampl.kind_of?(InvalidXampl) then
215
+ write(xampl)
216
+ end
217
+ end
218
+ end
219
+
220
+ def sync
221
+ #raise XamplException.new(:live_across_rollback) if @rolled_back
222
+ begin
223
+ #puts "SYNC"
224
+ #puts "SYNC"
225
+ #puts "SYNC changed: #{@changed.size}" if 0 < @changed.size
226
+ #@changed.each do | key, value |
227
+ ##puts " #{key.class.name}"
228
+ ##puts "key: #{key.class.name}, value: #{value.class.name}"
229
+ #puts key.to_xml
230
+ #end
231
+ #puts "SYNC"
232
+ #puts "SYNC"
233
+
234
+ #if 0 < @changed.size then
235
+ #puts "SYNC changed: #{@changed.size}"
236
+ ##caller(0).each do | trace |
237
+ ## next if /xamplr/ =~ trace
238
+ ## puts " #{trace}"
239
+ ## break if /actionpack/ =~ trace
240
+ ##end
241
+ #end
242
+ busy(true)
243
+ @syncing = true
244
+
245
+ do_sync_write
246
+
247
+ @changed = {}
248
+
249
+ @total_read_count = @total_read_count + @read_count
250
+ @total_write_count = @total_write_count + @write_count
251
+ @total_cache_hits = @total_cache_hits + @cache_hits
252
+ @total_sync_count = @total_sync_count + 1
253
+
254
+ @read_count = 0
255
+ @last_write_count = @write_count
256
+ @write_count = 0
257
+
258
+ self.sync_done()
259
+
260
+ return @last_write_count
261
+ ensure
262
+ busy(false)
263
+ @syncing = false
264
+ end
265
+ end
266
+
267
+ def sync_done
268
+ raise XamplException.new(:unimplemented)
269
+ end
270
+
271
+ def rollback
272
+ begin
273
+ busy(true)
274
+
275
+ return Xampl.rollback(self)
276
+ ensure
277
+ busy(false)
278
+ end
279
+ end
280
+
281
+ def rollback_cleanup
282
+ @changed = {}
283
+ end
284
+
285
+ def print_stats
286
+ printf("SYNC:: TOTAL cache_hits: %d, reads: %d, writes: %d\n",
287
+ @total_cache_hits, @total_read_count, @total_write_count)
288
+ printf(" cache_hits: %d, reads: %d, last writes: %d\n",
289
+ @cache_hits, @read_count, @last_write_count)
290
+ printf(" syncs: %d\n", @total_sync_count)
291
+ printf(" changed count: %d (%d)\n", count_changed, @changed.size)
292
+ @changed.each do |thing, ignore|
293
+ if thing.is_changed then
294
+ puts " changed: #{thing}, index: #{thing.get_the_index}"
295
+ else
296
+ puts " UNCHANGED: #{thing}, index: #{thing.get_the_index} <<<<<<<<<<<<<<<<<<< BAD!"
297
+ end
298
+ end
299
+ end
300
+ end
301
+
302
+ require "xamplr/persisters/simple"
303
+ require "xamplr/persisters/in-memory"
304
+ require "xamplr/persisters/filesystem"
305
+
306
+ if require 'tokyocabinet' then
307
+ require "xamplr/persisters/tokyo-cabinet"
308
+ end
309
+
310
+ end
@@ -0,0 +1,186 @@
1
+ module Xampl
2
+
3
+ #TODO -- this is **way** too big!
4
+ #TODO -- FIX THIS PROBLEM
5
+ # increase the default cache size to 2000 (which is way too big, but there is
6
+ # a bug... removing from the cache does not remove from memory, so if a
7
+ # storybook exists that points (even indirectly) at something flushed, the
8
+ # thing flushed is still held in memory. What is needed is for the thing to
9
+ # be invalidated somehow withought DUPLICATES being created when the thing
10
+ # is read again next time)
11
+
12
+ DEFAULT_CAPACITY = 2000
13
+
14
+ class XamplCache
15
+ require 'xamplr/indexed-array'
16
+
17
+ attr_reader :cache, :capacity
18
+
19
+ def initialize(capacity=DEFAULT_CAPACITY)
20
+ @capacity = capacity
21
+ @now = 0
22
+ @size = 0
23
+ @cache = {}
24
+ end
25
+
26
+ def size
27
+ #@cache.size
28
+ return @size
29
+ end
30
+
31
+ def delete(key)
32
+ @cache.delete(key)
33
+ end
34
+
35
+ def limit
36
+ victim = nil
37
+ actual_victim = nil
38
+ min = 1 + @now
39
+ @size = 0
40
+ @cache.each do |key, pair|
41
+ possibility = pair[0]
42
+ if (not possibility.load_needed) and pair[1] < min then
43
+ @size += 1
44
+ victim = key
45
+ actual_victim = possibility
46
+ min = pair[1]
47
+ end
48
+ end
49
+ #puts
50
+ #puts
51
+ #puts "REMOVE FROM CACHE(XamplCache): victim: #{victim}, actual: #{actual_victim}"
52
+ #puts " size: #{@size}, physical size: #{@cache.size}"
53
+ #puts
54
+ #puts
55
+ #@cache.delete(victim)
56
+ actual_victim.force_load if actual_victim
57
+ #puts ">>>>>>> #{actual_victim.load_needed} #{actual_victim.class.name}" if actual_victim
58
+ end
59
+
60
+ def fetch(key, default_value=nil)
61
+ pair = @cache[key]
62
+ if pair then
63
+ pair[1] = (@now += 1)
64
+ return pair[0]
65
+ else
66
+ return default_value
67
+ end
68
+ end
69
+
70
+ def store(key, value)
71
+ if (@capacity <= @size) then
72
+ self.limit
73
+ end
74
+
75
+ pair = @cache[key]
76
+ if pair then
77
+ pair[0] = value
78
+ pair[1] = (@now += 1)
79
+ else
80
+ @cache[key] = [value, (@now += 1)]
81
+ end
82
+
83
+ return value
84
+ end
85
+
86
+ def print(out = "")
87
+ out << "Cache (standard) with capacity: #{@capacity}, current size: #{@size}\n"
88
+ @cache.each do |key, pair|
89
+ out << sprintf(" key: '%s', value: '%s', accessed: %s\n",
90
+ key, pair[0], pair[1])
91
+ end
92
+ out
93
+ end
94
+
95
+ alias [] fetch
96
+ alias []= store
97
+ end
98
+
99
+ class XamplCacheLFU
100
+ require 'xamplr/indexed-array'
101
+
102
+ attr_reader :cache, :capacity
103
+
104
+ def initialize(capacity=DEFAULT_CAPACITY)
105
+ @capacity = capacity
106
+ @accesses = 0
107
+ @size = 0
108
+ @cache = {}
109
+ end
110
+
111
+ def size
112
+ #@cache.size
113
+ @size
114
+ end
115
+
116
+ def delete(key)
117
+ @cache.delete(key)
118
+ end
119
+
120
+ def limit
121
+ victim = nil
122
+ actual_victim = nil
123
+ min = 1 + @accesses
124
+ live = 0
125
+ @cache.each do |key, pair|
126
+ pair[1] -= 1
127
+ possibility = pair[0]
128
+ if (not possibility.load_needed) and pair[1] < min then
129
+ live += 1
130
+ victim = key
131
+ actual_victim = possibility
132
+ min = pair[1]
133
+ end
134
+ end
135
+ #puts
136
+ #puts
137
+ #puts "REMOVE FROM CACHE(XamplCacheLFU): victim: #{victim}, actual: #{actual_victim} -- live: #{live}, size: #{@size}"
138
+ #puts
139
+ #puts
140
+ #@cache.delete(victim)
141
+ actual_victim.force_load if actual_victim
142
+ end
143
+
144
+ def fetch(key, default_value=nil)
145
+ @accesses += 1
146
+
147
+ pair = @cache[key]
148
+ if pair then
149
+ pair[1] += 1
150
+ return pair[0]
151
+ else
152
+ return default_value
153
+ end
154
+ end
155
+
156
+ def store(key, value)
157
+ @accesses += 1
158
+
159
+ if (@capacity <= @size) then
160
+ self.limit
161
+ end
162
+
163
+ pair = @cache[key]
164
+ if pair then
165
+ pair[0] = value
166
+ pair[1] += 1
167
+ else
168
+ @cache[key] = [value, 1]
169
+ end
170
+
171
+ return value
172
+ end
173
+
174
+ def print(out = "")
175
+ out << "Cache (LFU) with capacity: #{@capacity}, current size: #{@size}\n"
176
+ @cache.each do |key, pair|
177
+ out << sprintf(" key: '%s', value: '%s', count: %s\n",
178
+ key, pair[0], pair[1])
179
+ end
180
+ out
181
+ end
182
+
183
+ alias [] fetch
184
+ alias []= store
185
+ end
186
+ end