[KVM-AUTOTEST PATCH] KVM test: kvm_monitor.py: use select whenever possible

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

 



As suggested by Luiz Capitulino, use select() whenever possible to minimize
delays.

(_data_available() is a wrapper for select().)

Signed-off-by: Michael Goldish <mgoldish@xxxxxxxxxx>
---
 client/tests/kvm/kvm_monitor.py |   73 +++++++++++++++++++++------------------
 1 files changed, 39 insertions(+), 34 deletions(-)

diff --git a/client/tests/kvm/kvm_monitor.py b/client/tests/kvm/kvm_monitor.py
index 40be77d..5ad80d8 100644
--- a/client/tests/kvm/kvm_monitor.py
+++ b/client/tests/kvm/kvm_monitor.py
@@ -4,7 +4,7 @@ Interfaces to the QEMU monitor.
 @copyright: 2008-2010 Red Hat Inc.
 """
 
-import socket, time, threading, logging
+import socket, time, threading, logging, select
 import kvm_utils
 try:
     import json
@@ -60,7 +60,6 @@ class Monitor:
         self.filename = filename
         self._lock = threading.RLock()
         self._socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
-        self._socket.setblocking(False)
 
         try:
             self._socket.connect(filename)
@@ -104,13 +103,15 @@ class Monitor:
         return False
 
 
+    def _data_available(self, timeout=0):
+        timeout = max(0, timeout)
+        return bool(select.select([self._socket], [], [], timeout)[0])
+
+
     def _recvall(self):
         s = ""
-        while True:
-            try:
-                data = self._socket.recv(1024)
-            except socket.error:
-                break
+        while self._data_available():
+            data = self._socket.recv(1024)
             if not data:
                 break
             s += data
@@ -160,19 +161,19 @@ class HumanMonitor(Monitor):
     # Private methods
 
     def _read_up_to_qemu_prompt(self, timeout=20):
-        o = ""
+        s = ""
         end_time = time.time() + timeout
-        while time.time() < end_time:
+        while self._data_available(end_time - time.time()):
+            data = self._socket.recv(1024)
+            if not data:
+                break
+            s += data
             try:
-                data = self._socket.recv(1024)
-                if not data:
-                    break
-                o += data
-                if o.splitlines()[-1].split()[-1] == "(qemu)":
-                    return True, "\n".join(o.splitlines()[:-1])
-            except (socket.error, IndexError):
-                time.sleep(0.01)
-        return False, "\n".join(o.splitlines())
+                if s.splitlines()[-1].split()[-1] == "(qemu)":
+                    return True, "\n".join(s.splitlines()[:-1])
+            except IndexError:
+                continue
+        return False, "\n".join(s.splitlines())
 
 
     def _send(self, cmd):
@@ -389,14 +390,13 @@ class QMPMonitor(Monitor):
 
             # Read greeting message
             end_time = time.time() + 20
-            while time.time() < end_time:
+            while self._data_available(end_time - time.time()):
                 for obj in self._read_objects():
                     if "QMP" in obj:
                         self._greeting = obj["QMP"]
                         break
                 if self._greeting:
                     break
-                time.sleep(0.1)
             else:
                 raise MonitorProtocolError("No QMP greeting message received")
 
@@ -423,7 +423,7 @@ class QMPMonitor(Monitor):
 
     def _read_objects(self, timeout=5):
         """
-        Read lines from monitor and try to decode them.
+        Read lines from the monitor and try to decode them.
         Stop when all available lines have been successfully decoded, or when
         timeout expires.  If any decoded objects are asynchronous events, store
         them in self._events.  Return all decoded objects.
@@ -431,24 +431,30 @@ class QMPMonitor(Monitor):
         @param timeout: Time to wait for all lines to decode successfully
         @return: A list of objects
         """
+        if not self._data_available():
+            return []
         s = ""
-        objs = []
         end_time = time.time() + timeout
-        while time.time() < end_time:
+        while self._data_available(end_time - time.time()):
             s += self._recvall()
+            # Make sure all lines are decodable
             for line in s.splitlines():
-                if not line:
-                    continue
-                try:
-                    obj = json.loads(line)
-                except:
-                    # Found an incomplete or broken line -- keep reading
-                    break
-                objs += [obj]
+                if line:
+                    try:
+                        json.loads(line)
+                    except:
+                        # Found an incomplete or broken line -- keep reading
+                        break
             else:
                 # All lines are OK -- stop reading
                 break
-            time.sleep(0.1)
+        # Decode all decodable lines
+        objs = []
+        for line in s.splitlines():
+            try:
+                objs += [json.loads(line)]
+            except:
+                pass
         # Keep track of asynchronous events
         self._events += [obj for obj in objs if "event" in obj]
         return objs
@@ -476,14 +482,13 @@ class QMPMonitor(Monitor):
         @return: The response dict, or None if none was found
         """
         end_time = time.time() + timeout
-        while time.time() < end_time:
+        while self._data_available(end_time - time.time()):
             for obj in self._read_objects():
                 if isinstance(obj, dict):
                     if id is not None and obj.get("id") != id:
                         continue
                     if "return" in obj or "error" in obj:
                         return obj
-            time.sleep(0.1)
 
 
     # Public methods
-- 
1.5.5.6

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux