]> git.ipfire.org Git - thirdparty/squid.git/blob - src/adaptation/History.cc
Completed protos.h split and code refactoring
[thirdparty/squid.git] / src / adaptation / History.cc
1 #include "squid.h"
2 #include "adaptation/Config.h"
3 #include "adaptation/History.h"
4 #include "base/TextException.h"
5 #include "Debug.h"
6 #include "globals.h"
7 #include "SquidTime.h"
8
9 /// impossible services value to identify unset theNextServices
10 const static char *TheNullServices = ",null,";
11
12 Adaptation::History::Entry::Entry(const String &serviceId, const timeval &when):
13 service(serviceId), start(when), theRptm(-1), retried(false)
14 {
15 }
16
17 Adaptation::History::Entry::Entry():
18 start(current_time), theRptm(-1), retried(false)
19 {
20 }
21
22 void Adaptation::History::Entry::stop()
23 {
24 // theRptm may already be set if the access log entry has already been made
25 (void)rptm(); // will cache result in theRptm if not set already
26 }
27
28 int Adaptation::History::Entry::rptm()
29 {
30 if (theRptm < 0)
31 theRptm = tvSubMsec(start, current_time);
32 return theRptm;
33 }
34
35 Adaptation::History::History():
36 lastMeta(hoReply),
37 allMeta(hoReply),
38 theNextServices(TheNullServices)
39 {
40 }
41
42 int Adaptation::History::recordXactStart(const String &serviceId, const timeval &when, bool retrying)
43 {
44 // the history will be empty on retries if it was enabled after the failure
45 if (retrying && !theEntries.empty())
46 theEntries.back().retried = true;
47
48 theEntries.push_back(Adaptation::History::Entry(serviceId, when));
49 return theEntries.size() - 1; // record position becomes history ID
50 }
51
52 void Adaptation::History::recordXactFinish(int hid)
53 {
54 Must(0 <= hid && hid < static_cast<int>(theEntries.size()));
55 theEntries[hid].stop();
56 }
57
58 void Adaptation::History::allLogString(const char *serviceId, String &s)
59 {
60 s="";
61 bool prevWasRetried = false;
62 // XXX: Fix Vector<> so that we can use const_iterator here
63 typedef Adaptation::History::Entries::iterator ECI;
64 for (ECI i = theEntries.begin(); i != theEntries.end(); ++i) {
65 // TODO: here and below, optimize service ID comparison?
66 if (!serviceId || i->service == serviceId) {
67 if (s.size() > 0) // not the first logged time, must delimit
68 s.append(prevWasRetried ? "+" : ",");
69
70 char buf[64];
71 snprintf(buf, sizeof(buf), "%d", i->rptm());
72 s.append(buf);
73
74 // continue; we may have two identical services (e.g., for retries)
75 }
76 prevWasRetried = i->retried;
77 }
78 }
79
80 void Adaptation::History::sumLogString(const char *serviceId, String &s)
81 {
82 s="";
83 int retriedRptm = 0; // sum of rptm times of retried transactions
84 typedef Adaptation::History::Entries::iterator ECI;
85 for (ECI i = theEntries.begin(); i != theEntries.end(); ++i) {
86 if (i->retried) { // do not log retried xact but accumulate their time
87 retriedRptm += i->rptm();
88 } else if (!serviceId || i->service == serviceId) {
89 if (s.size() > 0) // not the first logged time, must delimit
90 s.append(",");
91
92 char buf[64];
93 snprintf(buf, sizeof(buf), "%d", retriedRptm + i->rptm());
94 s.append(buf);
95
96 // continue; we may have two identical services (e.g., for retries)
97 }
98
99 if (!i->retried)
100 retriedRptm = 0;
101 }
102
103 // the last transaction is never retried or it would not be the last
104 Must(!retriedRptm);
105 }
106
107 void Adaptation::History::updateXxRecord(const char *name, const String &value)
108 {
109 theXxName = name;
110 theXxValue = value;
111 }
112
113 bool Adaptation::History::getXxRecord(String &name, String &value) const
114 {
115 if (theXxName.size() <= 0)
116 return false;
117
118 name = theXxName;
119 value = theXxValue;
120 return true;
121 }
122
123 void Adaptation::History::updateNextServices(const String &services)
124 {
125 if (theNextServices != TheNullServices)
126 debugs(93,3, HERE << "old services: " << theNextServices);
127 debugs(93,3, HERE << "new services: " << services);
128 Must(services != TheNullServices);
129 theNextServices = services;
130 }
131
132 bool Adaptation::History::extractNextServices(String &value)
133 {
134 if (theNextServices == TheNullServices)
135 return false;
136
137 value = theNextServices;
138 theNextServices = TheNullServices; // prevents resetting the plan twice
139 return true;
140 }
141
142 void Adaptation::History::recordMeta(const HttpHeader *lm)
143 {
144 lastMeta.clean();
145 lastMeta.update(lm, NULL);
146
147 allMeta.update(lm, NULL);
148 allMeta.compact();
149 }
150
151 void
152 Adaptation::History::setFutureServices(const DynamicGroupCfg &services)
153 {
154 if (!theFutureServices.empty())
155 debugs(93,3, HERE << "old future services: " << theFutureServices);
156 debugs(93,3, HERE << "new future services: " << services);
157 theFutureServices = services; // may be empty
158 }
159
160 bool Adaptation::History::extractFutureServices(DynamicGroupCfg &value)
161 {
162 if (theFutureServices.empty())
163 return false;
164
165 value = theFutureServices;
166 theFutureServices.clear();
167 return true;
168 }