def _clr_trace_local(): if coro.get_local(CORO_LOCAL_TCTRL, {}).get('clear', False): data = coro.pop_local(CORO_LOCAL_TCTRL, {}) else: data = coro.get_local(CORO_LOCAL_TCTRL, {}) return data.get('value', False)
def _set_trace_local(value, clear): if not coro.has_local(CORO_LOCAL_TCTRL): coro.set_local(CORO_LOCAL_TCTRL, {}) data = coro.get_local(CORO_LOCAL_TCTRL) data['value'] = value data['clear'] = clear
def _trace_data(start, obj, cmd, vids, **kwargs): if not _get_trace_local(): return None if not _trace_check_limits(obj, cmd, vids): return None elapse = time.time() - start if not coro.has_local(CORO_LOCAL_TDATA): coro.set_local(CORO_LOCAL_TDATA, {}) data = coro.get_local(CORO_LOCAL_TDATA) data = data.setdefault(obj, {}) look = not isinstance(vids, (list, tuple)) and 1 or len(vids) data[cmd] = sum_tuple(data.get(cmd, (0, 0, 0)), (elapse, look, 1)) if _get_trace_local() > ACCESS_TRACE_DEBUG: stack = pyinfo.rawstack() stack = stack[:-5] # remove 5 levels of mod_python, publisher while stack and stack[0][0].startswith('access'): stack.pop(0) stack = ' @ %s' % '|'.join(['%s:%s:%s' % x for x in stack]) else: stack = '' if _get_trace_local() < ACCESS_TRACE_DEBUG: return None print 'Access | %.4f | obj: %s cmd: %s vid: %s args: %s kwargs: %s%s' % ( elapse, obj, cmd, vids, kwargs.get('args', ()), kwargs.get('kwargs', {}), stack)
def trace_dump(clear = True): '''trace_dump Dump to stdout current trace data at the current trace level. An optional clear parameter to reset or preserve the trace data. (default: True) See Also: enable_trace() ''' if clear: tdata = coro.pop_local(CORO_LOCAL_TDATA, {}) tlevl = _clr_trace_local() else: tdata = coro.get_local(CORO_LOCAL_TDATA, {}) tlevl = _get_trace_local() if not tlevl: return None total, idcnt, count = 0, 0, 0 for obj, data in tdata.items(): for cmd, (elapse, ids, cnt) in data.items(): total += elapse count += cnt idcnt += ids if tlevl > ACCESS_TRACE_TERSE: print 'Access | %0.4f | %4d | %4d | Summary (%s.%s)' % ( elapse, cnt, ids, obj, cmd) if not total: return None lmt = has_trace_limits() if lmt is None: lmt = '' else: lmt = 'limit: %s' % lmt print 'Access | %.4f | %4d | %4d | Summary (TOTAL) %s' % ( total, count, idcnt, lmt)
def _get_trace_local(): data = coro.get_local(CORO_LOCAL_TCTRL, {}) return data.get('value', False)
def _tlb_status(object): return coro.get_local('tlb-%s' % object, False)
def execute( object, notifier, command, vids, args = (), kwargs = {}, timeout = None, retry = None, raw = False): # # emtpy sets fail to no RPC. still, match the type the caller expects. # if not vids and isinstance(vids, list): return [] # # default retry when none specificed # if retry is None: retry = DEFAULT_RETRY # # lookaside determination/setup. Three possible values: # # None - No lookup currently in progress # False - Lookup in progress but first order # True - Second order lookup in progress, do not # initiate a recursive lookup. # tlb = 'tlb-%s' % object val = coro.get_local(tlb) if val is None: val = False elif not val: val = True else: raise LookAside((tlb, val)) look = (isinstance(vids, (list, tuple)) and [vids] or [[vids]])[0] data = { 'tlb': (tlb, val), 'slave': ('slave-read', slave_read()), 'source': socket.gethostname(), 'command': command, 'args': args, 'kwargs': kwargs} retry += 1 results = map(lambda i: None, xrange(len(look))) pending = {} # # quick pass on empty lookup set. # if not look: return results # # create a dictionary of pending vector elements to result # array offsets, de-duplicate the lookup vector, order is # no longer imporatant since order is now maintained in the # pending dictionary # filter( lambda i: pending.setdefault(i[0], set([])).add(i[1]), zip(look, xrange(len(look)))) # # process blank requests # for pos in pending.pop(BLANK_TOKEN, []): results[pos] = [{}] # # process remaining retry number of times. # while retry and pending: retry -= 1 lookup = pending.keys() values = notifier.rpcs( object, lookup, 'execute', data, timeout = timeout, local = not val) if not values: continue # # map values to correct result location # for i in xrange(len(lookup)): if not values[i]: push = pending.get(lookup[i]) else: push = pending.pop(lookup[i]) for pos in push: results[pos] = values[i] # # look for absence of any results, raize an error even if only # one element is in error # errors = filter(lambda i: not i, results) if errors: # # since we can only raise one type of error, decide based on # the type of the first list element in the error set. # (empty list is a server error, none is a client error # if errors[0] is None: raise ClientError(look, data, errors) else: raise ServerError(look, data, errors) # # if we're not looking for raw data (function called with raw=True) then # strip out all but the first result and _unwrap it. otherwise just # _unwrap all the results and return them. # if not raw: results = map(lambda i: _unwrap((i and [i[0]] or [None])[0]), results) else: results = map(lambda i: map(_unwrap, i), results) # # when request is for a single ID and not a list of IDs rip the # result to match the request. # if not isinstance(vids, list): results = results[0] return results
def slave_read(status = None): if status is None: return coro.get_local('slave-read', False) else: return coro.set_local('slave-read', status)