bes  Updated for version 3.20.5
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 #ifdef HAVE_ATEXIT
53 #define AT_EXIT(x) atexit((x))
54 #else
55 #define AT_EXIT(x)
56 #endif
57 
58 
59 using namespace cmr;
60 
61 CmrCache *CmrCache::d_instance = 0;
62 bool CmrCache::d_enabled = true;
63 
64 const string CmrCache::DIR_KEY = "CMR.Cache.dir";
65 const string CmrCache::PREFIX_KEY = "CMR.Cache.prefix";
66 const string CmrCache::SIZE_KEY = "CMR.Cache.size";
67 
68 unsigned long CmrCache::getCacheSizeFromConfig()
69 {
70 
71  bool found;
72  string size;
73  unsigned long size_in_megabytes = 0;
74  TheBESKeys::TheKeys()->get_value(SIZE_KEY, size, found);
75  if (found) {
76  std::istringstream iss(size);
77  iss >> size_in_megabytes;
78  }
79  else {
80  string msg = "CmrCache - The BES Key " + SIZE_KEY + " is not set.";
81  BESDEBUG(MODULE, msg << endl);
82  throw BESInternalError(msg, __FILE__, __LINE__);
83  }
84  return size_in_megabytes;
85 }
86 
87 string CmrCache::getCacheDirFromConfig()
88 {
89  bool found;
90  string subdir = "";
91  TheBESKeys::TheKeys()->get_value(DIR_KEY, subdir, found);
92 
93  if (!found) {
94  string msg = "CmrCache - The BES Key " + DIR_KEY + " is not set.";
95  BESDEBUG(MODULE, msg << endl);
96  throw BESInternalError(msg, __FILE__, __LINE__);
97  }
98 
99  return subdir;
100 }
101 
102 string CmrCache::getCachePrefixFromConfig()
103 {
104  bool found;
105  string prefix = "";
106  TheBESKeys::TheKeys()->get_value(PREFIX_KEY, prefix, found);
107  if (found) {
108  prefix = BESUtil::lowercase(prefix);
109  }
110  else {
111  string msg = "CmrCache - The BES Key " + PREFIX_KEY + " is not set.";
112  BESDEBUG(MODULE, msg << endl);
113  throw BESInternalError(msg, __FILE__, __LINE__);
114  }
115 
116  return prefix;
117 }
118 
119 CmrCache::CmrCache()
120 {
121  BESDEBUG(MODULE, "CmrCache::CmrCache() - BEGIN" << endl);
122 
123  string cacheDir = getCacheDirFromConfig();
124  string cachePrefix = getCachePrefixFromConfig();
125  unsigned long cacheSizeMbytes = getCacheSizeFromConfig();
126 
127  BESDEBUG(MODULE,
128  "CmrCache() - Cache configuration params: " << cacheDir << ", " << cachePrefix << ", " << cacheSizeMbytes << endl);
129 
130  initialize(cacheDir, cachePrefix, cacheSizeMbytes);
131 
132  BESDEBUG(MODULE, "CmrCache::CmrCache() - END" << endl);
133 }
134 
135 CmrCache::CmrCache(const string &cache_dir, const string &prefix, unsigned long long size)
136 {
137  BESDEBUG(MODULE, "CmrCache::CmrCache() - BEGIN" << endl);
138 
139  initialize(cache_dir, prefix, size);
140 
141  BESDEBUG(MODULE, "CmrCache::CmrCache() - END" << endl);
142 }
143 
144 CmrCache *
145 CmrCache::get_instance(const string &cache_dir, const string &cache_file_prefix, unsigned long long max_cache_size)
146 {
147  if (d_enabled && d_instance == 0) {
148  if (dir_exists(cache_dir)) {
149  d_instance = new CmrCache(cache_dir, cache_file_prefix, max_cache_size);
150  d_enabled = d_instance->cache_enabled();
151  if (!d_enabled) {
152  delete d_instance;
153  d_instance = 0;
154  BESDEBUG(MODULE, "CmrCache::"<<__func__ << "() - " << "Cache is DISABLED"<< endl);
155  }
156  else {
157  AT_EXIT(delete_instance);
158 
159  BESDEBUG(MODULE, "CmrCache::"<<__func__ << "() - " << "Cache is ENABLED"<< endl);
160  }
161  }
162  }
163 
164  return d_instance;
165 }
166 
170 CmrCache *
172 {
173  if (d_enabled && d_instance == 0) {
174  try {
175  d_instance = new CmrCache();
176  d_enabled = d_instance->cache_enabled();
177  if (!d_enabled) {
178  delete d_instance;
179  d_instance = 0;
180  BESDEBUG(MODULE, "CmrCache::"<<__func__ << "() - " << "Cache is DISABLED"<< endl);
181  }
182  else {
183  AT_EXIT(delete_instance);
184 
185  BESDEBUG(MODULE, "CmrCache::" << __func__ << "() - " << "Cache is ENABLED"<< endl);
186  }
187  }
188  catch (BESInternalError &bie) {
189  BESDEBUG(MODULE,
190  "[ERROR] CmrCache::get_instance(): Failed to obtain cache! msg: " << bie.get_message() << endl);
191  }
192  }
193 
194  return d_instance;
195 }
196 
197 
204 inline string
205 CmrCache::get_hash(const string &name)
206 {
207  if (name.empty())
208  throw BESInternalError("Empty name passed to the Metadata Store.", __FILE__, __LINE__);
209  return picosha2::hash256_hex_string(name[0] == '/' ? name : "/" + name);
210 }
211 
212 string CmrCache::get_cache_file_name(const string &src, bool /*mangle*/){
214 }
215 
exception thrown if inernal error encountered
const std::string get_cache_file_prefix()
static string lowercase(const string &s)
Definition: BESUtil.cc:197
virtual string get_cache_file_name(const string &src, bool mangle=true)
Definition: CmrCache.cc:212
virtual std::string get_message()
get the error message for this exception
Definition: BESError.h:99
static bool dir_exists(const std::string &dir)
void get_value(const std::string &s, std::string &val, bool &found)
Retrieve the value of a given key, if set.
Definition: TheBESKeys.cc:420
static TheBESKeys * TheKeys()
Definition: TheBESKeys.cc:61
const std::string get_cache_directory()
void initialize(const std::string &cache_dir, const std::string &prefix, unsigned long long size)
Initialize an instance of FileLockingCache.
static CmrCache * get_instance()
Definition: CmrCache.cc:171
string get_hash(const string &name)
Definition: CmrCache.cc:205
static string assemblePath(const string &firstPart, const string &secondPart, bool leadingSlash=false, bool trailingSlash=false)
Assemble path fragments making sure that they are separated by a single '/' character.
Definition: BESUtil.cc:818
A cache for content accessed via the CMR.
Definition: CmrCache.h:56