bes Updated for version 3.21.1
The Backend Server (BES) is the lower two tiers of the Hyrax data server
MemoryCache.h
1// -*- mode: c++; c-basic-offset:4 -*-
2
3// This file is part of ngap_module, A C++ module that can be loaded in to
4// the OPeNDAP Back-End Server (BES) and is able to handle remote requests.
5
6// Copyright (c) 2023 OPeNDAP, Inc.
7// Author: James Gallagher <jgallagher@opendap.org>
8//
9// This library is free software; you can redistribute it and/or
10// modify it under the terms of the GNU Lesser General Public
11// License as published by the Free Software Foundation; either
12// version 2.1 of the License, or (at your option) any later version.
13//
14// This library is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17// Lesser General Public License for more details.
18//
19// You should have received a copy of the GNU Lesser General Public
20// License along with this library; if not, write to the Free Software
21// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22//
23// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
24
25//
26// Created by James Gallagher on 10/16/23.
27//
28
29#ifndef BES_MEMORYCACHE_H
30#define BES_MEMORYCACHE_H
31
32#include <string>
33#include <unordered_map>
34#include <deque>
35
36#ifndef BESInternalError_h_
37#include "BESInternalError.h"
38#endif
39
40namespace ngap {
41
63template <typename VALUE>
64class MemoryCache {
65 unsigned int d_max_items = 100; //< Max number of items to cache (not bytes, but items)
66 unsigned int d_purge_items = 20; //< When purging, remove this many items
67
68 std::deque<std::string> d_fifo_keys; //< FIFO queue of keys; used by purge()
69 std::unordered_map<std::string, VALUE> d_cache;
70
72 void purge() {
73 // if number of elements > threshold, purge
74 for (int entries = 0; entries < d_purge_items; ++entries) {
75 std::string key = d_fifo_keys.front();
76
77 d_cache.erase(d_cache.find(key));
78 d_fifo_keys.pop_front();
79 }
80 }
81
83 bool invariant(bool expensive = true) const {
84 if (d_cache.size() > d_max_items)
85 return false;
86 if (d_fifo_keys.size() > d_max_items)
87 return false;
88 if (d_cache.size() != d_fifo_keys.size())
89 return false;
90
91 if (expensive) {
92 // check that the keys in the queue are also in the map
93 for (const auto &key : d_fifo_keys) {
94 if (d_cache.find(key) == d_cache.end())
95 return false;
96 }
97 }
98
99 return true;
100 }
101
102 friend class MemoryCacheTest;
103
104public:
105 MemoryCache() = default; // this makes testing easier
106 MemoryCache(const MemoryCache *src) = delete;
107
108 virtual ~MemoryCache() = default;
109 MemoryCache &operator=(const MemoryCache *src) = delete;
110
117 virtual bool initialize(int max_items, int purge_items) {
118 if (max_items <= 0 || purge_items <= 0)
119 return false;
120
121 d_max_items = (unsigned int)max_items;
122 d_purge_items = (unsigned int)purge_items;
123 return true;
124 }
125
133 virtual bool get(const std::string &key, VALUE &value) {
134 if (d_cache.find(key) != d_cache.end()) {
135 value = d_cache[key];
136 return true;
137 }
138 else {
139 return false;
140 }
141 }
142
149 virtual void put(const std::string &key, const VALUE &value) {
150 // add key, value to the queue of entries if key is not in the cache
151 // add or overwrite/update the value associated with key
152 if (d_cache.find(key) == d_cache.end()) {
153 d_cache.insert(std::pair<std::string, VALUE>(key, value));
154 d_fifo_keys.push_back(key);
155 if (d_cache.size() > d_max_items)
156 purge();
157 }
158 else
159 d_cache[key] = value;
160 }
161
163 virtual unsigned long size() const { return d_cache.size(); }
164
166 virtual void clear() { d_cache.clear(); d_fifo_keys.clear(); }
167};
168
169} // ngap
170
171#endif //BES_MEMORYCACHE_H
virtual bool initialize(int max_items, int purge_items)
Initialize the cache.
virtual unsigned long size() const
How many items are in the cache.
virtual void clear()
Clear the cache.
virtual void put(const std::string &key, const VALUE &value)
Put the item in the cache. If the key is already in the cache, the value is updated.
virtual bool get(const std::string &key, VALUE &value)
Get the item from the cache. If the item is not in the cache, the value-result parameter is not modif...