This adds a VMSTATE_HASH_V macro. This implements put/get callbacks for it. This implements a qemu_hash_init() wrapper to save key/value sizes.
Signed-off-by: Alexey Kardashevskiy <a...@ozlabs.ru> --- include/migration/vmstate.h | 10 +++++++++ include/qemu-common.h | 13 +++++++++++ vmstate.c | 54 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+) diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h index 7e45048..6af599d 100644 --- a/include/migration/vmstate.h +++ b/include/migration/vmstate.h @@ -166,6 +166,7 @@ extern const VMStateInfo vmstate_info_timer; extern const VMStateInfo vmstate_info_buffer; extern const VMStateInfo vmstate_info_unused_buffer; extern const VMStateInfo vmstate_info_bitmap; +static const VMStateInfo vmstate_info_hash; #define type_check_2darray(t1,t2,n,m) ((t1(*)[n][m])0 - (t2*)0) #define type_check_array(t1,t2,n) ((t1(*)[n])0 - (t2*)0) @@ -740,6 +741,15 @@ extern const VMStateInfo vmstate_info_bitmap; #define VMSTATE_BUFFER_UNSAFE(_field, _state, _version, _size) \ VMSTATE_BUFFER_UNSAFE_INFO(_field, _state, _version, vmstate_info_buffer, _size) +#define VMSTATE_HASH_V(_field, _state, _version) { \ + .name = (stringify(_field)), \ + .version_id = (_version), \ + .size = sizeof(qemu_hash), \ + .info = &vmstate_info_hash, \ + .flags = VMS_SINGLE, \ + .offset = vmstate_offset_value(_state, _field, qemu_hash), \ +} + #define VMSTATE_UNUSED_V(_v, _size) \ VMSTATE_UNUSED_BUFFER(NULL, _v, _size) diff --git a/include/qemu-common.h b/include/qemu-common.h index 3f3fd60..ee973e7 100644 --- a/include/qemu-common.h +++ b/include/qemu-common.h @@ -462,4 +462,17 @@ int parse_debug_env(const char *name, int max, int initial); const char *qemu_ether_ntoa(const MACAddr *mac); +typedef struct qemu_hash { + GHashTable *hash; + int key_size; + int value_size; +} qemu_hash; + +static inline void qemu_hash_init(qemu_hash *h, int key_size, int value_size) +{ + h->key_size = key_size; + h->value_size = value_size; + h->hash = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, g_free); +} + #endif diff --git a/vmstate.c b/vmstate.c index b5882fa..2148e73 100644 --- a/vmstate.c +++ b/vmstate.c @@ -667,3 +667,57 @@ const VMStateInfo vmstate_info_bitmap = { .get = get_bitmap, .put = put_bitmap, }; + +/* Save restore for qemu_hash which is a wrapper over GHashTable */ +static int get_hash(QEMUFile *f, void *pv, size_t size) +{ + qemu_hash *h = pv; + uint32_t num = g_hash_table_size(h->hash); + gpointer key, value; + + num = qemu_get_be32(f); + + for ( ; num; --num) { + int i; + + key = g_malloc0(h->key_size); + for (i = 0; i < h->key_size; ++i) { + ((uint8_t *)key)[i] = qemu_get_byte(f); + } + value = g_malloc0(h->value_size); + for (i = 0; i < h->value_size; ++i) { + ((uint8_t *)value)[i] = qemu_get_byte(f); + } + g_hash_table_insert(h->hash, key, value); + } + + return 0; +} + +static void put_hash(QEMUFile *f, void *pv, size_t size) +{ + qemu_hash *h = pv; + uint32_t num = g_hash_table_size(h->hash); + GHashTableIter iter; + gpointer key, value; + + qemu_put_be32(f, num); + + g_hash_table_iter_init(&iter, h->hash); + while (g_hash_table_iter_next (&iter, &key, &value)) { + int i; + + for (i = 0; i < h->key_size; ++i) { + qemu_put_byte(f, ((uint8_t *)key)[i]); + } + for (i = 0; i < h->value_size; ++i) { + qemu_put_byte(f, ((uint8_t *)value)[i]); + } + } +} + +static const VMStateInfo vmstate_info_hash = { + .name = "qemu-hash-desc", + .get = get_hash, + .put = put_hash, +}; -- 1.9.rc0