// ----------------------------------------------------------------------
// File: AsyncUint64ShellCmd.cc
// Author: Steven Murray - CERN
// ----------------------------------------------------------------------
/************************************************************************
* 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/tgc/AsyncUint64ShellCmd.hh"
#include "mgm/tgc/SmartSpaceStats.hh"
#include "mgm/CtaUtils.hh"
#include
#include
EOSTGCNAMESPACE_BEGIN
//----------------------------------------------------------------------------
// Constructor
AsyncUint64ShellCmd::AsyncUint64ShellCmd(ITapeGcMgm& mgm):
m_mgm(mgm)
{
}
//----------------------------------------------------------------------------
//! Return the current result of the shell command
//----------------------------------------------------------------------------
AsyncUint64ShellCmd::Uint64AsyncResult
AsyncUint64ShellCmd::getUint64FromShellCmdStdOut(const std::string& cmdStr)
{
try {
std::lock_guard lock(m_mutex);
// Invalid means this is either the very first call to get() or it is
// after the successful reading of a previous async result
if (!m_future.valid()) {
m_future = std::async(std::launch::async,
&AsyncUint64ShellCmd::runShellCmdAndParseStdOut, this, cmdStr);
}
if (!m_future.valid()) {
throw std::runtime_error("Failed to create a valid std::future");
}
const auto futureStatus = m_future.wait_for(std::chrono::seconds(0));
switch (futureStatus) {
case std::future_status::deferred: { // Should never happen
throw std::runtime_error("futureStatus is deferred");
}
case std::future_status::ready: {
const std::uint64_t uint64Result = m_future.get();
const auto result = Uint64AsyncResult::createValue(uint64Result);
m_previousResult = uint64Result;
m_future = {};
return result;
}
case std::future_status::timeout: {
const auto result = m_previousResult ?
Uint64AsyncResult::createPendingAndPreviousValue(m_previousResult.value()) :
Uint64AsyncResult::createPendingAndNoPreviousValue();
return result;
}
default: // Should never happen
throw std::runtime_error("Unknown std::future_status value");
}
} catch (std::exception& ex) {
m_previousResult = std::nullopt;
return Uint64AsyncResult::createError(ex.what());
} catch (...) {
m_previousResult = std::nullopt;
return Uint64AsyncResult::createError("Caught an unknown exception");
}
}
//------------------------------------------------------------------------------
//! Run the specified shell command and parse its standard out as a uint64
//! @param cmdStr The shell command string to be executed
//------------------------------------------------------------------------------
std::uint64_t
AsyncUint64ShellCmd::runShellCmdAndParseStdOut(const std::string cmdStr)
{
const ssize_t outputMaxLen = 256;
const std::string cmdOut = m_mgm.getStdoutFromShellCmd(cmdStr, outputMaxLen);
return CtaUtils::toUint64(cmdOut);
}
EOSTGCNAMESPACE_END