xamplr 1.2.0 → 1.3.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (133) hide show
  1. data/.document +5 -0
  2. data/.gitignore +12 -0
  3. data/CHANGES.txt +37 -0
  4. data/COPYING +661 -0
  5. data/Makefile +13 -0
  6. data/README.rdoc +24 -4
  7. data/Rakefile +2 -2
  8. data/VERSION.yml +3 -2
  9. data/bin/xampl-gen +17 -0
  10. data/docs/intro/.gitignore +1 -0
  11. data/docs/intro/example1/example1.rb +6 -0
  12. data/docs/intro/example1/xml/hello.xml +1 -0
  13. data/docs/intro/example2/example2.rb +38 -0
  14. data/docs/intro/example2/project-generator.rb +22 -0
  15. data/docs/intro/example2/xml/hello.xml +2 -0
  16. data/docs/intro/example3/example3.rb +30 -0
  17. data/docs/intro/example3/example3a.rb +16 -0
  18. data/docs/intro/example3/generated.png +0 -0
  19. data/docs/intro/example3/grab-yuml.rb +10 -0
  20. data/docs/intro/example3/greeter.rb +15 -0
  21. data/docs/intro/example3/greeting.rb +9 -0
  22. data/docs/intro/example3/project-generator.rb +25 -0
  23. data/docs/intro/example3/xml/greeter.xml +6 -0
  24. data/docs/intro/example4/example4.rb +27 -0
  25. data/docs/intro/example4/example4a.rb +19 -0
  26. data/docs/intro/example4/grab-yuml.rb +10 -0
  27. data/docs/intro/example4/greeter.rb +15 -0
  28. data/docs/intro/example4/greeting.rb +9 -0
  29. data/docs/intro/example4/project-generator.rb +25 -0
  30. data/docs/intro/example4/xml/greeter.xml +6 -0
  31. data/docs/intro/grab-yuml.rb +10 -0
  32. data/docs/intro/project-generator.rb +51 -0
  33. data/docs/intro/xampl.lyx +1494 -0
  34. data/docs/intro/xampl.pdf +0 -0
  35. data/examples/employees/final/xampl-gen.rb +38 -0
  36. data/examples/employees/final/xml/ddd-final.xml +86 -0
  37. data/examples/employees/final-xampl/xampl-gen.rb +38 -0
  38. data/examples/employees/final-xampl/xml/ddd-final-xampl.xml +86 -0
  39. data/examples/employees/first/xampl-gen.rb +38 -0
  40. data/examples/employees/first/xml/ddd-first.xml +48 -0
  41. data/examples/employees/twist/twist.graphml +333 -0
  42. data/examples/employees/twist/xampl-gen.rb +38 -0
  43. data/examples/employees/twist/xml/twist.xml +90 -0
  44. data/examples/employees/xamplr-twist.xml +2 -0
  45. data/examples/employees/yuml-diagrams/DDD-final-approach.graphml +393 -0
  46. data/examples/employees/yuml-diagrams/DDD-final-xampl-approach.graphml +265 -0
  47. data/examples/employees/yuml-diagrams/DDD-ideal-final-approach.graphml +357 -0
  48. data/examples/employees/yuml-diagrams/ddd-final.png +0 -0
  49. data/examples/employees/yuml-diagrams/ddd-final.yuml +8 -0
  50. data/examples/employees/yuml-diagrams/ddd-first.png +0 -0
  51. data/examples/employees/yuml-diagrams/ddd-first.yuml +7 -0
  52. data/examples/employees/yuml-diagrams/final-yed.png +0 -0
  53. data/examples/employees/yuml-diagrams/first-yed.png +0 -0
  54. data/examples/employees/yuml-diagrams/twist.png +0 -0
  55. data/examples/employees/yuml-diagrams/twist.yuml +12 -0
  56. data/examples/employees/yuml-diagrams/xamplr-final-no-mixins.png +0 -0
  57. data/examples/employees/yuml-diagrams/xamplr-final-simplified.png +0 -0
  58. data/examples/employees/yuml-diagrams/xamplr-final-with-mixins.png +0 -0
  59. data/examples/employees/yuml-diagrams/yuml-simplified.txt +19 -0
  60. data/examples/employees/yuml-diagrams/yuml-with-mixins.txt +53 -0
  61. data/examples/employees/yuml-diagrams/yuml.txt +27 -0
  62. data/examples/hobbies/Makefile +5 -0
  63. data/examples/hobbies/hobbies.rb +193 -0
  64. data/examples/hobbies/project-generator.rb +25 -0
  65. data/examples/hobbies/xampl-gen.rb +38 -0
  66. data/examples/hobbies/xml/hobby.xml +3 -0
  67. data/examples/hobbies/xml/people.xml +5 -0
  68. data/examples/random-people/.gitignore +2 -0
  69. data/examples/random-people/Makefile +5 -1
  70. data/examples/random-people/xampl-gen.rb +5 -2
  71. data/examples/random-people-shared-addresses/.gitignore +2 -0
  72. data/examples/random-people-shared-addresses/Makefile +8 -9
  73. data/examples/random-people-shared-addresses/batch-load-users-profiled.rb +91 -0
  74. data/examples/random-people-shared-addresses/batch-load-users-safe.rb +81 -0
  75. data/examples/random-people-shared-addresses/batch-load-users.rb +59 -63
  76. data/examples/random-people-shared-addresses/xampl-gen.rb +2 -0
  77. data/examples/read-testing/.gitignore +2 -0
  78. data/examples/read-testing/rrr.rb +2 -1
  79. data/examples/read-testing/xampl-gen.rb +2 -0
  80. data/examples/tokyo-cabinet-experimental/.gitignore +2 -0
  81. data/examples/tokyo-cabinet-experimental/xampl-gen.rb +2 -0
  82. data/examples/write-testing/README +4 -0
  83. data/examples/write-testing/RESULTS.home +33 -0
  84. data/examples/write-testing/RESULTS.raconteur +33 -0
  85. data/examples/write-testing/write-speed-test.rb +40 -0
  86. data/lib/xamplr/.cvsignore +1 -0
  87. data/lib/xamplr/TODO +2 -1
  88. data/lib/xamplr/exceptions.rb +24 -1
  89. data/lib/xamplr/from-xml.rb +13 -5
  90. data/lib/xamplr/graphml-out.rb +6 -25
  91. data/lib/xamplr/indexed-array.rb +10 -2
  92. data/lib/xamplr/persist-to-xml.rb +6 -7
  93. data/lib/xamplr/persistence.rb +132 -48
  94. data/lib/xamplr/persister.rb +48 -25
  95. data/lib/xamplr/persisters/filesystem.rb +8 -2
  96. data/lib/xamplr/persisters/tokyo-cabinet.rb +243 -63
  97. data/lib/xamplr/persisters/tokyo-cabinet.rb.1-DB +694 -0
  98. data/lib/xamplr/persisters/tokyo-cabinet.rb.N-DB +692 -0
  99. data/lib/xamplr/persisters/tokyo-cabinet.rb.NICE-TRY +807 -0
  100. data/lib/xamplr/templates/.cvsignore +3 -0
  101. data/lib/xamplr/templates/child_indexed.template +6 -6
  102. data/lib/xamplr/templates/element_data.template +2 -1
  103. data/lib/xamplr/templates/element_empty.template +2 -10
  104. data/lib/xamplr/templates/element_mixed.template +2 -1
  105. data/lib/xamplr/templates/element_simple.template +2 -1
  106. data/lib/xamplr/templates/package.template +13 -1
  107. data/lib/xamplr/visitor.rb +7 -6
  108. data/lib/xamplr/visitors.rb +2 -1
  109. data/lib/xamplr/xampl-cl-gen.rb +89 -0
  110. data/lib/xamplr/xampl-generator.rb +86 -50
  111. data/lib/xamplr/xampl-object.rb +51 -0
  112. data/lib/xamplr/xampl-persisted-object.rb +13 -4
  113. data/lib/xamplr/yuml-out.rb +129 -0
  114. data/lib/xamplr-generator.rb +0 -1
  115. data/lib/xamplr.rb +18 -18
  116. data/regression/tc-indexes-crossing-pid-boundaries/Makefile +14 -0
  117. data/regression/tc-indexes-crossing-pid-boundaries/bad-idea.rb +40 -0
  118. data/regression/tc-indexes-crossing-pid-boundaries/fail-badly.rb +17 -0
  119. data/regression/tc-indexes-crossing-pid-boundaries/fail.rb +11 -0
  120. data/regression/tc-indexes-crossing-pid-boundaries/fucking-bad-idea.rb +44 -0
  121. data/regression/tc-indexes-crossing-pid-boundaries/setup.rb +15 -0
  122. data/regression/tc-indexes-crossing-pid-boundaries/xml/bad-idea.xml +4 -0
  123. data/regression/tightly-nested-mutual-mentions/Makefile +14 -0
  124. data/regression/tightly-nested-mutual-mentions/build.rb +31 -0
  125. data/regression/tightly-nested-mutual-mentions/load.rb +21 -0
  126. data/regression/tightly-nested-mutual-mentions/repo-keep.tgz +0 -0
  127. data/regression/tightly-nested-mutual-mentions/setup.rb +8 -0
  128. data/regression/tightly-nested-mutual-mentions/xampl-gen.rb +36 -0
  129. data/regression/tightly-nested-mutual-mentions/xml/stuff.xml +7 -0
  130. data/xamplr.gemspec +322 -0
  131. metadata +116 -13
  132. data/test/test_helper.rb +0 -10
  133. data/test/xamplr_test.rb +0 -7
