Add sessionhandler.portal_disconnect_all to remove another needless call between server and portal on logout. This means logout from either side will clean up on the respective side and then inform the other side once, rather than triggering a return call.
This commit is contained in:
parent
8eb500f8e0
commit
86c970eb62
7 changed files with 54 additions and 9 deletions
|
|
@ -118,8 +118,8 @@ class CmdShutdown(COMMAND_DEFAULT_CLASS):
|
||||||
announcement += "%s\n" % self.args
|
announcement += "%s\n" % self.args
|
||||||
logger.log_info('Server shutdown by %s.' % self.caller.name)
|
logger.log_info('Server shutdown by %s.' % self.caller.name)
|
||||||
SESSIONS.announce_all(announcement)
|
SESSIONS.announce_all(announcement)
|
||||||
SESSIONS.server.shutdown(mode='shutdown')
|
|
||||||
SESSIONS.portal_shutdown()
|
SESSIONS.portal_shutdown()
|
||||||
|
SESSIONS.server.shutdown(mode='shutdown')
|
||||||
|
|
||||||
|
|
||||||
class CmdPy(COMMAND_DEFAULT_CLASS):
|
class CmdPy(COMMAND_DEFAULT_CLASS):
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ SSHUTD = chr(7) # server shutdown
|
||||||
SSYNC = chr(8) # server session sync
|
SSYNC = chr(8) # server session sync
|
||||||
SCONN = chr(11) # server creating new connection (for irc/imc2 bots etc)
|
SCONN = chr(11) # server creating new connection (for irc/imc2 bots etc)
|
||||||
PCONNSYNC = chr(12) # portal post-syncing a session
|
PCONNSYNC = chr(12) # portal post-syncing a session
|
||||||
|
PDISCONNALL = chr(13) # portal session disconnect all
|
||||||
AMP_MAXLEN = amp.MAX_VALUE_LENGTH # max allowed data length in AMP protocol (cannot be changed)
|
AMP_MAXLEN = amp.MAX_VALUE_LENGTH # max allowed data length in AMP protocol (cannot be changed)
|
||||||
|
|
||||||
BATCH_RATE = 250 # max commands/sec before switching to batch-sending
|
BATCH_RATE = 250 # max commands/sec before switching to batch-sending
|
||||||
|
|
@ -495,6 +496,10 @@ class AMPProtocol(amp.AMP):
|
||||||
session = server_sessionhandler[sessid]
|
session = server_sessionhandler[sessid]
|
||||||
server_sessionhandler.portal_disconnect(session)
|
server_sessionhandler.portal_disconnect(session)
|
||||||
|
|
||||||
|
elif operation == PDISCONNALL: # portal_disconnect_all
|
||||||
|
# portal orders all sessions to close
|
||||||
|
server_sessionhandler.portal_disconnect_all()
|
||||||
|
|
||||||
elif operation == PSYNC: # portal_session_sync
|
elif operation == PSYNC: # portal_session_sync
|
||||||
# force a resync of sessions when portal reconnects to
|
# force a resync of sessions when portal reconnects to
|
||||||
# server (e.g. after a server reboot) the data kwarg
|
# server (e.g. after a server reboot) the data kwarg
|
||||||
|
|
|
||||||
|
|
@ -168,8 +168,7 @@ class Portal(object):
|
||||||
# we get here due to us calling reactor.stop below. No need
|
# we get here due to us calling reactor.stop below. No need
|
||||||
# to do the shutdown procedure again.
|
# to do the shutdown procedure again.
|
||||||
return
|
return
|
||||||
for session in self.sessions.itervalues():
|
self.sessions.disconnect_all()
|
||||||
session.disconnect()
|
|
||||||
self.set_restart_mode(restart)
|
self.set_restart_mode(restart)
|
||||||
if os.name == 'nt' and os.path.exists(PORTAL_PIDFILE):
|
if os.name == 'nt' and os.path.exists(PORTAL_PIDFILE):
|
||||||
# for Windows we need to remove pid files manually
|
# for Windows we need to remove pid files manually
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,8 @@ from time import time
|
||||||
from collections import deque
|
from collections import deque
|
||||||
from twisted.internet import reactor
|
from twisted.internet import reactor
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from evennia.server.sessionhandler import SessionHandler, PCONN, PDISCONN, PCONNSYNC
|
from evennia.server.sessionhandler import SessionHandler, PCONN, PDISCONN, \
|
||||||
|
PCONNSYNC, PDISCONNALL
|
||||||
from evennia.utils.logger import log_trace
|
from evennia.utils.logger import log_trace
|
||||||
|
|
||||||
# module import
|
# module import
|
||||||
|
|
@ -23,6 +24,10 @@ _ERROR_COMMAND_OVERFLOW = settings.COMMAND_RATE_WARNING
|
||||||
|
|
||||||
_CONNECTION_QUEUE = deque()
|
_CONNECTION_QUEUE = deque()
|
||||||
|
|
||||||
|
class DummySession(object):
|
||||||
|
sessid = 0
|
||||||
|
DUMMYSESSION = DummySession()
|
||||||
|
|
||||||
#------------------------------------------------------------
|
#------------------------------------------------------------
|
||||||
# Portal-SessionHandler class
|
# Portal-SessionHandler class
|
||||||
#------------------------------------------------------------
|
#------------------------------------------------------------
|
||||||
|
|
@ -152,6 +157,10 @@ class PortalSessionHandler(SessionHandler):
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
session (PortalSession): Session to disconnect.
|
session (PortalSession): Session to disconnect.
|
||||||
|
delete (bool, optional): Delete the session from
|
||||||
|
the handler. Only time to not do this is when
|
||||||
|
this is called from a loop, such as from
|
||||||
|
self.disconnect_all().
|
||||||
|
|
||||||
"""
|
"""
|
||||||
global _CONNECTION_QUEUE
|
global _CONNECTION_QUEUE
|
||||||
|
|
@ -161,7 +170,7 @@ class PortalSessionHandler(SessionHandler):
|
||||||
_CONNECTION_QUEUE.remove(session)
|
_CONNECTION_QUEUE.remove(session)
|
||||||
return
|
return
|
||||||
|
|
||||||
if session.sessid in self:
|
if session.sessid in self and not hasattr(self, "_disconnect_all"):
|
||||||
# if this was called directly from the protocol, the
|
# if this was called directly from the protocol, the
|
||||||
# connection is already dead and we just need to cleanup
|
# connection is already dead and we just need to cleanup
|
||||||
del self[session.sessid]
|
del self[session.sessid]
|
||||||
|
|
@ -170,6 +179,23 @@ class PortalSessionHandler(SessionHandler):
|
||||||
self.portal.amp_protocol.send_AdminPortal2Server(session,
|
self.portal.amp_protocol.send_AdminPortal2Server(session,
|
||||||
operation=PDISCONN)
|
operation=PDISCONN)
|
||||||
|
|
||||||
|
def disconnect_all(self):
|
||||||
|
"""
|
||||||
|
Disconnect all sessions, informing the Server.
|
||||||
|
"""
|
||||||
|
def _callback(result, sessionhandler):
|
||||||
|
# we set a watchdog to stop self.disconnect from deleting
|
||||||
|
# sessions while we are looping over them.
|
||||||
|
sessionhandler._disconnect_all = True
|
||||||
|
for session in sessionhandler.values():
|
||||||
|
session.disconnect(session)
|
||||||
|
del sessionhandler._disconnect_all
|
||||||
|
|
||||||
|
# inform Server; wait until finished sending before we continue
|
||||||
|
# removing all the sessions.
|
||||||
|
self.portal.amp_protocol.send_AdminPortal2Server(DUMMYSESSION,
|
||||||
|
operation=PDISCONNALL).addCallback(_callback, self)
|
||||||
|
|
||||||
def server_connect(self, protocol_path="", config=dict()):
|
def server_connect(self, protocol_path="", config=dict()):
|
||||||
"""
|
"""
|
||||||
Called by server to force the initialization of a new protocol
|
Called by server to force the initialization of a new protocol
|
||||||
|
|
|
||||||
|
|
@ -506,7 +506,7 @@ if WEBSERVER_ENABLED:
|
||||||
# Start a django-compatible webserver.
|
# Start a django-compatible webserver.
|
||||||
|
|
||||||
from twisted.python import threadpool
|
from twisted.python import threadpool
|
||||||
from evennia.server.webserver import DjangoWebRoot, WSGIWebServer, NonLoggingSite
|
from evennia.server.webserver import DjangoWebRoot, WSGIWebServer, Website
|
||||||
|
|
||||||
# start a thread pool and define the root url (/) as a wsgi resource
|
# start a thread pool and define the root url (/) as a wsgi resource
|
||||||
# recognized by Django
|
# recognized by Django
|
||||||
|
|
@ -522,7 +522,7 @@ if WEBSERVER_ENABLED:
|
||||||
# custom overloads
|
# custom overloads
|
||||||
web_root = WEB_PLUGINS_MODULE.at_webserver_root_creation(web_root)
|
web_root = WEB_PLUGINS_MODULE.at_webserver_root_creation(web_root)
|
||||||
|
|
||||||
web_site = NonLoggingSite(web_root, logPath=settings.HTTP_LOG_FILE)
|
web_site = Website(web_root, logPath=settings.HTTP_LOG_FILE)
|
||||||
|
|
||||||
for proxyport, serverport in WEBSERVER_PORTS:
|
for proxyport, serverport in WEBSERVER_PORTS:
|
||||||
# create the webserver (we only need the port for this)
|
# create the webserver (we only need the port for this)
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,7 @@ SSHUTD = chr(7) # server shutdown
|
||||||
SSYNC = chr(8) # server session sync
|
SSYNC = chr(8) # server session sync
|
||||||
SCONN = chr(11) # server portal connection (for bots)
|
SCONN = chr(11) # server portal connection (for bots)
|
||||||
PCONNSYNC = chr(12) # portal post-syncing session
|
PCONNSYNC = chr(12) # portal post-syncing session
|
||||||
|
PDISCONNALL = chr(13) # portal session discnnect all
|
||||||
|
|
||||||
# i18n
|
# i18n
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
|
@ -342,6 +343,19 @@ class ServerSessionHandler(SessionHandler):
|
||||||
# Portal already knows.
|
# Portal already knows.
|
||||||
self.disconnect(session, reason="", sync_portal=False)
|
self.disconnect(session, reason="", sync_portal=False)
|
||||||
|
|
||||||
|
def portal_disconnect_all(self):
|
||||||
|
"""
|
||||||
|
Called from Portal when Portal is closing down. All
|
||||||
|
Sessions should die. The Portal should not be informed.
|
||||||
|
|
||||||
|
"""
|
||||||
|
# set a watchdog to avoid self.disconnect from deleting
|
||||||
|
# the session while we are looping over them
|
||||||
|
self._disconnect_all = True
|
||||||
|
for session in self.values:
|
||||||
|
session.disconnect()
|
||||||
|
del self._disconnect_all
|
||||||
|
|
||||||
# server-side access methods
|
# server-side access methods
|
||||||
|
|
||||||
def start_bot_session(self, protocol_path, configdict):
|
def start_bot_session(self, protocol_path, configdict):
|
||||||
|
|
@ -459,7 +473,8 @@ class ServerSessionHandler(SessionHandler):
|
||||||
|
|
||||||
session.at_disconnect()
|
session.at_disconnect()
|
||||||
sessid = session.sessid
|
sessid = session.sessid
|
||||||
del self[sessid]
|
if sessid in self and not hasattr(self, "_disconnect_all"):
|
||||||
|
del self[sessid]
|
||||||
if sync_portal:
|
if sync_portal:
|
||||||
# inform portal that session should be closed.
|
# inform portal that session should be closed.
|
||||||
self.server.amp_protocol.send_AdminServer2Portal(session,
|
self.server.amp_protocol.send_AdminServer2Portal(session,
|
||||||
|
|
|
||||||
|
|
@ -140,7 +140,7 @@ class DjangoWebRoot(resource.Resource):
|
||||||
# Site with deactivateable logging
|
# Site with deactivateable logging
|
||||||
#
|
#
|
||||||
|
|
||||||
class NonLoggingSite(server.Site):
|
class Website(server.Site):
|
||||||
"""
|
"""
|
||||||
This class will only log http requests if settings.DEBUG is True.
|
This class will only log http requests if settings.DEBUG is True.
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue