[Spice-devel] [PATCH 07/18] worker: move dcc_handle_migrate_data

Frediano Ziglio fziglio at redhat.com
Mon Nov 23 09:01:53 PST 2015


From: Marc-André Lureau <marcandre.lureau at gmail.com>

Acked-by: Fabiano FidĂȘncio <fabiano at fidencio.org>
---
 server/dcc.c        | 135 +++++++++++++++++++++++++++++++++++++++++++
 server/dcc.h        |   5 ++
 server/red_worker.c | 161 +---------------------------------------------------
 3 files changed, 143 insertions(+), 158 deletions(-)

diff --git a/server/dcc.c b/server/dcc.c
index 1c82139..5be3769 100644
--- a/server/dcc.c
+++ b/server/dcc.c
@@ -1259,3 +1259,138 @@ int dcc_handle_message(RedChannelClient *rcc, uint32_t size, uint16_t type, void
         return red_channel_client_handle_message(rcc, size, type, msg);
     }
 }
+
+static int dcc_handle_migrate_glz_dictionary(DisplayChannelClient *dcc,
+                                             SpiceMigrateDataDisplay *migrate)
+{
+    spice_return_val_if_fail(!dcc->glz_dict, FALSE);
+
+    ring_init(&dcc->glz_drawables);
+    ring_init(&dcc->glz_drawables_inst_to_free);
+    pthread_mutex_init(&dcc->glz_drawables_inst_to_free_lock, NULL);
+    dcc->glz_dict = dcc_restore_glz_dictionary(dcc,
+                                               migrate->glz_dict_id,
+                                               &migrate->glz_dict_data);
+    return dcc->glz_dict != NULL;
+}
+
+static int restore_surface(DisplayChannelClient *dcc, uint32_t surface_id)
+{
+    /* we don't process commands till we receive the migration data, thus,
+     * we should have not sent any surface to the client. */
+    if (dcc->surface_client_created[surface_id]) {
+        spice_warning("surface %u is already marked as client_created", surface_id);
+        return FALSE;
+    }
+    dcc->surface_client_created[surface_id] = TRUE;
+    return TRUE;
+}
+
+static int restore_surfaces_lossless(DisplayChannelClient *dcc,
+                                         MigrateDisplaySurfacesAtClientLossless *mig_surfaces)
+{
+    uint32_t i;
+
+    spice_debug(NULL);
+    for (i = 0; i < mig_surfaces->num_surfaces; i++) {
+        uint32_t surface_id = mig_surfaces->surfaces[i].id;
+
+        if (!restore_surface(dcc, surface_id))
+            return FALSE;
+    }
+    return TRUE;
+}
+
+static int restore_surfaces_lossy(DisplayChannelClient *dcc,
+                                  MigrateDisplaySurfacesAtClientLossy *mig_surfaces)
+{
+    uint32_t i;
+
+    spice_debug(NULL);
+    for (i = 0; i < mig_surfaces->num_surfaces; i++) {
+        uint32_t surface_id = mig_surfaces->surfaces[i].id;
+        SpiceMigrateDataRect *mig_lossy_rect;
+        SpiceRect lossy_rect;
+
+        if (!restore_surface(dcc, surface_id))
+            return FALSE;
+
+        mig_lossy_rect = &mig_surfaces->surfaces[i].lossy_rect;
+        lossy_rect.left = mig_lossy_rect->left;
+        lossy_rect.top = mig_lossy_rect->top;
+        lossy_rect.right = mig_lossy_rect->right;
+        lossy_rect.bottom = mig_lossy_rect->bottom;
+        region_init(&dcc->surface_client_lossy_region[surface_id]);
+        region_add(&dcc->surface_client_lossy_region[surface_id], &lossy_rect);
+    }
+    return TRUE;
+}
+
+int dcc_handle_migrate_data(DisplayChannelClient *dcc, uint32_t size, void *message)
+{
+    DisplayChannel *display = DCC_TO_DC(dcc);
+    int surfaces_restored = FALSE;
+    SpiceMigrateDataHeader *header = (SpiceMigrateDataHeader *)message;
+    SpiceMigrateDataDisplay *migrate_data = (SpiceMigrateDataDisplay *)(header + 1);
+    uint8_t *surfaces;
+    int i;
+
+    spice_return_val_if_fail(
+        size >= (sizeof(*migrate_data) + sizeof(SpiceMigrateDataHeader)), FALSE);
+    spice_return_val_if_fail(
+         migration_protocol_validate_header(header,
+             SPICE_MIGRATE_DATA_DISPLAY_MAGIC, SPICE_MIGRATE_DATA_DISPLAY_VERSION), FALSE);
+
+    /* size is set to -1 in order to keep the cache frozen until the original
+     * channel client that froze the cache on the src size receives the migrate
+     * data and unfreezes the cache by setting its size > 0 and by triggering
+     * pixmap_cache_reset */
+    dcc->pixmap_cache = pixmap_cache_get(RED_CHANNEL_CLIENT(dcc)->client,
+                                         migrate_data->pixmap_cache_id, -1);
+    spice_return_val_if_fail(dcc->pixmap_cache, FALSE);
+
+    pthread_mutex_lock(&dcc->pixmap_cache->lock);
+    for (i = 0; i < MAX_CACHE_CLIENTS; i++) {
+        dcc->pixmap_cache->sync[i] = MAX(dcc->pixmap_cache->sync[i],
+                                         migrate_data->pixmap_cache_clients[i]);
+    }
+    pthread_mutex_unlock(&dcc->pixmap_cache->lock);
+
+    if (migrate_data->pixmap_cache_freezer) {
+        /* activating the cache. The cache will start to be active after
+         * pixmap_cache_reset is called, when handling PIPE_ITEM_TYPE_PIXMAP_RESET */
+        dcc->pixmap_cache->size = migrate_data->pixmap_cache_size;
+        red_channel_client_pipe_add_type(RED_CHANNEL_CLIENT(dcc), PIPE_ITEM_TYPE_PIXMAP_RESET);
+    }
+
+    if (dcc_handle_migrate_glz_dictionary(dcc, migrate_data)) {
+        dcc->glz =
+            glz_encoder_create(dcc->common.id, dcc->glz_dict->dict, &dcc->glz_data.usr);
+    } else {
+        spice_critical("restoring global lz dictionary failed");
+    }
+
+    dcc->common.is_low_bandwidth = migrate_data->low_bandwidth_setting;
+
+    if (migrate_data->low_bandwidth_setting) {
+        red_channel_client_ack_set_client_window(RED_CHANNEL_CLIENT(dcc), WIDE_CLIENT_ACK_WINDOW);
+        if (dcc->jpeg_state == SPICE_WAN_COMPRESSION_AUTO) {
+            display->enable_jpeg = TRUE;
+        }
+        if (dcc->zlib_glz_state == SPICE_WAN_COMPRESSION_AUTO) {
+            display->enable_zlib_glz_wrap = TRUE;
+        }
+    }
+
+    surfaces = (uint8_t *)message + migrate_data->surfaces_at_client_ptr;
+    surfaces_restored = display->enable_jpeg ?
+        restore_surfaces_lossy(dcc, (MigrateDisplaySurfacesAtClientLossy *)surfaces) :
+        restore_surfaces_lossless(dcc, (MigrateDisplaySurfacesAtClientLossless*)surfaces);
+
+    spice_return_val_if_fail(surfaces_restored, FALSE);
+
+    red_channel_client_pipe_add_type(RED_CHANNEL_CLIENT(dcc), PIPE_ITEM_TYPE_INVAL_PALETTE_CACHE);
+    /* enable sending messages */
+    red_channel_client_ack_zero_messages_window(RED_CHANNEL_CLIENT(dcc));
+    return TRUE;
+}
diff --git a/server/dcc.h b/server/dcc.h
index 12bb38e..94b9195 100644
--- a/server/dcc.h
+++ b/server/dcc.h
@@ -38,6 +38,9 @@
 /* Each drawable can refer to at most 3 images: src, brush and mask */
 #define MAX_DRAWABLE_PIXMAP_CACHE_ITEMS 3
 