@@ -1,4 +1,3 @@
1
-
2
1
  require "xamplr/persistence"
3
2
 
4
3
  module Xampl
@@ -41,6 +40,11 @@ module Xampl
41
40
  self.sync
42
41
  end
43
42
 
43
+ def shutdown
44
+ # self.sync
45
+ # self.close
46
+ end
47
+
44
48
  def busy(yes)
45
49
  if yes then
46
50
  @busy_count += 1
@@ -204,7 +208,15 @@ module Xampl
204
208
 
205
209
  def put_changed(msg="")
206
210
  puts "Changed::#{msg}:"
207
- @changed.each { | xampl, ignore | puts " #{xampl.tag} #{xampl.get_the_index}" }
211
+ @changed.each { | xampl, ignore | puts " #{xampl.tag} #{xampl.get_the_index}" }
212
+ end
213
+
214
+ def start_sync_write
215
+ #only if needed
216
+ end
217
+
218
+ def done_sync_write
219
+ # only if needed
208
220
  end
209
221
 
210
222
  def do_sync_write
@@ -220,29 +232,39 @@ module Xampl
220
232
  def sync
221
233
  #raise XamplException.new(:live_across_rollback) if @rolled_back
222
234
  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
235
+ # puts "#{ __FILE__ }:#{ __LINE__ } [#{__method__}] SYNC changed: #{@changed.size}" if 0 < @changed.size
236
+ # @changed.each do | key, value |
237
+ # puts "#{ __FILE__ }:#{ __LINE__ } [#{__method__}] key: #{key.class.name}, pid: #{key.get_the_index}"
238
+ # end
239
+ #
240
+ # if 0 < @changed.size then
241
+ # puts "#{ __FILE__ }:#{ __LINE__ } [#{__method__}] SYNC changed: #{@changed.size}"
242
+ # caller(0).each do | trace |
243
+ # next if /xamplr/ =~ trace
244
+ # puts " #{trace}"
245
+ # break if /actionpack/ =~ trace
246
+ # end
247
+ # end
248
+ #
249
+ # puts "#{ __FILE__ }:#{ __LINE__ } [#{__method__}] SYNC changed: #{@changed.size}"
250
+ if 0 < @changed.size then
251
+ begin
252
+ # puts "#{ __FILE__ }:#{ __LINE__ } [#{__method__}] SYNC changed: #{@changed.size}"
253
+ busy(true)
254
+ # if @syncing then
255
+ # puts "\n\n\n\n#{ __FILE__ }:#{ __LINE__ } [#{__method__}] SYNCING IS ALREADY TRUE!!!!!!\n\n\n"
256
+ # end
257
+ @syncing = true
258
+
259
+ start_sync_write
260
+ do_sync_write
261
+ ensure
262
+ done_sync_write
263
+ @syncing = false
264
+ end
265
+ else
266
+ # puts "#{ __FILE__ }:#{ __LINE__ } [#{__method__}] SYNC, noting changed"
267
+ end
246
268
 
