]> git.ipfire.org Git - thirdparty/squid.git/blame - src/MessageDelayPools.cc
Source Format Enforcement (#763)
[thirdparty/squid.git] / src / MessageDelayPools.cc
CommitLineData
b27668ec 1/*
f70aedc4 2 * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
b27668ec
EB
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
9#include "squid.h"
10
11#if USE_DELAY_POOLS
12#include "acl/Gadgets.h"
13#include "cache_cf.h"
14#include "ConfigParser.h"
15#include "DelaySpec.h"
16#include "event.h"
17#include "MessageBucket.h"
18#include "MessageDelayPools.h"
19#include "Parsing.h"
20#include "SquidTime.h"
21#include "Store.h"
22
23#include <algorithm>
24#include <map>
25
26MessageDelayPools::~MessageDelayPools()
27{
28 freePools();
29}
30
31MessageDelayPools *
32MessageDelayPools::Instance()
33{
34 static MessageDelayPools pools;
35 return &pools;
36}
37
38MessageDelayPool::Pointer
39MessageDelayPools::pool(const SBuf &name)
40{
41 auto it = std::find_if(pools.begin(), pools.end(),
42 [&name](const MessageDelayPool::Pointer p) { return p->poolName == name; });
43 return it == pools.end() ? 0 : *it;
44}
45
46void
47MessageDelayPools::add(MessageDelayPool *p)
48{
49 const auto it = std::find_if(pools.begin(), pools.end(),
50 [&p](const MessageDelayPool::Pointer mp) { return mp->poolName == p->poolName; });
51 if (it != pools.end()) {
52 debugs(3, DBG_CRITICAL, "WARNING: Ignoring duplicate " << p->poolName << " response delay pool");
53 return;
54 }
55 pools.push_back(p);
56}
57
58void
59MessageDelayPools::freePools()
60{
61 pools.clear();
62}
63
64MessageDelayPool::MessageDelayPool(const SBuf &name, int64_t bucketSpeed, int64_t bucketSize,
65 int64_t aggregateSpeed, int64_t aggregateSize, uint16_t initialBucketPercent):
66 access(0),
67 poolName(name),
68 individualRestore(bucketSpeed),
69 individualMaximum(bucketSize),
70 aggregateRestore(aggregateSpeed),
71 aggregateMaximum(aggregateSize),
72 initialBucketLevel(initialBucketPercent),
73 lastUpdate(squid_curtime)
74{
75 theBucket.level() = aggregateMaximum;
76}
77
78MessageDelayPool::~MessageDelayPool()
79{
80 if (access)
81 aclDestroyAccessList(&access);
82}
83
84void
85MessageDelayPool::refillBucket()
86{
87 if (noLimit())
88 return;
89 const int incr = squid_curtime - lastUpdate;
90 if (incr >= 1) {
91 lastUpdate = squid_curtime;
92 DelaySpec spec;
93 spec.restore_bps = aggregateRestore;
94 spec.max_bytes = aggregateMaximum;
95 theBucket.update(spec, incr);
96 }
97}
98
99void
100MessageDelayPool::dump(StoreEntry *entry) const
101{
102 SBuf name("response_delay_pool_access ");
103 name.append(poolName);
104 dump_acl_access(entry, name.c_str(), access);
105 storeAppendPrintf(entry, "response_delay_pool parameters %" PRId64 " %" PRId64 " %" PRId64 " %" PRId64 " %d\n",
106 individualRestore, individualMaximum, aggregateRestore, aggregateMaximum, initialBucketLevel);
107 storeAppendPrintf(entry, "\n");
108}
109
110MessageBucket::Pointer
111MessageDelayPool::createBucket()
112{
113 return new MessageBucket(individualRestore, initialBucketLevel, individualMaximum, this);
114}
115
116void
117MessageDelayConfig::parseResponseDelayPool()
118{
119 static const SBuf bucketSpeedLimit("individual-restore");
120 static const SBuf maxBucketSize("individual-maximum");
121 static const SBuf aggregateSpeedLimit("aggregate-restore");
122 static const SBuf maxAggregateSize("aggregate-maximum");
123 static const SBuf initialBucketPercent("initial-bucket-level");
124
125 static std::map<SBuf, int64_t> params;
126 params[bucketSpeedLimit] = -1;
127 params[maxBucketSize] = -1;
128 params[aggregateSpeedLimit] = -1;
129 params[maxAggregateSize] = -1;
130 params[initialBucketPercent] = 50;
131
132 const SBuf name(ConfigParser::NextToken());
133 if (name.isEmpty()) {
134 debugs(3, DBG_CRITICAL, "FATAL: response_delay_pool missing required \"name\" parameter.");
135 self_destruct();
941bcba7 136 return;
b27668ec
EB
137 }
138
139 char *key = nullptr;
140 char *value = nullptr;
141 while (ConfigParser::NextKvPair(key, value)) {
142 if (!value) {
143 debugs(3, DBG_CRITICAL, "FATAL: '" << key << "' option missing value");
144 self_destruct();
941bcba7 145 return;
b27668ec
EB
146 }
147 auto it = params.find(SBuf(key));
148 if (it == params.end()) {
149 debugs(3, DBG_CRITICAL, "FATAL: response_delay_pool unknown option '" << key << "'");
150 self_destruct();
941bcba7 151 return;
b27668ec
EB
152 }
153 it->second = (it->first == initialBucketPercent) ? xatos(value) : xatoll(value, 10);
154 }
155
156 const char *fatalMsg = nullptr;
157 if ((params[bucketSpeedLimit] < 0) != (params[maxBucketSize] < 0))
158 fatalMsg = "'individual-restore' and 'individual-maximum'";
159 else if ((params[aggregateSpeedLimit] < 0) != (params[maxAggregateSize] < 0))
160 fatalMsg = "'aggregate-restore' and 'aggregate-maximum'";
161
162 if (fatalMsg) {
163 debugs(3, DBG_CRITICAL, "FATAL: must use " << fatalMsg << " options in conjunction");
164 self_destruct();
941bcba7 165 return;
b27668ec
EB
166 }
167
168 MessageDelayPool *pool = new MessageDelayPool(name,
169 params[bucketSpeedLimit],
170 params[maxBucketSize],
171 params[aggregateSpeedLimit],
172 params[maxAggregateSize],
173 static_cast<uint16_t>(params[initialBucketPercent])
174 );
175 MessageDelayPools::Instance()->add(pool);
176}
177
178void
179MessageDelayConfig::parseResponseDelayPoolAccess() {
180 const char *token = ConfigParser::NextToken();
181 if (!token) {
182 debugs(3, DBG_CRITICAL, "ERROR: required pool_name option missing");
183 return;
184 }
185 MessageDelayPool::Pointer pool = MessageDelayPools::Instance()->pool(SBuf(token));
186 static ConfigParser parser;
187 if (pool)
188 aclParseAccessLine("response_delay_pool_access", parser, &pool->access);
189}
190
191void
192MessageDelayConfig::freePools()
193{
194 MessageDelayPools::Instance()->freePools();
195}
196
197void
198MessageDelayConfig::dumpResponseDelayPoolParameters(StoreEntry *entry, const char *name)
199{
200 auto &pools = MessageDelayPools::Instance()->pools;
201 for (auto pool: pools)
202 pool->dump(entry);
203}
204
205#endif
206