OTPServer: client gets zone changes

This commit is contained in:
Joe Shochet 2005-01-07 21:09:22 +00:00
parent ec6fab321c
commit 506fe267ba
3 changed files with 157 additions and 41 deletions

View File

@ -22,8 +22,12 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
self.setClientDatagram(1) self.setClientDatagram(1)
self.recorder = base.recorder self.recorder = base.recorder
self.doId2do={} # Dict of {DistributedObject ids : DistributedObjects}
self.doId2do = {}
if wantOtpServer:
# Dict of {parent DistributedObject id : {zoneIds : [child DistributedObject ids]}}
self.__doHierarchy = {}
self.readDCFile() self.readDCFile()
self.cache=CRCache.CRCache() self.cache=CRCache.CRCache()
self.serverDelta = 0 self.serverDelta = 0
@ -138,52 +142,132 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
it should be accurate plus or minus a couple of seconds. it should be accurate plus or minus a couple of seconds.
""" """
return time.time() + self.serverDelta return time.time() + self.serverDelta
def handleObjectLocation(self, di): if wantOtpServer:
# CLEINT_OBJECT_LOCATION def handleObjectLocation(self, di):
ThedoId = di.getUint32() # CLIENT_OBJECT_LOCATION
TheParent = di.getUint32() doId = di.getUint32()
TheZone = di.getUint32() parentId = di.getUint32()
print "Object Location->Id=%s Parent=%s Zone=%s"%(ThedoId,TheParent, TheZone) zoneId = di.getUint32()
obj = self.doId2do.get(doId)
if (obj != None):
self.notify.info("handleObjectLocation: doId: %s parentId: %s zoneId: %s" %
(doId, parentId, zoneId))
# Let the object finish the job
obj.setLocation(parentId, zoneId)
else:
ClientRepository.notify.warning(
"handleObjectLocation: Asked to update non-existent obj: %s" % (doId))
def storeObjectLocation(self, objId, parentId, zoneId):
# Do not store null values
if ((parentId is None) or (zoneId is None)):
return
# TODO: check current location
obj = self.doId2do.get(objId)
oldParentId, oldZoneId = obj.getLocation()
# Case 1: Same parent, new zone
if (oldParentId == parentId):
parentZoneDict = self.__doHierarchy.get(parentId)
# Remove this objId from the old zone list
oldObjList = parentZoneDict.get(oldZoneId)
oldObjList.remove(objId)
# Add it to the new zone list
objList = parentZoneDict.get(zoneId)
if objList is None:
# No existing objList for this zone, let's make a new one
parentZoneDict[zoneId] = [objId]
return
else:
# Just add this objId to the existing list
assert(objId not in objList)
objList.append(objId)
return
# Case 2: New parent, valid old parent
# First delete the old location
if ((oldParentId is not None) and (oldZoneId is not None)):
self.deleteObjectLocation(objId, oldParentId, oldZoneId)
# Do not return because we still need to add to the new location
# Case 2: continued, already deleted from old location
# Case 3: New parent - no old parent
parentZoneDict = self.__doHierarchy.get(parentId)
if parentZoneDict is None:
# This parent is not here, just fill the whole entry in
self.__doHierarchy[parentId] = {zoneId : [objId]}
else:
objList = parentZoneDict.get(zoneId)
if objList is None:
# This parent has no objects in this zone before
# create a new entry for this zone and list this objId
parentZoneDict[zoneId] = [objId]
else:
# Just add this objId to the existing list
objList.append(objId)
def deleteObjectLocation(self, objId, parentId, zoneId):
# Do not worry about null values
if ((parentId is None) or (zoneId is None)):
return
parentZoneDict = self.__doHierarchy.get(parentId)
assert(parentZoneDict is not None, "deleteObjectLocation: parentId: %s not found" % (parentId))
objList = parentZoneDict.get(zoneId)
assert(objList is not None, "deleteObjectLocation: zoneId: %s not found" % (zoneId))
assert(objId in objList, "deleteObjectLocation: objId: %s not found" % (objId))
if len(objList) == 1:
# If this is the last obj in this zone, delete the entire entry
del parentZoneDict[zoneId]
else:
# Just remove the object
objList.remove(objId)
def handleGenerateWithRequired(self, di): def handleGenerateWithRequired(self, di):
if wantOtpServer: if wantOtpServer:
TheParent = di.getUint32() parentId = di.getUint32()
TheZone = di.getUint32() zoneId = di.getUint32()
# Get the class Id # Get the class Id
classId = di.getUint16(); classId = di.getUint16()
# Get the DO Id # Get the DO Id
doId = di.getUint32() doId = di.getUint32()
# Look up the dclass # Look up the dclass
dclass = self.dclassesByNumber[classId] dclass = self.dclassesByNumber[classId]
dclass.startGenerate() dclass.startGenerate()
# Create a new distributed object, and put it in the dictionary # Create a new distributed object, and put it in the dictionary
distObj = self.generateWithRequiredFields(dclass, doId, di) if wantOtpServer:
distObj = self.generateWithRequiredFields(dclass, doId, di, parentId, zoneId)
else:
distObj = self.generateWithRequiredFields(dclass, doId, di)
dclass.stopGenerate() dclass.stopGenerate()
def handleGenerateWithRequiredOther(self, di): def handleGenerateWithRequiredOther(self, di):
if wantOtpServer: if wantOtpServer:
TheParent = di.getUint32() parentId = di.getUint32()
TheZone = di.getUint32() zoneId = di.getUint32()
# Get the class Id # Get the class Id
classId = di.getUint16(); classId = di.getUint16()
# Get the DO Id # Get the DO Id
doId = di.getUint32() doId = di.getUint32()
# Look up the dclass # Look up the dclass
dclass = self.dclassesByNumber[classId] dclass = self.dclassesByNumber[classId]
dclass.startGenerate() dclass.startGenerate()
# Create a new distributed object, and put it in the dictionary # Create a new distributed object, and put it in the dictionary
distObj = self.generateWithRequiredOtherFields(dclass, doId, di) if wantOtpServer:
distObj = self.generateWithRequiredOtherFields(dclass, doId, di, parentId, zoneId)
else:
distObj = self.generateWithRequiredOtherFields(dclass, doId, di)
dclass.stopGenerate() dclass.stopGenerate()
def handleQuietZoneGenerateWithRequired(self, di): def handleQuietZoneGenerateWithRequired(self, di):
# Special handler for quiet zone generates -- we need to filter # Special handler for quiet zone generates -- we need to filter
if wantOtpServer: if wantOtpServer:
TheParent = di.getUint32() parentId = di.getUint32()
TheZone = di.getUint32() zoneId = di.getUint32()
# Get the class Id # Get the class Id
classId = di.getUint16(); classId = di.getUint16()
# Get the DO Id # Get the DO Id
doId = di.getUint32() doId = di.getUint32()
# Look up the dclass # Look up the dclass
@ -196,16 +280,16 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
# Create a new distributed object, and put it in the dictionary # Create a new distributed object, and put it in the dictionary
distObj = self.generateWithRequiredFields(dclass, doId, di) distObj = self.generateWithRequiredFields(dclass, doId, di)
else: else:
distObj = self.generateWithRequiredFields(dclass, doId, di) distObj = self.generateWithRequiredFields(dclass, doId, di, parentId, zoneId)
dclass.stopGenerate() dclass.stopGenerate()
def handleQuietZoneGenerateWithRequiredOther(self, di): def handleQuietZoneGenerateWithRequiredOther(self, di):
# Special handler for quiet zone generates -- we need to filter # Special handler for quiet zone generates -- we need to filter
if wantOtpServer: if wantOtpServer:
TheParent = di.getUint32() parentId = di.getUint32()
TheZone = di.getUint32() zoneId = di.getUint32()
# Get the class Id # Get the class Id
classId = di.getUint16(); classId = di.getUint16()
# Get the DO Id # Get the DO Id
doId = di.getUint32() doId = di.getUint32()
# Look up the dclass # Look up the dclass
@ -218,15 +302,18 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
# Create a new distributed object, and put it in the dictionary # Create a new distributed object, and put it in the dictionary
distObj = self.generateWithRequiredOtherFields(dclass, doId, di) distObj = self.generateWithRequiredOtherFields(dclass, doId, di)
else: else:
distObj = self.generateWithRequiredOtherFields(dclass, doId, di) distObj = self.generateWithRequiredOtherFields(dclass, doId, di, parentId, zoneId)
dclass.stopGenerate() dclass.stopGenerate()
def generateWithRequiredFields(self, dclass, doId, di): # wantOtpServer: remove the None defaults when we remove this config variable
def generateWithRequiredFields(self, dclass, doId, di, parentId = None, zoneId = None):
if self.doId2do.has_key(doId): if self.doId2do.has_key(doId):
# ...it is in our dictionary. # ...it is in our dictionary.
# Just update it. # Just update it.
distObj = self.doId2do[doId] distObj = self.doId2do[doId]
assert(distObj.dclass == dclass) assert(distObj.dclass == dclass)
if wantOtpServer:
distObj.setLocation(parentId, zoneId)
distObj.generate() distObj.generate()
distObj.updateRequiredFields(dclass, di) distObj.updateRequiredFields(dclass, di)
# updateRequiredFields calls announceGenerate # updateRequiredFields calls announceGenerate
@ -238,6 +325,8 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
# put it in the dictionary: # put it in the dictionary:
self.doId2do[doId] = distObj self.doId2do[doId] = distObj
# and update it. # and update it.
if wantOtpServer:
distObj.setLocation(parentId, zoneId)
distObj.generate() distObj.generate()
distObj.updateRequiredFields(dclass, di) distObj.updateRequiredFields(dclass, di)
# updateRequiredFields calls announceGenerate # updateRequiredFields calls announceGenerate
@ -254,6 +343,8 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
# Put the new do in the dictionary # Put the new do in the dictionary
self.doId2do[doId] = distObj self.doId2do[doId] = distObj
# Update the required fields # Update the required fields
if wantOtpServer:
distObj.setLocation(parentId, zoneId)
distObj.generateInit() # Only called when constructed distObj.generateInit() # Only called when constructed
distObj.generate() distObj.generate()
distObj.updateRequiredFields(dclass, di) distObj.updateRequiredFields(dclass, di)
@ -279,17 +370,24 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
# Put the new do in the dictionary # Put the new do in the dictionary
self.doId2do[doId] = distObj self.doId2do[doId] = distObj
# Update the required fields # Update the required fields
if wantOtpServer:
# TODO: ROGER: where should we get parentId and zoneId?
parentId = None
zoneId = None
distObj.setLocation(parentId, zoneId)
distObj.generateInit() # Only called when constructed distObj.generateInit() # Only called when constructed
distObj.generate() distObj.generate()
# updateRequiredFields calls announceGenerate # updateRequiredFields calls announceGenerate
return distObj return distObj
def generateWithRequiredOtherFields(self, dclass, doId, di): def generateWithRequiredOtherFields(self, dclass, doId, di, parentId = None, zoneId = None):
if self.doId2do.has_key(doId): if self.doId2do.has_key(doId):
# ...it is in our dictionary. # ...it is in our dictionary.
# Just update it. # Just update it.
distObj = self.doId2do[doId] distObj = self.doId2do[doId]
assert(distObj.dclass == dclass) assert(distObj.dclass == dclass)
if wantOtpServer:
distObj.setLocation(parentId, zoneId)
distObj.generate() distObj.generate()
distObj.updateRequiredOtherFields(dclass, di) distObj.updateRequiredOtherFields(dclass, di)
# updateRequiredOtherFields calls announceGenerate # updateRequiredOtherFields calls announceGenerate
@ -301,6 +399,8 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
# put it in the dictionary: # put it in the dictionary:
self.doId2do[doId] = distObj self.doId2do[doId] = distObj
# and update it. # and update it.
if wantOtpServer:
distObj.setLocation(parentId, zoneId)
distObj.generate() distObj.generate()
distObj.updateRequiredOtherFields(dclass, di) distObj.updateRequiredOtherFields(dclass, di)
# updateRequiredOtherFields calls announceGenerate # updateRequiredOtherFields calls announceGenerate
@ -317,6 +417,8 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
# Put the new do in the dictionary # Put the new do in the dictionary
self.doId2do[doId] = distObj self.doId2do[doId] = distObj
# Update the required fields # Update the required fields
if wantOtpServer:
distObj.setLocation(parentId, zoneId)
distObj.generateInit() # Only called when constructed distObj.generateInit() # Only called when constructed
distObj.generate() distObj.generate()
distObj.updateRequiredOtherFields(dclass, di) distObj.updateRequiredOtherFields(dclass, di)
@ -467,7 +569,7 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
self.handleGenerateWithRequiredOther(di) self.handleGenerateWithRequiredOther(di)
elif wantOtpServer and msgType == CLIENT_DONE_SET_ZONE_RESP: elif wantOtpServer and msgType == CLIENT_DONE_SET_ZONE_RESP:
self.handleSetZoneDone() self.handleSetZoneDone()
elif wantOtpServer and msgType == CLEINT_OBJECT_LOCATION: elif wantOtpServer and msgType == CLIENT_OBJECT_LOCATION:
self.handleObjectLocation(di) self.handleObjectLocation(di)
else: else:
currentLoginState = self.loginFSM.getCurrentState() currentLoginState = self.loginFSM.getCurrentState()
@ -541,22 +643,22 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
## interest managment ## interest managment
## ##
## ##
def InterestAdd(self, parentId, zoneId, Description): def InterestAdd(self, parentId, zoneId, Description):
""" """
Part of the new otp-server code. Part of the new otp-server code.
""" """
self.__interest_id_assign += 1 self.__interest_id_assign += 1
self.__interesthash[self.__interest_id_assign] = Description self.__interesthash[self.__interest_id_assign] = Description
contextId = self.__interest_id_assign; contextId = self.__interest_id_assign
self.__sendAddInterest(contextId, parentId, zoneId) self.__sendAddInterest(contextId, parentId, zoneId)
self.DumpInterests() self.DumpInterests()
return contextId; return contextId
def InterestRemove(self, contextId): def InterestRemove(self, contextId):
""" """
Part of the new otp-server code. Part of the new otp-server code.
""" """
answer = 0; answer = 0
if self.__interesthash.has_key(contextId): if self.__interesthash.has_key(contextId):
self.__sendRemoveInterest(contextId) self.__sendRemoveInterest(contextId)
del self.__interesthash[contextId] del self.__interesthash[contextId]

