Coverage Report

Created: 2026-10-23 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/trafficserver/include/proxy/HostStatus.h
Line
Count
Source
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
#include "iocore/eventsystem/Continuation.h"
33
#include "iocore/eventsystem/Event.h"
34
#include "records/RecCore.h"
35
#include "tscore/Filenames.h"
36
#include "tscore/Layout.h"
37
#include "tsutil/Bravo.h"
38
39
#include <ctime>
40
#include <string>
41
#include <sstream>
42
#include <unordered_map>
43
44
// host_status stats prefix.
45
static const std::string stat_prefix = "proxy.process.host_status.";
46
47
static const constexpr char *HostStatusNames[3] = {"HOST_STATUS_INIT", "HOST_STATUS_DOWN", "HOST_STATUS_UP"};
48
static const constexpr char *ReasonStatus[2]    = {"UP", "DOWN"};
49
50
struct Reason {
51
  static constexpr const unsigned int ACTIVE      = 0x1;
52
  static constexpr const unsigned int LOCAL       = 0x2;
53
  static constexpr const unsigned int MANUAL      = 0x4;
54
  static constexpr const unsigned int SELF_DETECT = 0x8;
55
  static constexpr const unsigned int ALL         = 0xf;
56
57
  static constexpr const char *ACTIVE_REASON      = "active";
58
  static constexpr const char *LOCAL_REASON       = "local";
59
  static constexpr const char *MANUAL_REASON      = "manual";
60
  static constexpr const char *SELF_DETECT_REASON = "self_detect";
61
  static constexpr const char *ALL_REASON         = "all";
62
63
  static constexpr const char *reasons[3] = {ACTIVE_REASON, LOCAL_REASON, MANUAL_REASON};
64
65
  static bool
66
  validReason(const char *reason)
67
0
  {
68
0
    for (const char *i : reasons) {
69
0
      if (strcmp(i, reason) == 0) {
70
0
        return true;
71
0
      }
72
0
    }
73
0
    return false;
74
0
  }
75
76
  static unsigned int
77
  getReason(const char *reason_str)
78
0
  {
79
0
    if (strcmp(reason_str, ACTIVE_REASON) == 0) {
80
0
      return ACTIVE;
81
0
    } else if (strcmp(reason_str, LOCAL_REASON) == 0) {
82
0
      return LOCAL;
83
0
    } else if (strcmp(reason_str, MANUAL_REASON) == 0) {
84
0
      return MANUAL;
85
0
    } else if (strcmp(reason_str, SELF_DETECT_REASON) == 0) {
86
0
      return SELF_DETECT;
87
0
    } else if (strcmp(reason_str, ALL_REASON) == 0) {
88
0
      return ALL;
89
0
    }
90
    // default is MANUAL
91
0
    return MANUAL;
92
0
  }
93
};
94
95
struct HostStatuses {
96
  std::string hostname;
97
  std::string status;
98
};
99
100
// host status POD
101
struct HostStatRec {
102
  TSHostStatus status{TSHostStatus::TS_HOST_STATUS_INIT};
103
  unsigned int reasons{0};
104
  // time the host was marked down for a given reason.
105
  time_t active_marked_down{0};
106
  time_t local_marked_down{0};
107
  time_t manual_marked_down{0};
108
  time_t self_detect_marked_down{0};
109
  // number of seconds that the host should be marked down for a given reason.
110
  unsigned int active_down_time{0};
111
  unsigned int local_down_time{0};
112
  unsigned int manual_down_time{0};
113
114
  HostStatRec();
115
  HostStatRec(std::string str);
116
  HostStatRec(const HostStatRec &src)
117
0
  {
118
0
    status                  = src.status;
119
0
    reasons                 = src.reasons;
120
0
    active_marked_down      = src.active_marked_down;
121
0
    active_down_time        = src.active_down_time;
122
0
    local_marked_down       = src.local_marked_down;
123
0
    local_down_time         = src.local_down_time;
124
0
    manual_marked_down      = src.manual_marked_down;
125
0
    manual_down_time        = src.manual_down_time;
126
0
    self_detect_marked_down = src.self_detect_marked_down;
127
0
  }
128
0
  ~HostStatRec() {}
129
130
  HostStatRec &operator=(const HostStatRec &source) = default;
131
132
  // serialize this HostStatusRec
133
  std::stringstream &
134
  operator<<(std::stringstream &os)
135
0
  {
136
0
    unsigned int r = getReasonState(Reason::ACTIVE);
137
0
    os << HostStatusNames[status];
138
0
    os << ",ACTIVE:" << ReasonStatus[r] << ":" << active_marked_down << ":" << active_down_time;
139
0
    r = getReasonState(Reason::LOCAL);
140
0
    os << ",LOCAL:" << ReasonStatus[r] << ":" << local_marked_down << ":" << local_down_time;
141
0
    r = getReasonState(Reason::MANUAL);
142
0
    os << ",MANUAL:" << ReasonStatus[r] << ":" << manual_marked_down << ":" << manual_down_time;
143
0
    r = getReasonState(Reason::SELF_DETECT);
144
0
    os << ",SELF_DETECT:" << ReasonStatus[r] << ":" << self_detect_marked_down;
145
0
146
0
    return os;
147
0
  }
148
149
  // serialize a HostStatRec
150
  friend std::stringstream &
151
  operator<<(std::stringstream &os, HostStatRec &hs)
152
0
  {
153
0
    unsigned int r = hs.getReasonState(Reason::ACTIVE);
154
0
    os << HostStatusNames[hs.status];
155
0
    os << ",ACTIVE:" << ReasonStatus[r] << ":" << hs.active_marked_down << ":" << hs.active_down_time;
156
0
    r = hs.getReasonState(Reason::LOCAL);
157
0
    os << ",LOCAL:" << ReasonStatus[r] << ":" << hs.local_marked_down << ":" << hs.local_down_time;
158
0
    r = hs.getReasonState(Reason::MANUAL);
159
0
    os << ",MANUAL:" << ReasonStatus[r] << ":" << hs.manual_marked_down << ":" << hs.manual_down_time;
160
0
    r = hs.getReasonState(Reason::SELF_DETECT);
161
0
    os << ",SELF_DETECT:" << ReasonStatus[r] << ":" << hs.self_detect_marked_down;
162
163
0
    return os;
164
0
  }
165
166
  inline unsigned int
167
  getReasonState(unsigned int reason)
168
0
  {
169
0
    unsigned int r = 0;
170
0
    if (reasons == 0) {
171
0
      r = 0;
172
0
    } else if (reasons & reason) {
173
0
      r = 1;
174
0
    }
175
0
    return r;
176
0
  }
177
};
178
179
class HostStatusSync : public Continuation
180
{
181
private:
182
  HostStatusSync()
183
0
  {
184
0
    getHostStatusPersistentFilePath();
185
186
0
    SET_HANDLER(&HostStatusSync::mainEvent);
187
0
  }
188
189
0
  ~HostStatusSync() = default;
190
191
public:
192
  HostStatusSync(HostStatusSync const &) = delete;
193
194
  std::string hostRecordsFile;
195
196
  static HostStatusSync *
197
  new_instance()
198
0
  {
199
0
    return new HostStatusSync;
200
0
  }
201
202
  void sync_task();
203
  void
204
  getHostStatusPersistentFilePath()
205
0
  {
206
0
    std::string rundir(RecConfigReadRuntimeDir());
207
0
    hostRecordsFile = Layout::relative_to(rundir, ts::filename::HOST_RECORDS);
208
0
  }
209
210
  // Deletes instance.
211
  int
212
  mainEvent(int /* event ATS_UNUSED */, Event * /* e ATS_UNUSED */)
213
0
  {
214
0
    sync_task();
215
216
0
    delete this;
217
218
0
    return EVENT_DONE;
219
0
  }
220
};
221
222
/**
223
 * Singleton placeholder for next hop status.
224
 */
225
struct HostStatus {
226
  ~HostStatus();
227
228
  static HostStatus &
229
  instance()
230
0
  {
231
0
    static HostStatus instance;
232
0
    return instance;
233
0
  }
234
  void         setHostStatus(const std::string_view name, const TSHostStatus status, const unsigned int down_time,
235
                             const unsigned int reason);
236
  void         loadFromPersistentStore();
237
  void         loadRecord(std::string_view name, HostStatRec &h);
238
  HostStatRec *getHostStatus(const std::string_view name);
239
  void         getAllHostStatuses(std::vector<HostStatuses> &hosts);
240
  std::string
241
  getHostStatusPersistentFilePath()
242
0
  {
243
0
    std::string rundir(RecConfigReadRuntimeDir());
244
0
    return Layout::relative_to(rundir, ts::filename::HOST_RECORDS);
245
0
  }
246
247
private:
248
  HostStatus();
249
  HostStatus(const HostStatus &obj)         = delete;
250
  HostStatus &operator=(HostStatus const &) = delete;
251
252
  // next hop status, key is hostname or ip string, data is HostStatRec
253
  std::unordered_map<std::string, HostStatRec *> hosts_statuses;
254
255
  ts::bravo::shared_mutex host_status_rwlock;
256
};