* Get report date as a string of characters.
*
* IN:
- * @rectime Date to display (don't use time fields).
+ * @tm_time Date to display (don't use time fields).
* @cur_date String where date will be saved.
* @sz Max size of cur_date string.
*
* TRUE if S_TIME_FORMAT is set to ISO, or FALSE otherwise.
***************************************************************************
*/
-int set_report_date(struct tm *rectime, char cur_date[], int sz)
+int set_report_date(struct tm *tm_time, char cur_date[], int sz)
{
- if (rectime == NULL) {
+ if (tm_time == NULL) {
strncpy(cur_date, "?/?/?", sz);
cur_date[sz - 1] = '\0';
}
else if (is_iso_time_fmt()) {
- strftime(cur_date, sz, "%Y-%m-%d", rectime);
+ strftime(cur_date, sz, "%Y-%m-%d", tm_time);
return 1;
}
else {
- strftime(cur_date, sz, "%x", rectime);
+ strftime(cur_date, sz, "%x", tm_time);
}
return 0;
* Print banner.
*
* IN:
- * @rectime Date to display (don't use time fields).
+ * @tm_time Date to display (don't use time fields).
* @sysname System name to display.
* @release System release number to display.
* @nodename Hostname to display.
* TRUE if S_TIME_FORMAT is set to ISO, or FALSE otherwise.
***************************************************************************
*/
-int print_gal_header(struct tm *rectime, char *sysname, char *release,
+int print_gal_header(struct tm *tm_time, char *sysname, char *release,
char *nodename, char *machine, int cpu_nr, int format)
{
char cur_date[TIMESTAMP_LEN];
int rc = 0;
- rc = set_report_date(rectime, cur_date, sizeof(cur_date));
+ rc = set_report_date(tm_time, cur_date, sizeof(cur_date));
if (format == PLAIN_OUTPUT) {
/* Plain output */
/* Miscellaneous constants */
#define USE_SADC 0
#define USE_SA_FILE 1
-#define NO_TM_START 0
-#define NO_TM_END 0
#define NO_RESET 0
#define NO_RANGE 0
#define NON_FATAL 0
/* Type for all functions displaying statistics */
#define __print_funct_t void
+/*
+ * **************************************************************************
+ * Various structure definitions.
+ ***************************************************************************
+ */
+
+enum time_mode {
+ NO_TIME = 0,
+ USE_HHMMSS_T = 1,
+ USE_EPOCH_T = 2
+};
+
+/*
+ * Structure for timestamps.
+ * @tm_time has the GMT or local broken time representation of @epoch_time.
+ * Exception is when the structure is used to save the timestamp given by the
+ * user on the command line with options -s/-e. In this case, it includes either
+ * the number of seconds since the epoch *or* the broken time entered by the user.
+ */
+struct tstamp_ext {
+ unsigned long long epoch_time;
+ struct tm tm_time;
+ enum time_mode use;
+};
+
+/* Structure for items in list */
+struct sa_item {
+ char *item_name;
+ struct sa_item *next;
+};
+
/*
***************************************************************************
- * Output formats for sadfsize_mode
+ * Output formats for sadf
***************************************************************************
*/
* This is the main function used to display all the statistics for current format.
*/
void (*f_display) (int, char *, struct file_activity *, struct file_magic *,
- struct tm *, void *);
+ struct tstamp_ext *, void *);
};
#define CLOSE(_fd_) if (_fd_ >= 0) \
close(_fd_)
-
-/*
- ***************************************************************************
- * Various structure definitions.
- ***************************************************************************
- */
-
-/* Structure for timestamps */
-struct tstamp {
- int tm_sec;
- int tm_min;
- int tm_hour;
- int use;
-};
-
-/* Structure for items in list */
-struct sa_item {
- char *item_name;
- struct sa_item *next;
-};
-
-
/*
***************************************************************************
* Functions prototypes.
(struct activity *, int, int, int);
int check_net_edev_reg
(struct activity *, int, int, int);
+int check_time_limits
+ (struct tstamp_ext *, struct tstamp_ext *);
double compute_ifutil
(struct stats_net_dev *, double, double);
void copy_structures
(struct activity * [], unsigned int [], struct record_header [], int, int);
int datecmp
- (struct tm *, struct tstamp *, int);
+ (struct tstamp_ext *, struct tstamp_ext *, int);
void display_sa_file_version
(FILE *, struct file_magic *);
void free_bitmaps
int parse_sar_q_opt
(char * [], int *, struct activity * []);
int parse_timestamp
- (char * [], int *, struct tstamp *, const char *, uint64_t);
+ (char * [], int *, struct tstamp_ext *, const char *, uint64_t);
void print_report_hdr
(uint64_t, struct tm *, struct file_header *);
void print_sar_comment
__printf_funct_t print_sar_restart
(int *, int, char *, char *, char *, struct file_header *, struct record_header *);
int print_special_record
- (struct record_header *, uint64_t, struct tstamp *, struct tstamp *,
- int, int, struct tm *, char *, int, char *, struct file_magic *,
+ (struct record_header *, uint64_t, struct tstamp_ext *, struct tstamp_ext *,
+ int, int, struct tstamp_ext *, char *, int, char *, struct file_magic *,
struct file_header *, struct activity * [], struct report_format *, int, int);
int read_file_stat_bunch
(struct activity * [], int, int, int, struct file_activity *, int, int,
int sa_fread
(int, void *, size_t, enum size_mode, enum on_eof);
int sa_get_record_timestamp_struct
- (uint64_t, struct record_header *, struct tm *);
+ (uint64_t, struct record_header *, struct tstamp_ext *);
int sa_open_read_magic
(int *, char *, struct file_magic *, int, int *, int);
int search_list_item
void set_hdr_rectime
(unsigned int, struct tm *, struct file_header *);
void set_record_timestamp_string
- (uint64_t, struct record_header *, char *, char *, int, struct tm *);
+ (uint64_t, char *, char *, int, struct tstamp_ext *);
void swap_struct
(unsigned int [], void *, int);
#endif /* SOURCE_SADC undefined */
/*
***************************************************************************
- * Use time stamp to fill tstamp structure.
+ * Use time stamp to fill tstamp_ext structure.
*
* IN:
* @timestamp Timestamp to decode (format: HH:MM:SS).
* 0 if the timestamp has been successfully decoded, 1 otherwise.
***************************************************************************
*/
-int decode_timestamp(char timestamp[], struct tstamp *tse)
+int decode_timestamp(char timestamp[], struct tstamp_ext *tse)
{
timestamp[2] = timestamp[5] = '\0';
(strspn(×tamp[6], DIGITS) != 2))
return 1;
- tse->tm_sec = atoi(×tamp[6]);
- tse->tm_min = atoi(×tamp[3]);
- tse->tm_hour = atoi(timestamp);
+ tse->tm_time.tm_sec = atoi(×tamp[6]);
+ tse->tm_time.tm_min = atoi(×tamp[3]);
+ tse->tm_time.tm_hour = atoi(timestamp);
- if ((tse->tm_sec < 0) || (tse->tm_sec > 59) ||
- (tse->tm_min < 0) || (tse->tm_min > 59) ||
- (tse->tm_hour < 0) || (tse->tm_hour > 23)) {
- tse->use = FALSE;
+ if ((tse->tm_time.tm_sec < 0) || (tse->tm_time.tm_sec > 59) ||
+ (tse->tm_time.tm_min < 0) || (tse->tm_time.tm_min > 59) ||
+ (tse->tm_time.tm_hour < 0) || (tse->tm_time.tm_hour > 23)) {
+ tse->use = NO_TIME;
return 1;
}
- tse->use = TRUE;
+ tse->use = USE_HHMMSS_T;
return 0;
}
/*
***************************************************************************
- * Use time stamp to fill tstamp structure.
+ * Use time stamp to fill tstamp_ext structure.
*
* IN:
* @timestamp Epoch time to decode (format: number of seconds since
* 0 if the epoch time has been successfully decoded, 1 otherwise.
***************************************************************************
*/
-int decode_epoch(char timestamp[], struct tstamp *tse, uint64_t flags)
+int decode_epoch(char timestamp[], struct tstamp_ext *tse, uint64_t flags)
{
- time_t epoch = atol(timestamp);
- struct tm given_time;
+ tse->epoch_time = atol(timestamp);
- if (epoch <= 0) {
- tse->use = FALSE;
+ if (tse->epoch_time <= 0) {
+ tse->use = NO_TIME;
return 1;
}
- if (PRINT_LOCAL_TIME(flags)) {
- /* This is for sar or sadf -T */
- localtime_r(&epoch, &given_time);
- }
- else {
- /* This is for sadf */
- gmtime_r(&epoch, &given_time);
- }
- tse->tm_sec = given_time.tm_sec;
- tse->tm_min = given_time.tm_min;
- tse->tm_hour = given_time.tm_hour;
-
- tse->use = TRUE;
+ tse->use = USE_EPOCH_T;
return 0;
}
* RETURNS:
* A positive value if @rectime is greater than @tse,
* a negative one otherwise.
+ * Also returns 0 if no valid time is saved in @tse.
***************************************************************************
*/
-int datecmp(struct tm *rectime, struct tstamp *tse, int cross_day)
+int datecmp(struct tstamp_ext *rectime, struct tstamp_ext *tse, int cross_day)
{
- int tm_hour = rectime->tm_hour;
+ int tm_hour;
- if (cross_day) {
- /*
- * This is necessary if we want to properly handle something like:
- * sar -s time_start -e time_end with
- * time_start(day D) > time_end(day D+1)
- */
- tm_hour += 24;
- }
+ switch (tse->use) {
- if (tm_hour == tse->tm_hour) {
- if (rectime->tm_min == tse->tm_min)
- return (rectime->tm_sec - tse->tm_sec);
- else
- return (rectime->tm_min - tse->tm_min);
+ case USE_HHMMSS_T:
+ /*
+ * This is necessary if we want to properly handle something like:
+ * sar -s time_start -e time_end with
+ * time_start(day D) > time_end(day D+1)
+ */
+ tm_hour = rectime->tm_time.tm_hour + (24 * (cross_day != 0));
+
+ if (tm_hour == tse->tm_time.tm_hour) {
+ if (rectime->tm_time.tm_min == tse->tm_time.tm_min)
+ return (rectime->tm_time.tm_sec - tse->tm_time.tm_sec);
+ else
+ return (rectime->tm_time.tm_min - tse->tm_time.tm_min);
+ }
+ else
+ return (tm_hour - tse->tm_time.tm_hour);
+
+ case USE_EPOCH_T:
+ return (rectime->epoch_time - tse->epoch_time);
+
+ default: /* NO_TIME */
+ return 0;
}
- else
- return (tm_hour - tse->tm_hour);
}
/*
* 0 if the timestamp has been successfully decoded, 1 otherwise.
***************************************************************************
*/
-int parse_timestamp(char *argv[], int *opt, struct tstamp *tse,
+int parse_timestamp(char *argv[], int *opt, struct tstamp_ext *tse,
const char *def_timestamp, uint64_t flags)
{
char timestamp[11];
/*
***************************************************************************
- * Fill the rectime structure with the file's creation date, based on file's
+ * Fill the tm_time structure with the file's creation date, based on file's
* time data saved in file header.
* The resulting timestamp is expressed in the locale of the file creator or
* in the user's own locale, depending on whether option -t has been used
* @file_hdr System activity file standard header.
*
* OUT:
- * @rectime Date (and possibly time) from file header. Only the date,
+ * @tm_time Date (and possibly time) from file header. Only the date,
* not the time, should be used by the caller.
***************************************************************************
*/
-void get_file_timestamp_struct(uint64_t flags, struct tm *rectime,
+void get_file_timestamp_struct(uint64_t flags, struct tm *tm_time,
struct file_header *file_hdr)
{
time_t t = file_hdr->sa_ust_time;
if (PRINT_TRUE_TIME(flags)) {
/* Get local time. This is just to fill fields with a default value. */
- get_time(rectime, 0);
+ get_time(tm_time, 0);
- rectime->tm_mday = file_hdr->sa_day;
- rectime->tm_mon = file_hdr->sa_month;
- rectime->tm_year = file_hdr->sa_year;
+ tm_time->tm_mday = file_hdr->sa_day;
+ tm_time->tm_mon = file_hdr->sa_month;
+ tm_time->tm_year = file_hdr->sa_year;
/*
* Call mktime() to set DST (Daylight Saving Time) flag.
* Has anyone a better way to do it?
*/
- rectime->tm_hour = rectime->tm_min = rectime->tm_sec = 0;
- mktime(rectime);
+ tm_time->tm_hour = tm_time->tm_min = tm_time->tm_sec = 0;
+ mktime(tm_time);
}
else {
- localtime_r(&t, rectime);
+ localtime_r(&t, tm_time);
}
}
* @file_hdr System activity file standard header.
*
* OUT:
- * @rectime Date and time from file header.
+ * @tm_time Date and time from file header.
***************************************************************************
*/
-void print_report_hdr(uint64_t flags, struct tm *rectime,
+void print_report_hdr(uint64_t flags, struct tm *tm_time,
struct file_header *file_hdr)
{
/* Get date of file creation */
- get_file_timestamp_struct(flags, rectime, file_hdr);
+ get_file_timestamp_struct(flags, tm_time, file_hdr);
/*
* Display the header.
* 1 means that there is only one proc and non SMP kernel.
* 2 means one proc and SMP kernel. Etc.
*/
- print_gal_header(rectime, file_hdr->sa_sysname, file_hdr->sa_release,
+ print_gal_header(tm_time, file_hdr->sa_sysname, file_hdr->sa_release,
file_hdr->sa_nodename, file_hdr->sa_machine,
file_hdr->sa_cpu_nr > 1 ? file_hdr->sa_cpu_nr - 1 : 1,
PLAIN_OUTPUT);
***************************************************************************
*/
int sa_get_record_timestamp_struct(uint64_t l_flags, struct record_header *record_hdr,
- struct tm *rectime)
+ struct tstamp_ext *rectime)
{
struct tm *ltm;
- time_t t = record_hdr->ust_time;
+ time_t t = (time_t) record_hdr->ust_time;
int rc = 0;
+ rectime->epoch_time = record_hdr->ust_time;
+
if (!PRINT_LOCAL_TIME(l_flags) && !PRINT_TRUE_TIME(l_flags)) {
/*
* Get time in UTC
* (the user doesn't want local time nor time of file's creator).
*/
- ltm = gmtime_r(&t, rectime);
+ ltm = gmtime_r(&t, &(rectime->tm_time));
}
else {
/*
* Fill generic rectime structure in local time.
* Done so that we have some default values.
*/
- ltm = localtime_r(&t, rectime);
- rectime->tm_gmtoff = TRUE;
+ ltm = localtime_r(&t, &(rectime->tm_time));
+ rectime->tm_time.tm_gmtoff = TRUE;
}
if (!ltm) {
if (PRINT_TRUE_TIME(l_flags)) {
/* Time of file's creator */
- rectime->tm_hour = record_hdr->hour;
- rectime->tm_min = record_hdr->minute;
- rectime->tm_sec = record_hdr->second;
+ rectime->tm_time.tm_hour = record_hdr->hour;
+ rectime->tm_time.tm_min = record_hdr->minute;
+ rectime->tm_time.tm_sec = record_hdr->second;
}
return rc;
* @l_flags Flags indicating the type of time expected by the user.
* S_F_SEC_EPOCH means the time should be expressed in seconds
* since the epoch (01/01/1970).
- * @record_hdr Record header containing the number of seconds since the
- * epoch.
* @cur_date String where timestamp's date will be saved. May be NULL.
* @cur_time String where timestamp's time will be saved.
* @len Maximum length of timestamp strings.
* been used.
***************************************************************************
*/
-void set_record_timestamp_string(uint64_t l_flags, struct record_header *record_hdr,
- char *cur_date, char *cur_time, int len, struct tm *rectime)
+void set_record_timestamp_string(uint64_t l_flags, char *cur_date, char *cur_time, int len,
+ struct tstamp_ext *rectime)
{
/* Set cur_time date value */
if (PRINT_SEC_EPOCH(l_flags) && cur_date) {
- sprintf(cur_time, "%llu", record_hdr->ust_time);
+ sprintf(cur_time, "%llu", rectime->epoch_time);
strcpy(cur_date, "");
}
else {
* expressed in local time. Else it is expressed in UTC.
*/
if (cur_date) {
- strftime(cur_date, len, "%Y-%m-%d", rectime);
+ strftime(cur_date, len, "%Y-%m-%d", &(rectime->tm_time));
}
if (USE_PREFD_TIME_OUTPUT(l_flags)) {
- strftime(cur_time, len, "%X", rectime);
+ strftime(cur_time, len, "%X", &(rectime->tm_time));
}
else {
- strftime(cur_time, len, "%H:%M:%S", rectime);
+ strftime(cur_time, len, "%H:%M:%S", &(rectime->tm_time));
}
}
}
***************************************************************************
*/
int print_special_record(struct record_header *record_hdr, uint64_t l_flags,
- struct tstamp *tm_start, struct tstamp *tm_end, int rtype, int ifd,
- struct tm *rectime, char *file, int tab, char *my_tz,
+ struct tstamp_ext *tm_start, struct tstamp_ext *tm_end, int rtype,
+ int ifd, struct tstamp_ext *rectime, char *file, int tab, char *my_tz,
struct file_magic *file_magic, struct file_header *file_hdr,
struct activity *act[], struct report_format *ofmt,
int endian_mismatch, int arch_64)
return 0;
/* The record must be in the interval specified by -s/-e options */
- if ((tm_start->use && (datecmp(rectime, tm_start, FALSE) < 0)) ||
- (tm_end->use && (datecmp(rectime, tm_end, FALSE) > 0))) {
+ if ((datecmp(rectime, tm_start, FALSE) < 0) ||
+ (datecmp(rectime, tm_end, FALSE) > 0)) {
/* Will not display the special record */
dp = 0;
}
else {
/* Set date and time strings to be displayed for current record */
- set_record_timestamp_string(l_flags, record_hdr,
- cur_date, cur_time, TIMESTAMP_LEN, rectime);
+ set_record_timestamp_string(l_flags, cur_date, cur_time, TIMESTAMP_LEN,
+ rectime);
}
if (rtype == R_RESTART) {
}
return pname;
}
+
+/*
+ * **************************************************************************
+ * Make a few checks on timestamps entered with options -s/-e.
+ *
+ * IN:
+ * @tm_start Timestamp entered with option -s.
+ * @tm_end Timestamp entered with option -e.
+ *
+ * RETURNS:
+ * 1 if an error has been detected.
+ ***************************************************************************
+ */
+int check_time_limits(struct tstamp_ext *tm_start, struct tstamp_ext *tm_end)
+{
+ if ((tm_start->use == USE_HHMMSS_T) && (tm_end->use == USE_HHMMSS_T) &&
+ (tm_end->tm_time.tm_hour < tm_start->tm_time.tm_hour)) {
+ tm_end->tm_time.tm_hour += 24;
+ }
+
+ if ((tm_start->use == USE_EPOCH_T) && (tm_end->use == USE_EPOCH_T) &&
+ (tm_end->epoch_time < tm_start->epoch_time))
+ return 1;
+
+ return 0;
+}
+
#endif /* SOURCE_SADC undefined */
struct record_header record_hdr[3];
/* Contain the date specified by -s and -e options */
-struct tstamp tm_start, tm_end;
+struct tstamp_ext tm_start, tm_end;
char *args[MAX_ARGV_NR];
/* Current timezone */
*/
int read_next_sample(int ifd, int action, int curr, char *file, int *rtype, int tab,
struct file_magic *file_magic, struct file_activity *file_actlst,
- struct tm *rectime, enum on_eof oneof)
+ struct tstamp_ext *rectime, enum on_eof oneof)
{
int rc;
char rec_hdr_tmp[MAX_RECORD_HEADER_SIZE];
***************************************************************************
*/
int count_file_items(int ifd, char *file, struct file_magic *file_magic,
- struct file_activity *file_actlst, struct tm *rectime)
+ struct file_activity *file_actlst, struct tstamp_ext *rectime)
{
int i, eosaf, rtype;
/* No record to display */
return 0;
}
- while ((tm_start.use && (datecmp(rectime, &tm_start, FALSE) < 0)) ||
- (tm_end.use && (datecmp(rectime, &tm_end, FALSE) >= 0)));
+ while ((datecmp(rectime, &tm_start, FALSE) < 0) ||
+ (datecmp(rectime, &tm_end, FALSE) > 0));
/*
* Read all the file and determine the maximum number
eosaf = read_next_sample(ifd, IGNORE_RESTART | IGNORE_COMMENT | SET_TIMESTAMPS,
0, file, &rtype, 0, file_magic, file_actlst,
rectime, UEOF_CONT);
- if (eosaf ||
- (tm_end.use && (datecmp(rectime, &tm_end, FALSE) >= 0)))
+ if (eosaf || (datecmp(rectime, &tm_end, FALSE) > 0))
/* End of data file or end time exceeded */
break;
}
while ((rtype == R_RESTART) || (rtype == R_COMMENT));
}
- while (!eosaf && !(tm_end.use && (datecmp(rectime, &tm_end, FALSE) >= 0)));
+ while (!eosaf && !(datecmp(rectime, &tm_end, FALSE) > 0));
/* Rewind file */
seek_file_position(ifd, DO_RESTORE);
***************************************************************************
*/
int get_svg_graph_nr(int ifd, char *file, struct file_magic *file_magic,
- struct file_activity *file_actlst, struct tm *rectime,
+ struct file_activity *file_actlst, struct tstamp_ext *rectime,
int *views_per_row, int *nr_act_dispd)
{
int i, n, p, tot_g_nr = 0;
*
* IN:
* @curr Index in array for current sample statistics.
- * @use_tm_start Set to TRUE if option -s has been used.
- * @use_tm_end Set to TRUE if option -e has been used.
+ * @use_tm_start Set to non-zero if option -s has been used.
+ * @use_tm_end Set to non-zero if option -e has been used.
* @reset Set to TRUE if last_uptime should be reinitialized
* (used in next_slice() function).
* @parm Pointer on parameters depending on output format
* 1 if stats have been successfully displayed.
***************************************************************************
*/
-int generic_write_stats(int curr, int use_tm_start, int use_tm_end, int reset,
- long *cnt, void *parm, struct tm *rectime,
+int generic_write_stats(int curr, enum time_mode use_tm_start, enum time_mode use_tm_end,
+ int reset, long *cnt, void *parm, struct tstamp_ext *rectime,
int reset_cd, unsigned int act_id)
{
int i;
}
/* Set date and time strings for current record */
- set_record_timestamp_string(flags, &record_hdr[curr],
- cur_date, cur_time, TIMESTAMP_LEN, rectime);
+ set_record_timestamp_string(flags, cur_date, cur_time, TIMESTAMP_LEN, rectime);
if (*fmt[f_position]->f_timestamp) {
pre = (char *) (*fmt[f_position]->f_timestamp)(parm, F_BEGIN, cur_date, cur_time,
*/
void rw_curr_act_stats(int ifd, int *curr, long *cnt, int *eosaf,
unsigned int act_id, int *reset, struct file_activity *file_actlst,
- struct tm *rectime, char *file,
+ struct tstamp_ext *rectime, char *file,
struct file_magic *file_magic)
{
int rtype;
*/
void display_curr_act_graphs(int ifd, int *curr, long *cnt, int *eosaf,
int p, int *reset, struct file_activity *file_actlst,
- struct tm *rectime, char *file, struct file_magic *file_magic,
- int *g_nr, int nr_act_dispd)
+ struct tstamp_ext *rectime, char *file,
+ struct file_magic *file_magic, int *g_nr, int nr_act_dispd)
{
struct svg_parm parm;
int rtype;
***************************************************************************
*/
void logic1_display_loop(int ifd, char *file, struct file_activity *file_actlst,
- struct file_magic *file_magic, struct tm *rectime, void *dparm)
+ struct file_magic *file_magic, struct tstamp_ext *rectime, void *dparm)
{
int curr, rtype, tab = 0;
int eosaf, next, reset = FALSE;
rectime, UEOF_STOP);
}
while (!eosaf && ((rtype == R_RESTART) || (rtype == R_COMMENT) ||
- (tm_start.use && (datecmp(rectime, &tm_start, FALSE) < 0)) ||
- (tm_end.use && (datecmp(rectime, &tm_end, FALSE) >= 0))));
+ (datecmp(rectime, &tm_start, FALSE) < 0) ||
+ (datecmp(rectime, &tm_end, FALSE) > 0)));
curr = 1;
cnt = count;
***************************************************************************
*/
void logic2_display_loop(int ifd, char *file, struct file_activity *file_actlst,
- struct file_magic *file_magic, struct tm *rectime, void *dparm)
+ struct file_magic *file_magic, struct tstamp_ext *rectime, void *dparm)
{
int i, p;
int curr = 1, rtype;
return;
}
while ((rtype == R_RESTART) || (rtype == R_COMMENT) ||
- (tm_start.use && (datecmp(rectime, &tm_start, FALSE) < 0)) ||
- (tm_end.use && (datecmp(rectime, &tm_end, FALSE) >= 0)));
+ (datecmp(rectime, &tm_start, FALSE) < 0) ||
+ (datecmp(rectime, &tm_end, FALSE) > 0));
/* Save the first stats collected. Used for example in next_slice() function */
copy_structures(act, id_seq, record_hdr, 2, 0);
***************************************************************************
*/
void svg_display_loop(int ifd, char *file, struct file_activity *file_actlst,
- struct file_magic *file_magic, struct tm *rectime, void *dparm)
+ struct file_magic *file_magic, struct tstamp_ext *rectime, void *dparm)
{
struct svg_hdr_parm parm;
int i, p;
}
}
while ((rtype == R_RESTART) || (rtype == R_COMMENT) ||
- (tm_start.use && (datecmp(rectime, &tm_start, FALSE) < 0)) ||
- (tm_end.use && (datecmp(rectime, &tm_end, FALSE) >= 0)));
+ (datecmp(rectime, &tm_start, FALSE) < 0) ||
+ (datecmp(rectime, &tm_end, FALSE) > 0));
/* Save the first stats collected. Used for example in next_slice() function */
copy_structures(act, id_seq, record_hdr, 2, 0);
{
struct file_magic file_magic;
struct file_activity *file_actlst = NULL;
- struct tm rectime;
+ struct tstamp_ext rectime;
int ifd, tab = 0;
/* Prepare file for reading and read its headers */
init_nls();
#endif
- tm_start.use = tm_end.use = FALSE;
+ tm_start.use = tm_end.use = NO_TIME;
/* Allocate and init activity bitmaps */
allocate_bitmaps(act);
}
#endif
- if (tm_start.use && tm_end.use && (tm_end.tm_hour < tm_start.tm_hour)) {
- tm_end.tm_hour += 24;
+ if (check_time_limits(&tm_start, &tm_end)) {
+ usage(argv[0]);
}
if (DISPLAY_PRETTY(flags)) {
*/
void logic1_display_loop
(int, char *, struct file_activity *, struct file_magic *,
- struct tm *, void *);
+ struct tstamp_ext *, void *);
void logic2_display_loop
(int, char *, struct file_activity *, struct file_magic *,
- struct tm *, void *);
+ struct tstamp_ext *, void *);
void svg_display_loop
(int, char *, struct file_activity *, struct file_magic *,
- struct tm *, void *);
+ struct tstamp_ext *, void *);
#endif /* _SADF_H */
*/
unsigned int id_seq[NR_ACT];
-struct tm rectime;
+struct tstamp_ext rectime;
/* Contain the date specified by -s and -e options */
-struct tstamp tm_start, tm_end;
+struct tstamp_ext tm_start, tm_end;
char *args[MAX_ARGV_NR];
* @curr Index in array for current sample statistics.
* @read_from_file Set to TRUE if stats are read from a system activity
* data file.
- * @use_tm_start Set to TRUE if option -s has been used.
- * @use_tm_end Set to TRUE if option -e has been used.
+ * @use_tm_start Set to non-zero (USE_HHMMSS_T or USE_EPOCH_T) if
+ * option -s has been used.
+ * @use_tm_end Set to non-zero (USE_HHMMSS_T or USE_EPOCH_T) if
+ * option -e has been used.
* @reset Set to TRUE if last_uptime variable should be
* reinitialized (used in next_slice() function).
* @act_id Activity that can be displayed or ~0 for all.
* 1 if stats have been successfully displayed, and 0 otherwise.
***************************************************************************
*/
-int write_stats(int curr, int read_from_file, long *cnt, int use_tm_start,
- int use_tm_end, int reset, unsigned int act_id, int reset_cd)
+int write_stats(int curr, int read_from_file, long *cnt, enum time_mode use_tm_start,
+ enum time_mode use_tm_end, int reset, unsigned int act_id, int reset_cd)
{
int i, prev_hour, rc = 0;
unsigned long long itv;
/* Get then set previous timestamp */
if (sa_get_record_timestamp_struct(flags, &record_hdr[!curr], &rectime))
return 0;
- prev_hour = rectime.tm_hour;
- set_record_timestamp_string(flags, &record_hdr[!curr],
- NULL, timestamp[!curr], TIMESTAMP_LEN, &rectime);
+ prev_hour = rectime.tm_time.tm_hour;
+ set_record_timestamp_string(flags, NULL, timestamp[!curr], TIMESTAMP_LEN, &rectime);
/* Get then set current timestamp */
if (sa_get_record_timestamp_struct(flags, &record_hdr[curr], &rectime))
return 0;
- set_record_timestamp_string(flags, &record_hdr[curr],
- NULL, timestamp[curr], TIMESTAMP_LEN, &rectime);
+ set_record_timestamp_string(flags, NULL, timestamp[curr], TIMESTAMP_LEN, &rectime);
/*
* Check if we are beginning a new day.
* to take into account the current timezone (hours displayed will depend on the
* TZ variable value).
*/
- if (use_tm_start && record_hdr[!curr].ust_time &&
+ if ((use_tm_start == USE_HHMMSS_T) && record_hdr[!curr].ust_time &&
(record_hdr[curr].ust_time > record_hdr[!curr].ust_time) &&
- (rectime.tm_hour < prev_hour)) {
+ (rectime.tm_time.tm_hour < prev_hour)) {
cross_day = TRUE;
}
/* Check time (2) */
- if (use_tm_end && (datecmp(&rectime, &tm_end, cross_day) > 0)) {
+ if ((use_tm_end != NO_TIME) && datecmp(&rectime, &tm_end, cross_day) > 0) {
/* End time exceeded */
*cnt = 0;
return 0;
flags |= S_F_SINCE_BOOT;
dish = TRUE;
- write_stats(curr, USE_SADC, &count, NO_TM_START, NO_TM_END, NO_RESET,
+ write_stats(curr, USE_SADC, &count, NO_TIME, NO_TIME, NO_RESET,
ALL_ACTIVITIES, TRUE);
exit(0);
allocate_structures(act);
/* Print report header */
- print_report_hdr(flags, &rectime, &file_hdr);
+ print_report_hdr(flags, &(rectime.tm_time), &file_hdr);
/* Read system statistics from file */
do {
}
}
while ((rtype == R_RESTART) || (rtype == R_COMMENT) ||
- (tm_start.use && (datecmp(&rectime, &tm_start, FALSE) < 0)) ||
- (tm_end.use && (datecmp(&rectime, &tm_end, FALSE) >= 0)));
+ (datecmp(&rectime, &tm_start, FALSE) < 0) ||
+ (datecmp(&rectime, &tm_end, FALSE) > 0));
/* Save the first stats collected. Will be used to compute the average */
copy_structures(act, id_seq, record_hdr, 2, 0);
allocate_structures(act);
/* Print report header */
- print_report_hdr(flags, &rectime, &file_hdr);
+ print_report_hdr(flags, &(rectime.tm_time), &file_hdr);
/* Read system statistics sent by the data collector */
read_sadc_stat_bunch(0);
}
lines++;
}
- write_stats(curr, USE_SADC, &count, NO_TM_START, tm_end.use,
+ write_stats(curr, USE_SADC, &count, NO_TIME, tm_end.use,
NO_RESET, ALL_ACTIVITIES, TRUE);
+ if ((tm_end.use != NO_TIME) && (datecmp(&rectime, &tm_end, FALSE) == 0)) {
+ /*
+ * The last record displayed has reached ending time.
+ * Set @count to 0 to keep sadc from saving an additional
+ * record on next loop and stop now.
+ * This is not perfect anyway: If the last displayed record hasn't
+ * reached ending time, but the next one exceeds it, it will not be
+ * displayed but will still have been saved in datafile by sadc since
+ * the test is made later at display time.
+ */
+ count = 0;
+ }
+
if (record_hdr[curr].record_type == R_LAST_STATS) {
/* File rotation is happening: Re-read header data sent by sadc */
read_header_data();
init_nls();
#endif
- tm_start.use = tm_end.use = FALSE;
+ tm_start.use = tm_end.use = NO_TIME;
/* Allocate and init activity bitmaps */
allocate_bitmaps(act);
set_default_file(from_file, day_offset, -1);
}
- if (tm_start.use && tm_end.use && (tm_end.tm_hour < tm_start.tm_hour)) {
- tm_end.tm_hour += 24;
+ if (check_time_limits(&tm_start, &tm_end)) {
+ usage(argv[0]);
}
/*
set_bitmaps(act, &flags);
}
/* Use time start or option -i only when reading stats from a file */
- if ((tm_start.use || INTERVAL_SET(flags)) && !from_file[0]) {
+ if (((tm_start.use != NO_TIME) || INTERVAL_SET(flags)) && !from_file[0]) {
fprintf(stderr,
_("Not reading from a system activity file (use -f option)\n"));
exit(1);
void display_vgrid(long int xpos, double xfactor, int v_gridnr, struct svg_parm *svg_p)
{
struct record_header stamp;
- struct tm rectime;
+ struct tstamp_ext rectime;
char cur_time[TIMESTAMP_LEN];
int j;
#endif
exit(1);
}
- set_record_timestamp_string(flags, &stamp, NULL, cur_time, TIMESTAMP_LEN, &rectime);
+ set_record_timestamp_string(flags, NULL, cur_time, TIMESTAMP_LEN, &rectime);
printf("<polyline points=\"%ld,0 %ld,%d\" style=\"vector-effect: non-scaling-stroke; "
"stroke: #%06x\" transform=\"scale(%f,1)\"/>\n",
xpos * j, xpos * j, -SVG_G_YSIZE,
* NB: We may have tm_min != 0 if we have more than 24H worth of data in one datafile.
* In this case, we should rather display the exact time instead of only the hour.
*/
- if (DISPLAY_ONE_DAY(flags) && (rectime.tm_min == 0)) {
+ if (DISPLAY_ONE_DAY(flags) && (rectime.tm_time.tm_min == 0)) {
printf("<text x=\"%ld\" y=\"15\" style=\"fill: #%06x; stroke: none; font-size: 14px; "
"text-anchor: start\">%2d:00</text>\n",
(long) (xpos * j * xfactor) - 15,
svg_colors[palette][SVG_COL_AXIS_IDX],
- rectime.tm_hour);
+ rectime.tm_time.tm_hour);
}
else {
printf("<text x=\"%ld\" y=\"10\" style=\"fill: #%06x; stroke: none; font-size: 12px; "