bes  Updated for version 3.20.6
CmrCache.cc
1 // -*- mode: c++; c-basic-offset:4 -*-
2 
3 // This file is part of cmr_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) 2015 OPeNDAP, Inc.
7 // Author: Nathan Potter <ndp@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  * CmrCache.cc
27  *
28  * Created on: July, 10 2018
29  * Author: ndp
30  */
31 
32 #include "config.h"
33 
34 #include <sys/stat.h>
35 
36 #include <string>
37 #include <fstream>
38 #include <sstream>
39 
40 #include <cstdlib>
41 
42 #include "PicoSHA2/picosha2.h"
43 
44 #include "BESInternalError.h"
45 #include "BESDebug.h"
46 #include "BESUtil.h"
47 #include "TheBESKeys.h"
48 
49 #include "CmrNames.h"
50 #include "CmrCache.h"
51 
52 using std::endl;
53 using std::string;
54 
55 #ifdef HAVE_ATEXIT
56 #define AT_EXIT(x) atexit((x))
57 #else
58 #define AT_EXIT(x)
59 #endif
60 
61 
62 using namespace cmr;
63 
64 CmrCache *CmrCache::d_instance = 0;
65 bool CmrCache::d_enabled = true;
66 
67 const string CmrCache::DIR_KEY = "CMR.Cache.dir";
68 const string CmrCache::PREFIX_KEY = "CMR.Cache.prefix";
69 const string CmrCache::SIZE_KEY = "CMR.Cache.size";
70 
71 unsigned long CmrCache::getCacheSizeFromConfig()
72 {
73 
74  bool found;
75  string size;
76  unsigned long size_in_megabytes = 0;
77  TheBESKeys::TheKeys()->get_value(SIZE_KEY, size, found);
78  if (found) {
79  std::istringstream iss(size);
80  iss >> size_in_megabytes;
81  }
82  else {
83  string msg = "CmrCache - The BES Key " + SIZE_KEY + " is not set.";
84  BESDEBUG(MODULE, msg << endl);
85  throw BESInternalError(msg, __FILE__, __LINE__);
86  }
87  return size_in_megabytes;
88 }
89 
90 string CmrCache::getCacheDirFromConfig()
91 {
92  bool found;
93  string subdir = "";
94  TheBESKeys::TheKeys()->get_value(DIR_KEY, subdir, found);
95 
96  if (!found) {
97  string msg = "CmrCache - The BES Key " + DIR_KEY + " is not set.";
98  BESDEBUG(MODULE, msg << endl);
99  throw BESInternalError(msg, __FILE__, __LINE__);
100  }
101 
102  return subdir;
103 }
104 
105 string CmrCache::getCachePrefixFromConfig()
106 {
107  bool found;
108  string prefix = "";
109  TheBESKeys::TheKeys()->get_value(PREFIX_KEY, prefix, found);
110  if (found) {
111  prefix = BESUtil::lowercase(prefix);
112  }
113  else {
114  string msg = "CmrCache - The BES Key " + PREFIX_KEY + " is not set.";
115  BESDEBUG(MODULE, msg << endl);
116  throw BESInternalError(msg, __FILE__, __LINE__);
117  }
118 
119  return prefix;
120 }
121 
122 CmrCache::CmrCache()
123 {
124  BESDEBUG(MODULE, "CmrCache::CmrCache() - BEGIN" << endl);
125 
126  string cacheDir = getCacheDirFromConfig();
127  string cachePrefix = getCachePrefixFromConfig();
128  unsigned long cacheSizeMbytes = getCacheSizeFromConfig();
129 
130  BESDEBUG(MODULE,
131  "CmrCache() - Cache configuration params: " << cacheDir << ", " << cachePrefix << ", " << cacheSizeMbytes << endl);
132 
133  initialize(cacheDir, cachePrefix, cacheSizeMbytes);
134 
135  BESDEBUG(MODULE, "CmrCache::CmrCache() - END" << endl);
136 }
137 
138 CmrCache::CmrCache(const string &cache_dir, const string &prefix, unsigned long long size)
139 {
140  BESDEBUG(MODULE, "CmrCache::CmrCache() - BEGIN" << endl);
141 
142  initialize(cache_dir, prefix, size);
143 
144  BESDEBUG(MODULE, "CmrCache::CmrCache() - END" << endl);
145 }
146 
147 CmrCache *
148 CmrCache::get_instance(const string &cache_dir, const string &cache_file_prefix, unsigned long long max_cache_size)
149 {
150  if (d_enabled && d_instance == 0) {
151  if (dir_exists(cache_dir)) {
152  d_instance = new CmrCache(cache_dir, cache_file_prefix, max_cache_size);
153  d_enabled = d_instance->cache_enabled();
154  if (!d_enabled) {
155  delete d_instance;
156  d_instance = 0;
157  BESDEBUG(MODULE, "CmrCache::"<<__func__ << "() - " << "Cache is DISABLED"<< endl);
158  }
159  else {
160  AT_EXIT(delete_instance);
161 
162  BESDEBUG(MODULE, "CmrCache::"<<__func__ << "() - " << "Cache is ENABLED"<< endl);
163  }
164  }
165  }
166 
167  return d_instance;
168 }
169 
173 CmrCache *
175 {
176  if (d_enabled && d_instance == 0) {
177  try {
178  d_instance = new CmrCache();
179  d_enabled = d_instance->cache_enabled();
180  if (!d_enabled) {
181  delete d_instance;
182  d_instance = 0;
183  BESDEBUG(MODULE, "CmrCache::"<<__func__ << "() - " << "Cache is DISABLED"<< endl);
184  }
185  else {
186  AT_EXIT(delete_instance);
187 
188  BESDEBUG(MODULE, "CmrCache::" << __func__ << "() - " << "Cache is ENABLED"<< endl);
189  }
190  }
191  catch (BESInternalError &bie) {
192  BESDEBUG(MODULE,
193  "[ERROR] CmrCache::get_instance(): Failed to obtain cache! msg: " << bie.get_message() << endl);
194  }
195  }
196 
197  return d_instance;
198 }
199 
200 
207 inline string
208 CmrCache::get_hash(const string &name)
209 {
210  if (name.empty())
211  throw BESInternalError("Empty name passed to the Metadata Store.", __FILE__, __LINE__);
212  return picosha2::hash256_hex_string(name[0] == '/' ? name : "/" + name);
213 }
214 
215 string CmrCache::get_cache_file_name(const string &src, bool /*mangle*/){
217 }
218 
cmr::CmrCache::get_hash
std::string get_hash(const std::string &name)
Definition: CmrCache.cc:208
BESFileLockingCache::cache_enabled
bool cache_enabled() const
Definition: BESFileLockingCache.h:198
BESError::get_message
virtual std::string get_message()
get the error message for this exception
Definition: BESError.h:99
BESFileLockingCache::dir_exists
static bool dir_exists(const std::string &dir)
Definition: BESFileLockingCache.cc:1136
BESFileLockingCache::get_cache_file_prefix
const std::string get_cache_file_prefix()
Definition: BESFileLockingCache.h:182
BESUtil::assemblePath
static std::string assemblePath(const std::string &firstPart, const std::string &secondPart, bool leadingSlash=false, bool trailingSlash=false)
Assemble path fragments making sure that they are separated by a single '/' character.
Definition: BESUtil.cc:821
TheBESKeys::TheKeys
static TheBESKeys * TheKeys()
Definition: TheBESKeys.cc:62
BESFileLockingCache::initialize
void initialize(const std::string &cache_dir, const std::string &prefix, unsigned long long size)
Initialize an instance of FileLockingCache.
Definition: BESFileLockingCache.cc:116
BESInternalError
exception thrown if internal error encountered
Definition: BESInternalError.h:43
TheBESKeys::get_value
void get_value(const std::string &s, std::string &val, bool &found)
Retrieve the value of a given key, if set.
Definition: TheBESKeys.cc:272
BESUtil::lowercase
static std::string lowercase(const std::string &s)
Definition: BESUtil.cc:200
cmr::CmrCache
A cache for content accessed via the CMR.
Definition: CmrCache.h:56
cmr::CmrCache::get_cache_file_name
virtual std::string get_cache_file_name(const std::string &src, bool mangle=true)
Definition: CmrCache.cc:215
cmr::CmrCache::get_instance
static CmrCache * get_instance()
Definition: CmrCache.cc:174
BESFileLockingCache::get_cache_directory
const std::string get_cache_directory()
Definition: BESFileLockingCache.h:188