247
269
  @changed = {}
248
270
 
@@ -260,6 +282,7 @@ module Xampl
260
282
  return @last_write_count
261
283
  ensure
262
284
  busy(false)
285
+ # puts "#{ __FILE__ }:#{ __LINE__ } [#{__method__}] **** SYNCING IS FALSE"
263
286
  @syncing = false
264
287
  end
265
288
  end
@@ -25,7 +25,6 @@ module Xampl
25
25
  end
26
26
  end
27
27
 
28
-
29
28
  def write(xampl)
30
29
  #raise XamplException.new(:no_index_so_no_persist) unless xampl.get_the_index or xampl.ignore_when_no_index
31
30
  raise XamplException.new("no_index_so_no_persist [#{xampl.class.name}]") unless xampl.get_the_index or xampl.ignore_when_no_index
@@ -39,7 +38,14 @@ module Xampl
39
38
 
40
39
  representation = represent(xampl)
41
40
  if representation then
42
- File.open(place, "w"){ | out | out.puts representation }
41
+ File.open(place, "w")do |out|
42
+ out.puts representation
43
+ out.fsync
44
+ if $is_darwin then
45
+ out.fcntl(51, 0) # Attempt an F_FULLFSYNC fcntl to commit data to disk
46
+ end
47
+
48
+ end
43
49
  @write_count = @write_count + 1
