Added the BatchServer2Portal AMP command for testing.
This commit is contained in:
parent
ec05a47065
commit
56f158a9a0
2 changed files with 96 additions and 5 deletions
|
|
@ -18,6 +18,7 @@ Server - (AMP server) Handles all mud operations. The server holds its own list
|
||||||
|
|
||||||
# imports needed on both server and portal side
|
# imports needed on both server and portal side
|
||||||
import os
|
import os
|
||||||
|
from time import time
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
try:
|
try:
|
||||||
import cPickle as pickle
|
import cPickle as pickle
|
||||||
|
|
@ -162,6 +163,21 @@ class MsgServer2Portal(amp.Command):
|
||||||
response = []
|
response = []
|
||||||
|
|
||||||
|
|
||||||
|
class BatchServer2Portal(amp.Command):
|
||||||
|
"""
|
||||||
|
Batch data server -> portal
|
||||||
|
|
||||||
|
This is used when the amount of outgoing data
|
||||||
|
is very high, to minimize the throughput.
|
||||||
|
"""
|
||||||
|
key = "BatchServer2Portal"
|
||||||
|
arguments = [('hashid', amp.Integer()),
|
||||||
|
('data', amp.String()),
|
||||||
|
('ipart', amp.Integer()),
|
||||||
|
('nparts', amp.Integer())]
|
||||||
|
errors = [(Exception, 'EXCEPTION')]
|
||||||
|
response = []
|
||||||
|
|
||||||
class ServerAdmin(amp.Command):
|
class ServerAdmin(amp.Command):
|
||||||
"""
|
"""
|
||||||
Portal -> Server
|
Portal -> Server
|
||||||
|
|
@ -236,6 +252,15 @@ class AMPProtocol(amp.AMP):
|
||||||
subclasses that specify the datatypes of the input/output of these methods.
|
subclasses that specify the datatypes of the input/output of these methods.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Initialize the protocol
|
||||||
|
"""
|
||||||
|
super(AMPProtocol, self).__init__(*args, **kwargs)
|
||||||
|
self.outbatch = []
|
||||||
|
self.inbatch = []
|
||||||
|
self.lastsend = time()
|
||||||
|
|
||||||
# helper methods
|
# helper methods
|
||||||
|
|
||||||
def connectionMade(self):
|
def connectionMade(self):
|
||||||
|
|
@ -264,6 +289,53 @@ class AMPProtocol(amp.AMP):
|
||||||
print "AMP Error for %(info)s: %(e)s" % {'info': info,
|
print "AMP Error for %(info)s: %(e)s" % {'info': info,
|
||||||
'e': e.getErrorMessage()}
|
'e': e.getErrorMessage()}
|
||||||
|
|
||||||
|
def batch_send(self, command, sessid, **kwargs):
|
||||||
|
"""
|
||||||
|
This will batch data together to send fewer, large batches.
|
||||||
|
"""
|
||||||
|
self.outbatch.append((sessid, kwargs))
|
||||||
|
|
||||||
|
if time() - self.lastsend > 0.0001:
|
||||||
|
batch = dumps(self.outbatch)
|
||||||
|
self.outbatch = []
|
||||||
|
to_send = [batch[i:i+MAXLEN] for i in range(0, len(batch), MAXLEN)]
|
||||||
|
nparts = len(to_send)
|
||||||
|
hashid=id(batch)
|
||||||
|
if nparts == 1:
|
||||||
|
return self.callRemote(command,
|
||||||
|
hashid=hashid,
|
||||||
|
data=batch,
|
||||||
|
ipart=0,
|
||||||
|
nparts=1).addErrback(self.errback, "BatchServer2Portal")
|
||||||
|
else:
|
||||||
|
deferreds = []
|
||||||
|
for ipart, part in enumerate(to_send):
|
||||||
|
deferred = self.callRemote(command,
|
||||||
|
hashid=hashid,
|
||||||
|
data=part,
|
||||||
|
ipart=ipart,
|
||||||
|
nparts=nparts)
|
||||||
|
deferred.addErrback(self.errback, "BatchServer2Portal-part")
|
||||||
|
deferreds.append(deferred)
|
||||||
|
return deferreds
|
||||||
|
|
||||||
|
def batch_recv(self, hashid, data, ipart, nparts):
|
||||||
|
"""
|
||||||
|
This will receive and unpack data sent as a batch.
|
||||||
|
"""
|
||||||
|
global _MSGBUFFER
|
||||||
|
if nparts == 1:
|
||||||
|
return loads(data)
|
||||||
|
else:
|
||||||
|
if ipart < nparts-1:
|
||||||
|
# not yet complete
|
||||||
|
_MSGBUFFER[hashid].append(data)
|
||||||
|
else:
|
||||||
|
# all parts in place
|
||||||
|
data = _MSGBUFFER.pop(hashid) + data
|
||||||
|
return loads(data)
|
||||||
|
|
||||||
|
|
||||||
def safe_send(self, command, sessid, **kwargs):
|
def safe_send(self, command, sessid, **kwargs):
|
||||||
"""
|
"""
|
||||||
This helper method splits the sending of a message into
|
This helper method splits the sending of a message into
|
||||||
|
|
@ -277,6 +349,8 @@ class AMPProtocol(amp.AMP):
|
||||||
|
|
||||||
Returns a deferred or a list of such
|
Returns a deferred or a list of such
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
to_send = [(key, [string[i:i+MAXLEN] for i in range(0, len(string), MAXLEN)])
|
to_send = [(key, [string[i:i+MAXLEN] for i in range(0, len(string), MAXLEN)])
|
||||||
for key, string in kwargs.items()]
|
for key, string in kwargs.items()]
|
||||||
nparts_max = max(len(part[1]) for part in to_send)
|
nparts_max = max(len(part[1]) for part in to_send)
|
||||||
|
|
@ -383,14 +457,28 @@ class AMPProtocol(amp.AMP):
|
||||||
return {}
|
return {}
|
||||||
MsgServer2Portal.responder(amp_msg_server2portal)
|
MsgServer2Portal.responder(amp_msg_server2portal)
|
||||||
|
|
||||||
|
def amp_batch_server2portal(self, hashid, data, ipart, nparts):
|
||||||
|
"""
|
||||||
|
Relays batch data to Portal. This method is executed on the Portal.
|
||||||
|
"""
|
||||||
|
batch = self.batch_recv(hashid, data, ipart, nparts)
|
||||||
|
if batch is not None:
|
||||||
|
for (sessid, kwargs) in batch:
|
||||||
|
self.factory.portal.sessions.data_out(sessid,
|
||||||
|
text=kwargs["msg"],
|
||||||
|
**kwargs["data"])
|
||||||
|
return {}
|
||||||
|
BatchServer2Portal.responder(amp_batch_server2portal)
|
||||||
|
|
||||||
def call_remote_MsgServer2Portal(self, sessid, msg, data=""):
|
def call_remote_MsgServer2Portal(self, sessid, msg, data=""):
|
||||||
"""
|
"""
|
||||||
Access method called by the Server and executed on the Server.
|
Access method called by the Server and executed on the Server.
|
||||||
"""
|
"""
|
||||||
#print "msg server->portal (server side):", sessid, msg, data
|
#print "msg server->portal (server side):", sessid, msg, data
|
||||||
return self.safe_send(MsgServer2Portal, sessid,
|
return self.batch_send(BatchServer2Portal, sessid, msg=msg, data=data)
|
||||||
msg=msg if msg is not None else "",
|
#return self.safe_send(MsgServer2Portal, sessid,
|
||||||
data=dumps(data))
|
# msg=msg if msg is not None else "",
|
||||||
|
# data=dumps(data))
|
||||||
|
|
||||||
# Server administration from the Portal side
|
# Server administration from the Portal side
|
||||||
def amp_server_admin(self, sessid, ipart, nparts, operation, data):
|
def amp_server_admin(self, sessid, ipart, nparts, operation, data):
|
||||||
|
|
@ -489,7 +577,7 @@ class AMPProtocol(amp.AMP):
|
||||||
"""
|
"""
|
||||||
Access method called by the server side.
|
Access method called by the server side.
|
||||||
"""
|
"""
|
||||||
self.safe_send(PortalAdmin, sessid, operation=operation, data=dumps(data))
|
return self.safe_send(PortalAdmin, sessid, operation=operation, data=dumps(data))
|
||||||
|
|
||||||
# Extra functions
|
# Extra functions
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -205,6 +205,9 @@ def c_moves_s(client):
|
||||||
"move through south exit if available"
|
"move through south exit if available"
|
||||||
return "south"
|
return "south"
|
||||||
|
|
||||||
|
def c_test(client):
|
||||||
|
return "@test"
|
||||||
|
|
||||||
# Action tuple (required)
|
# Action tuple (required)
|
||||||
#
|
#
|
||||||
# This is a tuple of client action functions. The first element is the
|
# This is a tuple of client action functions. The first element is the
|
||||||
|
|
@ -247,7 +250,7 @@ def c_moves_s(client):
|
||||||
# "inactive player" definition
|
# "inactive player" definition
|
||||||
ACTIONS = (c_login_nodig,
|
ACTIONS = (c_login_nodig,
|
||||||
c_logout,
|
c_logout,
|
||||||
(1.0, c_idles))
|
(1.0, c_test))
|
||||||
## "normal player" definition
|
## "normal player" definition
|
||||||
#ACTIONS = ( c_login,
|
#ACTIONS = ( c_login,
|
||||||
# c_logout,
|
# c_logout,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue