6f3a87dcb7fff63e23fd794d15b62772199a6c3d
[monitor.git] / monitor / database / dbpickle.py
1 import os
2 import sys
3 import pickle
4 import inspect
5 import shutil
6 from monitor import config
7
8 noserial=False
9 try:
10         from util.PHPSerialize import *
11         from util.PHPUnserialize import *
12 except:
13         #print >>sys.stderr, "PHPSerial db type not allowed."
14         noserial=True
15
16 DEBUG= 0
17 PICKLE_PATH=config.MONITOR_DATA_ROOT
18
19
20 def dbLoad(name, type=None):
21         return SPickle().load(name, type)
22
23 def dbExists(name, type=None):
24         #if self.config.debug:
25         #       name = "debug.%s" % name
26         return SPickle().exists(name, type)
27
28 def dbDump(name, obj=None, type=None):
29         # depth of the dump is 2 now, since we're redirecting to '.dump'
30         return SPickle().dump(name, obj, type, 2)
31
32 def if_cached_else_refresh(cond, refresh, name, function, type=None):
33         s = SPickle()
34         if refresh:
35                 if not config.debug and s.exists("production.%s" % name, type):
36                         s.remove("production.%s" % name, type)
37                 if config.debug and s.exists("debug.%s" % name, type):
38                         s.remove("debug.%s" % name, type)
39
40         return if_cached_else(cond, name, function, type)
41
42 def if_cached_else(cond, name, function, type=None):
43         s = SPickle()
44         if (cond and s.exists("production.%s" % name, type)) or \
45            (cond and config.debug and s.exists("debug.%s" % name, type)):
46                 o = s.load(name, type)
47         else:
48                 o = function()
49                 if cond:
50                         s.dump(name, o, type)   # cache the object using 'name'
51                         o = s.load(name, type)
52                 # TODO: what if 'o' hasn't been converted...
53         return o
54
55 class SPickle:
56         def __init__(self, path=PICKLE_PATH):
57                 self.path = path
58
59         def if_cached_else(self, cond, name, function, type=None):
60                 if cond and self.exists("production.%s" % name, type):
61                         o = self.load(name, type)
62                 else:
63                         o = function()
64                         if cond:
65                                 self.dump(name, o, type)        # cache the object using 'name'
66                 return o
67
68         def __file(self, name, type=None):
69                 if type == None:
70                         return "%s/%s.pkl" % (self.path, name)
71                 else:
72                         if noserial:
73                                 raise Exception("No PHPSerializer module available")
74
75                         return "%s/%s.phpserial" % (self.path, name)
76                 
77         def exists(self, name, type=None):
78                 return os.path.exists(self.__file(name, type))
79
80         def remove(self, name, type=None):
81                 return os.remove(self.__file(name, type))
82
83         def load(self, name, type=None):
84                 """ 
85                 In debug mode, we should fail if neither file exists.
86                         if the debug file exists, reset name
87                         elif the original file exists, make a copy, reset name
88                         else neither exist, raise an error
89                 Otherwise, it's normal mode, if the file doesn't exist, raise error
90                 Load the file
91                 """
92                 print "loading %s" % name
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                 #import traceback
115                 #print traceback.print_stack()
116                 #print "loading %s" % self.__file(name, type)
117                 #sys.stderr.write("-----------------------------\n")
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