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