cache in dictionary storage

This commit is contained in:
Emmanuel Garette 2018-06-25 21:40:16 +02:00
parent f30ca3dc46
commit b10f02a8e9
6 changed files with 306 additions and 231 deletions

View File

@ -376,26 +376,26 @@ def test_cache_not_cache():
# api.property.pop('disabled') # api.property.pop('disabled')
# #
# c.cfgimpl_get_values().force_cache() # c.cfgimpl_get_values().force_cache()
# assert c.cfgimpl_get_values()._p_.get_cached() == {'u1': {None: ([], None)}, # compare(c.cfgimpl_get_values()._p_.get_cached(), {'u1': {None: ([], None)},
# 'u2': {None: (None, None)}, # 'u2': {None: (None, None)},
# 'u3': {None: ([], None)}, # 'u3': {None: ([], None)},
# 'u4': {None: (None, None)}} # 'u4': {None: (None, None)}})
# assert c.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'frozen', 'hidden', 'validator', 'warnings']), None)}, # compare(c.cfgimpl_get_settings()._p_.get_cached(), {None: {None: (set(['cache', 'frozen', 'hidden', 'validator', 'warnings']), None)},
# 'u1': {None: (set(['empty']), None)}, # 'u1': {None: (set(['empty']), None)},
# 'u2': {None: (set([]), None)}, # 'u2': {None: (set([]), None)},
# 'u3': {None: (set(['empty']), None)}, # 'u3': {None: (set(['empty']), None)},
# 'u4': {None: (set(['disabled']), None)}} # 'u4': {None: (set(['disabled']), None)}})
# api.property.read_only() # api.property.read_only()
# #
# c.cfgimpl_get_values().force_cache() # c.cfgimpl_get_values().force_cache()
# assert c.cfgimpl_get_values()._p_.get_cached() == {'u1': {None: ([], None)}, # compare(c.cfgimpl_get_values()._p_.get_cached(), {'u1': {None: ([], None)},
# 'u2': {None: (None, None)}, # 'u2': {None: (None, None)},
# 'u3': {None: ([], None)}} # 'u3': {None: ([], None)}})
# assert c.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'empty', 'everything_frozen', 'frozen', 'mandatory', 'validator', 'warnings']), None)}, # compare(c.cfgimpl_get_settings()._p_.get_cached(), {None: {None: (set(['cache', 'disabled', 'empty', 'everything_frozen', 'frozen', 'mandatory', 'validator', 'warnings']), None)},
# 'u1': {None: (set(['empty']), None)}, # 'u1': {None: (set(['empty']), None)},
# 'u2': {None: (set([]), None)}, # 'u2': {None: (set([]), None)},
# 'u3': {None: (set(['empty']), None)}, # 'u3': {None: (set(['empty']), None)},
# 'u4': {None: (set(['disabled']), None)}} # 'u4': {None: (set(['disabled']), None)}})
# #
# c.cfgimpl_get_settings().remove('cache') # c.cfgimpl_get_settings().remove('cache')
# raises(ConfigError, "c.cfgimpl_get_values().force_cache()") # raises(ConfigError, "c.cfgimpl_get_values().force_cache()")
@ -465,6 +465,15 @@ def return_value(value=None):
return value return value
def compare(calculated, expected):
assert set(calculated.keys()) == set(expected.keys())
for calculated_key in calculated:
assert set(calculated[calculated_key].keys()) == set(expected[calculated_key].keys())
for calculated_subkey in calculated[calculated_key]:
# do not check timestamp
assert calculated[calculated_key][calculated_subkey][0] == expected[calculated_key][calculated_subkey][0]
def test_cache_callback(): def test_cache_callback():
val1 = StrOption('val1', "", 'val') val1 = StrOption('val1', "", 'val')
val2 = StrOption('val2', "", callback=return_value, callback_params=Params((ParamOption(val1),)), properties=('mandatory',)) val2 = StrOption('val2', "", callback=return_value, callback_params=Params((ParamOption(val1),)), properties=('mandatory',))
@ -480,81 +489,81 @@ def test_cache_callback():
api.option.make_dict() api.option.make_dict()
#assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, #assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
# 'val1': {None: (set([]), None)}} # 'val1': {None: (set([]), None)}}
assert cfg.cfgimpl_get_values()._p_.get_cached() == {'val1': {None: ('val', None)}, compare(cfg.cfgimpl_get_values()._p_.get_cached(), {'val1': {None: ('val', None)},
'val2': {None: ('val', None)}, 'val2': {None: ('val', None)},
'val3': {None: ('yes', None)}, 'val3': {None: ('yes', None)},
'val4': {None: ('val', None)}, 'val4': {None: ('val', None)},
'val5': {None: (['yes'], None)}} 'val5': {None: (['yes'], None)}})
api.option('val1').value.set('new') api.option('val1').value.set('new')
#assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, #assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
# 'val1': {None: (set([]), None)}} # 'val1': {None: (set([]), None)}}
assert cfg.cfgimpl_get_values()._p_.get_cached() == {'val3': {None: ('yes', None)}, compare(cfg.cfgimpl_get_values()._p_.get_cached(), {'val3': {None: ('yes', None)},
'val5': {None: (['yes'], None)}} 'val5': {None: (['yes'], None)}})
api.option.make_dict() api.option.make_dict()
#assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, #assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
# 'val1': {None: (set([]), None)}} # 'val1': {None: (set([]), None)}}
assert cfg.cfgimpl_get_values()._p_.get_cached() == {'val1': {None: ('new', None)}, compare(cfg.cfgimpl_get_values()._p_.get_cached(), {'val1': {None: ('new', None)},
'val2': {None: ('new', None)}, 'val2': {None: ('new', None)},
'val3': {None: ('yes', None)}, 'val3': {None: ('yes', None)},
'val4': {None: ('new', None)}, 'val4': {None: ('new', None)},
'val5': {None: (['yes'], None)}} 'val5': {None: (['yes'], None)}})
api.option('val3').value.set('new2') api.option('val3').value.set('new2')
#assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, #assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
# 'val1': {None: (set([]), None)}, # 'val1': {None: (set([]), None)},
# 'val3': {None: (set([]), None)}} # 'val3': {None: (set([]), None)}}
assert cfg.cfgimpl_get_values()._p_.get_cached() == {'val1': {None: ('new', None)}, compare(cfg.cfgimpl_get_values()._p_.get_cached(), {'val1': {None: ('new', None)},
'val2': {None: ('new', None)}, 'val2': {None: ('new', None)},
'val4': {None: ('new', None)}, 'val4': {None: ('new', None)},
'val5': {None: (['yes'], None)}} 'val5': {None: (['yes'], None)}})
api.option.make_dict() api.option.make_dict()
#assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, #assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
# 'val1': {None: (set([]), None)}, # 'val1': {None: (set([]), None)},
# 'val3': {None: (set([]), None)}} # 'val3': {None: (set([]), None)}}
assert cfg.cfgimpl_get_values()._p_.get_cached() == {'val1': {None: ('new', None)}, compare(cfg.cfgimpl_get_values()._p_.get_cached(), {'val1': {None: ('new', None)},
'val2': {None: ('new', None)}, 'val2': {None: ('new', None)},
'val3': {None: ('new2', None)}, 'val3': {None: ('new2', None)},
'val4': {None: ('new', None)}, 'val4': {None: ('new', None)},
'val5': {None: (['yes'], None)}} 'val5': {None: (['yes'], None)}})
api.option('val4').value.set('new3') api.option('val4').value.set('new3')
#assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, #assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
# 'val1': {None: (set([]), None)}, # 'val1': {None: (set([]), None)},
# 'val3': {None: (set([]), None)}, # 'val3': {None: (set([]), None)},
# 'val4': {None: (set([]), None)}} # 'val4': {None: (set([]), None)}}
assert cfg.cfgimpl_get_values()._p_.get_cached() == {'val1': {None: ('new', None)}, compare(cfg.cfgimpl_get_values()._p_.get_cached(), {'val1': {None: ('new', None)},
'val2': {None: ('new', None)}, 'val2': {None: ('new', None)},
'val3': {None: ('new2', None)}, 'val3': {None: ('new2', None)},
'val5': {None: (['yes'], None)}} 'val5': {None: (['yes'], None)}})
api.option.make_dict() api.option.make_dict()
#assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, #assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
# 'val1': {None: (set([]), None)}, # 'val1': {None: (set([]), None)},
# 'val3': {None: (set([]), None)}, # 'val3': {None: (set([]), None)},
# 'val4': {None: (set([]), None)}} # 'val4': {None: (set([]), None)}}
assert cfg.cfgimpl_get_values()._p_.get_cached() == {'val1': {None: ('new', None)}, compare(cfg.cfgimpl_get_values()._p_.get_cached(), {'val1': {None: ('new', None)},
'val2': {None: ('new', None)}, 'val2': {None: ('new', None)},
'val3': {None: ('new2', None)}, 'val3': {None: ('new2', None)},
'val4': {None: ('new3', None)}, 'val4': {None: ('new3', None)},
'val5': {None: (['yes'], None)}} 'val5': {None: (['yes'], None)}})
api.option('val5').value.set([undefined, 'new4']) api.option('val5').value.set([undefined, 'new4'])
#assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, #assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
# 'val1': {None: (set([]), None)}, # 'val1': {None: (set([]), None)},
# 'val3': {None: (set([]), None)}, # 'val3': {None: (set([]), None)},
# 'val4': {None: (set([]), None)}, # 'val4': {None: (set([]), None)},
# 'val5': {None: (set(['empty']), None)}} # 'val5': {None: (set(['empty']), None)}}
assert cfg.cfgimpl_get_values()._p_.get_cached() == {'val1': {None: ('new', None)}, compare(cfg.cfgimpl_get_values()._p_.get_cached(), {'val1': {None: ('new', None)},
'val2': {None: ('new', None)}, 'val2': {None: ('new', None)},
'val3': {None: ('new2', None)}, 'val3': {None: ('new2', None)},
'val4': {None: ('new3', None)}} 'val4': {None: ('new3', None)}})
api.option.make_dict() api.option.make_dict()
#assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, #assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
# 'val1': {None: (set([]), None)}, # 'val1': {None: (set([]), None)},
# 'val3': {None: (set([]), None)}, # 'val3': {None: (set([]), None)},
# 'val4': {None: (set([]), None)}, # 'val4': {None: (set([]), None)},
# 'val5': {None: (set(['empty']), None)}} # 'val5': {None: (set(['empty']), None)}}
assert cfg.cfgimpl_get_values()._p_.get_cached() == {'val1': {None: ('new', None)}, compare(cfg.cfgimpl_get_values()._p_.get_cached(), {'val1': {None: ('new', None)},
'val2': {None: ('new', None)}, 'val2': {None: ('new', None)},
'val3': {None: ('new2', None)}, 'val3': {None: ('new2', None)},
'val4': {None: ('new3', None)}, 'val4': {None: ('new3', None)},
'val5': {None: (['yes', 'new4'], None)}} 'val5': {None: (['yes', 'new4'], None)}})
def test_cache_master_and_slaves_master(): def test_cache_master_and_slaves_master():
@ -588,16 +597,16 @@ def test_cache_master_and_slaves_master():
assert cfg.cfgimpl_get_settings()._p_.get_cached() == {} assert cfg.cfgimpl_get_settings()._p_.get_cached() == {}
assert cfg.cfgimpl_get_values()._p_.get_cached() == {} assert cfg.cfgimpl_get_values()._p_.get_cached() == {}
else: else:
assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (global_props, None)}, compare(cfg.cfgimpl_get_settings()._p_.get_cached(), {None: {None: (global_props, None)},
'val1': {None: (val1_props, None)}, 'val1': {None: (val1_props, None)},
'val1.val1': {None: (val1_val1_props, None)}, 'val1.val1': {None: (val1_val1_props, None)},
'val1.val2': {idx_val2: (val1_val2_props, None)}} 'val1.val2': {idx_val2: (val1_val2_props, None)}})
# len is 0 so don't get any value # len is 0 so don't get any value
assert cfg.cfgimpl_get_values()._p_.get_cached() == {'val1.val1': {None: ([], None)}} compare(cfg.cfgimpl_get_values()._p_.get_cached(), {'val1.val1': {None: ([], None)}})
# #
api.option('val1.val1').value.set([undefined]) api.option('val1.val1').value.set([undefined])
assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, compare(cfg.cfgimpl_get_settings()._p_.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
'val1': {None: (set([]), None)}} 'val1': {None: (set([]), None)}})
assert cfg.cfgimpl_get_values()._p_.get_cached() == {} assert cfg.cfgimpl_get_values()._p_.get_cached() == {}
api.option.make_dict() api.option.make_dict()
if TIRAMISU_VERSION == 2: if TIRAMISU_VERSION == 2:
@ -608,17 +617,17 @@ def test_cache_master_and_slaves_master():
idx_val2 = 0 idx_val2 = 0
val_val2 = None val_val2 = None
val_val2_props = {idx_val2: (val1_val2_props, None)} val_val2_props = {idx_val2: (val1_val2_props, None)}
assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (global_props, None)}, compare(cfg.cfgimpl_get_settings()._p_.get_cached(), {None: {None: (global_props, None)},
'val1': {None: (val1_props, None)}, 'val1': {None: (val1_props, None)},
'val1.val1': {None: (val1_val1_props, None)}, 'val1.val1': {None: (val1_val1_props, None)},
'val1.val2': val_val2_props} 'val1.val2': val_val2_props})
assert cfg.cfgimpl_get_values()._p_.get_cached() == {'val1.val1': {None: ([None], None)}, compare(cfg.cfgimpl_get_values()._p_.get_cached(), {'val1.val1': {None: ([None], None)},
'val1.val2': {idx_val2: (val_val2, None)}} 'val1.val2': {idx_val2: (val_val2, None)}})
api.option('val1.val1').value.set([undefined, undefined]) api.option('val1.val1').value.set([undefined, undefined])
api.option.make_dict() api.option.make_dict()
api.option('val1.val2', 1).value.set('oui') api.option('val1.val2', 1).value.set('oui')
assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, compare(cfg.cfgimpl_get_settings()._p_.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
'val1': {None: (set([]), None)}} 'val1': {None: (set([]), None)}})
assert cfg.cfgimpl_get_values()._p_.get_cached() == {} assert cfg.cfgimpl_get_values()._p_.get_cached() == {}
if TIRAMISU_VERSION == 2: if TIRAMISU_VERSION == 2:
val1_val2_props = {None: (set([]), None), 0: (set([]), None), 1: (set([]), None)} val1_val2_props = {None: (set([]), None), 0: (set([]), None), 1: (set([]), None)}
@ -665,14 +674,14 @@ def test_cache_master_callback():
assert cfg.cfgimpl_get_settings()._p_.get_cached() == {} assert cfg.cfgimpl_get_settings()._p_.get_cached() == {}
assert cfg.cfgimpl_get_values()._p_.get_cached() == {} assert cfg.cfgimpl_get_values()._p_.get_cached() == {}
else: else:
assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (global_props, None)}, compare(cfg.cfgimpl_get_settings()._p_.get_cached(), {None: {None: (global_props, None)},
'val1': {None: (val1_props, None)}, 'val1': {None: (val1_props, None)},
'val1.val1': {None: (val1_val1_props, None)}, 'val1.val1': {None: (val1_val1_props, None)},
'val1.val2': {None: (val1_val2_props, None)}} 'val1.val2': {None: (val1_val2_props, None)}})
assert cfg.cfgimpl_get_values()._p_.get_cached() == {'val1.val1': {None: ([], None)}} compare(cfg.cfgimpl_get_values()._p_.get_cached(), {'val1.val1': {None: ([], None)}})
api.option('val1.val1').value.set([undefined]) api.option('val1.val1').value.set([undefined])
assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, compare(cfg.cfgimpl_get_settings()._p_.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
'val1': {None: (set([]), None)}} 'val1': {None: (set([]), None)}})
assert cfg.cfgimpl_get_values()._p_.get_cached() == {} assert cfg.cfgimpl_get_values()._p_.get_cached() == {}
api.option.make_dict() api.option.make_dict()
@ -694,35 +703,35 @@ def test_cache_master_callback():
# api.property.read_write() # api.property.read_write()
# api.property.pop('expire') # api.property.pop('expire')
# api.option.make_dict() # api.option.make_dict()
# assert cfg.cfgimpl_get_values()._p_.get_cached() == {'int': {None: ([0], None)}, # compare(cfg.cfgimpl_get_values()._p_.get_cached(), {'int': {None: ([0], None)},
# 'str': {None: ([None], None)}, # 'str': {None: ([None], None)},
# 'str1': {None: ([None], None)}} # 'str1': {None: ([None], None)}})
# assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, # conver(cfg.cfgimpl_get_settings()._p_.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
# 'int': {None: (set(['empty']), None)}, # 'int': {None: (set(['empty']), None)},
# 'str': {None: (set([]), None), 0: (set([]), None)}, # 'str': {None: (set([]), None), 0: (set([]), None)},
# 'str1': {None: (set([]), None), 0: (set([]), None)}} # 'str1': {None: (set([]), None), 0: (set([]), None)}})
# api.option('int').value.set([0, 1]) # api.option('int').value.set([0, 1])
# api.option.make_dict() # api.option.make_dict()
# assert cfg.cfgimpl_get_values()._p_.get_cached() == {'int': {None: ([0, 1], None)}, # compare(cfg.cfgimpl_get_values()._p_.get_cached(), {'int': {None: ([0, 1], None)},
# 'str': {None: ([None, None], None)}, # 'str': {None: ([None, None], None)},
# 'str1': {None: ([None, None], None)}} # 'str1': {None: ([None, None], None)}})
# assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, # compare(cfg.cfgimpl_get_settings()._p_.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
# 'int': {None: (set(['empty']), None)}, # 'int': {None: (set(['empty']), None)},
# 'str': {None: (set([]), None), 0: (set([]), None), 1: (set([]), None)}, # 'str': {None: (set([]), None), 0: (set([]), None), 1: (set([]), None)},
# 'str1': {None: (set([]), None), 0: (set([]), None), 1: (set([]), None)}} # 'str1': {None: (set([]), None), 0: (set([]), None), 1: (set([]), None)}})
# #
# api.option('str', 1).value.set('1') # api.option('str', 1).value.set('1')
# api.option.make_dict() # api.option.make_dict()
# assert set(cfg.cfgimpl_get_values()._p_.get_cached().keys()) == set(['int', 'str', 'str1']) # assert set(cfg.cfgimpl_get_values()._p_.get_cached().keys()) == set(['int', 'str', 'str1'])
# assert cfg.cfgimpl_get_values()._p_.get_cached()['int'] == {None: ([0, 1], None)} # compare(cfg.cfgimpl_get_values()._p_.get_cached()['int'], {None: ([0, 1], None)})
# assert cfg.cfgimpl_get_values()._p_.get_cached()['str'] == {None: ([None, '1'], None)} # compare(cfg.cfgimpl_get_values()._p_.get_cached()['str'], {None: ([None, '1'], None)})
# assert cfg.cfgimpl_get_values()._p_.get_cached()['str1'][None][0][0] == None # assert cfg.cfgimpl_get_values()._p_.get_cached()['str1'][None][0][0] == None
# raises(PropertiesOptionError, "cfg.cfgimpl_get_values()._p_.get_cached()['str1'][None][0][1]") # raises(PropertiesOptionError, "cfg.cfgimpl_get_values()._p_.get_cached()['str1'][None][0][1]")
# assert cfg.cfgimpl_get_values()._p_.get_cached()['str1'][None][1] == None # assert cfg.cfgimpl_get_values()._p_.get_cached()['str1'][None][1] == None
# assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, # compare(cfg.cfgimpl_get_settings()._p_.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
# 'int': {None: (set(['empty']), None)}, # 'int': {None: (set(['empty']), None)},
# 'str': {None: (set([]), None), 0: (set([]), None), 1: (set([]), None)}, # 'str': {None: (set([]), None), 0: (set([]), None), 1: (set([]), None)},
# 'str1': {None: (set([]), None), 0: (set([]), None), 1: (set(['hidden']), None)}} # 'str1': {None: (set([]), None), 0: (set([]), None), 1: (set(['hidden']), None)}})
# api.property.read_only() # api.property.read_only()
# assert cfg.cfgimpl_get_values()._p_.get_cached() == {} # assert cfg.cfgimpl_get_values()._p_.get_cached() == {}
# assert cfg.cfgimpl_get_settings()._p_.get_cached() == {} # assert cfg.cfgimpl_get_settings()._p_.get_cached() == {}
@ -736,7 +745,6 @@ def test_cache_master_callback():
# 'str1': {None: (set([]), None), 0: (set([]), None), 1: (set(['hidden']), None)}} # 'str1': {None: (set([]), None), 0: (set([]), None), 1: (set(['hidden']), None)}}
def test_cache_requires(): def test_cache_requires():
a = BoolOption('activate_service', '', True) a = BoolOption('activate_service', '', True)
b = IPOption('ip_address_service', '', b = IPOption('ip_address_service', '',
@ -747,47 +755,46 @@ def test_cache_requires():
api.property.read_write() api.property.read_write()
if TIRAMISU_VERSION == 2: if TIRAMISU_VERSION == 2:
api.property.pop('expire') api.property.pop('expire')
#assert c.cfgimpl_get_settings()._p_.get_cached() == {}
assert c.cfgimpl_get_values()._p_.get_cached() == {} assert c.cfgimpl_get_values()._p_.get_cached() == {}
assert api.option('ip_address_service').value.get() == None assert api.option('ip_address_service').value.get() == None
assert c.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, compare(c.cfgimpl_get_settings()._p_.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
'activate_service': {None: (set([]), None)}, 'activate_service': {None: (set([]), None)},
'ip_address_service': {None: (set([]), None)}} 'ip_address_service': {None: (set([]), None)}})
if TIRAMISU_VERSION == 2: if TIRAMISU_VERSION == 2:
assert c.cfgimpl_get_values()._p_.get_cached() == {'ip_address_service': {None: (None, None)}} assert c.cfgimpl_get_values()._p_.get_cached() == {'ip_address_service': {None: (None, None)}}
else: else:
assert c.cfgimpl_get_values()._p_.get_cached() == {'ip_address_service': {None: (None, None)}, compare(c.cfgimpl_get_values()._p_.get_cached(), {'ip_address_service': {None: (None, None)},
'activate_service': {None: (True, None)}} 'activate_service': {None: (True, None)}})
api.option.make_dict() api.option.make_dict()
assert c.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, compare(c.cfgimpl_get_settings()._p_.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
'activate_service': {None: (set([]), None)}, 'activate_service': {None: (set([]), None)},
'ip_address_service': {None: (set([]), None)}} 'ip_address_service': {None: (set([]), None)}})
assert c.cfgimpl_get_values()._p_.get_cached() == {'ip_address_service': {None: (None, None)}, compare(c.cfgimpl_get_values()._p_.get_cached(), {'ip_address_service': {None: (None, None)},
'activate_service': {None: (True, None)}} 'activate_service': {None: (True, None)}})
api.option('ip_address_service').value.set('1.1.1.1') api.option('ip_address_service').value.set('1.1.1.1')
assert c.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, compare(c.cfgimpl_get_settings()._p_.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
'activate_service': {None: (set([]), None)}} 'activate_service': {None: (set([]), None)}})
assert c.cfgimpl_get_values()._p_.get_cached() == {'activate_service': {None: (True, None)}} compare(c.cfgimpl_get_values()._p_.get_cached(), {'activate_service': {None: (True, None)}})
api.option.make_dict() api.option.make_dict()
assert c.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, compare(c.cfgimpl_get_settings()._p_.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
'activate_service': {None: (set([]), None)}, 'activate_service': {None: (set([]), None)},
'ip_address_service': {None: (set([]), None)}} 'ip_address_service': {None: (set([]), None)}})
assert c.cfgimpl_get_values()._p_.get_cached() == {'ip_address_service': {None: ('1.1.1.1', None)}, compare(c.cfgimpl_get_values()._p_.get_cached(), {'ip_address_service': {None: ('1.1.1.1', None)},
'activate_service': {None: (True, None)}} 'activate_service': {None: (True, None)}})
api.option('activate_service').value.set(False) api.option('activate_service').value.set(False)
assert c.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}} compare(c.cfgimpl_get_settings()._p_.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}})
assert c.cfgimpl_get_values()._p_.get_cached() == {} assert c.cfgimpl_get_values()._p_.get_cached() == {}
api.option.make_dict() api.option.make_dict()
assert c.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, compare(c.cfgimpl_get_settings()._p_.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
'activate_service': {None: (set([]), None)}, 'activate_service': {None: (set([]), None)},
'ip_address_service': {None: (set(['disabled']), None)}} 'ip_address_service': {None: (set(['disabled']), None)}})
assert c.cfgimpl_get_values()._p_.get_cached() == {'activate_service': {None: (False, None)}} compare(c.cfgimpl_get_values()._p_.get_cached(), {'activate_service': {None: (False, None)}})
def test_cache_global_properties(): def test_cache_global_properties():
@ -798,30 +805,27 @@ def test_cache_global_properties():
c = Config(od) c = Config(od)
api = getapi(c) api = getapi(c)
api.property.read_write() api.property.read_write()
if TIRAMISU_VERSION == 2:
api.property.pop('expire')
#assert c.cfgimpl_get_settings()._p_.get_cached() == {}
assert c.cfgimpl_get_values()._p_.get_cached() == {} assert c.cfgimpl_get_values()._p_.get_cached() == {}
assert api.option('ip_address_service').value.get() == None assert api.option('ip_address_service').value.get() == None
assert c.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, compare(c.cfgimpl_get_settings()._p_.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
'activate_service': {None: (set([]), None)}, 'activate_service': {None: (set([]), None)},
'ip_address_service': {None: (set([]), None)}} 'ip_address_service': {None: (set([]), None)}})
if TIRAMISU_VERSION == 2: if TIRAMISU_VERSION == 2:
assert c.cfgimpl_get_values()._p_.get_cached() == {'ip_address_service': {None: (None, None)}} assert c.cfgimpl_get_values()._p_.get_cached() == {'ip_address_service': {None: (None, None)}}
else: else:
assert c.cfgimpl_get_values()._p_.get_cached() == {'ip_address_service': {None: (None, None)}, compare(c.cfgimpl_get_values()._p_.get_cached(), {'ip_address_service': {None: (None, None)},
'activate_service': {None: (True, None)}} 'activate_service': {None: (True, None)}})
api.property.pop('disabled') api.property.pop('disabled')
assert api.option('ip_address_service').value.get() == None assert api.option('ip_address_service').value.get() == None
assert c.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'frozen', 'hidden', 'validator', 'warnings']), None)}, compare(c.cfgimpl_get_settings()._p_.get_cached(), {None: {None: (set(['cache', 'frozen', 'hidden', 'validator', 'warnings']), None)},
'activate_service': {None: (set([]), None)}, 'activate_service': {None: (set([]), None)},
'ip_address_service': {None: (set([]), None)}} 'ip_address_service': {None: (set([]), None)}})
api.property.add('test') api.property.add('test')
assert api.option('ip_address_service').value.get() == None assert api.option('ip_address_service').value.get() == None
assert c.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'frozen', 'hidden', 'validator', 'warnings', 'test']), None)}, compare(c.cfgimpl_get_settings()._p_.get_cached(), {None: {None: (set(['cache', 'frozen', 'hidden', 'validator', 'warnings', 'test']), None)},
'activate_service': {None: (set([]), None)}, 'activate_service': {None: (set([]), None)},
'ip_address_service': {None: (set([]), None)}} 'ip_address_service': {None: (set([]), None)}})
def test_callback_value_incr(): def test_callback_value_incr():

