]> git.ipfire.org Git - thirdparty/squid.git/blob - src/MessageDelayPools.cc
Source Format Enforcement (#532)
[thirdparty/squid.git] / src / MessageDelayPools.cc
1 /*
2 * Copyright (C) 1996-2020 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
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
26 MessageDelayPools::~MessageDelayPools()
27 {
28 freePools();
29 }
30
31 MessageDelayPools *
32 MessageDelayPools::Instance()
33 {
34 static MessageDelayPools pools;
35 return &pools;
36 }
37
38 MessageDelayPool::Pointer
39 MessageDelayPools::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
46 void
47 MessageDelayPools::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
58 void
59 MessageDelayPools::freePools()
60 {
61 pools.clear();
62 }
63
64 MessageDelayPool::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
78 MessageDelayPool::~MessageDelayPool()
79 {
80 if (access)
81 aclDestroyAccessList(&access);
82 }
83
84 void
85 MessageDelayPool::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
99 void
100 MessageDelayPool::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
110 MessageBucket::Pointer
111 MessageDelayPool::createBucket()
112 {
113 return new MessageBucket(individualRestore, initialBucketLevel, individualMaximum, this);
114 }
115
116 void
117 MessageDelayConfig::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();
136 return;
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();
145 return;
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();
151 return;
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();
165 return;
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
178 void
179 MessageDelayConfig::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
191 void
192 MessageDelayConfig::freePools()
193 {
194 MessageDelayPools::Instance()->freePools();
195 }
196
197 void
198 MessageDelayConfig::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