2 * Copyright (C) 1996-2022 The Squid Software Foundation and contributors
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.
9 /* DEBUG: section 77 Delay Pools */
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"
21 DelayUser::DelayUser()
23 DelayPools::registerForUpdates (this);
26 static Splay
<DelayUserBucket::Pointer
>::SPLAYFREE DelayUserFree
;
28 DelayUser::~DelayUser()
30 DelayPools::deregisterForUpdates (this);
31 buckets
.destroy(DelayUserFree
);
34 static Splay
<DelayUserBucket::Pointer
>::SPLAYCMP DelayUserCmp
;
37 DelayUserCmp(DelayUserBucket::Pointer
const &left
, DelayUserBucket::Pointer
const &right
)
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);
43 /* for rate limiting, case insensitive */
44 return strcasecmp(left
->authUser
->username(), right
->authUser
->username());
48 DelayUserFree(DelayUserBucket::Pointer
&)
51 struct DelayUserStatsVisitor
{
53 explicit DelayUserStatsVisitor(StoreEntry
*s
) : se(s
) {}
54 void operator() (DelayUserBucket::Pointer
const ¤t
) {
60 DelayUser::stats(StoreEntry
* sentry
)
62 spec
.stats (sentry
, "Per User");
64 if (spec
.restore_bps
== -1)
67 storeAppendPrintf(sentry
, "\t\tCurrent: ");
69 if (buckets
.empty()) {
70 storeAppendPrintf (sentry
, "Not used yet.\n\n");
74 DelayUserStatsVisitor
visitor(sentry
);
75 buckets
.visit(visitor
);
76 storeAppendPrintf(sentry
, "\n\n");
80 DelayUser::dump(StoreEntry
*entry
) const
85 struct DelayUserUpdater
{
86 DelayUserUpdater (DelaySpec
&_spec
, int _incr
):spec(_spec
),incr(_incr
) {};
92 struct DelayUserUpdateVisitor
{
94 DelayUserUpdateVisitor(DelayUserUpdater
*updater
) : t(updater
) {}
95 void operator() (DelayUserBucket::Pointer
const ¤t
) {
96 const_cast<DelayUserBucket
*>(current
.getRaw())->theBucket
.update(t
->spec
, t
->incr
);
101 DelayUser::update(int incr
)
103 DelayUserUpdater
updater(spec
, incr
);
104 DelayUserUpdateVisitor
visitor(&updater
);
105 buckets
.visit(visitor
);
114 DelayIdComposite::Pointer
115 DelayUser::id(CompositePoolNode::CompositeSelectionDetails
&details
)
117 if (!details
.user
|| !details
.user
->user() || !details
.user
->user()->username())
118 return new NullDelayId
;
120 debugs(77, 3, "Adding a slow-down for User '" << details
.user
->user()->username() << "'");
121 return new Id(this, details
.user
->user());
124 DelayUserBucket::DelayUserBucket(Auth::User::Pointer aUser
) : authUser(aUser
)
126 debugs(77, 3, "DelayUserBucket::DelayUserBucket");
129 DelayUserBucket::~DelayUserBucket()
132 debugs(77, 3, "DelayUserBucket::~DelayUserBucket");
136 DelayUserBucket::stats (StoreEntry
*entry
) const
138 storeAppendPrintf(entry
, " %s:", authUser
->username());
139 theBucket
.stats(entry
);
142 DelayUser::Id::Id(DelayUser::Pointer aDelayUser
, Auth::User::Pointer aUser
) : theUser(aDelayUser
)
144 theBucket
= new DelayUserBucket(aUser
);
145 DelayUserBucket::Pointer
const *existing
= theUser
->buckets
.find(theBucket
, DelayUserCmp
);
148 theBucket
= *existing
;
152 theBucket
->theBucket
.init(theUser
->spec
);
153 theUser
->buckets
.insert (theBucket
, DelayUserCmp
);
158 debugs(77, 3, "DelayUser::Id::~Id");
162 DelayUser::Id::bytesWanted (int min
, int max
) const
164 return theBucket
->theBucket
.bytesWanted(min
,max
);
168 DelayUser::Id::bytesIn(int qty
)
170 theBucket
->theBucket
.bytesIn(qty
);
173 #endif /* USE_DELAY_POOLS && USE_AUTH */