OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
BESCache3.cc
Go to the documentation of this file.
1 // BESCache3.cc
2 
3 // This file is part of bes, A C++ back-end server implementation framework
4 // for the OPeNDAP Data Access Protocol.
5 
6 // Copyright (c) 2012 OPeNDAP, Inc
7 // Author: James Gallagher <jgallagher@opendap.org>
8 // Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu>
9 //
10 // This library is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU Lesser General Public
12 // License as published by the Free Software Foundation; either
13 // version 2.1 of the License, or (at your option) any later version.
14 //
15 // This library is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 // Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public
21 // License along with this library; if not, write to the Free Software
22 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 //
24 // You can contact University Corporation for Atmospheric Research at
25 // 3080 Center Green Drive, Boulder, CO 80301
26 
27 #include "config.h"
28 
29 #include <sys/file.h>
30 #include <sys/stat.h>
31 #include <unistd.h>
32 #include <dirent.h>
33 #include <fcntl.h>
34 
35 #include <string>
36 #include <sstream>
37 #include <cstring>
38 #include <cerrno>
39 
40 #include "BESCache3.h"
41 
42 #include "BESSyntaxUserError.h"
43 #include "BESInternalError.h"
44 
45 #include "TheBESKeys.h"
46 #include "BESDebug.h"
47 #include "BESLog.h"
48 
49 using namespace std;
50 
51 // conversion factor
52 static const unsigned long long BYTES_PER_MEG = 1048576ULL;
53 
54 // Max cache size in megs, so we can check the user input and warn.
55 // 2^64 / 2^20 == 2^44
56 static const unsigned long long MAX_CACHE_SIZE_IN_MEGABYTES = (1ULL << 44);
57 
58 BESCache3 *BESCache3::d_instance = 0;
59 
60 // The BESCache3 code is a singleton that assumes it's running in the absence of threads but that
61 // the cache is shared by several processes, each of which have their own instance of BESCache3.
73 BESCache3 *
74 BESCache3::get_instance(BESKeys *keys, const string &cache_dir_key, const string &prefix_key, const string &size_key)
75 {
76  if (d_instance == 0)
77  d_instance = new BESCache3(keys, cache_dir_key, prefix_key, size_key);
78 
79  return d_instance;
80 }
81 
85 BESCache3 *
86 BESCache3::get_instance(const string &cache_dir, const string &prefix, unsigned long size)
87 {
88  if (d_instance == 0)
89  d_instance = new BESCache3(cache_dir, prefix, size);
90 
91  return d_instance;
92 }
93 
97 BESCache3 *
99 {
100  if (d_instance == 0)
101  throw BESInternalError("Tried to get the BESCache3 instance, but it hasn't been created yet", __FILE__, __LINE__);
102 
103  return d_instance;
104 }
105 
106 static inline string get_errno() {
107  char *s_err = strerror(errno);
108  if (s_err)
109  return s_err;
110  else
111  return "Unknown error.";
112 }
113 
114 // Apply cmd and type to the entire file.
115 // cmd is one of F_GETLK, F_SETLK, F_SETLKW, F_UNLCK
116 // type is one of F_RDLCK, F_WRLCK
117 static inline struct flock *lock(int type) {
118  static struct flock lock;
119  lock.l_type = type;
120  lock.l_whence = SEEK_SET;
121  lock.l_start = 0;
122  lock.l_len = 0;
123  lock.l_pid = getpid();
124 
125  return &lock;
126 }
127 
128 inline void BESCache3::m_record_descriptor(const string &file, int fd) {
129  BESDEBUG("cache", "BES Cache: recording descriptor: " << file << ", " << fd << endl);
130  d_locks.insert(std::pair<string, int>(file, fd));
131 }
132 
133 inline int BESCache3::m_get_descriptor(const string &file) {
134  FilesAndLockDescriptors::iterator i = d_locks.find(file);
135  int fd = i->second;
136  BESDEBUG("cache", "BES Cache: getting descriptor: " << file << ", " << fd << endl);
137  d_locks.erase(i);
138  return fd;
139 }
140 
146 static void unlock(int fd)
147 {
148  if (fcntl(fd, F_SETLK, lock(F_UNLCK)) == -1) {
149  throw BESInternalError("An error occurred trying to unlock the file" + get_errno(), __FILE__, __LINE__);
150  }
151 
152  if (close(fd) == -1)
153  throw BESInternalError("Could not close the (just) unlocked file.", __FILE__, __LINE__);
154 }
155 
168 static bool getSharedLock(const string &file_name, int &ref_fd)
169 {
170  BESDEBUG("cache_internal", "getSharedLock: " << file_name <<endl);
171 
172  int fd;
173  if ((fd = open(file_name.c_str(), O_RDONLY)) < 0) {
174  switch (errno) {
175  case ENOENT:
176  return false;
177 
178  default:
179  throw BESInternalError(get_errno(), __FILE__, __LINE__);
180  }
181  }
182 
183  struct flock *l = lock(F_RDLCK);
184  if (fcntl(fd, F_SETLKW, l) == -1) {
185  close(fd);
186  ostringstream oss;
187  oss << "cache process: " << l->l_pid << " triggered a locking error: " << get_errno();
188  throw BESInternalError(oss.str(), __FILE__, __LINE__);
189  }
190 
191  BESDEBUG("cache_internal", "getSharedLock exit: " << file_name <<endl);
192 
193  // Success
194  ref_fd = fd;
195  return true;
196 }
197 
210 static bool getExclusiveLock(string file_name, int &ref_fd)
211 {
212  BESDEBUG("cache_internal", "getExclusiveLock: " << file_name <<endl);
213 
214  int fd;
215  if ((fd = open(file_name.c_str(), O_RDWR)) < 0) {
216  switch (errno) {
217  case ENOENT:
218  return false;
219 
220  default:
221  throw BESInternalError(get_errno(), __FILE__, __LINE__);
222  }
223  }
224 
225  struct flock *l = lock(F_WRLCK);
226  if (fcntl(fd, F_SETLKW, l) == -1) {
227  close(fd);
228  ostringstream oss;
229  oss << "cache process: " << l->l_pid << " triggered a locking error: " << get_errno();
230  throw BESInternalError(oss.str(), __FILE__, __LINE__);
231  }
232 
233  BESDEBUG("cache_internal", "getExclusiveLock exit: " << file_name <<endl);
234 
235  // Success
236  ref_fd = fd;
237  return true;
238 }
239 
251 static bool getExclusiveLockNB(string file_name, int &ref_fd)
252 {
253  BESDEBUG("cache_internal", "getExclusiveLock_nonblocking: " << file_name <<endl);
254 
255  int fd;
256  if ((fd = open(file_name.c_str(), O_RDWR)) < 0) {
257  switch (errno) {
258  case ENOENT:
259  return false;
260 
261  default:
262  throw BESInternalError(get_errno(), __FILE__, __LINE__);
263  }
264  }
265 
266  struct flock *l = lock(F_WRLCK);
267  if (fcntl(fd, F_SETLK, l) == -1) {
268  switch (errno) {
269  case EAGAIN:
270  BESDEBUG("cache_internal", "getExclusiveLock_nonblocking exit (false): " << file_name << " by: " << l->l_pid << endl);
271  close(fd);
272  return false;
273 
274  default: {
275  close(fd);
276  ostringstream oss;
277  oss << "cache process: " << l->l_pid << " triggered a locking error: " << get_errno();
278  throw BESInternalError(oss.str(), __FILE__, __LINE__);
279  }
280  }
281  }
282 
283  BESDEBUG("cache_internal", "getExclusiveLock_nonblocking exit (true): " << file_name <<endl);
284 
285  // Success
286  ref_fd = fd;
287  return true;
288 }
289 
303 static bool createLockedFile(string file_name, int &ref_fd)
304 {
305  BESDEBUG("cache_internal", "createLockedFile: " << file_name <<endl);
306 
307  int fd;
308  if ((fd = open(file_name.c_str(), O_CREAT | O_EXCL | O_RDWR, 0666)) < 0) {
309  switch (errno) {
310  case EEXIST:
311  return false;
312 
313  default:
314  throw BESInternalError(get_errno(), __FILE__, __LINE__);
315  }
316  }
317 
318  struct flock *l = lock(F_WRLCK);
319  if (fcntl(fd, F_SETLKW, l) == -1) {
320  close(fd);
321  ostringstream oss;
322  oss << "cache process: " << l->l_pid << " triggered a locking error: " << get_errno();
323  throw BESInternalError(oss.str(), __FILE__, __LINE__);
324  }
325 
326  BESDEBUG("cache_internal", "createLockedFile exit: " << file_name <<endl);
327 
328  // Success
329  ref_fd = fd;
330  return true;
331 }
332 
334 void BESCache3::m_check_ctor_params()
335 {
336  if (d_cache_dir.empty()) {
337  string err = "The cache directory was not specified, must be non-empty";
338  throw BESSyntaxUserError(err, __FILE__, __LINE__);
339  }
340 
341  struct stat buf;
342  int statret = stat(d_cache_dir.c_str(), &buf);
343  if (statret != 0 || !S_ISDIR(buf.st_mode)) {
344  string err = "The cache directory " + d_cache_dir + " does not exist";
345  throw BESSyntaxUserError(err, __FILE__, __LINE__);
346  }
347 
348  if (d_prefix.empty()) {
349  string err = "The cache file prefix was not specified, must not be empty";
350  throw BESSyntaxUserError(err, __FILE__, __LINE__);
351  }
352 
353  if (d_max_cache_size_in_bytes <= 0) {
354  string err = "The cache size was not specified, must be greater than zero";
355  throw BESSyntaxUserError(err, __FILE__, __LINE__);
356  }
357 
358  // If the user specifies a cache that is too large,
359  // it is a user exception and we should tell them.
360  if (d_max_cache_size_in_bytes > MAX_CACHE_SIZE_IN_MEGABYTES) {
361  std::ostringstream msg;
362  msg << "The specified cache size was larger than the max cache size of: " << MAX_CACHE_SIZE_IN_MEGABYTES;
363  throw BESSyntaxUserError(msg.str(), __FILE__, __LINE__);
364  }
365 
366  BESDEBUG( "cache_internal", "BES Cache: directory " << d_cache_dir
367  << ", prefix " << d_prefix
368  << ", max size " << d_max_cache_size_in_bytes << endl );
369 }
370 
372 void BESCache3::m_initialize_cache_info()
373 {
374  d_max_cache_size_in_bytes = min(d_max_cache_size_in_bytes, MAX_CACHE_SIZE_IN_MEGABYTES);
375  if (d_max_cache_size_in_bytes > MAX_CACHE_SIZE_IN_MEGABYTES)
376  *(BESLog::TheLog()) << "Cache size too big in configuration file, set to max limit." << endl ;
377 
378  d_max_cache_size_in_bytes *= BYTES_PER_MEG;
379  d_target_size = d_max_cache_size_in_bytes * 0.8;
380 
381  m_check_ctor_params(); // Throws BESSyntaxUserError on error.
382 
383  d_cache_info = d_cache_dir + "/bes.cache.info";
384 
385  // See if we can create it. If so, that means it doesn't exist. So make it and
386  // set the cache initial size to zero.
387  if (createLockedFile(d_cache_info, d_cache_info_fd)) {
388  // initialize the cache size to zero
389  unsigned long long size = 0;
390  if (write(d_cache_info_fd, &size, sizeof(unsigned long long)) != sizeof(unsigned long long))
391  throw BESInternalError("Could not write size info to the cache info file in startup!", __FILE__, __LINE__);
392 
393  // This leaves the d_cache_info_fd file descriptor open
394  unlock_cache();
395  }
396  else {
397  if ((d_cache_info_fd = open(d_cache_info.c_str(), O_RDWR)) == -1) {
398  throw BESInternalError(get_errno(), __FILE__, __LINE__);
399  }
400  }
401 
402  BESDEBUG("cache_internal", "d_cache_info_fd: " << d_cache_info_fd << endl);
403 }
404 
419 BESCache3::BESCache3(BESKeys *keys, const string &cache_dir_key, const string &prefix_key, const string &size_key) :
420  d_max_cache_size_in_bytes(0)
421 {
422  bool found = false;
423  keys->get_value(cache_dir_key, d_cache_dir, found);
424  if (!found)
425  throw BESSyntaxUserError("The cache directory key " + cache_dir_key + " was not found in the BES configuration file", __FILE__, __LINE__);
426 
427  found = false;
428  keys->get_value(prefix_key, d_prefix, found);
429  if (!found)
430  throw BESSyntaxUserError("The prefix key " + prefix_key + " was not found in the BES configuration file", __FILE__, __LINE__);
431 
432  found = false;
433  string cache_size_str;
434  keys->get_value(size_key, cache_size_str, found);
435  if (!found)
436  throw BESSyntaxUserError("The size key " + size_key + " was not found in the BES configuration file", __FILE__, __LINE__);
437 
438  std::istringstream is(cache_size_str);
439  is >> d_max_cache_size_in_bytes;
440 
441  m_initialize_cache_info();
442 }
443 
450 BESCache3::BESCache3(const string &cache_dir, const string &prefix, unsigned long size) :
451  d_cache_dir(cache_dir), d_prefix(prefix), d_max_cache_size_in_bytes(size)
452 {
453  m_initialize_cache_info();
454 }
455 
465 string BESCache3::get_cache_file_name(const string &src)
466 {
467  string target = src;
468  if (target.at(0) == '/') {
469  target = src.substr(1, target.length() - 1);
470  }
471  string::size_type slash = 0;
472  while ((slash = target.find('/')) != string::npos) {
473  target.replace(slash, 1, 1, BESCache3::BES_CACHE_CHAR);
474  }
475  string::size_type last_dot = target.rfind('.');
476  if (last_dot != string::npos) {
477  target = target.substr(0, last_dot);
478  }
479 
480  return d_cache_dir + "/" + d_prefix + BESCache3::BES_CACHE_CHAR + target;
481 }
482 
500 bool BESCache3::get_read_lock(const string &target, int &fd)
501 {
502  lock_cache_read();
503 
504  bool status = getSharedLock(target, fd);
505 
506  BESDEBUG("cache_internal", "BES Cache: read_lock: " << target << "(" << status << ")" << endl);
507 
508  if (status)
509  m_record_descriptor(target, fd);
510 
511  unlock_cache();
512 
513  return status;
514 }
515 
528 bool BESCache3::create_and_lock(const string &target, int &fd)
529 {
531 
532  bool status = createLockedFile(target, fd);
533 
534  BESDEBUG("cache_internal", "BES Cache: create_and_lock: " << target << "(" << status << ")" << endl);
535 
536  if (status)
537  m_record_descriptor(target, fd);
538 
539  unlock_cache();
540 
541  return status;
542 
543 }
544 
559 {
560  struct flock lock;
561  lock.l_type = F_RDLCK;
562  lock.l_whence = SEEK_SET;
563  lock.l_start = 0;
564  lock.l_len = 0;
565  lock.l_pid = getpid();
566 
567  if (fcntl(fd, F_SETLKW, &lock) == -1) {
568  throw BESInternalError(get_errno(), __FILE__, __LINE__);
569  }
570 }
571 
581 {
582  BESDEBUG("cache_internal", "lock_cache - d_cache_info_fd: " << d_cache_info_fd << endl);
583 
584  if (fcntl(d_cache_info_fd, F_SETLKW, lock(F_WRLCK)) == -1) {
585  throw BESInternalError("An error occurred trying to lock the cache-control file" + get_errno(), __FILE__, __LINE__);
586  }
587 }
588 
593 {
594  BESDEBUG("cache_internal", "lock_cache - d_cache_info_fd: " << d_cache_info_fd << endl);
595 
596  if (fcntl(d_cache_info_fd, F_SETLKW, lock(F_RDLCK)) == -1) {
597  throw BESInternalError("An error occurred trying to lock the cache-control file" + get_errno(), __FILE__, __LINE__);
598  }
599 }
600 
607 {
608  BESDEBUG("cache_internal", "BES Cache: unlock: cache_info (fd: " << d_cache_info_fd << ")" << endl);
609 
610  if (fcntl(d_cache_info_fd, F_SETLK, lock(F_UNLCK)) == -1) {
611  throw BESInternalError("An error occurred trying to unlock the cache-control file" + get_errno(), __FILE__, __LINE__);
612  }
613 }
614 
626 void BESCache3::unlock_and_close(const string &file_name)
627 {
628  BESDEBUG("cache_internal", "BES Cache: unlock file: " << file_name << endl);
629 
630  unlock(m_get_descriptor(file_name));
631 }
632 
639 {
640  BESDEBUG("cache_internal", "BES Cache: unlock fd: " << fd << endl);
641 
642  unlock(fd);
643 
644  BESDEBUG("cache_internal", "BES Cache: unlock " << fd << " Success" << endl);
645 }
646 
657 unsigned long long BESCache3::update_cache_info(const string &target)
658 {
659  try {
661 
662  if (lseek(d_cache_info_fd, 0, SEEK_SET) == -1)
663  throw BESInternalError("Could not rewind to front of cache info file.", __FILE__, __LINE__);
664 
665  // read the size from the cache info file
666  unsigned long long current_size;
667  if (read(d_cache_info_fd, &current_size, sizeof(unsigned long long)) != sizeof(unsigned long long))
668  throw BESInternalError("Could not get read size info from the cache info file!", __FILE__, __LINE__);
669 
670  struct stat buf;
671  int statret = stat(target.c_str(), &buf);
672  if (statret == 0)
673  current_size += buf.st_size;
674  else
675  throw BESInternalError("Could not read the size of the new file: " + target + " : " + get_errno(), __FILE__, __LINE__);
676 
677  BESDEBUG("cache_internal", "BES Cache: cache size updated to: " << current_size << endl);
678 
679  if (lseek(d_cache_info_fd, 0, SEEK_SET) == -1)
680  throw BESInternalError("Could not rewind to front of cache info file.", __FILE__, __LINE__);
681 
682  if(write(d_cache_info_fd, &current_size, sizeof(unsigned long long)) != sizeof(unsigned long long))
683  throw BESInternalError("Could not write size info from the cache info file!", __FILE__, __LINE__);
684 
685  unlock_cache();
686  return current_size;
687  }
688  catch (...) {
689  unlock_cache();
690  throw;
691  }
692 }
693 
698 bool BESCache3::cache_too_big(unsigned long long current_size) const
699 {
700  return current_size > d_max_cache_size_in_bytes;
701 }
702 
710 unsigned long long BESCache3::get_cache_size()
711 {
712  try {
713  lock_cache_read();
714 
715  if (lseek(d_cache_info_fd, 0, SEEK_SET) == -1)
716  throw BESInternalError("Could not rewind to front of cache info file.", __FILE__, __LINE__);
717  // read the size from the cache info file
718  unsigned long long current_size;
719  if(read(d_cache_info_fd, &current_size, sizeof(unsigned long long)) != sizeof(unsigned long long))
720  throw BESInternalError("Could not get read size info from the cache info file!", __FILE__, __LINE__);
721 
722  unlock_cache();
723  return current_size;
724  }
725  catch(...) {
726  unlock_cache();
727  throw;
728  }
729 }
730 
731 
732 static bool entry_op(cache_entry &e1, cache_entry &e2)
733 {
734  return e1.time < e2.time;
735 }
736 
738 unsigned long long BESCache3::m_collect_cache_dir_info(CacheFiles &contents)
739 {
740  DIR *dip = opendir(d_cache_dir.c_str());
741  if (!dip)
742  throw BESInternalError("Unable to open cache directory " + d_cache_dir, __FILE__, __LINE__);
743 
744  struct dirent *dit;
745  vector<string> files;
746  // go through the cache directory and collect all of the files that
747  // start with the matching prefix
748  while ((dit = readdir(dip)) != NULL) {
749  string dirEntry = dit->d_name;
750  if (dirEntry.compare(0, d_prefix.length(), d_prefix) == 0) {
751  files.push_back(d_cache_dir + "/" + dirEntry);
752  }
753  }
754 
755  closedir(dip);
756 
757  unsigned long long current_size = 0;
758  struct stat buf;
759  for (vector<string>::iterator file = files.begin(); file != files.end(); ++file) {
760  if (stat(file->c_str(), &buf) == 0) {
761  current_size += buf.st_size;
762  cache_entry entry;
763  entry.name = *file;
764  entry.size = buf.st_size;
765  entry.time = buf.st_atime;
766  // Sanity check; Removed after initial testing since some files might be zero bytes
767 #if 0
768  if (entry.size == 0)
769  throw BESInternalError("Zero-byte file found in cache. " + *file, __FILE__, __LINE__);
770 #endif
771  contents.push_back(entry);
772  }
773  }
774 
775  // Sort so smaller (older) times are first.
776  contents.sort(entry_op);
777 
778  return current_size;
779 }
780 
792 void BESCache3::update_and_purge(const string &new_file)
793 {
794  BESDEBUG("cache_purge", "purge - starting the purge" << endl);
795 
796  try {
798 
799  CacheFiles contents;
800  unsigned long long computed_size = m_collect_cache_dir_info(contents);
801 
802  if (BESISDEBUG( "cache_contents" )) {
803  BESDEBUG( "cache_contents", endl << "BEFORE Purge " << computed_size/BYTES_PER_MEG << endl );
804  CacheFiles::iterator ti = contents.begin();
805  CacheFiles::iterator te = contents.end();
806  for (; ti != te; ti++) {
807  BESDEBUG( "cache_contents", (*ti).time << ": " << (*ti).name << ": size " << (*ti).size/BYTES_PER_MEG << endl );
808  }
809  }
810 
811  BESDEBUG( "cache_purge", "purge - current and target size (in MB) " << computed_size/BYTES_PER_MEG << ", " << d_target_size/BYTES_PER_MEG << endl );
812 
813  // This deletes files and updates computed_size
814  if (cache_too_big(computed_size)) {
815 
816  // d_target_size is 80% of the maximum cache size.
817  // Grab the first which is the oldest in terms of access time.
818  CacheFiles::iterator i = contents.begin();
819  while (i != contents.end() && computed_size > d_target_size) {
820  // Grab an exclusive lock but do not block - if another process has the file locked
821  // just move on to the next file. Also test to see if the current file is the file
822  // this process just added to the cache - don't purge that!
823  int cfile_fd;
824  if (i->name != new_file && getExclusiveLockNB(i->name, cfile_fd)) {
825  BESDEBUG( "cache_purge", "purge: " << i->name << " removed." << endl );
826 
827  if (unlink(i->name.c_str()) != 0)
828  throw BESInternalError("Unable to purge the file " + i->name + " from the cache: " + get_errno(), __FILE__, __LINE__);
829 
830  unlock(cfile_fd);
831  computed_size -= i->size;
832  }
833 #if 1
834  else {
835  // This information is useful when debugging... Might comment out for production
836  BESDEBUG( "cache_purge", "purge: " << i->name << " is in use." << endl );
837  }
838 #endif
839  ++i;
840 
841  BESDEBUG( "cache_purge", "purge - current and target size (in MB) " << computed_size/BYTES_PER_MEG << ", " << d_target_size/BYTES_PER_MEG << endl );
842  }
843 
844  }
845 
846  if (lseek(d_cache_info_fd, 0, SEEK_SET) == -1)
847  throw BESInternalError("Could not rewind to front of cache info file.", __FILE__, __LINE__);
848 
849  if(write(d_cache_info_fd, &computed_size, sizeof(unsigned long long)) != sizeof(unsigned long long))
850  throw BESInternalError("Could not write size info to the cache info file!", __FILE__, __LINE__);
851 
852  if (BESISDEBUG( "cache_contents" )) {
853  contents.clear();
854  computed_size = m_collect_cache_dir_info(contents);
855  BESDEBUG( "cache_contents", endl << "AFTER Purge " << computed_size/BYTES_PER_MEG << endl );
856  CacheFiles::iterator ti = contents.begin();
857  CacheFiles::iterator te = contents.end();
858  for (; ti != te; ti++) {
859  BESDEBUG( "cache_contents", (*ti).time << ": " << (*ti).name << ": size " << (*ti).size/BYTES_PER_MEG << endl );
860  }
861  }
862 
863  unlock_cache();
864  }
865  catch(...) {
866  unlock_cache();
867  throw;
868  }
869 }
870 
878 void BESCache3::dump(ostream &strm) const
879 {
880  strm << BESIndent::LMarg << "BESCache3::dump - (" << (void *) this << ")" << endl;
882  strm << BESIndent::LMarg << "cache dir: " << d_cache_dir << endl;
883  strm << BESIndent::LMarg << "prefix: " << d_prefix << endl;
884  strm << BESIndent::LMarg << "size (bytes): " << d_max_cache_size_in_bytes << endl;
886 }
887 
virtual void exclusive_to_shared_lock(int fd)
Transfer from an exclusive lock to a shared lock.
Definition: BESCache3.cc:558
virtual void dump(ostream &strm) const
dumps information about this object
Definition: BESCache3.cc:878
#define BESISDEBUG(x)
macro used to determine if the specified debug context is set
Definition: BESDebug.h:83
std::list< cache_entry > CacheFiles
Definition: BESCache3.h:48
exception thrown if inernal error encountered
time_t time
Definition: BESCache3.h:45
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...
Definition: BESCache3.cc:698
Definition: BESCache3.h:42
virtual void lock_cache_write()
Get an exclusive lock on the 'cache info' file.
Definition: BESCache3.cc:580
unsigned long long size
Definition: BESCache3.h:44
string name
Definition: BESCache3.h:43
virtual void unlock_and_close(const string &target)
Unlock the named file.
Definition: BESCache3.cc:626
static void Indent()
Definition: BESIndent.cc:38
error thrown if there is a user syntax error in the request or any other user error ...
virtual void lock_cache_read()
Get a shared lock on the 'cache info' file.
Definition: BESCache3.cc:592
mapping of key/value pairs defining different behaviors of an application.
Definition: BESKeys.h:84
Implementation of a caching mechanism for compressed data.
Definition: BESCache3.h:73
static ostream & LMarg(ostream &strm)
Definition: BESIndent.cc:73
virtual unsigned long long update_cache_info(const string &target)
Update the cache info file to include 'target'.
Definition: BESCache3.cc:657
virtual bool create_and_lock(const string &target, int &fd)
Create a file in the cache and lock it for write access.
Definition: BESCache3.cc:528
void get_value(const string &s, string &val, bool &found)
Retrieve the value of a given key, if set.
Definition: BESKeys.cc:453
virtual bool get_read_lock(const string &target, int &fd)
Get a read-only lock on the file if it exists.
Definition: BESCache3.cc:500
static BESLog * TheLog()
Definition: BESLog.cc:347
string get_cache_file_name(const string &src)
Build the name of file that will holds the uncompressed data from 'src' in the cache.
Definition: BESCache3.cc:465
virtual void update_and_purge(const string &new_file)
Purge files from the cache.
Definition: BESCache3.cc:792
virtual void unlock_cache()
Unlock the cache info file.
Definition: BESCache3.cc:606
#define BESDEBUG(x, y)
macro used to send debug information to the debug stream
Definition: BESDebug.h:64
static void UnIndent()
Definition: BESIndent.cc:44
virtual unsigned long long get_cache_size()
Get the cache size.
Definition: BESCache3.cc:710
static BESCache3 * get_instance()
Get an instance of the BESCache3 object.
Definition: BESCache3.cc:98