Add json output for client/server mode
[fio.git] / stat.c
diff --git a/stat.c b/stat.c
index 03a45fc70a197562cc09c2a21d1fbf9f645c3867..ac5ff162acc4f6c8d93ee56cf7b0b16fe30fd1db 100644 (file)
--- a/stat.c
+++ b/stat.c
@@ -14,6 +14,8 @@
 #include "lib/getrusage.h"
 #include "idletime.h"
 
+static struct fio_mutex *stat_mutex;
+
 void update_rusage_stat(struct thread_data *td)
 {
        struct thread_stat *ts = &td->ts;
@@ -241,15 +243,13 @@ out:
 int calc_lat(struct io_stat *is, unsigned long *min, unsigned long *max,
             double *mean, double *dev)
 {
-       double n = is->samples;
+       double n = (double) is->samples;
 
-       if (is->samples == 0)
+       if (n == 0)
                return 0;
 
        *min = is->min_val;
        *max = is->max_val;
-
-       n = (double) is->samples;
        *mean = is->mean.u.f;
 
        if (n > 1.0)
@@ -497,7 +497,8 @@ static void show_latencies(struct thread_stat *ts)
        show_lat_m(io_u_lat_m);
 }
 
-void show_thread_status(struct thread_stat *ts, struct group_run_stats *rs)
+
+void show_thread_status_normal(struct thread_stat *ts, struct group_run_stats *rs)
 {
        double usr_cpu, sys_cpu;
        unsigned long runtime;
@@ -883,7 +884,8 @@ static void show_thread_status_terse_v3_v4(struct thread_stat *ts,
                log_info(";%3.2f%%", io_u_lat_m[i]);
 
        /* disk util stats, if any */
-       show_disk_util(1, NULL);
+       if (is_backend)
+               show_disk_util(1, NULL);
 
        /* Additional output if continue_on_error set - default off*/
        if (ts->continue_on_error)
@@ -970,7 +972,7 @@ static struct json_object *show_thread_status_json(struct thread_stat *ts,
        /* Additional output if continue_on_error set - default off*/
        if (ts->continue_on_error) {
                json_object_add_value_int(root, "total_err", ts->total_err_count);
-               json_object_add_value_int(root, "total_err", ts->first_error);
+               json_object_add_value_int(root, "first_error", ts->first_error);
        }
 
        /* Additional output if description is set */
@@ -991,6 +993,18 @@ static void show_thread_status_terse(struct thread_stat *ts,
                log_err("fio: bad terse version!? %d\n", terse_version);
 }
 
+struct json_object *show_thread_status(struct thread_stat *ts,
+                                      struct group_run_stats *rs)
+{
+       if (output_format == FIO_OUTPUT_TERSE)
+               show_thread_status_terse(ts, rs);
+       else if (output_format == FIO_OUTPUT_JSON)
+               return(show_thread_status_json(ts, rs));
+       else
+               show_thread_status_normal(ts, rs);
+       return NULL;
+}
+
 static void sum_stat(struct io_stat *dst, struct io_stat *src, int nr)
 {
        double mean, S;
@@ -1141,7 +1155,7 @@ void init_thread_stat(struct thread_stat *ts)
        ts->groupid = -1;
 }
 
-void show_run_stats(void)
+static void __show_run_stats(void)
 {
        struct group_run_stats *runstats, *rs;
        struct thread_data *td;
@@ -1324,7 +1338,7 @@ void show_run_stats(void)
                        struct json_object *tmp = show_thread_status_json(ts, rs);
                        json_array_add_value_object(array, tmp);
                } else
-                       show_thread_status(ts, rs);
+                       show_thread_status_normal(ts, rs);
        }
        if (output_format == FIO_OUTPUT_JSON) {
                /* disk util stats, if any */
@@ -1359,6 +1373,13 @@ void show_run_stats(void)
        free(threadstats);
 }
 
+void show_run_stats(void)
+{
+       fio_mutex_down(stat_mutex);
+       __show_run_stats();
+       fio_mutex_up(stat_mutex);
+}
+
 static void *__show_running_run_stats(void fio_unused *arg)
 {
        struct thread_data *td;
@@ -1393,7 +1414,7 @@ static void *__show_running_run_stats(void fio_unused *arg)
                td->update_rusage = 0;
        }
 
-       show_run_stats();
+       __show_run_stats();
 
        for_each_td(td, i) {
                if (td_read(td) && td->io_bytes[DDIR_READ])
@@ -1405,6 +1426,7 @@ static void *__show_running_run_stats(void fio_unused *arg)
        }
 
        free(rt);
+       fio_mutex_up(stat_mutex);
        return NULL;
 }
 
@@ -1417,8 +1439,14 @@ void show_running_run_stats(void)
 {
        pthread_t thread;
 
-       pthread_create(&thread, NULL, __show_running_run_stats, NULL);
-       pthread_detach(thread);
+       fio_mutex_down(stat_mutex);
+
+       if (!pthread_create(&thread, NULL, __show_running_run_stats, NULL)) {
+               pthread_detach(thread);
+               return;
+       }
+
+       fio_mutex_up(stat_mutex);
 }
 
 static int status_interval_init;
@@ -1429,11 +1457,21 @@ static struct timeval status_time;
 static int check_status_file(void)
 {
        struct stat sb;
+       const char *temp_dir;
+       char fio_status_file_path[PATH_MAX];
+
+       temp_dir = getenv("TMPDIR");
+       if (temp_dir == NULL)
+               temp_dir = getenv("TEMP");
+       if (temp_dir == NULL)
+               temp_dir = "/tmp";
+
+       snprintf(fio_status_file_path, sizeof(fio_status_file_path), "%s/%s", temp_dir, FIO_STATUS_FILE);
 
-       if (stat(FIO_STATUS_FILE, &sb))
+       if (stat(fio_status_file_path, &sb))
                return 0;
 
-       unlink(FIO_STATUS_FILE);
+       unlink(fio_status_file_path);
        return 1;
 }
 
@@ -1480,13 +1518,23 @@ static void __add_log_sample(struct io_log *iolog, unsigned long val,
 {
        const int nr_samples = iolog->nr_samples;
 
+       if (iolog->disabled)
+               return;
+
        if (!iolog->nr_samples)
                iolog->avg_last = t;
 
        if (iolog->nr_samples == iolog->max_samples) {
                int new_size = sizeof(struct io_sample) * iolog->max_samples*2;
+               void *new_log;
 
-               iolog->log = realloc(iolog->log, new_size);
+               new_log = realloc(iolog->log, new_size);
+               if (!new_log) {
+                       log_err("fio: failed extending iolog! Will stop logging.\n");
+                       iolog->disabled = 1;
+                       return;
+               }
+               iolog->log = new_log;
                iolog->max_samples <<= 1;
        }
 
@@ -1667,7 +1715,7 @@ void add_bw_sample(struct thread_data *td, enum fio_ddir ddir, unsigned int bs,
        fio_gettime(&td->bw_sample_time, NULL);
 }
 
-void add_iops_sample(struct thread_data *td, enum fio_ddir ddir,
+void add_iops_sample(struct thread_data *td, enum fio_ddir ddir, unsigned int bs,
                     struct timeval *t)
 {
        struct thread_stat *ts = &td->ts;
@@ -1694,10 +1742,25 @@ void add_iops_sample(struct thread_data *td, enum fio_ddir ddir,
                add_stat_sample(&ts->iops_stat[ddir], iops);
 
                if (td->iops_log)
-                       add_log_sample(td, td->iops_log, iops, ddir, 0);
+                       add_log_sample(td, td->iops_log, iops, ddir, bs);
 
                td->stat_io_blocks[ddir] = td->this_io_blocks[ddir];
        }
 
        fio_gettime(&td->iops_sample_time, NULL);
 }
+
+void stat_init(void)
+{
+       stat_mutex = fio_mutex_init(FIO_MUTEX_UNLOCKED);
+}
+
+void stat_exit(void)
+{
+       /*
+        * When we have the mutex, we know out-of-band access to it
+        * have ended.
+        */
+       fio_mutex_down(stat_mutex);
+       fio_mutex_remove(stat_mutex);
+}