lore 0.4.8 → 0.9.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest.txt +16 -7
- data/README.rdoc +91 -0
- data/benchmark/benchmark.sql +11 -0
- data/benchmark/results.txt +28 -0
- data/benchmark/select.rb +352 -0
- data/lib/lore.rb +22 -8
- data/lib/lore/adapters/context.rb +64 -0
- data/lib/lore/adapters/postgres-pr.rb +6 -0
- data/lib/lore/adapters/postgres-pr/connection.rb +93 -0
- data/lib/lore/adapters/postgres-pr/result.rb +63 -0
- data/lib/lore/{types.rb → adapters/postgres-pr/types.rb} +36 -0
- data/lib/lore/adapters/postgres.rb +24 -0
- data/lib/lore/adapters/postgres/connection.rb +81 -0
- data/lib/lore/adapters/postgres/result.rb +82 -0
- data/lib/lore/adapters/postgres/types.rb +91 -0
- data/lib/lore/bits.rb +18 -0
- data/lib/lore/cache/abstract_entity_cache.rb +2 -1
- data/lib/lore/cache/cacheable.rb +12 -177
- data/lib/lore/cache/memcache_entity_cache.rb +89 -0
- data/lib/lore/cache/memory_entity_cache.rb +77 -0
- data/lib/lore/cache/mmap_entity_cache.rb +2 -2
- data/lib/lore/cache/mmap_entity_cache_bork.rb +86 -0
- data/lib/lore/clause.rb +107 -35
- data/lib/lore/{exception → exceptions}/ambiguous_attribute.rb +2 -2
- data/lib/lore/{exception → exceptions}/cache_exception.rb +1 -1
- data/lib/lore/exceptions/database_exception.rb +16 -0
- data/lib/lore/{exception/invalid_parameter.rb → exceptions/invalid_field.rb} +7 -4
- data/lib/lore/exceptions/unknown_type.rb +18 -0
- data/lib/lore/exceptions/validation_failure.rb +71 -0
- data/lib/lore/gui/form_generator.rb +109 -60
- data/lib/lore/gui/lore_model_select_field.rb +1 -0
- data/lib/lore/migration.rb +84 -25
- data/lib/lore/model.rb +3 -18
- data/lib/lore/{aspect.rb → model/aspect.rb} +0 -0
- data/lib/lore/model/associations.rb +225 -0
- data/lib/lore/model/attribute_settings.rb +233 -0
- data/lib/lore/model/filters.rb +34 -0
- data/lib/lore/model/mockable.rb +62 -0
- data/lib/lore/{model_factory.rb → model/model_factory.rb} +68 -39
- data/lib/lore/model/model_instance.rb +382 -0
- data/lib/lore/{model_shortcuts.rb → model/model_shortcuts.rb} +7 -0
- data/lib/lore/model/polymorphic.rb +53 -0
- data/lib/lore/model/prepare.rb +97 -0
- data/lib/lore/model/table_accessor.rb +1016 -0
- data/lib/lore/query.rb +71 -0
- data/lib/lore/query_shortcuts.rb +43 -11
- data/lib/lore/strategies/table_delete.rb +115 -0
- data/lib/lore/strategies/table_insert.rb +146 -0
- data/lib/lore/strategies/table_select.rb +299 -0
- data/lib/lore/strategies/table_update.rb +155 -0
- data/lib/lore/validation/parameter_validator.rb +85 -26
- data/lib/lore/validation/type_validator.rb +34 -78
- data/{custom_models.rb → lore-0.9.2.gem} +0 -0
- data/lore.gemspec +26 -17
- data/spec/clause.rb +37 -0
- data/spec/fixtures/blank_models.rb +37 -0
- data/{test/model.rb → spec/fixtures/models.rb} +64 -41
- data/spec/fixtures/polymorphic_models.rb +68 -0
- data/spec/model_associations.rb +86 -0
- data/spec/model_create.rb +47 -0
- data/spec/model_definition.rb +151 -0
- data/spec/model_delete.rb +31 -0
- data/spec/model_inheritance.rb +50 -0
- data/spec/model_polymorphic.rb +85 -0
- data/spec/model_select.rb +101 -0
- data/spec/model_select_eager.rb +42 -0
- data/spec/model_union_select.rb +33 -0
- data/spec/model_update.rb +45 -0
- data/spec/model_validation.rb +20 -0
- data/spec/spec_db.sql +808 -0
- data/spec/spec_env.rb +19 -0
- data/spec/spec_helpers.rb +77 -0
- metadata +93 -82
- data/lib/lore/README.txt +0 -84
- data/lib/lore/behaviours/lockable.rb +0 -55
- data/lib/lore/behaviours/movable.rb +0 -72
- data/lib/lore/behaviours/paginated.rb +0 -31
- data/lib/lore/behaviours/versioned.rb +0 -36
- data/lib/lore/connection.rb +0 -152
- data/lib/lore/exception/invalid_klass_parameters.rb +0 -63
- data/lib/lore/exception/unknown_typecode.rb +0 -19
- data/lib/lore/result.rb +0 -119
- data/lib/lore/symbol.rb +0 -58
- data/lib/lore/table_accessor.rb +0 -1790
- data/lib/lore/table_deleter.rb +0 -116
- data/lib/lore/table_inserter.rb +0 -170
- data/lib/lore/table_instance.rb +0 -389
- data/lib/lore/table_selector.rb +0 -285
- data/lib/lore/table_updater.rb +0 -157
- data/lib/lore/validation.rb +0 -65
- data/lib/lore/validation/message.rb +0 -60
- data/lib/lore/validation/reason.rb +0 -52
- data/lore_test.log +0 -2366
- data/test/README +0 -31
- data/test/custom_models.rb +0 -18
- data/test/env.rb +0 -5
- data/test/prepare.rb +0 -37
- data/test/tc_aspect.rb +0 -58
- data/test/tc_cache.rb +0 -83
- data/test/tc_clause.rb +0 -104
- data/test/tc_deep_inheritance.rb +0 -49
- data/test/tc_factory.rb +0 -57
- data/test/tc_filter.rb +0 -37
- data/test/tc_form.rb +0 -32
- data/test/tc_model.rb +0 -140
- data/test/tc_prepare.rb +0 -44
- data/test/tc_refined_query.rb +0 -88
- data/test/tc_table_accessor.rb +0 -267
- data/test/tc_thread.rb +0 -100
- data/test/test_db.sql +0 -400
- data/test/test_lore.rb +0 -50
@@ -0,0 +1,82 @@
|
|
1
|
+
|
2
|
+
require('postgres')
|
3
|
+
|
4
|
+
module Lore
|
5
|
+
|
6
|
+
class Result
|
7
|
+
|
8
|
+
attr_reader :query_hashval, :field_names, :field_types
|
9
|
+
|
10
|
+
# expects PGresult
|
11
|
+
def initialize(query, result)
|
12
|
+
@result = result
|
13
|
+
@field_types = nil
|
14
|
+
@result_rows = Array.new
|
15
|
+
@num_fields = @result.num_fields
|
16
|
+
@num_tuples = @result.num_tuples
|
17
|
+
@field_counter = 0
|
18
|
+
@field_names = @result.fields
|
19
|
+
end # def initialize
|
20
|
+
|
21
|
+
def get_field_value(row_index, field_name)
|
22
|
+
field_index = @result.fieldnum(field_name)
|
23
|
+
return @result.getvalue(row_index, field_index)
|
24
|
+
end # def get_field_value
|
25
|
+
|
26
|
+
def get_field_types()
|
27
|
+
|
28
|
+
return @field_types unless @field_types.nil?
|
29
|
+
|
30
|
+
@field_types = Hash.new
|
31
|
+
for field_index in 0...get_field_num()
|
32
|
+
@field_types[@result.fields[field_index]] = @result.type(field_index)
|
33
|
+
end
|
34
|
+
|
35
|
+
return @field_types
|
36
|
+
end
|
37
|
+
alias field_types get_field_types
|
38
|
+
alias get_field_names field_names
|
39
|
+
|
40
|
+
def get_field_num()
|
41
|
+
@num_fields
|
42
|
+
end
|
43
|
+
|
44
|
+
def get_tuple_num()
|
45
|
+
@num_tuples
|
46
|
+
end
|
47
|
+
|
48
|
+
def get_row(row_num=0)
|
49
|
+
@result[row_num]
|
50
|
+
end
|
51
|
+
def get_row_with_field_names(row_num=0)
|
52
|
+
|
53
|
+
return if @result.num_tuples == 0
|
54
|
+
|
55
|
+
row_result = Array.new
|
56
|
+
|
57
|
+
@field_counter = 0
|
58
|
+
for @field_counter in 0...@num_fields do
|
59
|
+
row_result << @result.getvalue(row_num, @field_counter)
|
60
|
+
end
|
61
|
+
@fieldnames = []
|
62
|
+
for @field_counter in 0...@num_fields do
|
63
|
+
@fieldnames << @result.fieldname(@field_counter)
|
64
|
+
end
|
65
|
+
return { :values => row_result, :fields => @fieldnames }
|
66
|
+
end
|
67
|
+
|
68
|
+
def get_rows()
|
69
|
+
rows = []
|
70
|
+
for tuple_count in 0...@result.num_tuples do
|
71
|
+
rows << @result[tuple_count]
|
72
|
+
end
|
73
|
+
return rows
|
74
|
+
end
|
75
|
+
|
76
|
+
def fieldname(index)
|
77
|
+
return @result.fieldname(index)
|
78
|
+
end
|
79
|
+
|
80
|
+
end # class Result
|
81
|
+
|
82
|
+
end # module Lore
|
@@ -0,0 +1,91 @@
|
|
1
|
+
|
2
|
+
module Lore
|
3
|
+
|
4
|
+
PG_BOOL = 16
|
5
|
+
PG_BYTEA = 17
|
6
|
+
PG_SMALLINT = 21
|
7
|
+
PG_CHAR = 18
|
8
|
+
PG_INT = 23
|
9
|
+
PG_TEXT = 25
|
10
|
+
PG_FLOAT = 701
|
11
|
+
PG_CHARACTER = 1042
|
12
|
+
PG_VARCHAR = 1043
|
13
|
+
PG_TIME = 1083
|
14
|
+
PG_TIMESTAMP_TIMEZONE = 1184
|
15
|
+
PG_TIMESTAMP = 1114
|
16
|
+
PG_DATE = 1082
|
17
|
+
PG_VCHAR_LIST = 1015
|
18
|
+
PG_DECIMAL = 1700
|
19
|
+
|
20
|
+
TYPE_NAMES = {
|
21
|
+
PG_BYTEA => 'bytea',
|
22
|
+
PG_BOOL => 'boolean',
|
23
|
+
PG_SMALLINT => 'small int',
|
24
|
+
PG_CHAR => 'char',
|
25
|
+
PG_INT => 'integer',
|
26
|
+
PG_TEXT => 'text',
|
27
|
+
PG_FLOAT => 'float',
|
28
|
+
PG_CHARACTER => 'character',
|
29
|
+
PG_VARCHAR => 'character varying(1000)',
|
30
|
+
PG_TIME => 'time',
|
31
|
+
PG_TIMESTAMP_TIMEZONE => 'timestamp with timezone',
|
32
|
+
PG_TIMESTAMP => 'timestamp',
|
33
|
+
PG_DATE => 'data',
|
34
|
+
PG_VCHAR_LIST => 'character varying[]',
|
35
|
+
PG_DECIMAL => 'decimal'
|
36
|
+
}
|
37
|
+
|
38
|
+
class Type
|
39
|
+
|
40
|
+
def self.integer; 'integer'; end
|
41
|
+
def self.boolean; 'boolean'; end
|
42
|
+
def self.bytea; 'bytea'; end
|
43
|
+
def self.char; 'char'; end
|
44
|
+
def self.varchar(length=255); 'character varying(' << length.to_s + ')'; end
|
45
|
+
def self.time; 'time'; end
|
46
|
+
def self.timestamp; 'timestamp'; end
|
47
|
+
def self.date; 'date'; end
|
48
|
+
def self.text; 'text'; end
|
49
|
+
def self.decimal; 'decimal'; end
|
50
|
+
|
51
|
+
def self.type_name(int)
|
52
|
+
TYPE_NAMES[int]
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
class Type_Filters
|
58
|
+
|
59
|
+
@@input_filters = {
|
60
|
+
PG_VCHAR_LIST => lambda { |v| "{#{v.join(',')}}" },
|
61
|
+
PG_BOOL => lambda { |v| if (v && v != 'f' || v == 't') then 'f' elsif (v.instance_of?(FalseClass) || v == 'f') then 'f' else nil end },
|
62
|
+
PG_DATE => lambda { |v| v.to_s },
|
63
|
+
PG_TIME => lambda { |v| v.to_s },
|
64
|
+
PG_TIMESTAMP_TIMEZONE => lambda { |v| v.to_s },
|
65
|
+
PG_TIMESTAMP => lambda { |v| v.to_s },
|
66
|
+
}
|
67
|
+
@@output_filters = {
|
68
|
+
PG_VCHAR_LIST => lambda { |v| v[1..-2].split(',') },
|
69
|
+
PG_INT => lambda { |v| if v then v.to_i else nil end },
|
70
|
+
PG_SMALLINT => lambda { |v| if v then v.to_i else nil end },
|
71
|
+
PG_FLOAT => lambda { |v| if v && v.length > 0 then v.to_f else nil end },
|
72
|
+
PG_DECIMAL => lambda { |v| if v && v.length > 0 then v.to_f else nil end },
|
73
|
+
PG_BOOL => lambda { |v| if v == 't' then true elsif v == 'f' then false else nil end }
|
74
|
+
# SLOW!
|
75
|
+
# PG_DATE => lambda { |v| Date.parse(v) if v },
|
76
|
+
# PG_TIME => lambda { |v| Time.parse(v) if v },
|
77
|
+
# PG_TIMESTAMP_TIMEZONE => lambda { |v| DateTime.parse(v) if v },
|
78
|
+
# PG_TIMESTAMP => lambda { |v| DateTime.parse(v) if v }
|
79
|
+
}
|
80
|
+
|
81
|
+
def self.in
|
82
|
+
@@input_filters
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.out
|
86
|
+
@@output_filters
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
end # module
|
data/lib/lore/bits.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
require('logger')
|
3
3
|
require('pstore')
|
4
4
|
require('digest/md5')
|
5
|
+
require('lore/exceptions/cache_exception')
|
5
6
|
|
6
7
|
module Lore
|
7
8
|
module Cache
|
@@ -69,7 +70,7 @@ module Cache
|
|
69
70
|
end
|
70
71
|
|
71
72
|
def storefile_of(model_name, query)
|
72
|
-
|
73
|
+
"/tmp/lore_cache__#{model_name}_#{Digest::MD5.hexdigest(query)}"
|
73
74
|
end
|
74
75
|
|
75
76
|
def create_store(storefile_name)
|
data/lib/lore/cache/cacheable.rb
CHANGED
@@ -2,198 +2,33 @@
|
|
2
2
|
require('pstore')
|
3
3
|
|
4
4
|
require('lore/cache/bits')
|
5
|
-
require('lore/
|
5
|
+
require('lore/exceptions/cache_exception')
|
6
6
|
|
7
7
|
module Lore
|
8
8
|
module Cache
|
9
9
|
|
10
10
|
module Cacheable
|
11
11
|
|
12
|
-
@@
|
13
|
-
@@cache_on_pkeys = Hash.new
|
14
|
-
@@distinctive_params = Hash.new
|
15
|
-
@@cache_entities = false
|
12
|
+
@@cache_impl = false
|
16
13
|
|
17
|
-
|
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]
|
14
|
+
def entity_cache
|
15
|
+
@@cache_impl
|
24
16
|
end
|
25
17
|
|
26
|
-
|
27
|
-
|
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
|
-
|
18
|
+
def use_entity_cache(entity_cache_class)
|
19
|
+
@@cache_impl = entity_cache_class
|
43
20
|
end
|
44
21
|
|
45
|
-
|
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
|
-
|
22
|
+
def flush_entity_cache
|
23
|
+
@@cache_impl.flush(self) if @@cache_impl
|
55
24
|
end
|
56
25
|
|
57
|
-
def
|
58
|
-
@@
|
26
|
+
def create_entity_cache(query_string, result)
|
27
|
+
@@cache_impl.create(self, query_string, result) if @@cache_impl
|
59
28
|
end
|
60
29
|
|
61
|
-
def
|
62
|
-
@@
|
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
|
30
|
+
def read_entity_cache(query_string)
|
31
|
+
@@cache_impl.read(self, query_string) if @@cache_impl
|
197
32
|
end
|
198
33
|
|
199
34
|
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
|
2
|
+
require 'lore'
|
3
|
+
require 'lore/cache/abstract_entity_cache'
|
4
|
+
begin
|
5
|
+
require 'mmap'
|
6
|
+
require 'activesupport'
|
7
|
+
require 'active_support/cache/mem_cache_store'
|
8
|
+
rescue LoadError
|
9
|
+
Lore.log { 'Mmap or ActiveSupport for Ruby could not be loaded. You won\'t be able to use Mmap_Entity_Cache. ' }
|
10
|
+
|
11
|
+
module ActiveSupport
|
12
|
+
module Cache
|
13
|
+
class MemCacheStore
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class Object
|
20
|
+
def logger
|
21
|
+
Lore.logger
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
module Lore
|
26
|
+
module Cache
|
27
|
+
|
28
|
+
|
29
|
+
# Implementation of entity cache using MMapped PStor files.
|
30
|
+
# Derived from Abstract_Entity_Cache.
|
31
|
+
# Uses Lore::Cache::Cache_Helpers for generating PStor files.
|
32
|
+
class Memcache_Entity_Cache < Abstract_Entity_Cache
|
33
|
+
extend Cache_Helpers
|
34
|
+
|
35
|
+
@@logger = Logger.new('/tmp/lore_cache.log')
|
36
|
+
|
37
|
+
@@store = ActiveSupport::Cache::MemCacheStore.new()
|
38
|
+
|
39
|
+
|
40
|
+
def self.flush(accessor)
|
41
|
+
index = accessor.table_name
|
42
|
+
return unless Lore.cache_enabled?
|
43
|
+
Dir.glob("/tmp/lore_cache__#{index}*").each { |cache_file|
|
44
|
+
@@logger.debug('Clearing cache file ' << cache_file.to_s.split('_').last)
|
45
|
+
begin
|
46
|
+
@@store.delete(cache_file.to_s.split('_').last)
|
47
|
+
rescue ::Exception => excep
|
48
|
+
# Another process already killed this file
|
49
|
+
end
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.read(accessor, query_obj)
|
54
|
+
@@logger.debug { 'Loading from cache: ' << index_for(query_obj[:query]) }
|
55
|
+
store = @@store.read("#{accessor.table_name}--#{index_for(query_obj[:query])}")
|
56
|
+
return [] unless store
|
57
|
+
return store[:values]
|
58
|
+
|
59
|
+
result = []
|
60
|
+
store.each { |r|
|
61
|
+
joined_models = r[:joined_models]
|
62
|
+
joined_models ||= []
|
63
|
+
result << accessor.new(r[:values].dup, joined_models, true)
|
64
|
+
}
|
65
|
+
return result
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.create(accessor, query_object, result)
|
69
|
+
entry = query_object.update({ :values => result })
|
70
|
+
@@store.write("#{accessor.table_name}--#{index_for(query_object[:query])}", entry)
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.include?(accessor, query_obj)
|
74
|
+
hit = @@store.exist?("#{accessor.table_name}--#{index_for(query_obj[:query])}")
|
75
|
+
@@logger.debug { 'Cache miss: ' << index_for(query_obj[:query]) } unless hit
|
76
|
+
return hit
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.delete(index)
|
80
|
+
@@logger.debug { "Deleting index #{index}" }
|
81
|
+
@@store.delete(index)
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
|