44
50
  end
45
51
  xampl.changes_accepted
@@ -5,29 +5,49 @@ module Xampl
5
5
  require 'xamplr/persisters/caching'
6
6
  require 'set'
7
7
 
8
- # require 'ruby-prof'
8
+ # require 'ruby-prof'
9
9
 
10
10
  class TokyoCabinetPersister < AbstractCachingPersister
11
11
  include TokyoCabinet
12
12
 
13
13
  def note_errors(msg="TokyoCabinet Error:: %s\n")
14
- result = yield
14
+ # puts "#{ __FILE__ }:#{ __LINE__ } [#{__method__}] START"
15
+ # puts "--------------------------------------------------"
16
+ # caller(0).each { |trace| puts " #{trace}" }
17
+ # puts "--------------------------------------------------\n\n"
18
+ exception = nil
19
+ begin
20
+ result = yield
21
+ rescue => e
22
+ exception = e
23
+ end
15
24
 
16
25
  rmsg = nil
17
26
  unless result then
18
27
  rmsg = sprintf(msg, @tc_db.errmsg(@tc_db.ecode))
28
+ STDERR.puts "NOTE: TokyoCabinet Error!"
19
29
  STDERR.printf(rmsg)
20
30
  STDERR.puts "---------"
21
31
  caller(0).each do |trace|
22
32
  STDERR.puts(trace)
23
33
  end
24
34
  STDERR.puts "---------"
35
+
36
+ # STDOUT.puts "NOTE: TokyoCabinet Error!"
37
+ # STDOUT.printf(rmsg)
38
+ # STDOUT.puts "---------"
39
+ # caller(0).each do |trace|
40
+ # STDOUT.puts(trace)
41
+ # end
42
+ # STDOUT.puts "---------"
25
43
  end
44
+ raise exception if exception
26
45
  return rmsg
27
46
  end
28
47
 
29
- $lexical_indexes = Set.new(%w{ class pid time-stamp xampl_from xampl_to }) unless defined?($lexical_indexes)
30
- $numeric_indexes = Set.new unless defined?($numeric_indexes)
48
+ $lexical_indexes = Set.new(%w{ class pid time-stamp xampl-from xampl-to xampl-place }) unless defined?($lexical_indexes)
49
+
50
+ $numeric_indexes = Set.new(%w{ scheduled-delete-at }) unless defined?($numeric_indexes)
31
51
 
32
52
  def TokyoCabinetPersister.add_lexical_indexs(indexes)
33
53
  $lexical_indexes.merge(indexes)
@@ -40,31 +60,54 @@ module Xampl
40
60
  def initialize(name=nil, format=nil, root=File.join(".", "repo"))
41
61
  super(root, name, format)
42
62
 
43
- FileUtils.mkdir_p(@root_dir) unless File.exist?(@root_dir)
63
+ @files_dir = "#{ @root_dir }/files"
64
+ # FileUtils.mkdir_p(@root_dir) unless File.exist?(@root_dir)
65
+ FileUtils.mkdir_p(@files_dir) unless File.exist?(@files_dir)
44
66
  @filename = "#{@root_dir}/repo.tct"
67
+ @tc_db = nil
68
+ # puts "#{ __FILE__ }:#{ __LINE__ } [#{__method__}] file: #{ @filename }, db: #{ @tc_db.class.name }"
45
69
 
46
70
  open_tc_db()
47
71
 
