Add LockedRingBuffer
This is a refactor for DnsQueryLog. No functional behavior change.
Bug: 79727473
Test: resolv_unit_test passed
Test: adb shell dumpsys dnsresolver querylog
Change-Id: Id9fc9b7868dab5861feda5ab2cb04759e7a34846
diff --git a/DnsQueryLog.cpp b/DnsQueryLog.cpp
index 6f0e179..b9f6f80 100644
--- a/DnsQueryLog.cpp
+++ b/DnsQueryLog.cpp
@@ -59,11 +59,7 @@
} // namespace
void DnsQueryLog::push(Record&& record) {
- std::lock_guard guard(mLock);
- mQueue.push_back(std::move(record));
- if (mQueue.size() > mCapacity) {
- mQueue.pop_front();
- }
+ mQueue.push(std::move(record));
}
void DnsQueryLog::dump(netdutils::DumpWriter& dw) const {
@@ -71,8 +67,7 @@
netdutils::ScopedIndent indentStats(dw);
const auto now = std::chrono::system_clock::now();
- std::lock_guard guard(mLock);
- for (const auto& record : mQueue) {
+ for (const auto& record : mQueue.copy()) {
if (now - record.timestamp > mValidityTimeMs) continue;
const std::string maskedHostname = maskHostname(record.hostname);
diff --git a/DnsQueryLog.h b/DnsQueryLog.h
index c19f8db..3e6478e 100644
--- a/DnsQueryLog.h
+++ b/DnsQueryLog.h
@@ -17,16 +17,16 @@
#pragma once
-#include <deque>
#include <string>
#include <vector>
-#include <android-base/thread_annotations.h>
#include <netdutils/DumpWriter.h>
+#include "LockedQueue.h"
+
namespace android::net {
-// A circular buffer based class used for query logging. It's thread-safe for concurrent access.
+// This class stores query records in a locked ring buffer. It's thread-safe for concurrent access.
class DnsQueryLog {
public:
static constexpr std::string_view DUMP_KEYWORD = "querylog";
@@ -52,15 +52,13 @@
// Allow the tests to set the capacity and the validaty time in milliseconds.
DnsQueryLog(size_t size = kDefaultLogSize,
std::chrono::milliseconds time = kDefaultValidityMinutes)
- : mCapacity(size), mValidityTimeMs(time) {}
+ : mQueue(size), mValidityTimeMs(time) {}
- void push(Record&& record) EXCLUDES(mLock);
- void dump(netdutils::DumpWriter& dw) const EXCLUDES(mLock);
+ void push(Record&& record);
+ void dump(netdutils::DumpWriter& dw) const;
private:
- mutable std::mutex mLock;
- std::deque<Record> mQueue GUARDED_BY(mLock);
- const size_t mCapacity;
+ LockedRingBuffer<Record> mQueue;
const std::chrono::milliseconds mValidityTimeMs;
// The capacity of the circular buffer.
diff --git a/LockedQueue.h b/LockedQueue.h
index 0481eda..8694f2d 100644
--- a/LockedQueue.h
+++ b/LockedQueue.h
@@ -46,6 +46,30 @@
std::deque<T> mQueue GUARDED_BY(mLock);
};
+template <typename T>
+class LockedRingBuffer {
+ public:
+ explicit LockedRingBuffer(size_t size) : mCapacity(size) {}
+
+ void push(T&& record) {
+ std::lock_guard guard(mLock);
+ mQueue.push_back(std::move(record));
+ if (mQueue.size() > mCapacity) {
+ mQueue.pop_front();
+ }
+ }
+
+ std::deque<T> copy() const {
+ std::lock_guard guard(mLock);
+ return mQueue;
+ }
+
+ private:
+ mutable std::mutex mLock;
+ const size_t mCapacity;
+ std::deque<T> mQueue GUARDED_BY(mLock);
+};
+
} // end of namespace net
} // end of namespace android