Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames M Snell <jasnell@gmail.com>2020-08-03 21:36:49 +0300
committerJames M Snell <jasnell@gmail.com>2020-08-10 17:52:03 +0300
commit6d1f0aed52b890e4f4bfa2281894df4d423cf1c6 (patch)
tree99c75e6e4ca8ff4f5fef67454dd20aae5d32036b /src/node_sockaddr-inl.h
parent6b0b33cd4ca647865457be2199c31b16bab14648 (diff)
src: add SocketAddressLRU Utility
Adds a LRU cache for information associated with a SocketAddress. PR-URL: https://github.com/nodejs/node/pull/34618 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Rich Trott <rtrott@gmail.com>
Diffstat (limited to 'src/node_sockaddr-inl.h')
-rw-r--r--src/node_sockaddr-inl.h67
1 files changed, 67 insertions, 0 deletions
diff --git a/src/node_sockaddr-inl.h b/src/node_sockaddr-inl.h
index a9d0ed061a1..c8b985aedda 100644
--- a/src/node_sockaddr-inl.h
+++ b/src/node_sockaddr-inl.h
@@ -7,6 +7,7 @@
#include "node_internals.h"
#include "node_sockaddr.h"
#include "util-inl.h"
+#include "memory_tracker-inl.h"
#include <string>
@@ -164,6 +165,72 @@ bool SocketAddress::operator==(const SocketAddress& other) const {
bool SocketAddress::operator!=(const SocketAddress& other) const {
return !(*this == other);
}
+
+template <typename T>
+SocketAddressLRU<T>::SocketAddressLRU(
+ size_t max_size)
+ : max_size_(max_size) {}
+
+template <typename T>
+typename T::Type* SocketAddressLRU<T>::Peek(
+ const SocketAddress& address) const {
+ auto it = map_.find(address);
+ return it == std::end(map_) ? nullptr : &it->second->second;
+}
+
+template <typename T>
+void SocketAddressLRU<T>::CheckExpired() {
+ auto it = list_.rbegin();
+ while (it != list_.rend()) {
+ if (T::CheckExpired(it->first, it->second)) {
+ map_.erase(it->first);
+ list_.pop_back();
+ it = list_.rbegin();
+ continue;
+ } else {
+ break;
+ }
+ }
+}
+
+template <typename T>
+void SocketAddressLRU<T>::MemoryInfo(MemoryTracker* tracker) const {
+ tracker->TrackFieldWithSize("list", size() * sizeof(Pair));
+}
+
+// If an item already exists for the given address, bump up it's
+// position in the LRU list and return it. If the item does not
+// exist, create it. If an item is created, check the size of the
+// cache and adjust if necessary. Whether the item exists or not,
+// purge expired items.
+template <typename T>
+typename T::Type* SocketAddressLRU<T>::Upsert(
+ const SocketAddress& address) {
+
+ auto on_exit = OnScopeLeave([&]() { CheckExpired(); });
+
+ auto it = map_.find(address);
+ if (it != std::end(map_)) {
+ list_.splice(list_.begin(), list_, it->second);
+ T::Touch(it->first, &it->second->second);
+ return &it->second->second;
+ }
+
+ list_.push_front(Pair(address, { }));
+ map_[address] = list_.begin();
+ T::Touch(list_.begin()->first, &list_.begin()->second);
+
+ // Drop the last item in the list if we are
+ // over the size limit...
+ if (map_.size() > max_size_) {
+ auto last = list_.end();
+ map_.erase((--last)->first);
+ list_.pop_back();
+ }
+
+ return &map_[address]->second;
+}
+
} // namespace node
#endif // NODE_WANT_INTERNALS