48
- # note_errors("TC[[#{ @filename }]]:: optimisation error: %s\n") do
49
- # @tc_db.optimize(-1, -1, -1, TDB::TDEFLATE)
50
- # end
51
- # note_errors("TC[[#{ @filename }]]:: close error: %s\n") do
52
- # @tc_db.close
53
- # end
72
+ # note_errors("TC[[#{ @filename }]]:: optimisation error: %s\n") do
73
+ # @tc_db.optimize(-1, -1, -1, TDB::TDEFLATE)
74
+ # end
75
+ # note_errors("TC[[#{ @filename }]]:: close error: %s\n") do
76
+ # @tc_db.close
77
+ # end
78
+
79
+ begin
80
+ note_errors("TC[[#{ @filename }]]:: close error in initialize: %s\n") do
81
+ @tc_db.close
82
+ end
83
+ @tc_db = nil
84
+ rescue => e
85
+ puts "#{ __FILE__ }:#{ __LINE__ } [#{__method__}] OH CRAP!!! #{ e }"
86
+ end
54
87
  end
55
88
 
56
89
  def open_tc_db
57
- return if @tc_db
58
- # puts "#{File.basename(__FILE__)}:#{__LINE__} open tc db: #{ @filename }"
59
- #puts "#{File.basename(__FILE__)}:#{__LINE__} callers..."
60
- #caller(0).each { | trace | puts " #{trace}"}
90
+ # if @tcdb then
91
+ # puts "#{ __FILE__ }:#{ __LINE__ } [#{__method__}] ALREADY OPEN #{ @filename }"
92
+ # else
93
+ # puts "#{ __FILE__ }:#{ __LINE__ } [#{__method__}] OPEN #{ @filename }"
94
+ ## callers = caller(0)
95
+ ## puts " 0 #{ callers[0] }"
96
+ ## puts " 1 #{ callers[1] }"
97
+ ## puts " 2 #{ callers[2] }"
98
+ # #puts "#{File.basename(__FILE__)}:#{__LINE__} callers..."
99
+ # #caller(0).each { | trace | puts " #{trace}"}
100
+ # end
101
+
102
+ return if @tc_db # if there is a tc_db then it is already open
103
+
61
104
  @tc_db = TDB.new
62
105
  note_errors("TC[[#{ @filename }]]:: tuning error: %s\n") do
63
106
  @tc_db.tune(-1, -1, -1, TDB::TDEFLATE)
64
107
  end
65
108
 
66
109
  note_errors("TC[[#{ @filename }]]:: open [#{ @filename }] error: %s\n") do
67
- @tc_db.open(@filename, TDB::OWRITER | TDB::OCREAT | TDB::OLCKNB ) #TDB::OTSYNC slows it down by almost 50 times
110
+ @tc_db.open(@filename, TDB::OWRITER | TDB::OCREAT | TDB::OLCKNB | TDB::OTSYNC ) #TDB::OTSYNC slows it down by almost 50 times
68
111
  end
69
112
 
70
113
  # Don't care if there are errors (in fact, if the index exists a failure is the expected thing)
@@ -96,13 +139,24 @@ module Xampl
96
139
  end
97
140
 
98
141
  def close
142
+ # puts "#{ __FILE__ }:#{ __LINE__ } [#{__method__}] CLOSE #{ @filename }"
143
+ # callers = caller(0)
144
+ # puts " 0 #{ callers[0] }"
145
+ # puts " 1 #{ callers[1] }"
146
+ # puts " 2 #{ callers[2] }"
147
+
99
148
  if @tc_db then
100
- self.sync
101
- note_errors("TC[[#{ @filename }]]:: close error: %s\n") do
102
- @tc_db.close
149
+ begin
150
+ # puts "#{ __FILE__ }:#{ __LINE__ } [#{__method__}] NO SELF SYNC?? [#{ @currently_syncing }] --> db: #{ @tc_db.class.name }"
151
+ self.sync unless @currently_syncing
152
+ rescue => e
153
+ puts "#{ __FILE__ }:#{ __LINE__ } [#{__method__}] OH CRAP!!! #{ e }"
154
+ ensure
155
+ note_errors("TC[[#{ @filename }]]:: close error: %s\n") do
156
+ @tc_db.close
157
+ end
158
+ @tc_db = nil
103
159
  end
104
- @tc_db = nil
105
- # puts "#{File.basename(__FILE__)}:#{__LINE__} close tc db: #{ @filename }"
106
160
  end
107
161
  end
108
162
 
@@ -155,9 +209,9 @@ module Xampl
155
209
  end
156
210
 
157
211
  if hint then
158
- return results, the_hint
212
+ return results.uniq, the_hint
159
213
  else
160
- return results
214
+ return results.uniq
161
215
  end
162
216
  end
163
217
 
@@ -199,9 +253,9 @@ module Xampl
199
253
  end
200
254
 
201
255
  if hint then
