[Spice-devel] [PATCH 1/4] start refactoring vdi_port

Alon Levy alevy at redhat.com
Thu Dec 30 05:07:23 PST 2010


introduce VDIPort::get_num_events and VDIPort::fill_events,
change VDService::_events to be dynamically allocated
document _events contents: STATIC events, then vdi_port, then agent.
---
 vdservice/vdi_port.cpp  |    2 +-
 vdservice/vdi_port.h    |   17 +++++++--
 vdservice/vdservice.cpp |   83 +++++++++++++++++++++++++++++-----------------
 3 files changed, 66 insertions(+), 36 deletions(-)

diff --git a/vdservice/vdi_port.cpp b/vdservice/vdi_port.cpp
index e36ff86..f4dfaeb 100644
--- a/vdservice/vdi_port.cpp
+++ b/vdservice/vdi_port.cpp
@@ -56,7 +56,7 @@ bool VDIPort::init()
     _handle = CreateFile(VIOSERIAL_PORT_PATH, GENERIC_READ | GENERIC_WRITE , 0, NULL,
                          OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
     if (_handle == INVALID_HANDLE_VALUE) {
-        vd_printf("CreateFile() failed: %u", GetLastError());
+        vd_printf("CreateFile() %s failed: %u", VIOSERIAL_PORT_PATH, GetLastError());
         return false;
     }
     _write.overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
diff --git a/vdservice/vdi_port.h b/vdservice/vdi_port.h
index a10b346..8e057bb 100644
--- a/vdservice/vdi_port.h
+++ b/vdservice/vdi_port.h
@@ -46,14 +46,23 @@ public:
     size_t ring_read(void* buf, size_t size);
     size_t read_ring_size();
     size_t read_ring_continuous_remaining_size();
-    HANDLE get_write_event() { return _write.overlap.hEvent; }
-    HANDLE get_read_event() { return _read.overlap.hEvent; }
+    unsigned get_num_events() { return 2; }
+    void fill_events(HANDLE *handle) {
+        handle[0] = _write.overlap.hEvent;
+        handle[1] = _read.overlap.hEvent;
+    }
+    void handle_event(int event) {
+        switch (event) {
+            case 0: write_completion(); break;
+            case 1: read_completion(); break;
+        }
+    }
     int write();
     int read();
-    void write_completion();
-    void read_completion();
 
 private:
+    void write_completion();
+    void read_completion();
     int handle_error();
 
 private:
diff --git a/vdservice/vdservice.cpp b/vdservice/vdservice.cpp
index ae5ad87..72882ea 100644
--- a/vdservice/vdservice.cpp
+++ b/vdservice/vdservice.cpp
@@ -40,15 +40,19 @@
 #define CREATE_PROC_MAX_RETRIES 10
 #define CREATE_PROC_INTERVAL_MS 500
 
+// This enum simplifies WaitForMultipleEvents for static
+// events, that is handles that are guranteed non NULL.
+// It doesn't include:
+// VDIPort Handles - these are filled by an interface because
+//  of variable handle number.
+// VDAgent handle - this can be 1 or 0 (NULL or not), so it is also added at
+//  the end of VDService::_events
 enum {
     VD_EVENT_PIPE_READ = 0,
     VD_EVENT_PIPE_WRITE,
     VD_EVENT_CONTROL,
-    VD_EVENT_READ,
-    VD_EVENT_WRITE,
     VD_EVENT_LOGON,
-    VD_EVENT_AGENT, // Must be before last
-    VD_EVENTS_COUNT // Must be last
+    VD_STATIC_EVENTS_COUNT // Must be last
 };
 
 class VDService {
@@ -76,7 +80,15 @@ private:
     bool launch_agent();
     void send_logon();
     bool kill_agent();
-
+    unsigned fill_agent_event() {
+        ASSERT(_events);
+        if (_agent_proc_info.hProcess) {
+            _events[_events_count - 1] = _agent_proc_info.hProcess;
+            return _events_count;
+        } else {
+            return _events_count - 1;
+        }
+    }
 private:
     static VDService* _singleton;
     SERVICE_STATUS _status;
@@ -84,7 +96,7 @@ private:
     PROCESS_INFORMATION _agent_proc_info;
     HANDLE _control_event;
     HANDLE _logon_event;
-    HANDLE _events[VD_EVENTS_COUNT];
+    HANDLE* _events;
     TCHAR _agent_path[MAX_PATH];
     VDIPort* _vdi_port;
     VDPipeState _pipe_state;
@@ -103,6 +115,8 @@ private:
     bool _agent_alive;
     bool _running;
     VDLog* _log;
+    unsigned _events_count;
+    unsigned _events_vdi_port_base;
 };
 
 VDService* VDService::_singleton = NULL;
@@ -142,6 +156,7 @@ int supported_system_version()
 
 VDService::VDService()
     : _status_handle (0)
+    , _events (NULL)
     , _vdi_port (NULL)
     , _connection_id (0)
     , _session_id (0)
@@ -156,10 +171,11 @@ VDService::VDService()
     , _agent_alive (false)
     , _running (false)
     , _log (NULL)
+    , _events_count(0)
+    , _events_vdi_port_base(0)
 {
     ZeroMemory(&_agent_proc_info, sizeof(_agent_proc_info));
     ZeroMemory(&_pipe_state, sizeof(_pipe_state));
-    ZeroMemory(_events, sizeof(_events));
     _system_version = supported_system_version();
     _control_event = CreateEvent(NULL, FALSE, FALSE, NULL);
     _pipe_state.write.overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
@@ -176,6 +192,7 @@ VDService::~VDService()
     CloseHandle(_pipe_state.read.overlap.hEvent);
     CloseHandle(_pipe_state.write.overlap.hEvent);
     CloseHandle(_control_event);
+    delete _events;
     delete _log;
 }
 
@@ -423,14 +440,19 @@ bool VDService::execute()
         CloseHandle(pipe);
         return false;
     }
