lore 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. data/LICENSE +19 -0
  2. data/README +74 -0
  3. data/aspect.rb +80 -0
  4. data/behaviours/lockable.rb +41 -0
  5. data/behaviours/movable.rb +54 -0
  6. data/behaviours/versioned.rb +24 -0
  7. data/benchmark.rb +193 -0
  8. data/bits.rb +52 -0
  9. data/cache/abstract_entity_cache.rb +82 -0
  10. data/cache/bits.rb +22 -0
  11. data/cache/cacheable.rb +202 -0
  12. data/cache/cached_entities.rb +116 -0
  13. data/cache/file_index.rb +35 -0
  14. data/cache/mmap_entity_cache.rb +67 -0
  15. data/clause.rb +528 -0
  16. data/connection.rb +155 -0
  17. data/custom_functions.sql +14 -0
  18. data/exception/ambiguous_attribute.rb +14 -0
  19. data/exception/cache_exception.rb +30 -0
  20. data/exception/invalid_klass_parameters.rb +63 -0
  21. data/exception/invalid_parameter.rb +42 -0
  22. data/exception/unknown_typecode.rb +19 -0
  23. data/file_index.sql +56 -0
  24. data/gui/erb_template.rb +79 -0
  25. data/gui/erb_template_helpers.rhtml +19 -0
  26. data/gui/form.rb +314 -0
  27. data/gui/form_element.rb +676 -0
  28. data/gui/form_generator.rb +151 -0
  29. data/gui/templates/button.rhtml +2 -0
  30. data/gui/templates/checkbox.rhtml +3 -0
  31. data/gui/templates/checkbox_row.rhtml +1 -0
  32. data/gui/templates/file.rhtml +2 -0
  33. data/gui/templates/file_readonly.rhtml +3 -0
  34. data/gui/templates/form_element.rhtml +5 -0
  35. data/gui/templates/form_element_horizontal.rhtml +3 -0
  36. data/gui/templates/form_element_listed.rhtml +8 -0
  37. data/gui/templates/form_table.rhtml +3 -0
  38. data/gui/templates/form_table_blank.rhtml +3 -0
  39. data/gui/templates/form_table_horizontal.rhtml +8 -0
  40. data/gui/templates/password.rhtml +2 -0
  41. data/gui/templates/password_readonly.rhtml +3 -0
  42. data/gui/templates/radio.rhtml +1 -0
  43. data/gui/templates/radio_row.rhtml +1 -0
  44. data/gui/templates/select.rhtml +23 -0
  45. data/gui/templates/text.rhtml +2 -0
  46. data/gui/templates/text_readonly.rhtml +3 -0
  47. data/gui/templates/textarea.rhtml +3 -0
  48. data/gui/templates/textarea_readonly.rhtml +4 -0
  49. data/lore.gemspec +40 -0
  50. data/lore.rb +94 -0
  51. data/migration.rb +48 -0
  52. data/model.rb +139 -0
  53. data/model_factory.rb +202 -0
  54. data/model_shortcuts.rb +16 -0
  55. data/query_shortcuts.rb +367 -0
  56. data/reserved_methods.txt +3 -0
  57. data/result.rb +100 -0
  58. data/symbol.rb +58 -0
  59. data/table_accessor.rb +1926 -0
  60. data/table_deleter.rb +115 -0
  61. data/table_inserter.rb +168 -0
  62. data/table_instance.rb +384 -0
  63. data/table_selector.rb +314 -0
  64. data/table_updater.rb +155 -0
  65. data/test/README +31 -0
  66. data/test/env.rb +5 -0
  67. data/test/lore_test.log +8218 -0
  68. data/test/model.rb +142 -0
  69. data/test/prepare.rb +37 -0
  70. data/test/tc_aspect.rb +58 -0
  71. data/test/tc_cache.rb +80 -0
  72. data/test/tc_clause.rb +104 -0
  73. data/test/tc_deep_inheritance.rb +49 -0
  74. data/test/tc_factory.rb +57 -0
  75. data/test/tc_filter.rb +37 -0
  76. data/test/tc_form.rb +32 -0
  77. data/test/tc_model.rb +86 -0
  78. data/test/tc_prepare.rb +45 -0
  79. data/test/tc_refined_query.rb +88 -0
  80. data/test/tc_table_accessor.rb +265 -0
  81. data/test/test.log +181 -0
  82. data/test/test_db.sql +400 -0
  83. data/test/ts_lore.rb +49 -0
  84. data/types.rb +55 -0
  85. data/validation/message.rb +60 -0
  86. data/validation/parameter_validator.rb +104 -0
  87. data/validation/reason.rb +54 -0
  88. data/validation/type_validator.rb +91 -0
  89. data/validation.rb +65 -0
  90. metadata +170 -0
