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