lore 0.4.8 → 0.9.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.
- 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
|
+
|