Commit 9b292489 authored by Ivan Tyagov's avatar Ivan Tyagov

Merge branch 'cache'

parents 364be170 255d3227
......@@ -1128,7 +1128,8 @@ class ObjectTemplateItem(BaseTemplateItem):
container._mapTransform(obj)
elif obj.meta_type in ('ERP5 Ram Cache',
'ERP5 Distributed Ram Cache',):
assert container.meta_type == 'ERP5 Cache Factory'
assert container.meta_type in ('ERP5 Cache Factory',
'ERP5 Cache Bag')
container.getParentValue().updateCache()
elif (container.meta_type == 'CMF Skins Tool') and \
(old_obj is not None):
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ActionInformation" module="Products.CMFCore.ActionInformation"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/object_view</string>
</tuple>
</value>
</item>
<item>
<key> <string>category</string> </key>
<value> <string>object_view</string> </value>
</item>
<item>
<key> <string>condition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>icon</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>view</string> </value>
</item>
<item>
<key> <string>permissions</string> </key>
<value>
<tuple>
<string>View</string>
</tuple>
</value>
</item>
<item>
<key> <string>priority</string> </key>
<value> <float>1.0</float> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>View</string> </value>
</item>
<item>
<key> <string>visible</string> </key>
<value> <int>1</int> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Expression" module="Products.CMFCore.Expression"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string>string:${object_url}/CacheBag_view</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -19,7 +19,12 @@
<item>Action Information</item>
<item>Role Information</item>
</portal_type>
<portal_type id="Cache Bag">
<item>Distributed Ram Cache</item>
<item>Ram Cache</item>
</portal_type>
<portal_type id="Cache Factory">
<item>Cache Bag</item>
<item>Distributed Ram Cache</item>
<item>Ram Cache</item>
</portal_type>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Base Type" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>acquire_local_roles</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>content_icon</string> </key>
<value> <string>document_icon.gif</string> </value>
</item>
<item>
<key> <string>content_meta_type</string> </key>
<value> <string>ERP5 Cache Factory</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string> CacheBag is .....</string> </value>
</item>
<item>
<key> <string>factory</string> </key>
<value> <string>addCacheFactory</string> </value>
</item>
<item>
<key> <string>filter_content_types</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>group_list</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Cache Bag</string> </value>
</item>
<item>
<key> <string>init_script</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>permission</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>type_class</string> </key>
<value> <string>CacheBag</string> </value>
</item>
<item>
<key> <string>type_interface</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>type_mixin</string> </key>
<value>
<tuple/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ERP5Form" module="Products.ERP5Form.Form"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>action</string> </key>
<value> <string>Base_edit</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>edit_order</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>encoding</string> </key>
<value> <string>UTF-8</string> </value>
</item>
<item>
<key> <string>enctype</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>group_list</string> </key>
<value>
<list>
<string>left</string>
<string>right</string>
<string>center</string>
<string>bottom</string>
<string>hidden</string>
</list>
</value>
</item>
<item>
<key> <string>groups</string> </key>
<value>
<dictionary>
<item>
<key> <string>bottom</string> </key>
<value>
<list>
<string>listbox</string>
</list>
</value>
</item>
<item>
<key> <string>center</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>hidden</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>left</string> </key>
<value>
<list>
<string>my_id</string>
<string>my_title</string>
<string>my_cache_duration</string>
<string>my_int_index</string>
</list>
</value>
</item>
<item>
<key> <string>right</string> </key>
<value>
<list/>
</value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>CacheBag_view</string> </value>
</item>
<item>
<key> <string>method</string> </key>
<value> <string>POST</string> </value>
</item>
<item>
<key> <string>name</string> </key>
<value> <string>General</string> </value>
</item>
<item>
<key> <string>pt</string> </key>
<value> <string>form_view</string> </value>
</item>
<item>
<key> <string>row_length</string> </key>
<value> <int>4</int> </value>
</item>
<item>
<key> <string>stored_encoding</string> </key>
<value> <string>UTF-8</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Cache Bag</string> </value>
</item>
<item>
<key> <string>unicode_mode</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>update_action</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>update_action_title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>columns</string>
<string>count_method</string>
<string>list_method</string>
<string>portal_types</string>
<string>search_columns</string>
<string>selection_name</string>
<string>sort</string>
<string>sort_columns</string>
<string>title</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>listbox</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>all_editable_columns</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>columns</string> </key>
<value>
<list>
<tuple>
<string>id</string>
<string>ID</string>
</tuple>
<tuple>
<string>int_index</string>
<string>Priority</string>
</tuple>
<tuple>
<string>title</string>
<string>Title</string>
</tuple>
<tuple>
<string>portal_type</string>
<string>Type</string>
</tuple>
</list>
</value>
</item>
<item>
<key> <string>count_method</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_list_mode_listbox</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>list_method</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>portal_types</string> </key>
<value>
<list>
<tuple>
<string>Ram Cache</string>
<string>Ram Cache</string>
</tuple>
<tuple>
<string>Distributed Ram Cache</string>
<string>Distributed Ram Cache</string>
</tuple>
</list>
</value>
</item>
<item>
<key> <string>search_columns</string> </key>
<value>
<list>
<tuple>
<string>id</string>
<string>ID</string>
</tuple>
<tuple>
<string>title</string>
<string>Title</string>
</tuple>
</list>
</value>
</item>
<item>
<key> <string>selection_name</string> </key>
<value> <string>search_selection1</string> </value>
</item>
<item>
<key> <string>sort</string> </key>
<value>
<list>
<tuple>
<string>int_index</string>
<string>Priority</string>
</tuple>
</list>
</value>
</item>
<item>
<key> <string>sort_columns</string> </key>
<value>
<list>
<tuple>
<string>id</string>
<string>ID</string>
</tuple>
<tuple>
<string>int_index</string>
<string>Priority</string>
</tuple>
<tuple>
<string>title</string>
<string>Title</string>
</tuple>
<tuple>
<string>portal_type</string>
<string>Type</string>
</tuple>
</list>
</value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Cache Plugins</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Method" module="Products.Formulator.MethodField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>method_name</string> </key>
<value> <string>objectValues</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="IntegerField" module="Products.Formulator.StandardFields"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>my_cache_duration</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
<item>
<key> <string>integer_out_of_range</string> </key>
<value> <string>The integer you entered was out of range.</string> </value>
</item>
<item>
<key> <string>not_integer</string> </key>
<value> <string>You did not enter an integer.</string> </value>
</item>
<item>
<key> <string>required_not_found</string> </key>
<value> <string>Input is required but no input given.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>display_maxwidth</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>display_width</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>end</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>start</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>whitespace_preserve</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>display_maxwidth</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>display_width</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>end</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>start</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>whitespace_preserve</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>display_maxwidth</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>display_width</string> </key>
<value> <int>20</int> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>end</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>start</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Cache Duration</string> </value>
</item>
<item>
<key> <string>whitespace_preserve</string> </key>
<value> <int>0</int> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="IntegerField" module="Products.Formulator.StandardFields"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>my_int_index</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
<item>
<key> <string>integer_out_of_range</string> </key>
<value> <string>The integer you entered was out of range.</string> </value>
</item>
<item>
<key> <string>not_integer</string> </key>
<value> <string>You did not enter an integer.</string> </value>
</item>
<item>
<key> <string>required_not_found</string> </key>
<value> <string>Input is required but no input given.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>display_maxwidth</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>display_width</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>end</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>start</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>whitespace_preserve</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>display_maxwidth</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>display_width</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>end</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>start</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>whitespace_preserve</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Lower value means higher priority</string> </value>
</item>
<item>
<key> <string>display_maxwidth</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>display_width</string> </key>
<value> <int>2</int> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>end</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>start</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Priority</string> </value>
</item>
<item>
<key> <string>whitespace_preserve</string> </key>
<value> <int>0</int> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>my_title</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_title</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -129,6 +129,10 @@
<string>Cache Factory</string>
<string>Cache Factory</string>
</tuple>
<tuple>
<string>Cache Bag</string>
<string>Cache Bag</string>
</tuple>
</list>
</value>
</item>
......
......@@ -35,6 +35,7 @@ Business Template | view
Business Template | view_catalog
Business Template | view_detail
Business Template | view_portal_types
Cache Bag | view
Cache Factory | statistics
Cache Factory | view
Cache Tool | statistics
......
......@@ -6,6 +6,9 @@ Base Domain | Domain
Base Domain | Domain Generator
Base Type | Action Information
Base Type | Role Information
Cache Bag | Distributed Ram Cache
Cache Bag | Ram Cache
Cache Factory | Cache Bag
Cache Factory | Distributed Ram Cache
Cache Factory | Ram Cache
Cache Tool | Cache Factory
......@@ -52,4 +55,4 @@ Simulation Movement | Applied Rule
Simulation Tool | Applied Rule
Template Tool | Business Template
Trash Tool | Trash Bin
Types Tool | Base Type
\ No newline at end of file
Types Tool | Base Type
......@@ -15,6 +15,7 @@ Base Category
Base Domain
Base Type
Business Template
Cache Bag
Cache Factory
Cache Tool
Category
......
......@@ -74,20 +74,15 @@ class CachedConvertableMixin:
def _getCacheFactory(self):
"""
"""
# XXX: is this really needed ?
if self.getOriginalDocument() is None:
return None
portal = self.getPortalObject()
cache_tool = portal.portal_caches
preference_tool = portal.portal_preferences
cache_factory_name = preference_tool.getPreferredConversionCacheFactory('document_cache_factory')
cache_factory = cache_tool.getRamCacheRoot().get(cache_factory_name)
#XXX This conditional statement should be remove as soon as
#Broadcasting will be enable among all zeo clients.
#Interaction which update portal_caches should interact with all nodes.
if cache_factory is None and getattr(cache_tool, cache_factory_name, None) is not None:
#ram_cache_root is not up to date for current node
cache_tool.updateCache()
return cache_tool.getRamCacheRoot().get(cache_factory_name)
cache_factory_name = portal.portal_preferences.getPreferredConversionCacheFactory('document_cache_factory')
if cache_factory_name is not None:
return getattr(portal.portal_caches, cache_factory_name, None)
security.declareProtected(Permissions.AccessContentsInformation,
'generateCacheId')
......@@ -167,23 +162,18 @@ class CachedConvertableMixin:
self.temp_conversion_data = {}
self.temp_conversion_data[cache_id] = stored_data_dict
return
cache_duration = cache_factory.cache_duration
# The purpose of this transaction cache is to help calls
# to the same cache value in the same transaction.
tv = getTransactionalVariable()
tv[cache_id] = stored_data_dict
for cache_plugin in cache_factory.getCachePluginList():
cache_plugin.set(cache_id, DEFAULT_CACHE_SCOPE,
stored_data_dict, cache_duration=cache_duration)
cache_factory.set(cache_id, stored_data_dict)
security.declareProtected(Permissions.View, '_getConversionDataDict')
def _getConversionDataDict(self, **kw):
"""
"""
cache_id = self._getCacheKey(**kw)
cache_factory = self._getCacheFactory()
if cache_factory is None:
return getattr(aq_base(self), 'temp_conversion_data', {})[cache_id]
# The purpose of this cache is to help calls to the same cache value
# in the same transaction.
tv = getTransactionalVariable()
......@@ -191,26 +181,33 @@ class CachedConvertableMixin:
return tv[cache_id]
except KeyError:
pass
for cache_plugin in cache_factory.getCachePluginList():
cache_entry = cache_plugin.get(cache_id, DEFAULT_CACHE_SCOPE)
if cache_entry is not None:
data_dict = cache_entry.getValue()
if data_dict:
if isinstance(data_dict, tuple):
# Backward compatibility: if cached value is a tuple
# as it was before refactoring
# http://svn.erp5.org?rev=35216&view=rev
# raise a KeyError to invalidate this cache entry and force
# calculation of a new conversion
raise KeyError('Old cache conversion format,'\
'cache entry invalidated for key:%r' % cache_id)
content_md5 = data_dict['content_md5']
if content_md5 != self.getContentMd5():
raise KeyError, 'Conversion cache key is compromised for %r' % cache_id
# Fill transactional cache in order to help
# querying real cache during same transaction
tv[cache_id] = data_dict
return data_dict
# get preferred cache factory or cache bag
cache_factory = self._getCacheFactory()
# volatile case
if cache_factory is None:
return getattr(aq_base(self), 'temp_conversion_data', {})[cache_id]
else:
data_dict = cache_factory.get(cache_id, None)
if data_dict:
if isinstance(data_dict, tuple):
# Backward compatibility: if cached value is a tuple
# as it was before refactoring
# http://svn.erp5.org?rev=35216&view=rev
# raise a KeyError to invalidate this cache entry and force
# calculation of a new conversion
raise KeyError('Old cache conversion format,'\
'cache entry invalidated for key:%r' % cache_id)
content_md5 = data_dict['content_md5']
if content_md5 != self.getContentMd5():
raise KeyError, 'Conversion cache key is compromised for %r' % cache_id
# Fill transactional cache in order to help
# querying real cache during same transaction
tv[cache_id] = data_dict
return data_dict
raise KeyError, 'Conversion cache key does not exists for %r' % cache_id
security.declareProtected(Permissions.View, 'getConversion')
......
......@@ -133,9 +133,14 @@ class TestDocumentMixin(ERP5TypeTestCase):
preference_list = self.portal.portal_preferences.contentValues(
portal_type=portal_type)
if not preference_list:
# create a Cache Factory for tests
cache_factory = self.portal.portal_caches.newContent(portal_type = 'Cache Factory')
cache_factory.cache_duration = 36000
cache_plugin = cache_factory.newContent(portal_type='Ram Cache')
cache_plugin.cache_expire_check_interval = 54000
preference = self.portal.portal_preferences.newContent(title="Default System Preference",
# use local RAM based cache as some tests need it
preferred_conversion_cache_factory = 'erp5_content_long',
preferred_conversion_cache_factory = cache_factory.getId(),
portal_type=portal_type)
else:
preference = preference_list[0]
......
......@@ -44,11 +44,14 @@ class TestDocumentWithFlare(TestDocument):
def setSystemPreference(self):
system_preference = TestDocument.setSystemPreference(self)
memcached = _getPersistentMemcachedServerDict()
system_preference.setPreferredConversionCacheFactory('dms_cache_factory')
# create a Cache Factory for tests
cache_factory = self.portal.portal_caches.newContent(portal_type = 'Cache Factory')
cache_factory.cache_duration = 15768000
cache_plugin = cache_factory.newContent(portal_type='Distributed Ram Cache')
system_preference.setPreferredConversionCacheFactory(cache_factory.getId())
persistent_memcached_plugin = self.portal.portal_memcached.persistent_memcached_plugin
persistent_memcached_plugin.setUrlString('%s:%s' %(memcached['hostname'], memcached['port']))
self.portal.portal_caches.dms_cache_factory.persistent_cache_plugin.setSpecialiseValue(persistent_memcached_plugin)
cache_plugin.setSpecialiseValue(persistent_memcached_plugin)
def test_suite():
suite = unittest.TestSuite()
......
......@@ -68,7 +68,6 @@ class TestDocumentWithPreConversion(TestDocument):
"""
Test pre converion only happens on proper documents.
"""
print "da"
image = self.portal.image_module.newContent(portal_type='Image',
reference='Embedded-XXX',
version='001',
......
......@@ -29,6 +29,7 @@
import unittest
from testIngestion import TestIngestion
from Products.ERP5Type.tests.ERP5TypeTestCase import _getPersistentMemcachedServerDict
class TestIngestionWithFlare(TestIngestion):
"""
......@@ -47,7 +48,15 @@ class TestIngestionWithFlare(TestIngestion):
def setSystemPreference(self):
default_pref = self.portal.portal_preferences.default_site_preference
default_pref.setPreferredConversionCacheFactory('dms_cache_factory')
memcached = _getPersistentMemcachedServerDict()
# create a Cache Factory for tests
cache_factory = self.portal.portal_caches.newContent(portal_type = 'Cache Factory')
cache_factory.cache_duration = 15768000
cache_plugin = cache_factory.newContent(portal_type='Distributed Ram Cache')
default_pref.setPreferredConversionCacheFactory(cache_factory.getId())
persistent_memcached_plugin = self.portal.portal_memcached.persistent_memcached_plugin
persistent_memcached_plugin.setUrlString('%s:%s' %(memcached['hostname'], memcached['port']))
cache_plugin.setSpecialiseValue(persistent_memcached_plugin)
TestIngestion.setSystemPreference(self)
......
......@@ -265,19 +265,17 @@ class TestDocumentConversionCache(TestDocumentMixin):
document.convert(**kw)
cache_id = document._getCacheKey(**kw)
cache_factory = document._getCacheFactory()
for cache_plugin in cache_factory.getCachePluginList():
cache_entry = cache_plugin.get(cache_id, DEFAULT_CACHE_SCOPE)
data_dict = cache_entry.getValue()
#get data from cache
self.assertTrue(data_dict['content_md5'])
self.assertTrue(data_dict['conversion_md5'])
self.assertTrue(data_dict['mime'])
self.assertTrue(data_dict['data'])
self.assertTrue(data_dict['date'])
self.assertTrue(data_dict['size'])
#Change md5 manualy
data_dict['content_md5'] = 'Anything which is not md5'
cache_plugin.set(cache_id, DEFAULT_CACHE_SCOPE, data_dict, 100, 0)
data_dict = cache_factory.get(cache_id)
#get data from cache
self.assertTrue(data_dict['content_md5'])
self.assertTrue(data_dict['conversion_md5'])
self.assertTrue(data_dict['mime'])
self.assertTrue(data_dict['data'])
self.assertTrue(data_dict['date'])
self.assertTrue(data_dict['size'])
#Change md5 manualy
data_dict['content_md5'] = 'Anything which is not md5'
cache_factory.set(cache_id, data_dict)
self.commit()
self.assertRaises(KeyError, document.getConversion, format='html')
......
......@@ -200,6 +200,16 @@ class CacheFactory:
return cp
return None
def getCachePluginById(self, id, default=None):
""" get cache plugin by its id """
for cp in self.cache_plugins:
if id == cp.id:
return cp
if default is not None:
return default
raise KeyError("No such plugin exists %s" % id)
def clearCache(self):
""" clear cache for this cache factory """
for cp in self.cache_plugins:
......
......@@ -94,10 +94,11 @@ class BaseCache(object):
## Time interval (s) to check for expired objects
cache_expire_check_interval = 60
def __init__(self, params={}):
def __init__(self, id, params={}):
self._next_cache_expire_check_at = time()
self._cache_hit_count = 0
self._cache_miss_count = 0
self.id = id
def markCacheHit(self, delta=1):
""" Mark a read operation from cache """
......
......@@ -55,14 +55,14 @@ class DistributedRamCache(BaseCache):
interfaces.ICachePlugin
)
def __init__(self, params={}):
def __init__(self, uid, params={}):
self._servers = params.get('server', '')
self._expiration_time = params.get('expiration_time', 0)
self._server_max_key_length = params.get('server_max_key_length', 250)
self._server_max_value_length = params.get('server_max_value_length', 1024*1024)
self._debug_level = params.get('debug_level', 0)
self._key_prefix = params.get('key_prefix', '')
BaseCache.__init__(self)
BaseCache.__init__(self, uid)
def initCacheStorage(self):
""" Init cache storage """
......
......@@ -59,9 +59,9 @@ class RamCache(BaseCache):
cache_expire_check_interval = 300
def __init__(self, params={}):
def __init__(self, uid, params={}):
self._cache_dict = {}
BaseCache.__init__(self)
BaseCache.__init__(self, uid)
def initCacheStorage(self):
""" Init cache storage """
......
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2005 Nexedi SARL and Contributors. All Rights Reserved.
# Ivan Tyagov <ivan@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions
from Products.ERP5Type.Cache import DEFAULT_CACHE_SCOPE
from Products.ERP5Type.Core.CacheFactory import CacheFactory
class CacheBag(CacheFactory):
"""
CacheBag is a special type of a CacheFactory that allows multi level caching
in different backends describe by CachePlugin.
CacheBag 1
- Cache Plugin 1 (priority 0)
- Cache Plugin 2 (priority 1)
"""
meta_type = 'ERP5 Cache Bag'
portal_type = 'Cache Bag'
security = ClassSecurityInfo()
security.declareProtected(Permissions.AccessContentsInformation, 'get')
def get(self, cache_id, default=None):
"""
Get value or return default.
"""
ram_cache_factory_plugin_list = self.getRamCacheFactoryPluginList()
for cache_plugin in ram_cache_factory_plugin_list:
data_dict = cache_plugin.get(cache_id, DEFAULT_CACHE_SCOPE, default)
if data_dict is not None:
value = data_dict.getValue()
if ram_cache_factory_plugin_list.index(cache_plugin) > 0:
# update first plugin as it's the one to be used
# XXX: JPS we can have different update policy here based on a project requirements.
# c0 c1 c2....cN where c0 is filled from cN
# c1.... cN-1 untouched then rotate i -> i+1
# this way you can create "groups of caches" per date and trash old stuff
# instead of using 2x more disk space, you can use 1/N more disk space
cache_duration = self.getRamCacheFactory().cache_duration
ram_cache_factory_plugin_list[0].set(cache_id, DEFAULT_CACHE_SCOPE, value, cache_duration)
return value
return default
security.declareProtected(Permissions.AccessContentsInformation, 'set')
def set(self, cache_id, value):
"""
Set value.
"""
cache_duration = self.getRamCacheFactory().cache_duration
ram_cache_factory_plugin_list = self.getRamCacheFactoryPluginList()
# set only in first plugin in sequence
ram_cache_factory_plugin_list[0].set(cache_id, DEFAULT_CACHE_SCOPE, value, cache_duration)
......@@ -58,12 +58,48 @@ class CacheFactory(XMLObject):
, PropertySheet.SimpleItem
, PropertySheet.Folder
, PropertySheet.CacheFactory
, PropertySheet.SortIndex
)
def getCacheId(self):
"""
Get a common Cache Factory / Cache Bag ID in this
case relative to portal_caches.
It's required to use relative url (i.e. mainly ID) due
to CachingMethod legacy.
"""
relative_url = self.getRelativeUrl()
assert relative_url[:14] == 'portal_caches/'
return relative_url[14:]
def getCachePluginList(self):
security.declareProtected(Permissions.AccessContentsInformation, 'get')
def get(self, cache_id, default=None):
"""
Get value or return default from all contained Cache Bag
or Cache Plugin.
"""
cache_plugin_list = self.getCachePluginList(list(self.allowed_types) + ['ERP5 Cache Bag'])
for cache_plugin in cache_plugin_list:
value = cache_plugin.get(cache_id, default)
if value is not None:
return value
return default
security.declareProtected(Permissions.AccessContentsInformation, 'set')
def set(self, cache_id, value):
"""
Set value to all contained cache plugin or cache bag.
"""
cache_plugin_list = self.getCachePluginList(list(self.allowed_types) + ['ERP5 Cache Bag'])
for cache_plugin in cache_plugin_list:
cache_plugin.set(cache_id, value)
def getCachePluginList(self, allowed_type_list=None):
""" get ordered list of installed cache plugins in ZODB """
cache_plugins = self.objectValues(self.allowed_types)
if allowed_type_list is None:
# fall back to default ones
allowed_type_list = self.allowed_types
cache_plugins = self.objectValues(allowed_type_list)
cache_plugins = map(None, cache_plugins)
cache_plugins.sort(key=lambda x: x.getIntIndex(0))
return cache_plugins
......@@ -71,8 +107,16 @@ class CacheFactory(XMLObject):
security.declareProtected(Permissions.AccessContentsInformation, 'getRamCacheFactory')
def getRamCacheFactory(self):
""" Return RAM based cache factory """
erp5_site_id = self.getPortalObject().getId()
return CachingMethod.factories[erp5_site_id][self.cache_scope]
cache_factory_name = self.getCacheId()
cache_tool = self.portal_caches
cache_factory = CachingMethod.factories.get(cache_factory_name)
#XXX This conditional statement should be remove as soon as
#Broadcasting will be enable among all zeo clients.
#Interaction which update portal_caches should interact with all nodes.
if cache_factory is None and getattr(cache_tool, cache_factory_name, None) is not None:
#ram_cache_root is not up to date for current node
cache_tool.updateCache()
return CachingMethod.factories[cache_factory_name]
security.declareProtected(Permissions.AccessContentsInformation, 'getRamCacheFactoryPluginList')
def getRamCacheFactoryPluginList(self):
......@@ -81,5 +125,5 @@ class CacheFactory(XMLObject):
def clearCache(self):
""" clear cache for this cache factory """
for cp in self.getRamCacheFactory().getCachePluginList():
for cp in self.getRamCacheFactoryPluginList():
cp.clearCache()
......@@ -31,8 +31,9 @@ from AccessControl import ClassSecurityInfo
from Products.ERP5Type.XMLObject import XMLObject
from Products.ERP5Type import PropertySheet
from Products.ERP5Type import Permissions
from Products.ERP5Type.mixin.cache_provider import CacheProviderMixIn
class DistributedRamCache(XMLObject):
class DistributedRamCache(CacheProviderMixIn, XMLObject):
"""
DistributedRamCache is a Zope (persistent) representation of
the Distributed RAM Cache real cache plugin object.
......
......@@ -32,8 +32,9 @@ from AccessControl import ClassSecurityInfo
from Products.ERP5Type.XMLObject import XMLObject
from Products.ERP5Type import PropertySheet
from Products.ERP5Type import Permissions
from Products.ERP5Type.mixin.cache_provider import CacheProviderMixIn
class RamCache(XMLObject):
class RamCache(CacheProviderMixIn, XMLObject):
"""
RamCache is a Zope (persistent) representation of
the RAM based real cache plugin object.
......
......@@ -66,38 +66,56 @@ class CacheTool(BaseTool):
security.declareProtected(Permissions.AccessContentsInformation, 'getCacheFactoryList')
def getCacheFactoryList(self):
""" Return available cache factories """
def getRamCachePlugin(cp):
cp_meta_type = cp.meta_type
id = cp.getCacheId()
if cp_meta_type == 'ERP5 Ram Cache':
return RamCache(id)
if cp_meta_type == 'ERP5 Distributed Ram Cache':
## even thougn we have such plugin in ZODB that doens't mean
## we have corresponding memcache module installed
if getattr(cp, 'getSpecialiseValue', None) is not None:
memcached_plugin = cp.getSpecialiseValue()
if memcached_plugin is not None:
server = memcached_plugin.getUrlString('')
init_dict = {
'server': server,
'expiration_time': cf.getCacheDuration(),
'server_max_key_length': memcached_plugin.getServerMaxKeyLength(),
'server_max_value_length': memcached_plugin.getServerMaxValueLength(),
'key_prefix': getattr(self, 'erp5_site_global_id', '')}
return DistributedRamCache(id, init_dict)
rd = {}
for cf in self.objectValues('ERP5 Cache Factory'):
cache_scope = cf.getId()
cache_scope = cf.getCacheId()
rd[cache_scope] = {}
rd[cache_scope]['cache_plugins'] = []
rd[cache_scope]['cache_params'] = {}
for cp in cf.getCachePluginList():
cache_obj = None
cp_meta_type = cp.meta_type
if cp_meta_type == 'ERP5 Ram Cache':
cache_obj = RamCache()
elif cp_meta_type == 'ERP5 Distributed Ram Cache':
## even thougn we have such plugin in ZODB that doens't mean
## we have corresponding memcache module installed
cache_obj = None
if getattr(cp, 'getSpecialiseValue', None) is not None:
memcached_plugin = cp.getSpecialiseValue()
if memcached_plugin is not None:
server = memcached_plugin.getUrlString('')
init_dict = {
'server': server,
'expiration_time': cf.getCacheDuration(),
'server_max_key_length': memcached_plugin.getServerMaxKeyLength(),
'server_max_value_length': memcached_plugin.getServerMaxValueLength(),
'key_prefix': getattr(self, 'erp5_site_global_id', '')
}
cache_obj = DistributedRamCache(init_dict)
cache_obj = getRamCachePlugin(cp)
if cache_obj is not None:
## set cache expire check interval
cache_obj.cache_expire_check_interval = cp.getCacheExpireCheckInterval()
rd[cache_scope]['cache_plugins'].append(cache_obj)
rd[cache_scope]['cache_params']['cache_duration'] = cf.getCacheDuration()
# support for cache bags which are like Cache Factory
# i.e. provide Cache Plugins
for cache_bag in cf.objectValues('ERP5 Cache Bag'):
cache_scope = cache_bag.getCacheId()
rd[cache_scope] = {}
rd[cache_scope]['cache_plugins'] = []
rd[cache_scope]['cache_params'] = {}
for cp in cache_bag.getCachePluginList():
cache_obj = getRamCachePlugin(cp)
if cache_obj is not None:
## set cache expire check interval
cache_obj.cache_expire_check_interval = cp.getCacheExpireCheckInterval()
rd[cache_scope]['cache_plugins'].append(cache_obj)
rd[cache_scope]['cache_params']['cache_duration'] = cf.getCacheDuration()
return rd
##
......
......@@ -36,7 +36,7 @@ class ICachePlugin(Interface):
"""CachePlugin Interface Specification
"""
def __init__(params={}):
def __init__(uid, params={}):
"""Initialise default values
"""
......
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2012 Nexedi SA and Contributors. All Rights Reserved.
# Ivan Tyagov <ivan@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions
from Products.ERP5Type.Cache import DEFAULT_CACHE_SCOPE
class CacheProviderMixIn:
"""
Generic Cache Plugin set / get API implementation.
"""
security = ClassSecurityInfo()
def _getRamCachePlugin(self):
"""
Get RAM based cache plugin for this ZODB cache plugin.
"""
return self.getParentValue().getRamCacheFactory().getCachePluginById(self.getCacheId())
security.declareProtected(Permissions.AccessContentsInformation, 'get')
def get(self, cache_id, default=None):
"""
Get value from cache plugin.
"""
cache_plugin = self._getRamCachePlugin()
value = cache_plugin.get(cache_id, DEFAULT_CACHE_SCOPE, default)
if value is not None:
value = value.getValue()
return value
security.declareProtected(Permissions.AccessContentsInformation, 'set')
def set(self, cache_id, value):
"""
Set value to cache plugin.
"""
cache_duration = self.getParentValue().getRamCacheFactory().cache_duration
cache_plugin = self._getRamCachePlugin()
cache_plugin.set(cache_id, DEFAULT_CACHE_SCOPE, value, cache_duration)
def getCacheId(self):
"""
Get a common Cache Factory / Cache Bag ID in this
case relative to portal_caches.
It's required to use relative url (i.e. mainly ID) due
to CachingMethod legacy.
"""
relative_url = self.getRelativeUrl()
assert relative_url[:14] == 'portal_caches/'
return relative_url[14:]
......@@ -50,8 +50,9 @@ class TestRamCache(ERP5TypeTestCase):
return "Cache"
def afterSetUp(self):
self.cache_plugins = (RamCache(),
DistributedRamCache({'server': '127.0.0.1:11211',
self.cache_plugins = (RamCache('ram_cache'),
DistributedRamCache('distributed_ram_cache',
{'server': '127.0.0.1:11211',
'debug_level': 7,
'server_max_key_length': 250,
'server_max_value_length': 1048576,}),
......
......@@ -35,7 +35,7 @@ from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
from Products.ERP5Type.tests.ERP5TypeTestCase import _getPersistentMemcachedServerDict, _getVolatileMemcachedServerDict
from Products.ERP5Type.CachePlugins.DummyCache import DummyCache
from AccessControl.SecurityManagement import newSecurityManager
from Products.ERP5Type.Cache import CachingMethod
from Products.ERP5Type.Cache import CachingMethod, DEFAULT_CACHE_SCOPE
from zLOG import LOG
class TestingCache(DummyCache):
......@@ -483,6 +483,83 @@ return 'a' * 1024 * 1024 * 25
calculation_time = self._callCache(my_cache, real_calculation=True)
print "\n\tCalculation time (3rd call)", calculation_time
def test_06_CheckCacheBag(self):
"""
Check Cache Bag
"""
portal_caches = self.portal.portal_caches
cache_factory = portal_caches.newContent(portal_type="Cache Factory",
cache_duration=3600)
cache_bag = cache_factory.newContent(portal_type="Cache Bag",
cache_duration=3600)
cache_plugin1 = cache_bag.newContent(portal_type="Ram Cache")
cache_plugin1.setIntIndex(0)
cache_plugin2 = cache_bag.newContent(portal_type="Ram Cache")
cache_plugin2.setIntIndex(1)
self.tic()
portal_caches.updateCache()
# test proper init
ram_cache_factory_plugin_list = cache_bag.getRamCacheFactoryPluginList()
self.assertEqual(2, len(ram_cache_factory_plugin_list))
# test get / set API
cache_bag.set('x', 'value_fox_x')
self.assertEqual('value_fox_x', cache_bag.get('x'))
# test that only first cache plugin is used to set
self.assertEqual('value_fox_x',
ram_cache_factory_plugin_list[0].get('x',DEFAULT_CACHE_SCOPE).getValue())
self.assertRaises(KeyError, ram_cache_factory_plugin_list[1].get, 'x', DEFAULT_CACHE_SCOPE)
# check hot copy happens from second in order plugin to first
ram_cache_factory_plugin_list[1].set('y', DEFAULT_CACHE_SCOPE, 'value_for_y', cache_bag.cache_duration)
self.assertEqual('value_for_y', cache_bag.get('y'))
self.assertEqual('value_for_y', ram_cache_factory_plugin_list[0].get('y',DEFAULT_CACHE_SCOPE).getValue())
def test_07_CheckCacheFactory(self):
"""
Check Cache Factory set and get API.
"""
portal_caches = self.portal.portal_caches
cache_factory = portal_caches.newContent(portal_type="Cache Factory",
cache_duration=3600)
cache_plugin1 = cache_factory.newContent(portal_type="Ram Cache")
cache_plugin1.setIntIndex(0)
cache_bag1 = cache_factory.newContent(portal_type="Cache Bag",
cache_duration=3600)
cache_bag1.setIntIndex(1)
ram_cache1 = cache_bag1.newContent(portal_type="Ram Cache")
ram_cache2 = cache_bag1.newContent(portal_type="Ram Cache")
self.tic()
portal_caches.updateCache()
# test get / set API
cache_factory.set('x', 'value_for_x')
self.assertEqual('value_for_x', cache_factory.get('x'))
# test that all cache plugin have this set
self.assertEqual('value_for_x', cache_plugin1.get('x'))
self.assertEqual('value_for_x', cache_bag1.get('x'))
# test set on individual cache plugin as this cache plugin has highest priority
# it will affect what root Cache Factory returns
cache_plugin1.set('x', 'new_value_for_x')
self.assertEqual('new_value_for_x', cache_plugin1.get('x'))
self.assertEqual('new_value_for_x', cache_factory.get('x'))
# others cache plugins will remain with old value until ...
self.assertEqual('value_for_x', cache_bag1.get('x'))
# .. root Cache Factory set will update all
cache_factory.set('x', 'new_value_for_x')
self.assertEqual(cache_factory.get('x'), cache_plugin1.get('x'))
self.assertEqual(cache_plugin1.get('x'), cache_bag1.get('x'))
self.assertEqual('new_value_for_x', cache_factory.get('x'))
def test_99_CachePluginInterface(self):
"""Test Class against Interface
"""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment