Exemplo n.º 1
0
        rpc_paths = ('/RPC2', )

    # Create server
    server = SimpleXMLRPCServer(("localhost", port),
                                requestHandler=RequestHandler)
    # server.register_introspection_functions()

    server.register_function(xmlaction, 'action')
    server.register_function(xmlrcmd, 'rcmd')

    # This informs the action function that it is running
    log("Running")

    running = {}
    while (True):
        if (datawaiting(server.fileno())):
            log("Handled request.")
            server.handle_request()

        expired = []
        for context in running:
            program = running[context]
            # check to see if process has ended
            poll = program['proc'].wait(os.WNOHANG)
            if (poll == None):
                # It hasn't ended, update it's last seen time
                program['last'] = int(time.time())
            else:
                program['done'] = True
                if (int(time.time()) - program['last'] > 20):
                    # Been too long after it ended, destroy the buffer
Exemplo n.º 2
0
class ConnectionManager(Unpickable(topologyInfo=TopologyInfo,
                                   scheduledTasks=TimedSet.create,
                                   lock=PickableLock,
                                   alive=(bool, False),
                                   tags_file=str),
                        ICallbackAcceptor):
    def InitXMLRPCServer(self):
        self.rpcserver = SimpleXMLRPCServer(("", self.port), allow_none=True)
        self.rpcserver.register_function(self.set_tags, "set_tags")
        self.rpcserver.register_function(self.list_clients, "list_clients")
        self.rpcserver.register_function(self.list_tags, "list_tags")
        self.rpcserver.register_function(self.suspend_client, "suspend_client")
        self.rpcserver.register_function(self.resume_client, "resume_client")
        self.rpcserver.register_function(self.reload_config, "reload_config")
        self.rpcserver.register_function(self.register_share, "register_share")
        self.rpcserver.register_function(self.unregister_share, "unregister_share")
        self.rpcserver.register_function(self.get_client_info, "get_client_info")
        self.rpcserver.register_function(self.list_shares, "list_shares")
        self.rpcserver.register_function(self.list_subscriptions, "list_subscriptions")
        self.rpcserver.register_function(self.check_connection, "check_connection")
        self.rpcserver.register_function(self.ping, "ping")

    def UpdateContext(self, context):
        self.scheduler = context.Scheduler
        self.network_name = context.network_name
        self.tags_file = context.remote_tags_db_file
        self.port = context.system_port
        if self.tags_file:
            self.acceptors = bsddb3.btopen(self.tags_file, "c")
        self.topologyInfo.UpdateContext(context)
        self.max_remotetags_resend_delay = context.max_remotetags_resend_delay

    def Start(self):
        if not self.network_name or not self.tags_file or not self.port:
            logging.warning("ConnectionManager could'n start: wrong configuration. " +
                            "network_name: %s, remote_tags_db_file: %s, system_port: %r",
                            self.network_name, self.tags_file, self.port)
            return
        self.ReloadConfig()
        self.alive = True
        self.InitXMLRPCServer()
        threading.Thread(target=self.ServerLoop).start()
        for client in self.topologyInfo.servers.values():
            self.scheduler.ScheduleTask(0, self.SendData, client, skip_logging=True)

    def Stop(self):
        self.alive = False

    def ServerLoop(self):
        rpc_fd = self.rpcserver.fileno()
        while self.alive:
            rout, _, _ = select.select((rpc_fd,), (), (), 0.01)
            if rpc_fd in rout:
                self.rpcserver.handle_request()

    def SendData(self, client):
        if (len(client.subscriptions) > 0 or len(client.taglist) > 0) and client.active and self.alive:
            client.Connect()
            numTags = 1 if client.errorsCnt > 0 else client.MAX_TAGS_BULK
            tags = list(client.taglist)[:numTags]
            subscriptions = list(client.subscriptions)[:numTags]
            try:
                if len(tags) > 0:
                    logging.debug("SendData to %s: %d tags", client.name, len(tags))
                    client.connection.set_tags(tags)
                    client.taglist.difference_update(tags)

                if len(subscriptions) > 0:
                    logging.debug("SendData to %s: %d subscriptions", client.name, len(subscriptions))
                    client.connection.register_share(subscriptions, self.network_name)
                    client.subscriptions.difference_update(subscriptions)

                client.errorsCnt = 0
                logging.debug("SendData to %s: ok", client.name)
            except IOError as e:
                logging.warning("SendData to %s: failed", client.name)
                client.lastError = e
                client.errorsCnt += 1
            except Exception as e:
                logging.error("SendData to %s: failed: %s", client.name, e)
        if hasattr(self, "scheduler"):
            self.scheduler.ScheduleTask(
                min(client.PENALTY_FACTOR ** client.errorsCnt, self.max_remotetags_resend_delay),
                self.SendData,
                client,
                skip_logging=True
            )

    def OnDone(self, tag):
        if not self.alive:
            return
        if not isinstance(tag, Tag):
            logging.error("%s is not Tag class instance", tag.GetName())
            return
        tagname = tag.GetName()
        if not tag.IsRemote():
            acceptors = self.GetTagAcceptors(tagname)
            if acceptors:
                logging.debug("ondone connmanager %s with acceptors list %s", tagname, acceptors)
                for clientname in acceptors:
                    self.SetTag(tagname, clientname)

    def SetTag(self, tagname, clientname):
        logging.debug("set remote tag %s on host %s", tagname, clientname)
        client = self.topologyInfo.GetClient(clientname, checkname=False)
        if client is None:
            logging.error("unknown client %s appeared", clientname)
            return False
        client.SetTag("%s:%s" % (self.network_name, tagname))

    def ReloadConfig(self, filename=None):
        old_servers = set(self.topologyInfo.servers.keys())
        self.topologyInfo.ReloadConfig()
        new_servers = set(self.topologyInfo.servers.keys())
        new_servers -= old_servers
        if self.alive:
            for client in new_servers:
                self.scheduler.ScheduleTask(0, self.SendData, self.topologyInfo.servers[client], skip_logging=True)

    def GetTagAcceptors(self, tagname):
        if self.acceptors.has_key(tagname):
            data = self.acceptors[tagname]
            return cPickle.loads(data)
        return set()

    def AddTagAcceptor(self, tagname, clientname):
        with self.lock:
            subscribers = self.GetTagAcceptors(tagname)
            subscribers.add(clientname)
            self.acceptors[tagname] = cPickle.dumps(subscribers)
            self.acceptors.sync()

    def RemoveTagAcceptor(self, tagname, clientname):
        with self.lock:
            subscribers = self.GetTagAcceptors(tagname)
            if clientname not in subscribers:
                return False
            subscribers.discard(clientname)
            self.acceptors[tagname] = cPickle.dumps(subscribers)
            self.acceptors.sync()
            return True

    def Subscribe(self, tag):
        if tag.IsRemote():
            client = self.topologyInfo.GetClient(tag.GetRemoteHost(), checkname=True)
            client.Subscribe(tag.GetName())
            return True
        return False

    @traced_rpc_method()
    def set_tags(self, tags):
        logging.debug("set %d remote tags", len(tags))
        for tagname in tags:
            self.scheduler.tagRef.SetRemoteTag(tagname)
        return True

    @traced_rpc_method()
    def list_clients(self):

        return [{"name": client.name,
                 "url": client.url,
                 "systemUrl": client.systemUrl,
                 "active": client.active,
                 "errorsCount": client.errorsCnt,
                 "tagsCount": len(client.taglist),
                 "subscriptionsCount": len(client.subscriptions),
                 "lastError": str(client.lastError)} for client in self.topologyInfo.servers.values()]

    @traced_rpc_method()
    def list_tags(self, name_prefix):
        data = set()
        for server in self.topologyInfo.servers.values():
            if name_prefix is None or server.name.startswith(name_prefix):
                data.update(server.taglist)
        return list(data)

    @traced_rpc_method()
    def suspend_client(self, name):
        client = self.topologyInfo.GetClient(name)
        return client.Suspend()

    @traced_rpc_method()
    def resume_client(self, name):
        client = self.topologyInfo.GetClient(name)
        return client.Resume()

    @traced_rpc_method()
    def reload_config(self, location=None):
        self.ReloadConfig(location)

    @traced_rpc_method()
    def register_share(self, tags, clientname):
        if not isinstance(tags, list):
            tags = [tags]
        for tagname in tags:
            self.AddTagAcceptor(tagname, clientname)
            if self.scheduler.tagRef.CheckTag(tagname):
                self.SetTag(tagname, clientname)

    @traced_rpc_method()
    def unregister_share(self, tagname, clientname):
        return self.RemoveTagAcceptor(tagname, clientname)

    @traced_rpc_method()
    def get_client_info(self, clientname):
        client = self.topologyInfo.GetClient(clientname)
        res = {"name": client.name,
               "url": client.url,
               "systemUrl": client.systemUrl,
               "active": client.active,
               "errorsCount": client.errorsCnt,
               "deferedTagsCount": len(client.taglist),
               "subscriptionsCount": len(client.subscriptions),
               "lastError": str(client.lastError)}
        return res

    @traced_rpc_method()
    def list_shares(self, clientname):
        client = self.topologyInfo.GetClient(clientname)
        return list(client.taglist)

    @traced_rpc_method()
    def list_subscriptions(self, clientname):
        client = self.topologyInfo.GetClient(clientname)
        return list(client.subscriptions)

    @traced_rpc_method()
    def check_connection(self, clientname):
        client = self.topologyInfo.GetClient(clientname)
        return client.connection.ping()

    @traced_rpc_method()
    def ping(self):
        return True

    def __getstate__(self):
        sdict = self.__dict__.copy()
        sdict["scheduledTasks"] = self.scheduledTasks.copy()
        sdict.pop("scheduler", None)
        sdict.pop("rpcserver", None)
        sdict.pop("acceptors", None)
        sdict["alive"] = False
        return getattr(super(ConnectionManager, self), "__getstate__", lambda: sdict)()
Exemplo n.º 3
0
class Sync(gtk.VBox):

	__gsignals__ = {
		'syncFinished' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_STRING, )),
		'syncBeforeStart' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_STRING, )),
	}

	def __init__(self, db, parentwindow, port):
		gtk.VBox.__init__(self, homogeneous = False, spacing = 0)

		_moduleLogger.info("Sync, init")
		self.db = db
		self.progress = None
		self.server = None
		self.port = int(port)
		self.parentwindow = parentwindow
		self.concernedRows = None

		#print "Sync, 2"
		#sql = "DROP TABLE sync"
		#self.db.speichereSQL(sql, log = False)

		sql = "CREATE TABLE sync (id INTEGER PRIMARY KEY, syncpartner TEXT, uuid TEXT, pcdatum INTEGER)"
		self.db.speichereSQL(sql, log = False)

		#print "Sync, 3"

		sql = "SELECT uuid, pcdatum FROM sync WHERE syncpartner = ?"
		rows = self.db.ladeSQL(sql, ("self", )) #Eigene Id feststellen

		#print "Sync, 3a"
		if (rows == None)or(len(rows) != 1):
			sql = "DELETE FROM sync WHERE syncpartner = ?"
			self.db.speichereSQL(sql, ("self", ), log = False)

			#uuid1 = uuid()
			#print "Sync, 3b"

			#print "Sync, 3bb"
			self.sync_uuid = str(uuid.uuid4())
			sql = "INSERT INTO sync (syncpartner, uuid, pcdatum) VALUES (?, ?, ?)"
			self.db.speichereSQL(sql, ("self", str(self.sync_uuid), int(time.time())), log = False)
			#print "Sync, 3c"
		else:
			sync_uuid, pcdatum = rows[0]
			self.sync_uuid = sync_uuid
		#print "x1"
		#print "Sync, 4"

		frame = gtk.Frame(_("Local SyncServer (port ")+str(self.port)+")")
		self.comboIP = gtk.combo_box_entry_new_text()
		self.comboIP.append_text("") #self.get_ip_address("eth0"))
		#self.comboIP.append_text(self.get_ip_address("eth1")) #fixme
		#self.comboIP.append_text(self.get_ip_address("eth2"))
		#self.comboIP.append_text(self.get_ip_address("eth3"))
		#print "Sync, 4d"
		#self.comboIP.append_text(self.get_ip_address("wlan0"))
		#self.comboIP.append_text(self.get_ip_address("wlan1"))

		#print "Sync, 4e"

		frame.add(self.comboIP)
		serverbutton = gtk.ToggleButton(_("Start SyncServer"))
		serverbutton.connect("clicked", self.startServer, (None, ))
		self.pack_start(frame, expand = False, fill = True, padding = 1)
		self.pack_start(serverbutton, expand = False, fill = True, padding = 1)
		self.syncServerStatusLabel = gtk.Label(_("Syncserver not running"))
		self.pack_start(self.syncServerStatusLabel, expand = False, fill = True, padding = 1)

		frame = gtk.Frame(_("RemoteSync-Server (Port ")+str(self.port)+")")
		self.comboRemoteIP = gtk.combo_box_entry_new_text()
		self.comboRemoteIP.append_text("192.168.0.?")
		self.comboRemoteIP.append_text("192.168.1.?")
		self.comboRemoteIP.append_text("192.168.176.?")
		frame.add(self.comboRemoteIP)
		syncbutton = gtk.Button(_("Connect to remote SyncServer"))
		syncbutton.connect("clicked", self.syncButton, (None, ))
		self.pack_start(frame, expand = False, fill = True, padding = 1)
		self.pack_start(syncbutton, expand = False, fill = True, padding = 1)
		self.syncStatusLabel = gtk.Label(_("no sync process (at the moment)"))
		self.pack_start(self.syncStatusLabel, expand = False, fill = True, padding = 1)

		#self.comboRemoteIP.set_text_column("Test")
		self.comboRemoteIP.get_child().set_text(self.db.ladeDirekt("syncRemoteIP"))
		self.comboIP.get_child().set_text(self.db.ladeDirekt("syncServerIP"))

		#load
		if (self.db.ladeDirekt("startSyncServer", False) == True):
			serverbutton.set_active(True)

	def changeSyncStatus(self, active, title):
		self.syncStatusLabel.set_text(title)
		if active == True:
			if self.progress == None:
				self.progress = ProgressDialog(parent = self.parentwindow)
				self.emit("syncBeforeStart", "syncBeforeStart")
		else:
			if self.progress is not None:
				self.progress.hide()
				self.progress.destroy()
				self.progress = None
				self.emit("syncFinished", "syncFinished")

	def pulse(self):
		if self.progress is not None:
			self.progress.pulse()
		#if self.server is not None:
		#	self.server.pulse()

	def getUeberblickBox(self):
		frame = gtk.Frame(_("Query"))
		return frame

	def handleRPC(self):
		try:
			if self.rpcserver is None:
				return False
		except:
			return False

		while 0 < len(self.poll.poll(0)):
			self.rpcserver.hande_request()
		return True

	def get_ip_address(self, ifname):
		return socket.gethostbyname(socket.gethostname())
		#try:
		#	s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
		#	ip = socket.inet_ntoa(fcntl.ioctl(s.fileno(), 0x8915, struct.pack('256s', ifname[:15]))[20:24])
		#	s.close()
		#except:
		#	ip = socket.gethostbyname(socket.gethostname())
		#	s.close()

		#return ip FixME

	def getLastSyncDate(self, sync_uuid):
		sql = "SELECT syncpartner, pcdatum FROM sync WHERE uuid = ?"
		rows = self.db.ladeSQL(sql, (sync_uuid, ))
		if (rows is not None)and(len(rows) == 1):
			syncpartner, pcdatum = rows[0]
		else:
			pcdatum = -1
		_moduleLogger.info("LastSyncDatum: "+str(pcdatum)+" Jetzt "+str(int(time.time())))
		return pcdatum

	def check4commit(self, newSQL, lastdate):
		_moduleLogger.info("check4commit 1")
		if self.concernedRows == None:
			_moduleLogger.info("check4commit Updatung concernedRows")
			sql = "SELECT pcdatum, rowid FROM logtable WHERE pcdatum>? ORDER BY pcdatum DESC"
			self.concernedRows = self.db.ladeSQL(sql, (lastdate, ))

		if (self.concernedRows is not None)and(len(self.concernedRows)>0):
			#_moduleLogger.info("check4commit 2")
			id1, pcdatum, sql, param, host, rowid = newSQL

			if len(rowid)>0:
				for x in self.concernedRows:
					#_moduleLogger.info("check4commit 3")
					if (x[1] == rowid):
						if (x[0]>pcdatum):
							_moduleLogger.info("newer sync entry, ignoring old one")
							#_moduleLogger.info("check4commit 9.1")
							return False
						else:
							#_moduleLogger.info("check4commit 9.2")
							return True

		#_moduleLogger.info("check4commit 9.3")
		return True

	def writeSQLTupel(self, newSQLs, lastdate):
		if newSQLs is None:
			return

		self.concernedRows = None
		pausenzaehler = 0
		_moduleLogger.info("writeSQLTupel got "+str(len(newSQLs))+" sql tupels")
		for newSQL in newSQLs:
			#print ""
			#print "SQL1: ", newSQL[1]
			#print "SQL2: ", newSQL[2]
			#print "SQL3: ", newSQL[3]
			#print "Param:", string.split(newSQL[3], " <<Tren-ner>> ")
			#print ""
			if (newSQL[3] != ""):
				param = string.split(newSQL[3], " <<Tren-ner>> ")
			else:
				param = None

			if (len(newSQL)>2):
				commitSQL = True

				if (newSQL[5] is not None)and(len(newSQL[5])>0):
					commitSQL = self.check4commit(newSQL, lastdate)

				if commitSQL:
					self.db.speichereSQL(newSQL[2], param, commit = False, pcdatum = newSQL[1], rowid = newSQL[5])
			else:
				_moduleLogger.error("writeSQLTupel: Error")

			pausenzaehler += 1
			if (pausenzaehler % 10) == 0:
				self.pulse()
				while gtk.events_pending():
					gtk.main_iteration()

		_moduleLogger.info("Alle SQLs an sqlite geschickt, commiting now")
		self.db.commitSQL()
		_moduleLogger.info("Alle SQLs commited")

	def doSync(self, sync_uuid, pcdatum, newSQLs, pcdatumjetzt):
		#print uuid, pcdatum, newSQLs
		#_moduleLogger.info("doSync 0")
		self.changeSyncStatus(True, _("sync process running"))
		self.pulse()
		#_moduleLogger.info("doSync 1")

		while gtk.events_pending():
			gtk.main_iteration();
		diff = abs(time.time() - pcdatumjetzt)
		if 30 < diff:
			return -1

		_moduleLogger.info("doSync read sqls")
		sql = "SELECT * FROM logtable WHERE pcdatum>?"
		rows = self.db.ladeSQL(sql, (pcdatum, ))
		_moduleLogger.info("doSync read sqls")
		self.writeSQLTupel(newSQLs, pcdatum)
		_moduleLogger.info("doSync wrote "+str(len(newSQLs))+" sqls")
		_moduleLogger.info("doSync sending "+str(len(rows))+" sqls")
		return rows

	def getRemoteSyncUUID(self):
		return self.sync_uuid

	@gtk_toolbox.log_exception(_moduleLogger)
	def startServer(self, widget, data = None):
		#Starte RPCServer
		self.db.speichereDirekt("syncServerIP", self.comboIP.get_child().get_text())

		if (widget.get_active() == True):
			_moduleLogger.info("Starting Server")

			try:
				ip = self.comboIP.get_child().get_text()
				self.rpcserver = SimpleXMLRPCServer((ip, self.port), allow_none = True)
				self.rpcserver.register_function(pow)
				self.rpcserver.register_function(self.getLastSyncDate)
				self.rpcserver.register_function(self.doSync)
				self.rpcserver.register_function(self.getRemoteSyncUUID)
				self.rpcserver.register_function(self.doSaveFinalTime)
				self.rpcserver.register_function(self.pulse)
				self.poll = select.poll()
				self.poll.register(self.rpcserver.fileno())
				gobject.timeout_add(1000, self.handleRPC)
				self.syncServerStatusLabel.set_text(_("Syncserver running..."))

				#save
				self.db.speichereDirekt("startSyncServer", True)

			except:
				s = str(sys.exc_info())
				_moduleLogger.error("libsync: could not start server. Error: "+s)
				mbox = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, _("Sync server could not start. Please check IP and port.")) #gtk.DIALOG_MODAL
				mbox.set_modal(False)
				response = mbox.run()
				mbox.hide()
				mbox.destroy()
				widget.set_active(False)
		else:
			_moduleLogger.info("Stopping Server")
			try:
				del self.rpcserver
			except:
				pass
			self.syncServerStatusLabel.set_text(_("Syncserver not running..."))
			#save
			self.db.speichereDirekt("startSyncServer", False)

	def doSaveFinalTime(self, sync_uuid, pcdatum = None):
		if pcdatum is None:
			pcdatum = int(time.time())
		if (time.time()>pcdatum):
			pcdatum = int(time.time()) #größere Zeit nehmen

		self.pulse()

		#fime save time+uuid
		sql = "DELETE FROM sync WHERE uuid = ?"
		self.db.speichereSQL(sql, (sync_uuid, ), log = False)
		sql = "INSERT INTO sync (syncpartner, uuid, pcdatum) VALUES (?, ?, ?)"
		self.db.speichereSQL(sql, ("x", str(sync_uuid), pcdatum), log = False)
		self.pulse()
		self.changeSyncStatus(False, _("no sync process (at the moment)"))
		return (self.sync_uuid, pcdatum)

	@gtk_toolbox.log_exception(_moduleLogger)
	def syncButton(self, widget, data = None):
		_moduleLogger.info("Syncing")
		#sql = "DELETE FROM logtable WHERE sql LIKE externeStundenplanung"
		#self.db.speichereSQL(sql)

		self.changeSyncStatus(True, _("sync process running"))
		while (gtk.events_pending()):
			gtk.main_iteration()

		self.db.speichereDirekt("syncRemoteIP", self.comboRemoteIP.get_child().get_text())
		try:
			self.server = xmlrpclib.ServerProxy("http://"+self.comboRemoteIP.get_child().get_text()+":"+str(self.port), allow_none = True)
			#lastDate = server.getLastSyncDate(str(self.sync_uuid))
			server_sync_uuid = self.server.getRemoteSyncUUID()
			lastDate = self.getLastSyncDate(str(server_sync_uuid))

			#print ("LastSyncDate: "+str(lastDate)+" Now: "+str(int(time.time())))

			sql = "SELECT * FROM logtable WHERE pcdatum>?"
			rows = self.db.ladeSQL(sql, (lastDate, ))

			_moduleLogger.info("loaded concerned rows")

			newSQLs = self.server.doSync(self.sync_uuid, lastDate, rows, time.time())

			_moduleLogger.info("did do sync, processing sqls now")
			if newSQLs != -1:
				self.writeSQLTupel(newSQLs, lastDate)

				sync_uuid, finalpcdatum = self.server.doSaveFinalTime(self.sync_uuid)
				self.doSaveFinalTime(sync_uuid, finalpcdatum)

				self.changeSyncStatus(False, _("no sync process (at the moment)"))

				mbox =  gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, _("Synchronization successfully completed"))
				response = mbox.run()
				mbox.hide()
				mbox.destroy()
			else:
				_moduleLogger.warning("Zeitdiff zu groß/oder anderer db-Fehler")
				self.changeSyncStatus(False, _("no sync process (at the moment)"))
				mbox =  gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, _("The clocks are not synchronized between stations"))
				response = mbox.run()
				mbox.hide()
				mbox.destroy()
		except:
			_moduleLogger.warning("Sync connect failed")
			self.changeSyncStatus(False, _("no sync process (at the moment)"))
			mbox =  gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, _("Sync failed, reason: ")+unicode(sys.exc_info()[1][1]))
			response = mbox.run()
			mbox.hide()
			mbox.destroy()
			self.server = None
		self.server = None
