Bug 1890277: part 4) Add CSPParser support for the `trusted-types` directive, guarded...
[gecko.git] / netwerk / dns / HostRecordQueue.cpp
blobc4ec4bc58549cceb264c2f757332176c26d05aca
1 /* vim:set ts=4 sw=2 sts=2 et cin: */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "HostRecordQueue.h"
7 #include "mozilla/Telemetry.h"
8 #include "nsQueryObject.h"
10 namespace mozilla {
11 namespace net {
13 void HostRecordQueue::InsertRecord(nsHostRecord* aRec,
14 nsIDNSService::DNSFlags aFlags,
15 const MutexAutoLock& aProofOfLock) {
16 if (aRec->isInList()) {
17 MOZ_DIAGNOSTIC_ASSERT(!mEvictionQ.contains(aRec),
18 "Already in eviction queue");
19 MOZ_DIAGNOSTIC_ASSERT(!mHighQ.contains(aRec), "Already in high queue");
20 MOZ_DIAGNOSTIC_ASSERT(!mMediumQ.contains(aRec), "Already in med queue");
21 MOZ_DIAGNOSTIC_ASSERT(!mLowQ.contains(aRec), "Already in low queue");
22 MOZ_DIAGNOSTIC_ASSERT(false, "Already on some other queue?");
25 switch (AddrHostRecord::GetPriority(aFlags)) {
26 case AddrHostRecord::DNS_PRIORITY_HIGH:
27 mHighQ.insertBack(aRec);
28 break;
30 case AddrHostRecord::DNS_PRIORITY_MEDIUM:
31 mMediumQ.insertBack(aRec);
32 break;
34 case AddrHostRecord::DNS_PRIORITY_LOW:
35 mLowQ.insertBack(aRec);
36 break;
38 mPendingCount++;
41 void HostRecordQueue::AddToEvictionQ(
42 nsHostRecord* aRec, uint32_t aMaxCacheEntries,
43 nsRefPtrHashtable<nsGenericHashKey<nsHostKey>, nsHostRecord>& aDB,
44 const MutexAutoLock& aProofOfLock) {
45 if (aRec->isInList()) {
46 bool inEvictionQ = mEvictionQ.contains(aRec);
47 MOZ_DIAGNOSTIC_ASSERT(!inEvictionQ, "Already in eviction queue");
48 bool inHighQ = mHighQ.contains(aRec);
49 MOZ_DIAGNOSTIC_ASSERT(!inHighQ, "Already in high queue");
50 bool inMediumQ = mMediumQ.contains(aRec);
51 MOZ_DIAGNOSTIC_ASSERT(!inMediumQ, "Already in med queue");
52 bool inLowQ = mLowQ.contains(aRec);
53 MOZ_DIAGNOSTIC_ASSERT(!inLowQ, "Already in low queue");
54 MOZ_DIAGNOSTIC_ASSERT(false, "Already on some other queue?");
56 // Bug 1678117 - it's not clear why this can happen, but let's fix it
57 // for release users.
58 aRec->remove();
59 if (inEvictionQ) {
60 MOZ_DIAGNOSTIC_ASSERT(mEvictionQSize > 0);
61 mEvictionQSize--;
62 } else if (inHighQ || inMediumQ || inLowQ) {
63 MOZ_DIAGNOSTIC_ASSERT(mPendingCount > 0);
64 mPendingCount--;
67 mEvictionQ.insertBack(aRec);
68 if (mEvictionQSize < aMaxCacheEntries) {
69 mEvictionQSize++;
70 } else {
71 // remove first element on mEvictionQ
72 RefPtr<nsHostRecord> head = mEvictionQ.popFirst();
73 aDB.Remove(*static_cast<nsHostKey*>(head.get()));
75 if (!head->negative) {
76 // record the age of the entry upon eviction.
77 TimeDuration age = TimeStamp::NowLoRes() - head->mValidStart;
78 if (aRec->IsAddrRecord()) {
79 Telemetry::Accumulate(Telemetry::DNS_CLEANUP_AGE,
80 static_cast<uint32_t>(age.ToSeconds() / 60));
81 } else {
82 Telemetry::Accumulate(Telemetry::DNS_BY_TYPE_CLEANUP_AGE,
83 static_cast<uint32_t>(age.ToSeconds() / 60));
85 if (head->CheckExpiration(TimeStamp::Now()) !=
86 nsHostRecord::EXP_EXPIRED) {
87 if (aRec->IsAddrRecord()) {
88 Telemetry::Accumulate(Telemetry::DNS_PREMATURE_EVICTION,
89 static_cast<uint32_t>(age.ToSeconds() / 60));
90 } else {
91 Telemetry::Accumulate(Telemetry::DNS_BY_TYPE_PREMATURE_EVICTION,
92 static_cast<uint32_t>(age.ToSeconds() / 60));
99 void HostRecordQueue::MaybeRenewHostRecord(nsHostRecord* aRec,
100 const MutexAutoLock& aProofOfLock) {
101 if (!aRec->isInList()) {
102 return;
105 bool inEvictionQ = mEvictionQ.contains(aRec);
106 MOZ_DIAGNOSTIC_ASSERT(inEvictionQ, "Should be in eviction queue");
107 bool inHighQ = mHighQ.contains(aRec);
108 MOZ_DIAGNOSTIC_ASSERT(!inHighQ, "Already in high queue");
109 bool inMediumQ = mMediumQ.contains(aRec);
110 MOZ_DIAGNOSTIC_ASSERT(!inMediumQ, "Already in med queue");
111 bool inLowQ = mLowQ.contains(aRec);
112 MOZ_DIAGNOSTIC_ASSERT(!inLowQ, "Already in low queue");
114 // we're already on the eviction queue. This is a renewal
115 aRec->remove();
116 if (inEvictionQ) {
117 MOZ_DIAGNOSTIC_ASSERT(mEvictionQSize > 0);
118 mEvictionQSize--;
119 } else if (inHighQ || inMediumQ || inLowQ) {
120 MOZ_DIAGNOSTIC_ASSERT(mPendingCount > 0);
121 mPendingCount--;
125 void HostRecordQueue::FlushEvictionQ(
126 nsRefPtrHashtable<nsGenericHashKey<nsHostKey>, nsHostRecord>& aDB,
127 const MutexAutoLock& aProofOfLock) {
128 mEvictionQSize = 0;
130 // Clear the evictionQ and remove all its corresponding entries from
131 // the cache first
132 if (!mEvictionQ.isEmpty()) {
133 for (const RefPtr<nsHostRecord>& rec : mEvictionQ) {
134 rec->Cancel();
135 aDB.Remove(*static_cast<nsHostKey*>(rec));
137 mEvictionQ.clear();
141 void HostRecordQueue::MaybeRemoveFromQ(nsHostRecord* aRec,
142 const MutexAutoLock& aProofOfLock) {
143 if (!aRec->isInList()) {
144 return;
147 if (mHighQ.contains(aRec) || mMediumQ.contains(aRec) ||
148 mLowQ.contains(aRec)) {
149 mPendingCount--;
150 } else if (mEvictionQ.contains(aRec)) {
151 mEvictionQSize--;
152 } else {
153 MOZ_ASSERT(false, "record is in other queue");
156 aRec->remove();
159 void HostRecordQueue::MoveToAnotherPendingQ(nsHostRecord* aRec,
160 nsIDNSService::DNSFlags aFlags,
161 const MutexAutoLock& aProofOfLock) {
162 if (!(mHighQ.contains(aRec) || mMediumQ.contains(aRec) ||
163 mLowQ.contains(aRec))) {
164 MOZ_ASSERT(false, "record is not in the pending queue");
165 return;
168 aRec->remove();
169 // We just removed from pending queue. Insert record will
170 // increment this value again.
171 mPendingCount--;
173 InsertRecord(aRec, aFlags, aProofOfLock);
176 already_AddRefed<nsHostRecord> HostRecordQueue::Dequeue(
177 bool aHighQOnly, const MutexAutoLock& aProofOfLock) {
178 RefPtr<nsHostRecord> rec;
179 if (!mHighQ.isEmpty()) {
180 rec = mHighQ.popFirst();
181 } else if (!mMediumQ.isEmpty() && !aHighQOnly) {
182 rec = mMediumQ.popFirst();
183 } else if (!mLowQ.isEmpty() && !aHighQOnly) {
184 rec = mLowQ.popFirst();
187 if (rec) {
188 mPendingCount--;
191 return rec.forget();
194 void HostRecordQueue::ClearAll(
195 const std::function<void(nsHostRecord*)>& aCallback,
196 const MutexAutoLock& aProofOfLock) {
197 mPendingCount = 0;
199 auto clearPendingQ = [&](LinkedList<RefPtr<nsHostRecord>>& aPendingQ) {
200 if (aPendingQ.isEmpty()) {
201 return;
204 // loop through pending queue, erroring out pending lookups.
205 for (const RefPtr<nsHostRecord>& rec : aPendingQ) {
206 rec->Cancel();
207 aCallback(rec);
209 aPendingQ.clear();
212 clearPendingQ(mHighQ);
213 clearPendingQ(mMediumQ);
214 clearPendingQ(mLowQ);
216 mEvictionQSize = 0;
217 if (!mEvictionQ.isEmpty()) {
218 for (const RefPtr<nsHostRecord>& rec : mEvictionQ) {
219 rec->Cancel();
223 mEvictionQ.clear();
226 } // namespace net
227 } // namespace mozilla