View File

@ -31,6 +31,9 @@ class DistributedObject(PandaObject):
except: except:
self.DistributedObject_initialized = 1 self.DistributedObject_initialized = 1
self.cr = cr self.cr = cr
if wantOtpServer:
# Location stores the parentId, zoneId of this object
self.__location = (None, None)
# Most DistributedObjects are simple and require no real # Most DistributedObjects are simple and require no real
# effort to load. Some, particularly actors, may take # effort to load. Some, particularly actors, may take
@ -150,6 +153,10 @@ class DistributedObject(PandaObject):
assert(self.notify.debug('disable(): %s' % (self.doId))) assert(self.notify.debug('disable(): %s' % (self.doId)))
self.activeState = ESDisabled self.activeState = ESDisabled
self.__callbacks = {} self.__callbacks = {}
if wantOtpServer:
self.cr.deleteObjectLocation(self.doId, self.__location[0], self.__location[1])
self.__location = (None, None)
# TODO: disable my children
def isDisabled(self): def isDisabled(self):
""" """
@ -325,5 +332,13 @@ class DistributedObject(PandaObject):
if self.__barrierContext != None: if self.__barrierContext != None:
self.sendUpdate("setBarrierReady", [self.__barrierContext]) self.sendUpdate("setBarrierReady", [self.__barrierContext])
self.__barrierContext = None self.__barrierContext = None
if wantOtpServer:
def setLocation(self, parentId, zoneId):
# The store must run first so we know the old location
self.cr.storeObjectLocation(self.doId, parentId, zoneId)
self.__location = (parentId, zoneId)
def getLocation(self):
return self.__location

View File

@ -72,12 +72,11 @@ CLIENT_GET_PET_DETAILS = 81
CLIENT_GET_PET_DETAILS_RESP = 82 CLIENT_GET_PET_DETAILS_RESP = 82
# (Proposed new message): CLIENT_SET_WORLD_POS = 83 # (Proposed new message): CLIENT_SET_WORLD_POS = 83
CLIENT_ADD_INTEREST = 97
CLEINT_ALTER_INTEREST = 98
CLEINT_REMOVE_INTEREST = 99
if wantOtpServer: if wantOtpServer:
CLEINT_OBJECT_LOCATION = 102 CLIENT_ADD_INTEREST = 97
CLIENT_ALTER_INTEREST = 98
CLIENT_REMOVE_INTEREST = 99
CLIENT_OBJECT_LOCATION = 102
# These messages are ignored when the client is headed to the quiet zone # These messages are ignored when the client is headed to the quiet zone
QUIET_ZONE_IGNORED_LIST = [ QUIET_ZONE_IGNORED_LIST = [