+#define WIDE_CLIENT_ACK_WINDOW 40
+#define NARROW_CLIENT_ACK_WINDOW 20
+
 typedef struct WaitForChannels {
     SpiceMsgWaitForChannels header;
     SpiceWaitForChannel buf[MAX_CACHE_CLIENTS];
@@ -161,6 +164,8 @@ void                       dcc_start                                 (DisplayCha
 int                        dcc_handle_message                        (RedChannelClient *rcc,
                                                                       uint32_t size,
                                                                       uint16_t type, void *msg);
+int                        dcc_handle_migrate_data                   (DisplayChannelClient *dcc,
+                                                                      uint32_t size, void *message);
 void                       dcc_push_monitors_config                  (DisplayChannelClient *dcc);
 void                       dcc_destroy_surface                       (DisplayChannelClient *dcc,
                                                                       uint32_t surface_id);
diff --git a/server/red_worker.c b/server/red_worker.c
index e0fd6e5..5d32f4f 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -85,9 +85,6 @@ struct SpiceWatch {
 
 #define MAX_PIPE_SIZE 50
 
-#define WIDE_CLIENT_ACK_WINDOW 40
-#define NARROW_CLIENT_ACK_WINDOW 20
-
 typedef struct UpgradeItem {
     PipeItem base;
     int refs;
@@ -4254,20 +4251,6 @@ static inline void flush_all_qxl_commands(RedWorker *worker)
     flush_cursor_commands(worker);
 }
 
-static int dcc_handle_migrate_glz_dictionary(DisplayChannelClient *dcc,
-                                             SpiceMigrateDataDisplay *migrate)
-{
-    spice_return_val_if_fail(!dcc->glz_dict, FALSE);
-
-    ring_init(&dcc->glz_drawables);
-    ring_init(&dcc->glz_drawables_inst_to_free);
-    pthread_mutex_init(&dcc->glz_drawables_inst_to_free_lock, NULL);
-    dcc->glz_dict = dcc_restore_glz_dictionary(dcc,
-                                               migrate->glz_dict_id,
-                                               &migrate->glz_dict_data);
-    return dcc->glz_dict != NULL;
-}
-
 static int display_channel_handle_migrate_mark(RedChannelClient *rcc)
 {
     DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
@@ -4277,8 +4260,7 @@ static int display_channel_handle_migrate_mark(RedChannelClient *rcc)
     return TRUE;
 }
 
-static uint64_t display_channel_handle_migrate_data_get_serial(
-                RedChannelClient *rcc, uint32_t size, void *message)
+static uint64_t display_channel_handle_migrate_data_get_serial(RedChannelClient *rcc, uint32_t size, void *message)
 {
     SpiceMigrateDataDisplay *migrate_data;
 
@@ -4287,146 +4269,9 @@ static uint64_t display_channel_handle_migrate_data_get_serial(
     return migrate_data->message_serial;
 }
 
-static int display_channel_client_restore_surface(DisplayChannelClient *dcc, uint32_t surface_id)
-{
-    /* we don't process commands till we receive the migration data, thus,
-     * we should have not sent any surface to the client. */
-    if (dcc->surface_client_created[surface_id]) {
-        spice_warning("surface %u is already marked as client_created", surface_id);
-        return FALSE;
-    }
-    dcc->surface_client_created[surface_id] = TRUE;
-    return TRUE;
-}
-
-static int display_channel_client_restore_surfaces_lossless(DisplayChannelClient *dcc,
-                                                            MigrateDisplaySurfacesAtClientLossless *mig_surfaces)
+static int display_channel_handle_migrate_data(RedChannelClient *rcc, uint32_t size, void *message)
 {
-    uint32_t i;
-
-    spice_debug(NULL);
-    for (i = 0; i < mig_surfaces->num_surfaces; i++) {
-        uint32_t surface_id = mig_surfaces->surfaces[i].id;
-
-        if (!display_channel_client_restore_surface(dcc, surface_id)) {
-            return FALSE;
-        }
-    }
-    return TRUE;
-}
-
-static int display_channel_client_restore_surfaces_lossy(DisplayChannelClient *dcc,
-                                                          MigrateDisplaySurfacesAtClientLossy *mig_surfaces)
-{
-    uint32_t i;
-
-    spice_debug(NULL);
-    for (i = 0; i < mig_surfaces->num_surfaces; i++) {
-        uint32_t surface_id = mig_surfaces->surfaces[i].id;
-        SpiceMigrateDataRect *mig_lossy_rect;
-        SpiceRect lossy_rect;
-
-        if (!display_channel_client_restore_surface(dcc, surface_id)) {
-            return FALSE;
-        }
-        spice_assert(dcc->surface_client_created[surface_id]);
-
-        mig_lossy_rect = &mig_surfaces->surfaces[i].lossy_rect;
-        lossy_rect.left = mig_lossy_rect->left;
-        lossy_rect.top = mig_lossy_rect->top;
-        lossy_rect.right = mig_lossy_rect->right;
-        lossy_rect.bottom = mig_lossy_rect->bottom;
-        region_init(&dcc->surface_client_lossy_region[surface_id]);
-        region_add(&dcc->surface_client_lossy_region[surface_id], &lossy_rect);
-    }
-    return TRUE;
-}
-static int display_channel_handle_migrate_data(RedChannelClient *rcc, uint32_t size,
-                                               void *message)
-{
-    SpiceMigrateDataHeader *header;
-    SpiceMigrateDataDisplay *migrate_data;
-    DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
-    DisplayChannelClient *dcc = RCC_TO_DCC(rcc);
-    uint8_t *surfaces;
-    int surfaces_restored = FALSE;
-    int i;
-
-    spice_debug(NULL);
-    if (size < sizeof(*migrate_data) + sizeof(SpiceMigrateDataHeader)) {
-        spice_error("bad message size");
-        return FALSE;
-    }
-    header = (SpiceMigrateDataHeader *)message;
-    migrate_data = (SpiceMigrateDataDisplay *)(header + 1);
-    if (!migration_protocol_validate_header(header,
-                                            SPICE_MIGRATE_DATA_DISPLAY_MAGIC,
-                                            SPICE_MIGRATE_DATA_DISPLAY_VERSION)) {
-        spice_error("bad header");
-        return FALSE;
-    }
-    /* size is set to -1 in order to keep the cache frozen until the original
-     * channel client that froze the cache on the src size receives the migrate
-     * data and unfreezes the cache by setting its size > 0 and by triggering
-     * pixmap_cache_reset */
-    dcc->pixmap_cache = pixmap_cache_get(RED_CHANNEL_CLIENT(dcc)->client,
-                                         migrate_data->pixmap_cache_id, -1);
-    if (!dcc->pixmap_cache) {
-        return FALSE;
-    }
-    pthread_mutex_lock(&dcc->pixmap_cache->lock);
-    for (i = 0; i < MAX_CACHE_CLIENTS; i++) {
-        dcc->pixmap_cache->sync[i] = MAX(dcc->pixmap_cache->sync[i],
-                                         migrate_data->pixmap_cache_clients[i]);
-    }
-    pthread_mutex_unlock(&dcc->pixmap_cache->lock);
-
-    if (migrate_data->pixmap_cache_freezer) {
-        /* activating the cache. The cache will start to be active after
-         * pixmap_cache_reset is called, when handling PIPE_ITEM_TYPE_PIXMAP_RESET */
-        dcc->pixmap_cache->size = migrate_data->pixmap_cache_size;
-        red_channel_client_pipe_add_type(rcc,
-                                         PIPE_ITEM_TYPE_PIXMAP_RESET);
-    }
-
-    if (dcc_handle_migrate_glz_dictionary(dcc, migrate_data)) {
-        dcc->glz = glz_encoder_create(dcc->common.id,
-                                      dcc->glz_dict->dict, &dcc->glz_data.usr);
-        if (!dcc->glz) {
-            spice_critical("create global lz failed");
-        }
-    } else {
-        spice_critical("restoring global lz dictionary failed");
-    }
-
-    dcc->common.is_low_bandwidth = migrate_data->low_bandwidth_setting;
-
-    if (migrate_data->low_bandwidth_setting) {
-        red_channel_client_ack_set_client_window(rcc, WIDE_CLIENT_ACK_WINDOW);
-        if (dcc->jpeg_state == SPICE_WAN_COMPRESSION_AUTO) {
-            display_channel->enable_jpeg = TRUE;
-        }
-        if (dcc->zlib_glz_state == SPICE_WAN_COMPRESSION_AUTO) {
-            display_channel->enable_zlib_glz_wrap = TRUE;
-        }
-    }
-
-    surfaces = (uint8_t *)message + migrate_data->surfaces_at_client_ptr;
-    if (display_channel->enable_jpeg) {
-        surfaces_restored = display_channel_client_restore_surfaces_lossy(dcc,
-                                (MigrateDisplaySurfacesAtClientLossy *)surfaces);
-    } else {
-        surfaces_restored = display_channel_client_restore_surfaces_lossless(dcc,
-                                (MigrateDisplaySurfacesAtClientLossless*)surfaces);
-    }
-
-    if (!surfaces_restored) {
-        return FALSE;
-    }
-    red_channel_client_pipe_add_type(rcc, PIPE_ITEM_TYPE_INVAL_PALETTE_CACHE);
-    /* enable sending messages */
-    red_channel_client_ack_zero_messages_window(rcc);
-    return TRUE;
+    return dcc_handle_migrate_data(RCC_TO_DCC(rcc), size, message);
 }
 
 static int common_channel_config_socket(RedChannelClient *rcc)
-- 
2.4.3



More information about the Spice-devel mailing list