mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
This commit is based on the s390-tools-1.39.0 version. Changes on top of s390-tools-1.39.0: - Add MIT license to all source files - Add LICENSE file - Transform REAMDE to README.md (markdown) - Add AUTHORS.md file - Add CONTRIBUTING.md file - Move changelog from README to CHANGELOG.md file Reviewed-by: Stefan Haberland <sth@linux.vnet.ibm.com> Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
288 lines
7.6 KiB
C++
288 lines
7.6 KiB
C++
/*
|
|
* FCP report generators
|
|
*
|
|
* Class for reading messages into frames.
|
|
*
|
|
* Copyright IBM Corp. 2008, 2017
|
|
*
|
|
* s390-tools is free software; you can redistribute it and/or modify
|
|
* it under the terms of the MIT license. See LICENSE for details.
|
|
*/
|
|
|
|
#include <assert.h>
|
|
#include <unistd.h>
|
|
#define __STDC_LIMIT_MACROS
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "ziorep_framer.hpp"
|
|
#include "ziorep_utils.hpp"
|
|
|
|
extern "C" {
|
|
#include "ziomon_msg_tools.h"
|
|
}
|
|
|
|
extern const char *toolname;
|
|
extern int verbose;
|
|
|
|
|
|
Framer::Framer(__u64 begin, __u64 end, __u32 interval_length,
|
|
list<MsgTypes> *filter_types, DeviceFilter *devFilter,
|
|
const char *filename, int *rc)
|
|
: m_interval_length(interval_length), m_type_filter(NULL),
|
|
m_device_filter(devFilter), m_filename(filename), m_fp(NULL),
|
|
m_agg_read(false)
|
|
{
|
|
m_begin = begin;
|
|
m_end = end;
|
|
assert(m_begin <= m_end);
|
|
|
|
// set up .log file on first time
|
|
if (open_data_files(&m_fp, m_filename, &m_fhdr, &m_agg_data)) {
|
|
*rc = -2;
|
|
return;
|
|
}
|
|
if (m_agg_data)
|
|
conv_aggr_data_msg_data_from_BE(m_agg_data);
|
|
|
|
if (filter_types) {
|
|
m_type_filter = new MsgTypeFilter;
|
|
for (list<MsgTypes>::const_iterator i = filter_types->begin();
|
|
i != filter_types->end(); ++i) {
|
|
switch (*i) {
|
|
case utilization:
|
|
m_type_filter->add_type(m_fhdr.msgid_utilization);
|
|
break;
|
|
case ioerr:
|
|
m_type_filter->add_type(m_fhdr.msgid_ioerr);
|
|
break;
|
|
case blkiomon:
|
|
m_type_filter->add_type(m_fhdr.msgid_blkiomon);
|
|
break;
|
|
case zfcpdd:
|
|
m_type_filter->add_type(m_fhdr.msgid_zfcpdd);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
*rc = 0;
|
|
}
|
|
|
|
Framer::~Framer()
|
|
{
|
|
close_data_files(m_fp);
|
|
|
|
if (m_type_filter)
|
|
delete m_type_filter;
|
|
|
|
if (m_agg_data) {
|
|
discard_aggr_data_struct(m_agg_data);
|
|
free(m_agg_data);
|
|
}
|
|
}
|
|
|
|
bool Framer::handle_agg_data(Frameset &frameset) const
|
|
{
|
|
// Initial test - if we pass, we still have to check
|
|
// the messages individually later on!
|
|
if (m_begin > m_agg_data->end_time || m_end < m_agg_data->begin_time)
|
|
return false;
|
|
|
|
/* collate all messages */
|
|
list<struct message *> agg_msgs;
|
|
if (m_agg_data->util_aggr)
|
|
agg_msgs.insert(agg_msgs.end(), m_agg_data->util_aggr);
|
|
if (m_agg_data->ioerr_aggr)
|
|
agg_msgs.insert(agg_msgs.end(), m_agg_data->ioerr_aggr);
|
|
for (unsigned int i = 0; i<m_agg_data->num_blkiomon; ++i)
|
|
agg_msgs.insert(agg_msgs.end(), m_agg_data->blkio_aggr[i]);
|
|
for (unsigned int i = 0; i<m_agg_data->num_zfcpdd; ++i)
|
|
agg_msgs.insert(agg_msgs.end(), m_agg_data->zfcpdd_aggr[i]);
|
|
|
|
/* loop over collated msgs */
|
|
for (list<struct message*>::iterator i=agg_msgs.begin();
|
|
i != agg_msgs.end(); ++i) {
|
|
// we do an all-or-nothing approach - anything else would be
|
|
// too confusing
|
|
/*
|
|
__u64 t = get_timestamp_from_msg(*i);
|
|
if (m_begin > t || m_end < t) {
|
|
vverbose_msg("message not in timeframe\n");
|
|
continue;
|
|
} */
|
|
if (m_type_filter && !m_type_filter->is_eligible(*i)) {
|
|
vverbose_msg("message type not eligible\n");
|
|
continue;
|
|
}
|
|
vverbose_msg("adding msg\n");
|
|
handle_msg(*i, frameset);
|
|
}
|
|
verbose_msg(" found eligible data in aggregated messages: %d\n",
|
|
frameset.is_aggregated());
|
|
|
|
return (!frameset.is_empty());
|
|
}
|
|
|
|
void Framer::handle_msg(struct message *msg, Frameset &frameset) const
|
|
{
|
|
if (msg->type == m_fhdr.msgid_utilization) {
|
|
struct utilization_data *res = (struct utilization_data*)msg->data;
|
|
struct adapter_utilization *a_res;
|
|
for (int i = 0; i < res->num_adapters; ++i) {
|
|
a_res = &res->adapt_utils[i];
|
|
if (m_device_filter && !m_device_filter->is_eligible(a_res)) {
|
|
vverbose_msg("message not for eligible device\n");
|
|
continue;
|
|
}
|
|
vverbose_msg("adding utilization msg\n");
|
|
frameset.add_data(a_res);
|
|
}
|
|
}
|
|
else if (msg->type == m_fhdr.msgid_ioerr) {
|
|
struct ioerr_data *data = (struct ioerr_data*)msg->data;
|
|
struct ioerr_cnt *cnt;
|
|
for (unsigned int i = 0; i < data->num_luns; ++i) {
|
|
cnt = &data->ioerrors[i];
|
|
if (m_device_filter && !m_device_filter->is_eligible(cnt)) {
|
|
vverbose_msg("message not for eligible device\n");
|
|
continue;
|
|
}
|
|
vverbose_msg("adding ioerr msg\n");
|
|
frameset.add_data(cnt);
|
|
}
|
|
}
|
|
else {
|
|
if (m_device_filter && !m_device_filter->is_eligible(msg, &m_fhdr)) {
|
|
vverbose_msg("message not for eligible device\n");
|
|
return;
|
|
}
|
|
if (msg->type == m_fhdr.msgid_blkiomon) {
|
|
vverbose_msg("adding blkiomon msg\n");
|
|
frameset.add_data((struct blkiomon_stat*)msg->data);
|
|
}
|
|
else {
|
|
assert(msg->type == m_fhdr.msgid_zfcpdd);
|
|
vverbose_msg("adding zfcpdd msg\n");
|
|
frameset.add_data((struct zfcpdd_dstat*)msg->data);
|
|
}
|
|
}
|
|
}
|
|
|
|
int Framer::get_next_frameset(Frameset &frameset, bool replace_missing)
|
|
{
|
|
int rc = 0;
|
|
int msgs_read = 0;
|
|
__u64 shifted_begin;
|
|
__u64 shifted_end;
|
|
__u64 frame_begin = 0;
|
|
|
|
frameset.reinit();
|
|
|
|
if (m_begin > m_end)
|
|
return 1;
|
|
|
|
if (verbose >= 2) {
|
|
#ifndef NDEBUG
|
|
time_t t = m_begin;
|
|
#endif
|
|
vverbose_msg("retrieving next frameset for: %s", ctime(&t));
|
|
}
|
|
|
|
// did we check out .agg yet?
|
|
if (!m_agg_read) {
|
|
m_agg_read = true;
|
|
if (m_agg_data) {
|
|
verbose_msg(" found aggregated data, check if eligible\n");
|
|
handle_agg_data(frameset);
|
|
if (!frameset.is_empty()) {
|
|
if (m_interval_length != 0) {
|
|
verbose_msg(".agg data processed, wrap up frame\n");
|
|
frameset.set_aggregated(true);
|
|
frameset.set_timeframe(
|
|
m_agg_data->begin_time
|
|
- m_fhdr.interval_length / 2,
|
|
m_agg_data->end_time
|
|
+ m_fhdr.interval_length / 2,
|
|
m_agg_data->end_time);
|
|
// just bump it to the next frame
|
|
m_begin += m_fhdr.interval_length;
|
|
if (replace_missing)
|
|
frameset.replace_missing_datasets(m_fhdr.interval_length);
|
|
|
|
return 0;
|
|
}
|
|
verbose_msg(".agg data processed, add all of the rest to it\n");
|
|
frame_begin = m_agg_data->begin_time - m_fhdr.interval_length / 2;
|
|
}
|
|
}
|
|
else
|
|
verbose_msg(" no aggregated data found\n");
|
|
}
|
|
|
|
// down to real business
|
|
struct message msg;
|
|
struct message_preview msg_preview;
|
|
|
|
shifted_begin = m_begin - m_fhdr.interval_length / 2;
|
|
shifted_end = shifted_begin + m_interval_length;
|
|
if (m_interval_length == 0 || shifted_end > m_end)
|
|
shifted_end = m_end + m_fhdr.interval_length / 2;
|
|
MsgTimeFilter timeFilter(shifted_begin, shifted_end);
|
|
|
|
if (frame_begin == 0)
|
|
frame_begin = timeFilter.get_begin_time();
|
|
|
|
while( (rc = get_next_msg_preview(m_fp, &msg_preview, &m_fhdr)) == 0 ) {
|
|
vverbose_msg("checking out next msg\n");
|
|
++msgs_read;
|
|
if (msg_preview.timestamp > timeFilter.get_end_time()) {
|
|
vverbose_msg("timeframe exceeded\n");
|
|
rewind_to(m_fp, &msg_preview);
|
|
break;
|
|
}
|
|
// is this necessary at all?!?
|
|
if (!timeFilter.is_eligible(&msg_preview))
|
|
continue;
|
|
vverbose_msg("timestamp: OK\n");
|
|
if (m_type_filter && !m_type_filter->is_eligible(&msg_preview)) {
|
|
vverbose_msg("wrong type (%u)\n", msg_preview.type);
|
|
continue;
|
|
}
|
|
vverbose_msg("type : OK\n");
|
|
if (get_complete_msg(m_fp, &msg_preview, &msg) < 0) {
|
|
fprintf(stderr, "%s: Error retrieving next message, aborting"
|
|
" - file corrupt?\n", toolname);
|
|
return -5;
|
|
}
|
|
conv_msg_data_from_BE(&msg, &m_fhdr);
|
|
handle_msg(&msg, frameset);
|
|
discard_msg(&msg);
|
|
}
|
|
|
|
if (rc < 0) {
|
|
fprintf(stderr, "%s: Error retrieving next message, aborting"
|
|
" - file corrupt?\n", toolname);
|
|
return -4;
|
|
}
|
|
|
|
/* if we read some messages, though not the right ones,
|
|
we pass on an empty frame still. Will indicate EOF next time */
|
|
if (rc > 0 && msgs_read)
|
|
rc = 0;
|
|
|
|
if (rc == 0) {
|
|
frameset.set_timeframe(frame_begin, timeFilter.get_end_time(),
|
|
timeFilter.get_end_time() - m_fhdr.interval_length / 2);
|
|
if (m_interval_length == 0)
|
|
m_begin = m_end + 1; // we're done
|
|
else
|
|
m_begin += m_interval_length;
|
|
if (replace_missing)
|
|
frameset.replace_missing_datasets(m_fhdr.interval_length);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|