Mercurial > libervia-backend
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) |