xamplr 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
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,763 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'sync'
4
+
5
+ module Xampl
6
+
7
+ @@persister = nil
8
+ @@known_persisters = {}
9
+ @@persister_kinds = {}
10
+
11
+ def Xampl.persister
12
+ @@persister
13
+ end
14
+
15
+ def Xampl.block_future_changes(on=true)
16
+ if(@@persister) then
17
+ @@persister.block_changes = on
18
+ end
19
+ end
20
+
21
+ def Xampl.auto_persistence(on=true)
22
+ if(@@persister) then
23
+ @@persister.automatic = on
24
+ end
25
+ end
26
+
27
+ def Xampl.register_persister_kind(klass)
28
+ @@persister_kinds[klass.kind] = klass
29
+ end
30
+
31
+ def Xampl.disable_all_persisters
32
+ @@persister = nil
33
+ @@known_persisters = {}
34
+ end
35
+
36
+ def Xampl.disable_persister
37
+ @@persister = nil
38
+ end
39
+
40
+ @@default_persister_kind = :simple
41
+ @@default_persister_format = :xml_format
42
+
43
+ def Xampl.default_persister_kind
44
+ @@default_persister_kind
45
+ end
46
+ def Xampl.set_default_persister_kind(kind)
47
+ @@default_persister_kind = kind
48
+ puts "SET KIND format: #{@@default_persister_format}, kind: #{@@default_persister_kind}"
49
+ end
50
+
51
+ def Xampl.default_persister_format
52
+ @@default_persister_format
53
+ end
54
+ def Xampl.set_default_persister_format(format)
55
+ @@default_persister_format = format
56
+ puts "SET FORMAT format: #{@@default_persister_format}, kind: #{@@default_persister_kind}"
57
+ end
58
+
59
+ def Xampl.enable_persister(name, kind=nil, format=nil)
60
+
61
+ kind = kind || @@default_persister_kind
62
+ format = format || @@default_persister_format
63
+ @@persister = @@known_persisters[name]
64
+
65
+ if @@persister then
66
+ #raise XamplException.new(:live_across_rollback) if @@persister.rolled_back
67
+ if kind and kind != @@persister.kind then
68
+ raise IncompatiblePersisterRequest.new(@@persister, "kind", kind, @@persister.kind)
69
+ end
70
+ if format and format != @@persister.format then
71
+ raise IncompatiblePersisterRequest.new(@@persister, "format", format, @@persister.format)
72
+ end
73
+ end
74
+
75
+ unless @@persister then
76
+ # puts "CREATE PERSISTER #{name}, format: #{format}, kind: #{kind}"
77
+ @@persister = @@persister_kinds[kind].new(name, format)
78
+ if(nil != name) then
79
+ @@known_persisters[name] = @@persister
80
+ end
81
+ end
82
+
83
+ @@persister
84
+ end
85
+
86
+ def Xampl.print_known_persisters
87
+ puts "Known Persisters:: --------------------------"
88
+ @@known_persisters.each { | n, k |
89
+ puts " #{n} #{k}"
90
+ }
91
+ puts "---------------------------------------------"
92
+ end
93
+
94
+ def Xampl.flush_persister_caches
95
+ Xampl.print_known_persisters
96
+ @@known_persisters.delete(@@persister.name)
97
+ Xampl.print_known_persisters
98
+ end
99
+
100
+ def Xampl.drop_all_persisters
101
+ puts "Drop All Persisters:: --------------------------"
102
+ @@known_persisters.each { | n, k |
103
+ puts " #{n} #{k}"
104
+ }
105
+ puts "---------------------------------------------"
106
+ @@known_persisters = {}
107
+ GC.start
108
+ GC.start
109
+ GC.start
110
+ end
111
+
112
+ def Xampl.drop_persister(name)
113
+ Xampl.print_known_persisters
114
+ @@known_persisters.delete(name)
115
+ Xampl.print_known_persisters
116
+ end
117
+
118
+ @@xampl_lock = Sync.new
119
+
120
+ def Xampl.transaction(thing, kind=nil, automatic=true, format=nil, &block)
121
+ if String === thing then
122
+ name = thing
123
+ elsif XamplObject === thing then
124
+ name = thing.persister.name
125
+ else
126
+ raise XamplException.new("can't base a transaction on a #{thing.class.name} (#{thing})")
127
+ end
128
+
129
+ if block_given? then
130
+ @@xampl_lock.synchronize(:EX) do
131
+ initial_persister = @@persister
132
+ Xampl.enable_persister(name, kind, format)
133
+
134
+ rollback = true
135
+ exception = nil
136
+ original_automatic = @@persister.automatic
137
+ begin
138
+ #TODO -- impose some rules on nested transactions/enable_persisters??
139
+ Xampl.auto_persistence(automatic)
140
+ result = yield
141
+ Xampl.block_future_changes(true)
142
+ Xampl.sync
143
+ rollback = false
144
+ return result
145
+ rescue => e
146
+ exception = e
147
+ ensure
148
+ Xampl.block_future_changes(false)
149
+ Xampl.auto_persistence(original_automatic)
150
+ if rollback then
151
+ if exception then
152
+ puts "ROLLBACK(#{__LINE__}):: #{exception}" if rollback
153
+ print exception.backtrace.join("\n") if rollback
154
+ else
155
+ puts "ROLLBACK(#{__LINE__}):: UNKNOWN CAUSE" if rollback
156
+ end
157
+ end
158
+ Xampl.rollback if rollback
159
+ @@persister = initial_persister
160
+ end
161
+ end
162
+ end
163
+ end
164
+
165
+ def Xampl.read_only_transaction(thing, kind=nil, automatic=true, format=nil, &block)
166
+ if String === thing then
167
+ name = thing
168
+ elsif XamplObject === thing then
169
+ name = thing.persister.name
170
+ else
171
+ raise XamplException.new("can't base a transaction on a #{thing.class.name} (#{thing})")
172
+ end
173
+
174
+ target_persister = nil
175
+ if block_given? then
176
+ @@xampl_lock.synchronize(:EX) do
177
+ initial_persister = @@persister
178
+ Xampl.enable_persister(name, kind, format)
179
+ target_persister = @@persister
180
+
181
+ rollback = true
182
+ original_automatic = @@persister.automatic
183
+ @changed ||= nil
184
+ original_changed = @changed
185
+ @changed = {}
186
+ begin
187
+ Xampl.auto_persistence(false)
188
+ #Xampl.block_future_changes(true)
189
+
190
+ yield
191
+ rollback = false
192
+ ensure
193
+ Xampl.auto_persistence(original_automatic)
194
+ #Xampl.block_future_changes(false)
195
+
196
+ if 0 == @changed.size then
197
+ @changed = original_changed
198
+
199
+ puts "ROLLBACK(#{__LINE__})" if rollback
200
+ Xampl.rollback if rollback
201
+ @@persister = initial_persister
202
+ else
203
+ puts "CHANGED COUNT: #{@changed.size}"
204
+ @changed = original_changed
205
+
206
+ puts "ROLLBACK(#{__LINE__})" if rollback
207
+ Xampl.rollback
208
+
209
+ @@persister = initial_persister
210
+
211
+ raise BlockedChange.new(target_persister)
212
+ end
213
+ end
214
+ end
215
+ end
216
+ end
217
+
218
+ def Xampl.read_only(target_persister)
219
+ #TODO -- EXCLUSIVE ACCESS TO THE PERSISTER!!!
220
+ name = target_persister.name
221
+
222
+ if block_given? then
223
+ initial_persister = @@persister
224
+ Xampl.enable_persister(name, target_persister.kind, target_persister.format)
225
+
226
+ rollback = true
227
+ original_automatic = @@persister.automatic
228
+ original_changed = @changed
229
+ @changed = {}
230
+ begin
231
+ Xampl.auto_persistence(false)
232
+ #Xampl.block_future_changes(true)
233
+
234
+ yield
235
+ rollback = false
236
+ ensure
237
+ #### Xampl.auto_persistence(original_automatic)
238
+ #### #Xampl.block_future_changes(false)
239
+ ####
240
+ #### if 0 < @changed.size then
241
+ #### puts "CHANGED COUNT: #{@changed.size}"
242
+ #### raise BlockedChange.new(target_persister)
243
+ #### end
244
+ ####
245
+ #### @changed = original_changed
246
+ ####
247
+ #### puts "ROLLBACK(#{__LINE__})" if rollback
248
+ #### Xampl.rollback if rollback
249
+ #### @@persister = initial_persister
250
+
251
+ Xampl.auto_persistence(original_automatic)
252
+ #Xampl.block_future_changes(false)
253
+
254
+ if 0 == @changed.size then
255
+ @changed = original_changed
256
+
257
+ puts "ROLLBACK(#{__LINE__})" if rollback
258
+ Xampl.rollback if rollback
259
+ @@persister = initial_persister
260
+ else
261
+ puts "CHANGED COUNT: #{@changed.size}"
262
+ @changed = original_changed
263
+
264
+ puts "ROLLBACK(#{__LINE__})" if rollback
265
+ Xampl.rollback
266
+
267
+ @@persister = initial_persister
268
+
269
+ raise BlockedChange.new(target_persister)
270
+ end
271
+ end
272
+ end
273
+ end
274
+
275
+ def Xampl.introduce_to_persister(xampl)
276
+ @@persister.introduce(xampl) if @@persister
277
+ end
278
+
279
+ def Xampl.count_changed
280
+ @@persister.count_changed if @@persister
281
+ end
282
+
283
+ def Xampl.print_stats
284
+ @@persister.print_stats if @@persister
285
+ end
286
+
287
+ def Xampl.auto_cache(xampl)
288
+ if (nil == xampl.persister) and @@persister and @@persister.automatic then
289
+ xampl.persister = @@persister
290
+ end
291
+ if xampl.persister and xampl.persister.automatic then
292
+ xampl.persister.cache(xampl)
293
+ end
294
+ end
295
+
296
+ def Xampl.auto_uncache(xampl)
297
+ if xampl.persister and xampl.persister.automatic then
298
+ xampl.persister.uncache(xampl)
299
+ end
300
+ end
301
+
302
+ def Xampl.clear_cache
303
+ @@persister.clear_cache if nil != @@persister
304
+ end
305
+
306
+ def Xampl.sync
307
+ #raise XamplException.new(:live_across_rollback) if @@persister.rolled_back
308
+ @@persister.sync if nil != @@persister
309
+ end
310
+
311
+ def Xampl.sync_all
312
+ @@known_persisters.each{ | name, persister |
313
+ persister.sync
314
+ }
315
+ end
316
+
317
+ def Xampl.rollback(persister=@@persister)
318
+ raise NoActivePersister unless persister
319
+ persister.rollback_cleanup
320
+ end
321
+
322
+ def Xampl.rollback_all
323
+ @@known_persisters.values.each{ | persister |
324
+ persister.rollback
325
+ }
326
+ end
327
+
328
+ def Xampl.lazy_load(xampl)
329
+ pid = xampl.get_the_index
330
+ if xampl and pid and @@persister then
331
+ @@persister.lazy_load(xampl, xampl.class, pid) if xampl and pid and @@persister
332
+ xampl.load_needed = false
333
+ else
334
+ puts "XAMPL.LAZY_LOAD -- REFUSED"
335
+ end
336
+ end
337
+
338
+ def Xampl.lookup(klass, pid)
339
+ @@persister.lookup(klass, pid) if nil != persister
340
+ end
341
+
342
+ def Xampl.find_known(klass, pid)
343
+ xampl, ignore = @@persister.find_known(klass, pid) if nil != persister
344
+ return xampl
345
+ end
346
+
347
+ def Xampl.write_to_cache(xampl)
348
+ @@persister.write_to_cache(xampl)
349
+ end
350
+
351
+ def Xampl.cache(xampl)
352
+ @@persister.cache(xampl)
353
+ end
354
+
355
+ def Xampl.lookup_in_map(map, klass, pid)
356
+ return nil if nil == pid
357
+
358
+ module_name = klass.module_name
359
+ tag = klass.tag
360
+
361
+ tag_map = map[module_name]
362
+ return nil if nil == tag_map
363
+
364
+ pid_map = tag_map[tag]
365
+ return nil if nil == pid_map
366
+
367
+ return pid_map[pid]
368
+ end
369
+
370
+ def Xampl.store_in_map(map, xampl)
371
+ module_name = xampl.module_name
372
+ tag = xampl.tag
373
+ pid = xampl.get_the_index
374
+
375
+ if nil == pid then
376
+ return false
377
+ end
378
+
379
+ if block_given? then
380
+ data = yield
381
+ else
382
+ data = xampl
383
+ end
384
+
385
+ tag_map = map[module_name]
386
+ if nil == tag_map then
387
+ tag_map = {}
388
+ map[module_name] = tag_map
389
+ end
390
+
391
+ pid_map = tag_map[tag]
392
+ if nil == pid_map then
393
+ pid_map = {}
394
+ tag_map[tag] = pid_map
395
+ end
396
+
397
+ pid_map[pid] = data
398
+
399
+ return true
400
+ end
401
+
402
+ def Xampl.store_in_cache(map, xampl, container)
403
+ module_name = xampl.module_name
404
+ tag = xampl.tag
405
+ pid = xampl.get_the_index
406
+
407
+ if nil == pid then
408
+ return false
409
+ end
410
+
411
+ if block_given? then
412
+ data = yield
413
+ else
414
+ data = xampl
415
+ end
416
+
417
+ tag_map = map[module_name]
418
+ if nil == tag_map then
419
+ tag_map = {}
420
+ map[module_name] = tag_map
421
+ end
422
+
423
+ pid_map = tag_map[tag]
424
+ if nil == pid_map then
425
+ pid_map = container.fresh_cache
426
+ tag_map[tag] = pid_map
427
+ end
428
+
429
+ pid_map[pid] = data
430
+
431
+ return true
432
+ end
433
+
434
+ def Xampl.remove_from_map(map, xampl)
435
+ pid = xampl.get_the_index
436
+ return nil unless pid
437
+
438
+ tag_map = map[xampl.module_name]
439
+ return nil unless tag_map
440
+
441
+ pid_map = tag_map[xampl.tag]
442
+ return nil unless pid_map
443
+
444
+ return pid_map.delete(pid)
445
+ end
446
+
447
+ class Persister
448
+ attr_accessor :name,
449
+ :automatic,
450
+ :block_changes,
451
+ :read_count, :total_read_count,
452
+ :write_count, :total_write_count,
453
+ :total_sync_count, :total_rollback_count,
454
+ :cache_hits, :total_cache_hits,
455
+ :last_write_count,
456
+ :rolled_back
457
+ attr_reader :syncing, :format
458
+
459
+ def initialize(name=nil, format=nil)
460
+ @name = name
461
+ @format = format
462
+ @automatic = false
463
+ @changed = {}
464
+ @cache_hits = 0
465
+ @total_cache_hits = 0
466
+ @read_count = 0
467
+ @total_read_count = 0
468
+ @write_count = 0
469
+ @total_write_count = 0
470
+ @last_write_count = 0
471
+ @total_sync_count = 0
472
+ @total_rollback_count = 0
473
+ @rolled_back = false
474
+ @syncing = false
475
+
476
+ @busy_count = 0
477
+ end
478
+
479
+ def busy(yes)
480
+ if yes then
481
+ @busy_count += 1
482
+ elsif 0 < @busy_count then
483
+ @busy_count -= 1
484
+ end
485
+ end
486
+
487
+ def is_busy
488
+ return 0 < @busy_count
489
+ end
490
+
491
+ def introduce(xampl)
492
+ if xampl.introduce_persister(self) then
493
+ cache(xampl)
494
+ end
495
+ has_changed(xampl) if xampl.is_changed
496
+ end
497
+
498
+ def has_changed(xampl)
499
+ #raise XamplException.new(:live_across_rollback) if @rolled_back
500
+ # puts "!!!! has_changed #{xampl} #{xampl.get_the_index} -- persist required: #{xampl.persist_required}"
501
+ if xampl.persist_required && xampl.is_changed then
502
+ unless self == xampl.persister
503
+ raise MixedPersisters.new(xampl.persister, self)
504
+ end
505
+ @changed[xampl] = xampl
506
+ # puts "!!!! change recorded ==> #{@changed.size}/#{count_changed} #{@changed.object_id} !!!!"
507
+ # @changed.each{ | thing, ignore |
508
+ # puts " changed: #{thing}, index: #{thing.get_the_index}, changed: #{thing.is_changed}"
509
+ # }
510
+ end
511
+ end
512
+
513
+ def has_not_changed(xampl)
514
+ # puts "!!!! has_not_changed #{xampl} #{xampl.get_the_index} -- in @changed: #{nil != @changed[xampl]}"
515
+ @changed.delete(xampl) if xampl
516
+ end
517
+
518
+ def count_changed
519
+ # @changed.each{ | thing, ignore |
520
+ # puts "changed: #{thing}, index: #{thing.get_the_index}"
521
+ # }
522
+ return @changed.size
523
+ end
524
+
525
+ def cache(xampl)
526
+ raise XamplException.new(:unimplemented)
527
+ end
528
+
529
+ def uncache(xampl)
530
+ raise XamplException.new(:unimplemented)
531
+ end
532
+
533
+ def clear_cache
534
+ raise XamplException.new(:unimplemented)
535
+ end
536
+
537
+ def Persister.replace(old_xampl, new_xampl)
538
+ pid = old_xampl.get_the_index
539
+ if old_xampl.persister != @@persister then
540
+ raise MixedPersisters.new(@@persister, old_xampl.persister)
541
+ end
542
+ if new_xampl.persister != @@persister then
543
+ raise MixedPersisters.new(@@persister, new_xampl.persister)
544
+ end
545
+
546
+ new_xampl.note_replacing(old_xampl)
547
+
548
+ unless old_xampl.load_needed then
549
+ Xampl.log.warn("Replacing live xampl: #{old_xampl} pid: #{pid}")
550
+ @@persister.uncache(old_xampl)
551
+ old_xampl.invalidate
552
+ end
553
+ new_xampl.pid = nil
554
+ new_xampl.pid = pid
555
+ @@persister.introduce(new_xampl)
556
+ end
557
+
558
+ def represent(xampl)
559
+ case @format
560
+ when nil, :xml_format then
561
+ return xampl.persist
562
+ when :ruby_format then
563
+ return xampl.to_ruby
564
+ end
565
+ end
566
+
567
+ def realise(representation, target=nil)
568
+ # Normally we'd expect to see the representation in the @format format, but
569
+ # that isn't necessarily the case. Try to work out what the format might be...
570
+
571
+ if representation =~ /^</ then
572
+ return XamplObject.realise_from_xml_string(representation, target)
573
+ else
574
+ XamplObject.from_ruby(representation, target)
575
+ end
576
+ end
577
+
578
+ def write(xampl)
579
+ raise XamplException.new(:unimplemented)
580
+ end
581
+
582
+ def read(klass, pid, target=nil)
583
+ raise XamplException.new(:unimplemented)
584
+ end
585
+
586
+ def lookup(klass, pid)
587
+ #raise XamplException.new(:live_across_rollback) if @rolled_back
588
+
589
+ # puts "LOOKUP:: klass: #{klass} pid: #{pid}"
590
+
591
+ begin
592
+ busy(true)
593
+ xampl = read(klass, pid)
594
+ ensure
595
+ busy(false)
596
+ end
597
+
598
+ return xampl
599
+ end
600
+
601
+ def find_known(klass, pid)
602
+ #raise XamplException.new(:live_across_rollback) if @rolled_back
603
+
604
+ xampl = read_from_cache(klass, pid, nil)
605
+
606
+ return xampl
607
+ end
608
+
609
+ def lazy_load(target, klass, pid)
610
+ # puts "LAZY_LOAD:: klass: #{klass} pid: #{pid} target: #{target}"
611
+
612
+ xampl = read(klass, pid, target)
613
+
614
+ # puts " LAZY_LOAD --> #{xampl}"
615
+
616
+ return xampl
617
+ end
618
+
619
+ def put_changed(msg="")
620
+ puts "Changed::#{msg}:"
621
+ @changed.each { | xampl, ignore | puts " #{xampl.tag} #{xampl.get_the_index}" }
622
+ end
623
+
624
+ def do_sync_write
625
+ unchanged_in_changed_list = 0
626
+ # puts "DO SYNC WRITE:: changed: #{@changed.size}, #{@changed.object_id}"
627
+ @changed.each { | xampl, ignore |
628
+ # puts " WRITE: #{xampl}, index: #{xampl.get_the_index}, changed: #{xampl.is_changed}"
629
+
630
+ unchanged_in_changed_list += 1 unless xampl.is_changed
631
+ write(xampl) unless xampl.kind_of?(InvalidXampl)
632
+ }
633
+ end
634
+
635
+ def sync
636
+ #raise XamplException.new(:live_across_rollback) if @rolled_back
637
+ begin
638
+ #puts "SYNC"
639
+ #puts "SYNC"
640
+ #puts "SYNC changed: #{@changed.size}"
641
+ #@changed.each do | key, value |
642
+ # #puts "key: #{key.class.name}, value: #{value.class.name}"
643
+ # puts key.to_xml
644
+ #end
645
+ #puts "SYNC"
646
+ #puts "SYNC"
647
+ busy(true)
648
+ @syncing = true
649
+
650
+ do_sync_write
651
+
652
+ @changed = {}
653
+
654
+ @total_read_count = @total_read_count + @read_count
655
+ @total_write_count = @total_write_count + @write_count
656
+ @total_cache_hits = @total_cache_hits + @cache_hits
657
+ @total_sync_count = @total_sync_count + 1
658
+
659
+ @read_count = 0
660
+ @last_write_count = @write_count
661
+ @write_count = 0
662
+
663
+ self.sync_done()
664
+
665
+ return @last_write_count
666
+ ensure
667
+ busy(false)
668
+ @syncing = false
669
+ end
670
+ end
671
+
672
+ def sync_done
673
+ raise XamplException.new(:unimplemented)
674
+ end
675
+
676
+ def rollback
677
+ begin
678
+ busy(true)
679
+
680
+ return Xampl.rollback(self)
681
+ ensure
682
+ busy(false)
683
+ end
684
+ end
685
+
686
+ def rollback_cleanup
687
+ @changed = {}
688
+ end
689
+
690
+ def print_stats
691
+ printf("SYNC:: TOTAL cache_hits: %d, reads: %d, writes: %d\n",
692
+ @total_cache_hits, @total_read_count, @total_write_count)
693
+ printf(" cache_hits: %d, reads: %d, last writes: %d\n",
694
+ @cache_hits, @read_count, @last_write_count)
695
+ printf(" syncs: %d\n", @total_sync_count)
696
+ printf(" changed count: %d (%d)\n", count_changed, @changed.size)
697
+ @changed.each{ | thing, ignore |
698
+ if thing.is_changed then
699
+ puts " changed: #{thing}, index: #{thing.get_the_index}"
700
+ else
701
+ puts " UNCHANGED: #{thing}, index: #{thing.get_the_index} <<<<<<<<<<<<<<<<<<< BAD!"
702
+ end
703
+ }
704
+ end
705
+ end
706
+
707
+ class NoActivePersister < Exception
708
+ def message
709
+ "No Persister is active"
710
+ end
711
+ end
712
+
713
+ class BlockedChange < Exception
714
+ attr_reader :xampl
715
+
716
+ def initialize(xampl=nil)
717
+ @xampl = xampl
718
+ end
719
+
720
+ def message
721
+ "attempt to change #{@xampl}, pid: #{@xampl.get_the_index}, oid: #{@xampl.object_id} when changes are blocked"
722
+ end
723
+ end
724
+
725
+ class UnmanagedChange < Exception
726
+ attr_reader :xampl
727
+
728
+ def initialize(xampl=nil)
729
+ @xampl = xampl
730
+ end
731
+
732
+ def message
733
+ "attempt to change #{@xampl}, pid: #{@xampl.get_the_index}, oid: #{@xampl.object_id} outside of its persister's management"
734
+ end
735
+ end
736
+
737
+ class IncompatiblePersisterRequest < Exception
738
+ attr_reader :msg
739
+ def initialize(persister, feature_name, requested_feature_value, actual_feature_value)
740
+ @msg = "persister #{persister.name}:: requested feature: #{feature_name} #{requested_feature_value}, actual: #{actual_feature_value}"
741
+ end
742
+
743
+ def message
744
+ @msg
745
+ end
746
+ end
747
+
748
+ class MixedPersisters < Exception
749
+ attr_reader :msg
750
+ def initialize(active, local)
751
+ @msg = "mixed persisters:: active #{active.name}, local: #{local.name}"
752
+ end
753
+
754
+ def message
755
+ @msg
756
+ end
757
+ end
758
+
759
+ require "persister/simple"
760
+ require "persister/in-memory"
761
+ require "persister/filesystem"
762
+ end
763
+