Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/netwerk/dns/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 6 kB image not shown  

Quelle  HostRecordQueue.cpp

  Sprache: C
 

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "HostRecordQueue.h"
#include "mozilla/glean/NetwerkDnsMetrics.h"
#include "nsQueryObject.h"

namespace mozilla {
namespace net {

void HostRecordQueue::InsertRecord(nsHostRecord* aRec,
                                   nsIDNSService::DNSFlags aFlags) {
  if (aRec->isInList()) {
    MOZ_DIAGNOSTIC_ASSERT(!mEvictionQ.contains(aRec),
                          "Already in eviction queue");
    MOZ_DIAGNOSTIC_ASSERT(!mHighQ.contains(aRec), "Already in high queue");
    MOZ_DIAGNOSTIC_ASSERT(!mMediumQ.contains(aRec), "Already in med queue");
    MOZ_DIAGNOSTIC_ASSERT(!mLowQ.contains(aRec), "Already in low queue");
    MOZ_DIAGNOSTIC_CRASH("Already on some other queue?");
  }

  switch (AddrHostRecord::GetPriority(aFlags)) {
    case AddrHostRecord::DNS_PRIORITY_HIGH:
      mHighQ.insertBack(aRec);
      break;

    case AddrHostRecord::DNS_PRIORITY_MEDIUM:
      mMediumQ.insertBack(aRec);
      break;

    case AddrHostRecord::DNS_PRIORITY_LOW:
      mLowQ.insertBack(aRec);
      break;
  }
  mPendingCount++;
}

void HostRecordQueue::AddToEvictionQ(
    nsHostRecord* aRec, uint32_t aMaxCacheEntries,
    nsRefPtrHashtable<nsGenericHashKey<nsHostKey>, nsHostRecord>& aDB) {
  if (aRec->isInList()) {
    bool inEvictionQ = mEvictionQ.contains(aRec);
    MOZ_DIAGNOSTIC_ASSERT(!inEvictionQ, "Already in eviction queue");
    bool inHighQ = mHighQ.contains(aRec);
    MOZ_DIAGNOSTIC_ASSERT(!inHighQ, "Already in high queue");
    bool inMediumQ = mMediumQ.contains(aRec);
    MOZ_DIAGNOSTIC_ASSERT(!inMediumQ, "Already in med queue");
    bool inLowQ = mLowQ.contains(aRec);
    MOZ_DIAGNOSTIC_ASSERT(!inLowQ, "Already in low queue");
    MOZ_DIAGNOSTIC_CRASH("Already on some other queue?");

    // Bug 1678117 - it's not clear why this can happen, but let's fix it
    // for release users.
    aRec->remove();
    if (inEvictionQ) {
      MOZ_DIAGNOSTIC_ASSERT(mEvictionQSize > 0);
      mEvictionQSize--;
    } else if (inHighQ || inMediumQ || inLowQ) {
      MOZ_DIAGNOSTIC_ASSERT(mPendingCount > 0);
      mPendingCount--;
    }
  }
  mEvictionQ.insertBack(aRec);
  if (mEvictionQSize < aMaxCacheEntries) {
    mEvictionQSize++;
  } else {
    // remove first element on mEvictionQ
    RefPtr<nsHostRecord> head = mEvictionQ.popFirst();
    aDB.Remove(*static_cast<nsHostKey*>(head.get()));

    if (!head->negative) {
      // record the age of the entry upon eviction.
      TimeDuration age = TimeStamp::NowLoRes() - head->mValidStart;
      if (aRec->IsAddrRecord()) {
        glean::dns::cleanup_age.AccumulateRawDuration(age);
      } else {
        glean::dns::by_type_cleanup_age.AccumulateRawDuration(age);
      }
      if (head->CheckExpiration(TimeStamp::Now()) !=
          nsHostRecord::EXP_EXPIRED) {
        if (aRec->IsAddrRecord()) {
          glean::dns::premature_eviction.AccumulateRawDuration(age);
        } else {
          glean::dns::by_type_premature_eviction.AccumulateRawDuration(age);
        }
      }
    }
  }
}

void HostRecordQueue::MoveToEvictionQueueTail(nsHostRecord* aRec) {
  bool inEvictionQ = mEvictionQ.contains(aRec);
  if (!inEvictionQ) {
    // Note: this function can be called when the record isn't in the
    // mEvictionQ. For example, if we immediately start a TTL lookup (see
    // nsHostResolver::CompleteLookupLocked), the record may not be in
    // mEvictionQ.
    return;
  }

  aRec->remove();
  mEvictionQ.insertBack(aRec);
}

void HostRecordQueue::MaybeRenewHostRecord(nsHostRecord* aRec) {
  if (!aRec->isInList()) {
    return;
  }

  bool inEvictionQ = mEvictionQ.contains(aRec);
  MOZ_DIAGNOSTIC_ASSERT(inEvictionQ, "Should be in eviction queue");
  bool inHighQ = mHighQ.contains(aRec);
  MOZ_DIAGNOSTIC_ASSERT(!inHighQ, "Already in high queue");
  bool inMediumQ = mMediumQ.contains(aRec);
  MOZ_DIAGNOSTIC_ASSERT(!inMediumQ, "Already in med queue");
  bool inLowQ = mLowQ.contains(aRec);
  MOZ_DIAGNOSTIC_ASSERT(!inLowQ, "Already in low queue");

  // we're already on the eviction queue. This is a renewal
  aRec->remove();
  if (inEvictionQ) {
    MOZ_DIAGNOSTIC_ASSERT(mEvictionQSize > 0);
    mEvictionQSize--;
  } else if (inHighQ || inMediumQ || inLowQ) {
    MOZ_DIAGNOSTIC_ASSERT(mPendingCount > 0);
    mPendingCount--;
  }
}

void HostRecordQueue::FlushEvictionQ(
    nsRefPtrHashtable<nsGenericHashKey<nsHostKey>, nsHostRecord>& aDB) {
  mEvictionQSize = 0;

  // Clear the evictionQ and remove all its corresponding entries from
  // the cache first
  if (!mEvictionQ.isEmpty()) {
    for (const RefPtr<nsHostRecord>& rec : mEvictionQ) {
      rec->Cancel();
      aDB.Remove(*static_cast<nsHostKey*>(rec));
    }
    mEvictionQ.clear();
  }
}

void HostRecordQueue::MaybeRemoveFromQ(nsHostRecord* aRec) {
  if (!aRec->isInList()) {
    return;
  }

  if (mHighQ.contains(aRec) || mMediumQ.contains(aRec) ||
      mLowQ.contains(aRec)) {
    mPendingCount--;
  } else if (mEvictionQ.contains(aRec)) {
    mEvictionQSize--;
  } else {
    MOZ_ASSERT(false"record is in other queue");
  }

  aRec->remove();
}

void HostRecordQueue::MoveToAnotherPendingQ(nsHostRecord* aRec,
                                            nsIDNSService::DNSFlags aFlags) {
  if (!(mHighQ.contains(aRec) || mMediumQ.contains(aRec) ||
        mLowQ.contains(aRec))) {
    MOZ_ASSERT(false"record is not in the pending queue");
    return;
  }

  aRec->remove();
  // We just removed from pending queue. Insert record will
  // increment this value again.
  mPendingCount--;

  InsertRecord(aRec, aFlags);
}

already_AddRefed<nsHostRecord> HostRecordQueue::Dequeue(bool aHighQOnly) {
  RefPtr<nsHostRecord> rec;
  if (!mHighQ.isEmpty()) {
    rec = mHighQ.popFirst();
  } else if (!mMediumQ.isEmpty() && !aHighQOnly) {
    rec = mMediumQ.popFirst();
  } else if (!mLowQ.isEmpty() && !aHighQOnly) {
    rec = mLowQ.popFirst();
  }

  if (rec) {
    mPendingCount--;
  }

  return rec.forget();
}

void HostRecordQueue::ClearAll(
    const std::function<void(nsHostRecord*)>& aCallback) {
  mPendingCount = 0;

  auto clearPendingQ = [&](LinkedList<RefPtr<nsHostRecord>>& aPendingQ) {
    if (aPendingQ.isEmpty()) {
      return;
    }

    // loop through pending queue, erroring out pending lookups.
    for (const RefPtr<nsHostRecord>& rec : aPendingQ) {
      rec->Cancel();
      aCallback(rec);
    }
    aPendingQ.clear();
  };

  clearPendingQ(mHighQ);
  clearPendingQ(mMediumQ);
  clearPendingQ(mLowQ);

  mEvictionQSize = 0;
  if (!mEvictionQ.isEmpty()) {
    for (const RefPtr<nsHostRecord>& rec : mEvictionQ) {
      rec->Cancel();
    }
  }

  mEvictionQ.clear();
}

}  // namespace net
}  // namespace mozilla

Messung V0.5 in Prozent
C=89 H=94 G=91

¤ Dauer der Verarbeitung: 0.16 Sekunden  (vorverarbeitet am  2026-08-25) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.