modifications to allow big-little endian and 32-64 bit machines to work correctly
authorFilippo Gioachin <gioachin@illinois.edu>
Tue, 23 Nov 2004 03:25:13 +0000 (03:25 +0000)
committerFilippo Gioachin <gioachin@illinois.edu>
Tue, 23 Nov 2004 03:25:13 +0000 (03:25 +0000)
src/libs/ck-libs/pythonCCS/PythonCCS-client.C
src/libs/ck-libs/pythonCCS/PythonCCS-client.h
src/libs/ck-libs/pythonCCS/PythonCCS.C
tests/charm++/python/client.C

index 82a65d80438738edafd56d4b895ddc0c54c2dff9..4ba254b6fa11929f659d90cf754f112020b6426e 100644 (file)
@@ -1,31 +1,31 @@
+#include <netinet/in.h>
 #include "PythonCCS-client.h"
 
-PythonExecute::PythonExecute(char *_code, bool _persistent, bool _highlevel, char _interp[4]) {
+PythonExecute::PythonExecute(char *_code, bool _persistent, bool _highlevel, CmiUInt4 _interp) {
   magic = sizeof(*this);
   codeLength = strlen(_code);
-  code = strdup(_code);
+  code.code = strdup(_code);
   methodNameLength = 0;
-  methodName = 0;
+  methodName.methodName = 0;
   infoSize = 0;
-  info = 0;
+  info.info = 0;
   flags = 0;
   if (_persistent) {
     flags |= FLAG_PERSISTENT;
     flags |= FLAG_KEEPPRINT;
   }
   if (_highlevel) flags |= FLAG_HIGHLEVEL;
-  if (_interp) memcpy(interpreter, _interp, 4);
-  else memset(interpreter, 0, 4);
+  interpreter = _interp;
 }
 
-PythonExecute::PythonExecute(char *_code, char *_method, PythonIterator *_info, bool _persistent, bool _highlevel, char _interp[4]) {
+PythonExecute::PythonExecute(char *_code, char *_method, PythonIterator *_info, bool _persistent, bool _highlevel, CmiUInt4 _interp) {
   magic = sizeof(*this);
   codeLength = strlen(_code);
-  code = strdup(_code);
+  code.code = strdup(_code);
   methodNameLength = strlen(_method);
-  methodName = strdup(_method);
+  methodName.methodName = strdup(_method);
   infoSize = _info->size();
-  info = _info->pack();
+  info.info = _info->pack();
   flags = 0;
   if (_persistent) {
     flags |= FLAG_PERSISTENT;
@@ -33,29 +33,28 @@ PythonExecute::PythonExecute(char *_code, char *_method, PythonIterator *_info,
   }
   if (_highlevel) flags |= FLAG_HIGHLEVEL;
   flags |= FLAG_ITERATE;
-  if (_interp) memcpy(interpreter, _interp, 4);
-  else memset(interpreter, 0, 4);
+  interpreter = _interp;
 }
 
 PythonExecute::~PythonExecute() {
-  if (code) free(code);
-  if (methodName) free(methodName);
-  if (info) free(info);
+  if (code.code) free(code.code);
+  if (methodName.methodName) free(methodName.methodName);
+  if (info.info) free(info.info);
 }
 
 void PythonExecute::setCode(char *_set) {
   codeLength = strlen(_set);
-  code = strdup(_set);
+  code.code = strdup(_set);
 }
 
 void PythonExecute::setMethodName(char *_set) {
   methodNameLength = strlen(_set);
-  methodName = strdup(_set);
+  methodName.methodName = strdup(_set);
 }
 
 void PythonExecute::setIterator(PythonIterator *_set) {
   infoSize = _set->size();
-  info = _set->pack();
+  info.info = _set->pack();
 }
 
 void PythonExecute::setPersistent(bool _set) {
@@ -87,28 +86,38 @@ char *PythonExecute::toString() {
   memcpy (memory, this, sizeof(PythonExecute));
   char *ptr = (char*)memory+sizeof(PythonExecute);
   if (codeLength) {
-    memcpy (ptr, code, codeLength+1);
+    memcpy (ptr, code.code, codeLength+1);
     ptr += codeLength+1;
   }
   if (methodNameLength) {
-    memcpy (ptr, methodName, methodNameLength+1);
+    memcpy (ptr, methodName.methodName, methodNameLength+1);
     ptr += methodNameLength+1;
   }
   if (infoSize) {
-    memcpy (ptr, info, infoSize);
+    memcpy (ptr, info.info, infoSize);
   }
+  // transform unsigned integers from host byte order to network byte order
+  ((PythonExecute*)memory)->codeLength = htonl(codeLength);
+  ((PythonExecute*)memory)->methodNameLength = htonl(methodNameLength);
+  ((PythonExecute*)memory)->infoSize = htonl(infoSize);
+
   return (char*)memory;
 }
 
 void PythonExecute::unpack() {
-  if (codeLength) code = (char*)this + sizeof(PythonExecute);
-  if (methodNameLength) methodName = code + codeLength+1;
-  if (infoSize) info = (PythonIterator*) (methodName + methodNameLength+1);
+  // transform unsigned integers back to host byte order (from network byte order)
+  codeLength = ntohl(codeLength);
+  methodNameLength = ntohl(methodNameLength);
+  infoSize = ntohl(infoSize);
+  if (codeLength) code.code = (char*)this + sizeof(PythonExecute);
+  if (methodNameLength) methodName.methodName = code.code + codeLength+1;
+  if (infoSize) info.info = (PythonIterator*) (methodName.methodName + methodNameLength+1);
 }
 
-PythonPrint::PythonPrint(char _interp[4], bool Wait) {
+PythonPrint::PythonPrint(CmiUInt4 _interp, bool Wait) {
   magic = sizeof(*this);
-  memcpy(interpreter, _interp, 4);
+  interpreter = _interp;
+  flags = 0;
   if (Wait) flags |= FLAG_WAIT;
 }
 
@@ -117,6 +126,14 @@ void PythonPrint::setWait(bool _set) {
   else flags &= ~FLAG_WAIT;
 }
 
+void PythonExecute::print() {
+  printf("magic %d, interpreter %d, flags 0x%x\n",magic ,interpreter, flags);
+}
+
+void PythonPrint::print() {
+  printf("magic %d, interpreter %d, flags 0x%x\n",magic, interpreter, flags);
+}
+
 /* Testing routine */
 /*
 int main () {
index 7c84865ec29a8a7e29db5c72850c1039d1b82ebc..56f8d06e97cfeaaddb533ba7763e84c1f75faf1b 100644 (file)
@@ -33,7 +33,7 @@ class PythonIterator {
 
   // pack the message into a contiguous memory and return the pointer to this
   // memory. the memory needs to be persistent (i.e. cannot disappear) and will
-  // be freed automatically
+  // be freed automatically. It should not modify the original data.
   virtual PythonIterator *pack() {
     void *memory = malloc(size());
     memcpy (memory, this, size());
@@ -55,19 +55,34 @@ class PythonAbstract {
   CmiUInt4 magic;
 };
 
+/* the unions with the "dummy" variables are to force a 64 bit space, which will
+   allow compatibility with 64 bit machines */
+/* all the integers (CmiUInt4) are interpreted in network byte order */
 class PythonExecute : private PythonAbstract {
   friend class PythonObject;
  private:
-  int codeLength;
-  char * code;
+  CmiUInt4 codeLength;
+  union {
+    char * code;
+    char dummy[8];
+  } code;
 
   /* the following parameters are used when the iterator mode is invoked */
-  int methodNameLength;
-  char * methodName;
-  int infoSize; /* must contain the size of the info structure passed */
-  PythonIterator *info;
-
-  char interpreter[4]; /* request for an existing interpreter */
+  CmiUInt4 methodNameLength;
+  union {
+    char * methodName;
+    char dummy[8];
+  } methodName;
+  CmiUInt4 infoSize; /* must contain the size of the info structure passed */
+  union {
+    PythonIterator *info;
+    char dummy[8];
+  } info;
+
+  /* interpreter is not sent in network byte order, since it does not need to be
+     interpreted by the client. The only two values which need to be interpreted
+     are 0 and -1 which are the same in both big and little endian notation. */
+  CmiUInt4 interpreter; /* request for an existing interpreter */
   char flags;
   /* flags has the following parameters: (bit 1 is the MSB)
      bit 1: isPersistent
@@ -84,8 +99,8 @@ class PythonExecute : private PythonAbstract {
 
   /* constructors */
   /* by default, if the code is persistent, then the prints will be maintained */
-  PythonExecute(char *_code, bool _persistent=false, bool _highlevel=false, char _interp[4]=0);
-  PythonExecute(char *_code, char *_method, PythonIterator *_info, bool _persistent=false, bool _highlevel=false, char _interp[4]=0);
+  PythonExecute(char *_code, bool _persistent=false, bool _highlevel=false, CmiUInt4 _interp=0);
+  PythonExecute(char *_code, char *_method, PythonIterator *_info, bool _persistent=false, bool _highlevel=false, CmiUInt4 _interp=0);
   ~PythonExecute();
 
   /* routines to set all parameters in the class */
@@ -96,31 +111,36 @@ class PythonExecute : private PythonAbstract {
   void setIterate(bool _set);
   void setHighLevel(bool _set);
   void setKeepPrint(bool _set);
-  void setInterpreter(char i[4]) { memcpy(interpreter, i, 4); };
+  void setInterpreter(CmiUInt4 i) { interpreter = i; };
 
   bool isPersistent() { return flags & FLAG_PERSISTENT; };
   bool isIterate() { return flags & FLAG_ITERATE; };
   bool isHighLevel() { return flags & FLAG_HIGHLEVEL; };
   bool isKeepPrint() { return flags & FLAG_KEEPPRINT; };
-  void getInterpreter(char i[4]) { memcpy(i, interpreter, 4); };
+  CmiUInt4 getInterpreter() { return interpreter; };
 
   int size();
   char *toString();
+  inline char *pack() { return toString(); };
   void unpack();
+
+  void print(); /* for debugging */
 };
 
 class PythonPrint : private PythonAbstract {
   friend class PythonObject;
  private:
-  char interpreter[4];;
+  CmiUInt4 interpreter;
   char flags;
   /* flags has the following parameters: (bit 1 is the MSB)
      bit 1: noWait
   */
   static const char FLAG_WAIT = 0x80;
  public:
-  PythonPrint(char _interp[4], bool Wait=true);
+  PythonPrint(CmiUInt4 _interp, bool Wait=true);
 
   void setWait(bool _set);
   bool isWait() { return flags & FLAG_WAIT; };
+
+  void print(); /* for debugging */
 };
index 5f04901c30f667dcf7f12f469d4b97ceff5e8e03..a0bb13d11daf1fd4048e57ae78f8b9af131aae63 100644 (file)
@@ -114,7 +114,7 @@ void PythonObject::execute (CkCcsRequestMsg *msg) {
 
   // check if this is just a request for prints
   if (pyPrint) {
-    PythonTable::iterator iter = CsvAccess(pyWorkers)->find((CmiUInt4)*pyPrint->interpreter);
+    PythonTable::iterator iter = CsvAccess(pyWorkers)->find(pyPrint->interpreter);
     if (iter == CsvAccess(pyWorkers)->end()) {
       // Malformed request!
       CkPrintf("PythonCCS: print request on invalid interpreter\n");
@@ -129,7 +129,7 @@ void PythonObject::execute (CkCcsRequestMsg *msg) {
        CcsSendDelayedReply(msg->reply, strlen(str)+1, str);
        if (iter->second.clientReady == -1) {
          // after the client flush the printed buffer, delete the entry
-         CsvAccess(pyWorkers)->erase((CmiUInt4)*pyPrint->interpreter);
+         CsvAccess(pyWorkers)->erase(pyPrint->interpreter);
        }
        CmiUnlock(CsvAccess(pyLock));
       } else {
@@ -148,13 +148,13 @@ void PythonObject::execute (CkCcsRequestMsg *msg) {
   // re-establish the pointers in the structure
   pyMsg->unpack();
 
-  if ((CmiUInt4)*pyMsg->interpreter > 0) {
+  if (pyMsg->interpreter > 0) {
     // the user specified an interpreter, check if it is free
     PythonTable::iterator iter;
-    if ((iter=CsvAccess(pyWorkers)->find((CmiUInt4)*pyMsg->interpreter))!=CsvAccess(pyWorkers)->end() && !iter->second.inUse) {
+    if ((iter=CsvAccess(pyWorkers)->find(pyMsg->interpreter))!=CsvAccess(pyWorkers)->end() && !iter->second.inUse) {
       // the interpreter already exists and it is not in use
       //CkPrintf("interpreter present and not in use\n");
-      pyReference = (CmiUInt4)*pyMsg->interpreter;
+      pyReference = pyMsg->interpreter;
       iter->second.inUse = true;
       // send back this number to the client, which is an ack
       CcsSendDelayedReply(msg->reply, sizeof(CmiUInt4), (void *)&pyReference);
@@ -234,10 +234,10 @@ void PythonObject::executeThread(CkCcsRequestMsg *msg) {
 
   // decide whether it is iterative or not
   if (!pyMsg->isIterate()) {
-    PyRun_SimpleString(pyMsg->code);
+    PyRun_SimpleString(pyMsg->code.code);
   } else {
     // compile the program
-    char *userCode = pyMsg->code;
+    char *userCode = pyMsg->code.code;
     struct _node* programNode = PyParser_SimpleParseString(userCode, Py_file_input);
     if (programNode==NULL) {
       CkPrintf("Program error\n");
@@ -269,7 +269,7 @@ void PythonObject::executeThread(CkCcsRequestMsg *msg) {
     }
 
     // load the user defined method
-    char *userMethod = userCode + strlen(userCode) + 1;
+    char *userMethod = pyMsg->methodName.methodName;
     PyObject *item = PyDict_GetItemString(dict, userMethod);
     if (item==NULL) {
       CkPrintf("Method not found\n");
@@ -289,7 +289,7 @@ void PythonObject::executeThread(CkCcsRequestMsg *msg) {
     PyTuple_SetItem(arg, 0, part);
 
     // construct the iterator calling the user defined method in the interiting class
-    void *userIterator = (void *)(userMethod + strlen(userMethod) + 1);
+    PythonIterator *userIterator = pyMsg->info.info;
     int more = buildIterator(part, userIterator);
 
     // iterate over all the provided iterators from the user class
index 81486704283dde602192ae2934892d5c44fed965..b603e3156d532970ff386d554c7a6c2c3a854e3c 100644 (file)
@@ -30,20 +30,25 @@ int main (int argc, char** argv) {
   wrapper.setKeepPrint(true);
 
   // if there is a third argument means kill the server
-  char buffer[10];
+  CmiUInt4 remoteValue;
+  char buffer[100];
   if (argc>3) {
     CcsSendRequest (&server, "kill", 0, 1, code.c_str());
   }
   else {
     CcsSendRequest (&server, "pyCode", 0, wrapper.size(), wrapper.toString());
-    CcsRecvResponse (&server, 10, buffer, 100);
-    printf("buffer: %d\n",*(int*)buffer);
-    PythonPrint request(buffer);
+    CcsRecvResponse (&server, 10, &remoteValue, sizeof(remoteValue));
+    printf("buffer: %d\n",remoteValue);
+    PythonPrint request(remoteValue);
     sleep(2);
+    //request.print();
     CcsSendRequest (&server, "pyCode", 0, sizeof(request), &request);
+    //request.print();
     CcsRecvResponse (&server, 100, buffer, 100);
+    //request.print();
     printf("responce: %s\n",buffer);
     sleep(2);
+    //request.print();
     CcsSendRequest (&server, "pyCode", 0, sizeof(request), &request);
     CcsRecvResponse (&server, 100, buffer, 100);
     printf("responce: %x\n",*buffer);