View File

@ -166,12 +166,15 @@ class CacheOptionDescription(BaseOption):
if option.impl_is_master_slaves('slave'): if option.impl_is_master_slaves('slave'):
# problem with index # problem with index
raise ConfigError(_('the slave "{0}" cannot have ' raise ConfigError(_('the slave "{0}" cannot have '
'"force_store_value" property').format(option.impl_get_display_name())) '"force_store_value" property').format(
option.impl_get_display_name()))
if option.issubdyn(): if option.issubdyn():
raise ConfigError(_('the dynoption "{0}" cannot have ' raise ConfigError(_('the dynoption "{0}" cannot have '
'"force_store_value" property').format(option.impl_get_display_name())) '"force_store_value" property').format(
option.impl_get_display_name()))
if not values._p_.hasvalue(subpath): if not values._p_.hasvalue(subpath):
config_bag = ConfigBag(config=context, option=option) config_bag = ConfigBag(config=context, option=option)
config_bag.properties = frozenset()
value = values.getvalue(subpath, value = values.getvalue(subpath,
None, None,
config_bag) config_bag)

View File

@ -15,7 +15,6 @@
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# ____________________________________________________________ # ____________________________________________________________
from time import time
from copy import copy from copy import copy
from logging import getLogger from logging import getLogger
import weakref import weakref
@ -337,27 +336,24 @@ class Settings(object):
# get properties and permissive methods # get properties and permissive methods
def get_context_properties(self): def get_context_properties(self):
ntime = int(time())
if self._p_.hascache(None,
None):
is_cached, props = self._p_.getcache(None, is_cached, props = self._p_.getcache(None,
ntime, None,
None) None,
else: None,
is_cached = False None,
if not is_cached or 'cache' not in props: 'context_props')
if not is_cached:
meta = self._getcontext().cfgimpl_get_meta() meta = self._getcontext().cfgimpl_get_meta()
if meta is None: if meta is None:
props = self._p_.getproperties(None, props = self._p_.getproperties(None,
default_properties) default_properties)
else: else:
props = meta.cfgimpl_get_settings().get_context_properties() props = meta.cfgimpl_get_settings().get_context_properties()
if 'cache' in props: self._p_.setcache(None,
if 'expire' in props: None,
ntime = ntime + expires_time props,
else: props,
ntime = None None)
self._p_.setcache(None, props, ntime, None)
return props return props
def getproperties(self, def getproperties(self,
@ -371,19 +367,17 @@ class Settings(object):
if opt.impl_is_symlinkoption(): if opt.impl_is_symlinkoption():
opt = opt.impl_getopt() opt = opt.impl_getopt()
path = opt.impl_getpath(self._getcontext()) path = opt.impl_getpath(self._getcontext())
is_cached = False
if apply_requires and config_bag.setting_properties is not None: if apply_requires:
if 'cache' in config_bag.setting_properties and \ props = config_bag.setting_properties
'expire' in config_bag.setting_properties:
ntime = int(time())
else:
ntime = None
if 'cache' in config_bag.setting_properties and self._p_.hascache(path,
index):
is_cached, props = self._p_.getcache(path, is_cached, props = self._p_.getcache(path,
ntime, expires_time,
index) index,
props,
None,
'self_props')
else:
is_cached = False
if not is_cached: if not is_cached:
meta = self._getcontext().cfgimpl_get_meta() meta = self._getcontext().cfgimpl_get_meta()
if meta is None: if meta is None:
@ -403,14 +397,12 @@ class Settings(object):
opt.impl_get_display_name()) opt.impl_get_display_name())
props -= self.getpermissive(opt, props -= self.getpermissive(opt,
path) path)
if apply_requires and config_bag.setting_properties is not None and \ if apply_requires:
'cache' in config_bag.setting_properties:
if 'expire' in config_bag.setting_properties:
ntime = ntime + expires_time
self._p_.setcache(path, self._p_.setcache(path,
index,
props, props,
ntime, config_bag.setting_properties,
index) config_bag.setting_properties)
return props return props
def get_context_permissive(self): def get_context_permissive(self):
@ -599,6 +591,7 @@ class Settings(object):
"""save properties for specified path """save properties for specified path
(never save properties if same has option properties) (never save properties if same has option properties)
""" """
# should have index !!!
if self._getcontext().cfgimpl_get_meta() is not None: if self._getcontext().cfgimpl_get_meta() is not None:
raise ConfigError(_('cannot change property with metaconfig')) raise ConfigError(_('cannot change property with metaconfig'))
if path is not None and config_bag.option.impl_getrequires() is not None: if path is not None and config_bag.option.impl_getrequires() is not None:

