+ switch (state) {
+ case S_DISABLED:
+ break;
+
+ case S_WAITING:
+ if (time_msec() >= next_refresh) {
+ worker_request(NULL, 0, NULL, 0, system_stats_request_cb,
+ system_stats_reply_cb, NULL);
+ state = S_REQUEST_SENT;
+ }
+ break;
+
+ case S_REQUEST_SENT:
+ break;
+
+ case S_REPLY_RECEIVED:
+ if (enabled) {
+ state = S_WAITING;
+ next_refresh = time_msec() + SYSTEM_STATS_INTERVAL;
+ return received_stats;
+ } else {
+ smap_destroy(received_stats);
+ free(received_stats);
+ state = S_DISABLED;
+ }
+ break;
+ }
+
+ return NULL;
+}
+
+/* Causes poll_block() to wake up when system_stats_run() needs to be
+ * called. */
+void
+system_stats_wait(void)
+{
+ switch (state) {
+ case S_DISABLED:
+ break;
+
+ case S_WAITING:
+ poll_timer_wait_until(next_refresh);
+ break;
+
+ case S_REQUEST_SENT:
+ /* Someone else should be calling worker_wait() to wake up when the
+ * reply arrives, otherwise there's a bug. */
+ break;
+
+ case S_REPLY_RECEIVED:
+ poll_immediate_wake();
+ break;
+ }
+}
+
+static void
+system_stats_request_cb(struct ofpbuf *request OVS_UNUSED,
+ const int fds[] OVS_UNUSED, size_t n_fds OVS_UNUSED)
+{
+ struct smap stats;
+ struct json *json;
+ char *s;
+
+ smap_init(&stats);
+ get_cpu_cores(&stats);
+ get_load_average(&stats);
+ get_memory_stats(&stats);
+ get_process_stats(&stats);
+ get_filesys_stats(&stats);
+
+ json = smap_to_json(&stats);
+ s = json_to_string(json, 0);
+ worker_reply(s, strlen(s) + 1, NULL, 0);
+
+ free(s);
+ json_destroy(json);
+ smap_destroy(&stats);
+}
+
+static void
+system_stats_reply_cb(struct ofpbuf *reply,
+ const int fds[] OVS_UNUSED, size_t n_fds OVS_UNUSED,
+ void *aux OVS_UNUSED)
+{
+ struct json *json = json_from_string(reply->data);
+
+ received_stats = xmalloc(sizeof *received_stats);
+ smap_init(received_stats);
+ smap_from_json(received_stats, json);
+
+ assert(state == S_REQUEST_SENT);
+ state = S_REPLY_RECEIVED;
+
+ json_destroy(json);