@@ -0,0 +1,202 @@
1
+
2
+ require('pstore')
3
+
4
+ require('lore/cache/bits')
5
+ require('lore/exception/cache_exception')
6
+
7
+ module Lore
8
+ module Cache
9
+
10
+ module Cacheable
11
+
12
+ @@cache_control = Hash.new
13
+ @@cache_on_pkeys = Hash.new
14
+ @@distinctive_params = Hash.new
15
+ @@cache_entities = false
16
+
17
+ @@logger = Lore.logger
18
+
19
+ public
20
+
21
+ def is_cacheable(controller)
22
+ controller = controller.intern unless controller.instance_of? Symbol
23
+ return !@@cache_control[controller].nil? && @@cache_control[controller]
24
+ end
25
+
26
+ # Returns whether a Table_Accessor state
27
+ # is cached or not.
28
+ def is_cached(controller, mode, keys)
29
+
30
+ store_filename = Lore::Cache::store_name(self.name.to_s, controller, mode, keys)
31
+ if store_filename.nil? then
32
+ excep_mesg = 'Cannot resolve store filename for ['+self.name.to_s+'|'+controller+'|'+mode+']'
33
+ excep_mesg += ' Keys: '+keys.to_s
34
+ raise ::Exception.new(excep_mesg)
35
+ end
36
+
37
+ if FileTest.exist?(store_filename) then
38
+ true
39
+ else
40
+ false
41
+ end
42
+
43
+ end
44
+
45
+ protected
46
+
47
+ def cache(controller, additional_params=nil)
48
+ controller = controller.intern unless controller.instance_of? Symbol
49
+ @@cache_control[controller] = true
50
+ if !additional_params.nil? then
51
+ @@distinctive_params[controller] = Array.new unless !@@distinctive_params[controller].nil?
52
+ @@distinctive_params[controller] += additional_params
53
+ end
54
+
55
+ end
56
+
57
+ def cache_select_entities
58
+ @@cache_entities = true
59
+ end
60
+
61
+ def cache_entities
62
+ @@cache_entities
63
+ end
64
+
65
+ def cache_on_pkeys(controller, additional_params=nil)
66
+ @@logger.log('Caching depending from pkeys only, controller: ' << controller.to_s << ', params: ' << additional_params.to_s)
67
+ cache(controller, additional_params)
68
+ @@cache_on_pkeys[controller] = true
69
+ end
70
+
71
+ def cache_pkeys_only?(controller)
72
+ !@@cache_on_pkeys[controller].nil? && @@cache_on_pkeys[controller]
73
+ end
74
+
75
+ def nocache(controller)
76
+ controller = controller.intern unless controller.instance_of? Symbol
77
+ @@cache_control[controller] = false
78
+ end
79
+
80
+ public
81
+
82
+ def cache_params(controller)
83
+ return @@distinctive_params[controller] unless @@distinctive_params[controller].nil?
84
+ return Hash.new
85
+ end
86
+
87
+ def create_cache(controller, mode, keys, output)
88
+
89
+ @@logger.log('cache_on_pkeys: '+@@cache_on_pkeys.inspect)
90
+ if !@@cache_on_pkeys[controller.intern].nil? &&
91
+ @@cache_on_pkeys[controller.intern]
92
+ then
93
+ keys = filter_pkeys(self, controller, keys)
94
+ @@logger.log('Filtered keys: '+keys.inspect)
95
+ end
96
+
97
+ if !@@cache_control[controller.intern].nil? &&
98
+ @@cache_control[controller.intern]
99
+ then
100
+
101
+ if !@@cache_control[:self].nil? &&
102
+ @@cache_control[:self]
103
+ then
104
+ class_copy = self
105
+ end
106
+
107
+ if is_cached(controller, mode, keys) then
108
+ return
109
+ end
110
+
111
+ store = create_store(controller, mode, keys, output)
112
+ store.transaction do
113
+ store['klass'] = class_copy unless class_copy.nil?
114
+ store['controller'] = controller
115
+ store['mode'] = mode
116
+ store['keys'] = keys
117
+ store['output'] = output
118
+ end
119
+
120
+ else
121
+ raise Cache_Write_Exception.new(self.name.to_s, controller, mode, keys)
122
+ end
123
+
124
+ end
125
+
126
+ public
127
+
128
+ def create_cache!(controller, mode, keys, output)
129
+ invalidate(controller, mode, keys)
130
+ create_cache(controller, mode, keys)
131
+ end
132
+
133
+ public
134
+
135
+ def read_cache(controller, mode, keys)
136
+
137
+ if !@@cache_control[controller.intern].nil? &&
138
+ @@cache_control[controller.intern] &&
139
+ is_cached(controller, mode, keys)
140
+ then
141
+
142
+ output = ''
143
+ store = create_store(controller, mode, keys, output)
144
+ store.transaction do
145
+ output = store['output']
146
+ end
147
+
148
+ return output
149
+
150
+ else
151
+ raise Cache_Read_Exception.new(self.name.to_s, controller, mode, keys)
152
+ end
153
+
154
+ end
155
+
156
+ def invalidate(controller, mode, keys)
157
+ File.unlink(Lore::Cache::store_name(self.name.to_s, controller, mode, keys))
158
+ end
159
+ def invalidate_all(controller=:all, mode=:all, keys=:all)
160
+ cwd = Dir.getwd
161
+ Dir.chdir('/tmp/')
162
+ if keys == :all then keys = Hash.new end
163
+ invalid_cache_pattern = Lore::Cache::store_name(self.name.to_s, controller, mode, keys)
164
+ @@logger.log('Deleting cache for: '+invalid_cache_pattern)
165
+ invalid_cache_files = Dir.glob(invalid_cache_pattern)
166
+ invalid_cache_files.each { |cache_file|
167
+ @@logger.log('Deleting '+cache_file)
168
+ File.delete(cache_file)
169
+ }
170
+ Dir.chdir(cwd)
171
+ end
172
+
173
+ private
174
+
175
+ def create_store(controller, mode, keys, output)
176
+ store_file = Lore::Cache::store_name(self.to_s, controller, mode, keys)
177
+ store = PStore.new(store_file) unless store_file.nil?
178
+ return store
179
+ end
180
+
181
+ def filter_pkeys(model_klass, controller, keys)
182
+ if !model_klass.respond_to? 'key_array' then
183
+ @@logger.log('could not filter for pkeys')
184
+ return keys
185
+ end
186
+ result = Hash.new
187
+ model_klass.key_array.each { |pkey|
188
+ result[pkey] = keys[pkey]
189
+ }
190
+ if !@@distinctive_params[controller].nil? then
191
+ @@distinctive_params[controller].each { |param|
192
+ result[param] = keys[param]
193
+ }
194
+ end
195
+
196
+ return result
197
+ end
198
+
199
+ end
200
+
201
+ end # module
202
+ end # module
@@ -0,0 +1,116 @@
1
+
2
+ require('logger')
3
+
4
+ module Lore
5
+ module Cache
6
+
7
+ class Cached_Entities
8
+
9
+ @@logger = Lore.logger
10
+ @@mmap_cache = Hash.new
11
+ @@file_index = Hash.new
12
+
13
+ public
14
+
15
+ def self.flush(type)
16
+ index = type.table_name
17
+ return if (!Lore.cache_entities() || @@file_index[index].nil?)
18
+ @@file_index[index].each { |cache_file|
19
+ @@logger.debug { 'Clearing cache file ' << cache_file }
20
+ File.unlink(cache_file)
21
+ }
22
+ @@file_index.delete(type.table_name)
23
+ end
24
+
25
+ def self.[]=(query_string, result)
26
+ if $cb__use_pstore_cache then
27
+ create_pstore_cache(query_string, result)
28
+ else
29
+ create_mmap_cache(query_string, result)
30
+ end
31
+ end
32
+
33
+ def self.create(accessor, query_string, result)
34
+ if $cb__use_pstore_cache then
35
+ file = create_pstore_cache(query_string, result)
36
+ else
37
+ file = create_mmap_cache(query_string, result)
38
+ end
39
+ @@file_index[accessor.table_name] = Array.new unless @@file_index[accessor.table_name]
40
+ @@file_index[accessor.table_name] << file
41
+ end
42
+
43
+ def self.[](query_string)
44
+ if $cb__use_pstore_cache then
45
+ return read_pstore_cache(query_string)
46
+ else
47
+ return read_mmap_cache(query_string)
48
+ end
49
+ end
50
+
51
+ def self.include?(query_string)
52
+ FileTest.exist?(storefile_of(query_string))
53
+ end
54
+
55
+ private
56
+
57
+ def self.create_pstore_cache(query_string, result)
58
+ storefile = storefile_of(query_string)
59
+ store = create_store(storefile)
60
+ store.transaction do
61
+ store['dump'] = result
62
+ end
63
+ return storefile
64
+ end
65
+
66
+ def self.read_pstore_cache(query_string)
67
+ store = create_store(storefile_of(query_string))
68
+ result = Array.new
69
+ store.transaction do
70
+ result = store['dump']
71
+ end
72
+ return result
73
+ end
74
+
75
+ def self.create_mmap_cache(query_string, result)
76
+ storefile = storefile_of(query_string)
77
+ store = create_store(storefile)
78
+ store.transaction do
79
+ store['dump'] = result
80
+ end
81
+ @@mmap_cache[index_for(query_string)] = Mmap.new(storefile)
82
+ return storefile
83
+ end
84
+
85
+ def self.read_mmap_cache(query_string)
86
+ @@logger.debug { 'Loading from cache: ' << index_for(query_string) }
87
+ store = @@mmap_cache[index_for(query_string)]
88
+ @@logger.debug { 'STORE: ' << store.inspect }
89
+ return [] unless store
90
+ result = Marshal::load(store)
91
+ return result['dump']
92
+ end
93
+
94
+ def self.delete_mmap_cache(index)
95
+ @@mmap_cache[index].munmap
96
+ end
97
+
98
+ private
99
+
100
+ def self.index_for(query)
101
+ Digest::MD5.hexdigest(query)
102
+ end
103
+
104
+ def self.storefile_of(query)
105
+ '/tmp/cb__cache__entities__' << Digest::MD5.hexdigest(query)
106
+ end
107
+
108
+ def self.create_store(storefile_name)
109
+ store = PStore.new(storefile_name) unless storefile_name.nil?
110
+ return store
111
+ end
112
+
113
+ end
114
+
115
+ end
116
+ end
@@ -0,0 +1,35 @@
1
+
2
+ require 'lore/model'
3
+
4
+ Lore.disable_cache
5
+
6
+ module Lore
7
+ module Cache
8
+
9
+ class File_Index < Lore::Model
10
+ context :lore
11
+ table :file_index, :public
12
+ primary_key :file_index_id, :file_index_id_seq
13
+
14
+ # Return array of cache file names depending
15
+ # from model
16
+ def self.for(table_name)
17
+ select { |i|
18
+ i.where(i.model == table_name)
19
+ }.collect { |index|
20
+ index.file
21
+ }
22
+ end
23
+
24
+ def self.delete_entry(table_name)
25
+ delete { |i|
26
+ i.where(i.model == table_name)
27
+ }
28
+ end
29
+
30
+ end
31
+
32
+ end
33
+ end
34
+
35
+ Lore.enable_cache
@@ -0,0 +1,67 @@
1
+
2
+ require 'lore'
3
+ require 'lore/cache/abstract_entity_cache'
4
+ require 'mmap'
5
+
6
+ module Lore
7
+ module Cache
8
+
9
+
10
+ # Implementation of entity cache using MMapped PStor files.
11
+ # Derived from Abstract_Entity_Cache.
12
+ # Uses Lore::Cache::Cache_Helpers for generating PStor files.
13
+ class Mmap_Entity_Cache < Abstract_Entity_Cache
14
+ extend Cache_Helpers
15
+
16
+ @@logger = Logger.new('/tmp/lore_cache.log')
17
+
18
+
19
+ def self.flush(accessor)
20
+ index = accessor.table_name
21
+ return unless Lore.cache_enabled?
22
+ Dir.glob("/tmp/lore_cache__#{index}*").each { |cache_file|
23
+ @@logger.debug('Clearing cache file ' << cache_file)
24
+ begin
25
+ File.unlink(cache_file)
26
+ rescue ::Exception => excep
27
+ # Another process already killed this file
28
+ end
29
+ }
30
+ end
31
+
32
+ def self.read(accessor, query_string)
33
+ @@logger.debug('Loading from cache: ' << index_for(query_string))
34
+ store = Mmap.new(storefile_of(accessor.table_name, query_string))
35
+ @@logger.debug('STORE: ' << store.inspect)
36
+ return [] unless store
37
+ result = Marshal::load(store)
38
+ return result['dump']
39
+ end
40
+
41
+ def self.create(accessor, query_string, result)
42
+ storefile = create_mmap(accessor, query_string, result)
43
+ end
44
+ def self.create_mmap(accessor, query_string, result)
45
+ storefile = storefile_of(accessor.table_name, query_string)
46
+ store = create_store(storefile)
47
+ store.transaction do
48
+ store['dump'] = result
49
+ end
50
+ @@logger.debug('Creating cache entry for ' << storefile )
51
+ Mmap.new(storefile)
52
+ return storefile
53
+ end
54
+
55
+ def self.include?(accessor, query_string)
56
+ FileTest.exist?(storefile_of(accessor.table_name, query_string))
57
+ end
58
+
59
+ def self.delete(index)
60
+ end
61
+
62
+ end
63
+
64
+ end
65
+ end
66
+
67
+