Exemplo n.º 4
0
	server = SimpleXMLRPCServer(("localhost", port),requestHandler=RequestHandler)
	# server.register_introspection_functions()


	server.register_function(xmlaction, 'action')
	server.register_function(xmlrcmd,   'rcmd')
	
	
	
	# This informs the action function that it is running
	log("Running")

		
	running={}
	while(True):
		if(datawaiting(server.fileno())):
			log("Handled request.")
			server.handle_request()
		
		expired=[]
		for context in running:
			program=running[context]
			# check to see if process has ended
			poll = program['proc'].wait(os.WNOHANG)
			if(poll == None):
				# It hasn't ended, update it's last seen time
				program['last']=int(time.time())
			else:
				program['done']=True
				if(int(time.time())-program['last'] > 20):
					# Been too long after it ended, destroy the buffer
Exemplo n.º 5
0
class ConnectionManager(Unpickable(topologyInfo=TopologyInfo,
                                   scheduledTasks=TimedSet.create,
                                   lock=PickableLock,
                                   alive=(bool, False),
                                   tags_file=str),
                        ICallbackAcceptor):
    def InitXMLRPCServer(self):
        self.rpcserver = SimpleXMLRPCServer(("", self.port), allow_none=True)
        self.rpcserver.register_function(self.set_tags, "set_tags")
        self.rpcserver.register_function(self.list_clients, "list_clients")
        self.rpcserver.register_function(self.list_tags, "list_tags")
        self.rpcserver.register_function(self.suspend_client, "suspend_client")
        self.rpcserver.register_function(self.resume_client, "resume_client")
        self.rpcserver.register_function(self.reload_config, "reload_config")
        self.rpcserver.register_function(self.register_share, "register_share")
        self.rpcserver.register_function(self.unregister_share, "unregister_share")
        self.rpcserver.register_function(self.get_client_info, "get_client_info")
        self.rpcserver.register_function(self.list_shares, "list_shares")
        self.rpcserver.register_function(self.list_subscriptions, "list_subscriptions")
        self.rpcserver.register_function(self.check_connection, "check_connection")
        self.rpcserver.register_function(self.ping, "ping")

    def UpdateContext(self, context):
        self.scheduler = context.Scheduler
        self.network_name = context.network_name
        self.tags_file = context.remote_tags_db_file
        self.port = context.system_port
        if self.tags_file:
            self.acceptors = bsddb3.btopen(self.tags_file, "c")
        self.topologyInfo.UpdateContext(context)
        self.max_remotetags_resend_delay = context.max_remotetags_resend_delay

    def Start(self):
        if not self.network_name or not self.tags_file or not self.port:
            logging.warning("ConnectionManager could'n start: wrong configuration. " +
                            "network_name: %s, remote_tags_db_file: %s, system_port: %r",
                            self.network_name, self.tags_file, self.port)
            return
        self.ReloadConfig()
        self.alive = True
        self.InitXMLRPCServer()
        threading.Thread(target=self.ServerLoop).start()
        for client in self.topologyInfo.servers.values():
            self.scheduler.ScheduleTaskT(0, self.SendData, client, skip_logging=True)

    def Stop(self):
        self.alive = False

    def ServerLoop(self):
        rpc_fd = self.rpcserver.fileno()
        while self.alive:
            rout, _, _ = select.select((rpc_fd,), (), (), 0.01)
            if rpc_fd in rout:
                self.rpcserver.handle_request()

    def SendData(self, client):
        if (len(client.subscriptions) > 0 or len(client.taglist) > 0) and client.active and self.alive:
            client.Connect()
            numTags = 1 if client.errorsCnt > 0 else client.MAX_TAGS_BULK
            tags = list(client.taglist)[:numTags]
            subscriptions = list(client.subscriptions)[:numTags]
            try:
                if len(tags) > 0:
                    logging.debug("SendData to %s: %d tags", client.name, len(tags))
                    client.connection.set_tags(tags)
                    client.taglist.difference_update(tags)

                if len(subscriptions) > 0:
                    logging.debug("SendData to %s: %d subscriptions", client.name, len(subscriptions))
                    client.connection.register_share(subscriptions, self.network_name)
                    client.subscriptions.difference_update(subscriptions)

                client.errorsCnt = 0
                logging.debug("SendData to %s: ok", client.name)
            except IOError as e:
                logging.warning("SendData to %s: failed", client.name)
                client.lastError = e
                client.errorsCnt += 1
            except Exception as e:
                logging.error("SendData to %s: failed: %s", client.name, e)
        if hasattr(self, "scheduler"):
            self.scheduler.ScheduleTaskT(
                min(client.PENALTY_FACTOR ** client.errorsCnt, self.max_remotetags_resend_delay),
                self.SendData,
                client,
                skip_logging=True
            )

    def OnDone(self, tag):
        if not self.alive:
            return
        if not isinstance(tag, Tag):
            logging.error("%s is not Tag class instance", tag.GetName())
            return
        tagname = tag.GetName()
        if not tag.IsRemote():
            acceptors = self.GetTagAcceptors(tagname)
            if acceptors:
                logging.debug("ondone connmanager %s with acceptors list %s", tagname, acceptors)
                for clientname in acceptors:
                    self.SetTag(tagname, clientname)

    def SetTag(self, tagname, clientname):
        logging.debug("set remote tag %s on host %s", tagname, clientname)
        client = self.topologyInfo.GetClient(clientname, checkname=False)
        if client is None:
            logging.error("unknown client %s appeared", clientname)
            return False
        client.SetTag("%s:%s" % (self.network_name, tagname))

    def ReloadConfig(self, filename=None):
        old_servers = set(self.topologyInfo.servers.keys())
        self.topologyInfo.ReloadConfig()
        new_servers = set(self.topologyInfo.servers.keys())
        new_servers -= old_servers
        if self.alive:
            for client in new_servers:
                self.scheduler.ScheduleTaskT(0, self.SendData, self.topologyInfo.servers[client], skip_logging=True)

    def GetTagAcceptors(self, tagname):
        if self.acceptors.has_key(tagname):
            data = self.acceptors[tagname]
            return cPickle.loads(data)
        return set()

    def AddTagAcceptor(self, tagname, clientname):
        with self.lock:
            subscribers = self.GetTagAcceptors(tagname)
            subscribers.add(clientname)
            self.acceptors[tagname] = cPickle.dumps(subscribers)
            self.acceptors.sync()

    def RemoveTagAcceptor(self, tagname, clientname):
        with self.lock:
            subscribers = self.GetTagAcceptors(tagname)
            if clientname not in subscribers:
                return False
            subscribers.discard(clientname)
            self.acceptors[tagname] = cPickle.dumps(subscribers)
            self.acceptors.sync()
            return True

    def Subscribe(self, tag):
        if tag.IsRemote():
            client = self.topologyInfo.GetClient(tag.GetRemoteHost(), checkname=True)
            client.Subscribe(tag.GetName())
            return True
        return False

    @traced_rpc_method()
    def set_tags(self, tags):
        logging.debug("set %d remote tags", len(tags))
        for tagname in tags:
            self.scheduler.tagRef.SetRemoteTag(tagname)
        return True

    @traced_rpc_method()
    def list_clients(self):

        return [{"name": client.name,
                 "url": client.url,
                 "systemUrl": client.systemUrl,
                 "active": client.active,
                 "errorsCount": client.errorsCnt,
                 "tagsCount": len(client.taglist),
                 "subscriptionsCount": len(client.subscriptions),
                 "lastError": str(client.lastError)} for client in self.topologyInfo.servers.values()]

    @traced_rpc_method()
    def list_tags(self, name_prefix):
        data = set()
        for server in self.topologyInfo.servers.values():
            if name_prefix is None or server.name.startswith(name_prefix):
                data.update(server.taglist)
        return list(data)

    @traced_rpc_method()
    def suspend_client(self, name):
        client = self.topologyInfo.GetClient(name)
        return client.Suspend()

    @traced_rpc_method()
    def resume_client(self, name):
        client = self.topologyInfo.GetClient(name)
        return client.Resume()

    @traced_rpc_method()
    def reload_config(self, location=None):
        self.ReloadConfig(location)

    @traced_rpc_method()
    def register_share(self, tags, clientname):
        if not isinstance(tags, list):
            tags = [tags]
        for tagname in tags:
            self.AddTagAcceptor(tagname, clientname)
            if self.scheduler.tagRef.CheckTag(tagname):
                self.SetTag(tagname, clientname)

    @traced_rpc_method()
    def unregister_share(self, tagname, clientname):
        return self.RemoveTagAcceptor(tagname, clientname)

    @traced_rpc_method()
    def get_client_info(self, clientname):
        client = self.topologyInfo.GetClient(clientname)
        res = {"name": client.name,
               "url": client.url,
               "systemUrl": client.systemUrl,
               "active": client.active,
               "errorsCount": client.errorsCnt,
               "deferedTagsCount": len(client.taglist),
               "subscriptionsCount": len(client.subscriptions),
               "lastError": str(client.lastError)}
        return res

    @traced_rpc_method()
    def list_shares(self, clientname):
        client = self.topologyInfo.GetClient(clientname)
        return list(client.taglist)

    @traced_rpc_method()
    def list_subscriptions(self, clientname):
        client = self.topologyInfo.GetClient(clientname)
        return list(client.subscriptions)

    @traced_rpc_method()
    def check_connection(self, clientname):
        client = self.topologyInfo.GetClient(clientname)
        return client.connection.ping()

    @traced_rpc_method()
    def ping(self):
        return True

    def __getstate__(self):
        sdict = self.__dict__.copy()
        sdict["scheduledTasks"] = self.scheduledTasks.copy()
        sdict.pop("scheduler", None)
        sdict.pop("rpcserver", None)
        sdict.pop("acceptors", None)
        sdict["alive"] = False
        return getattr(super(ConnectionManager, self), "__getstate__", lambda: sdict)()