202
- return results, the_hint
256
+ return results.uniq, the_hint
203
257
  else
204
- return results
258
+ return results.uniq
205
259
  end
206
260
  end
207
261
 
@@ -219,10 +273,15 @@ module Xampl
219
273
  result_keys = query.search
220
274
  end
221
275
 
276
+ results = result_keys.collect do |key|
277
+ meta = @tc_db[ key ]
278
+ meta['xampl-place'] || meta['place']
279
+ end
280
+
222
281
  if hint then
223
- return result_keys, the_hint
282
+ return results.uniq, the_hint
224
283
  else
225
- return result_keys
284
+ return results.uniq
226
285
  end
227
286
  end
228
287
 
@@ -255,7 +314,7 @@ module Xampl
255
314
  place = File.join(xampl.class.name.split("::"), xampl.get_the_index)
256
315
 
257
316
  query = TableQuery.new(@tc_db)
258
- query.add_condition('xampl_to', :equals, place)
317
+ query.add_condition('xampl-to', :equals, place)
259
318
  result_keys = query.search
260
319
 
261
320
  class_cache = {}
@@ -263,8 +322,8 @@ module Xampl
263
322
  result = @tc_db[ key ]
264
323
  next unless result
265
324
 
266
- mentioner = result['xampl_from']
267
- class_name = result['class']
325
+ mentioner = result['xampl-from']
326
+ class_name = result['mentioned_class']
268
327
  result_class = class_cache[class_name]
269
328
  unless result_class then
270
329
  class_name.split("::").each do | chunk |
@@ -280,30 +339,43 @@ module Xampl
280
339
 
281
340
  self.lookup(result_class, result['pid'])
282
341
  end
283
- return results
342
+ return results.uniq
284
343
  end
285
344
 
286
- def do_sync_write
287
- # RubyProf.start
288
- #
289
- # do_sync_write_work
290
- #
291
- # result = RubyProf.stop
292
- # printer = RubyProf::FlatPrinter.new(result)
293
- # printer.print(STDOUT, 0)
294
- # puts "#{File.basename(__FILE__)}:#{__LINE__} stop this profiler"
295
- # end
296
- #
297
- # def do_sync_write_work
345
+ def start_sync_write
346
+ # puts "#{ __FILE__ }:#{ __LINE__ } [#{__method__}] #{ @filename }"
347
+ # callers = caller(0)
348
+ # puts " 0 #{ callers[0] }"
349
+ # puts " 1 #{ callers[1] }"
350
+ # puts " 2 #{ callers[2] }"
351
+
352
+ @currently_syncing = true
298
353
  open_tc_db
299
- @time_stamp = Time.now.to_f.to_s
354
+ end
355
+
356
+ def done_sync_write
357
+ begin
358
+ note_errors("TC[[#{ @filename }]]:: sync error in done_sync_write: %s\n") do
359
+ @tc_db.sync
360
+ end
361
+ # close
362
+ ensure
363
+ @currently_syncing = false
364
+ end
365
+ end
300
366
 
301
- # puts "DO SYNC WRITE: #{ @changed.size } to be written (#{ @filename })"
302
- # note_errors("TC:: open error: %s\n") do
303
- # @tc_db.open(@filename, TDB::OWRITER | TDB::OCREAT | TDB::OLCKNB ) #TDB::OTSYNC slows it down by almost 50 times
304
- # end
305
367
 
368
+ def do_sync_write
306
369
  begin
370
+ # puts "#{ __FILE__ }:#{ __LINE__ } [#{__method__}] **************************"
371
+ # callers = caller(0)
372
+ # puts " 0 #{ callers[0] }"
373
+ # puts " 1 #{ callers[1] }"
374
+ # puts " 2 #{ callers[2] }"
375
+
376
+ # open_tc_db
377
+ @time_stamp = Time.now.to_f.to_s
378
+
307
379
  note_errors("TC[[#{ @filename }]]:: tranbegin error: %s\n") do
308
380
  @tc_db.tranbegin
309
381
  end
@@ -313,45 +385,97 @@ module Xampl
313
385
  end
314
386
  rescue => e
315
387
  msg = "no TC.abort attempted"
316
- msg = note_errors("TC[[#{ @filename }]]:: trancommit error: %s\n") do
388
+ msg = note_errors("TC[[#{ @filename }]]:: tranabort error: %s\n") do
317
389
  @tc_db.tranabort
318
390
  end
