renamed from 'soltesz' to reflect it's function and content. Should be able
[monitor.git] / database.py
1 import os
2 import sys
3 import pickle
4 noserial=False
5 try:
6         from PHPSerialize import *
7         from PHPUnserialize import *
8 except:
9         #print >>sys.stderr, "PHPSerial db type not allowed."
10         noserial=True
11
12 import inspect
13 import shutil
14 from config import config as cfg
15 config = cfg()
16
17 import monitorconfig
18
19 DEBUG= 0
20 PICKLE_PATH=monitorconfig.MONITOR_DATA_ROOT
21
22 class ExceptionTimeout(Exception): pass
23
24 def dbLoad(name, type=None):
25         return SPickle().load(name, type)
26
27 def dbExists(name, type=None):
28         #if self.config.debug:
29         #       name = "debug.%s" % name
30         return SPickle().exists(name, type)
31
32 def dbDump(name, obj=None, type=None):
33         # depth of the dump is 2 now, since we're redirecting to '.dump'
34         return SPickle().dump(name, obj, type, 2)
35
36 def if_cached_else_refresh(cond, refresh, name, function, type=None):
37         s = SPickle()
38         if refresh:
39                 if not config.debug and s.exists("production.%s" % name, type):
40                         s.remove("production.%s" % name, type)
41                 if config.debug and s.exists("debug.%s" % name, type):
42                         s.remove("debug.%s" % name, type)
43
44         return if_cached_else(cond, name, function, type)
45
46 def if_cached_else(cond, name, function, type=None):
47         s = SPickle()
48         if (cond and s.exists("production.%s" % name, type)) or \
49            (cond and config.debug and s.exists("debug.%s" % name, type)):
50                 o = s.load(name, type)
51         else:
52                 o = function()
53                 if cond:
54                         s.dump(name, o, type)   # cache the object using 'name'
55                         o = s.load(name, type)
56                 # TODO: what if 'o' hasn't been converted...
57         return o
58
59 class SPickle:
60         def __init__(self, path=PICKLE_PATH):
61                 self.path = path
62
63         def if_cached_else(self, cond, name, function, type=None):
64                 if cond and self.exists("production.%s" % name, type):
65                         o = self.load(name, type)
66                 else:
67                         o = function()
68                         if cond:
69                                 self.dump(name, o, type)        # cache the object using 'name'
70                 return o
71
72         def __file(self, name, type=None):
73                 if type == None:
74                         return "%s/%s.pkl" % (self.path, name)
75                 else:
76                         if noserial:
77                                 raise Exception("No PHPSerializer module available")
78
79                         return "%s/%s.phpserial" % (self.path, name)
80                 
81         def exists(self, name, type=None):
82                 return os.path.exists(self.__file(name, type))
83
84         def remove(self, name, type=None):
85                 return os.remove(self.__file(name, type))
86
87         def load(self, name, type=None):
88                 """ 
89                 In debug mode, we should fail if neither file exists.
90                         if the debug file exists, reset name
91                         elif the original file exists, make a copy, reset name
92                         else neither exist, raise an error
93                 Otherwise, it's normal mode, if the file doesn't exist, raise error
94                 Load the file
95                 """
96
97                 if config.debug:
98                         if self.exists("debug.%s" % name, type):
99                                 name = "debug.%s" % name
100                         elif self.exists("production.%s" % name, type):
101                                 debugname = "debug.%s" % name
102                                 if not self.exists(debugname, type):
103                                         name = "production.%s" % name
104                                         shutil.copyfile(self.__file(name, type), self.__file(debugname, type))
105                                 name = debugname
106                         else:   # neither exist
107                                 raise Exception, "No such pickle based on %s" % self.__file("debug.%s" % name, type)
108                 else:
109                         if   self.exists("production.%s" % name, type):
110                                 name = "production.%s" % name
111                         elif self.exists(name, type):
112                                 name = name
113                         else:
114                                 raise Exception, "No such file %s" % name
115                                 
116
117                 #print "loading %s" % self.__file(name, type)
118                 f = open(self.__file(name, type), 'r')
119                 if type == None:
120                         o = pickle.load(f)
121                 else:
122                         if noserial:
123                                 raise Exception("No PHPSerializer module available")
124                         s = PHPUnserialize()
125                         o = s.unserialize(f.read())
126                 f.close()
127                 return o
128                         
129         
130         # use the environment to extract the data associated with the local
131         # variable 'name'
132         def dump(self, name, obj=None, type=None, depth=1):
133                 if obj == None:
134                         o = inspect.getouterframes(inspect.currentframe())
135                         up1 = o[depth][0] # get the frame one prior to (up from) this frame
136                         argvals = inspect.getargvalues(up1)
137                         # TODO: check that 'name' is a local variable; otherwise this would fail.
138                         obj = argvals[3][name] # extract the local variable name 'name'
139                 if not os.path.isdir("%s/" % self.path):
140                         os.mkdir("%s" % self.path)
141                 if config.debug:
142                         name = "debug.%s" % name
143                 else:
144                         name = "production.%s" % name
145                 f = open(self.__file(name, type), 'w')
146                 if type == None:
147                         pickle.dump(obj, f)
148                 else:
149                         if noserial:
150                                 raise Exception("No PHPSerializer module available")
151                         s = PHPSerialize()
152                         f.write(s.serialize(obj))
153                 f.close()
154                 return