]> git.ipfire.org Git - thirdparty/squid.git/blob - src/adaptation/History.cc
Polished r9854 "crash on shutdown" changes by removing explicit String
[thirdparty/squid.git] / src / adaptation / History.cc
1 #include "config.h"
2 #include "globals.h"
3 #include "TextException.h"
4 #include "SquidTime.h"
5 #include "HttpRequest.h" /* for alLogformatHasAdaptToken */
6 #include "adaptation/Config.h"
7 #include "adaptation/History.h"
8
9 /// impossible services value to identify unset theNextServices
10 const static char *TheNullServices = ",null,";
11
12 Adaptation::History::Entry::Entry(const String &sid, const timeval &when):
13 service(sid), 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(): theNextServices(TheNullServices) {
37 }
38
39 int Adaptation::History::recordXactStart(const String &sid, const timeval &when, bool retrying)
40 {
41 if (retrying) {
42 Must(!theEntries.empty()); // or there would be nothing to retry
43 theEntries.back().retried = true;
44 }
45 theEntries.push_back(Adaptation::History::Entry(sid, when));
46 return theEntries.size() - 1; // record position becomes history ID
47 }
48
49 void Adaptation::History::recordXactFinish(int hid)
50 {
51 Must(0 <= hid && hid < static_cast<int>(theEntries.size()));
52 theEntries[hid].stop();
53 }
54
55 void Adaptation::History::allLogString(const char *serviceId, String &s)
56 {
57 s="";
58 bool prevWasRetried = false;
59 // XXX: Fix Vector<> so that we can use const_iterator here
60 typedef Adaptation::History::Entries::iterator ECI;
61 for (ECI i = theEntries.begin(); i != theEntries.end(); ++i) {
62 // TODO: here and below, optimize service ID comparison?
63 if (!serviceId || i->service == serviceId) {
64 if (s.size() > 0) // not the first logged time, must delimit
65 s.append(prevWasRetried ? "+" : ",");
66
67 char buf[64];
68 snprintf(buf, sizeof(buf), "%d", i->rptm());
69 s.append(buf);
70
71 // continue; we may have two identical services (e.g., for retries)
72 }
73 prevWasRetried = i->retried;
74 }
75 }
76
77 void Adaptation::History::sumLogString(const char *serviceId, String &s)
78 {
79 s="";
80 int retriedRptm = 0; // sum of rptm times of retried transactions
81 typedef Adaptation::History::Entries::iterator ECI;
82 for (ECI i = theEntries.begin(); i != theEntries.end(); ++i) {
83 if (i->retried) { // do not log retried xact but accumulate their time
84 retriedRptm += i->rptm();
85 } else
86 if (!serviceId || i->service == serviceId) {
87 if (s.size() > 0) // not the first logged time, must delimit
88 s.append(",");
89
90 char buf[64];
91 snprintf(buf, sizeof(buf), "%d", retriedRptm + i->rptm());
92 s.append(buf);
93
94 // continue; we may have two identical services (e.g., for retries)
95 }
96
97 if (!i->retried)
98 retriedRptm = 0;
99 }
100
101 // the last transaction is never retried or it would not be the last
102 Must(!retriedRptm);
103 }
104
105 void Adaptation::History::updateXxRecord(const char *name, const String &value)
106 {
107 theXxName = name;
108 theXxValue = value;
109 }
110
111 bool Adaptation::History::getXxRecord(String &name, String &value) const
112 {
113 if (theXxName.size() <= 0)
114 return false;
115
116 name = theXxName;
117 value = theXxValue;
118 return true;
119 }
120
121 void Adaptation::History::updateNextServices(const String &services)
122 {
123 if (theNextServices != TheNullServices)
124 debugs(93,3, HERE << "old services: " << theNextServices);
125 debugs(93,3, HERE << "new services: " << services);
126 Must(services != TheNullServices);
127 theNextServices = services;
128 }
129
130 bool Adaptation::History::extractNextServices(String &value)
131 {
132 if (theNextServices == TheNullServices)
133 return false;
134
135 value = theNextServices;
136 theNextServices = TheNullServices; // prevents resetting the plan twice
137 return true;
138 }