def setUp(self): # These defaults only make sense if the default encoding # prevents s from being promoted to Unicode. self.assertRaises(UnicodeError, unicode, self.s) # An object needs to be added to the database to self.db = DB(MappingStorage()) root = self.db.open().root() self.bucket = root["bucket"] = Bucket() self.set = root["set"] = Set() transaction.commit()
def PUT(self, REQUEST, RESPONSE): """Handle put requests""" self.dav__init(REQUEST, RESPONSE) self.dav__simpleifhandler(REQUEST, RESPONSE, refresh=1) body = REQUEST.get('BODY', '') m = re.match(r'\s*<params>(.*)</params>\s*\n', body, re.I | re.S) if m: self.arguments_src = m.group(1) self._arg = parse(self.arguments_src) body = body[m.end():] template = body self.src = template self.template = t = self.template_class(template) t.cook() self._v_cache = ({}, Bucket()) RESPONSE.setStatus(204) return RESPONSE
def manage_edit(self, title, connection_id, arguments, template, SUBMIT='Change', dtpref_cols='100%', dtpref_rows='20', REQUEST=None): """Change database method properties The 'connection_id' argument is the id of a database connection that resides in the current folder or in a folder above the current folder. The database should understand SQL. The 'arguments' argument is a string containing an arguments specification, as would be given in the SQL method cration form. The 'template' argument is a string containing the source for the SQL Template. """ if SUBMIT in self._size_changes: return self._er(title, connection_id, arguments, template, SUBMIT, dtpref_cols, dtpref_rows, REQUEST) if self.wl_isLocked(): raise ResourceLockedError('SQL Method is locked via WebDAV') self.title = str(title) self.connection_id = str(connection_id) arguments = str(arguments) self.arguments_src = arguments self._arg = parse(arguments) template = str(template) self.src = template self.template = t = self.template_class(template) t.cook() self._v_cache = ({}, Bucket()) if REQUEST: if SUBMIT == 'Change and Test': return self.manage_testForm(REQUEST) message = 'ZSQL Method content changed' return self.manage_main(self, REQUEST, manage_tabs_message=message) return ''
def _cached_result(self, DB__, query, max_rows, conn_id): # Try to fetch a result from the cache. # Compute and cache the result otherwise. # Also maintains the cache and ensures stale entries # are never returned and that the cache never gets too large. # NB: Correct cache behavior is predicated on Bucket.keys() # returning a sequence ordered from smalled number # (ie: the oldest cache entry) to largest number # (ie: the newest cache entry). Please be careful if you # change the class instantied below! # get hold of a cache caches = getattr(self, '_v_cache', None) if caches is None: caches = self._v_cache = {}, Bucket() cache, tcache = caches # the key for caching cache_key = query, max_rows, conn_id # the maximum number of result sets to cache max_cache = self.max_cache_ # the current time now = time() # the oldest time which is not stale t = now - self.cache_time_ # if the cache is too big, we purge entries from it if len(cache) >= max_cache: keys = tcache.keys() # We also hoover out any stale entries, as we're # already doing cache minimisation. # 'keys' is ordered, so we purge the oldest results # until the cache is small enough and there are no # stale entries in it while keys and (len(keys) >= max_cache or keys[0] < t): key = keys[0] q = tcache[key] del tcache[key] del cache[q] del keys[0] # okay, now see if we have a cached result if cache_key in cache: k, r = cache[cache_key] # the result may still be stale, as we only hoover out # stale results above if the cache gets too large. if k > t: # yay! a cached result returned! return r else: # delete stale cache entries del cache[cache_key] try: del tcache[k] except KeyError: # If there were two querys at the same timestamp, the # entry in `tcache` might have been already deleted when # purging the other query, so do not complain: pass # call the pure query result = DB__.query(query, max_rows) # When a ZSQL method is handled by one ZPublisher thread twice in # less time than it takes for time.time() to return a different # value, the SQL generated is different, then this code will leak # an entry in 'cache' for each time the ZSQL method generates # different SQL until time.time() returns a different value. # # On Linux, you would need an extremely fast machine under extremely # high load, making this extremely unlikely. On Windows, this is a # little more likely, but still unlikely to be a problem. # # If it does become a problem, the values of the tcache mapping # need to be turned into sets of cache keys rather than a single # cache key. tcache[now] = cache_key cache[cache_key] = now, result return result
def manage_advanced(self, max_rows, max_cache, cache_time, class_name, class_file, direct=None, REQUEST=None, connection_hook=None): """Change advanced properties The arguments are: max_rows -- The maximum number of rows to be returned from a query. max_cache -- The maximum number of results to cache cache_time -- The maximum amound of time to use a cached result. class_name -- The name of a class that provides additional attributes for result record objects. This class will be a base class of the result record class. class_file -- The name of the file containing the class definition. The class file normally resides in the 'Extensions' directory, however, the file name may have a prefix of 'product.', indicating that it should be found in a product directory. For example, if the class file is: 'ACMEWidgets.foo', then an attempt will first be made to use the file 'lib/python/Products/ACMEWidgets/Extensions/foo.py'. If this failes, then the file 'Extensions/ACMEWidgets.foo.py' will be used. """ # paranoid type checking if not isinstance(max_rows, int): max_rows = int(max_rows) if not isinstance(max_cache, int): max_cache = int(max_cache) if not isinstance(cache_time, int): cache_time = int(cache_time) class_name = str(class_name) class_file = str(class_file) self.max_rows_ = max_rows self.max_cache_, self.cache_time_ = max_cache, cache_time self._v_cache = {}, Bucket() self.class_name_, self.class_file_ = class_name, class_file self._v_brain = getBrain(self.class_file_, self.class_name_, 1) self.allow_simple_one_argument_traversal = direct self.connection_hook = connection_hook if REQUEST is not None: m = 'ZSQL Method advanced settings have been set' return self.manage_advancedForm(self, REQUEST, manage_tabs_message=m)