diff --git a/direct/src/distributed/CRCache.py b/direct/src/distributed/CRCache.py new file mode 100644 index 0000000000..e8960a0f37 --- /dev/null +++ b/direct/src/distributed/CRCache.py @@ -0,0 +1,70 @@ +"""CRCache module: contains the CRCache class""" + +import DirectNotifyGlobal +import DistributedObject + +class CRCache: + notify = DirectNotifyGlobal.directNotify.newCategory("CRCache") + + def __init__(self, maxCacheItems=50): + self.maxCacheItems = maxCacheItems + self.dict = {} + self.fifo = [] + return None + + def cache(self, distObj): + # Only distributed objects are allowed in the cache + assert(isinstance(distObj, DistributedObject.DistributedObject)) + # Get the doId + doId = distObj.getDoId() + # Error check + if self.dict.has_key(doId): + CRCache.notify.warning("Double cache attempted for distObj " + + str(doId)) + else: + # Call disable on the distObj + distObj.disable() + + # Put the distObj in the fifo and the dict + self.fifo.append(distObj) + self.dict[doId] = distObj + + if len(self.fifo) > self.maxCacheItems: + # if the cache is full, pop the oldest item + oldestDistObj = self.fifo.pop(0) + # and remove it from the dictionary + del(self.dict[oldestDistObj.getDoId()]) + # and delete it + oldestDistObj.delete() + + # Make sure that the fifo and the dictionary are sane + assert(len(self.dict) == len(self.fifo)) + return None + + def retrieve(self, doId): + if self.dict.has_key(doId): + # Find the object + distObj = self.dict[doId] + # Remove it from the dictionary + del(self.dict[doId]) + # Remove it from the fifo + self.fifo.remove(distObj) + # return the distObj + return distObj + else: + # If you can't find it, return None + return None + + def contains(self, doId): + return self.dict.has_key(doId) + + def delete(self, doId): + assert(self.dict.has_key(doId)) + # Look it up + distObj = self.dict[doId] + # Remove it from the dict and fifo + del(self.dict[doId]) + self.fifo.remove(distObj) + # and delete it + oldestDistObj.delete() + diff --git a/direct/src/distributed/ClientRepository.py b/direct/src/distributed/ClientRepository.py index 7ff88ef931..75355f856e 100644 --- a/direct/src/distributed/ClientRepository.py +++ b/direct/src/distributed/ClientRepository.py @@ -6,6 +6,7 @@ from MsgTypes import * import Task import DirectNotifyGlobal import ClientDistClass +import CRCache # The repository must import all known types of Distributed Objects import DistributedObject import DistributedToon @@ -21,6 +22,7 @@ class ClientRepository(DirectObject.DirectObject): self.doId2do={} self.doId2cdc={} self.parseDcFile(dcFileName) + self.cache=CRCache.CRCache() return None def parseDcFile(self, dcFileName): @@ -61,7 +63,7 @@ class ClientRepository(DirectObject.DirectObject): def readerPollOnce(self): availGetVal = self.qcr.dataAvailable() if availGetVal: - print "Client: Incoming message!" + #print "Client: Incoming message!" datagram = NetDatagram() readRetVal = self.qcr.getData(datagram) if readRetVal: @@ -98,12 +100,24 @@ class ClientRepository(DirectObject.DirectObject): # if it is there. The right thing to do would be to update # all the required fields, but that will come later, too. + # Is it in our dictionary? if self.doId2do.has_key(doId): - ClientRepository.notify.warning("doId: " + - str(doId) + - " was generated again") + # If so, just update it. distObj = self.doId2do[doId] distObj.updateRequiredFields(cdc, di) + + # Is it in the cache? If so, pull it out, put it in the dictionaries, + # and update it. + elif self.cache.contains(doId): + # If so, pull it out of the cache... + distObj = self.cache.retrieve(doId) + # put it in both dictionaries... + self.doId2do[doId] = distObj + self.doId2cdc[doId] = cdc + # and update it. + distObj.updateRequiredFields(cdc, di) + + # If it is not in the dictionary or the cache, then... else: # Construct a new one distObj = constructor(self) @@ -117,10 +131,46 @@ class ClientRepository(DirectObject.DirectObject): return distObj + def handleDisable(self, di): + # Get the DO Id + doId = di.getArg(STUint32) + # Make sure the object exists + if self.doId2do.has_key(doId): + # Look up the object + distObj = self.doId2do[doId] + # remove the object from both dictionaries + del(self.doId2do[doId]) + del(self.doId2cdc[doId]) + assert(len(self.doId2do) == len(self.doId2cdc)) + # cache the object + self.cache.cache(distObj) + else: + ClientRepository.notify.warning("Disable failed. DistObj " + + str(doId) + + " is not in dictionary") + return None + + def handleDelete(self, di): + # Get the DO Id + doId = di.getArg(STUint32) + # If it is in the dictionaries, remove it. + if self.doId2do.has_key(doId): + del(self.doId2do[doId]) + del(self.doId2cdc[doId]) + assert(len(self.doId2do) == len(self.doId2cdc)) + # If it is in the cache, remove it. + elif self.cache.contains(doId): + self.cache.delete(doId) + # Otherwise, ignore it + else: + ClientRepository.notify.warning( + "Asked to delete non-existent DistObj " + str(doId)) + return None + def handleUpdateField(self, di): # Get the DO Id doId = di.getArg(STUint32) - print("Updating " + str(doId)) + #print("Updating " + str(doId)) # Find the DO assert(self.doId2do.has_key(doId)) do = self.doId2do[doId] diff --git a/direct/src/distributed/DistributedNode.py b/direct/src/distributed/DistributedNode.py index 7e828b0b5a..be3630c7d1 100644 --- a/direct/src/distributed/DistributedNode.py +++ b/direct/src/distributed/DistributedNode.py @@ -1,5 +1,6 @@ """DistributedNode module: contains the DistributedNode class""" +from ShowBaseGlobal import * import NodePath import DistributedObject @@ -14,8 +15,9 @@ class DistributedNode(DistributedObject.DistributedObject, NodePath.NodePath): DistributedObject.DistributedObject.__init__(self, cr) return None - def generateInit(self, di): - DistributedObject.DistributedObject.generateInit(self, di) + def disable(self): + self.reparent(hidden) + DistributedObject.DistributedObject.disable(self) def d_setPos(self, x, y, z): self.sendUpdate("setPos", [x, y, z]) diff --git a/direct/src/distributed/DistributedObject.py b/direct/src/distributed/DistributedObject.py index fdf074f207..305c51407f 100644 --- a/direct/src/distributed/DistributedObject.py +++ b/direct/src/distributed/DistributedObject.py @@ -1,7 +1,7 @@ """DistributedObject module: contains the DistributedObject class""" from PandaObject import * -from ToonBaseGlobal import * +#from ToonBaseGlobal import * class DistributedObject(PandaObject): """Distributed Object class:""" @@ -12,6 +12,18 @@ class DistributedObject(PandaObject): self.DistributedObject_initialized = 1 self.cr = cr return None + + def disable(self): + """disable(self) + Inheritors should redefine this to take appropriate action on disable + """ + pass + + def delete(self): + """delete(self) + Inheritors should redefine this to take appropriate action on delete + """ + pass def getDoId(self): """getDoId(self)