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.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.cache=CRCache.CRCache()
self.serverDelta = 0
@ -138,52 +142,132 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
it should be accurate plus or minus a couple of seconds.
"""
return time.time() + self.serverDelta
def handleObjectLocation(self, di):
# CLEINT_OBJECT_LOCATION
ThedoId = di.getUint32()
TheParent = di.getUint32()
TheZone = di.getUint32()
print "Object Location->Id=%s Parent=%s Zone=%s"%(ThedoId,TheParent, TheZone)
if wantOtpServer:
def handleObjectLocation(self, di):
# CLIENT_OBJECT_LOCATION
doId = di.getUint32()
parentId = di.getUint32()
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):
if wantOtpServer:
TheParent = di.getUint32()
TheZone = di.getUint32()
if wantOtpServer:
parentId = di.getUint32()
zoneId = di.getUint32()
# Get the class Id
classId = di.getUint16();
classId = di.getUint16()
# Get the DO Id
doId = di.getUint32()
# Look up the dclass
dclass = self.dclassesByNumber[classId]
dclass.startGenerate()
# 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()
def handleGenerateWithRequiredOther(self, di):
if wantOtpServer:
TheParent = di.getUint32()
TheZone = di.getUint32()
parentId = di.getUint32()
zoneId = di.getUint32()
# Get the class Id
classId = di.getUint16();
classId = di.getUint16()
# Get the DO Id
doId = di.getUint32()
# Look up the dclass
dclass = self.dclassesByNumber[classId]
dclass.startGenerate()
# 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()
def handleQuietZoneGenerateWithRequired(self, di):
# Special handler for quiet zone generates -- we need to filter
if wantOtpServer:
TheParent = di.getUint32()
TheZone = di.getUint32()
parentId = di.getUint32()
zoneId = di.getUint32()
# Get the class Id
classId = di.getUint16();
classId = di.getUint16()
# Get the DO Id
doId = di.getUint32()
# Look up the dclass
@ -196,16 +280,16 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
# Create a new distributed object, and put it in the dictionary
distObj = self.generateWithRequiredFields(dclass, doId, di)
else:
distObj = self.generateWithRequiredFields(dclass, doId, di)
distObj = self.generateWithRequiredFields(dclass, doId, di, parentId, zoneId)
dclass.stopGenerate()
def handleQuietZoneGenerateWithRequiredOther(self, di):
# Special handler for quiet zone generates -- we need to filter
if wantOtpServer:
TheParent = di.getUint32()
TheZone = di.getUint32()
parentId = di.getUint32()
zoneId = di.getUint32()
# Get the class Id
classId = di.getUint16();
classId = di.getUint16()
# Get the DO Id
doId = di.getUint32()
# Look up the dclass
@ -218,15 +302,18 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
# Create a new distributed object, and put it in the dictionary
distObj = self.generateWithRequiredOtherFields(dclass, doId, di)
else:
distObj = self.generateWithRequiredOtherFields(dclass, doId, di)
distObj = self.generateWithRequiredOtherFields(dclass, doId, di, parentId, zoneId)
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):
# ...it is in our dictionary.
# Just update it.
distObj = self.doId2do[doId]
assert(distObj.dclass == dclass)
if wantOtpServer:
distObj.setLocation(parentId, zoneId)
distObj.generate()
distObj.updateRequiredFields(dclass, di)
# updateRequiredFields calls announceGenerate
@ -238,6 +325,8 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
# put it in the dictionary:
self.doId2do[doId] = distObj
# and update it.
if wantOtpServer:
distObj.setLocation(parentId, zoneId)
distObj.generate()
distObj.updateRequiredFields(dclass, di)
# updateRequiredFields calls announceGenerate
@ -254,6 +343,8 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
# Put the new do in the dictionary
self.doId2do[doId] = distObj
# Update the required fields
if wantOtpServer:
distObj.setLocation(parentId, zoneId)
distObj.generateInit() # Only called when constructed
distObj.generate()
distObj.updateRequiredFields(dclass, di)
@ -279,17 +370,24 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
# Put the new do in the dictionary
self.doId2do[doId] = distObj
# 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.generate()
# updateRequiredFields calls announceGenerate
return distObj
def generateWithRequiredOtherFields(self, dclass, doId, di):
def generateWithRequiredOtherFields(self, dclass, doId, di, parentId = None, zoneId = None):
if self.doId2do.has_key(doId):
# ...it is in our dictionary.
# Just update it.
distObj = self.doId2do[doId]
assert(distObj.dclass == dclass)
if wantOtpServer:
distObj.setLocation(parentId, zoneId)
distObj.generate()
distObj.updateRequiredOtherFields(dclass, di)
# updateRequiredOtherFields calls announceGenerate
@ -301,6 +399,8 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
# put it in the dictionary:
self.doId2do[doId] = distObj
# and update it.
if wantOtpServer:
distObj.setLocation(parentId, zoneId)
distObj.generate()
distObj.updateRequiredOtherFields(dclass, di)
# updateRequiredOtherFields calls announceGenerate
@ -317,6 +417,8 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
# Put the new do in the dictionary
self.doId2do[doId] = distObj
# Update the required fields
if wantOtpServer:
distObj.setLocation(parentId, zoneId)
distObj.generateInit() # Only called when constructed
distObj.generate()
distObj.updateRequiredOtherFields(dclass, di)
@ -467,7 +569,7 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
self.handleGenerateWithRequiredOther(di)
elif wantOtpServer and msgType == CLIENT_DONE_SET_ZONE_RESP:
self.handleSetZoneDone()
elif wantOtpServer and msgType == CLEINT_OBJECT_LOCATION:
elif wantOtpServer and msgType == CLIENT_OBJECT_LOCATION:
self.handleObjectLocation(di)
else:
currentLoginState = self.loginFSM.getCurrentState()
@ -541,22 +643,22 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
## interest managment
##
##
def InterestAdd(self, parentId, zoneId, Description):
def InterestAdd(self, parentId, zoneId, Description):
"""
Part of the new otp-server code.
"""
self.__interest_id_assign += 1
self.__interesthash[self.__interest_id_assign] = Description
contextId = self.__interest_id_assign;
contextId = self.__interest_id_assign
self.__sendAddInterest(contextId, parentId, zoneId)
self.DumpInterests()
return contextId;
return contextId
def InterestRemove(self, contextId):
"""
Part of the new otp-server code.
"""
answer = 0;
answer = 0
if self.__interesthash.has_key(contextId):
self.__sendRemoveInterest(contextId)
del self.__interesthash[contextId]

View File

@ -31,6 +31,9 @@ class DistributedObject(PandaObject):
except:
self.DistributedObject_initialized = 1
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
# effort to load. Some, particularly actors, may take
@ -150,6 +153,10 @@ class DistributedObject(PandaObject):
assert(self.notify.debug('disable(): %s' % (self.doId)))
self.activeState = ESDisabled
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):
"""
@ -325,5 +332,13 @@ class DistributedObject(PandaObject):
if self.__barrierContext != None:
self.sendUpdate("setBarrierReady", [self.__barrierContext])
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
# (Proposed new message): CLIENT_SET_WORLD_POS = 83
CLIENT_ADD_INTEREST = 97
CLEINT_ALTER_INTEREST = 98
CLEINT_REMOVE_INTEREST = 99
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
QUIET_ZONE_IGNORED_LIST = [