]> code.delx.au - pymsnt/blob - src/xdb.py
Major changes. Moved everything away from twistd and .tac files. Its nicer this way...
[pymsnt] / src / xdb.py
1 # Copyright 2004-2005 James Bunton <james@delx.cjb.net>
2 # Licensed for distribution under the GPL version 2, check COPYING for details
3
4 from tlib import xmlw
5 from debug import LogEvent, INFO, WARN
6 import os
7 import os.path
8 import config
9 import legacy
10
11 SPOOL_UMASK = 0077
12
13
14 def unmangle(file):
15 chunks = file.split("%")
16 end = chunks.pop()
17 file = "%s@%s" % ("%".join(chunks), end)
18 return file
19
20 def mangle(jid):
21 return jid.replace("@", "%")
22
23
24 class XDB:
25 """
26 Class for storage of data.
27
28 Create one instance of the class for each XDB 'folder' you want.
29 Call request()/set() with the xdbns argument you wish to retrieve
30 """
31 def __init__(self, name, mangle=False):
32 """ Creates an XDB object. If mangle is True then any '@' signs in filenames will be changed to '%' """
33 self.name = os.path.abspath(config.spooldir) + '/' + name
34 if not os.path.exists(self.name):
35 os.makedirs(self.name)
36 self.mangle = mangle
37
38 def __getFile(self, file):
39 if(self.mangle):
40 file = mangle(file)
41
42 hash = file[0:2]
43 document = xmlw.parseFile(self.name + "/" + hash + "/" + file + ".xml")
44
45 return document
46
47 def __writeFile(self, file, text):
48 if(self.mangle):
49 file = mangle(file)
50
51 prev_umask = os.umask(SPOOL_UMASK)
52 hash = file[0:2]
53 pre = self.name + "/" + hash + "/"
54 if not os.path.exists(pre):
55 os.makedirs(pre)
56 f = open(pre + file + ".xml", "w")
57 f.write(text)
58 f.close()
59 os.umask(prev_umask)
60
61 def files(self):
62 """ Returns a list containing the files in the current XDB database """
63 files = []
64 for dir in os.listdir(self.name):
65 if(os.path.isdir(self.name + "/" + dir)):
66 files.extend(os.listdir(self.name + "/" + dir))
67 if self.mangle:
68 files = [unmangle(x)[:-4] for x in files]
69 else:
70 files = [x[:-4] for x in files]
71
72 while files.count(''):
73 files.remove('')
74
75 return files
76
77 def request(self, file, xdbns):
78 """ Requests a specific xdb namespace from the XDB 'file' """
79 try:
80 document = self.__getFile(file)
81 for child in document.elements():
82 if(child.getAttribute("xdbns") == xdbns):
83 return child
84 except:
85 return None
86
87 def set(self, file, xdbns, element):
88 """ Sets a specific xdb namespace in the XDB 'file' to element """
89 try:
90 element.attributes["xdbns"] = xdbns
91 document = None
92 try:
93 document = self.__getFile(file)
94 except IOError:
95 pass
96 if(not document):
97 document = xmlw.Element((None, "xdb"))
98
99 # Remove the existing node (if any)
100 for child in document.elements():
101 if(child.getAttribute("xdbns") == xdbns):
102 document.children.remove(child)
103 # Add the new one
104 document.addChild(element)
105
106 self.__writeFile(file, document.toXml())
107 except IOError, e:
108 LogEvent(WARN, "", "IOError " + str(e))
109 raise
110
111 def remove(self, file):
112 """ Removes an XDB file """
113 file = self.name + "/" + file[0:2] + "/" + file + ".xml"
114 if(self.mangle):
115 file = mangle(file)
116 try:
117 os.remove(file)
118 except IOError, e:
119 LogEvent(WARN, "", "IOError " + str(e))
120 raise
121
122
123