// ----------------------------------------------------------------------
// File: InFlightTracker.cc
// Author: Andreas-Joachim Peters - CERN
// ----------------------------------------------------------------------
/************************************************************************
* EOS - the CERN Disk Storage System *
* Copyright (C) 2021 CERN/Switzerland *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see .*
************************************************************************/
/*----------------------------------------------------------------------------*/
#include "mgm/InFlightTracker.hh"
#include "mgm/Access.hh"
#include "common/utils/RandUtils.hh"
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
EOSMGMNAMESPACE_BEGIN
std::string
InFlightTracker::PrintOut(bool monitoring)
{
std::string format_l = !monitoring ? "+l" : "ol";
std::string format_s = !monitoring ? "s" : "os";
TableFormatterBase table_all;
if (!monitoring) {
table_all.SetHeader({
std::make_tuple("uid", 8, format_s),
std::make_tuple("threads", 5, format_l),
std::make_tuple("sessions", 5, format_l),
std::make_tuple("limit", 5, format_l),
std::make_tuple("stalls", 5, format_l),
std::make_tuple("stalltime", 5, format_l),
std::make_tuple("status", 16, format_s)
});
} else {
table_all.SetHeader({
std::make_tuple("uid", 0, format_s),
std::make_tuple("threads", 0, format_l),
std::make_tuple("sessions", 0, format_l),
std::make_tuple("limit", 0, format_l),
std::make_tuple("stalls", 0, format_l),
std::make_tuple("stalltime", 00, format_l),
std::make_tuple("status", 0, format_s)
});
}
std::map vids = getInFlightUids();
for (auto it : vids) {
TableData table_data;
size_t limit = Access::ThreadLimit(it.first);
size_t global_limit = Access::ThreadLimit();
table_data.emplace_back();
table_data.back().push_back(TableCell(std::to_string((long long)it.first),
format_l));
table_data.back().push_back(TableCell((long long)it.second, format_l));
table_data.back().push_back(TableCell((long long)
eos::common::Mapping::ActiveSessions(it.first), format_l));
table_data.back().push_back(TableCell((long long)limit, format_l));
table_data.back().push_back(TableCell((long long)getStalls(it.first),
format_l));
table_data.back().push_back(TableCell((long long)getStallTime(it.first, limit),
format_l));
if (GetInFlight() > (int64_t) global_limit) {
table_data.back().push_back(TableCell("pool-OL", format_s));
} else if (it.second >= limit) {
table_data.back().push_back(TableCell("user-OL", format_s));
} else {
if (it.second >= (0.9 * limit)) {
table_data.back().push_back(TableCell("user-LIMIT", format_s));
} else {
table_data.back().push_back(TableCell("user-OK", format_s));
}
}
table_all.AddRows(table_data);
}
return table_all.GenerateTable(HEADER);
}
size_t
InFlightTracker::getStallTime(uid_t uid, size_t& limit)
{
size_t sessions = (uid == 0) ? eos::common::Mapping::ActiveSessions() :
eos::common::Mapping::ActiveSessions(uid);
size_t stalltime = limit ? ((size_t)(2.0 * sessions / limit)) : 0;
if (stalltime > 60) {
stalltime = 60;
} else if (stalltime < 1) {
stalltime = 1;
}
size_t random_stall = common::getRandom((size_t)1, stalltime);
stalltime /= 2;
stalltime += random_stall;
return stalltime;
}
size_t
InFlightTracker::ShouldStall(uid_t uid, bool& saturated, size_t& threads_used)
{
size_t limit = Access::ThreadLimit(uid, false);
size_t global_limit = Access::ThreadLimit(false);
//size_t global_sessions = eos::common::Mapping::ActiveSessions();
saturated = false;
threads_used = limit;
// user limit
if (limit > 1) {
if (getInFlight(uid) > limit) {
if (GetInFlight() > (int64_t) global_limit) {
saturated = true;
}
incStalls(uid);
// estimate a stall time
return getStallTime(uid, limit);
}
}
// global limit
if (GetInFlight() > (int64_t) global_limit) {
saturated = true;
incStalls(uid);
return getStallTime(0, global_limit);
}
return 0;
}
EOSMGMNAMESPACE_END