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