View File

@ -0,0 +1,41 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2018 Team tiramisu (see AUTHORS for all contributors)
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by the
# Free Software Foundation, either version 3 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 Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# ____________________________________________________________
class Cache(object):
__slots__ = ('_cache',)
def __init__(self):
self._cache = {}
def _setcache(self, path, index, val, time):
self._cache.setdefault(path, {})[index] = (val, int(time))
def _getcache(self, path, index):
values = self._cache.get(path)
if values is None:
return
return values.get(index)
def _delcache(self, path):
del self._cache[path]
def _get_cached(self):
return self._cache
def _reset_all_cache(self):
self._cache.clear()

View File

@ -15,6 +15,10 @@
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# ____________________________________________________________ # ____________________________________________________________
from time import time
from .dictionary.cache import Cache as DictCache
def _display_classname(obj): def _display_classname(obj):
return(obj.__class__.__name__.lower()) return(obj.__class__.__name__.lower())
@ -22,31 +26,78 @@ DEBUG = False
#DEBUG = True #DEBUG = True
class Cache(object): class Cache(DictCache):
__slots__ = ('_cache', '_storage') __slots__ = ('_storage',)
key_is_path = False
def __init__(self, storage): def __init__(self, storage):
self._cache = {}
self._storage = storage self._storage = storage
super().__init__()
def setcache(self, path, val, time, index): def setcache(self, path, index, val, props, self_props):
"""add val in cache for a specified path """add val in cache for a specified path
if slave, add index if slave, add index
""" """
if props is None or 'cache' in props or \
(self_props is not None and 'cache' in self_props):
if DEBUG: if DEBUG:
print('setcache', path, val, _display_classname(self), id(self)) print('setcache {} with index {} and value {} in {} ({})'.format(path, index, val,
self._cache.setdefault(path, {})[index] = (val, time) _display_classname(self),
id(self)))
self._setcache(path, index, val, time())
if DEBUG:
print('not setcache {} with index {} and value {} in {} ({})'.format(path,
index,
val,
_display_classname(self),
id(self)))
return
def getcache(self, path, exp, index): def getcache(self,
value, created = self._cache[path][index] path,
if created is None or exp is None or exp <= created: expires_time,
index,
props,
self_props,
type_):
no_cache = False, None
if props is None or 'cache' in props:
indexed = self._getcache(path, index)
if indexed is None:
return no_cache
value, timestamp = indexed
if type_ == 'context_props':
# cached value is settings properties so value is props
props = value
elif type_ == 'self_props':
# if self_props is None, so cached value is self properties
# so value is self_props
self_props = value
# recheck "cache" value
if props is None or 'cache' in props or (self_props is not None and 'cache' in props):
if expires_time and timestamp and \
(props is not None and 'expire' in props or \
self_props is not None and 'expire' in self_props):
ntime = int(time())
if timestamp + expires_time >= ntime:
if DEBUG: if DEBUG:
print('getcache in cache', path, value, _display_classname(self), id(self), index, exp) print('getcache in cache (1)', path, value, _display_classname(self),
id(self), index)
return True, value
else:
if DEBUG:
print('getcache expired value for path {} < {}'.format(
timestamp + expires_time, ntime))
# if expired, remove from cache
self.delcache(path)
else:
if DEBUG:
print('getcache in cache (2)', path, value, _display_classname(self),
id(self), index)
return True, value return True, value
if DEBUG: if DEBUG:
print('getcache not in cache') print('getcache {} with index {} not in {} cache'.format(path, index,
return False, None # pragma: no cover _display_classname(self)))
return no_cache
def delcache(self, path): def delcache(self, path):
"""remove cache for a specified path """remove cache for a specified path
@ -54,36 +105,19 @@ class Cache(object):
if DEBUG: if DEBUG:
print('delcache', path, _display_classname(self), id(self)) print('delcache', path, _display_classname(self), id(self))
if path in self._cache: if path in self._cache:
del self._cache[path] self._delcache(path)
def hascache(self, path, index):
""" path is in the cache
:param path: the path's option
"""
if DEBUG:
print('hascache', path, _display_classname(self), id(self))
return path in self._cache and index in self._cache[path]
def reset_expired_cache(self, exp):
cache_keys = list(self._cache.keys())
for key in cache_keys:
key_cache_keys = list(self._cache[key].keys())
for index in key_cache_keys:
val, created = self._cache[key][index]
if created is not None and exp > created:
del(self._cache[key][index])
if self._cache[key] == {}:
del(self._cache[key])
def reset_all_cache(self): def reset_all_cache(self):
"empty the cache" "empty the cache"
if DEBUG: if DEBUG:
print('reset_all_cache', _display_classname(self), id(self)) print('reset_all_cache', _display_classname(self), id(self))
self._cache.clear() self._reset_all_cache()
def get_cached(self): def get_cached(self):
"""return all values in a dictionary """return all values in a dictionary
please only use it in test purpose
example: {'path1': {'index1': ('value1', 'time1')}, 'path2': {'index2': ('value2', 'time2', )}} example: {'path1': {'index1': ('value1', 'time1')}, 'path2': {'index2': ('value2', 'time2', )}}
""" """
return self._cache if DEBUG:
print('get_chached', self._cache)
return self._get_cached()

View File

@ -15,7 +15,6 @@
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# ____________________________________________________________ # ____________________________________________________________
from time import time
import weakref import weakref
from .error import ConfigError, PropertiesOptionError from .error import ConfigError, PropertiesOptionError
from .setting import owners, expires_time, undefined, forbidden_owners from .setting import owners, expires_time, undefined, forbidden_owners
@ -81,19 +80,14 @@ class Values(object):
:returns: value :returns: value
""" """
ntime = None
# try to retrive value in cache # try to retrive value in cache
setting_properties = config_bag.setting_properties setting_properties = config_bag.setting_properties
is_cached = False
if setting_properties and 'cache' in setting_properties and \
self._p_.hascache(path,
index):
if 'expire' in setting_properties or \
(config_bag.properties and 'expire' in config_bag.properties):
ntime = int(time())
is_cached, value = self._p_.getcache(path, is_cached, value = self._p_.getcache(path,
ntime, expires_time,
index) index,
setting_properties,
config_bag.properties,
'value')
if not is_cached: if not is_cached:
# no cached value so get value # no cached value so get value
@ -115,13 +109,12 @@ class Values(object):
check_error=False, check_error=False,
config_bag=config_bag) config_bag=config_bag)
# store value in cache # store value in cache
if not is_cached and \ if not is_cached:
setting_properties and 'cache' in setting_properties: self._p_.setcache(path,
if 'expire' in setting_properties or 'expire' in config_bag.properties: index,
if ntime is None: value,
ntime = int(time()) setting_properties,
ntime = ntime + expires_time config_bag.properties)
self._p_.setcache(path, value, ntime, index)
# and return it # and return it
return value return value
@ -198,9 +191,15 @@ class Values(object):
context = self._getcontext() context = self._getcontext()
opt = config_bag.option opt = config_bag.option
def _reset_cache(_value): def _reset_cache(_value):
if self._p_.hascache(path, index): is_cache, cache_value = self._p_.getcache(path,
is_cache, cache_value = self._p_.getcache(path, None, index) expires_time,
index,
config_bag.setting_properties,
config_bag.properties,
'value')
if is_cache and cache_value == _value: if is_cache and cache_value == _value:
# calculation return same value as previous value,
# so do not invalidate cache
return return
# calculated value is a new value, so reset cache # calculated value is a new value, so reset cache
context.cfgimpl_reset_cache(opt, context.cfgimpl_reset_cache(opt,
@ -389,6 +388,7 @@ class Values(object):
config_bag, config_bag,
commit=True): commit=True):
self._getcontext().cfgimpl_reset_cache(config_bag.option, self._getcontext().cfgimpl_reset_cache(config_bag.option,
path, path,
config_bag) config_bag)