def cache(self, **kwargs): """ DAS web cache interface. Fire up new process for new requests and record its pid. The client is in charge to keep track of pid. The new process uses DAS core call to request the data into cache. Since query are cached the repeated call with the same query has no cost to DAS core. """ # do not allow caching set_no_cache_flags() # if busy return right away if self.busy(): return self.empty_return(kwargs) uinput = kwargs.get('input', '').strip() check_query(uinput) if not uinput: head = {'status': 'fail', 'reason': 'No input found', 'args': kwargs, 'ctime': 0, 'input': uinput} data = [] return self.datastream(dict(head=head, data=data)) self.adjust_input(kwargs) pid = kwargs.get('pid', '') inst = kwargs.get('instance', self.dbs_global) uinput = kwargs.get('input', '') view = kwargs.get('view', 'list') qcache = kwargs.get('qcache', 0) data = [] # textual views need text only error messages... check, content = self.generate_dasquery(uinput, inst, html_mode=self._is_web_request(view), qcache=qcache) if check: head = dict(timestamp=time.time()) head.update({'status': 'fail', 'reason': 'Can not interpret the query'+ \ ' (while creating DASQuery)', 'ctime': 0}) if not self._is_web_request(view): head['error_details'] = content head['reason'] = head['reason'] + '\n\n' + content return self.datastream(dict(head=head, data=data)) dasquery = content # returned content is valid DAS query status, error, reason = self.dasmgr.get_status(dasquery) kwargs.update({'status':status, 'error':error, 'reason':reason}) if not pid: pid = dasquery.qhash if status == None and not self.reqmgr.has_pid(pid): # submit new request uid = cherrypy.request.headers.get('Remote-Addr') if hasattr(cherrypy.request, 'user'): uid = cherrypy.request.user.get('dn', None) _evt, pid = self.taskmgr.spawn(\ self.dasmgr.call, dasquery, uid=uid, pid=dasquery.qhash) self.reqmgr.add(pid, kwargs) return pid if status == 'ok': self.reqmgr.remove(pid) self.taskmgr.remove(pid) kwargs['dasquery'] = dasquery head, data = self.get_data(kwargs) return self.datastream(dict(head=head, data=data)) kwargs['dasquery'] = dasquery.storage_query if not self.pid_pat.match(str(pid)) or len(str(pid)) != 32: self.reqmgr.remove(pid) self.taskmgr.remove(pid) return self.empty_return(dasquery, 'fail', 'Invalid pid') elif self.taskmgr.is_alive(pid): return pid elif status == None: # DAS was busy and query expired since status==None if not self.taskmgr.is_alive(pid) and self.reqmgr.has_pid(pid): self.reqmgr.remove(pid) self.taskmgr.remove(pid) return self.empty_return(dasquery, 'fail', 'request expired') return pid else: # process is done, get data self.reqmgr.remove(pid) self.taskmgr.remove(pid) head, data = self.get_data(kwargs) return self.datastream(dict(head=head, data=data))
def request(self, **kwargs): """ Request data from DAS cache. """ # do not allow caching set_no_cache_flags() uinput = kwargs.get('input', '').strip() check_query(uinput) if not uinput: kwargs['reason'] = 'No input found' return self.redirect(**kwargs) # if busy return right away if self.busy(): return self.busy_page(uinput) time0 = time.time() self.adjust_input(kwargs) view = kwargs.get('view', 'list') qcache = kwargs.get('qcache', 0) if 'instance' in uinput: form = self.form(uinput=uinput, view=view) content = 'On DAS web UI please use drop-down menu to specify DBS' content += ' instance to avoid ambiguity. ' content += 'To proceed please clear your input query.' return self.page(form + '<div class="box_red">%s</div>' % content) else: inst = kwargs.get('instance', self.dbs_global) uinput = kwargs.get('input', '') form = self.form(uinput=uinput, instance=inst, view=view) check, content = self.generate_dasquery(uinput, inst, qcache=qcache) if check: if view == 'list' or view == 'table': return self.page(form + content, ctime=time.time()-time0) else: return content dasquery = content # returned content is valid DAS query status, error, reason = self.dasmgr.get_status(dasquery) kwargs.update({'status':status, 'error':error, 'reason':reason}) pid = dasquery.qhash if status is None: # process new request kwargs['dasquery'] = dasquery.storage_query uid = cherrypy.request.headers.get('Remote-Addr') if hasattr(cherrypy.request, 'user'): uid = cherrypy.request.user.get('dn', None) _evt, pid = self.taskmgr.spawn(self.dasmgr.call, dasquery, uid=uid, pid=dasquery.qhash) self.reqmgr.add(pid, kwargs) elif status == 'ok' or status == 'fail': self.reqmgr.remove(pid) self.taskmgr.remove(pid) # check if query can be rewritten via nested PK query rew_msg = self.q_rewriter and self.q_rewriter.check_fields(dasquery) if rew_msg: content = self.templatepage('das_error', msg=rew_msg) return self.page(form + content, ctime=time.time()-time0) kwargs['dasquery'] = dasquery page = self.get_page_content(kwargs, complete_msg=False) ctime = (time.time()-time0) if view == 'list' or view == 'table': return self.page(form + page, ctime=ctime) return page if self.taskmgr.is_alive(pid): page = self.templatepage('das_check_pid', method='check_pid', uinput=uinput, view=view, urllib=urllib, base=self.base, pid=pid, interval=self.interval) elif status == None: # DAS was busy and query expired since status==None if not self.taskmgr.is_alive(pid) and self.reqmgr.has_pid(pid): self.reqmgr.remove(pid) self.taskmgr.remove(pid) return self.empty_return(dasquery, 'fail', 'request expired') page = self.templatepage('das_check_pid', method='check_pid', uinput=uinput, view=view, urllib=urllib, base=self.base, pid=pid, interval=self.interval) else: self.reqmgr.remove(pid) self.taskmgr.remove(pid) page = self.get_page_content(kwargs) ctime = (time.time()-time0) return self.page(form + page, ctime=ctime)