bes  Updated for version 3.17.1
ObjMemCache.cc
1 // This file is part of bes, A C++ back-end server implementation framework
2 // for the OPeNDAP Data Access Protocol.
3 
4 // Copyright (c) 2016 OPeNDAP
5 // Author: James Gallagher <jgallagher@opendap.org>
6 //
7 // This library is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU Lesser General Public
9 // License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 //
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // Lesser General Public License for more details.
16 //
17 // You should have received a copy of the GNU Lesser General Public
18 // License along with this library; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 
21 /*
22  * ObjMemCache.cc
23  *
24  * Created on: May 18, 2016
25  * Author: jimg
26  */
27 
28 
29 #include "config.h"
30 
31 #include <string>
32 #include <map>
33 
34 #include <DapObj.h>
35 #include <InternalErr.h>
36 
37 #include "ObjMemCache.h"
38 
39 // using namespace bes {
40 
41 using namespace std;
42 using namespace libdap;
43 
44 ObjMemCache::~ObjMemCache()
45 {
46  for (cache_t::iterator i = cache.begin(), e = cache.end(); i != e; ++i) {
47  assert(i->second);
48  delete i->second;
49  }
50 }
51 
62 void ObjMemCache::add(DapObj *obj, const string &key)
63 {
64  ++d_count;
65 
66  // if d_entries_threshold is zero, the caller handles calling
67  // purge.
68  if (d_entries_threshold && (d_count > d_entries_threshold))
69  purge(d_purge_threshold);
70 
71  index.insert(index_pair_t(key, d_count));
72 
73  cache.insert(cache_pair_t(d_count, new Entry(obj, key)));
74 }
75 
80 void ObjMemCache::remove(const string &key)
81 {
82  index_t::iterator i = index.find(key);
83 
84  if (i != index.end()) {
85  unsigned int count = i->second;
86  index.erase(i);
87  cache_t::iterator c = cache.find(count);
88  assert(c != cache.end());
89  assert(c->second); // should never cache a null ptr
90  delete c->second; // delete the Entry*, but not the contained obj*
91  cache.erase(c);
92  }
93 }
94 
100 DapObj *ObjMemCache::get(const string &key)
101 {
102  DapObj *cached_obj = 0;
103 
104  index_t::iterator i = index.find(key);
105  if (i != index.end()) {
106  cache_t::iterator c = cache.find(i->second);
107  assert(c != cache.end());
108  // leave this second test in, but unless the cache is
109  // broken, it should never be false.
110  if (c != cache.end()) {
111  assert(c->second);
112  // get the Entry and the DDS
113  Entry *e = c->second;
114  cached_obj = e->d_obj; // cached_obj == the return value
115 
116  // now erase & reinsert the pair
117  cache.erase(c);
118  cache.insert(cache_pair_t(++d_count, e));
119  }
120  else {
121  // I'm leaving the test and this exception in because getting
122  // a bad DDS will lead to a bug that is hard to figure out. Other
123  // parts of the code I'm assuming assert() calls are good enough.
124  // jhrg 5/20/16
125  throw InternalErr(__FILE__, __LINE__, "Memory cache consistency error.");
126  }
127 
128  // update the index
129  index.erase(i);
130  index.insert(index_pair_t(key, d_count));
131  }
132 
133  return cached_obj;
134 }
135 
140 void ObjMemCache::purge(float fraction)
141 {
142  // Map are ordered using less by default, so the oldest entries are first
143  size_t num_remove = cache.size() * fraction;
144 
145  cache_t::iterator c = cache.begin(), e = cache.end();
146  for (unsigned int i = 0; i < num_remove && c != e; ++i) {
147  const string name = c->second->d_name;
148  delete c->second; // deletes the Entry, not the obj that its internals point to
149  cache.erase(c);
150  c = cache.begin(); // erase() invalidates the iterator
151 
152  index_t::iterator pos = index.find(name);
153  assert(pos != index.end());
154  index.erase(pos);
155  }
156 }
157 
158 // } namespace bes
virtual libdap::DapObj * get(const std::string &key)
Get the cached pointer.
Definition: ObjMemCache.cc:100
STL namespace.
virtual void purge(float fraction)
Purge the oldest elements.
Definition: ObjMemCache.cc:140
virtual void add(libdap::DapObj *obj, const std::string &key)
Added a DDS to the cache and associate it with a key Add the pointer to the cache, purging the cache of the least recently used items if the cache was initialized with a specific threshold value. If not, the caller must take care of calling the purge() method.
Definition: ObjMemCache.cc:62
virtual void remove(const std::string &key)
Remove the object associated with a key.
Definition: ObjMemCache.cc:80