]> git.ipfire.org Git - thirdparty/squid.git/blob - src/DelayUser.cc
Maintenance: Removed most NULLs using modernize-use-nullptr (#1075)
[thirdparty/squid.git] / src / DelayUser.cc
1 /*
2 * Copyright (C) 1996-2022 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 DelayUser::DelayUser()
22 {
23 DelayPools::registerForUpdates (this);
24 }
25
26 static Splay<DelayUserBucket::Pointer>::SPLAYFREE DelayUserFree;
27
28 DelayUser::~DelayUser()
29 {
30 DelayPools::deregisterForUpdates (this);
31 buckets.destroy(DelayUserFree);
32 }
33
34 static Splay<DelayUserBucket::Pointer>::SPLAYCMP DelayUserCmp;
35
36 int
37 DelayUserCmp(DelayUserBucket::Pointer const &left, DelayUserBucket::Pointer const &right)
38 {
39 /* Verify for re-currance of Bug 2127. either of these missing will crash strcasecmp() */
40 assert(left->authUser->username() != nullptr);
41 assert(right->authUser->username() != nullptr);
42
43 /* for rate limiting, case insensitive */
44 return strcasecmp(left->authUser->username(), right->authUser->username());
45 }
46
47 void
48 DelayUserFree(DelayUserBucket::Pointer &)
49 {}
50
51 struct DelayUserStatsVisitor {
52 StoreEntry *se;
53 explicit DelayUserStatsVisitor(StoreEntry *s) : se(s) {}
54 void operator() (DelayUserBucket::Pointer const &current) {
55 current->stats(se);
56 }
57 };
58
59 void
60 DelayUser::stats(StoreEntry * sentry)
61 {
62 spec.stats (sentry, "Per User");
63
64 if (spec.restore_bps == -1)
65 return;
66
67 storeAppendPrintf(sentry, "\t\tCurrent: ");
68
69 if (buckets.empty()) {
70 storeAppendPrintf (sentry, "Not used yet.\n\n");
71 return;
72 }
73
74 DelayUserStatsVisitor visitor(sentry);
75 buckets.visit(visitor);
76 storeAppendPrintf(sentry, "\n\n");
77 }
78
79 void
80 DelayUser::dump(StoreEntry *entry) const
81 {
82 spec.dump(entry);
83 }
84
85 struct DelayUserUpdater {
86 DelayUserUpdater (DelaySpec &_spec, int _incr):spec(_spec),incr(_incr) {};
87
88 DelaySpec spec;
89 int incr;
90 };
91
92 struct DelayUserUpdateVisitor {
93 DelayUserUpdater *t;
94 DelayUserUpdateVisitor(DelayUserUpdater *updater) : t(updater) {}
95 void operator() (DelayUserBucket::Pointer const &current) {
96 const_cast<DelayUserBucket *>(current.getRaw())->theBucket.update(t->spec, t->incr);
97 }
98 };
99
100 void
101 DelayUser::update(int incr)
102 {
103 DelayUserUpdater updater(spec, incr);
104 DelayUserUpdateVisitor visitor(&updater);
105 buckets.visit(visitor);
106 }
107
108 void
109 DelayUser::parse()
110 {
111 spec.parse();
112 }
113
114 DelayIdComposite::Pointer
115 DelayUser::id(CompositePoolNode::CompositeSelectionDetails &details)
116 {
117 if (!details.user || !details.user->user() || !details.user->user()->username())
118 return new NullDelayId;
119
120 debugs(77, 3, "Adding a slow-down for User '" << details.user->user()->username() << "'");
121 return new Id(this, details.user->user());
122 }
123
124 DelayUserBucket::DelayUserBucket(Auth::User::Pointer aUser) : authUser(aUser)
125 {
126 debugs(77, 3, "DelayUserBucket::DelayUserBucket");
127 }
128
129 DelayUserBucket::~DelayUserBucket()
130 {
131 authUser = nullptr;
132 debugs(77, 3, "DelayUserBucket::~DelayUserBucket");
133 }
134
135 void
136 DelayUserBucket::stats (StoreEntry *entry) const
137 {
138 storeAppendPrintf(entry, " %s:", authUser->username());
139 theBucket.stats(entry);
140 }
141
142 DelayUser::Id::Id(DelayUser::Pointer aDelayUser, Auth::User::Pointer aUser) : theUser(aDelayUser)
143 {
144 theBucket = new DelayUserBucket(aUser);
145 DelayUserBucket::Pointer const *existing = theUser->buckets.find(theBucket, DelayUserCmp);
146
147 if (existing) {
148 theBucket = *existing;
149 return;
150 }
151
152 theBucket->theBucket.init(theUser->spec);
153 theUser->buckets.insert (theBucket, DelayUserCmp);
154 }
155
156 DelayUser::Id::~Id()
157 {
158 debugs(77, 3, "DelayUser::Id::~Id");
159 }
160
161 int
162 DelayUser::Id::bytesWanted (int min, int max) const
163 {
164 return theBucket->theBucket.bytesWanted(min,max);
165 }
166
167 void
168 DelayUser::Id::bytesIn(int qty)
169 {
170 theBucket->theBucket.bytesIn(qty);
171 }
172
173 #endif /* USE_DELAY_POOLS && USE_AUTH */
174