1 /** @file
2 
3   A brief file description
4 
5   @section license License
6 
7   Licensed to the Apache Software Foundation (ASF) under one
8   or more contributor license agreements.  See the NOTICE file
9   distributed with this work for additional information
10   regarding copyright ownership.  The ASF licenses this file
11   to you under the Apache License, Version 2.0 (the
12   "License"); you may not use this file except in compliance
13   with the License.  You may obtain a copy of the License at
14 
15       http://www.apache.org/licenses/LICENSE-2.0
16 
17   Unless required by applicable law or agreed to in writing, software
18   distributed under the License is distributed on an "AS IS" BASIS,
19   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20   See the License for the specific language governing permissions and
21   limitations under the License.
22  */
23 
24 /*****************************************************************************
25  *
26  *  HostStatus.h - Interface to Host Status System
27  *
28  *
29  ****************************************************************************/
30 
31 #pragma once
32 
33 #include <ctime>
34 #include <string>
35 #include <sstream>
36 #include "tscore/ink_rwlock.h"
37 #include "records/P_RecProcess.h"
38 
39 #include <unordered_map>
40 
41 // host_status stats prefix.
42 static const std::string stat_prefix = "proxy.process.host_status.";
43 
44 enum HostStatus_t {
45   HOST_STATUS_INIT,
46   HOST_STATUS_DOWN,
47   HOST_STATUS_UP,
48 };
49 
50 static const constexpr char *HostStatusNames[3] = {"HOST_STATUS_INIT", "HOST_STATUS_DOWN", "HOST_STATUS_UP"};
51 static const constexpr char *ReasonStatus[2]    = {"UP", "DOWN"};
52 
53 struct Reason {
54   static constexpr const unsigned int ACTIVE      = 0x1;
55   static constexpr const unsigned int LOCAL       = 0x2;
56   static constexpr const unsigned int MANUAL      = 0x4;
57   static constexpr const unsigned int SELF_DETECT = 0x8;
58   static constexpr const unsigned int ALL         = 0xf;
59 
60   static constexpr const char *ACTIVE_REASON      = "active";
61   static constexpr const char *LOCAL_REASON       = "local";
62   static constexpr const char *MANUAL_REASON      = "manual";
63   static constexpr const char *SELF_DETECT_REASON = "self_detect";
64   static constexpr const char *ALL_REASON         = "all";
65 
66   static constexpr const char *reasons[3] = {ACTIVE_REASON, LOCAL_REASON, MANUAL_REASON};
67 
68   static bool
validReasonReason69   validReason(const char *reason)
70   {
71     for (const char *i : reasons) {
72       if (strcmp(i, reason) == 0) {
73         return true;
74       }
75     }
76     return false;
77   }
78 
79   static unsigned int
getReasonReason80   getReason(const char *reason_str)
81   {
82     if (strcmp(reason_str, ACTIVE_REASON) == 0) {
83       return ACTIVE;
84     } else if (strcmp(reason_str, LOCAL_REASON) == 0) {
85       return LOCAL;
86     } else if (strcmp(reason_str, MANUAL_REASON) == 0) {
87       return MANUAL;
88     } else if (strcmp(reason_str, SELF_DETECT_REASON) == 0) {
89       return SELF_DETECT;
90     } else if (strcmp(reason_str, ALL_REASON) == 0) {
91       return ALL;
92     }
93     // default is MANUAL
94     return MANUAL;
95   }
96 };
97 
98 // host status POD
99 struct HostStatRec {
100   HostStatus_t status;
101   unsigned int reasons;
102   // time the host was marked down for a given reason.
103   time_t active_marked_down;
104   time_t local_marked_down;
105   time_t manual_marked_down;
106   time_t self_detect_marked_down;
107   // number of seconds that the host should be marked down for a given reason.
108   unsigned int active_down_time;
109   unsigned int local_down_time;
110   unsigned int manual_down_time;
111 
112   HostStatRec();
113   HostStatRec(std::string str);
HostStatRecHostStatRec114   HostStatRec(const HostStatRec &src)
115   {
116     status                  = src.status;
117     reasons                 = src.reasons;
118     active_marked_down      = src.active_marked_down;
119     active_down_time        = src.active_down_time;
120     local_marked_down       = src.local_marked_down;
121     local_down_time         = src.local_down_time;
122     manual_marked_down      = src.manual_marked_down;
123     manual_down_time        = src.manual_down_time;
124     self_detect_marked_down = src.self_detect_marked_down;
125   }
~HostStatRecHostStatRec126   ~HostStatRec() {}
127 
128   HostStatRec &operator=(const HostStatRec &source) = default;
129 
130   // serialize this HostStatusRec
131   std::stringstream &
132   operator<<(std::stringstream &os)
133   {
134     unsigned int r = getReasonState(Reason::ACTIVE);
135     os << HostStatusNames[status];
136     os << ",ACTIVE:" << ReasonStatus[r] << ":" << active_marked_down << ":" << active_down_time;
137     r = getReasonState(Reason::LOCAL);
138     os << ",LOCAL:" << ReasonStatus[r] << ":" << local_marked_down << ":" << local_down_time;
139     r = getReasonState(Reason::MANUAL);
140     os << ",MANUAL:" << ReasonStatus[r] << ":" << manual_marked_down << ":" << manual_down_time;
141     r = getReasonState(Reason::SELF_DETECT);
142     os << ",SELF_DETECT:" << ReasonStatus[r] << ":" << self_detect_marked_down;
143 
144     return os;
145   }
146 
147   // serialize a HostStatRec
148   friend std::stringstream &
149   operator<<(std::stringstream &os, HostStatRec &hs)
150   {
151     unsigned int r = hs.getReasonState(Reason::ACTIVE);
152     os << HostStatusNames[hs.status];
153     os << ",ACTIVE:" << ReasonStatus[r] << ":" << hs.active_marked_down << ":" << hs.active_down_time;
154     r = hs.getReasonState(Reason::LOCAL);
155     os << ",LOCAL:" << ReasonStatus[r] << ":" << hs.local_marked_down << ":" << hs.local_down_time;
156     r = hs.getReasonState(Reason::MANUAL);
157     os << ",MANUAL:" << ReasonStatus[r] << ":" << hs.manual_marked_down << ":" << hs.manual_down_time;
158     r = hs.getReasonState(Reason::SELF_DETECT);
159     os << ",SELF_DETECT:" << ReasonStatus[r] << ":" << hs.self_detect_marked_down;
160 
161     return os;
162   }
163 
164   inline unsigned int
getReasonStateHostStatRec165   getReasonState(unsigned int reason)
166   {
167     unsigned int r = 0;
168     if (reasons == 0) {
169       r = 0;
170     } else if (reasons & reason) {
171       r = 1;
172     }
173     return r;
174   }
175 };
176 
177 /**
178  * Singleton placeholder for next hop status.
179  */
180 struct HostStatus {
181   ~HostStatus();
182 
183   static HostStatus &
instanceHostStatus184   instance()
185   {
186     static HostStatus instance;
187     return instance;
188   }
189   void setHostStatus(const char *name, const HostStatus_t status, const unsigned int down_time, const unsigned int reason);
190   HostStatRec *getHostStatus(const char *name);
191   void createHostStat(const char *name, const char *data = nullptr);
192   void loadHostStatusFromStats();
193   void loadRecord(std::string &name, HostStatRec &h);
194   RecErrT getHostStat(std::string &stat_name, char *buf, unsigned int buf_len);
195 
196 private:
197   HostStatus();
198   HostStatus(const HostStatus &obj) = delete;
199   HostStatus &operator=(HostStatus const &) = delete;
200 
201   // next hop status, key is hostname or ip string, data is HostStatRec
202   std::unordered_map<std::string, HostStatRec *> hosts_statuses;
203 
204   ink_rwlock host_status_rwlock;
205 };
206