]> git.ipfire.org Git - thirdparty/squid.git/blob - src/DelayUser.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / DelayUser.cc
1 /*
2 * Copyright (C) 1996-2015 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 /* DEBUG: section 77 Delay Pools */
10
11 #include "squid.h"
12
13 #if USE_DELAY_POOLS && USE_AUTH
14 #include "auth/User.h"
15 #include "auth/UserRequest.h"
16 #include "comm/Connection.h"
17 #include "DelayUser.h"
18 #include "NullDelayId.h"
19 #include "Store.h"
20
21 void *
22 DelayUser::operator new(size_t size)
23 {
24 DelayPools::MemoryUsed += sizeof (DelayUser);
25 return ::operator new (size);
26 }
27
28 void
29 DelayUser::operator delete (void *address)
30 {
31 DelayPools::MemoryUsed -= sizeof (DelayUser);
32 ::operator delete (address);
33 }
34
35 DelayUser::DelayUser()
36 {
37 DelayPools::registerForUpdates (this);
38 }
39
40 static Splay<DelayUserBucket::Pointer>::SPLAYFREE DelayUserFree;
41
42 DelayUser::~DelayUser()
43 {
44 DelayPools::deregisterForUpdates (this);
45 buckets.destroy(DelayUserFree);
46 }
47
48 static Splay<DelayUserBucket::Pointer>::SPLAYCMP DelayUserCmp;
49
50 int
51 DelayUserCmp(DelayUserBucket::Pointer const &left, DelayUserBucket::Pointer const &right)
52 {
53 /* Verify for re-currance of Bug 2127. either of these missing will crash strcasecmp() */
54 assert(left->authUser->username() != NULL);
55 assert(right->authUser->username() != NULL);
56
57 /* for rate limiting, case insensitive */
58 return strcasecmp(left->authUser->username(), right->authUser->username());
59 }
60
61 void
62 DelayUserFree(DelayUserBucket::Pointer &)
63 {}
64
65 void
66 DelayUserStatsWalkee(DelayUserBucket::Pointer const &current, void *state)
67 {
68 current->stats ((StoreEntry *)state);
69 }
70
71 struct DelayUserStatsVisitor {
72 StoreEntry *se;
73 explicit DelayUserStatsVisitor(StoreEntry *s) : se(s) {}
74 void operator() (DelayUserBucket::Pointer const &current) {
75 current->stats(se);
76 }
77 };
78
79 void
80 DelayUser::stats(StoreEntry * sentry)
81 {
82 spec.stats (sentry, "Per User");
83
84 if (spec.restore_bps == -1)
85 return;
86
87 storeAppendPrintf(sentry, "\t\tCurrent: ");
88
89 if (buckets.empty()) {
90 storeAppendPrintf (sentry, "Not used yet.\n\n");
91 return;
92 }
93
94 DelayUserStatsVisitor visitor(sentry);
95 buckets.visit(visitor);
96 storeAppendPrintf(sentry, "\n\n");
97 }
98
99 void
100 DelayUser::dump(StoreEntry *entry) const
101 {
102 spec.dump(entry);
103 }
104
105 struct DelayUserUpdater {
106 DelayUserUpdater (DelaySpec &_spec, int _incr):spec(_spec),incr(_incr) {};
107
108 DelaySpec spec;
109 int incr;
110 };
111
112 void
113 DelayUserUpdateWalkee(DelayUserBucket::Pointer const &current, void *state)
114 {
115 DelayUserUpdater *t = (DelayUserUpdater *)state;
116 /* This doesn't change the value of the DelayUserBucket, so is safe */
117 const_cast<DelayUserBucket *>(current.getRaw())->theBucket.update(t->spec, t->incr);
118 }
119
120 struct DelayUserUpdateVisitor {
121 DelayUserUpdater *t;
122 DelayUserUpdateVisitor(DelayUserUpdater *updater) : t(updater) {}
123 void operator() (DelayUserBucket::Pointer const &current) {
124 const_cast<DelayUserBucket *>(current.getRaw())->theBucket.update(t->spec, t->incr);
125 }
126 };
127
128 void
129 DelayUser::update(int incr)
130 {
131 DelayUserUpdater updater(spec, incr);
132 DelayUserUpdateVisitor visitor(&updater);
133 buckets.visit(visitor);
134 }
135
136 void
137 DelayUser::parse()
138 {
139 spec.parse();
140 }
141
142 DelayIdComposite::Pointer
143 DelayUser::id(CompositePoolNode::CompositeSelectionDetails &details)
144 {
145 if (!details.user || !details.user->user() || !details.user->user()->username())
146 return new NullDelayId;
147
148 debugs(77, 3, HERE << "Adding a slow-down for User '" << details.user->user()->username() << "'");
149 return new Id(this, details.user->user());
150 }
151
152 void *
153 DelayUser::Id::operator new(size_t size)
154 {
155 DelayPools::MemoryUsed += sizeof (Id);
156 return ::operator new (size);
157 }
158
159 void
160 DelayUser::Id::operator delete (void *address)
161 {
162 DelayPools::MemoryUsed -= sizeof (Id);
163 ::operator delete (address);
164 }
165
166 void *
167 DelayUserBucket::operator new(size_t size)
168 {
169 DelayPools::MemoryUsed += sizeof (DelayUserBucket);
170 return ::operator new (size);
171 }
172
173 void
174 DelayUserBucket::operator delete(void *address)
175 {
176 DelayPools::MemoryUsed -= sizeof(DelayUserBucket);
177 ::operator delete(address);
178 }
179
180 DelayUserBucket::DelayUserBucket(Auth::User::Pointer aUser) : authUser(aUser)
181 {
182 debugs(77, 3, "DelayUserBucket::DelayUserBucket");
183 }
184
185 DelayUserBucket::~DelayUserBucket()
186 {
187 authUser = NULL;
188 debugs(77, 3, "DelayUserBucket::~DelayUserBucket");
189 }
190
191 void
192 DelayUserBucket::stats (StoreEntry *entry) const
193 {
194 storeAppendPrintf(entry, " %s:", authUser->username());
195 theBucket.stats(entry);
196 }
197
198 DelayUser::Id::Id(DelayUser::Pointer aDelayUser, Auth::User::Pointer aUser) : theUser(aDelayUser)
199 {
200 theBucket = new DelayUserBucket(aUser);
201 DelayUserBucket::Pointer const *existing = theUser->buckets.find(theBucket, DelayUserCmp);
202
203 if (existing) {
204 theBucket = *existing;
205 return;
206 }
207
208 theBucket->theBucket.init(theUser->spec);
209 theUser->buckets.insert (theBucket, DelayUserCmp);
210 }
211
212 DelayUser::Id::~Id()
213 {
214 debugs(77, 3, "DelayUser::Id::~Id");
215 }
216
217 int
218 DelayUser::Id::bytesWanted (int min, int max) const
219 {
220 return theBucket->theBucket.bytesWanted(min,max);
221 }
222
223 void
224 DelayUser::Id::bytesIn(int qty)
225 {
226 theBucket->theBucket.bytesIn(qty);
227 }
228
229 #endif /* USE_DELAY_POOLS && USE_AUTH */
230