Mercurial > libervia-backend
comparison src/tools/memory.py @ 412:62b17854254e
database integration: first draft
- using SQLite as backend
/!\ Not finished yet, break execution. SàT CAN'T LAUNCH PROPERLY IN THE CURRENT STATE
author | Goffi <goffi@goffi.org> |
---|---|
date | Sun, 30 Oct 2011 23:13:40 +0100 |
parents | 3ed53803b3b3 |
children | dd4caab17008 |
comparison
equal
deleted
inserted
replaced
411:b109a79ac72f | 412:62b17854254e |
---|---|
25 import time | 25 import time |
26 import cPickle as pickle | 26 import cPickle as pickle |
27 from ConfigParser import SafeConfigParser, NoOptionError, NoSectionError | 27 from ConfigParser import SafeConfigParser, NoOptionError, NoSectionError |
28 from xml.dom import minidom | 28 from xml.dom import minidom |
29 from logging import debug, info, warning, error | 29 from logging import debug, info, warning, error |
30 import pdb | |
31 from twisted.internet import defer | 30 from twisted.internet import defer |
32 from twisted.words.protocols.jabber import jid | 31 from twisted.words.protocols.jabber import jid |
33 from sat.tools.xml_tools import paramsXml2xmlUI | 32 from sat.tools.xml_tools import paramsXml2xmlUI |
34 from sat.core.default_config import default_config | 33 from sat.core.default_config import default_config |
34 from sat.tools.sqlite import SqliteStorage | |
35 | 35 |
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 | 41 |
41 class Param(): | 42 class Param(): |
42 """This class manage parameters with xml""" | 43 """This class manage parameters with xml""" |
43 ### TODO: add desciption in params | 44 ### TODO: add desciption in params |
44 | 45 |
73 | 74 |
74 def load_xml(self, file): | 75 def load_xml(self, file): |
75 """Load parameters template from file""" | 76 """Load parameters template from file""" |
76 self.dom = minidom.parse(file) | 77 self.dom = minidom.parse(file) |
77 | 78 |
78 def load_data(self, file): | 79 def loadGenData(self, storage): |
79 """Load parameters data from file""" | 80 """Load general parameters data from storage |
80 file_ind = file + '_ind' | 81 @param storage: xxxStorage object instance |
81 file_gen = file + '_gen' | 82 @return: deferred triggered once params are loaded""" |
82 | 83 return storage.loadGenParams(self.params_gen) |
83 if os.path.exists(file_gen): | 84 |
84 try: | 85 def loadIndData(self, storage, profile): |
85 with open(file_gen, 'r') as file_gen_pickle: | 86 """Load individual parameters |
86 self.params_gen=pickle.load(file_gen_pickle) | 87 set self.params cache |
87 debug(_("general params data loaded")) | 88 @param storage: xxxStorage object instance |
88 except: | 89 @param profile: profile to load (*must exist*) |
89 error (_("Can't load general params data !")) | 90 @return: deferred triggered once params are loaded""" |
90 | 91 self.params[profile] = {} |
91 if os.path.exists(file_ind): | 92 return storage.loadIndParams(self.params, profile) |
92 try: | |
93 with open(file_ind, 'r') as file_ind_pickle: | |
94 self.params=pickle.load(file_ind_pickle) | |
95 debug(_("individual params data loaded")) | |
96 except: | |
97 error (_("Can't load individual params data !")) | |
98 | 93 |
99 def save_xml(self, file): | 94 def save_xml(self, file): |
100 """Save parameters template to xml file""" | 95 """Save parameters template to xml file""" |
101 with open(file, 'wb') as xml_file: | 96 with open(file, 'wb') as xml_file: |
102 xml_file.write(self.dom.toxml('utf-8')) | 97 xml_file.write(self.dom.toxml('utf-8')) |
122 self.params_gen = {} | 117 self.params_gen = {} |
123 host.set_const('savefile_param_xml', SAVEFILE_PARAM_XML) | 118 host.set_const('savefile_param_xml', SAVEFILE_PARAM_XML) |
124 host.set_const('savefile_param_data', SAVEFILE_PARAM_DATA) | 119 host.set_const('savefile_param_data', SAVEFILE_PARAM_DATA) |
125 host.registerGeneralCB("registerNewAccount", host.registerNewAccountCB) | 120 host.registerGeneralCB("registerNewAccount", host.registerNewAccountCB) |
126 | 121 |
127 def getProfilesList(self): | |
128 return self.params.keys() | |
129 | |
130 def createProfile(self, name): | 122 def createProfile(self, name): |
131 """Create a new profile | 123 """Create a new profile |
132 @param name: Name of the profile""" | 124 @param name: Name of the profile""" |
133 if self.params.has_key(name): | 125 if self.storage.hasProfile(name): |
134 info (_('The profile name already exists')) | 126 info (_('The profile name already exists')) |
135 return 1 | 127 return True |
136 if not self.host.trigger.point("ProfileCreation", name): | 128 if not self.host.trigger.point("ProfileCreation", name): |
137 return 0 | 129 return False |
138 self.params[name]={} | 130 self.params[name]={} |
139 return 0 | 131 return False |
140 | 132 |
141 def deleteProfile(self, name): | 133 def deleteProfile(self, name): |
142 """Delete an existing profile | 134 """Delete an existing profile |
143 @param name: Name of the profile""" | 135 @param name: Name of the profile""" |
144 if not self.params.has_key(name): | 136 if not self.storage.hasProfile(name): |
145 error (_('Trying to delete an unknown profile')) | 137 error (_('Trying to delete an unknown profile')) |
146 return 1 | 138 return True |
147 del self.params[name] | 139 del self.params[name] |
148 return 0 | 140 return False |
149 | 141 |
150 def getProfileName(self, profile_key): | 142 def getProfileName(self, profile_key): |
151 """return profile according to profile_key | 143 """return profile according to profile_key |
152 @param profile_key: profile name or key which can be | 144 @param profile_key: profile name or key which can be |
153 @ALL@ for all profiles | 145 @ALL@ for all profiles |
157 if not self.params: | 149 if not self.params: |
158 return "" | 150 return "" |
159 default = self.host.memory.getPrivate('Profile_default') | 151 default = self.host.memory.getPrivate('Profile_default') |
160 if not default or not default in self.params: | 152 if not default or not default in self.params: |
161 info(_('No default profile, returning first one')) #TODO: manage real default profile | 153 info(_('No default profile, returning first one')) #TODO: manage real default profile |
162 default = self.params.keys()[0] | 154 default = self.getProfilesList()[0] |
163 self.host.memory.setPrivate('Profile_default', default) | 155 self.host.memory.setPrivate('Profile_default', default) |
164 return default #FIXME: temporary, must use real default value, and fallback to first one if it doesn't exists | 156 return default #FIXME: temporary, must use real default value, and fallback to first one if it doesn't exists |
165 if not self.params.has_key(profile_key): | 157 if not self.storage.hasProfile(profile_key): |
166 info (_('Trying to access an unknown profile')) | 158 info (_('Trying to access an unknown profile')) |
167 return "" | 159 return "" |
168 return profile_key | 160 return profile_key |
169 | 161 |
170 def __get_unique_node(self, parent, tag, name): | 162 def __get_unique_node(self, parent, tag, name): |
394 error(_('Requesting an unknown parameter (%(category)s/%(name)s)') % {'category':category, 'name':name}) | 386 error(_('Requesting an unknown parameter (%(category)s/%(name)s)') % {'category':category, 'name':name}) |
395 return | 387 return |
396 | 388 |
397 if node[0] == 'general': | 389 if node[0] == 'general': |
398 self.params_gen[(category, name)] = value | 390 self.params_gen[(category, name)] = value |
391 self.storage.setGenParam(category, name, value) | |
399 for profile in self.getProfilesList(): | 392 for profile in self.getProfilesList(): |
400 if self.host.isConnected(profile): | 393 if self.host.isConnected(profile): |
401 self.host.bridge.paramUpdate(name, value, category, profile) | 394 self.host.bridge.paramUpdate(name, value, category, profile) |
402 return | 395 return |
403 | 396 |
406 | 399 |
407 type = node[1].getAttribute("type") | 400 type = node[1].getAttribute("type") |
408 if type=="button": | 401 if type=="button": |
409 print "clique",node.toxml() | 402 print "clique",node.toxml() |
410 else: | 403 else: |
411 self.params[profile][(category, name)] = value | 404 if self.host.isConnected(profile): #key can not exists if profile is not connected |
412 self.host.bridge.paramUpdate(name, value, category, profile) #TODO: add profile in signal | 405 self.params[profile][(category, name)] = value |
406 self.host.bridge.paramUpdate(name, value, category, profile) | |
407 self.storage.setIndParam(category, name, value, profile) | |
413 | 408 |
414 class Memory: | 409 class Memory: |
415 """This class manage all persistent informations""" | 410 """This class manage all persistent informations""" |
416 | 411 |
417 def __init__(self, host): | 412 def __init__(self, host): |
418 info (_("Memory manager init")) | 413 info (_("Memory manager init")) |
414 self.initialized = defer.Deferred() | |
415 init_defers = [] #list of deferred to wait before initialization is finished | |
419 self.host = host | 416 self.host = host |
420 self.contacts={} | 417 self.contacts={} |
421 self.presenceStatus={} | 418 self.presenceStatus={} |
422 self.lastResource={} #tmp, will be refactored with bdd integration | 419 self.lastResource={} #tmp, will be refactored with bdd integration |
423 self.subscriptions={} | 420 self.subscriptions={} |
427 self.server_features={} #used to store discovery's informations | 424 self.server_features={} #used to store discovery's informations |
428 self.server_identities={} | 425 self.server_identities={} |
429 self.config = self.parseMainConf() | 426 self.config = self.parseMainConf() |
430 host.set_const('savefile_history', SAVEFILE_HISTORY) | 427 host.set_const('savefile_history', SAVEFILE_HISTORY) |
431 host.set_const('savefile_private', SAVEFILE_PRIVATE) | 428 host.set_const('savefile_private', SAVEFILE_PRIVATE) |
432 self.load() | 429 host.set_const('savefile_database', SAVEFILE_DATABASE) |
430 database_file = os.path.expanduser(self.getConfig('','local_dir')+ | |
431 self.host.get_const('savefile_database')) | |
432 self.loadFiles() | |
433 self.storage = SqliteStorage(database_file) | |
434 self.storage.initialized.addCallback(lambda ignore: self.load(init_defers)) | |
435 | |
436 defer.DeferredList(init_defers).chainDeferred(self.initialized) | |
433 | 437 |
434 def parseMainConf(self): | 438 def parseMainConf(self): |
435 """look for main .ini configuration file, and parse it""" | 439 """look for main .ini configuration file, and parse it""" |
436 _config = SafeConfigParser(defaults=default_config) | 440 _config = SafeConfigParser(defaults=default_config) |
437 try: | 441 try: |
453 except NoOptionError, NoSectionError: | 457 except NoOptionError, NoSectionError: |
454 _value = '' | 458 _value = '' |
455 | 459 |
456 return os.path.expanduser(_value) if name.endswith('_path') or name.endswith('_dir') else _value | 460 return os.path.expanduser(_value) if name.endswith('_path') or name.endswith('_dir') else _value |
457 | 461 |
458 def load(self): | 462 |
463 def loadFiles(self): | |
459 """Load parameters and all memory things from file/db""" | 464 """Load parameters and all memory things from file/db""" |
460 param_file_xml = os.path.expanduser(self.getConfig('','local_dir')+ | 465 param_file_xml = os.path.expanduser(self.getConfig('','local_dir')+ |
461 self.host.get_const('savefile_param_xml')) | 466 self.host.get_const('savefile_param_xml')) |
462 param_file_data = os.path.expanduser(self.getConfig('','local_dir')+ | 467 param_file_data = os.path.expanduser(self.getConfig('','local_dir')+ |
463 self.host.get_const('savefile_param_data')) | 468 self.host.get_const('savefile_param_data')) |
464 history_file = os.path.expanduser(self.getConfig('','local_dir')+ | 469 history_file = os.path.expanduser(self.getConfig('','local_dir')+ |
465 self.host.get_const('savefile_history')) | 470 self.host.get_const('savefile_history')) |
466 private_file = os.path.expanduser(self.getConfig('','local_dir')+ | 471 private_file = os.path.expanduser(self.getConfig('','local_dir')+ |
467 self.host.get_const('savefile_private')) | 472 self.host.get_const('savefile_private')) |
468 | 473 |
469 #parameters | 474 #parameters template |
470 if os.path.exists(param_file_xml): | 475 if os.path.exists(param_file_xml): |
471 try: | 476 try: |
472 self.params.load_xml(param_file_xml) | 477 self.params.load_xml(param_file_xml) |
473 debug(_("params template loaded")) | 478 debug(_("params template loaded")) |
474 except: | 479 except: |
476 self.params.load_default_params() | 481 self.params.load_default_params() |
477 else: | 482 else: |
478 info (_("No params template, using default template")) | 483 info (_("No params template, using default template")) |
479 self.params.load_default_params() | 484 self.params.load_default_params() |
480 | 485 |
481 try: | 486 |
482 self.params.load_data(param_file_data) | |
483 debug(_("params loaded")) | |
484 except: | |
485 error (_("Can't load params !")) | |
486 | |
487 #history | 487 #history |
488 if os.path.exists(history_file): | 488 if os.path.exists(history_file): |
489 try: | 489 try: |
490 with open(history_file, 'r') as history_pickle: | 490 with open(history_file, 'r') as history_pickle: |
491 self.history=pickle.load(history_pickle) | 491 self.history=pickle.load(history_pickle) |
499 with open(private_file, 'r') as private_pickle: | 499 with open(private_file, 'r') as private_pickle: |
500 self.private=pickle.load(private_pickle) | 500 self.private=pickle.load(private_pickle) |
501 debug(_("private values loaded")) | 501 debug(_("private values loaded")) |
502 except: | 502 except: |
503 error (_("Can't load private values !")) | 503 error (_("Can't load private values !")) |
504 | |
505 def load(self, init_defers): | |
506 """Load parameters and all memory things from db | |
507 @param init_defers: list of deferred to wait before parameters are loaded""" | |
508 #parameters data | |
509 init_defers.append(self.params.loadGenData(self.storage)) | |
510 | |
511 def loadIndividualParams(self, profile_key): | |
512 """Load individual parameters for a profile | |
513 @param profile_key: %(doc_profile_key)s""" | |
514 profile = self.getProfileName(profile_key) | |
515 if not profile: | |
516 error (_('Trying to load parameters for a non-existant profile')) | |
517 raise Exception("Profile doesn't exist") | |
518 return self.params.loadIndParams(profile) | |
519 | |
504 | 520 |
505 def save(self): | 521 def save(self): |
506 """Save parameters and all memory things to file/db""" | 522 """Save parameters and all memory things to file/db""" |
507 #TODO: need to encrypt files (at least passwords !) and set permissions | 523 #TODO: need to encrypt files (at least passwords !) and set permissions |
508 param_file_xml = os.path.expanduser(self.getConfig('','local_dir')+ | 524 param_file_xml = os.path.expanduser(self.getConfig('','local_dir')+ |
523 with open(private_file, 'w') as private_pickle: | 539 with open(private_file, 'w') as private_pickle: |
524 pickle.dump(self.private, private_pickle) | 540 pickle.dump(self.private, private_pickle) |
525 debug(_("private values saved")) | 541 debug(_("private values saved")) |
526 | 542 |
527 def getProfilesList(self): | 543 def getProfilesList(self): |
528 return self.params.getProfilesList() | 544 return self.storage.getProfilesList() |
529 | 545 |
530 | 546 |
531 def getProfileName(self, profile_key): | 547 def getProfileName(self, profile_key): |
532 """Return name of profile from keyword | 548 """Return name of profile from keyword |
533 @param profile_key: can be the profile name or a keywork (like @DEFAULT@) | 549 @param profile_key: can be the profile name or a keywork (like @DEFAULT@) |