-#include "config.h"
-#include "globals.h"
-#include "TextException.h"
-#include "SquidTime.h"
-#include "HttpRequest.h" /* for alLogformatHasAdaptToken */
+/*
+ * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+#include "squid.h"
#include "adaptation/Config.h"
#include "adaptation/History.h"
+#include "base/TextException.h"
+#include "Debug.h"
+#include "globals.h"
+#include "SquidTime.h"
/// impossible services value to identify unset theNextServices
-const static String TheNullServices(",null,");
+const static char *TheNullServices = ",null,";
-Adaptation::History::Entry::Entry(const String &sid, const timeval &when):
- service(sid), start(when), theRptm(-1), retried(false)
+Adaptation::History::Entry::Entry(const String &serviceId, const timeval &when):
+ service(serviceId), start(when), theRptm(-1), retried(false)
{
}
return theRptm;
}
-
-Adaptation::History::History(): theNextServices(TheNullServices) {
+Adaptation::History::History():
+ lastMeta(hoReply),
+ allMeta(hoReply),
+ theNextServices(TheNullServices)
+{
}
-int Adaptation::History::recordXactStart(const String &sid, const timeval &when, bool retrying)
+int Adaptation::History::recordXactStart(const String &serviceId, const timeval &when, bool retrying)
{
- if (retrying) {
- Must(!theEntries.empty()); // or there would be nothing to retry
+ // the history will be empty on retries if it was enabled after the failure
+ if (retrying && !theEntries.empty())
theEntries.back().retried = true;
- }
- theEntries.push_back(Adaptation::History::Entry(sid, when));
+
+ theEntries.push_back(Adaptation::History::Entry(serviceId, when));
return theEntries.size() - 1; // record position becomes history ID
}
theEntries[hid].stop();
}
-void Adaptation::History::allLogString(const char *serviceId, String &s)
+void Adaptation::History::allLogString(const char *serviceId, SBuf &s)
{
- s="";
+ s.clear();
bool prevWasRetried = false;
- // XXX: Fix Vector<> so that we can use const_iterator here
- typedef Adaptation::History::Entries::iterator ECI;
- for (ECI i = theEntries.begin(); i != theEntries.end(); ++i) {
+ for (auto &i : theEntries) {
// TODO: here and below, optimize service ID comparison?
- if (!serviceId || i->service == serviceId) {
- if (s.size() > 0) // not the first logged time, must delimit
- s.append(prevWasRetried ? "+" : ",");
-
- char buf[64];
- snprintf(buf, sizeof(buf), "%d", i->rptm());
- s.append(buf);
-
+ if (!serviceId || i.service == serviceId) {
+ if (!s.isEmpty()) // not the first logged time, must delimit
+ s.append(prevWasRetried ? '+' : ',');
+ s.appendf("%d", i.rptm());
// continue; we may have two identical services (e.g., for retries)
}
- prevWasRetried = i->retried;
+ prevWasRetried = i.retried;
}
}
-void Adaptation::History::sumLogString(const char *serviceId, String &s)
+void Adaptation::History::sumLogString(const char *serviceId, SBuf &s)
{
- s="";
+ s.clear();
int retriedRptm = 0; // sum of rptm times of retried transactions
- typedef Adaptation::History::Entries::iterator ECI;
- for (ECI i = theEntries.begin(); i != theEntries.end(); ++i) {
- if (i->retried) { // do not log retried xact but accumulate their time
- retriedRptm += i->rptm();
- } else
- if (!serviceId || i->service == serviceId) {
- if (s.size() > 0) // not the first logged time, must delimit
- s.append(",");
-
- char buf[64];
- snprintf(buf, sizeof(buf), "%d", retriedRptm + i->rptm());
- s.append(buf);
-
+ for (auto & i : theEntries) {
+ if (i.retried) { // do not log retried xact but accumulate their time
+ retriedRptm += i.rptm();
+ } else if (!serviceId || i.service == serviceId) {
+ if (!s.isEmpty()) // not the first logged time, must delimit
+ s.append(',');
+ s.appendf("%d", retriedRptm + i.rptm());
// continue; we may have two identical services (e.g., for retries)
}
- if (!i->retried)
+ if (!i.retried)
retriedRptm = 0;
}
// the last transaction is never retried or it would not be the last
- Must(!retriedRptm);
+ Must(!retriedRptm);
}
void Adaptation::History::updateXxRecord(const char *name, const String &value)
bool Adaptation::History::getXxRecord(String &name, String &value) const
{
if (theXxName.size() <= 0)
- return false;
+ return false;
name = theXxName;
value = theXxValue;
void Adaptation::History::updateNextServices(const String &services)
{
if (theNextServices != TheNullServices)
- debugs(93,3, HERE << "old services: " << theNextServices);
+ debugs(93,3, HERE << "old services: " << theNextServices);
debugs(93,3, HERE << "new services: " << services);
Must(services != TheNullServices);
theNextServices = services;
bool Adaptation::History::extractNextServices(String &value)
{
if (theNextServices == TheNullServices)
- return false;
+ return false;
value = theNextServices;
theNextServices = TheNullServices; // prevents resetting the plan twice
return true;
}
+
+void Adaptation::History::recordMeta(const HttpHeader *lm)
+{
+ lastMeta.clean();
+ lastMeta.update(lm);
+
+ allMeta.update(lm);
+ allMeta.compact();
+}
+
+void
+Adaptation::History::recordAdaptationService(SBuf &srvId)
+{
+ theAdaptationServices.push_back(srvId);
+}
+
+void
+Adaptation::History::setFutureServices(const DynamicGroupCfg &services)
+{
+ if (!theFutureServices.empty())
+ debugs(93,3, HERE << "old future services: " << theFutureServices);
+ debugs(93,3, HERE << "new future services: " << services);
+ theFutureServices = services; // may be empty
+}
+
+bool Adaptation::History::extractFutureServices(DynamicGroupCfg &value)
+{
+ if (theFutureServices.empty())
+ return false;
+
+ value = theFutureServices;
+ theFutureServices.clear();
+ return true;
+}
+