#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
#include "statistic.h"
#include "generic.h"
#include "preferences.h"
#include "globalstats.h"
#include "top.h"
#include "sig.h"
struct log_get_total_data {
int total;
};
static bool log_get_total_iter(struct statistic *s, void *ptr) {
struct log_get_total_data *data = ptr;
struct generic_cells *cells;
cells = s->cells;
if(NULL == cells)
return false;
data->total = cells->length;
return false;
}
static int log_get_total(void *tinst) {
struct statistics_controller *c = tinst;
struct log_get_total_data data;
data.total = 0;
c->iterate(c, log_get_total_iter, &data);
return data.total;
}
struct log_print_header_data {
int x;
int xoffset;
bool have_limit;
int ncols;
int column;
};
static bool log_print_header_iter(struct statistic *s, void *ptr) {
struct log_print_header_data *data = ptr;
int max_width, headerlen;
struct generic_cells *cells;
int i, afterx;
cells = s->cells;
if(NULL == cells)
return false;
max_width = cells->max_width;
headerlen = (int)strlen(s->header);
if(headerlen > max_width)
max_width = headerlen;
afterx = max_width + data->x;
for(i = 0; i < data->xoffset; ++i)
putchar(' ');
printf("%s", s->header);
for(i = headerlen; i < max_width; ++i)
putchar(' ');
data->x = afterx;
data->xoffset = 1;
data->column++;
if(data->have_limit && data->column >= data->ncols)
return false;
return true;
}
static void log_print_header(void *tinst) {
struct statistics_controller *c = tinst;
struct log_print_header_data data;
data.x = 0;
data.xoffset = 0;
data.have_limit = top_prefs_get_ncols(&data.ncols);
data.column = 0;
c->iterate(c, log_print_header_iter, &data);
}
struct log_print_cell_data {
int x;
int xoffset;
bool have_limit;
int ncols;
int column;
int row;
};
static bool log_print_cell(struct statistic *s, void *ptr) {
struct log_print_cell_data *data = ptr;
struct generic_cells *cells;
size_t i;
int pad;
int afterx;
int max_width;
int headerlen;
cells = s->cells;
if(NULL == cells)
return false;
max_width = cells->max_width;
headerlen = (int)strlen(s->header);
if(headerlen > max_width)
max_width = headerlen;
afterx = data->x + max_width;
assert(data->row < cells->length);
for(pad = 0; pad < data->xoffset; ++pad) {
putchar(' ');
}
printf("%s", cells->array[data->row].string);
for(i = cells->array[data->row].length; i < (size_t)max_width; ++i) {
putchar(' ');
}
data->x = afterx;
data->xoffset = 1;
data->column++;
if(data->have_limit && data->column >= data->ncols)
return false;
return true;
}
static bool log_print_globalstats(char *s, void *ptr) {
printf("%s\n", s);
return true;
}
static void log_print_all(void *tinst) {
struct statistics_controller *c = tinst;
struct log_print_cell_data data;
int y, ylimit;
top_globalstats_iterate(c->globalstats, log_print_globalstats, NULL);
putchar('\n');
log_print_header(tinst);
putchar('\n');
data.x = 0;
data.xoffset = 0;
data.have_limit = top_prefs_get_ncols(&data.ncols);
data.column = 0;
data.row = 0;
ylimit = log_get_total(tinst);
for(y = 0; y < ylimit; ++y) {
data.x = 0;
data.xoffset = 0;
data.column = 0;
c->iterate(c, log_print_cell, &data);
data.row++;
putchar('\n');
}
}
void top_logging_loop_body(void *tinst, bool with_sleep) {
top_insert(tinst);
log_print_all(tinst);
fflush(stdout);
if (with_sleep) {
sleep(top_prefs_get_sleep());
}
if(top_signal_is_exit_set())
exit(EXIT_SUCCESS);
}
void top_logging_loop(void *tinst) {
int samples;
bool forever = false;
if(0 == top_prefs_get_samples())
forever = true;
if(forever) {
while(1)
top_logging_loop_body(tinst, true);
} else {
for(samples = top_prefs_get_samples(); samples > 0; --samples)
top_logging_loop_body(tinst, samples > 1);
exit(EXIT_SUCCESS);
}
}