391
+ puts "------------------------------------------------------------------------"
392
+ puts "TokyoCabinetPersister Error:: #{ msg }/#{ e }"
393
+ puts e.backtrace.join("\n")
394
+ puts "------------------------------------------------------------------------"
319
395
  raise "TokyoCabinetPersister Error:: #{ msg }/#{ e }"
320
396
  else
397
+ # puts "#{ __FILE__ }:#{ __LINE__ } [#{__method__}] COMMIT"
321
398
  note_errors("TC[[#{ @filename }]]:: trancommit error: %s\n") do
322
399
  @tc_db.trancommit
323
400
  end
324
401
  ensure
325
- # note_errors("TC[[#{ @filename }]]:: close error: %s\n") do
326
- # @tc_db.close()
327
- # end
328
- end
329
402
  # puts " num records: #{ @tc_db.rnum() }"
403
+ # puts "#{ __FILE__ }:#{ __LINE__ } keys..."
404
+ # @tc_db.keys.each do | key |
405
+ # meta = @tc_db[key]
406
+ # meta['xampl'] = (meta['xampl'] || "no rep")[0..25]
407
+ # puts " key: [#{ key }] -- #{ meta.inspect }"
408
+ # end
409
+
410
+ # close
411
+ end
412
+ end
413
+
414
+ def how_indexed(xampl)
415
+ raise XamplException.new(:no_index_so_no_persist) unless xampl.get_the_index
416
+ place = File.join(xampl.class.name.split("::"), xampl.get_the_index)
417
+
418
+ open_tc_db
419
+
420
+ result_keys = Set.new
421
+
422
+ query = TableQuery.new(@tc_db)
423
+ query.add_condition('xampl-place', :equals, place)
424
+ search_results = query.search
425
+ result_keys.merge( search_results)
426
+
427
+ primary = @tc_db[ place ]
428
+ if primary then
429
+ primary.delete('xampl')
430
+ end
431
+
432
+ results = primary ? [ primary ] : []
433
+ result_keys.each do | key |
434
+ result = @tc_db[ key ]
435
+ next unless result
436
+
437
+ result.delete('xampl')
438
+
439
+ results << result
440
+ end
441
+
442
+ results
330
443
  end
331
444
 
332
445
  def write(xampl)
333
446
  raise XamplException.new(:no_index_so_no_persist) unless xampl.get_the_index
334
447
 
335
- place = File.join(xampl.class.name.split("::"), xampl.get_the_index)
448
+ place_dir = xampl.class.name.split("::")
449
+ place = File.join( place_dir, xampl.get_the_index)
450
+ place_dir = File.join( @files_dir, place_dir )
336
451
  mentions = Set.new
337
452
  data = represent(xampl, mentions)
338
453
 
454
+ #get rid of any supplimentary indexes associated with this xampl object
455
+ # TODO -- This can be slow
339
456
  query = TableQuery.new(@tc_db)
340
- query.add_condition('xampl_from', :equals, place)
457
+ query.add_condition('xampl-from', :equals, place)
341
458
  note_errors("TC[[#{ @filename }]]:: failed to remove from mentions, error: %s\n") do
342
459
  query.searchout
343
460
  end
344
461
 
462
+ query = TableQuery.new(@tc_db)
463
+ query.add_condition('xampl-place', :equals, place)
464
+ note_errors("TC[[#{ @filename }]]:: failed to remove from mentions, error: %s\n") do
465
+ query.searchout
466
+ end
467
+
468
+ # TODO -- This can be slow
345
469
  mentions.each do | mention |
346
470
  mention_place = File.join(mention.class.name.split("::"), mention.get_the_index)
347
471
  #TODO -- will repeadedly changing a persisted xampl object fragment the TC db?
348
472
 
349
473
  pk = @tc_db.genuid
350
474
  mention_hash = {
351
- 'xampl_from' => place,
352
- 'class' => xampl.class.name,
475
+ 'xampl-from' => place,
476
+ 'mentioned_class' => xampl.class.name,
353
477
  'pid' => xampl.get_the_index,
354
- 'xampl_to' => mention_place
478
+ 'xampl-to' => mention_place
355
479
  }
356
480
 
357
481
  note_errors("TC[[#{ @filename }]]:: write error: %s\n") do
@@ -366,15 +490,56 @@ module Xampl
366
490
  'xampl' => data
367
491
  }
368
492
 
