blob: 5e800c24d2c8ca17e0a68c6e765d7dfd44b87a9a [file] [log] [blame]
Jiewen Tan99135962014-09-20 02:18:53 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2013-2014 Regents of the University of California.
4 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6 *
7 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20 */
21
22#ifndef NDN_UTIL_IN_MEMORY_STORAGE_HPP
23#define NDN_UTIL_IN_MEMORY_STORAGE_HPP
24
25#include "../common.hpp"
26#include "../interest.hpp"
27#include "../data.hpp"
28
29#include "in-memory-storage-entry.hpp"
30
31#include <boost/multi_index/member.hpp>
32#include <boost/multi_index_container.hpp>
33#include <boost/multi_index/ordered_index.hpp>
34#include <boost/multi_index/sequenced_index.hpp>
35#include <boost/multi_index/identity.hpp>
36#include <boost/multi_index/mem_fun.hpp>
37
38#include <stack>
39#include <iterator>
Jiewen Tan99135962014-09-20 02:18:53 -070040
41namespace ndn {
42namespace util {
43
44/** @brief Represents in-memory storage
45 */
46class InMemoryStorage : noncopyable
47{
48public:
49 //multi_index_container to implement storage
50 class byFullName;
51
52 typedef boost::multi_index_container<
53 InMemoryStorageEntry*,
54 boost::multi_index::indexed_by<
55
56 // by Full Name
57 boost::multi_index::ordered_unique<
58 boost::multi_index::tag<byFullName>,
59 boost::multi_index::const_mem_fun<InMemoryStorageEntry, const Name&,
60 &InMemoryStorageEntry::getFullName>,
61 std::less<Name>
62 >
63
64 >
65 > Cache;
66
67 /** @brief Represents a self-defined const_iterator for the in-memory storage
68 *
69 * @note Don't try to instantiate this class directly, use InMemoryStorage::begin() instead.
70 */
71 class const_iterator : public std::iterator<std::input_iterator_tag, const Data>
72 {
73 public:
74 const_iterator(const Data* ptr, const Cache* cache,
75 Cache::index<byFullName>::type::iterator it);
76
77 const_iterator&
78 operator++();
79
80 const_iterator
81 operator++(int);
82
83 const Data&
84 operator*();
85
86 const Data*
87 operator->();
88
89 bool
90 operator==(const const_iterator& rhs);
91
92 bool
93 operator!=(const const_iterator& rhs);
94
95 private:
96 const Data* m_ptr;
97 const Cache* m_cache;
98 Cache::index<byFullName>::type::iterator m_it;
99 };
100
101 /** @brief Represents an error might be thrown during reduce the current capacity of the
102 * in-memory storage through function setCapacity(size_t nMaxPackets).
103 */
104 class Error : public std::runtime_error
105 {
106 public:
107 Error() : std::runtime_error("Cannot reduce the capacity of the in-memory storage!")
108 {
109 }
110 };
111
112 explicit
113 InMemoryStorage(size_t limit = std::numeric_limits<size_t>::max());
114
115 /** @note Please make sure to implement it to free m_freeEntries and evict
116 * all items in the derived class for anybody who wishes to inherit this class
117 */
118 virtual
119 ~InMemoryStorage();
120
121 /** @brief Inserts a Data packet
122 *
123 * @note Packets are considered duplicate if the name with implicit digest matches.
124 * The new Data packet with the identical name, but a different payload
125 * will be placed in the in-memory storage.
126 *
127 * @note It will invoke afterInsert(shared_ptr<InMemoryStorageEntry>).
128 */
129 void
130 insert(const Data& data);
131
132 /** @brief Finds the best match Data for an Interest
133 *
134 * @note It will invoke afterAccess(shared_ptr<InMemoryStorageEntry>).
135 * As currently it is impossible to determine whether a Name contains implicit digest or not,
136 * therefore this find function is not able to locate a packet according to an interest(
137 * including implicit digest) whose name is not the full name of the data matching the
138 * implicit digest.
139 *
140 * @return{ the best match, if any; otherwise a null shared_ptr }
141 */
142 shared_ptr<const Data>
143 find(const Interest& interest);
144
145 /** @brief Finds the best match Data for a Name with or without
146 * the implicit digest.
147 *
148 * If packets with the same name but different digests exist
149 * and the Name supplied is the one without implicit digest, a packet
150 * will be arbitrarily chosen to return.
151 *
152 * @note It will invoke afterAccess(shared_ptr<InMemoryStorageEntry>).
153 *
154 * @return{ the one matched the Name; otherwise a null shared_ptr }
155 */
156 shared_ptr<const Data>
157 find(const Name& name);
158
159 /** @brief Deletes in-memory storage entry by prefix by default.
Alexander Afanasyevf2a46222015-09-17 18:01:30 -0700160 * @param prefix Exact name of a prefix of the data to remove
161 * @param isPrefix If false, the function will only delete the
Jiewen Tan99135962014-09-20 02:18:53 -0700162 * entry completely matched with the prefix according to canonical ordering.
163 * For this case, user should substitute the prefix with full name.
164 *
165 * @note Please do not use this function directly in any derived class to erase
166 * entry in the cache, use eraseHelper instead.
167 * @note It will invoke beforeErase(shared_ptr<InMemoryStorageEntry>).
168 */
169 void
170 erase(const Name& prefix, const bool isPrefix = true);
171
172 /** @return{ maximum number of packets that can be allowed to store in in-memory storage }
173 */
174 size_t
175 getLimit() const
176 {
177 return m_limit;
178 }
179
180 /** @return{ number of packets stored in in-memory storage }
181 */
182 size_t
183 size() const
184 {
185 return m_nPackets;
186 }
187
188 /** @brief Returns begin iterator of the in-memory storage ordering by
189 * name with digest
190 *
191 * @return{ const_iterator pointing to the beginning of the m_cache }
192 */
193 InMemoryStorage::const_iterator
194 begin() const;
195
196 /** @brief Returns end iterator of the in-memory storage ordering by
197 * name with digest
198 *
199 * @return{ const_iterator pointing to the end of the m_cache }
200 */
201 InMemoryStorage::const_iterator
202 end() const;
203
Junxiao Shi99848502014-10-13 19:22:22 -0700204NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PROTECTED:
Jiewen Tan99135962014-09-20 02:18:53 -0700205 /** @brief Update the entry when the entry is returned by the find() function
206 * according to derived class implemented replacement policy
207 */
208 virtual void
209 afterAccess(InMemoryStorageEntry* entry);
210
211 /** @brief Update the entry or other data structures
212 * after a entry is successfully inserted
213 * according to derived class implemented replacement policy
214 */
215 virtual void
216 afterInsert(InMemoryStorageEntry* entry);
217
218 /** @brief Update the entry or other data structures
219 * before a entry is successfully erased
220 * according to derived class implemented replacement policy
221 */
222 virtual void
223 beforeErase(InMemoryStorageEntry* entry);
224
225 /** @brief Removes one Data packet from in-memory storage based on
226 * derived class implemented replacement policy
227 *
228 * Please do not use this function directly in any derived class to erase
229 * entry in the cache, use eraseHelper instead.
230 * @return{ whether the Data was removed }
231 */
232 virtual bool
233 evictItem() = 0;
234
Junxiao Shi99848502014-10-13 19:22:22 -0700235NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PROTECTED:
Jiewen Tan99135962014-09-20 02:18:53 -0700236 /** @brief sets current capacity of in-memory storage (in packets)
237 */
238 void
239 setCapacity(size_t nMaxPackets);
240
241 /** @brief returns current capacity of in-memory storage (in packets)
242 * @return{ number of packets that can be stored in application cache }
243 */
244 size_t
245 getCapacity() const
246 {
247 return m_capacity;
248 }
249
250 /** @brief returns true if the in-memory storage uses up the current capacity, false otherwise
251 */
252 bool
253 isFull() const
254 {
255 return size() >= m_capacity;
256 }
257
258 /** @brief deletes in-memory storage entries by the Name with implicit digest.
259 *
260 * This is the function one should use to erase entry in the cache
261 * in derived class.
262 * It won't invoke beforeErase(shared_ptr<Entry>).
263 */
264 void
265 eraseImpl(const Name& name);
266
267 /** @brief Prints contents of the in-memory storage
268 */
269 void
270 printCache(std::ostream& os) const;
271
Junxiao Shi99848502014-10-13 19:22:22 -0700272NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
Jiewen Tan99135962014-09-20 02:18:53 -0700273 /** @brief free in-memory storage entries by an iterator pointing to that entry.
Alexander Afanasyev8e131fd2014-12-15 21:31:50 -0800274 @return An iterator pointing to the element that followed the last element erased.
275 */
276 Cache::iterator
277 freeEntry(Cache::iterator it);
Jiewen Tan99135962014-09-20 02:18:53 -0700278
279 /** @brief Implements child selector (leftmost, rightmost, undeclared).
280 * Operates on the first layer of a skip list.
281 *
282 * startingPoint must be less than Interest Name.
283 * startingPoint can be equal to Interest Name only
284 * when the item is in the begin() position.
285 *
286 * Iterates toward greater Names, terminates when application cache entry falls out of Interest
287 * prefix. When childSelector = leftmost, returns first application cache entry that satisfies
288 * other selectors. When childSelector = rightmost, it goes till the end, and returns application
289 * cache entry that satisfies other selectors. Returned application cache entry is the leftmost
290 * child of the rightmost child.
291 * @return{ the best match, if any; otherwise 0 }
292 */
293 InMemoryStorageEntry*
294 selectChild(const Interest& interest,
295 Cache::index<byFullName>::type::iterator startingPoint) const;
296
297private:
298 Cache m_cache;
299 /// user defined maximum capacity of the in-memory storage in packets
300 size_t m_limit;
301 /// current capacity of the in-memory storage in packets
302 size_t m_capacity;
303 /// current number of packets in in-memory storage
304 size_t m_nPackets;
305 /// memory pool
306 std::stack<InMemoryStorageEntry*> m_freeEntries;
307};
308
309} // namespace util
310} // namespace ndn
311
312#endif // NDN_UTIL_IN_MEMORY_STORAGE_HPP