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.
- data/CHANGES.txt +13 -0
- data/LICENSE +3 -0
- data/README.rdoc +26 -0
- data/README.rdoc.orig +118 -0
- data/Rakefile +85 -0
- data/VERSION.yml +4 -0
- data/examples/random-people-shared-addresses/Makefile +16 -0
- data/examples/random-people-shared-addresses/batch-load-users.rb +83 -0
- data/examples/random-people-shared-addresses/find-mentions.rb +47 -0
- data/examples/random-people-shared-addresses/find-people-by-address.rb +104 -0
- data/examples/random-people-shared-addresses/optimise.rb +16 -0
- data/examples/random-people-shared-addresses/people.rb +35 -0
- data/examples/random-people-shared-addresses/query.rb +75 -0
- data/examples/random-people-shared-addresses/query2.rb +73 -0
- data/examples/random-people-shared-addresses/random-names.csv +10000 -0
- data/examples/random-people-shared-addresses/settings.rb +3 -0
- data/examples/random-people-shared-addresses/what-to-query-on.rb +82 -0
- data/examples/random-people-shared-addresses/xampl-gen.rb +36 -0
- data/examples/random-people-shared-addresses/xml/people.xml +14 -0
- data/examples/random-people/Makefile +16 -0
- data/examples/random-people/batch-load-users.rb +61 -0
- data/examples/random-people/optimise.rb +16 -0
- data/examples/random-people/people.rb +22 -0
- data/examples/random-people/query.rb +73 -0
- data/examples/random-people/query2.rb +73 -0
- data/examples/random-people/random-names.csv +10000 -0
- data/examples/random-people/rawtc.rb +91 -0
- data/examples/random-people/settings.rb +3 -0
- data/examples/random-people/what-to-query-on.rb +80 -0
- data/examples/random-people/xampl-gen.rb +36 -0
- data/examples/random-people/xml/people.xml +11 -0
- data/examples/read-testing/Makefile +10 -0
- data/examples/read-testing/load.rb +65 -0
- data/examples/read-testing/read.rb +51 -0
- data/examples/read-testing/rrr.rb +87 -0
- data/examples/read-testing/settings.rb +2 -0
- data/examples/read-testing/xampl-gen.rb +36 -0
- data/examples/read-testing/xml/text.xml +8 -0
- data/examples/tokyo-cabinet-experimental/expt-query.rb +42 -0
- data/examples/tokyo-cabinet-experimental/expt-query2.rb +42 -0
- data/examples/tokyo-cabinet-experimental/expt-query3.rb +41 -0
- data/examples/tokyo-cabinet-experimental/expt-reader.rb +32 -0
- data/examples/tokyo-cabinet-experimental/expt.rb +61 -0
- data/examples/tokyo-cabinet-experimental/xampl-gen.rb +36 -0
- data/examples/tokyo-cabinet-experimental/xml/tcx.xml +6 -0
- data/lib/xampl-generator.rb +3 -0
- data/lib/xampl.rb +3 -0
- data/lib/xamplr-generator.rb +10 -0
- data/lib/xamplr.rb +37 -0
- data/lib/xamplr/README-POSSIBLE-PROBLEMS +5 -0
- data/lib/xamplr/TODO +1 -0
- data/lib/xamplr/exceptions.rb +97 -0
- data/lib/xamplr/from-xml-orig.rb +350 -0
- data/lib/xamplr/from-xml.rb +439 -0
- data/lib/xamplr/gen-elements.xml +6230 -0
- data/lib/xamplr/gen.elements.xml +108 -0
- data/lib/xamplr/generate-elements.rb +15 -0
- data/lib/xamplr/generator.rb +5 -0
- data/lib/xamplr/graphml-out.rb +470 -0
- data/lib/xamplr/handwritten/example.rb +698 -0
- data/lib/xamplr/handwritten/hand-example.rb +533 -0
- data/lib/xamplr/handwritten/test-handwritten.rb +873 -0
- data/lib/xamplr/indexed-array.rb +115 -0
- data/lib/xamplr/mixins.rb +397 -0
- data/lib/xamplr/my.gen.elements.xml +461 -0
- data/lib/xamplr/notifications.rb +57 -0
- data/lib/xamplr/obsolete/fsdb.rb +62 -0
- data/lib/xamplr/persist-to-xml.rb +249 -0
- data/lib/xamplr/persistence.rb +522 -0
- data/lib/xamplr/persistence.rb.more_thread_safe +771 -0
- data/lib/xamplr/persistence.rb.partially_thread_safe +763 -0
- data/lib/xamplr/persister.rb +310 -0
- data/lib/xamplr/persisters/caches.rb +186 -0
- data/lib/xamplr/persisters/caching.rb +172 -0
- data/lib/xamplr/persisters/filesystem.rb +60 -0
- data/lib/xamplr/persisters/in-memory.rb +180 -0
- data/lib/xamplr/persisters/simple.rb +59 -0
- data/lib/xamplr/persisters/tokyo-cabinet.rb +641 -0
- data/lib/xamplr/simpleTemplate/danger.rx +4 -0
- data/lib/xamplr/simpleTemplate/obsolete/input-c.r4 +35 -0
- data/lib/xamplr/simpleTemplate/obsolete/play.r6.txt +12 -0
- data/lib/xamplr/simpleTemplate/obsolete/play_more.r6.txt +20 -0
- data/lib/xamplr/simpleTemplate/obsolete/test001.r5 +8 -0
- data/lib/xamplr/simpleTemplate/obsolete/test002.r5 +13 -0
- data/lib/xamplr/simpleTemplate/obsolete/test003.r5 +37 -0
- data/lib/xamplr/simpleTemplate/old/r6.000.rb +122 -0
- data/lib/xamplr/simpleTemplate/old/r6.001.rb +145 -0
- data/lib/xamplr/simpleTemplate/play.r6 +12 -0
- data/lib/xamplr/simpleTemplate/play_more.r6 +20 -0
- data/lib/xamplr/simpleTemplate/play_noblanks.r6 +21 -0
- data/lib/xamplr/simpleTemplate/playq.r6 +16 -0
- data/lib/xamplr/simpleTemplate/r6.rb +87 -0
- data/lib/xamplr/simpleTemplate/simple-template.rb +75 -0
- data/lib/xamplr/templates/child.template +47 -0
- data/lib/xamplr/templates/child_indexed.template +89 -0
- data/lib/xamplr/templates/child_modules.template +5 -0
- data/lib/xamplr/templates/element_classes.template +11 -0
- data/lib/xamplr/templates/element_data.template +282 -0
- data/lib/xamplr/templates/element_empty.template +285 -0
- data/lib/xamplr/templates/element_mixed.template +277 -0
- data/lib/xamplr/templates/element_simple.template +276 -0
- data/lib/xamplr/templates/package.template +26 -0
- data/lib/xamplr/test-support/Makefile +47 -0
- data/lib/xamplr/test-support/bench-cache.rb +80 -0
- data/lib/xamplr/test-support/bench-script.rb +21 -0
- data/lib/xamplr/test-support/bench.rb +116 -0
- data/lib/xamplr/test-support/bench2.rb +132 -0
- data/lib/xamplr/test-support/test-cache.rb +147 -0
- data/lib/xamplr/test-support/test-data/binding.xml +7 -0
- data/lib/xamplr/test-support/test-data/example.xml +14 -0
- data/lib/xamplr/test-support/test-data/internationalization-utf8.txt +1 -0
- data/lib/xamplr/test-support/test-data/labels.xml +37 -0
- data/lib/xamplr/test-support/test-data/labels001.xml +38 -0
- data/lib/xamplr/test-support/test-deep-change.rb +135 -0
- data/lib/xamplr/test-support/test-elements.rb +109 -0
- data/lib/xamplr/test-support/test-indexed-array.rb +169 -0
- data/lib/xamplr/test-support/test-misc.rb +73 -0
- data/lib/xamplr/test-support/test-names.rb +67 -0
- data/lib/xamplr/test-support/test-rollback.rb +106 -0
- data/lib/xamplr/test-support/test.rb +1504 -0
- data/lib/xamplr/to-ruby.rb +220 -0
- data/lib/xamplr/to-xml.rb +158 -0
- data/lib/xamplr/version.rb +67 -0
- data/lib/xamplr/visitor.rb +140 -0
- data/lib/xamplr/visitors.rb +573 -0
- data/lib/xamplr/xampl-generator.rb +533 -0
- data/lib/xamplr/xampl-hand-generated.rb +1535 -0
- data/lib/xamplr/xampl-module.rb +36 -0
- data/lib/xamplr/xampl-object-internals.rb +6 -0
- data/lib/xamplr/xampl-object.rb +202 -0
- data/lib/xamplr/xampl-persisted-object.rb +122 -0
- data/lib/xamplr/xml-text.rb +117 -0
- data/lib/xamplr/xml/document.xml +7 -0
- data/lib/xamplr/xml/elements.xml +101 -0
- data/lib/xamplr/xml/elements000.xml +73 -0
- data/lib/xamplr/xml/example.xml +23 -0
- data/lib/xamplr/xml/options.xml +12 -0
- data/lib/xamplr/xml/uche.xml +38 -0
- data/lib/xamplr/yEd-sample.graphml +300 -0
- data/test/test_helper.rb +10 -0
- data/test/xamplr_test.rb +7 -0
- metadata +245 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
module Xampl
|
|
4
|
+
module XamplObject
|
|
5
|
+
|
|
6
|
+
# add text (while loading from XML)
|
|
7
|
+
# xml_text -- the text
|
|
8
|
+
# realising -- true when loading from a persister
|
|
9
|
+
def note_adding_text_content(xml_text, realising)
|
|
10
|
+
return xml_text
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# these are the arrays of attribute information about to be used to
|
|
14
|
+
# initialise the attributes
|
|
15
|
+
|
|
16
|
+
def note_initialise_attributes_with(names, namespaces, values, realising)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# attributes are setup up (while loading from XML)
|
|
20
|
+
|
|
21
|
+
def note_attributes_initialised(realising)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# just created
|
|
25
|
+
|
|
26
|
+
def note_created(realising)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# about to be added to a parent
|
|
30
|
+
|
|
31
|
+
def note_add_to_parent(parent, realising)
|
|
32
|
+
return self
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# about to be added to a parent
|
|
36
|
+
|
|
37
|
+
def note_add_child(child, realising)
|
|
38
|
+
return child
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# this element has been completed
|
|
42
|
+
|
|
43
|
+
def note_closed(realising)
|
|
44
|
+
return self
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# replacing the original
|
|
48
|
+
|
|
49
|
+
def note_replacing(original)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# about to be invalidated
|
|
53
|
+
|
|
54
|
+
def note_invalidate
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
module Xampl
|
|
2
|
+
|
|
3
|
+
require "fileutils"
|
|
4
|
+
require "fsdb"
|
|
5
|
+
require "xamplr/persister/caching"
|
|
6
|
+
|
|
7
|
+
class FSDBPersister < AbstractCachingPersister
|
|
8
|
+
|
|
9
|
+
def initialize(name=nil, format=nil, root=File.join(".", "repo-fsdb"))
|
|
10
|
+
super(root, name, format)
|
|
11
|
+
|
|
12
|
+
@db = FSDB::Database[@root_dir]
|
|
13
|
+
@db_lock = "lock"
|
|
14
|
+
@db[@db_lock] = @db_lock
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def FSDBPersister.kind
|
|
18
|
+
:fsdb
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def kind
|
|
22
|
+
FSDBPersister.kind
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def rollback_cleanup
|
|
26
|
+
super
|
|
27
|
+
@db.clear_cache
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def do_sync_write
|
|
31
|
+
@db.edit(@db_lock){ | lock |
|
|
32
|
+
@changed.each { | xampl, ignore | write(xampl) }
|
|
33
|
+
}
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def place_name(klass, id, type=".txt")
|
|
37
|
+
place = File.join(klass.name.split("::"), "#{id}#{type}")
|
|
38
|
+
return place
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def write(xampl)
|
|
42
|
+
raise XamplException.new(:no_index_so_no_persist) unless xampl.get_the_index
|
|
43
|
+
#return false unless xampl.get_the_index
|
|
44
|
+
|
|
45
|
+
place = place_name(xampl.class, xampl.get_the_index)
|
|
46
|
+
@db[place] = represent(xampl)
|
|
47
|
+
|
|
48
|
+
@write_count = @write_count + 1
|
|
49
|
+
xampl.changes_accepted
|
|
50
|
+
return true
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def read_representation(klass, pid)
|
|
54
|
+
place = place_name(klass, pid)
|
|
55
|
+
representation = @db.edit(@db_lock){ | lock | @db[place] }
|
|
56
|
+
return representation
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
Xampl.register_persister_kind(FSDBPersister)
|
|
61
|
+
end
|
|
62
|
+
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
require 'libxml'
|
|
2
|
+
|
|
3
|
+
module Xampl
|
|
4
|
+
|
|
5
|
+
class PersistXML < Visitor
|
|
6
|
+
attr_accessor :ns_to_prefix, :start_body, :body, :out, :mentions
|
|
7
|
+
|
|
8
|
+
def initialize(out="", mentions=nil)
|
|
9
|
+
super()
|
|
10
|
+
|
|
11
|
+
@out = out
|
|
12
|
+
@was_attr = false
|
|
13
|
+
|
|
14
|
+
@mentions = mentions
|
|
15
|
+
|
|
16
|
+
@ns_to_prefix = {}
|
|
17
|
+
@start_body = nil
|
|
18
|
+
@body = ""
|
|
19
|
+
@attr_list = nil
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def cycle(xampl)
|
|
23
|
+
raise XamplException.new(:cycle_detected_in_xampl_cluster) unless xampl.kind_of?(XamplPersistedObject)
|
|
24
|
+
return true
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def revisit(xampl)
|
|
28
|
+
return true
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def register_ns(ns)
|
|
32
|
+
if (0 == ns.length) then
|
|
33
|
+
return ""
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
prefix = ns_to_prefix[ns]
|
|
37
|
+
if (nil == prefix) then
|
|
38
|
+
preferred = XamplObject.lookup_preferred_ns_prefix(ns)
|
|
39
|
+
prefix = "" << preferred << ":" if preferred
|
|
40
|
+
prefix = "ns" << ns_to_prefix.size.to_s << ":" unless prefix
|
|
41
|
+
ns_to_prefix[ns] = prefix
|
|
42
|
+
end
|
|
43
|
+
return prefix
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def attr_esc(s)
|
|
47
|
+
unless defined?(@@doc) then
|
|
48
|
+
@@doc = LibXML::XML::Document.new()
|
|
49
|
+
@@doc.root = LibXML::XML::Node.new('r')
|
|
50
|
+
@@attr = LibXML::XML::Attr.new(@@doc.root, 'v', 'v')
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
@@attr.value = s.to_s
|
|
54
|
+
(@@doc.root.to_s)[6..-4]
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
=begin
|
|
59
|
+
|
|
60
|
+
def attr_esc_old(s)
|
|
61
|
+
if (s.kind_of? XamplObject)
|
|
62
|
+
return attr_esc(s.to_xml)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# stupid_test()
|
|
66
|
+
|
|
67
|
+
result = s.to_s.dup
|
|
68
|
+
|
|
69
|
+
result.gsub!("&", "&")
|
|
70
|
+
result.gsub!("<", "<")
|
|
71
|
+
result.gsub!(">", ">")
|
|
72
|
+
result.gsub!("'", "'")
|
|
73
|
+
result.gsub!("\"", """)
|
|
74
|
+
|
|
75
|
+
return result
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
=end
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
# def content_esc(s)
|
|
82
|
+
# #NO! the attribute has the right to compact white space
|
|
83
|
+
# unless defined?(@@doc) then
|
|
84
|
+
# @@doc = LibXML::XML::Document.new()
|
|
85
|
+
# @@doc.root = LibXML::XML::Node.new('r')
|
|
86
|
+
# @@attr = LibXML::XML::Attr.new(@@doc.root, 'v', 'v')
|
|
87
|
+
# end
|
|
88
|
+
#
|
|
89
|
+
# @@attr.value = s
|
|
90
|
+
# (@@doc.root.to_s)[6..-4]
|
|
91
|
+
# end
|
|
92
|
+
|
|
93
|
+
#TODO -- use libxml for this too
|
|
94
|
+
def content_esc(s)
|
|
95
|
+
result = s.to_s.dup
|
|
96
|
+
|
|
97
|
+
return result if (s.kind_of? XamplObject)
|
|
98
|
+
|
|
99
|
+
result.gsub!("&", "&")
|
|
100
|
+
result.gsub!("<", "<")
|
|
101
|
+
|
|
102
|
+
return result
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def attribute(xampl)
|
|
106
|
+
@attr_list = []
|
|
107
|
+
if (nil != xampl.attributes) then
|
|
108
|
+
xampl.attributes.each do |attr_spec|
|
|
109
|
+
prefix = (2 < attr_spec.length) ? register_ns(attr_spec[2]) : ""
|
|
110
|
+
value = xampl.instance_variable_get(attr_spec[0])
|
|
111
|
+
# @attr_list << (" " << prefix << attr_spec[1] << "='" << attr_esc(value) << "'") unless nil == value
|
|
112
|
+
@attr_list << (" " << prefix << attr_spec[1] << '="' << attr_esc(value) << '"') unless nil == value
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def persist_attribute(xampl)
|
|
118
|
+
@attr_list = []
|
|
119
|
+
pattr = xampl.indexed_by.to_s
|
|
120
|
+
if (nil != xampl.attributes) then
|
|
121
|
+
xampl.attributes.each do |attr_spec|
|
|
122
|
+
if pattr == attr_spec[1] then
|
|
123
|
+
prefix = (2 < attr_spec.length) ? register_ns(attr_spec[2]) : ""
|
|
124
|
+
value = xampl.instance_variable_get(attr_spec[0])
|
|
125
|
+
# @attr_list << (" " << prefix << attr_spec[1] << "='" << attr_esc(value) << "'") unless nil == value
|
|
126
|
+
@attr_list << (" " << prefix << attr_spec[1] << '="' << attr_esc(value) << '"') unless nil == value
|
|
127
|
+
break
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def show_attributes
|
|
134
|
+
result = @attr_list.join(" ")
|
|
135
|
+
if (0 == result.length) then
|
|
136
|
+
return ""
|
|
137
|
+
else
|
|
138
|
+
return result
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def start_element(xampl)
|
|
143
|
+
tag = xampl.tag
|
|
144
|
+
ns = xampl.ns
|
|
145
|
+
tag_info = "" << "<" << register_ns(ns) << tag
|
|
146
|
+
unless @start_body then
|
|
147
|
+
attribute(xampl)
|
|
148
|
+
attr_defn = show_attributes
|
|
149
|
+
@start_body = "" << tag_info << attr_defn
|
|
150
|
+
@was_attr = true if 0 < attr_defn.size
|
|
151
|
+
else
|
|
152
|
+
if xampl.persist_required then
|
|
153
|
+
@mentions << xampl if @mentions
|
|
154
|
+
@no_children = true
|
|
155
|
+
persist_attribute(xampl)
|
|
156
|
+
else
|
|
157
|
+
attribute(xampl)
|
|
158
|
+
end
|
|
159
|
+
@body << tag_info << show_attributes
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def end_element(xampl)
|
|
164
|
+
tag = xampl.tag
|
|
165
|
+
ns = xampl.ns
|
|
166
|
+
@body << "</" << register_ns(ns) << tag << ">"
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def define_ns
|
|
170
|
+
result = ""
|
|
171
|
+
ns_to_prefix.each do |ns, prefix|
|
|
172
|
+
# result = sprintf("%s xmlns:%s='%s'", result, prefix[0..-2], ns)
|
|
173
|
+
result = sprintf("%s xmlns:%s=\"%s\"", result, prefix[0..-2], ns)
|
|
174
|
+
end
|
|
175
|
+
return result
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def done
|
|
179
|
+
out << @start_body << define_ns << @body
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def before_visit_without_content(xampl)
|
|
183
|
+
start_element(xampl)
|
|
184
|
+
@body << "/>"
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def before_visit_simple_content(xampl)
|
|
188
|
+
start_element(xampl)
|
|
189
|
+
if @no_children then
|
|
190
|
+
@body << "/>"
|
|
191
|
+
else
|
|
192
|
+
@body << ">"
|
|
193
|
+
@body << content_esc(xampl._content) if xampl._content
|
|
194
|
+
end_element(xampl)
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def before_visit_data_content(xampl)
|
|
199
|
+
start_element(xampl)
|
|
200
|
+
if @no_children then
|
|
201
|
+
@body << "/>"
|
|
202
|
+
else
|
|
203
|
+
@body << ">"
|
|
204
|
+
@body << content_esc(xampl._content) if xampl._content
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def after_visit_data_content(xampl)
|
|
209
|
+
end_element(xampl) unless @no_children
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def before_visit_mixed_content(xampl)
|
|
213
|
+
if @no_children then
|
|
214
|
+
@body << "/>"
|
|
215
|
+
else
|
|
216
|
+
start_element(xampl)
|
|
217
|
+
@body << ">"
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def after_visit_mixed_content(xampl)
|
|
222
|
+
end_element(xampl) unless @no_children
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def before_visit(xampl)
|
|
226
|
+
if xampl.respond_to? "before_visit_by_element_kind" then
|
|
227
|
+
xampl.before_visit_by_element_kind(self)
|
|
228
|
+
else
|
|
229
|
+
@body << xampl.to_s
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def after_visit(xampl)
|
|
234
|
+
xampl.after_visit_by_element_kind(self) if xampl.respond_to? "after_visit_by_element_kind"
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def visit_string(string)
|
|
238
|
+
@body << string
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
module XamplObject
|
|
243
|
+
def to_xml(out="", skip=[])
|
|
244
|
+
PersistXML.new(out).start(self).done
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
end
|
|
249
|
+
|
|
@@ -0,0 +1,522 @@
|
|
|
1
|
+
|
|
2
|
+
require 'sync'
|
|
3
|
+
|
|
4
|
+
module Xampl
|
|
5
|
+
|
|
6
|
+
@@persister = nil
|
|
7
|
+
@@known_persisters = {}
|
|
8
|
+
@@persister_kinds = {}
|
|
9
|
+
|
|
10
|
+
def Xampl.persister
|
|
11
|
+
@@persister
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def Xampl.block_future_changes(on=true)
|
|
15
|
+
if (@@persister) then
|
|
16
|
+
@@persister.block_changes = on
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def Xampl.auto_persistence(on=true)
|
|
21
|
+
if (@@persister) then
|
|
22
|
+
@@persister.automatic = on
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def Xampl.register_persister_kind(klass)
|
|
27
|
+
@@persister_kinds[klass.kind] = klass
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def Xampl.disable_all_persisters
|
|
31
|
+
@@persister = nil
|
|
32
|
+
@@known_persisters.each { | persister | persister.close}
|
|
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
|
+
kind = kind || @@default_persister_kind
|
|
61
|
+
format = format || @@default_persister_format
|
|
62
|
+
@@persister = @@known_persisters[name]
|
|
63
|
+
|
|
64
|
+
if @@persister then
|
|
65
|
+
# @@persister.open # this won't work
|
|
66
|
+
# TODO -- if we know the persister, why are we being so anal about kind and format???
|
|
67
|
+
|
|
68
|
+
kind = @@persister.kind || kind
|
|
69
|
+
format = @@persister.format || format
|
|
70
|
+
|
|
71
|
+
#raise XamplException.new(:live_across_rollback) if @@persister.rolled_back
|
|
72
|
+
if kind and kind != @@persister.kind then
|
|
73
|
+
raise IncompatiblePersisterRequest.new(@@persister, "kind", kind, @@persister.kind)
|
|
74
|
+
end
|
|
75
|
+
if format and format != @@persister.format then
|
|
76
|
+
raise IncompatiblePersisterRequest.new(@@persister, "format", format, @@persister.format)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
unless @@persister then
|
|
81
|
+
# puts "CREATE PERSISTER #{name}, format: #{format}, kind: #{kind}"
|
|
82
|
+
@@persister = @@persister_kinds[kind].new(name, format)
|
|
83
|
+
if (nil != name) then
|
|
84
|
+
@@known_persisters[name] = @@persister
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
@@persister
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def Xampl.print_known_persisters
|
|
92
|
+
puts "Known Persisters:: --------------------------"
|
|
93
|
+
@@known_persisters.each { | n, k | puts " #{n} #{k}" }
|
|
94
|
+
puts "---------------------------------------------"
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def Xampl.flush_persister_caches
|
|
98
|
+
Xampl.print_known_persisters
|
|
99
|
+
@persister.close
|
|
100
|
+
@@known_persisters.delete(@@persister.name)
|
|
101
|
+
Xampl.print_known_persisters
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def Xampl.drop_all_persisters(verbose=false)
|
|
105
|
+
puts "Drop All Persisters:: --------------------------" if verbose
|
|
106
|
+
@@known_persisters.each do |name, persister|
|
|
107
|
+
puts " #{ name } #{ persister.class.name }" if verbose
|
|
108
|
+
next if persister == @@persister
|
|
109
|
+
persister.close
|
|
110
|
+
persister.clear_cache
|
|
111
|
+
end
|
|
112
|
+
puts "---------------------------------------------" if verbose
|
|
113
|
+
GC.start
|
|
114
|
+
GC.start
|
|
115
|
+
GC.start
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def Xampl.drop_persister(name)
|
|
119
|
+
Xampl.print_known_persisters
|
|
120
|
+
p = @@known_persisters[name]
|
|
121
|
+
p.close if p
|
|
122
|
+
@@known_persisters.delete(name)
|
|
123
|
+
Xampl.print_known_persisters
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
@@xampl_lock = Sync.new
|
|
127
|
+
|
|
128
|
+
@@verbose_transactions = true
|
|
129
|
+
def Xampl.verboseTransactions(v)
|
|
130
|
+
@@verbose_transactions = v
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def Xampl.transaction(thing, kind=nil, automatic=true, format=nil, &block)
|
|
134
|
+
if String === thing then
|
|
135
|
+
name = thing
|
|
136
|
+
elsif XamplObject === thing then
|
|
137
|
+
name = thing.persister.name
|
|
138
|
+
else
|
|
139
|
+
raise XamplException.new("can't base a transaction on a #{thing.class.name} (#{thing})")
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
if block_given? then
|
|
143
|
+
@@xampl_lock.synchronize(:EX) do
|
|
144
|
+
initial_persister = @@persister
|
|
145
|
+
Xampl.enable_persister(name, kind, format)
|
|
146
|
+
|
|
147
|
+
rollback = true
|
|
148
|
+
exception = nil
|
|
149
|
+
original_automatic = @@persister.automatic
|
|
150
|
+
|
|
151
|
+
begin
|
|
152
|
+
#TODO -- impose some rules on nested transactions/enable_persisters??
|
|
153
|
+
|
|
154
|
+
Xampl.auto_persistence(automatic)
|
|
155
|
+
result = yield
|
|
156
|
+
Xampl.block_future_changes(true)
|
|
157
|
+
Xampl.sync
|
|
158
|
+
rollback = false
|
|
159
|
+
return result
|
|
160
|
+
rescue => e
|
|
161
|
+
exception = e
|
|
162
|
+
ensure
|
|
163
|
+
Xampl.block_future_changes(false)
|
|
164
|
+
Xampl.auto_persistence(original_automatic)
|
|
165
|
+
if rollback then
|
|
166
|
+
if exception then
|
|
167
|
+
puts "ROLLBACK(#{__LINE__}):: #{exception}" if rollback and @@verbose_transactions
|
|
168
|
+
#print exception.backtrace.join("\n") if rollback
|
|
169
|
+
raise exception
|
|
170
|
+
else
|
|
171
|
+
if @@verbose_transactions and rollback then
|
|
172
|
+
puts "ROLLBACK(#{__LINE__}):: UNKNOWN CAUSE" if rollback
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
Xampl.rollback if rollback
|
|
177
|
+
@@persister = initial_persister
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def Xampl.read_only_transaction(thing, kind=nil, automatic=true, format=nil, &block)
|
|
184
|
+
if String === thing then
|
|
185
|
+
name = thing
|
|
186
|
+
elsif XamplObject === thing then
|
|
187
|
+
name = thing.persister.name
|
|
188
|
+
else
|
|
189
|
+
raise XamplException.new("can't base a transaction on a #{thing.class.name} (#{thing})")
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
target_persister = nil
|
|
193
|
+
if block_given? then
|
|
194
|
+
@@xampl_lock.synchronize(:EX) do
|
|
195
|
+
initial_persister = @@persister
|
|
196
|
+
Xampl.enable_persister(name, kind, format)
|
|
197
|
+
target_persister = @@persister
|
|
198
|
+
|
|
199
|
+
rollback = true
|
|
200
|
+
original_automatic = @@persister.automatic
|
|
201
|
+
@changed ||= nil
|
|
202
|
+
original_changed = @changed
|
|
203
|
+
@changed = {}
|
|
204
|
+
begin
|
|
205
|
+
Xampl.auto_persistence(false)
|
|
206
|
+
#Xampl.block_future_changes(true)
|
|
207
|
+
|
|
208
|
+
yield
|
|
209
|
+
rollback = false
|
|
210
|
+
rescue => e
|
|
211
|
+
exception = e
|
|
212
|
+
ensure
|
|
213
|
+
Xampl.auto_persistence(original_automatic)
|
|
214
|
+
#Xampl.block_future_changes(false)
|
|
215
|
+
|
|
216
|
+
if 0 == @changed.size then
|
|
217
|
+
@changed = original_changed
|
|
218
|
+
|
|
219
|
+
if rollback then
|
|
220
|
+
puts "ROLLBACK(#{__LINE__}):: #{exception}"
|
|
221
|
+
print exception.backtrace.join("\n")
|
|
222
|
+
Xampl.rollback
|
|
223
|
+
end
|
|
224
|
+
@@persister = initial_persister
|
|
225
|
+
else
|
|
226
|
+
puts "CHANGED COUNT: #{@changed.size}"
|
|
227
|
+
@changed = original_changed
|
|
228
|
+
|
|
229
|
+
puts "ROLLBACK(#{__LINE__}) #{exception}" if rollback
|
|
230
|
+
print exception.backtrace.join("\n")
|
|
231
|
+
Xampl.rollback
|
|
232
|
+
|
|
233
|
+
@@persister = initial_persister
|
|
234
|
+
|
|
235
|
+
raise BlockedChange.new(target_persister)
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
def Xampl.read_only(target_persister)
|
|
243
|
+
#TODO -- EXCLUSIVE ACCESS TO THE PERSISTER!!!
|
|
244
|
+
name = target_persister.name
|
|
245
|
+
|
|
246
|
+
if block_given? then
|
|
247
|
+
initial_persister = @@persister
|
|
248
|
+
Xampl.enable_persister(name, target_persister.kind, target_persister.format)
|
|
249
|
+
|
|
250
|
+
rollback = true
|
|
251
|
+
original_automatic = @@persister.automatic
|
|
252
|
+
original_changed = @changed
|
|
253
|
+
@changed = {}
|
|
254
|
+
begin
|
|
255
|
+
Xampl.auto_persistence(false)
|
|
256
|
+
#Xampl.block_future_changes(true)
|
|
257
|
+
|
|
258
|
+
yield
|
|
259
|
+
rollback = false
|
|
260
|
+
ensure
|
|
261
|
+
#### Xampl.auto_persistence(original_automatic)
|
|
262
|
+
#### #Xampl.block_future_changes(false)
|
|
263
|
+
####
|
|
264
|
+
#### if 0 < @changed.size then
|
|
265
|
+
#### puts "CHANGED COUNT: #{@changed.size}"
|
|
266
|
+
#### raise BlockedChange.new(target_persister)
|
|
267
|
+
#### end
|
|
268
|
+
####
|
|
269
|
+
#### @changed = original_changed
|
|
270
|
+
####
|
|
271
|
+
#### puts "ROLLBACK(#{__LINE__})" if rollback
|
|
272
|
+
#### Xampl.rollback if rollback
|
|
273
|
+
#### @@persister = initial_persister
|
|
274
|
+
|
|
275
|
+
Xampl.auto_persistence(original_automatic)
|
|
276
|
+
#Xampl.block_future_changes(false)
|
|
277
|
+
|
|
278
|
+
if 0 == @changed.size then
|
|
279
|
+
@changed = original_changed
|
|
280
|
+
|
|
281
|
+
puts "ROLLBACK(#{__LINE__})" if rollback
|
|
282
|
+
Xampl.rollback if rollback
|
|
283
|
+
@@persister = initial_persister
|
|
284
|
+
else
|
|
285
|
+
puts "CHANGED COUNT: #{@changed.size}"
|
|
286
|
+
@changed = original_changed
|
|
287
|
+
|
|
288
|
+
puts "ROLLBACK(#{__LINE__})" if rollback
|
|
289
|
+
Xampl.rollback
|
|
290
|
+
|
|
291
|
+
@@persister = initial_persister
|
|
292
|
+
|
|
293
|
+
raise BlockedChange.new(target_persister)
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
def Xampl.introduce_to_persister(xampl)
|
|
300
|
+
raise NoActivePersister unless @@persister
|
|
301
|
+
|
|
302
|
+
@@persister.introduce(xampl)
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
def Xampl.count_changed
|
|
306
|
+
@@persister.count_changed if @@persister
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
def Xampl.print_stats
|
|
310
|
+
@@persister.print_stats if @@persister
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
def Xampl.auto_cache(xampl)
|
|
314
|
+
if (nil == xampl.persister) and @@persister and @@persister.automatic then
|
|
315
|
+
xampl.persister = @@persister
|
|
316
|
+
end
|
|
317
|
+
if xampl.persister and xampl.persister.automatic then
|
|
318
|
+
xampl.persister.cache(xampl)
|
|
319
|
+
end
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
def Xampl.auto_uncache(xampl)
|
|
323
|
+
if xampl.persister and xampl.persister.automatic then
|
|
324
|
+
xampl.persister.uncache(xampl)
|
|
325
|
+
end
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
def Xampl.clear_cache
|
|
329
|
+
raise NoActivePersister unless @@persister
|
|
330
|
+
@@persister.clear_cache
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
def Xampl.sync
|
|
334
|
+
#raise XamplException.new(:live_across_rollback) if @@persister.rolled_back
|
|
335
|
+
raise NoActivePersister unless @@persister
|
|
336
|
+
@@persister.sync
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
def Xampl.version(stream)
|
|
340
|
+
@@persister.version(stream) if nil != @@persister
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
def Xampl.sync_all
|
|
344
|
+
@@known_persisters.each{ | name, persister | persister.sync }
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
def Xampl.close_all_persisters
|
|
348
|
+
@@known_persisters.each do | name, persister |
|
|
349
|
+
persister.close
|
|
350
|
+
end
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
def Xampl.rollback(persister=@@persister)
|
|
354
|
+
raise NoActivePersister unless @@persister
|
|
355
|
+
persister.rollback_cleanup
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
def Xampl.rollback_all
|
|
359
|
+
@@known_persisters.values.each { | persister | persister.rollback }
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
def Xampl.lazy_load(xampl)
|
|
363
|
+
raise NoActivePersister.new unless @@persister
|
|
364
|
+
|
|
365
|
+
pid = xampl.get_the_index
|
|
366
|
+
if xampl and pid then
|
|
367
|
+
@@persister.lazy_load(xampl, xampl.class, pid)
|
|
368
|
+
xampl.load_needed = false
|
|
369
|
+
else
|
|
370
|
+
raise "XAMPL.LAZY_LOAD -- REFUSED"
|
|
371
|
+
end
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
def Xampl.lookup(klass, pid)
|
|
375
|
+
raise NoActivePersister unless @@persister
|
|
376
|
+
@@persister.lookup(klass, pid)
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
def Xampl.find_known(klass, pid)
|
|
380
|
+
raise NoActivePersister unless @@persister
|
|
381
|
+
xampl, ignore = @@persister.find_known(klass, pid)
|
|
382
|
+
return xampl
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
def Xampl.write_to_cache(xampl)
|
|
386
|
+
@@persister.write_to_cache(xampl)
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
def Xampl.cache(xampl)
|
|
390
|
+
@@persister.cache(xampl)
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
def Xampl.lookup_in_map(map, klass, pid)
|
|
394
|
+
return nil if nil == pid
|
|
395
|
+
|
|
396
|
+
module_name = klass.module_name
|
|
397
|
+
tag = klass.tag
|
|
398
|
+
|
|
399
|
+
tag_map = map[module_name]
|
|
400
|
+
return nil if nil == tag_map
|
|
401
|
+
|
|
402
|
+
pid_map = tag_map[tag]
|
|
403
|
+
return nil if nil == pid_map
|
|
404
|
+
|
|
405
|
+
return pid_map[pid]
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
def Xampl.store_in_map(map, xampl)
|
|
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 = {}
|
|
432
|
+
tag_map[tag] = pid_map
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
pid_map[pid] = data
|
|
436
|
+
|
|
437
|
+
return true
|
|
438
|
+
end
|
|
439
|
+
|
|
440
|
+
def Xampl.store_in_cache(map, xampl, container)
|
|
441
|
+
module_name = xampl.module_name
|
|
442
|
+
tag = xampl.tag
|
|
443
|
+
pid = xampl.get_the_index
|
|
444
|
+
|
|
445
|
+
if nil == pid then
|
|
446
|
+
return false
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
if block_given? then
|
|
450
|
+
data = yield
|
|
451
|
+
else
|
|
452
|
+
data = xampl
|
|
453
|
+
end
|
|
454
|
+
|
|
455
|
+
tag_map = map[module_name]
|
|
456
|
+
if nil == tag_map then
|
|
457
|
+
tag_map = {}
|
|
458
|
+
map[module_name] = tag_map
|
|
459
|
+
end
|
|
460
|
+
|
|
461
|
+
pid_map = tag_map[tag]
|
|
462
|
+
if nil == pid_map then
|
|
463
|
+
pid_map = container.fresh_cache
|
|
464
|
+
tag_map[tag] = pid_map
|
|
465
|
+
end
|
|
466
|
+
|
|
467
|
+
pid_map[pid] = data
|
|
468
|
+
|
|
469
|
+
return true
|
|
470
|
+
end
|
|
471
|
+
|
|
472
|
+
def Xampl.remove_from_map(map, xampl)
|
|
473
|
+
pid = xampl.get_the_index
|
|
474
|
+
return nil unless pid
|
|
475
|
+
|
|
476
|
+
tag_map = map[xampl.module_name]
|
|
477
|
+
return nil unless tag_map
|
|
478
|
+
|
|
479
|
+
pid_map = tag_map[xampl.tag]
|
|
480
|
+
return nil unless pid_map
|
|
481
|
+
|
|
482
|
+
return pid_map.delete(pid)
|
|
483
|
+
end
|
|
484
|
+
|
|
485
|
+
def Xampl.optimise(opts={})
|
|
486
|
+
raise NoActivePersister unless @@persister
|
|
487
|
+
|
|
488
|
+
@@persister.optimise(opts)
|
|
489
|
+
end
|
|
490
|
+
|
|
491
|
+
def Xampl.query_implemented
|
|
492
|
+
raise NoActivePersister unless @@persister
|
|
493
|
+
@@persister.query_implemented
|
|
494
|
+
end
|
|
495
|
+
|
|
496
|
+
def Xampl.query(hint=false)
|
|
497
|
+
raise NoActivePersister unless @@persister
|
|
498
|
+
@@persister.query(hint) { | q | yield q }
|
|
499
|
+
end
|
|
500
|
+
|
|
501
|
+
def Xampl.find_xampl(hint=false)
|
|
502
|
+
raise NoActivePersister unless @@persister
|
|
503
|
+
@@persister.find_xampl(hint) { | q | yield q }
|
|
504
|
+
end
|
|
505
|
+
|
|
506
|
+
def Xampl.find_meta(hint=false)
|
|
507
|
+
raise NoActivePersister unless @@persister
|
|
508
|
+
@@persister.find_meta(hint) { | q | yield q }
|
|
509
|
+
end
|
|
510
|
+
|
|
511
|
+
def Xampl.find_pids(hint=false)
|
|
512
|
+
raise NoActivePersister unless @@persister
|
|
513
|
+
@@persister.find_pids(hint) { | q | yield q }
|
|
514
|
+
end
|
|
515
|
+
|
|
516
|
+
def Xampl.find_mentions_of(xampl)
|
|
517
|
+
raise NoActivePersister unless @@persister
|
|
518
|
+
@@persister.find_mentions_of(xampl)
|
|
519
|
+
end
|
|
520
|
+
|
|
521
|
+
end
|
|
522
|
+
|