// ----------------------------------------------------------------------
// File: proc/user/Who.cc
// Author: Andreas-Joachim Peters - CERN
// ----------------------------------------------------------------------
/******************A******************************************************
* EOS - the CERN Disk Storage System *
* Copyright (C) 2011 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/proc/ProcInterface.hh"
#include "mgm/XrdMgmOfs.hh"
#include "mgm/Stat.hh"
#include
#include "common/Mapping.hh"
EOSMGMNAMESPACE_BEGIN
int
ProcCommand::Who()
{
gOFS->MgmStats.Add("Who", pVid->uid, pVid->gid, 1);
std::map usernamecount;
std::map authcount;
std::vector tokens;
std::unordered_map active_tidents;
std::string delimiter = "^";
std::string option;
bool json_format = false;
bool monitoring = false;
bool showclients = false;
bool showall = false;
bool showauth = false;
bool showsummary = false;
bool numericids = false;
Json::Value json;
if (pOpaque->Get("mgm.option")) {
option = pOpaque->Get("mgm.option");
}
if (pOpaque->Get("mgm.format")) {
std::string format = pOpaque->Get("mgm.format");
json_format = (format == "json");
}
if ((option.find("m")) != std::string::npos) {
monitoring = true;
}
if ((option.find("c")) != std::string::npos) {
showclients = true;
}
if ((option.find("z")) != std::string::npos) {
showauth = true;
}
if ((option.find("a")) != std::string::npos) {
showall = true;
}
if ((option.find("s")) != std::string::npos) {
showsummary = true;
}
if ((option.find("n")) != std::string::npos) {
numericids = true;
}
for (size_t i = 0; i < eos::common::Mapping::ActiveTidentsSharded.num_shards();
++i) {
for (auto&& it: eos::common::Mapping::ActiveTidentsSharded.get_shard(i)) {
std::string username = "";
tokens.clear();
eos::common::StringConversion::Tokenize(it.first, tokens, delimiter);
uid_t uid = atoi(tokens[0].c_str());
int terrc = 0;
if (numericids) {
username = std::to_string(uid);
} else {
username = eos::common::Mapping::UidToUserName(uid, terrc);
}
usernamecount[username]++;
authcount[tokens[2]]++;
active_tidents.emplace(std::move(it.first), std::move(it.second));
}
}
if (showauth || showall) {
std::map::const_iterator it;
for (it = authcount.begin(); it != authcount.end(); it++) {
char formatline[1024];
if (monitoring) {
snprintf(formatline, sizeof(formatline) - 1, "auth=%s nsessions=%d\n",
it->first.c_str(), it->second);
stdOut += formatline;
} else if (json_format) {
Json::Value json_auth;
json_auth["auth"] = it->first;
json_auth["nsessions"] = it->second;
json.append(json_auth);
} else {
snprintf(formatline, sizeof(formatline) - 1, "auth : %-24s := %d sessions\n",
it->first.c_str(), it->second);
stdOut += formatline;
}
}
}
if (!showclients || showall) {
std::map::const_iterator ituname;
std::map::const_iterator ituid;
for (ituname = usernamecount.begin(); ituname != usernamecount.end();
ituname++) {
char formatline[1024];
if (monitoring) {
snprintf(formatline, sizeof(formatline) - 1, "uid=%s nsessions=%d\n",
ituname->first.c_str(), ituname->second);
stdOut += formatline;
} else if (json_format) {
Json::Value json_user;
json_user["uid"] = ituname->first;
json_user["nsessions"] = ituname->second;
json.append(json_user);
} else {
snprintf(formatline, sizeof(formatline) - 1, "user : %-24s := %d sessions\n",
ituname->first.c_str(), ituname->second);
stdOut += formatline;
}
}
}
unsigned long long cnt = 0;
if (showclients || showall || showsummary) {
for (const auto& it : active_tidents) {
cnt++;
std::string username = "";
tokens.clear();
// std::string intoken = it->first.c_str();
eos::common::StringConversion::Tokenize(it.first, tokens, delimiter);
uid_t uid = atoi(tokens[0].c_str());
int terrc = 0;
if (numericids) {
username = std::to_string(uid);
} else {
username = eos::common::Mapping::UidToUserName(uid, terrc);
}
char formatline[1024];
time_t now = time(NULL);
if (monitoring) {
snprintf(formatline, sizeof(formatline) - 1,
"client=%s uid=%s auth=%s idle=%ld gateway=\"%s\" app=%s\n",
tokens[1].c_str(), username.c_str(), tokens[2].c_str(),
now - it.second, tokens[3].c_str(),
(tokens.size() > 4) ? tokens[4].c_str() : "XRoot");
stdOut += formatline;
} else if (json_format) {
if (!showsummary) {
Json::Value json_client;
json_client["client"] = tokens[1];
json_client["uid"] = username;
json_client["auth"] = tokens[2];
json_client["idle"] = (Json::UInt64)(now - it.second);
json_client["gateway"] = tokens[3];
json_client["app"] =
(tokens.size() > 4) ? tokens[4].c_str() : "XRoot";
json.append(json_client);
}
} else {
snprintf(formatline, sizeof(formatline) - 1,
"client : %-10s := %-40s (%5s) [ %-40s ] { %-8s } %lds idle time \n",
username.c_str(), tokens[1].c_str(), tokens[2].c_str(),
tokens[3].c_str(),
((tokens.size() > 4) && tokens[4].length())
? tokens[4].c_str()
: "XRoot",
now - it.second);
if (!showsummary) {
stdOut += formatline;
}
}
}
}
if (showsummary) {
char formatline[1024];
if (monitoring) {
snprintf(formatline, sizeof(formatline) - 1, "nclients=%llu\n", cnt);
stdOut += formatline;
} else if (json_format) {
Json::Value json_count;
json_count["nclients"] = Json::UInt64(cnt);
json.append(json_count);
} else {
snprintf(formatline, sizeof(formatline) - 1, "sum(clients) : %llu\n", cnt);
stdOut += formatline;
}
}
if (json_format) {
stdOut = "";
Json::StreamWriterBuilder builder;
std::unique_ptr jsonwriter(
builder.newStreamWriter());
std::stringstream ss;
jsonwriter->write(json, &ss);
stdJson += ss.str().c_str();
}
return SFS_OK;
}
EOSMGMNAMESPACE_END