+    _events_count = VD_STATIC_EVENTS_COUNT + _vdi_port->get_num_events() + 1 /*for agent*/;
+    _events = new HANDLE[_events_count];
+    _events_vdi_port_base = VD_STATIC_EVENTS_COUNT;
+    ZeroMemory(_events, _events_count);
     vd_printf("Connected to server");
     _events[VD_EVENT_PIPE_READ] = _pipe_state.read.overlap.hEvent;
     _events[VD_EVENT_PIPE_WRITE] = _pipe_state.write.overlap.hEvent;
     _events[VD_EVENT_CONTROL] = _control_event;
-    _events[VD_EVENT_READ] = _vdi_port->get_read_event();
-    _events[VD_EVENT_WRITE] = _vdi_port->get_write_event();
     _events[VD_EVENT_LOGON] = _logon_event;
-    _events[VD_EVENT_AGENT] = _agent_proc_info.hProcess;
+    _agent_proc_info.hProcess;
+    vd_printf("Calling fill_events");
+    vd_printf("&_events[VD_ENVETS_COUNT] == %p", &_events[VD_STATIC_EVENTS_COUNT]);
+    _vdi_port->fill_events(&_events[_events_vdi_port_base]);
     _chunk_size = _chunk_port = 0;
     read_pipe();
     while (_running) {
@@ -456,8 +478,8 @@ bool VDService::execute()
             handle_pipe_data(0);
         }
         if (_running && (!cont || _pending_read || _pending_write)) {
-            DWORD events_count = _events[VD_EVENT_AGENT] ? VD_EVENTS_COUNT : VD_EVENTS_COUNT - 1;
-            DWORD wait_ret = WaitForMultipleObjects(events_count, _events, FALSE,
+            unsigned actual_events = fill_agent_event();
+            DWORD wait_ret = WaitForMultipleObjects(actual_events, _events, FALSE,
                                                               cont ? 0 : INFINITE);
             switch (wait_ret) {
             case WAIT_OBJECT_0 + VD_EVENT_PIPE_READ: {
@@ -482,28 +504,29 @@ bool VDService::execute()
             case WAIT_OBJECT_0 + VD_EVENT_CONTROL:
                 vd_printf("Control event");
                 break;
-            case WAIT_OBJECT_0 + VD_EVENT_READ:
-                _vdi_port->read_completion();
-                break;
-            case WAIT_OBJECT_0 + VD_EVENT_WRITE:
-                _vdi_port->write_completion();
-                break;
             case WAIT_OBJECT_0 + VD_EVENT_LOGON:
                 vd_printf("logon event");
                 write_agent_control(VD_AGENT_SESSION_LOGON, 0);
                 break;
-            case WAIT_OBJECT_0 + VD_EVENT_AGENT:
-                vd_printf("Agent killed");
-                if (_system_version == SYS_VER_WIN_XP) {
-                    restart_agent(false);
-                } else if (_system_version == SYS_VER_WIN_7) {
-                    kill_agent();
-                }
-                break;
             case WAIT_TIMEOUT:
                 break;
             default:
-                vd_printf("WaitForMultipleObjects failed %u", GetLastError());
+                if (wait_ret == WAIT_OBJECT_0 + _events_count - 1) {
+                    vd_printf("Agent killed");
+                    if (_system_version == SYS_VER_WIN_XP) {
+                        restart_agent(false);
+                    } else if (_system_version == SYS_VER_WIN_7) {
+                        kill_agent();
+                    }
+                } else {
+                    if (wait_ret >= WAIT_OBJECT_0 + _events_vdi_port_base &&
+                        wait_ret < WAIT_OBJECT_0 +
+                                   _events_vdi_port_base + _vdi_port->get_num_events()) {
+                        _vdi_port->handle_event(wait_ret - VD_STATIC_EVENTS_COUNT - WAIT_OBJECT_0);
+                    } else {
+                        vd_printf("WaitForMultipleObjects failed %u", GetLastError());
+                    }
+                }
             }
         }
     }
@@ -802,7 +825,6 @@ bool VDService::launch_agent()
         vd_printf("ConnectNamedPipe() failed: %u", GetLastError());
         return false;
     }
-    _events[VD_EVENT_AGENT] = _agent_proc_info.hProcess;
     return true;
 }
 
@@ -815,7 +837,6 @@ bool VDService::kill_agent()
     if (!_agent_alive) {
         return true;
     }
-    _events[VD_EVENT_AGENT] = 0;
     _agent_alive = false;
     if (_pipe_connected) {
         _pipe_connected = false;
@@ -909,8 +930,8 @@ void VDService::pipe_write_completion()
         } else {
             vd_printf("GetOverlappedResult() failed : %d", GetLastError());
         }
-	    _pending_write = false;
-	}
+        _pending_write = false;
+    }
 
     if (ps->write.start < ps->write.end) {
         _pending_write = true;
-- 
1.7.3.4



More information about the Spice-devel mailing list