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