You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by jr...@apache.org on 2019/05/08 19:26:47 UTC
[trafficserver] branch master updated: Change HostStatus to use
only one stat per host. The host stat is now a string value containing all
time and reason data so that it may be restored from persistent store when
ATS is restarted.
This is an automated email from the ASF dual-hosted git repository.
jrushford pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push:
new a028e7b Change HostStatus to use only one stat per host. The host stat is now a string value containing all time and reason data so that it may be restored from persistent store when ATS is restarted.
a028e7b is described below
commit a028e7b9b22d4dcca87544b93f079ff6a4165c91
Author: John Rushford <jr...@apache.org>
AuthorDate: Thu May 2 13:39:50 2019 +0000
Change HostStatus to use only one stat per host. The host stat
is now a string value containing all time and reason data so that
it may be restored from persistent store when ATS is restarted.
---
doc/appendices/command-line/traffic_ctl.en.rst | 40 ++-
iocore/cache/test/stub.cc | 4 +-
proxy/HostStatus.h | 140 +++++++--
proxy/ParentSelection.cc | 54 ++--
src/traffic_ctl/host.cc | 58 ++--
src/traffic_server/HostStatus.cc | 404 ++++++++++++++++++-------
6 files changed, 510 insertions(+), 190 deletions(-)
diff --git a/doc/appendices/command-line/traffic_ctl.en.rst b/doc/appendices/command-line/traffic_ctl.en.rst
index 6539eda..653598b 100644
--- a/doc/appendices/command-line/traffic_ctl.en.rst
+++ b/doc/appendices/command-line/traffic_ctl.en.rst
@@ -258,27 +258,53 @@ traffic_ctl host
Get the current status of the hosts used in parent.config as a next hop in a multi-tiered cache hierarchy. The value 0 or 1 is returned indicating that the host is marked as down '0' or marked as up '1'. If a host is marked as down, it will not be used as the next hop parent, another host marked as up will be chosen.
.. program:: traffic_ctl host
-.. option:: down --time seconds --reason 'manual|active|local' HOSTNAME [HOSTNAME ...]
+.. option:: down --time seconds --reason 'active|local|manual' HOSTNAME [HOSTNAME ...]
Marks the listed hosts as down so that they will not be chosen as a next hop parent.
If the --time option is included, the host is marked down for the specified number of
seconds after which the host will automatically be marked up. 0 seconds marks the host
down indefinitely until marked up manually and is the default. A reason tag may be used
- when marking a host down. Valid values are 'manual', 'active', or 'local', 'manual' is
- used as the default. The tags are used to indicate wehter the host was marked down
- manually or by an 'active' or 'local' health check. There are three reason tag
- metrics for each host that may be viewed to see the reason a host was marked down.
+ when marking a host down. Valid values are 'manual', 'active', and 'local', 'manual'
+ is used as the default if no reason is specified. The tags are used to indicate wether the host
+ was marked down manually or by an 'active' or 'local' health check. 'self_detect' indicates
+ that a parent entry in parent.config was marked down because the entry refers to the
+ local host so, it is automatically marked down to prevent requests from looping. A host is
+ not marked up until all reason codes are cleared by marking up the host for the specified
+ reason code.
+
+ A stat is created for each host, with a the host fqdn and is prefixed with the string
+ `proxy.process.host_status` with a string value. The string value is a
+ serialized representation of the Host status struct showing all current data ie, reasons,
+ marked down times, and down time for each host. The stats may be viewed using the
+ `traffic_ctl metric` command or through the `stats_over_http` endpoint.
.. program:: traffic_ctl host
-.. option:: up --reason 'manual|active|local' HOSTNAME [HOSTNAME ...]
+.. option:: up --reason 'active|local|manual' HOSTNAME [HOSTNAME ...]
Marks the listed hosts as up so that they will be available for use as a next hop parent.
By default, the 'manual' reason tag is used when marking up a host. Use the --reason
- tag to mark the host reason stat as up using one of 'manual', 'active', or 'local'.
+ tag to mark the host reason code as up using one of 'manual', 'active', or 'local'.
+ The 'self_detect' is an internal reason code used by parent selection to mark down
+ a parent when it is identified as itself and `proxy.config.http.parent_proxy.self_detect'
+ is set to the default of 2. 'self_detect' down cannot be set or unset with traffic_ctl
Examples
========
+Mark down a host with `traffic_ctl` and view the associated host stats::
+
+$ traffic_ctl host down cdn-cache-02.foo.com --reason manual
+
+$ /opt/trafficserver/bin/traffic_ctl metric match host_status
+proxy.process.host_status.cdn-cache-01.foo.com HOST_STATUS_DOWN,ACTIVE:UP:0:0,LOCAL:UP:0:0,MANUAL:DOWN:1556896844:0,SELF_DETECT:UP:0
+proxy.process.host_status.cdn-cache-02.foo.com HOST_STATUS_UP,ACTIVE:UP:0:0,LOCAL:UP:0:0,MANUAL:UP:0:0,SELF_DETECT:UP:0
+proxy.process.host_status.cdn-cache-origin-01.foo.com HOST_STATUS_UP,ACTIVE:UP:0:0,LOCAL:UP:0:0,MANUAL:UP:0:0,SELF_DETECT:UP:0
+
+In the example above, 'cdn-cache-01.foo.com' is unavailable, `HOST_STATUS_DOWN` and was marked down
+for the `manual` reason, `MANUAL:DOWN:1556896844:0`, at the time indicated by the UNIX time stamp
+`1556896844`. To make the host available, one would have to clear the `manual` reason using::
+`traffic_ctl host up cdn-cache-01.foo.com --reason manual`
+
Configure Traffic Server to insert ``Via`` header in the response to
the client::
diff --git a/iocore/cache/test/stub.cc b/iocore/cache/test/stub.cc
index d6710ec..56a5da2 100644
--- a/iocore/cache/test/stub.cc
+++ b/iocore/cache/test/stub.cc
@@ -149,7 +149,7 @@ ts::svtoi(TextView src, TextView *out, int base)
}
void
-HostStatus::setHostStatus(const char *name, HostStatus_t status, const unsigned int down_time, const char *reason)
+HostStatus::setHostStatus(const char *name, HostStatus_t status, const unsigned int down_time, const unsigned int reason)
{
}
@@ -160,7 +160,7 @@ HostStatus::getHostStatus(const char *name)
}
void
-HostStatus::createHostStat(const char *name)
+HostStatus::createHostStat(const char *name, const char *data)
{
}
diff --git a/proxy/HostStatus.h b/proxy/HostStatus.h
index f349b90..2fdc33c 100644
--- a/proxy/HostStatus.h
+++ b/proxy/HostStatus.h
@@ -32,30 +32,38 @@
#include <ctime>
#include <string>
+#include <sstream>
#include "tscore/ink_rwlock.h"
#include "records/P_RecProcess.h"
#include <unordered_map>
+// host_status stats prefix.
+static const std::string stat_prefix = "proxy.process.host_status.";
+
enum HostStatus_t {
HOST_STATUS_INIT,
HOST_STATUS_DOWN,
HOST_STATUS_UP,
};
-struct HostStatRec_t {
- HostStatus_t status;
- time_t marked_down; // the time that this host was marked down.
- unsigned int down_time; // number of seconds that the host should be down, 0 is indefinately
-};
+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;
-struct Reasons {
- static constexpr const char *ACTIVE = "active";
- static constexpr const char *LOCAL = "local";
- static constexpr const char *MANUAL = "manual";
- static constexpr const char *SELF_DETECT = "self_detect";
+ 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[4] = {ACTIVE, LOCAL, MANUAL, SELF_DETECT};
+ static constexpr const char *reasons[3] = {ACTIVE_REASON, LOCAL_REASON, MANUAL_REASON};
static bool
validReason(const char *reason)
@@ -67,9 +75,102 @@ struct Reasons {
}
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;
+ }
};
-static const std::string stat_prefix = "proxy.process.host_status.";
+// host status POD
+struct HostStatRec {
+ HostStatus_t 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() {}
+
+ // 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.
@@ -83,23 +184,20 @@ struct HostStatus {
static HostStatus instance;
return instance;
}
- void setHostStatus(const char *name, const HostStatus_t status, const unsigned int down_time, const char *reason);
+ void setHostStatus(const char *name, const HostStatus_t status, const unsigned int down_time, const unsigned int reason);
HostStatus_t getHostStatus(const char *name);
- void createHostStat(const char *name);
+ void createHostStat(const char *name, const char *data = nullptr);
void loadHostStatusFromStats();
- int getHostStatId(const char *name);
+ void loadRecord(std::string &name, HostStatRec &h);
+ RecErrT getHostStat(std::string &stat_name, char *buf, unsigned int buf_len);
private:
- int next_stat_id = 1;
HostStatus();
HostStatus(const HostStatus &obj) = delete;
HostStatus &operator=(HostStatus const &) = delete;
- // next hop status, key is hostname or ip string, data is bool (available).
- std::unordered_map<std::string, HostStatRec_t *> hosts_statuses;
- // next hop stat ids, key is hostname or ip string, data is int stat id.
- std::unordered_map<std::string, int> hosts_stats_ids;
+ // 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;
- ink_rwlock host_statids_rwlock;
};
diff --git a/proxy/ParentSelection.cc b/proxy/ParentSelection.cc
index 6d3d0e5..fd3fef3 100644
--- a/proxy/ParentSelection.cc
+++ b/proxy/ParentSelection.cc
@@ -372,7 +372,7 @@ ParentRecord::PreProcessParents(const char *val, const int line_num, char *buf,
continue;
} else {
Debug("parent_select", "token: %s, matches this machine. Marking down self from parent list at line %d", fqdn, line_num);
- hs.setHostStatus(fqdn, HostStatus_t::HOST_STATUS_DOWN, 0, Reasons::SELF_DETECT);
+ hs.setHostStatus(fqdn, HostStatus_t::HOST_STATUS_DOWN, 0, Reason::SELF_DETECT);
}
}
} else {
@@ -384,7 +384,7 @@ ParentRecord::PreProcessParents(const char *val, const int line_num, char *buf,
} else {
Debug("parent_select", "token: %s, matches this machine. Marking down self from parent list at line %d", token,
line_num);
- hs.setHostStatus(token, HostStatus_t::HOST_STATUS_DOWN, 0, Reasons::SELF_DETECT);
+ hs.setHostStatus(token, HostStatus_t::HOST_STATUS_DOWN, 0, Reason::SELF_DETECT);
}
}
}
@@ -516,7 +516,7 @@ ParentRecord::ProcessParents(char *val, bool isPrimary)
this->parents[i].name = this->parents[i].hash_string;
}
if (hs.getHostStatus(this->parents[i].hostname) == HostStatus_t::HOST_STATUS_INIT) {
- hs.setHostStatus(this->parents[i].hostname, HOST_STATUS_UP, 0, Reasons::MANUAL);
+ hs.setHostStatus(this->parents[i].hostname, HOST_STATUS_UP, 0, Reason::MANUAL);
}
} else {
memcpy(this->secondary_parents[i].hostname, current, tmp - current);
@@ -534,7 +534,7 @@ ParentRecord::ProcessParents(char *val, bool isPrimary)
this->secondary_parents[i].name = this->secondary_parents[i].hash_string;
}
if (hs.getHostStatus(this->secondary_parents[i].hostname) == HostStatus_t::HOST_STATUS_INIT) {
- hs.setHostStatus(this->secondary_parents[i].hostname, HOST_STATUS_UP, 0, Reasons::MANUAL);
+ hs.setHostStatus(this->secondary_parents[i].hostname, HOST_STATUS_UP, 0, Reason::MANUAL);
}
}
tmp3 = nullptr;
@@ -1451,7 +1451,7 @@ EXCLUSIVE_REGRESSION_TEST(PARENTSELECTION)(RegressionTest * /* t ATS_UNUSED */,
// Test 184
// mark fuzzy down with HostStatus API.
HostStatus &_st = HostStatus::instance();
- _st.setHostStatus("fuzzy", HOST_STATUS_DOWN, 0, Reasons::MANUAL);
+ _st.setHostStatus("fuzzy", HOST_STATUS_DOWN, 0, Reason::MANUAL);
ST(184);
REINIT;
@@ -1462,7 +1462,7 @@ EXCLUSIVE_REGRESSION_TEST(PARENTSELECTION)(RegressionTest * /* t ATS_UNUSED */,
// Test 185
// mark fluffy down and expect furry to be chosen
- _st.setHostStatus("fluffy", HOST_STATUS_DOWN, 0, Reasons::MANUAL);
+ _st.setHostStatus("fluffy", HOST_STATUS_DOWN, 0, Reason::MANUAL);
ST(185);
REINIT;
@@ -1473,9 +1473,9 @@ EXCLUSIVE_REGRESSION_TEST(PARENTSELECTION)(RegressionTest * /* t ATS_UNUSED */,
// Test 186
// mark furry and frisky down, fuzzy up and expect fuzzy to be chosen
- _st.setHostStatus("furry", HOST_STATUS_DOWN, 0, Reasons::MANUAL);
- _st.setHostStatus("frisky", HOST_STATUS_DOWN, 0, Reasons::MANUAL);
- _st.setHostStatus("fuzzy", HOST_STATUS_UP, 0, Reasons::MANUAL);
+ _st.setHostStatus("furry", HOST_STATUS_DOWN, 0, Reason::MANUAL);
+ _st.setHostStatus("frisky", HOST_STATUS_DOWN, 0, Reason::MANUAL);
+ _st.setHostStatus("fuzzy", HOST_STATUS_UP, 0, Reason::MANUAL);
ST(186);
REINIT;
@@ -1493,10 +1493,10 @@ EXCLUSIVE_REGRESSION_TEST(PARENTSELECTION)(RegressionTest * /* t ATS_UNUSED */,
REBUILD;
// mark all up.
- _st.setHostStatus("furry", HOST_STATUS_UP, 0, Reasons::MANUAL);
- _st.setHostStatus("fluffy", HOST_STATUS_UP, 0, Reasons::MANUAL);
- _st.setHostStatus("frisky", HOST_STATUS_UP, 0, Reasons::MANUAL);
- _st.setHostStatus("fuzzy", HOST_STATUS_UP, 0, Reasons::MANUAL);
+ _st.setHostStatus("furry", HOST_STATUS_UP, 0, Reason::MANUAL);
+ _st.setHostStatus("fluffy", HOST_STATUS_UP, 0, Reason::MANUAL);
+ _st.setHostStatus("frisky", HOST_STATUS_UP, 0, Reason::MANUAL);
+ _st.setHostStatus("fuzzy", HOST_STATUS_UP, 0, Reason::MANUAL);
REINIT;
br(request, "i.am.rabbit.net");
@@ -1506,7 +1506,7 @@ EXCLUSIVE_REGRESSION_TEST(PARENTSELECTION)(RegressionTest * /* t ATS_UNUSED */,
// Test 188
// mark fuzzy down and expect fluffy.
- _st.setHostStatus("fuzzy", HOST_STATUS_DOWN, 0, Reasons::MANUAL);
+ _st.setHostStatus("fuzzy", HOST_STATUS_DOWN, 0, Reason::MANUAL);
ST(188);
REINIT;
@@ -1517,7 +1517,7 @@ EXCLUSIVE_REGRESSION_TEST(PARENTSELECTION)(RegressionTest * /* t ATS_UNUSED */,
// Test 189
// mark fuzzy back up and expect fuzzy.
- _st.setHostStatus("fuzzy", HOST_STATUS_UP, 0, Reasons::MANUAL);
+ _st.setHostStatus("fuzzy", HOST_STATUS_UP, 0, Reason::MANUAL);
ST(189);
REINIT;
@@ -1533,7 +1533,7 @@ EXCLUSIVE_REGRESSION_TEST(PARENTSELECTION)(RegressionTest * /* t ATS_UNUSED */,
// because the host status is set to down.
params->markParentDown(result, fail_threshold, retry_time);
// set host status down
- _st.setHostStatus("fuzzy", HOST_STATUS_DOWN, 0, Reasons::MANUAL);
+ _st.setHostStatus("fuzzy", HOST_STATUS_DOWN, 0, Reason::MANUAL);
// sleep long enough so that fuzzy is retryable
sleep(params->policy.ParentRetryTime + 1);
ST(190);
@@ -1544,7 +1544,7 @@ EXCLUSIVE_REGRESSION_TEST(PARENTSELECTION)(RegressionTest * /* t ATS_UNUSED */,
// now set the host staus on fuzzy to up and it should now
// be retried.
- _st.setHostStatus("fuzzy", HOST_STATUS_UP, 0, Reasons::MANUAL);
+ _st.setHostStatus("fuzzy", HOST_STATUS_UP, 0, Reason::MANUAL);
ST(191);
REINIT;
br(request, "i.am.rabbit.net");
@@ -1557,10 +1557,10 @@ EXCLUSIVE_REGRESSION_TEST(PARENTSELECTION)(RegressionTest * /* t ATS_UNUSED */,
T("dest_domain=rabbit.net parent=fuzzy:80,fluffy:80,furry:80,frisky:80 round_robin=false go_direct=true\n");
REBUILD;
// mark all up.
- _st.setHostStatus("fuzzy", HOST_STATUS_UP, 0, Reasons::MANUAL);
- _st.setHostStatus("fluffy", HOST_STATUS_UP, 0, Reasons::MANUAL);
- _st.setHostStatus("furry", HOST_STATUS_UP, 0, Reasons::MANUAL);
- _st.setHostStatus("frisky", HOST_STATUS_UP, 0, Reasons::MANUAL);
+ _st.setHostStatus("fuzzy", HOST_STATUS_UP, 0, Reason::MANUAL);
+ _st.setHostStatus("fluffy", HOST_STATUS_UP, 0, Reason::MANUAL);
+ _st.setHostStatus("furry", HOST_STATUS_UP, 0, Reason::MANUAL);
+ _st.setHostStatus("frisky", HOST_STATUS_UP, 0, Reason::MANUAL);
// fuzzy should be chosen.
sleep(1);
REINIT;
@@ -1575,7 +1575,7 @@ EXCLUSIVE_REGRESSION_TEST(PARENTSELECTION)(RegressionTest * /* t ATS_UNUSED */,
sleep(params->policy.ParentRetryTime + 1);
// since the host status is down even though fuzzy is
// retryable, fluffy should be chosen
- _st.setHostStatus("fuzzy", HOST_STATUS_DOWN, 0, Reasons::MANUAL);
+ _st.setHostStatus("fuzzy", HOST_STATUS_DOWN, 0, Reason::MANUAL);
REINIT;
br(request, "i.am.rabbit.net");
FP;
@@ -1585,7 +1585,7 @@ EXCLUSIVE_REGRESSION_TEST(PARENTSELECTION)(RegressionTest * /* t ATS_UNUSED */,
// set the host status for fuzzy back up and since its
// retryable fuzzy should be chosen
ST(194);
- _st.setHostStatus("fuzzy", HOST_STATUS_UP, 0, Reasons::MANUAL);
+ _st.setHostStatus("fuzzy", HOST_STATUS_UP, 0, Reason::MANUAL);
REINIT;
br(request, "i.am.rabbit.net");
FP;
@@ -1706,7 +1706,7 @@ EXCLUSIVE_REGRESSION_TEST(PARENTSELECTION)(RegressionTest * /* t ATS_UNUSED */,
T("dest_domain=rabbit.net parent=fuzzy:80|1.0;fluffy:80|1.0 secondary_parent=furry:80|1.0;frisky:80|1.0 "
"round_robin=consistent_hash go_direct=false secondary_mode=3\n");
REBUILD;
- _st.setHostStatus("fuzzy", HOST_STATUS_DOWN, 0, Reasons::MANUAL);
+ _st.setHostStatus("fuzzy", HOST_STATUS_DOWN, 0, Reason::MANUAL);
REINIT;
br(request, "i.am.rabbit.net");
FP;
@@ -1777,15 +1777,15 @@ EXCLUSIVE_REGRESSION_TEST(PARENTSELECTION)(RegressionTest * /* t ATS_UNUSED */,
"round_robin=consistent_hash go_direct=false\n");
REBUILD;
REINIT;
- _st.setHostStatus("curly", HOST_STATUS_DOWN, 0, Reasons::MANUAL);
+ _st.setHostStatus("curly", HOST_STATUS_DOWN, 0, Reason::MANUAL);
br(request, "i.am.stooges.net");
FP;
RE(verify(result, PARENT_SPECIFIED, "carol", 80), 211);
// cleanup, allow changes to be persisted to records.snap
// so that subsequent test runs do not fail unexpectedly.
- _st.setHostStatus("curly", HOST_STATUS_UP, 0, Reasons::MANUAL);
- _st.setHostStatus("fuzzy", HOST_STATUS_UP, 0, Reasons::MANUAL);
+ _st.setHostStatus("curly", HOST_STATUS_UP, 0, Reason::MANUAL);
+ _st.setHostStatus("fuzzy", HOST_STATUS_UP, 0, Reason::MANUAL);
sleep(2);
delete request;
diff --git a/src/traffic_ctl/host.cc b/src/traffic_ctl/host.cc
index 2b23bc9..1834104 100644
--- a/src/traffic_ctl/host.cc
+++ b/src/traffic_ctl/host.cc
@@ -33,18 +33,15 @@ CtrlEngine::status_get()
TSMgmtError error;
std::string str = stat_prefix + it;
- for (const char *_reason_tag : Reasons::reasons) {
- std::string _stat = str + "_" + _reason_tag;
- error = record.fetch(_stat.c_str());
- if (error != TS_ERR_OKAY) {
- CtrlMgmtError(error, "failed to fetch %s", it.c_str());
- status_code = CTRL_EX_ERROR;
- return;
- }
-
- if (REC_TYPE_IS_STAT(record.rclass())) {
- std::cout << record.name() << ' ' << CtrlMgmtRecordValue(record).c_str() << std::endl;
- }
+ error = record.fetch(str.c_str());
+ if (error != TS_ERR_OKAY) {
+ CtrlMgmtError(error, "failed to fetch %s", it.c_str());
+ status_code = CTRL_EX_ERROR;
+ return;
+ }
+
+ if (REC_TYPE_IS_STAT(record.rclass())) {
+ std::cout << record.name() << ' ' << CtrlMgmtRecordValue(record).c_str() << std::endl;
}
}
}
@@ -52,21 +49,34 @@ CtrlEngine::status_get()
void
CtrlEngine::status_down()
{
- int down_time = 0;
- std::string reason = arguments.get("reason").value();
+ const char *usage = "traffic_ctl host down --reason 'active | local | manual' --time seconds host ....";
+ unsigned int down_time = 0;
+ std::string reason = arguments.get("reason").value();
+ std::string down = arguments.get("time").value();
// if reason is not set, set it to manual (default)
if (reason.empty()) {
- reason = Reasons::MANUAL;
+ reason = Reason::MANUAL;
+ }
+ if (!down.empty()) {
+ down_time = atoi(down.c_str());
}
- if (!Reasons::validReason(reason.c_str())) {
+ if (!Reason::validReason(reason.c_str())) {
fprintf(stderr, "\nInvalid reason: '%s'\n\n", reason.c_str());
- parser.help_message();
+ fprintf(stderr, "Usage: %s\n\n", usage);
+ status_code = CTRL_EX_ERROR;
+ return;
}
TSMgmtError error = TS_ERR_OKAY;
for (const auto &it : arguments.get("down")) {
+ if (strncmp(it.c_str(), "--", 2) == 0) {
+ fprintf(stderr, "\nInvalid option: %s\n", it.c_str());
+ fprintf(stderr, "Usage: %s\n\n", usage);
+ status_code = CTRL_EX_ERROR;
+ return;
+ }
error = TSHostStatusSetDown(it.c_str(), down_time, reason.c_str());
if (error != TS_ERR_OKAY) {
CtrlMgmtError(error, "failed to set %s", it.c_str());
@@ -78,21 +88,29 @@ CtrlEngine::status_down()
void
CtrlEngine::status_up()
{
+ const char *usage = "traffic_ctl host up --reason 'active | local | manual' host ....";
std::string reason = arguments.get("reason").value();
// if reason is not set, set it to manual (default)
if (reason.empty()) {
- reason = Reasons::MANUAL;
+ reason = Reason::MANUAL;
}
- if (!Reasons::validReason(reason.c_str())) {
+ if (!Reason::validReason(reason.c_str())) {
fprintf(stderr, "\nInvalid reason: '%s'\n\n", reason.c_str());
- parser.help_message();
+ fprintf(stderr, "Usage: %s\n\n", usage);
+ status_code = CTRL_EX_ERROR;
+ return;
}
TSMgmtError error;
for (const auto &it : arguments.get("up")) {
error = TSHostStatusSetUp(it.c_str(), 0, reason.c_str());
+ if (strncmp("--", it.c_str(), 2) == 0) {
+ fprintf(stderr, "\nInvalid option: %s\n", it.c_str());
+ fprintf(stderr, "Usage: %s\n\n", usage);
+ status_code = CTRL_EX_ERROR;
+ }
if (error != TS_ERR_OKAY) {
CtrlMgmtError(error, "failed to set %s", it.c_str());
status_code = CTRL_EX_ERROR;
diff --git a/src/traffic_server/HostStatus.cc b/src/traffic_server/HostStatus.cc
index 0facb4c..ac208f7 100644
--- a/src/traffic_server/HostStatus.cc
+++ b/src/traffic_server/HostStatus.cc
@@ -25,16 +25,10 @@
static RecRawStatBlock *host_status_rsb = nullptr;
-static void
-getStatName(std::string &stat_name, const char *name, const char *reason)
+inline void
+getStatName(std::string &stat_name, const char *name)
{
- stat_name = stat_prefix + name + "_";
-
- if (reason == nullptr) {
- stat_name += Reasons::MANUAL;
- } else {
- stat_name += reason;
- }
+ stat_name = stat_prefix + name;
}
static void
@@ -43,22 +37,27 @@ mgmt_host_status_up_callback(ts::MemSpan span)
MgmtInt op;
MgmtMarshallString name;
MgmtMarshallInt down_time;
- MgmtMarshallString reason;
- std::string reason_stat;
+ MgmtMarshallString reason_str;
+ std::string stat_name;
+ char buf[1024] = {0};
char *data = static_cast<char *>(span.data());
auto len = span.size();
static const MgmtMarshallType fields[] = {MGMT_MARSHALL_INT, MGMT_MARSHALL_STRING, MGMT_MARSHALL_STRING, MGMT_MARSHALL_INT};
Debug("host_statuses", "%s:%s:%d - data: %s, len: %ld\n", __FILE__, __func__, __LINE__, data, len);
- if (mgmt_message_parse(data, len, fields, countof(fields), &op, &name, &reason, &down_time) == -1) {
+ if (mgmt_message_parse(data, len, fields, countof(fields), &op, &name, &reason_str, &down_time) == -1) {
Error("Plugin message - RPC parsing error - message discarded.");
}
- Debug("host_statuses", "op: %ld, name: %s, down_time: %d, reason: %s", static_cast<long>(op), name, static_cast<int>(down_time),
- reason);
+ Debug("host_statuses", "op: %ld, name: %s, down_time: %d, reason_str: %s", static_cast<long>(op), name,
+ static_cast<int>(down_time), reason_str);
+
+ unsigned int reason = Reason::getReason(reason_str);
+
+ getStatName(stat_name, name);
if (data != nullptr) {
Debug("host_statuses", "marking up server %s", data);
HostStatus &hs = HostStatus::instance();
- if (hs.getHostStatId(reason_stat.c_str()) == -1) {
+ if (hs.getHostStat(stat_name, buf, 1024) == REC_ERR_FAIL) {
hs.createHostStat(name);
}
hs.setHostStatus(name, HostStatus_t::HOST_STATUS_UP, down_time, reason);
@@ -71,61 +70,142 @@ mgmt_host_status_down_callback(ts::MemSpan span)
MgmtInt op;
MgmtMarshallString name;
MgmtMarshallInt down_time;
- MgmtMarshallString reason;
- std::string reason_stat;
+ MgmtMarshallString reason_str;
+ std::string stat_name;
char *data = static_cast<char *>(span.data());
+ char buf[1024] = {0};
auto len = span.size();
static const MgmtMarshallType fields[] = {MGMT_MARSHALL_INT, MGMT_MARSHALL_STRING, MGMT_MARSHALL_STRING, MGMT_MARSHALL_INT};
Debug("host_statuses", "%s:%s:%d - data: %s, len: %ld\n", __FILE__, __func__, __LINE__, data, len);
- if (mgmt_message_parse(data, len, fields, countof(fields), &op, &name, &reason, &down_time) == -1) {
+ if (mgmt_message_parse(data, len, fields, countof(fields), &op, &name, &reason_str, &down_time) == -1) {
Error("Plugin message - RPC parsing error - message discarded.");
}
- Debug("host_statuses", "op: %ld, name: %s, down_time: %d, reason: %s", static_cast<long>(op), name, static_cast<int>(down_time),
- reason);
+ Debug("host_statuses", "op: %ld, name: %s, down_time: %d, reason_str: %s", static_cast<long>(op), name,
+ static_cast<int>(down_time), reason_str);
+
+ unsigned int reason = Reason::getReason(reason_str);
if (data != nullptr) {
Debug("host_statuses", "marking down server %s", name);
HostStatus &hs = HostStatus::instance();
- if (hs.getHostStatId(reason_stat.c_str()) == -1) {
+ if (hs.getHostStat(stat_name, buf, 1024) == REC_ERR_FAIL) {
hs.createHostStat(name);
}
hs.setHostStatus(name, HostStatus_t::HOST_STATUS_DOWN, down_time, reason);
}
}
+HostStatRec::HostStatRec()
+ : status(HOST_STATUS_UP),
+ reasons(0),
+ active_marked_down(0),
+ local_marked_down(0),
+ manual_marked_down(0),
+ self_detect_marked_down(0),
+ active_down_time(0),
+ local_down_time(0),
+ manual_down_time(0){};
+
+HostStatRec::HostStatRec(std::string str)
+{
+ std::vector<std::string> v1;
+ std::stringstream ss1(str);
+
+ reasons = 0;
+
+ // parse the csv strings from the stat record value string.
+ while (ss1.good()) {
+ char b1[64];
+ ss1.getline(b1, 64, ',');
+ v1.push_back(b1);
+ }
+
+ // v1 contains 5 strings.
+ ink_assert(v1.size() == 5);
+
+ // set the status and reasons fields.
+ for (unsigned int i = 0; i < v1.size(); i++) {
+ if (i == 0) { // set the status field
+ if (v1.at(i).compare("HOST_STATUS_UP") == 0) {
+ status = HOST_STATUS_UP;
+ } else if (v1.at(i).compare("HOST_STATUS_DOWN") == 0) {
+ status = HOST_STATUS_DOWN;
+ }
+ } else { // parse and set remaining reason fields.
+ std::vector<std::string> v2;
+ v2.clear();
+ std::stringstream ss2(v1.at(i));
+ while (ss2.good()) {
+ char b2[64];
+ ss2.getline(b2, 64, ':');
+ v2.push_back(b2);
+ }
+ // v2 contains 4 strings.
+ ink_assert(v2.size() == 3 || v2.size() == 4);
+
+ if (v2.at(0).compare("ACTIVE") == 0) {
+ if (v2.at(1).compare("DOWN") == 0) {
+ reasons |= Reason::ACTIVE;
+ } else if (reasons & Reason::ACTIVE) {
+ reasons ^= Reason::ACTIVE;
+ }
+ active_marked_down = atoi(v2.at(2).c_str());
+ active_down_time = atoi(v2.at(3).c_str());
+ }
+ if (v2.at(0).compare("LOCAL") == 0) {
+ if (v2.at(1).compare("DOWN") == 0) {
+ reasons |= Reason::LOCAL;
+ } else if (reasons & Reason::LOCAL) {
+ reasons ^= Reason::LOCAL;
+ }
+ local_marked_down = atoi(v2.at(2).c_str());
+ local_down_time = atoi(v2.at(3).c_str());
+ }
+ if (v2.at(0).compare("MANUAL") == 0) {
+ if (v2.at(1).compare("DOWN") == 0) {
+ reasons |= Reason::MANUAL;
+ } else if (reasons & Reason::MANUAL) {
+ reasons ^= Reason::MANUAL;
+ }
+ manual_marked_down = atoi(v2.at(2).c_str());
+ manual_down_time = atoi(v2.at(3).c_str());
+ }
+ if (v2.at(0).compare("SELF_DETECT") == 0) {
+ if (v2.at(1).compare("DOWN") == 0) {
+ reasons |= Reason::SELF_DETECT;
+ } else if (reasons & Reason::SELF_DETECT) {
+ reasons ^= Reason::SELF_DETECT;
+ }
+ self_detect_marked_down = atoi(v2.at(2).c_str());
+ }
+ }
+ }
+}
+
static void
handle_record_read(const RecRecord *rec, void *edata)
{
HostStatus &hs = HostStatus::instance();
std::string hostname;
- std::string reason;
if (rec) {
+ Debug("host_statuses", "name: %s", rec->name);
+
// parse the hostname from the stat name
char *s = const_cast<char *>(rec->name);
// 1st move the pointer past the stat prefix.
- s += strlen(stat_prefix.c_str());
+ s += stat_prefix.length();
hostname = s;
- // parse the reason from the stat name.
- reason = hostname.substr(hostname.find('_'));
- reason.erase(0, 1);
- // erase the reason tag
- hostname.erase(hostname.find('_'));
-
- // if the data loaded from stats indicates that the host was down,
- // then update the state so that the host remains down until
- // specifically marked up using traffic_ctl.
- if (rec->data.rec_int == 0 && Reasons::validReason(reason.c_str())) {
- hs.setHostStatus(hostname.c_str(), HOST_STATUS_DOWN, 0, reason.c_str());
- }
+ hs.createHostStat(hostname.c_str(), rec->data.rec_string);
+ HostStatRec h(rec->data.rec_string);
+ hs.loadRecord(hostname, h);
}
}
HostStatus::HostStatus()
{
ink_rwlock_init(&host_status_rwlock);
- ink_rwlock_init(&host_statids_rwlock);
pmgmt->registerMgmtCallback(MGMT_EVENT_HOST_STATUS_UP, &mgmt_host_status_up_callback);
pmgmt->registerMgmtCallback(MGMT_EVENT_HOST_STATUS_DOWN, &mgmt_host_status_down_callback);
host_status_rsb = RecAllocateRawStatBlock((int)TS_MAX_API_STATS);
@@ -136,64 +216,142 @@ HostStatus::~HostStatus()
for (auto &&it : hosts_statuses) {
ats_free(it.second);
}
- // release host_stats_ids hash and the read and writer locks.
+ // release the read and writer locks.
ink_rwlock_destroy(&host_status_rwlock);
- ink_rwlock_destroy(&host_statids_rwlock);
}
void
HostStatus::loadHostStatusFromStats()
{
- if (RecLookupMatchingRecords(RECT_ALL, stat_prefix.c_str(), handle_record_read, nullptr) != REC_ERR_OKAY) {
+ if (RecLookupMatchingRecords(RECT_PROCESS, stat_prefix.c_str(), handle_record_read, nullptr) != REC_ERR_OKAY) {
Error("[HostStatus] - While loading HostStatus stats, there was an Error reading HostStatus stats.");
}
}
void
-HostStatus::setHostStatus(const char *name, HostStatus_t status, const unsigned int down_time, const char *reason)
+HostStatus::loadRecord(std::string &name, HostStatRec &h)
+{
+ HostStatRec *host_stat = nullptr;
+ Debug("host_statuses", "loading host status record for %s", name.c_str());
+ ink_rwlock_wrlock(&host_status_rwlock);
+ {
+ if (auto it = hosts_statuses.find(name.c_str()); it != hosts_statuses.end()) {
+ host_stat = it->second;
+ } else {
+ host_stat = static_cast<HostStatRec *>(ats_malloc(sizeof(HostStatRec)));
+ *host_stat = h;
+ hosts_statuses.emplace(name, host_stat);
+ }
+ }
+ ink_rwlock_unlock(&host_status_rwlock);
+
+ *host_stat = h;
+}
+
+void
+HostStatus::setHostStatus(const char *name, HostStatus_t status, const unsigned int down_time, const unsigned int reason)
{
- std::string reason_stat;
+ std::string stat_name;
+ char buf[1024] = {0};
- getStatName(reason_stat, name, reason);
+ getStatName(stat_name, name);
- if (getHostStatId(reason_stat.c_str()) == -1) {
+ if (getHostStat(stat_name, buf, 1024) == REC_ERR_FAIL) {
createHostStat(name);
}
- int stat_id = getHostStatId(reason_stat.c_str());
+ RecErrT result = getHostStat(stat_name, buf, 1024);
- // update the stats
- if (stat_id != -1) {
+ // update / insert status.
+ // using the hash table pointer to store the HostStatus_t value.
+ HostStatRec *host_stat = nullptr;
+ ink_rwlock_wrlock(&host_status_rwlock);
+ {
+ if (auto it = hosts_statuses.find(name); it != hosts_statuses.end()) {
+ host_stat = it->second;
+ } else {
+ host_stat = static_cast<HostStatRec *>(ats_malloc(sizeof(HostStatRec)));
+ bzero(host_stat, sizeof(HostStatRec));
+ hosts_statuses.emplace(name, host_stat);
+ }
+ if (reason & Reason::ACTIVE) {
+ Debug("host_statuses", "for host %s set status: %s, Reason:ACTIVE", name, HostStatusNames[status]);
+ if (status == HostStatus_t::HOST_STATUS_DOWN) {
+ host_stat->active_marked_down = time(0);
+ host_stat->active_down_time = down_time;
+ host_stat->reasons |= Reason::ACTIVE;
+ } else {
+ host_stat->active_marked_down = 0;
+ host_stat->active_down_time = 0;
+ if (host_stat->reasons & Reason::ACTIVE) {
+ host_stat->reasons ^= Reason::ACTIVE;
+ }
+ }
+ }
+ if (reason & Reason::LOCAL) {
+ Debug("host_statuses", "for host %s set status: %s, Reason:LOCAL", name, HostStatusNames[status]);
+ if (status == HostStatus_t::HOST_STATUS_DOWN) {
+ host_stat->local_marked_down = time(0);
+ host_stat->local_down_time = down_time;
+ host_stat->reasons |= Reason::LOCAL;
+ } else {
+ host_stat->local_marked_down = 0;
+ host_stat->local_down_time = 0;
+ if (host_stat->reasons & Reason::LOCAL) {
+ host_stat->reasons ^= Reason::LOCAL;
+ }
+ }
+ }
+ if (reason & Reason::MANUAL) {
+ Debug("host_statuses", "for host %s set status: %s, Reason:MANUAL", name, HostStatusNames[status]);
+ if (status == HostStatus_t::HOST_STATUS_DOWN) {
+ host_stat->manual_marked_down = time(0);
+ host_stat->manual_down_time = down_time;
+ host_stat->reasons |= Reason::MANUAL;
+ } else {
+ host_stat->manual_marked_down = 0;
+ host_stat->manual_down_time = 0;
+ if (host_stat->reasons & Reason::MANUAL) {
+ host_stat->reasons ^= Reason::MANUAL;
+ }
+ }
+ }
+ if (reason & Reason::SELF_DETECT) {
+ Debug("host_statuses", "for host %s set status: %s, Reason:SELF_DETECT", name, HostStatusNames[status]);
+ if (status == HostStatus_t::HOST_STATUS_DOWN) {
+ host_stat->self_detect_marked_down = time(0);
+ host_stat->reasons |= Reason::SELF_DETECT;
+ } else {
+ host_stat->self_detect_marked_down = 0;
+ if (host_stat->reasons & Reason::SELF_DETECT) {
+ host_stat->reasons ^= Reason::SELF_DETECT;
+ }
+ }
+ }
if (status == HostStatus_t::HOST_STATUS_UP) {
- Debug("host_statuses", "set status up for : name: %s, status: %d, reason_stat: %s", name, status, reason_stat.c_str());
- RecSetRawStatCount(host_status_rsb, stat_id, 1);
- RecSetRawStatSum(host_status_rsb, stat_id, 1);
+ if (host_stat->reasons == 0) {
+ host_stat->status = HostStatus_t::HOST_STATUS_UP;
+ }
+ Debug("host_statuses", "reasons: %d, status: %s", host_stat->reasons, HostStatusNames[host_stat->status]);
} else {
- Debug("host_statuses", "set status down for : name: %s, status: %d, reason_stat: %s", name, status, reason_stat.c_str());
- RecSetRawStatCount(host_status_rsb, stat_id, 0);
- RecSetRawStatSum(host_status_rsb, stat_id, 0);
+ host_stat->status = status;
+ Debug("host_statuses", "reasons: %d, status: %s", host_stat->reasons, HostStatusNames[host_stat->status]);
}
}
- Debug("host_statuses", "name: %s, status: %d", name, status);
+ ink_rwlock_unlock(&host_status_rwlock);
- // update / insert status.
- // using the hash table pointer to store the HostStatus_t value.
- HostStatRec_t *host_stat = nullptr;
- ink_rwlock_wrlock(&host_status_rwlock);
- if (auto it = hosts_statuses.find(name); it != hosts_statuses.end()) {
- host_stat = it->second;
- } else {
- host_stat = static_cast<HostStatRec_t *>(ats_malloc(sizeof(HostStatRec_t)));
- hosts_statuses.emplace(name, host_stat);
- }
- host_stat->status = status;
- host_stat->down_time = down_time;
- if (status == HostStatus_t::HOST_STATUS_DOWN) {
- host_stat->marked_down = time(0);
- } else {
- host_stat->marked_down = 0;
+ // update the stats
+ if (result == REC_ERR_OKAY) {
+ std::stringstream status_rec;
+ status_rec << *host_stat;
+ RecSetRecordString(stat_name.c_str(), const_cast<char *>(status_rec.str().c_str()), REC_SOURCE_EXPLICIT, true, false);
+ if (status == HostStatus_t::HOST_STATUS_UP) {
+ Debug("host_statuses", "set status up for name: %s, status: %d, stat_name: %s", name, status, stat_name.c_str());
+ } else {
+ Debug("host_statuses", "set status down for name: %s, status: %d, stat_name: %s", name, status, stat_name.c_str());
+ }
}
- ink_rwlock_unlock(&host_status_rwlock);
+ Debug("host_statuses", "name: %s, status: %d", name, status);
// log it.
if (status == HostStatus_t::HOST_STATUS_DOWN) {
@@ -206,65 +364,85 @@ HostStatus::setHostStatus(const char *name, HostStatus_t status, const unsigned
HostStatus_t
HostStatus::getHostStatus(const char *name)
{
- HostStatRec_t *_status = 0;
- time_t now = time(0);
+ HostStatRec *_status = 0;
+ time_t now = time(0);
+ bool lookup = false;
// the hash table value pointer has the HostStatus_t value.
ink_rwlock_rdlock(&host_status_rwlock);
- auto it = hosts_statuses.find(name);
- bool lookup = it != hosts_statuses.end();
- if (lookup) {
- _status = it->second;
+ {
+ auto it = hosts_statuses.find(name);
+ lookup = it != hosts_statuses.end();
+ if (lookup) {
+ _status = it->second;
+ }
}
ink_rwlock_unlock(&host_status_rwlock);
// if the host was marked down and it's down_time has elapsed, mark it up.
- if (lookup && _status->status == HostStatus_t::HOST_STATUS_DOWN && _status->down_time > 0) {
- if ((_status->down_time + _status->marked_down) < now) {
- Debug("host_statuses", "name: %s, now: %ld, down_time: %d, marked_down: %ld", name, now, _status->down_time,
- _status->marked_down);
- setHostStatus(name, HostStatus_t::HOST_STATUS_UP, 0, nullptr);
+ if (lookup && _status->status == HostStatus_t::HOST_STATUS_DOWN) {
+ unsigned int reasons = _status->reasons;
+ if ((_status->reasons & Reason::ACTIVE) && _status->active_down_time > 0) {
+ if ((_status->active_down_time + _status->active_marked_down) < now) {
+ Debug("host_statuses", "name: %s, now: %ld, down_time: %d, marked_down: %ld, reason: %s", name, now,
+ _status->active_down_time, _status->active_marked_down, Reason::ACTIVE_REASON);
+ setHostStatus(name, HostStatus_t::HOST_STATUS_UP, 0, Reason::ACTIVE);
+ reasons ^= Reason::ACTIVE;
+ }
+ }
+ if ((_status->reasons & Reason::LOCAL) && _status->local_down_time > 0) {
+ if ((_status->local_down_time + _status->local_marked_down) < now) {
+ Debug("host_statuses", "name: %s, now: %ld, down_time: %d, marked_down: %ld, reason: %s", name, now,
+ _status->local_down_time, _status->local_marked_down, Reason::LOCAL_REASON);
+ setHostStatus(name, HostStatus_t::HOST_STATUS_UP, 0, Reason::LOCAL);
+ reasons ^= Reason::LOCAL;
+ }
+ }
+ if ((_status->reasons & Reason::MANUAL) && _status->manual_down_time > 0) {
+ if ((_status->manual_down_time + _status->manual_marked_down) < now) {
+ Debug("host_statuses", "name: %s, now: %ld, down_time: %d, marked_down: %ld, reason: %s", name, now,
+ _status->manual_down_time, _status->manual_marked_down, Reason::MANUAL_REASON);
+ setHostStatus(name, HostStatus_t::HOST_STATUS_UP, 0, Reason::MANUAL);
+ reasons ^= Reason::MANUAL;
+ }
+ }
+ if (reasons == 0) {
return HostStatus_t::HOST_STATUS_UP;
+ } else {
+ return HostStatus_t::HOST_STATUS_DOWN;
}
}
- return lookup ? static_cast<HostStatus_t>(_status->status) : HostStatus_t::HOST_STATUS_INIT;
+ // didn't find this host in host status db, create the record
+ if (!lookup) {
+ createHostStat(name);
+ }
+
+ return lookup ? static_cast<HostStatus_t>(_status->status) : HostStatus_t::HOST_STATUS_UP;
}
void
-HostStatus::createHostStat(const char *name)
+HostStatus::createHostStat(const char *name, const char *data)
{
- ink_rwlock_wrlock(&host_statids_rwlock);
- {
- for (const char *i : Reasons::reasons) {
- std::string reason_stat;
- getStatName(reason_stat, name, i);
- if (hosts_stats_ids.find(reason_stat) == hosts_stats_ids.end()) {
- RecRegisterRawStat(host_status_rsb, RECT_PROCESS, (reason_stat).c_str(), RECD_INT, RECP_PERSISTENT, (int)next_stat_id,
- RecRawStatSyncSum);
- RecSetRawStatCount(host_status_rsb, next_stat_id, 1);
- RecSetRawStatSum(host_status_rsb, next_stat_id, 1);
-
- hosts_stats_ids.emplace(reason_stat, next_stat_id);
-
- Debug("host_statuses", "stat name: %s, id: %d", reason_stat.c_str(), next_stat_id);
- next_stat_id++;
- }
- }
- }
- ink_rwlock_unlock(&host_statids_rwlock);
-}
+ char buf[1024] = {0};
+ HostStatRec r;
-int
-HostStatus::getHostStatId(const char *stat_name)
-{
- int _id = -1;
+ std::string stat_name;
+ std::stringstream status_rec;
+ if (data != nullptr) {
+ HostStatRec h(data);
+ r = h;
+ }
+ status_rec << r;
+ getStatName(stat_name, name);
- ink_rwlock_rdlock(&host_statids_rwlock);
- if (auto it = hosts_stats_ids.find(stat_name); it != hosts_stats_ids.end()) {
- _id = it->second;
+ if (getHostStat(stat_name, buf, 1024) == REC_ERR_FAIL) {
+ RecRegisterStatString(RECT_PROCESS, stat_name.c_str(), const_cast<char *>(status_rec.str().c_str()), RECP_PERSISTENT);
+ Debug("host_statuses", "stat name: %s, data: %s", stat_name.c_str(), status_rec.str().c_str());
}
- ink_rwlock_unlock(&host_statids_rwlock);
- Debug("host_statuses", "name: %s, id: %d", stat_name, static_cast<int>(_id));
+}
- return _id;
+RecErrT
+HostStatus::getHostStat(std::string &stat_name, char *buf, unsigned int buf_len)
+{
+ return RecGetRecordString(stat_name.c_str(), buf, buf_len, true);
}