lore 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
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
+