[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH] XML-RPC: Cope with large integers on x86-64 systems



Attached patch fixes a problem in marshaling large integers. It seems to only occur on systems with very large memory. However, on those systems, it's a show-stopper. I see this as a temporary solution until we can sanitize the XML-RPC functions and get rid of all the S-Expression stuff.

I'll run xm-test tomorrow against it. Right now I've only done basic testing.

Regards,

Anthony Liguori
# HG changeset patch
# User anthony@xxxxxxxxxxxxxxxxxxxxx
# Node ID 8dc8c7bdcbac0e56c606fe5c9205b4d9742e60d7
# Parent  8b5a752167a17785b998a080a5c1ce1991b9379b
In some cases, Xend can return a very large integer.  This so far only happens
on 64bit systems where the sizeof the Python integer is > 32bit.  Presumably,
this is occuring because of the fact that we return PFNs as part of the
domain info so on a system with greater than 2G of memory we get into the
invalid integer range.

For now, the work-around is to overload the xmlrpclib Marshaller and instead
of throwing an exception when we get out-of-range integers, we marshal them
as strings.  In the future, we can handle this in a more elegant way by
introducing higher-level types.  We also won't have to deal with things like
PFNs once we clean up the XML-RPC interface.

Signed-off-by: Anthony Liguori <aliguori@xxxxxxxxxx>

diff -r 8b5a752167a1 -r 8dc8c7bdcbac tools/python/xen/util/xmlrpclib2.py
--- a/tools/python/xen/util/xmlrpclib2.py       Mon Mar 27 10:16:36 2006
+++ b/tools/python/xen/util/xmlrpclib2.py       Mon Mar 27 23:40:31 2006
@@ -21,9 +21,10 @@
 """
 
 from httplib import HTTPConnection, HTTP
-from xmlrpclib import Transport
+from xmlrpclib import Transport, Fault
 from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler
-import xmlrpclib, socket, os, traceback
+import xmlrpclib, socket, os, traceback, string
+from types import *
 
 # A new ServerProxy that also supports httpu urls.  An http URL comes in the
 # form:
@@ -31,6 +32,9 @@
 # httpu:///absolute/path/to/socket.sock
 #
 # It assumes that the RPC handler is /RPC2.  This probably needs to be improved
+
+MAXINT =  2L**31-1
+MININT = -2L**31
 
 class HTTPUnixConnection(HTTPConnection):
     def connect(self):
@@ -58,6 +62,67 @@
         xmlrpclib.ServerProxy.__init__(self, uri, transport, encoding,
                                        verbose, allow_none)
 
+class Marshaller(xmlrpclib.Marshaller):
+    def __init__(self, encoding=None, allow_none=0):
+        xmlrpclib.Marshaller.__init__(self, encoding, allow_none)
+        self.dispatch[IntType] = Marshaller.dump_int
+        self.dispatch[LongType] = Marshaller.dump_long
+        
+    def dump_int(self, value, write):
+        if value > MAXINT or value < MININT:
+            self.dispatch[StringType](self, str(value), write)
+        else:
+            xmlrpclib.Marshaller.dump_int(self, value, write)
+
+    def dump_long(self, value, write):
+        if value > MAXINT or value < MININT:
+            self.dispatch[StringType](self, str(value), write)
+        else:
+            xmlrpclib.Marshaller.dump_long(self, value, write)
+
+def dumps(params, methodname=None, methodresponse=None, encoding=None,
+          allow_none=0):
+    assert isinstance(params, TupleType) or isinstance(params, Fault),\
+           "argument must be tuple or Fault instance"
+
+    if isinstance(params, Fault):
+        methodresponse = 1
+    elif methodresponse and isinstance(params, TupleType):
+        assert len(params) == 1, "response tuple must be a singleton"
+
+    if not encoding:
+        encoding = "utf-8"
+
+    m = Marshaller(encoding, allow_none)
+
+    data = m.dumps(params)
+
+    if encoding != "utf-8":
+        xmlheader = "<?xml version='1.0' encoding='%s'?>\n" % str(encoding)
+    else:
+        xmlheader = "<?xml version='1.0'?>\n" # utf-8 is default
+
+    if methodname:
+        if not isinstance(methodname, StringType):
+            methodname = methodname.encode(encoding)
+        data = (
+            xmlheader,
+            "<methodCall>\n"
+            "<methodName>", methodname, "</methodName>\n",
+            data,
+            "</methodCall>\n"
+            )
+    elif methodresponse:
+        data = (
+            xmlheader,
+            "<methodResponse>\n",
+            data,
+            "</methodResponse>\n"
+            )
+    else:
+        return data
+    return string.join(data, "")
+
 # This is a base XML-RPC server for TCP.  It sets allow_reuse_address to
 # true, and has an improved marshaller that serializes unknown exceptions
 # with full traceback information.
@@ -74,13 +139,13 @@
                 response = self._dispatch(method, params)
 
             response = (response,)
-            response = xmlrpclib.dumps(response,
-                                       methodresponse=1,
-                                       allow_none=1)
+            response = dumps(response,
+                             methodresponse=1,
+                             allow_none=1)
         except xmlrpclib.Fault, fault:
-            response = xmlrpclib.dumps(fault)
+            response = dumps(fault)
         except:
-            response = xmlrpclib.dumps(
+            response = dumps(
                 xmlrpclib.Fault(1, traceback.format_exc())
                 )
 
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.