369
- hash = xampl.describe_yourself
370
- if hash then
371
- xampl_hash = hash.merge(xampl_hash)
493
+ # puts "#{ __FILE__ }:#{ __LINE__ } [#{__method__}] #{ xampl.class.name } ... describe"
494
+ primary_description, secondary_descriptions = xampl.describe_yourself
495
+ if primary_description then
496
+ xampl_hash = primary_description.merge(xampl_hash)
372
497
  end
373
498
 
374
499
  note_errors("TC[[#{ @filename }]]:: write error: %s\n") do
500
+ if Xampl.raw_persister_options[:write_through] then
501
+ FileUtils.mkdir_p(place_dir) unless File.exist?(place_dir)
502
+ file_place = "#{ @files_dir }/#{ place }"
503
+ File.open(file_place, "w")do |out|
504
+ out.write xampl_hash['xampl']
505
+ if :sync == Xampl.raw_persister_options[:write_through] then
506
+ out.fsync
507
+ if $is_darwin then
508
+ out.fcntl(51, 0) # Attempt an F_FULLFSYNC fcntl to commit data to disk (darwin *ONLY*)
509
+ end
510
+ end
511
+ end
512
+
513
+ end
375
514
  @tc_db.put(place, xampl_hash)
376
515
  end
377
516
 
517
+ #TODO -- smarter regarding when to delete (e.g. mentions)
518
+ if xampl.should_schedule_delete? and xampl.scheduled_for_deletion_at then
519
+ secondary_descriptions = [] unless secondary_descriptions
520
+ secondary_descriptions << { 'scheduled-delete-at' => xampl.scheduled_for_deletion_at }
521
+ elsif xampl.scheduled_for_deletion_at then
522
+ puts "#{ __FILE__ }:#{ __LINE__ } HOW TO DO THIS without violating xampl's change rules????? "
523
+ #xampl.scheduled_for_deletion_at = nil
524
+ end
525
+
526
+ if secondary_descriptions then
527
+ xampl_hash = {
528
+ 'class' => xampl.class.name,
529
+ 'pid' => xampl.get_the_index,
530
+ 'xampl-place' => place
531
+ }
532
+
533
+ secondary_descriptions.each do | secondary_description |
534
+ description = secondary_description.merge(xampl_hash)
535
+
536
+ note_errors("TC[[#{ @filename }]]:: write error: %s\n") do
537
+ pk = @tc_db.genuid
538
+ @tc_db.put(pk, description)
539
+ end
540
+ end
541
+ end
542
+
378
543
  @write_count = @write_count + 1
379
544
  xampl.changes_accepted
380
545
  return true
@@ -389,10 +554,14 @@ module Xampl
389
554
  # puts "#{File.basename(__FILE__)}:#{__LINE__} READ #{ klass }/#{ pid }"
390
555
  # caller(0).each { | trace | puts " #{trace}"}
391
556
 
392
- open_tc_db
393
- place = File.join(klass.name.split("::"), pid)
394
557
  representation = nil
395
558
 
559
+ unless @tc_db then
560
+ # puts "#{ __FILE__ }:#{ __LINE__ } [#{__method__}] READ REP"
561
+ open_tc_db
562
+ end
563
+ place = File.join(klass.name.split("::"), pid)
564
+
396
565
  meta = @tc_db[place]
397
566
  representation = meta['xampl'] if meta
398
567
 
@@ -508,6 +677,7 @@ module Xampl
508
677
 
509
678
  def initialize (table)
510
679
  @query = TDBQRY::new(table)
680
+ @text_form = []
511
681
  @opts = {}
512
682
  end
513
683
 
@@ -602,6 +772,8 @@ module Xampl
602
772
  op = op | TDBQRY::QCNEGATE unless affirmative
603
773
  op = op | TDBQRY::QCNOIDX if no_index
604
774
 
775
+ @text_form << "operator: #{ operator }#{ affirmative ? '' : ' NEGATED'}#{ no_index ? ' NO INDEX' : ''} -- col: '#{ colname }', val: '#{ val }'"
776
+
605
777
  @query.addcond(colname, op, val)
606
778
  end
607
779
 
@@ -634,6 +806,14 @@ module Xampl
634
806
  def order_by (colname, direction=:strasc)
635
807
  @query.setorder(colname, DIRECTIONS[direction])
636
808
  end
809
+
810
+ def inspect
811
+ "TableQuery:\n#{ @text_form.join("\n") }"
812
+ end
813
+
814
+ def to_s
815
+ inspect
816
+ end
637
817
  end
638
818
 
639
819
  Xampl.register_persister_kind(TokyoCabinetPersister)