From 99ea64ac5a5243e56acc5f1991780d675c98ccd7 Mon Sep 17 00:00:00 2001 From: Yonit Halperin Date: Fri, 3 Aug 2012 00:22:29 +0300 Subject: char device migration: restore state at destination from migration data --- server/char_device.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ server/char_device.h | 3 +++ 2 files changed, 52 insertions(+) (limited to 'server') diff --git a/server/char_device.c b/server/char_device.c index d97c6dda..b85a24d1 100644 --- a/server/char_device.c +++ b/server/char_device.c @@ -873,3 +873,52 @@ void spice_char_device_state_migrate_data_marshall(SpiceCharDeviceState *dev, dev, *write_to_dev_size_ptr, *write_to_dev_tokens_ptr); } +int spice_char_device_state_restore(SpiceCharDeviceState *dev, + SpiceMigrateDataCharDevice *mig_data) +{ + SpiceCharDeviceClientState *client_state; + uint32_t client_tokens_window; + + spice_assert(dev->num_clients == 1 && dev->wait_for_migrate_data); + + client_state = SPICE_CONTAINEROF(ring_get_tail(&dev->clients), + SpiceCharDeviceClientState, + link); + if (mig_data->version > SPICE_MIGRATE_DATA_CHAR_DEVICE_VERSION) { + spice_error("dev %p error: migration data version %u is bigger than self %u", + dev, mig_data->version, SPICE_MIGRATE_DATA_CHAR_DEVICE_VERSION); + return FALSE; + } + spice_assert(!dev->cur_write_buf && ring_is_empty(&dev->write_queue)); + spice_assert(mig_data->connected); + + client_tokens_window = client_state->num_client_tokens; /* initial state of tokens */ + client_state->num_client_tokens = mig_data->num_client_tokens; + /* assumption: client_tokens_window stays the same across severs */ + client_state->num_client_tokens_free = client_tokens_window - + mig_data->num_client_tokens - + mig_data->write_num_client_tokens; + client_state->num_send_tokens = mig_data->num_send_tokens; + + if (mig_data->write_size > 0) { + if (mig_data->write_num_client_tokens) { + dev->cur_write_buf = __spice_char_device_write_buffer_get(dev, client_state->client, + mig_data->write_size, + mig_data->write_num_client_tokens); + } else { + dev->cur_write_buf = __spice_char_device_write_buffer_get(dev, NULL, mig_data->write_size, + 0); + } + /* the first write buffer contains all the data that was saved for migration */ + memcpy(dev->cur_write_buf->buf, + ((uint8_t *)mig_data) + mig_data->write_data_ptr - sizeof(SpiceMigrateDataHeader), + mig_data->write_size); + dev->cur_write_buf->buf_used = mig_data->write_size; + dev->cur_write_buf_pos = dev->cur_write_buf->buf; + } + dev->wait_for_migrate_data = FALSE; + spice_char_device_write_to_device(dev); + spice_char_device_read_from_device(dev); + return TRUE; +} + diff --git a/server/char_device.h b/server/char_device.h index f3278e3d..6688e913 100644 --- a/server/char_device.h +++ b/server/char_device.h @@ -126,6 +126,9 @@ void spice_char_device_state_migrate_data_marshall(SpiceCharDeviceState *dev, SpiceMarshaller *m); void spice_char_device_state_migrate_data_marshall_empty(SpiceMarshaller *m); +int spice_char_device_state_restore(SpiceCharDeviceState *dev, + SpiceMigrateDataCharDevice *mig_data); + /* * Resets write/read queues, and moves that state to being stopped. * This routine is a workaround for a bad tokens management in the vdagent -- cgit