comparison src/tools/memory.py @ 413:dd4caab17008

core: - individual parameters managed through sqlite - new asyncGetParamA method, which allow to get parameter for a not connected profile ==> individual parameters are cached in memory when the profile is connected, but must be accessed though sqlite else, and that must be done asynchronously primitivus: - profile manager updated to use asyncGetParamA /!\ still broken, need more work before being able to run again
author Goffi <goffi@goffi.org>
date Tue, 01 Nov 2011 20:39:22 +0100
parents 62b17854254e
children 32dc8b18c2ae
comparison
equal deleted inserted replaced
412:62b17854254e 413:dd4caab17008
36 SAVEFILE_PARAM_XML="/param" #xml parameters template 36 SAVEFILE_PARAM_XML="/param" #xml parameters template
37 SAVEFILE_PARAM_DATA="/param" #individual & general parameters; _ind and _gen suffixes will be added 37 SAVEFILE_PARAM_DATA="/param" #individual & general parameters; _ind and _gen suffixes will be added
38 SAVEFILE_HISTORY="/history" 38 SAVEFILE_HISTORY="/history"
39 SAVEFILE_PRIVATE="/private" #file used to store misc values (mainly for plugins) 39 SAVEFILE_PRIVATE="/private" #file used to store misc values (mainly for plugins)
40 SAVEFILE_DATABASE="/sat.db" 40 SAVEFILE_DATABASE="/sat.db"
41
42 class ProfileNotInCacheError(Exception):
43 pass
41 44
42 class Param(): 45 class Param():
43 """This class manage parameters with xml""" 46 """This class manage parameters with xml"""
44 ### TODO: add desciption in params 47 ### TODO: add desciption in params
45 48
74 77
75 def load_xml(self, file): 78 def load_xml(self, file):
76 """Load parameters template from file""" 79 """Load parameters template from file"""
77 self.dom = minidom.parse(file) 80 self.dom = minidom.parse(file)
78 81
79 def loadGenData(self, storage): 82 def loadGenData(self):
80 """Load general parameters data from storage 83 """Load general parameters data from storage
81 @param storage: xxxStorage object instance
82 @return: deferred triggered once params are loaded""" 84 @return: deferred triggered once params are loaded"""
83 return storage.loadGenParams(self.params_gen) 85 return self.storage.loadGenParams(self.params_gen)
84 86
85 def loadIndData(self, storage, profile): 87 def loadIndData(self, profile):
86 """Load individual parameters 88 """Load individual parameters
87 set self.params cache 89 set self.params cache
88 @param storage: xxxStorage object instance
89 @param profile: profile to load (*must exist*) 90 @param profile: profile to load (*must exist*)
90 @return: deferred triggered once params are loaded""" 91 @return: deferred triggered once params are loaded"""
91 self.params[profile] = {} 92 self.params[profile] = {}
92 return storage.loadIndParams(self.params, profile) 93 return self.storage.loadIndParams(self.params, profile)
93 94
94 def save_xml(self, file): 95 def save_xml(self, file):
95 """Save parameters template to xml file""" 96 """Save parameters template to xml file"""
96 with open(file, 'wb') as xml_file: 97 with open(file, 'wb') as xml_file:
97 xml_file.write(self.dom.toxml('utf-8')) 98 xml_file.write(self.dom.toxml('utf-8'))
107 108
108 #then individual params 109 #then individual params
109 with open(file+'_ind', 'w') as param_ind_pickle: 110 with open(file+'_ind', 'w') as param_ind_pickle:
110 pickle.dump(self.params, param_ind_pickle) 111 pickle.dump(self.params, param_ind_pickle)
111 112
112 def __init__(self, host): 113 def __init__(self, host, storage):
113 debug("Parameters init") 114 debug("Parameters init")
114 self.host = host 115 self.host = host
116 self.storage = storage
115 self.default_profile = None 117 self.default_profile = None
116 self.params = {} 118 self.params = {}
117 self.params_gen = {} 119 self.params_gen = {}
118 host.set_const('savefile_param_xml', SAVEFILE_PARAM_XML) 120 host.set_const('savefile_param_xml', SAVEFILE_PARAM_XML)
119 host.set_const('savefile_param_data', SAVEFILE_PARAM_DATA) 121 host.set_const('savefile_param_data', SAVEFILE_PARAM_DATA)
225 227
226 @return: attribute""" 228 @return: attribute"""
227 node = self.__getParamNode(name, category) 229 node = self.__getParamNode(name, category)
228 if not node: 230 if not node:
229 error(_("Requested param [%(name)s] in category [%(category)s] doesn't exist !") % {'name':name, 'category':category}) 231 error(_("Requested param [%(name)s] in category [%(category)s] doesn't exist !") % {'name':name, 'category':category})
230 return None 232 return ""
231 233
232 if node[0] == 'general': 234 if node[0] == 'general':
233 value = self.__getParam(None, category, name, 'general') 235 value = self.__getParam(None, category, name, 'general')
234 return value or node[1].getAttribute(attr) 236 return value or node[1].getAttribute(attr)
235 237
236 assert(node[0] == 'individual') 238 assert(node[0] == 'individual')
237 239
238 profile = self.getProfileName(profile_key) 240 profile = self.getProfileName(profile_key)
239 if not profile: 241 if not profile:
240 error(_('Requesting a param for an non-existant profile')) 242 error(_('Requesting a param for an non-existant profile'))
243 return ""
244
245 if profile not in self.params:
246 error(_('Requesting synchronous param for not connected profile'))
241 return "" 247 return ""
242 248
243 if attr == "value": 249 if attr == "value":
244 return self.__getParam(profile, category, name) or node[1].getAttribute(attr) 250 return self.__getParam(profile, category, name) or node[1].getAttribute(attr)
245 else: 251 else:
246 return node[1].getAttribute(attr) 252 return node[1].getAttribute(attr)
247 253
254 def asyncGetParamA(self, name, category, attr="value", profile_key="@DEFAULT@", callback=None, errback=None):
255 """Helper method to get a specific attribute
256 @param name: name of the parameter
257 @param category: category of the parameter
258 @param attr: name of the attribute (default: "value")
259 @param profile: owner of the param (@ALL@ for everyone)
260 @param callback: called when the profile is connected
261 @param errback: called is the connection fail"""
262 node = self.__getParamNode(name, category)
263 if not node:
264 error(_("Requested param [%(name)s] in category [%(category)s] doesn't exist !") % {'name':name, 'category':category})
265 return None
266
267 if node[0] == 'general':
268 value = self.__getParam(None, category, name, 'general')
269 callback(value or node[1].getAttribute(attr))
270 return
271
272 assert(node[0] == 'individual')
273
274 profile = self.getProfileName(profile_key)
275 if not profile:
276 error(_('Requesting a param for a non-existant profile'))
277 errback()
278 return
279
280 if attr != "value":
281 callback(node[1].getAttribute(attr))
282 return
283 default = node[1].getAttribute(attr)
284 try:
285 callback(self.__getParam(profile, category, name) or default)
286 except ProfileNotInCacheError:
287 #We have to ask data to the storage manager
288 d = self.storage.getIndParam(category, name, profile)
289 d.addCallback(callback)
290 d.addErrback(lambda x:errback())
248 291
249 def __getParam(self, profile, category, name, type='individual'): 292 def __getParam(self, profile, category, name, type='individual'):
250 """Return the param, or None if it doesn't exist 293 """Return the param, or None if it doesn't exist
251 @param profile: the profile name (not profile key, i.e. name and not something like @DEFAULT@) 294 @param profile: the profile name (not profile key, i.e. name and not something like @DEFAULT@)
252 @param category: param category 295 @param category: param category
255 if type == 'general': 298 if type == 'general':
256 if self.params_gen.has_key((category, name)): 299 if self.params_gen.has_key((category, name)):
257 return self.params_gen[(category, name)] 300 return self.params_gen[(category, name)]
258 return None #This general param has the default value 301 return None #This general param has the default value
259 assert (type == 'individual') 302 assert (type == 'individual')
260 if not self.params.has_key(profile) or not self.params[profile].has_key((category, name)): 303 if not self.params.has_key(profile):
304 raise ProfileNotInCacheError
305 if not self.params[profile].has_key((category, name)):
261 return None 306 return None
262 return self.params[profile][(category, name)] 307 return self.params[profile][(category, name)]
263 308
264 def __constructProfileXml(self, profile): 309 def __constructProfileXml(self, profile):
265 """Construct xml for asked profile, filling values when needed 310 """Construct xml for asked profile, filling values when needed
416 self.host = host 461 self.host = host
417 self.contacts={} 462 self.contacts={}
418 self.presenceStatus={} 463 self.presenceStatus={}
419 self.lastResource={} #tmp, will be refactored with bdd integration 464 self.lastResource={} #tmp, will be refactored with bdd integration
420 self.subscriptions={} 465 self.subscriptions={}
421 self.params=Param(host)
422 self.history={} #used to store chat history (key: short jid) 466 self.history={} #used to store chat history (key: short jid)
423 self.private={} #used to store private value 467 self.private={} #used to store private value
424 self.server_features={} #used to store discovery's informations 468 self.server_features={} #used to store discovery's informations
425 self.server_identities={} 469 self.server_identities={}
426 self.config = self.parseMainConf() 470 self.config = self.parseMainConf()
427 host.set_const('savefile_history', SAVEFILE_HISTORY) 471 host.set_const('savefile_history', SAVEFILE_HISTORY)
428 host.set_const('savefile_private', SAVEFILE_PRIVATE) 472 host.set_const('savefile_private', SAVEFILE_PRIVATE)
429 host.set_const('savefile_database', SAVEFILE_DATABASE) 473 host.set_const('savefile_database', SAVEFILE_DATABASE)
430 database_file = os.path.expanduser(self.getConfig('','local_dir')+ 474 database_file = os.path.expanduser(self.getConfig('','local_dir')+
431 self.host.get_const('savefile_database')) 475 self.host.get_const('savefile_database'))
476 self.storage = SqliteStorage(database_file)
477 self.params=Param(host, self.storage)
432 self.loadFiles() 478 self.loadFiles()
433 self.storage = SqliteStorage(database_file)
434 self.storage.initialized.addCallback(lambda ignore: self.load(init_defers)) 479 self.storage.initialized.addCallback(lambda ignore: self.load(init_defers))
435 480
436 defer.DeferredList(init_defers).chainDeferred(self.initialized) 481 defer.DeferredList(init_defers).chainDeferred(self.initialized)
437 482
438 def parseMainConf(self): 483 def parseMainConf(self):
504 549
505 def load(self, init_defers): 550 def load(self, init_defers):
506 """Load parameters and all memory things from db 551 """Load parameters and all memory things from db
507 @param init_defers: list of deferred to wait before parameters are loaded""" 552 @param init_defers: list of deferred to wait before parameters are loaded"""
508 #parameters data 553 #parameters data
509 init_defers.append(self.params.loadGenData(self.storage)) 554 init_defers.append(self.params.loadGenData())
510 555
511 def loadIndividualParams(self, profile_key): 556 def loadIndividualParams(self, profile_key):
512 """Load individual parameters for a profile 557 """Load individual parameters for a profile
513 @param profile_key: %(doc_profile_key)s""" 558 @param profile_key: %(doc_profile_key)s"""
514 profile = self.getProfileName(profile_key) 559 profile = self.getProfileName(profile_key)
762 return self.presenceStatus[profile] 807 return self.presenceStatus[profile]
763 808
764 def getParamA(self, name, category, attr="value", profile_key='@DEFAULT@'): 809 def getParamA(self, name, category, attr="value", profile_key='@DEFAULT@'):
765 return self.params.getParamA(name, category, attr, profile_key) 810 return self.params.getParamA(name, category, attr, profile_key)
766 811
812 def asyncGetParamA(self, name, category, attr="value", profile_key='@DEFAULT@', callback=None, errback=None):
813 return self.params.asyncGetParamA(name, category, attr, profile_key, callback, errback)
814
767 def getParamsUI(self, profile_key): 815 def getParamsUI(self, profile_key):
768 return self.params.getParamsUI(profile_key) 816 return self.params.getParamsUI(profile_key)
769 817
770 def getParams(self, profile_key): 818 def getParams(self, profile_key):
771 return self.params.getParams(profile_key) 819 return self.params.getParams(profile_key)