Browse Source

*** empty log message ***

Jesse Schell 25 years ago
parent
commit
c601286b46

+ 50 - 9
direct/src/distributed/ClientDistClass.py

@@ -2,20 +2,61 @@
 
 from PandaModules import *
 import DirectNotifyGlobal
+import ClientDistUpdate
 
 class ClientDistClass:
 	
     def __init__(self, dcClass):
-        self.number = dcClass.get_number()
-        self.name = dcClass.get_name()
-        self.atomicFields=[]
-        self.molecularFields=[]
-        self.parseAtomicFields(dcClass)
-        self.parseMolecularFields(dcClass)
+        self.number = dcClass.getNumber()
+        self.name = dcClass.getName()
+        self.allFields = self.parseFields(dcClass)
+        self.allCDU = self.createAllCDU(self.allFields)
+        self.number2CDU = self.createNumber2CDUDict(self.allCDU)
+        self.name2CDU = self.createName2CDUDict(self.allCDU)
         return None
 
-    def parseAtomicFields(dcClass):
-        for i in range(0,dcClass.get_num_inherited_atomics()):
-            self.atomicFields.append((dcClass.get_inherited_atomic(i))
+    def parseFields(self, dcClass):
+        fields=[]
+        for i in range(0,dcClass.getNumInheritedFields()):
+            fields.append(dcClass.getInheritedField(i))
+        return fields
+
+    def createAllCDU(self, allFields):
+        allCDU = []
+        for i in allFields:
+            allCDU.append(ClientDistUpdate.ClientDistUpdate(i))
+        return allCDU
+
+    def createNumber2CDUDict(self, allCDU):
+        dict={}
+        for i in allCDU:
+            dict[i.number] = i
+        return dict
+
+    def createName2CDUDict(self, allCDU):
+        dict={}
+        for i in allCDU:
+            dict[i.name] = i
+        return dict
+
+    def updateField(self, do, di):
+        # Get the update field id
+        fieldId = di.getArg(ST_uint8)
+        # look up the CDU
+        assert(self.number2CDU.has_key(fieldId))
+        cdu = self.number2CDU[fieldId]
+        # Let the cdu finish the job
+        cdu.updateField(cdc, do, di)
+        return None
+
+    def sendUpdate(self, do, fieldName, args):
+        # Look up the cdu
+        assert(self.name2CDU.has_key(fieldName))
+        cdu = self.name2CDU[fieldName]
+        # Let the cdu finish the job
+        cdu.sendUpdate(do, args)
+        
+
+    
             
         

+ 65 - 0
direct/src/distributed/ClientDistUpdate.py

@@ -0,0 +1,65 @@
+"""ClientDistUpdate module: contains the ClientDistUpdate class"""
+
+import DirectNotifyGlobal
+
+class ClientDistUpdate:
+    notify = DirectNotifyGlobal.directNotify.newCategory("ClientDistUpdate")
+
+    def __init__(self, dcField):
+        self.number = dcField.getNumber()
+        self.name = dcField.getName()
+        self.types = self.deriveTypesFromParticle(dcField)
+        return None
+
+    def deriveTypesFromParticle(self, dcField):
+        typeList=[]
+        dcFieldAtomic = dcField.asAtomicField()
+        dcFieldMolecular = dcField.asMolecularField()
+        if dcFieldAtomic:
+            for i in range(0, dcFieldAtomic.getNumElements()):
+                typeList.append(dcFieldAtomic.getElementType(i))
+        elif dcFieldMolecular:
+            for i in range(0, dcFieldMolecular.getNumAtomics()):
+                componentField = dcFieldMolecular.getAtomic(i)
+                for j in range(0, componentField.getNumElements()):
+                    typeList.append(componentField.getElementType(j))
+        else:
+            ClientDistUpdate.notify.error("field is neither atom nor molecule")
+        return typeList
+
+    def updateField(self, cdc, do, di):
+        # Look up the class
+        aClass = eval(cdc.name)
+        # Look up the function
+        assert(aClass.__dict__.has_key(self.name))
+        func = aClass.__dict__[self.name]
+        # Get the arguments into a list
+        args = self.extractArgs(di)
+        # Apply the function to the object with the arguments
+        apply(func, [do] + args)
+        return None
+
+    def extractArgs(self, di):
+        args = []
+        for i in self.types:
+            args.append(di.getArgs(i))
+        return args
+
+    def addArgs(self, datagram, args):
+        # Add the args to the datagram
+        numElems = len(args)
+        assert (numElems == len(self.types))
+        for i in range(0, numElems):
+            datagram.addArg(args[i], self.types[i])
+    
+    def sendUpdate(self, do, args):
+        datagram = Datagram()
+        # Add message type
+        datagram.addUint16(ALL_OBJECT_UPDATE_FIELD)
+        # Add the DO id
+        datagram.addUint32(do.doId)
+        # Add the field id
+        datagram.addUint8(self.number)
+        # Add the arguments
+        self.addArgs(datagram, args)
+        # send the datagram

+ 80 - 15
direct/src/distributed/ClientRepository.py

@@ -4,35 +4,37 @@ from PandaModules import *
 from TaskManagerGlobal import *
 import Task
 import DirectNotifyGlobal
+import ClientDistClass
 
 class ClientRepository:
     defaultServerPort = 5150
     notify = DirectNotifyGlobal.directNotify.newCategory("ClientRepository")
 
-    def __init__(self, dcFileName):
+    def __init__(self, dcFileName, AIClientFlag=0):
+        self.AIClientFlag=AIClientFlag
         self.number2cdc={}
         self.name2cdc={}
+        self.doId2do={}
+        self.doId2cdc={}
         self.parseDcFile(dcFileName)
         return None
 
-    def parseDcFile(dcFileName):
-        dcFile = DCFile()
-        dcFile.read(dcFileName)
-        return self.parseDcClasses(dcFile)
+    def parseDcFile(self, dcFileName):
+        self.dcFile = DCFile()
+        self.dcFile.read(dcFileName)
+        return self.parseDcClasses(self.dcFile)
 
-    def parseDcClasses(dcFile):
-        numClasses = dcFile.get_num_classes()
+    def parseDcClasses(self, dcFile):
+        numClasses = dcFile.getNumClasses()
         for i in range(0, numClasses):
             # Create a clientDistClass from the dcClass
-            clientDistClass = self.parseClass(dcFile.getClass())
+            dcClass = dcFile.getClass(i)
+            clientDistClass = ClientDistClass.ClientDistClass(dcClass)
             # List the cdc in the number and name dictionaries
-            self.number2cdc[clientDistClass.getNumber()]=clientDistClass
-            self.name2cdc[clientDistClass.getName()]=clientDistClass
+            self.number2cdc[dcClass.getNumber()]=clientDistClass
+            self.name2cdc[dcClass.getName()]=clientDistClass
         return None
 
-    def parseClass(dcClass):
-        
-
     def connect(self, serverName="localhost",
                 serverPort=defaultServerPort):
         self.qcm=QueuedConnectionManager()
@@ -64,9 +66,65 @@ class ClientRepository:
         return availGetVal
 
     def handleDatagram(datagram):
-        print 'Got it!'
+        di = DatagramIterator(datagram)
+        msgType = di.getArg(ST_uint16)
+
+        if msgType == ALL_OBJECT_GENERATE_WITH_REQUIRED:
+            self.handleGenerateWithRequired(di)
+        elif msgType == ALL_OBJECT_UPDATE_FIELD:
+            self.handleUpdateField(di)
+        else:
+            ClientRepository.notify.warning("We don't handle type: "
+                                            + str(msgType))
+        return None
+
+    def handleGenerateWithRequired(di):
+        # Get the class Id
+        classId = di.getArg(ST_uint8);
+        # Get the DO Id
+        doId = di.getArg(ST_uint32)
+        # Get the echo context
+        echoContext = di.getArg(ST_uint32);
+        # Look up the cdc
+        cdc = self.number2cdc[classId]
+        # Create a new distributed object, and put it in the dictionary
+        distObj = self.generateWithRequiredFields(cdc, doId, di)
         return None
 
+    def generateWithRequiredFields(cdc, doId, di):
+        # Someday, this function will look in a cache of old distributed
+        # objects to see if this object is in there, and pull it
+        # out if necessary. For now, we'll just check to see if
+        # it is in the standard dictionary, and ignore this update
+        # if it is there. The right thing to do would be to update
+        # all the required fields, but that will come later, too.
+
+        if self.doId2do.has_key(doId):
+            ClientRepository.notify.warning("doId: " +
+                                            str(doId) +
+                                            " was generated again")
+            distObj = self.doId2do(doId)
+        else:
+            distObj = \
+                    eval(cdc.name).generateWithRequiredFields(doId, di)
+            # Put the new do in both dictionaries
+            self.doId2do[doId] = distObj
+            self.doId2cdc[doId] = cdc
+            
+        return distObj
+
+    def handleUpdateField(di):
+        # Get the DO Id
+        doId = di.getArg(ST_uint32)
+        # Find the DO
+        assert(self.doId2do.has_key(doId))
+        do = self.doId2do(doId)
+        # Find the cdc
+        assert(self.doId2cdc.has_key(doId))
+        cdc = self.doId2cdc[doId]
+        # Let the cdc finish the job
+        cdc.updateField(do, di)
+        
     def sendLoginMsg(self):
         datagram = Datagram()
         # Add message type
@@ -80,5 +138,12 @@ class ClientRepository:
         # Send the message
         self.cw.send(datagram, self.tcpConn)
 
-        
+    def sendUpdate(self, do, fieldName, args):
+        # Get the DO id
+        doId = do.doId
+        # Get the cdc
+        assert(self.doId2cdc.has_key(doId))
+        cdc = self.doId2cdc[doId]
+        # Let the cdc finish the job
+        cdc.sendUpdate(do, fieldName, args)
         

+ 27 - 0
direct/src/extensions/Datagram-extensions.py

@@ -0,0 +1,27 @@
+
+    def putArg(self, arg, subatomicType):
+        # Import the type numbers
+        from DCSubatomicType import *
+        if subatomicType == STInt8:
+            self.addInt8(arg)
+        elif subatomicType == STInt16:
+            self.addInt16(arg)
+        elif subatomicType == STInt32:
+            self.addInt32(arg)
+        elif subatomicType == STInt64:
+            self.addInt64(arg)
+        elif subatomicType == STUint8:
+            self.addUint8(arg)
+        elif subatomicType == STUint16:
+            self.addUint16(arg)
+        elif subatomicType == STUint32:
+            self.addUint32(arg)
+        elif subatomicType == STUint64:
+            self.addUint64(arg)
+        elif subatomicType == STFloat64:
+            self.addFloat64(arg)
+        elif subatomicType == STString:
+            self.addString(arg)
+        else:
+            raise Exception("Error: No such type as: " + subatomicType)
+        return None

+ 29 - 0
direct/src/extensions/DatagramIterator-extensions.py

@@ -0,0 +1,29 @@
+
+    def getArg(self, subatomicType):
+        # Import the type numbers
+        from DCSubatomicType import *
+        if subatomicType == STInt8:
+            retVal = self.getInt8()
+        elif subatomicType == STInt16:
+            retVal = self.getInt16()
+        elif subatomicType == STInt32:
+            retVal = self.getInt32()
+        elif subatomicType == STInt64:
+            retVal = self.getInt64()
+        elif subatomicType == STUint8:
+            retVal = self.getUint8()
+        elif subatomicType == STUint16:
+            retVal = self.getUint16()
+        elif subatomicType == STUint32:
+            retVal = self.getUint32()
+        elif subatomicType == STUint64:
+            retVal = self.getUint64()
+        elif subatomicType == STFloat64:
+            retVal = self.getFloat64()
+        elif subatomicType == STString:
+            retVal = self.getString()
+        else:
+            raise Exception("Error: No such type as: " + str(subAtomicType))
+        return retVal
+
+