def __init__(self): self._git = None self._collaborationFrom = None self._collaborationTo = None self._no_collaboration = False self._localrepo = Config().datastore if Config().datastore else None self._response_queue = Queue.Queue(0) pymt.event.EventDispatcher.__init__(self) self._outstanding_events = 0 # Create the asynchronous objects if self._localrepo: self._git = GitManager(self._localrepo, not Config().sharedRepoNotAvailable, self._response_queue, log=Log) if not Config().collaborationNotAvailable: self._collaborationFrom = ServerManager(\ response_queue=self._response_queue, host='0.0.0.0', port=Config().local_port, log=Log) self._collaborationTo = ToCollaboration(\ self._response_queue, host='0.0.0.0', port=Config().collaboration_port, log=Log) else: self._no_collaboration = True # These are the events we will dispatch self.register_event_type(ON_GITSAVE) self.register_event_type(ON_GITCOMMIT) self.register_event_type(ON_GITMV) self.register_event_type(ON_GITRM) self.register_event_type(ON_GITHUBNOTIFICATION) self.register_event_type(ON_SUBSCRIPTION_RESPONSE) # We will get notified from the main event loop on each loop # iteration pymt.base.getWindow().push_handlers(self) # Start the asynchronous processing threads if self._localrepo: self._git.start() if not self._no_collaboration: self._collaborationFrom.start() self._collaborationTo.start() self.subscribe(True)
class Async(pymt.event.EventDispatcher): def __init__(self): self._git = None self._collaborationFrom = None self._collaborationTo = None self._no_collaboration = False self._localrepo = Config().datastore if Config().datastore else None self._response_queue = Queue.Queue(0) pymt.event.EventDispatcher.__init__(self) self._outstanding_events = 0 # Create the asynchronous objects if self._localrepo: self._git = GitManager(self._localrepo, not Config().sharedRepoNotAvailable, self._response_queue, log=Log) if not Config().collaborationNotAvailable: self._collaborationFrom = ServerManager(\ response_queue=self._response_queue, host='0.0.0.0', port=Config().local_port, log=Log) self._collaborationTo = ToCollaboration(\ self._response_queue, host='0.0.0.0', port=Config().collaboration_port, log=Log) else: self._no_collaboration = True # These are the events we will dispatch self.register_event_type(ON_GITSAVE) self.register_event_type(ON_GITCOMMIT) self.register_event_type(ON_GITMV) self.register_event_type(ON_GITRM) self.register_event_type(ON_GITHUBNOTIFICATION) self.register_event_type(ON_SUBSCRIPTION_RESPONSE) # We will get notified from the main event loop on each loop # iteration pymt.base.getWindow().push_handlers(self) # Start the asynchronous processing threads if self._localrepo: self._git.start() if not self._no_collaboration: self._collaborationFrom.start() self._collaborationTo.start() self.subscribe(True) def logAsyncInfo(self, ret): if ret is None: return msg = ret[1] # Log stdout messages if len(msg) <= 1: pass if msg[1]: for l in msg[1]: Log.info(l) # Log stderr messages if msg[2]: for l in msg[2]: if msg[0] == 0: Log.info(l) else: Log.error(l) def on_gitsave(self, ret): self._outstanding_events -= 1 Log.debug('Git save completed - outstanding events %s'\ % self._outstanding_events) assert(self._outstanding_events >= 0) self.logAsyncInfo(ret) def on_gitcommit(self, ret): self._outstanding_events -= 1 Log.debug('Git commit completed - outstanding events %s'\ % self._outstanding_events) assert(self._outstanding_events >= 0) self.logAsyncInfo(ret) def on_gitmv(self, ret): self._outstanding_events -= 1 Log.debug('Git mv completed - outstanding events %s'\ % self._outstanding_events) assert(self._outstanding_events >= 0) self.logAsyncInfo(ret) def on_gitrm(self, ret): self._outstanding_events -= 1 Log.debug('Git rm completed - outstanding events %s'\ % self._outstanding_events) assert(self._outstanding_events >= 0) self.logAsyncInfo(ret) def on_githubnotification(self, ret): msg = ret[1] Log.debug('Handle Github notification') user = Config().collaborationUser need_pull = False for c in msg['commits']: if user != c['author']['email']: need_pull = True if need_pull: self.save(None, 'Received notification of new content from Github') def on_subscriptionresponse(self, ret): self._outstanding_events -= 1 assert(self._outstanding_events >= 0) msg = ret[1] Log.debug('Got subscription response: %s'\ % 'accepted' if msg[0] == httplib.OK else 'rejected') if msg[0] != httplib.OK: if len(msg) > 2 and len(msg[2]) > 2 and msg[2][2] is not None: Log.error('Problematic HTTP response: %s' % str(msg[2])) else: Log.error('Subscription call failed: result: %i reason: %s' % (msg[0], str(msg[1]))) def on_update(self): ''' The main event loop is telling us to check if we have anything queued from any of our asynchronous processes. If so let our subscribers know ''' try: while True: # drain the event queue ret = self._response_queue.get(False) # Dispatch the event to the registered handlers Log.debug('About to dispatch %s' % str(ret)) self.dispatch_event(handler_mapper[ret[0]][ret[1][0]], ret[1]) except Queue.Empty: pass def isEmpty(self): return self._response_queue.empty() def save(self, files, message): if not self._localrepo: return # Local repo not present - don't do anything Git related self._outstanding_events += 1 self._git.save(files, message) def commit(self, files, message): if not self._localrepo: return self._outstanding_events += 1 Log.debug('About to run Git commit: %s' % self._outstanding_events) self._git.commit(files, message) def mv(self, old, new): self._outstanding_events += 1 Log.debug('About to run Git mv: %s' % self._outstanding_events) self._git.mv(old, new) def rm(self, target): self._outstanding_events += 1 Log.debug('About to run Git rm: %s' % self._outstanding_events) self._git.rm(target) def subscribe(self, on): if self._no_collaboration: return msg = self._collaborationTo.constructSubscriptionMsg(\ on, Config().gitSubscription, Config().collaborationResponseUrl, Config().local_port, Config().collaborationUser, testing=Config().testingServer) Log.debug('About to change subscription status %s' % on) self._outstanding_events += 1 self._collaborationTo.subscribe(msg, Config().collaborationServerUrl, Config().collaboration_port, Log.warning) def shutdown(self): # We need to handle any outstanding events before we shutdown try: if self._collaborationTo: # Unsubscribe from the collaboration server self.subscribe(False) while self._git and self._outstanding_events > 0: try: ret = self._response_queue.get(True, SHUTDOWN_TIMEOUT) Log.debug('Async return in shutdown: %s' % str(ret)) if not ret or not ret[1]: continue if ret[1][0] == SHUTDOWN: continue # No event handler for shutdown self.dispatch_event(handler_mapper[ret[0]][ret[1][0]], ret[1]) except Queue.Empty: self._outstanding_events = 0 finally: if self._collaborationFrom and not self._collaborationFrom.broken: self._collaborationFrom.server.shutdown() self._collaborationFrom = None if self._collaborationTo: self._collaborationTo.shutdown() self._collaborationTo = None if self._git: ret = self._git.shutdown() self._git = None # Prevent recursive shutdown if ret is not None: self.logAsyncInfo(ret[1]) self._outstanding_events = 0