blob: 1fd50986628281e28cc4cd30130cebfa3bc8e4a7 [file] [log] [blame]
/** @file
A brief file description
@section license License
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*****************************************************************************
*
* HostStatus.h - Interface to Host Status System
*
*
****************************************************************************/
#pragma once
#include <ctime>
#include <string>
#include <sstream>
#include "tscore/ink_rwlock.h"
#include "records/I_RecProcess.h"
#include <unordered_map>
// host_status stats prefix.
static const std::string stat_prefix = "proxy.process.host_status.";
static const constexpr char *HostStatusNames[3] = {"HOST_STATUS_INIT", "HOST_STATUS_DOWN", "HOST_STATUS_UP"};
static const constexpr char *ReasonStatus[2] = {"UP", "DOWN"};
struct Reason {
static constexpr const unsigned int ACTIVE = 0x1;
static constexpr const unsigned int LOCAL = 0x2;
static constexpr const unsigned int MANUAL = 0x4;
static constexpr const unsigned int SELF_DETECT = 0x8;
static constexpr const unsigned int ALL = 0xf;
static constexpr const char *ACTIVE_REASON = "active";
static constexpr const char *LOCAL_REASON = "local";
static constexpr const char *MANUAL_REASON = "manual";
static constexpr const char *SELF_DETECT_REASON = "self_detect";
static constexpr const char *ALL_REASON = "all";
static constexpr const char *reasons[3] = {ACTIVE_REASON, LOCAL_REASON, MANUAL_REASON};
static bool
validReason(const char *reason)
{
for (const char *i : reasons) {
if (strcmp(i, reason) == 0) {
return true;
}
}
return false;
}
static unsigned int
getReason(const char *reason_str)
{
if (strcmp(reason_str, ACTIVE_REASON) == 0) {
return ACTIVE;
} else if (strcmp(reason_str, LOCAL_REASON) == 0) {
return LOCAL;
} else if (strcmp(reason_str, MANUAL_REASON) == 0) {
return MANUAL;
} else if (strcmp(reason_str, SELF_DETECT_REASON) == 0) {
return SELF_DETECT;
} else if (strcmp(reason_str, ALL_REASON) == 0) {
return ALL;
}
// default is MANUAL
return MANUAL;
}
};
// host status POD
struct HostStatRec {
TSHostStatus status;
unsigned int reasons;
// time the host was marked down for a given reason.
time_t active_marked_down;
time_t local_marked_down;
time_t manual_marked_down;
time_t self_detect_marked_down;
// number of seconds that the host should be marked down for a given reason.
unsigned int active_down_time;
unsigned int local_down_time;
unsigned int manual_down_time;
HostStatRec();
HostStatRec(std::string str);
HostStatRec(const HostStatRec &src)
{
status = src.status;
reasons = src.reasons;
active_marked_down = src.active_marked_down;
active_down_time = src.active_down_time;
local_marked_down = src.local_marked_down;
local_down_time = src.local_down_time;
manual_marked_down = src.manual_marked_down;
manual_down_time = src.manual_down_time;
self_detect_marked_down = src.self_detect_marked_down;
}
~HostStatRec() {}
HostStatRec &operator=(const HostStatRec &source) = default;
// serialize this HostStatusRec
std::stringstream &
operator<<(std::stringstream &os)
{
unsigned int r = getReasonState(Reason::ACTIVE);
os << HostStatusNames[status];
os << ",ACTIVE:" << ReasonStatus[r] << ":" << active_marked_down << ":" << active_down_time;
r = getReasonState(Reason::LOCAL);
os << ",LOCAL:" << ReasonStatus[r] << ":" << local_marked_down << ":" << local_down_time;
r = getReasonState(Reason::MANUAL);
os << ",MANUAL:" << ReasonStatus[r] << ":" << manual_marked_down << ":" << manual_down_time;
r = getReasonState(Reason::SELF_DETECT);
os << ",SELF_DETECT:" << ReasonStatus[r] << ":" << self_detect_marked_down;
return os;
}
// serialize a HostStatRec
friend std::stringstream &
operator<<(std::stringstream &os, HostStatRec &hs)
{
unsigned int r = hs.getReasonState(Reason::ACTIVE);
os << HostStatusNames[hs.status];
os << ",ACTIVE:" << ReasonStatus[r] << ":" << hs.active_marked_down << ":" << hs.active_down_time;
r = hs.getReasonState(Reason::LOCAL);
os << ",LOCAL:" << ReasonStatus[r] << ":" << hs.local_marked_down << ":" << hs.local_down_time;
r = hs.getReasonState(Reason::MANUAL);
os << ",MANUAL:" << ReasonStatus[r] << ":" << hs.manual_marked_down << ":" << hs.manual_down_time;
r = hs.getReasonState(Reason::SELF_DETECT);
os << ",SELF_DETECT:" << ReasonStatus[r] << ":" << hs.self_detect_marked_down;
return os;
}
inline unsigned int
getReasonState(unsigned int reason)
{
unsigned int r = 0;
if (reasons == 0) {
r = 0;
} else if (reasons & reason) {
r = 1;
}
return r;
}
};
/**
* Singleton placeholder for next hop status.
*/
struct HostStatus {
~HostStatus();
static HostStatus &
instance()
{
static HostStatus instance;
return instance;
}
void setHostStatus(const std::string_view name, const TSHostStatus status, const unsigned int down_time,
const unsigned int reason);
HostStatRec *getHostStatus(const std::string_view name);
void createHostStat(const std::string_view name, const char *data = nullptr);
void loadHostStatusFromStats();
void loadRecord(std::string_view name, HostStatRec &h);
RecErrT getHostStat(std::string &stat_name, char *buf, unsigned int buf_len);
private:
HostStatus();
HostStatus(const HostStatus &obj) = delete;
HostStatus &operator=(HostStatus const &) = delete;
// next hop status, key is hostname or ip string, data is HostStatRec
std::unordered_map<std::string, HostStatRec *> hosts_statuses;
ink_rwlock host_status_rwlock;
};