blob: 3291bdab3dca065acc356b21b96ac92768ae03c5 [file] [log] [blame]
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -05001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Junxiao Shi5e4a02f2019-07-15 11:59:18 +00002/*
Davide Pesaventoae430302023-05-11 01:42:46 -04003 * Copyright (c) 2014-2023, Regents of the University of California,
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -05004 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology,
9 * The University of Memphis.
10 *
11 * This file is part of NFD (Named Data Networking Forwarding Daemon).
12 * See AUTHORS.md for complete list of NFD authors and contributors.
13 *
14 * NFD is free software: you can redistribute it and/or modify it under the terms
15 * of the GNU General Public License as published by the Free Software Foundation,
16 * either version 3 of the License, or (at your option) any later version.
17 *
18 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20 * PURPOSE. See the GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
24 */
25
26#ifndef NFD_DAEMON_TABLE_CS_POLICY_HPP
27#define NFD_DAEMON_TABLE_CS_POLICY_HPP
28
Junxiao Shi5e4a02f2019-07-15 11:59:18 +000029#include "cs-entry.hpp"
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -050030
Davide Pesaventoe422f9e2022-06-03 01:30:23 -040031namespace nfd::cs {
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -050032
33class Cs;
34
Davide Pesaventoa3a7a4e2022-05-29 16:06:22 -040035/**
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -040036 * \brief Represents a CS replacement policy.
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -050037 */
38class Policy : noncopyable
39{
Junxiao Shi52555b02016-11-25 21:39:06 +000040public: // registry
41 template<typename P>
42 static void
Davide Pesaventoae430302023-05-11 01:42:46 -040043 registerPolicy(std::string_view policyName = P::POLICY_NAME)
Junxiao Shi52555b02016-11-25 21:39:06 +000044 {
Davide Pesaventoa3a7a4e2022-05-29 16:06:22 -040045 BOOST_ASSERT(!policyName.empty());
Davide Pesaventoae430302023-05-11 01:42:46 -040046 auto r = getRegistry().insert_or_assign(std::string(policyName), [] { return make_unique<P>(); });
Davide Pesaventoa3a7a4e2022-05-29 16:06:22 -040047 BOOST_VERIFY(r.second);
Junxiao Shi52555b02016-11-25 21:39:06 +000048 }
49
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -040050 /**
51 * \brief Returns a cs::Policy identified by \p policyName,
52 * or nullptr if \p policyName is unknown.
Junxiao Shi52555b02016-11-25 21:39:06 +000053 */
54 static unique_ptr<Policy>
Junxiao Shi7ee00fb2016-12-04 21:23:00 +000055 create(const std::string& policyName);
56
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -040057 /**
58 * \brief Returns a list of available policy names.
Junxiao Shi7ee00fb2016-12-04 21:23:00 +000059 */
60 static std::set<std::string>
61 getPolicyNames();
Junxiao Shi52555b02016-11-25 21:39:06 +000062
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -050063public:
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -050064 virtual
Junxiao Shi2af9ca32016-08-25 21:51:02 +000065 ~Policy() = default;
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -050066
67 const std::string&
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -040068 getName() const noexcept
Junxiao Shi5e4a02f2019-07-15 11:59:18 +000069 {
70 return m_policyName;
71 }
72
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -040073 /**
74 * \brief Returns a pointer to the associated CS instance.
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -050075 */
76 Cs*
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -040077 getCs() const noexcept
Junxiao Shi5e4a02f2019-07-15 11:59:18 +000078 {
79 return m_cs;
80 }
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -050081
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -040082 /**
83 * \brief Sets the associated CS instance.
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -050084 */
85 void
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -040086 setCs(Cs* cs) noexcept
Junxiao Shi5e4a02f2019-07-15 11:59:18 +000087 {
88 m_cs = cs;
89 }
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -050090
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -040091 /**
92 * \brief Gets hard limit (in number of entries).
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -050093 */
94 size_t
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -040095 getLimit() const noexcept
Junxiao Shi5e4a02f2019-07-15 11:59:18 +000096 {
97 return m_limit;
98 }
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -050099
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -0400100 /** \brief Sets hard limit (in number of entries).
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -0500101 * \post getLimit() == nMaxEntries
102 * \post cs.size() <= getLimit()
103 *
104 * The policy may evict entries if necessary.
105 */
106 void
107 setLimit(size_t nMaxEntries);
108
Junxiao Shi07f2e2f2019-07-22 09:10:06 -0600109public:
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -0400110 /** \brief A reference to a CS entry.
111 * \note `operator<` of EntryRef compares the Data name enclosed in the Entry.
Junxiao Shi07f2e2f2019-07-22 09:10:06 -0600112 */
113 using EntryRef = Table::const_iterator;
114
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -0400115 /** \brief %Signal emitted when an entry is being evicted.
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -0500116 *
Junxiao Shi07f2e2f2019-07-22 09:10:06 -0600117 * A policy implementation should emit this signal to cause CS to erase an entry from its index.
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -0500118 * CS should connect to this signal and erase the entry upon signal emission.
119 */
Junxiao Shi07f2e2f2019-07-22 09:10:06 -0600120 signal::Signal<Policy, EntryRef> beforeEvict;
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -0500121
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -0400122 /** \brief Invoked by CS after a new entry is inserted.
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -0500123 * \post cs.size() <= getLimit()
124 *
125 * The policy may evict entries if necessary.
126 * During this process, \p i might be evicted.
127 */
128 void
Junxiao Shi07f2e2f2019-07-22 09:10:06 -0600129 afterInsert(EntryRef i);
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -0500130
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -0400131 /** \brief Invoked by CS after an existing entry is refreshed by same Data.
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -0500132 *
133 * The policy may witness this refresh to make better eviction decisions in the future.
134 */
135 void
Junxiao Shi07f2e2f2019-07-22 09:10:06 -0600136 afterRefresh(EntryRef i);
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -0500137
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -0400138 /** \brief Invoked by CS before an entry is erased due to management command.
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -0500139 * \warning CS must not invoke this method if an entry is erased due to eviction.
140 */
141 void
Junxiao Shi07f2e2f2019-07-22 09:10:06 -0600142 beforeErase(EntryRef i);
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -0500143
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -0400144 /** \brief Invoked by CS before an entry is used to match a lookup.
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -0500145 *
146 * The policy may witness this usage to make better eviction decisions in the future.
147 */
148 void
Junxiao Shi07f2e2f2019-07-22 09:10:06 -0600149 beforeUse(EntryRef i);
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -0500150
151protected:
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -0400152 /** \brief Invoked after a new entry is created in CS.
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -0500153 *
154 * When overridden in a subclass, a policy implementation should decide whether to accept \p i.
155 * If \p i is accepted, it should be inserted into a cleanup index.
156 * Otherwise, \p beforeEvict signal should be emitted with \p i to inform CS to erase the entry.
157 * A policy implementation may decide to evict other entries by emitting \p beforeEvict signal,
158 * in order to keep CS size under limit.
159 */
160 virtual void
Junxiao Shi07f2e2f2019-07-22 09:10:06 -0600161 doAfterInsert(EntryRef i) = 0;
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -0500162
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -0400163 /** \brief Invoked after an existing entry is refreshed by same Data.
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -0500164 *
165 * When overridden in a subclass, a policy implementation may witness this operation
166 * and adjust its cleanup index.
167 */
168 virtual void
Junxiao Shi07f2e2f2019-07-22 09:10:06 -0600169 doAfterRefresh(EntryRef i) = 0;
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -0500170
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -0400171 /** \brief Invoked before an entry is erased due to management command.
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -0500172 * \note This will not be invoked for an entry being evicted by policy.
173 *
174 * When overridden in a subclass, a policy implementation should erase \p i
175 * from its cleanup index without emitted \p afterErase signal.
176 */
177 virtual void
Junxiao Shi07f2e2f2019-07-22 09:10:06 -0600178 doBeforeErase(EntryRef i) = 0;
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -0500179
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -0400180 /** \brief Invoked before an entry is used to match a lookup.
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -0500181 *
182 * When overridden in a subclass, a policy implementation may witness this operation
183 * and adjust its cleanup index.
184 */
185 virtual void
Junxiao Shi07f2e2f2019-07-22 09:10:06 -0600186 doBeforeUse(EntryRef i) = 0;
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -0500187
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -0400188 /** \brief Evicts zero or more entries.
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -0500189 * \post CS size does not exceed hard limit
190 */
191 virtual void
192 evictEntries() = 0;
193
194protected:
Davide Pesaventoa3a7a4e2022-05-29 16:06:22 -0400195 explicit
196 Policy(std::string_view policyName);
197
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -0500198 DECLARE_SIGNAL_EMIT(beforeEvict)
199
Junxiao Shi52555b02016-11-25 21:39:06 +0000200private: // registry
Junxiao Shi07f2e2f2019-07-22 09:10:06 -0600201 using CreateFunc = std::function<unique_ptr<Policy>()>;
202 using Registry = std::map<std::string, CreateFunc>; // indexed by policy name
Junxiao Shi52555b02016-11-25 21:39:06 +0000203
204 static Registry&
205 getRegistry();
206
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -0500207private:
Davide Pesaventoa3a7a4e2022-05-29 16:06:22 -0400208 const std::string m_policyName;
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -0500209 size_t m_limit;
210 Cs* m_cs;
211};
212
Davide Pesaventoe422f9e2022-06-03 01:30:23 -0400213} // namespace nfd::cs
Minsheng Zhangcb6e05f2015-04-20 15:51:47 -0500214
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -0400215/** \brief Registers a CS policy.
Junxiao Shi52555b02016-11-25 21:39:06 +0000216 * \param P a subclass of nfd::cs::Policy
217 */
218#define NFD_REGISTER_CS_POLICY(P) \
219static class NfdAuto ## P ## CsPolicyRegistrationClass \
220{ \
221public: \
222 NfdAuto ## P ## CsPolicyRegistrationClass() \
223 { \
224 ::nfd::cs::Policy::registerPolicy<P>(); \
225 } \
226} g_nfdAuto ## P ## CsPolicyRegistrationVariable
227
Junxiao Shi2af9ca32016-08-25 21:51:02 +0000228#endif // NFD_DAEMON_TABLE_CS_POLICY_HPP