This patch adds functions to register and unregister notifiers for
migration state changes and a function to query the migration state.
The notifier is called on every state change.  Once after establishing a
new migration object (which is in active state then) and once when the
state changes from active to completed, canceled or error.

Signed-off-by: Gerd Hoffmann <kra...@redhat.com>
---
 migration.c |   28 ++++++++++++++++++++++++++++
 migration.h |    5 +++++
 2 files changed, 33 insertions(+), 0 deletions(-)

diff --git a/migration.c b/migration.c
index e5ba51c..3f88666 100644
--- a/migration.c
+++ b/migration.c
@@ -36,6 +36,9 @@ static int64_t max_throttle = (32 << 20);
 
 static MigrationState *current_migration;
 
+static NotifierList migration_state_notifiers =
+    NOTIFIER_LIST_INITIALIZER(migration_state_notifiers);
+
 int qemu_start_incoming_migration(const char *uri)
 {
     const char *p;
@@ -117,6 +120,7 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject 
**ret_data)
     }
 
     current_migration = s;
+    notifier_list_notify(&migration_state_notifiers);
     return 0;
 }
 
@@ -268,6 +272,7 @@ void migrate_fd_error(FdMigrationState *s)
 {
     DPRINTF("setting error state\n");
     s->state = MIG_STATE_ERROR;
+    notifier_list_notify(&migration_state_notifiers);
     migrate_fd_cleanup(s);
 }
 
@@ -325,6 +330,7 @@ ssize_t migrate_fd_put_buffer(void *opaque, const void 
*data, size_t size)
             monitor_resume(s->mon);
         }
         s->state = MIG_STATE_ERROR;
+        notifier_list_notify(&migration_state_notifiers);
     }
 
     return ret;
@@ -385,6 +391,7 @@ void migrate_fd_put_ready(void *opaque)
             state = MIG_STATE_ERROR;
         }
         s->state = state;
+        notifier_list_notify(&migration_state_notifiers);
     }
 }
 
@@ -404,6 +411,7 @@ void migrate_fd_cancel(MigrationState *mig_state)
     DPRINTF("cancelling migration\n");
 
     s->state = MIG_STATE_CANCELLED;
+    notifier_list_notify(&migration_state_notifiers);
     qemu_savevm_state_cancel(s->mon, s->file);
 
     migrate_fd_cleanup(s);
@@ -417,6 +425,7 @@ void migrate_fd_release(MigrationState *mig_state)
    
     if (s->state == MIG_STATE_ACTIVE) {
         s->state = MIG_STATE_CANCELLED;
+        notifier_list_notify(&migration_state_notifiers);
         migrate_fd_cleanup(s);
     }
     qemu_free(s);
@@ -448,3 +457,22 @@ int migrate_fd_close(void *opaque)
     qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
     return s->close(s);
 }
+
+void add_migration_state_change_notifier(Notifier *notify)
+{
+    notifier_list_add(&migration_state_notifiers, notify);
+}
+
+void remove_migration_state_change_notifier(Notifier *notify)
+{
+    notifier_list_remove(&migration_state_notifiers, notify);
+}
+
+int get_migration_state(void)
+{
+    if (current_migration) {
+        return migrate_fd_get_status(current_migration);
+    } else {
+        return MIG_STATE_ERROR;
+    }
+}
diff --git a/migration.h b/migration.h
index d13ed4f..2170792 100644
--- a/migration.h
+++ b/migration.h
@@ -16,6 +16,7 @@
 
 #include "qdict.h"
 #include "qemu-common.h"
+#include "notify.h"
 
 #define MIG_STATE_ERROR                -1
 #define MIG_STATE_COMPLETED    0
@@ -134,4 +135,8 @@ static inline FdMigrationState 
*migrate_to_fms(MigrationState *mig_state)
     return container_of(mig_state, FdMigrationState, mig_state);
 }
 
+void add_migration_state_change_notifier(Notifier *notify);
+void remove_migration_state_change_notifier(Notifier *notify);
+int get_migration_state(void);
+
 #endif
-- 
1.7.1


Reply via email to