OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
BESH4MCache.cc
Go to the documentation of this file.
1 // This file includes cache handling routines for the HDF4 handler.
3 // The skeleton of the code is adapted from BESDapResponseCache.cc under bes/dap
4 // Authors: MuQun Yang <myang6@hdfgroup.org>
5 // Copyright (c) 2014 The HDF Group
7 
8 #include <sys/stat.h>
9 #include <iostream>
10 #include <sstream>
11 
12 #include "BESH4MCache.h"
13 #include "BESUtil.h"
14 
15 #include "BESInternalError.h"
16 #include "TheBESKeys.h"
17 #include "BESDebug.h"
18 
19 using namespace std;
20 
21 BESH4Cache *BESH4Cache::d_instance = 0;
22 const string BESH4Cache::PATH_KEY = "HDF4.Cache.latlon.path";
23 const string BESH4Cache::PREFIX_KEY = "HDF4.Cache.latlon.prefix";
24 const string BESH4Cache::SIZE_KEY = "HDF4.Cache.latlon.size";
25 
27 
28  bool found;
29  string size;
30  unsigned long size_in_megabytes = 0;
31  TheBESKeys::TheKeys()->get_value( SIZE_KEY, size, found ) ;
32  if( found ) {
33  BESDEBUG("cache", "In BESH4Cache::getDefaultCacheSize(): Located BES key " <<
34  SIZE_KEY<< "=" << size << endl);
35  istringstream iss(size);
36  iss >> size_in_megabytes;
37  }
38  else {
39  string msg = "[ERROR] BESH4Cache::getCacheSize() - The BES Key " + SIZE_KEY + " is not set! It MUST be set to utilize the HDF4 cache. ";
40  BESDEBUG("cache", msg);
41  throw BESInternalError(msg , __FILE__, __LINE__);
42  }
43  return size_in_megabytes;
44 }
45 
47 
48  bool found;
49  string prefix = "";
50  TheBESKeys::TheKeys()->get_value( PREFIX_KEY, prefix, found ) ;
51  if( found ) {
52  BESDEBUG("cache", "In BESH4Cache::getDefaultCachePrefix(): Located BES key " <<
53  PREFIX_KEY<< "=" << prefix << endl);
54  prefix = BESUtil::lowercase( prefix ) ;
55  }
56  else {
57  string msg = "[ERROR] BESH4Cache::getCachePrefix() - The BES Key " + PREFIX_KEY + " is not set! It MUST be set to utilize the HDF4 cache. ";
58  BESDEBUG("cache", msg);
59  throw BESInternalError(msg , __FILE__, __LINE__);
60  }
61 
62  return prefix;
63 }
64 
65 
67 
68  bool found;
69 
70  string cacheDir = "";
71  TheBESKeys::TheKeys()->get_value( PATH_KEY, cacheDir, found ) ;
72  if( found ) {
73  BESDEBUG("cache", "In BESH4Cache::getCachePrefix(): Located BES key " <<
74  PATH_KEY<< "=" << cacheDir << endl);
75  cacheDir = BESUtil::lowercase( cacheDir ) ;
76  }
77  else {
78  string msg = "[ERROR] BESH4Cache::getCacheDir() - The BES Key " + PATH_KEY + " is not set! It MUST be set to utilize the HDF4 cache. ";
79  BESDEBUG("cache", msg);
80  throw BESInternalError(msg , __FILE__, __LINE__);
81  }
82  return cacheDir;
83 }
84 
85 BESH4Cache::BESH4Cache(){
86 
87  BESDEBUG("cache", "In BESH4Cache::BESH4Cache()" << endl);
88 
89  string cacheDir = getCacheDirFromConfig();
90  string prefix = getCachePrefixFromConfig();
91  unsigned long size_in_megabytes = getCacheSizeFromConfig();
92 
93  BESDEBUG("cache", "BESH4Cache() - Cache config params: " << cacheDir << ", " << prefix << ", " << size_in_megabytes << endl);
94 
95  //cerr << endl << "***** BESH4Cache::BESH4Cache() - Read cache params: " << path << ", " << prefix << ", " << size << endl;
96 
97  // The required params must be present. If initialize() is not called,
98  // then d_cache will stay null and is_available() will return false.
99  // Also, the directory 'path' must exist, or d_cache will be null.
100  if (!cacheDir.empty() && size_in_megabytes > 0) {
101  BESDEBUG("cache", "Before calling initialize function." << endl);
102  initialize(cacheDir, prefix, size_in_megabytes);
103  }
104 
105  BESDEBUG("cache", "Leaving BESH4Cache::BESH4Cache()" << endl);
106 }
107 
108 #if 0
109 
123 BESH4Cache::BESH4Cache(const string &cache_dir, const string &prefix, unsigned long long size): BESFileLockingCache(cache_dir,prefix,size) {
124 
125 }
137 BESH4Cache *
138 BESH4Cache::get_instance(const string &cache_dir, const string &prefix, unsigned long long size)
139 {
140  if (d_instance == 0){
141  if(dir_exists(cache_dir)){
142  try {
143  d_instance = new BESH4Cache(cache_dir, prefix, size);
144  }
145  catch(BESInternalError &bie){
146  BESDEBUG("cache", "BESH4Cache::get_instance(): Failed to obtain cache! msg: " << bie.get_message() << endl);
147  }
148  }
149  }
150  return d_instance;
151 }
152 #endif
153 
157 BESH4Cache *
159 {
160  if (d_instance == 0) {
161  struct stat buf;
162  string cache_dir = getCacheDirFromConfig();
163  if((stat(cache_dir.c_str(),&buf)==0) && (buf.st_mode & S_IFDIR)){
164  try {
165  d_instance = new BESH4Cache();
166  }
167  catch(BESInternalError &bie){
168  BESDEBUG("cache", "BESH4Cache::get_instance(): Failed to obtain cache! msg: " << bie.get_message() << endl);
169  }
170  }
171  }
172 
173  return d_instance;
174 }
175 
177  BESDEBUG("cache","BESH4Cache::delete_instance() - Deleting singleton BESH4Cache instance." << endl);
178  cerr << "BESH4Cache::delete_instance() - Deleting singleton BESH4Cache instance. d_instance="<< d_instance << endl;
179  delete d_instance;
180  d_instance = 0;
181 }
182 
183 // Check whether the real lat/lon file size is the same as the expected lat/lon size. If not, return false.
184 bool BESH4Cache::is_valid(const string & cache_file_name, const int expected_file_size){
185 
186  struct stat st;
187  int result = stat(cache_file_name.c_str(),&st);
188  if(result != 0 ) {
189  string msg ="Cannot check the cached file " + cache_file_name;
190  throw BESInternalError(msg,__FILE__,__LINE__);
191  }
192  if(expected_file_size == st.st_size)
193  return true;
194  else
195  return false;
196 }
197 
198 // This call will try to obtain the read lock.
199 bool BESH4Cache::get_data_from_cache(const string & cache_file_name, const int expected_file_size,int &fd) {
200 #if 0
201 cerr<<"coming to get_data_from_cache "<<endl;
202  BESDEBUG("cache", "In BESH4Cache::get_data_from_cache()" << endl);
203 cerr<<"cache_file_name is "<<cache_file_name <<endl;
204 int fd1;
205 string cache_file_name1 = cache_file_name;
206  get_read_lock(cache_file_name1,fd1);
207 
208 cerr<<"After get_read_lock "<<endl;
209 #endif
210  if(false == get_read_lock(cache_file_name,fd))
211  return false;
212  else if(false == is_valid(cache_file_name,expected_file_size)) {
213  unlock_and_close(cache_file_name);
214  purge_file(cache_file_name);
215  return false;
216  }
217  else
218  return true;
219 }
220 
221 
222 bool BESH4Cache::write_cached_data( const string & cache_file_name,const int expected_file_size,const vector<double> &val) {
223 
224  BESDEBUG("cache", "In BESH4Cache::write_cached_data()" << endl);
225  int fd = 0;
226  bool ret_value = false;
227 
228  // 1. create_and_lock.
229  if(create_and_lock(cache_file_name,fd)) {
230 
231  ssize_t ret_val = 0;
232 
233  // 2. write the file.
234  ret_val = write(fd,&val[0],expected_file_size);
235 
236 
237  // 3. If the written size is not the same as the expected file size, purge the file.
238  if(ret_val != expected_file_size) {
239  if(unlink(cache_file_name.c_str())!=0){
240  string msg = "Cannot remove the corrupt cached file " + cache_file_name;
241  throw BESInternalError(msg , __FILE__, __LINE__);
242  }
243 
244  }
245  else {
246  unsigned long long size = update_cache_info(cache_file_name);
247  if(cache_too_big(size))
248  update_and_purge(cache_file_name);
249  ret_value = true;
250  }
251  // 4. release the lock.
252  unlock_and_close(cache_file_name);
253 
254 
255  }
256 
257  return ret_value;
258 
259 }
260 
261 
262 #if 0
263 void BESH4Cache::dummy_test_func() {
264 
265 cerr<<"BESH4Cache function is fine "<<endl;
266 
267 }
268 
269 
270 string BESH4Cache::get_cache_file_name_h4(const string & src, bool mangle) {
271 
272 return src;
273 }
274 #endif
275 
276 
277 
exception thrown if inernal error encountered
virtual bool create_and_lock(const string &target, int &fd)
Create a file in the cache and lock it for write access.
static string lowercase(const string &s)
Convert a string to all lower case.
Definition: BESUtil.cc:182
bool get_data_from_cache(const string &cache_file_name, const int expected_file_size, int &fd)
Definition: BESH4MCache.cc:199
bool is_valid(const string &cache_file_name, const int expected_file_size)
Definition: BESH4MCache.cc:184
STL namespace.
static string getCachePrefixFromConfig()
Definition: BESH4MCache.cc:46
static const string SIZE_KEY
Definition: BESH4MCache.h:26
Implementation of a caching mechanism for compressed data.
static unsigned long getCacheSizeFromConfig()
Definition: BESH4MCache.cc:26
virtual string get_message()
get the error message for this exception
Definition: BESError.h:94
static void delete_instance()
Definition: BESH4MCache.cc:176
bool write_cached_data(const string &cache_file_name, const int expected_file_size, const std::vector< double > &val)
Definition: BESH4MCache.cc:222
virtual void purge_file(const string &file)
Purge a single file from the cache.
virtual bool cache_too_big(unsigned long long current_size) const
look at the cache size; is it too large? Look at the cache size and see if it is too big...
static BESH4Cache * get_instance()
Get the default instance of the BESH4Cache object.
Definition: BESH4MCache.cc:158
virtual bool get_read_lock(const string &target, int &fd)
Get a read-only lock on the file if it exists.
void get_value(const string &s, string &val, bool &found)
Retrieve the value of a given key, if set.
Definition: BESKeys.cc:453
virtual void update_and_purge(const string &new_file)
Purge files from the cache.
static const string PREFIX_KEY
Definition: BESH4MCache.h:25
virtual unsigned long long update_cache_info(const string &target)
Update the cache info file to include 'target'.
static const string PATH_KEY
Definition: BESH4MCache.h:24
#define BESDEBUG(x, y)
macro used to send debug information to the debug stream
Definition: BESDebug.h:64
static string getCacheDirFromConfig()
Definition: BESH4MCache.cc:66
static BESKeys * TheKeys()
Definition: TheBESKeys.cc:48
virtual void unlock_and_close(const string &target)
Unlock the named file.