def claims(self, q): '''claims($q): show claims established by query q''' cs = terms.loads(self.etb().query_claims(q)) self.print_claims(cs, 'established by query %s' % q) if len(cs) == 1: return terms.dumps(cs[0]) else: return [terms.dumps(c) for c in cs]
def interpret_goal_somewhere(self, goal, internal_goal): """Interpret the goal on some node, possibly this one.""" pred = goal.first_symbol() self.log.debug('Looking to interpret %s somewhere.' % pred) candidates = self.networking.neighbors_able_to_interpret(pred) link = False if not candidates: candidates = self.networking.links_able_to_interpret(pred) link = True if not candidates: self.error("no node able to interpret goal {0}".format(goal)) argspecstr = candidates[0].predicates[str(pred.val)] argspecs = wrapper.ArgSpec.parse(argspecstr) if len(argspecs) != len(goal.args): self.error( "Have %d argspecs, expect %d" % (len(argspecs), len(goal.args))) handles = [] for (spec, arg) in zip(argspecs, goal.args) : if spec.kind == 'handle': handles.append((spec, arg)) candidates = self.filter_candidates(candidates, goal) if not candidates: self.error("no node able to interpret goal {0}".format(goal)) best_node = min(candidates, key=lambda n: n.load) # adding internal goal: this needs to be added for remote evaluation if best_node.id == self.id : self.interpret_state.interpret(goal, internal_goal, sync=True) return argspecstr = best_node.predicates[str(goal.first_symbol().val)] argspecs = wrapper.ArgSpec.parse(argspecstr) new_id = uuid.uuid4().get_hex() self.active_remote_queries[new_id] = (goal, best_node, argspecs, goal) proxy = best_node.proxy if link: self.log.info('Sending %s to remote ETB on %s' % (goal.first_symbol(), best_node.id)) proxy.interpret_goal_remotely(self.id, terms.dumps(goal), new_id) else: self.log.info('Asking {0} to interpret {1}.' .format(best_node.id, goal.first_symbol())) proxy.interpret_goal(self.id, terms.dumps(goal), new_id) best_node.increment_load()
def task_interpret(etb, query_id=query_id, goals=goals): query = self.etb.create_query((goals,)) self.query_wait(query) answer = terms.dumps(self.etb.query_answers(query)) def task(etb, query_id=query_id, answer=answer): proxy.answer_query(query_id, answer) etb.short_pool.schedule(task)
def get_file(self, src, dst=None): ''' gets the file from the ETB src is a file handle ''' if is_filehandle(src): if dst is None: dst = src['file'] if isinstance(dst, terms.Const): dst = dst.val dst = dst.strip('"\'') # Get rid of outer quote marks jsrc = terms.dumps(src) contents = self.etb().get_file(jsrc) ndir = os.path.dirname(dst) if ndir != '' and not os.path.isdir(ndir): os.makedirs(ndir) with codecs.open(dst, mode='wb', errors='ignore') as fd: fd.write(base64.b64decode(contents)) elif isinstance(src, basestring): # Just get whatever version is in the working (Git) directory shandle = self.etb().get_filehandle(src) handle = json.loads(shandle) if is_filehandle(handle): return self.get_file(handle, dst) else: raise TypeError( 'get_file: string or filehandle expected: {0}: {1}'.format( src, type(src)))
def task_interpret(etb, query_id=query_id, goals=goals): query = self.etb.create_query((goals,)) self.query_wait(query) if False: filename = self.etb.engine.goal_deps_to_png(goals) os.rename(filename, "%s.png" % goals) self.log.debug("answering_png.png for %s dumped to %s" % (goals, os.getcwd())) ans = self.etb.query_answers(query) answer = terms.dumps(ans) self.log.debug('task_interpret: answer to query is: %s' % answer) def task(etb, query_id=query_id, answer=answer): if from_id in self._neighbors: proxy = self.neighbor(from_id).proxy else: print('setting proxy to None') proxy = None if proxy is not None: self.log.debug('Sending query answer to %s', from_id) # I don't know why, but at some point the following # started raising the exception printing proxy: # method "__unicode__" is not supported #self.log.info('proxy for %s is %s' % (from_id, proxy)) self.log.debug('_neighbors = %s' % self._neighbors) proxy.answer_query(query_id, answer) etb.short_pool.schedule(task)
def query_answers(self, qid): """Given a query ID, returns a JSON-encoded list of all current answers (substitutions) to the query. The list may grow later, as new claims are added to the system. """ answers = self.etb.query_answers(qid) if answers: return terms.dumps(answers['substs']) else: return ''
def link_predicates(self): """ Reveals our ETB network capabilities. Passed as a payload in pokes. """ predicates = self.etb.interpret_state.predicates() for n in list(self.neighbors): predicates.update(n.predicates) response = terms.dumps(predicates) #self.log.debug("link_predicates of %s are %s" % (self.id, response)) return response
def task(etb, neighbor=neighbor): #etb.networking.log.debug('PING') if neighbor.proxy is not None: predicates = etb.interpret_state.predicates() payload = { 'load': etb.load , 'predicates': predicates , 'subscriptions': list(etb.subscriptions) , 'to_hosts': list(neighbor.hosts) , 'tasks': [] #list(etb.active_queries()) } neighbor.proxy.ping(etb.id, etb.networking.port, neighbor.id, terms.dumps(payload))
def get_contents_from_somewhere(self, sha1, seen=[]): """ Find the content corresponding to a sha1, don't b64encode it (its for local use). Presupposes it isn't to be had locally. Tries each neighbor, then ask any remote link, taking care not to chase ones tail. """ contents = None execp = False self.log.debug('Being asked for contents with sha1 %s' % sha1) #do my neighbours have it? for n in self.neighbors: if n.id != self.id: #self.log.debug('Asking for %s from neighbor: %s with proxy %s' % (sha1, n.id, n.proxy)) self.log.debug('Asking for %s from neighbor: %s' % (sha1, n.id)) with self._rlock: try: if n.proxy is not None: b64_contents, execp = n.proxy.get_blob(sha1) contents = base64.b64decode(b64_contents) if contents is not None and contents is not '': break except Exception as e: pass if contents is not None and contents is not '': self.log.debug('My neigbours had %s!' % sha1) return contents, execp self.log.debug('Not local, asking for %s from my links %s (seen = %s)' % (sha1, self.links, seen)) for n in self.links: with self._rlock: try: if n.proxy is not None and n.id not in seen: visited = list(seen) visited.append(n.id) visited = terms.dumps(visited) self.log.debug('Asking for %s from link: %s with proxy %s (visited = %s)' % (sha1, n.id, n.proxy, visited)) b64_contents, execp = n.proxy.get_contents_from_network(sha1, visited) contents = base64.b64decode(b64_contents) if contents is not None and contents is not '': break except Exception as e: self.log.debug('Asking for %s from link: %s **THREW** %s' % (sha1, n.id, e)) pass if contents is None: self.log.error('Could not find file %s', sha1) else: self.log.debug('My links had %s!' % sha1) return contents, execp
def get_goals_dependencies(self, goal, remote_etb): for a in goal.get_args(): if a.is_ground(): try: fileref = { 'file' : str(a.get_args()[terms.mk_stringconst('file')]), 'sha1' : str(a.get_args()[terms.mk_stringconst('sha1')]) } content = remote_etb.get_file(terms.dumps(a)) if content: content = base64.b64decode(content) self.create_file(content, fileref['file']) else: self.log.error('Unable to get remote file: %s', fileref) except Exception as e: # Non-fileref will go there pass
def query_claims(self, qid): """Returns the set of fact answers for this query. It returns a JSON-encoded list of lists of terms. Each 'fact' may have one or more claims to back it. Otherwise, returns False. """ goals = self.etb.get_query(qid) if not goals: print('Invalid query id: {0}'.format(qid)) return [] answers = [] for goal in goals: claims = self.etb.engine.get_claims_matching_goal(goal) for claim in claims: answers.append(claim.literal) return terms.dumps(answers)
def get_all_claims(self): """Get all the claims known by this node, as a JSON list""" claims = list(self.etb.engine.get_claims()) return terms.dumps(claims)
def get_neighbors(self): """Returns, over the network, a JSON list of current neighbors.""" neighbors = list() neighbors = [((n.id, list(n.hosts), n.port, n.timestamp)) for n in self.neighbors] return terms.dumps(neighbors)
def find_claims(self, pattern, reasons=False): """Find and return claims that match the given pattern. See the Python re module for possible patterns.""" claims = list(self.etb.find_claims(pattern)) return terms.dumps(claims)
def all_claims(self): self.log.debug('looking for all claims') claims = list(self.etb.all_claims()) return terms.dumps(claims)
def get_facts(self): """Get the list of facts on this node. This returns a more readable form of the facts.""" return terms.dumps(self.etb.engine.facts)
def get_rules(self): """Get the list of rules on this node. This returns a more readable form of the rules.""" return terms.dumps(self.etb.engine.rules)