OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
BESFileLockingCache.cc
Go to the documentation of this file.
1 // BESFileLockingCache.cc
2 
3 // This file was originally part of bes, A C++ back-end server
4 // implementation framework for the OPeNDAP Data Access Protocol.
5 // Copied to libdap. This is used to cache responses built from
6 // functional CE expressions.
7 
8 // Moved back to the BES. 6/11/13 jhrg
9 
10 // Copyright (c) 2012 OPeNDAP, Inc
11 // Author: James Gallagher <jgallagher@opendap.org>
12 // Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu>
13 //
14 // This library is free software; you can redistribute it and/or
15 // modify it under the terms of the GNU Lesser General Public
16 // License as published by the Free Software Foundation; either
17 // version 2.1 of the License, or (at your option) any later version.
18 //
19 // This library is distributed in the hope that it will be useful,
20 // but WITHOUT ANY WARRANTY; without even the implied warranty of
21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 // Lesser General Public License for more details.
23 //
24 // You should have received a copy of the GNU Lesser General Public
25 // License along with this library; if not, write to the Free Software
26 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 //
28 // You can contact University Corporation for Atmospheric Research at
29 // 3080 Center Green Drive, Boulder, CO 80301
30 
31 #include "config.h"
32 
33 #include <sys/file.h>
34 #include <sys/stat.h>
35 #include <unistd.h>
36 #include <dirent.h>
37 #include <fcntl.h>
38 
39 #ifdef HAVE_STDLIB_H
40 #include <stdlib.h>
41 #endif
42 
43 #include <string>
44 #include <sstream>
45 #include <vector>
46 #include <cstring>
47 #include <cerrno>
48 
49 //#define DODS_DEBUG
50 
51 #include "BESInternalError.h"
52 
53 #include "BESDebug.h"
54 #include "BESLog.h"
55 
56 #include "BESFileLockingCache.h"
57 
58 using namespace std;
59 
60 // conversion factor
61 static const unsigned long long BYTES_PER_MEG = 1048576ULL;
62 
63 // Max cache size in megs, so we can check the user input and warn.
64 // 2^64 / 2^20 == 2^44
65 static const unsigned long long MAX_CACHE_SIZE_IN_MEGABYTES = (1ULL << 44);
66 
80 BESFileLockingCache::BESFileLockingCache(const string &cache_dir, const string &prefix, unsigned long long size) :
81  d_cache_dir(cache_dir), d_prefix(prefix), d_max_cache_size_in_bytes(size)
82 {
83  // cerr << endl << "***** BESFileLockingCache::BESFileLockingCache(" << d_cache_dir << ", " << d_prefix << ", " << d_max_cache_size_in_bytes << ")" << endl;
84 
85  m_initialize_cache_info();
86 }
87 
88 void BESFileLockingCache::initialize(const string &cache_dir, const string &prefix, unsigned long long size){
89  d_cache_dir = cache_dir;
90  d_prefix = prefix;
91  d_max_cache_size_in_bytes = size;
92 
93  // cerr << endl << "***** BESFileLockingCache::initialize(" << d_cache_dir << ", " << d_prefix << ", " << d_max_cache_size_in_bytes << ")" << endl;
94 
95  m_initialize_cache_info();
96 }
97 
98 
99 
100 static inline string get_errno() {
101  char *s_err = strerror(errno);
102  if (s_err)
103  return s_err;
104  else
105  return "Unknown error.";
106 }
107 
108 // Build a lock of a certain type.
109 static inline struct flock *lock(int type) {
110  static struct flock lock;
111  lock.l_type = type;
112  lock.l_whence = SEEK_SET;
113  lock.l_start = 0;
114  lock.l_len = 0;
115  lock.l_pid = getpid();
116 
117  return &lock;
118 }
119 
120 
121 inline void BESFileLockingCache::m_record_descriptor(const string &file, int fd) {
122  BESDEBUG("cache", "DAP Cache: recording descriptor: " << file << ", " << fd << endl);
123  d_locks.insert(std::pair<string, int>(file, fd));
124 }
125 
126 inline int BESFileLockingCache::m_get_descriptor(const string &file) {
127  FilesAndLockDescriptors::iterator i = d_locks.find(file);
128  if (i == d_locks.end())
129  return -1;
130 
131  int fd = i->second;
132  BESDEBUG("cache", "DAP Cache: getting descriptor: " << file << ", " << fd << endl);
133  d_locks.erase(i);
134  return fd;
135 }
136 
142 static void unlock(int fd)
143 {
144  if (fcntl(fd, F_SETLK, lock(F_UNLCK)) == -1) {
145  throw BESInternalError( "An error occurred trying to unlock the file" + get_errno(), __FILE__, __LINE__);
146  }
147 
148  if (close(fd) == -1)
149  throw BESInternalError("Could not close the (just) unlocked file.", __FILE__, __LINE__);
150 }
151 
164 static bool getSharedLock(const string &file_name, int &ref_fd)
165 {
166  BESDEBUG("cache", "getSharedLock: " << file_name <<endl);
167 
168  int fd;
169  if ((fd = open(file_name.c_str(), O_RDONLY)) < 0) {
170  switch (errno) {
171  case ENOENT:
172  return false;
173 
174  default:
175  throw BESInternalError( get_errno(), __FILE__, __LINE__);
176  }
177  }
178 
179  struct flock *l = lock(F_RDLCK);
180  if (fcntl(fd, F_SETLKW, l) == -1) {
181  close(fd);
182  ostringstream oss;
183  oss << "cache process: " << l->l_pid << " triggered a locking error: " << get_errno();
184  throw BESInternalError( oss.str(), __FILE__, __LINE__);
185  }
186 
187  BESDEBUG("cache", "getSharedLock exit: " << file_name <<endl);
188 
189  // Success
190  ref_fd = fd;
191  return true;
192 }
193 
206 static bool getExclusiveLock(string file_name, int &ref_fd)
207 {
208  BESDEBUG("cache", "getExclusiveLock: " << file_name <<endl);
209 
210  int fd;
211  if ((fd = open(file_name.c_str(), O_RDWR)) < 0) {
212  switch (errno) {
213  case ENOENT:
214  return false;
215 
216  default:
217  throw BESInternalError(get_errno(), __FILE__, __LINE__);
218  }
219  }
220 
221  struct flock *l = lock(F_WRLCK);
222  if (fcntl(fd, F_SETLKW, l) == -1) {
223  close(fd);
224  ostringstream oss;
225  oss << "cache process: " << l->l_pid << " triggered a locking error: " << get_errno();
226  throw BESInternalError(oss.str(), __FILE__, __LINE__);
227  }
228 
229  BESDEBUG("cache", "getExclusiveLock exit: " << file_name <<endl);
230 
231  // Success
232  ref_fd = fd;
233  return true;
234 }
235 
247 static bool getExclusiveLockNB(string file_name, int &ref_fd)
248 {
249  BESDEBUG("cache", "getExclusiveLock_nonblocking: " << file_name <<endl);
250 
251  int fd;
252  if ((fd = open(file_name.c_str(), O_RDWR)) < 0) {
253  switch (errno) {
254  case ENOENT:
255  return false;
256 
257  default:
258  throw BESInternalError(get_errno(), __FILE__, __LINE__);
259  }
260  }
261 
262  struct flock *l = lock(F_WRLCK);
263  if (fcntl(fd, F_SETLK, l) == -1) {
264  switch (errno) {
265  case EAGAIN:
266  BESDEBUG("cache", "getExclusiveLock_nonblocking exit (false): " << file_name << " by: " << l->l_pid << endl);
267  close(fd);
268  return false;
269 
270  default: {
271  close(fd);
272  ostringstream oss;
273  oss << "cache process: " << l->l_pid << " triggered a locking error: " << get_errno();
274  throw BESInternalError(oss.str(), __FILE__, __LINE__);
275  }
276  }
277  }
278 
279  BESDEBUG("cache", "getExclusiveLock_nonblocking exit (true): " << file_name <<endl);
280 
281  // Success
282  ref_fd = fd;
283  return true;
284 }
285 
299 static bool createLockedFile(string file_name, int &ref_fd)
300 {
301  BESDEBUG("cache", "createLockedFile: " << file_name <<endl);
302 
303  int fd;
304  if ((fd = open(file_name.c_str(), O_CREAT | O_EXCL | O_RDWR, 0666)) < 0) {
305  switch (errno) {
306  case EEXIST:
307  return false;
308 
309  default:
310  throw BESInternalError(get_errno(), __FILE__, __LINE__);
311  }
312  }
313 
314  struct flock *l = lock(F_WRLCK);
315  if (fcntl(fd, F_SETLKW, l) == -1) {
316  close(fd);
317  ostringstream oss;
318  oss << "cache process: " << l->l_pid << " triggered a locking error: " << get_errno();
319  throw BESInternalError(oss.str(), __FILE__, __LINE__);
320  }
321 
322  BESDEBUG("cache", "createLockedFile exit: " << file_name <<endl);
323 
324  // Success
325  ref_fd = fd;
326  return true;
327 }
328 
330 void BESFileLockingCache::m_check_ctor_params()
331 {
332  if (d_cache_dir.empty()) {
333  string err = "The cache directory was not specified";
334  throw BESInternalError(err, __FILE__, __LINE__);
335  }
336 
337  struct stat buf;
338  int statret = stat(d_cache_dir.c_str(), &buf);
339  if (statret != 0 || !S_ISDIR(buf.st_mode)) {
340  // Try to make the directory
341  int status = mkdir(d_cache_dir.c_str(), 0775);
342  if (status != 0) {
343  string err = "The cache directory " + d_cache_dir + " does not exist or could not be created.";
344  throw BESInternalError(err, __FILE__, __LINE__);
345  }
346  }
347 
348  if (d_prefix.empty()) {
349  string err = "The cache file prefix was not specified, must not be empty";
350  throw BESInternalError(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 BESInternalError(err, __FILE__, __LINE__);
356  }
357 
358  BESDEBUG("cache", "DAP Cache: directory " << d_cache_dir << ", prefix " << d_prefix
359  << ", max size " << d_max_cache_size_in_bytes << endl );
360 }
361 
363 void BESFileLockingCache::m_initialize_cache_info()
364 {
365  // The value set in configuration files, etc., is the size in megabytes. The private
366  // variable holds the size in bytes (converted below).
367  d_max_cache_size_in_bytes = min(d_max_cache_size_in_bytes, MAX_CACHE_SIZE_IN_MEGABYTES);
368  d_max_cache_size_in_bytes *= BYTES_PER_MEG;
369  d_target_size = d_max_cache_size_in_bytes * 0.8;
370 
371  m_check_ctor_params(); // Throws BESInternalError on error.
372 
373  d_cache_info = d_cache_dir + "/dap.cache.info";
374 
375  // See if we can create it. If so, that means it doesn't exist. So make it and
376  // set the cache initial size to zero.
377  if (createLockedFile(d_cache_info, d_cache_info_fd)) {
378  // initialize the cache size to zero
379  unsigned long long size = 0;
380  if (write(d_cache_info_fd, &size, sizeof(unsigned long long)) != sizeof(unsigned long long))
381  throw BESInternalError("Could not write size info to the cache info file `"+d_cache_info+"`", __FILE__, __LINE__);
382 
383  // This leaves the d_cache_info_fd file descriptor open
384  unlock_cache();
385  }
386  else {
387  if ((d_cache_info_fd = open(d_cache_info.c_str(), O_RDWR)) == -1) {
388  throw BESInternalError(get_errno(), __FILE__, __LINE__);
389  }
390  }
391 
392  // cerr << endl << "***** BESFileLockingCache::m_initialize_cache_info() completed. d_cache_info_fd: " << d_cache_info_fd << endl;
393 
394  BESDEBUG("cache", "d_cache_info_fd: " << d_cache_info_fd << endl);
395 }
396 
412 string BESFileLockingCache::get_cache_file_name(const string &src, bool mangle)
413 {
414  string target = src;
415 
416  if (mangle) {
417  if (target.at(0) == '/') {
418  target = src.substr(1, target.length() - 1);
419  }
420  string::size_type slash = 0;
421  while ((slash = target.find('/')) != string::npos) {
422  target.replace(slash, 1, 1, BESFileLockingCache::DAP_CACHE_CHAR);
423  }
424  string::size_type last_dot = target.rfind('.');
425  if (last_dot != string::npos) {
426  target = target.substr(0, last_dot);
427  }
428  }
429  BESDEBUG("cache", " d_cache_dir: '" << d_cache_dir << "'" << endl);
430  BESDEBUG("cache", " d_prefix: '" << d_prefix << "'" << endl);
431  BESDEBUG("cache", " target: '" << target << "'" << endl);
432 
433  return d_cache_dir + "/" + d_prefix + BESFileLockingCache::DAP_CACHE_CHAR + target;
434 }
435 
453 bool BESFileLockingCache::get_read_lock(const string &target, int &fd)
454 {
455  lock_cache_read();
456 
457  bool status = getSharedLock(target, fd);
458 
459  BESDEBUG("cache", "DAP Cache: read_lock: " << target << "(" << status << ")" << endl);
460 
461  if (status)
462  m_record_descriptor(target, fd);
463 
464  unlock_cache();
465 
466  return status;
467 }
468 
481 bool BESFileLockingCache::create_and_lock(const string &target, int &fd)
482 {
484 
485  bool status = createLockedFile(target, fd);
486 
487  BESDEBUG("cache", "DAP Cache: create_and_lock: " << target << "(" << status << ")" << endl);
488 
489  if (status)
490  m_record_descriptor(target, fd);
491 
492  unlock_cache();
493 
494  return status;
495 
496 }
497 
512 {
513  struct flock lock;
514  lock.l_type = F_RDLCK;
515  lock.l_whence = SEEK_SET;
516  lock.l_start = 0;
517  lock.l_len = 0;
518  lock.l_pid = getpid();
519 
520  if (fcntl(fd, F_SETLKW, &lock) == -1) {
521  throw BESInternalError(get_errno(), __FILE__, __LINE__);
522  }
523 }
524 
534 {
535  BESDEBUG("cache", "lock_cache - d_cache_info_fd: " << d_cache_info_fd << endl);
536 
537  if (fcntl(d_cache_info_fd, F_SETLKW, lock(F_WRLCK)) == -1) {
538  throw BESInternalError("An error occurred trying to lock the cache-control file" + get_errno(), __FILE__, __LINE__);
539  }
540 }
541 
546 {
547  BESDEBUG("cache", "lock_cache - d_cache_info_fd: " << d_cache_info_fd << endl);
548 
549  if (fcntl(d_cache_info_fd, F_SETLKW, lock(F_RDLCK)) == -1) {
550  throw BESInternalError("An error occurred trying to lock the cache-control file" + get_errno(), __FILE__, __LINE__);
551  }
552 }
553 
560 {
561  BESDEBUG("cache", "DAP Cache: unlock: cache_info (fd: " << d_cache_info_fd << ")" << endl);
562 
563  if (fcntl(d_cache_info_fd, F_SETLK, lock(F_UNLCK)) == -1) {
564  throw BESInternalError("An error occurred trying to unlock the cache-control file" + get_errno(), __FILE__, __LINE__);
565  }
566 }
567 
583 void BESFileLockingCache::unlock_and_close(const string &file_name)
584 {
585  BESDEBUG("cache", "DAP Cache: unlock file: " << file_name << endl);
586 
587  int fd = m_get_descriptor(file_name); // returns -1 when no more files desp. remain
588  while (fd != -1) {
589  unlock(fd);
590  fd = m_get_descriptor(file_name);
591  }
592 }
593 
600 {
601  BESDEBUG("cache", "DAP Cache: unlock fd: " << fd << endl);
602 
603  unlock(fd);
604 
605  BESDEBUG("cache", "DAP Cache: unlock " << fd << " Success" << endl);
606 }
607 
618 unsigned long long BESFileLockingCache::update_cache_info(const string &target)
619 {
620  unsigned long long current_size;
621  try {
623 
624  if (lseek(d_cache_info_fd, 0, SEEK_SET) == -1)
625  throw BESInternalError("Could not rewind to front of cache info file.", __FILE__, __LINE__);
626 
627  // read the size from the cache info file
628  if (read(d_cache_info_fd, &current_size, sizeof(unsigned long long)) != sizeof(unsigned long long))
629  throw BESInternalError("Could not get read size info from the cache info file!", __FILE__, __LINE__);
630 
631  struct stat buf;
632  int statret = stat(target.c_str(), &buf);
633  if (statret == 0)
634  current_size += buf.st_size;
635  else
636  throw BESInternalError("Could not read the size of the new file: " + target + " : " + get_errno(), __FILE__, __LINE__);
637 
638  BESDEBUG("cache", "DAP Cache: cache size updated to: " << current_size << endl);
639 
640  if (lseek(d_cache_info_fd, 0, SEEK_SET) == -1)
641  throw BESInternalError("Could not rewind to front of cache info file.", __FILE__, __LINE__);
642 
643  if(write(d_cache_info_fd, &current_size, sizeof(unsigned long long)) != sizeof(unsigned long long))
644  throw BESInternalError("Could not write size info from the cache info file!", __FILE__, __LINE__);
645 
646  unlock_cache();
647  }
648  catch (...) {
649  unlock_cache();
650  throw;
651  }
652 
653  return current_size;
654 }
655 
660 bool BESFileLockingCache::cache_too_big(unsigned long long current_size) const
661 {
662  return current_size > d_max_cache_size_in_bytes;
663 }
664 
673 {
674  unsigned long long current_size;
675  try {
676  lock_cache_read();
677 
678  if (lseek(d_cache_info_fd, 0, SEEK_SET) == -1)
679  throw BESInternalError("Could not rewind to front of cache info file.", __FILE__, __LINE__);
680  // read the size from the cache info file
681  if(read(d_cache_info_fd, &current_size, sizeof(unsigned long long)) != sizeof(unsigned long long))
682  throw BESInternalError("Could not get read size info from the cache info file!", __FILE__, __LINE__);
683 
684  unlock_cache();
685  }
686  catch(...) {
687  unlock_cache();
688  throw;
689  }
690 
691  return current_size;
692 }
693 
694 
695 static bool entry_op(cache_entry &e1, cache_entry &e2)
696 {
697  return e1.time < e2.time;
698 }
699 
701 unsigned long long BESFileLockingCache::m_collect_cache_dir_info(CacheFiles &contents)
702 {
703  DIR *dip = opendir(d_cache_dir.c_str());
704  if (!dip)
705  throw BESInternalError("Unable to open cache directory " + d_cache_dir, __FILE__, __LINE__);
706 
707  struct dirent *dit;
708  vector<string> files;
709  // go through the cache directory and collect all of the files that
710  // start with the matching prefix
711  while ((dit = readdir(dip)) != NULL) {
712  string dirEntry = dit->d_name;
713  if (dirEntry.compare(0, d_prefix.length(), d_prefix) == 0) {
714  files.push_back(d_cache_dir + "/" + dirEntry);
715  }
716  }
717 
718  closedir(dip);
719 
720  unsigned long long current_size = 0;
721  struct stat buf;
722  for (vector<string>::iterator file = files.begin(); file != files.end(); ++file) {
723  if (stat(file->c_str(), &buf) == 0) {
724  current_size += buf.st_size;
725  cache_entry entry;
726  entry.name = *file;
727  entry.size = buf.st_size;
728  entry.time = buf.st_atime;
729  // Sanity check; Removed after initial testing since some files might be zero bytes
730 #if 0
731  if (entry.size == 0)
732  throw BESInternalError("Zero-byte file found in cache. " + *file, __FILE__, __LINE__);
733 #endif
734  contents.push_back(entry);
735  }
736  }
737 
738  // Sort so smaller (older) times are first.
739  contents.sort(entry_op);
740 
741  return current_size;
742 }
743 
755 void BESFileLockingCache::update_and_purge(const string &new_file)
756 {
757  BESDEBUG("cache", "purge - starting the purge" << endl);
758 
759  try {
761 
762  CacheFiles contents;
763  unsigned long long computed_size = m_collect_cache_dir_info(contents);
764 #if 0
765  if (BESISDEBUG( "cache_contents" )) {
766  BESDEBUG("cache", "BEFORE Purge " << computed_size/BYTES_PER_MEG << endl );
767  CacheFiles::iterator ti = contents.begin();
768  CacheFiles::iterator te = contents.end();
769  for (; ti != te; ti++) {
770  BESDEBUG("cache", (*ti).time << ": " << (*ti).name << ": size " << (*ti).size/BYTES_PER_MEG << endl );
771  }
772  }
773 #endif
774  BESDEBUG("cache", "purge - current and target size (in MB) " << computed_size/BYTES_PER_MEG << ", " << d_target_size/BYTES_PER_MEG << endl );
775 
776  // This deletes files and updates computed_size
777  if (cache_too_big(computed_size)) {
778 
779  // d_target_size is 80% of the maximum cache size.
780  // Grab the first which is the oldest in terms of access time.
781  CacheFiles::iterator i = contents.begin();
782  while (i != contents.end() && computed_size > d_target_size) {
783  // Grab an exclusive lock but do not block - if another process has the file locked
784  // just move on to the next file. Also test to see if the current file is the file
785  // this process just added to the cache - don't purge that!
786  int cfile_fd;
787  if (i->name != new_file && getExclusiveLockNB(i->name, cfile_fd)) {
788  BESDEBUG("cache", "purge: " << i->name << " removed." << endl );
789 
790  if (unlink(i->name.c_str()) != 0)
791  throw BESInternalError("Unable to purge the file " + i->name + " from the cache: " + get_errno(), __FILE__, __LINE__);
792 
793  unlock(cfile_fd);
794  computed_size -= i->size;
795  }
796  ++i;
797 
798  BESDEBUG("cache", "purge - current and target size (in MB) " << computed_size/BYTES_PER_MEG << ", " << d_target_size/BYTES_PER_MEG << endl );
799  }
800 
801  }
802 
803  if (lseek(d_cache_info_fd, 0, SEEK_SET) == -1)
804  throw BESInternalError("Could not rewind to front of cache info file.", __FILE__, __LINE__);
805 
806  if(write(d_cache_info_fd, &computed_size, sizeof(unsigned long long)) != sizeof(unsigned long long))
807  throw BESInternalError("Could not write size info to the cache info file!", __FILE__, __LINE__);
808 #if 0
809  if (BESISDEBUG( "cache_contents" )) {
810  contents.clear();
811  computed_size = m_collect_cache_dir_info(contents);
812  BESDEBUG("cache", "AFTER Purge " << computed_size/BYTES_PER_MEG << endl );
813  CacheFiles::iterator ti = contents.begin();
814  CacheFiles::iterator te = contents.end();
815  for (; ti != te; ti++) {
816  BESDEBUG("cache", (*ti).time << ": " << (*ti).name << ": size " << (*ti).size/BYTES_PER_MEG << endl );
817  }
818  }
819 #endif
820  unlock_cache();
821  }
822  catch(...) {
823  unlock_cache();
824  throw;
825  }
826 }
827 
839 void BESFileLockingCache::purge_file(const string &file)
840 {
841  BESDEBUG("cache", "purge_file - starting the purge" << endl);
842 
843  try {
845 
846  // Grab an exclusive lock on the file
847  int cfile_fd;
848  if (getExclusiveLock(file, cfile_fd)) {
849  // Get the file's size
850  unsigned long long size = 0;
851  struct stat buf;
852  if (stat(file.c_str(), &buf) == 0) {
853  size = buf.st_size;
854  }
855 
856  BESDEBUG("cache", "purge_file: " << file << " removed." << endl );
857 
858  if (unlink(file.c_str()) != 0)
859  throw BESInternalError("Unable to purge the file " + file + " from the cache: " + get_errno(), __FILE__, __LINE__);
860 
861  unlock(cfile_fd);
862 
863  unsigned long long cache_size = get_cache_size() - size;
864 
865  if (lseek(d_cache_info_fd, 0, SEEK_SET) == -1)
866  throw BESInternalError("Could not rewind to front of cache info file.", __FILE__, __LINE__);
867 
868  if (write(d_cache_info_fd, &cache_size, sizeof(unsigned long long)) != sizeof(unsigned long long))
869  throw BESInternalError("Could not write size info to the cache info file!", __FILE__, __LINE__);
870  }
871 
872  unlock_cache();
873  }
874  catch (...) {
875  unlock_cache();
876  throw;
877  }
878 }
879 
880 
882  return d_prefix;
883 }
884 
886  return d_cache_dir;
887 }
888 
889 
890 
898 void BESFileLockingCache::dump(ostream &strm) const
899 {
900  strm << BESIndent::LMarg << "BESFileLockingCache::dump - (" << (void *) this << ")" << endl;
902  strm << BESIndent::LMarg << "cache dir: " << d_cache_dir << endl;
903  strm << BESIndent::LMarg << "prefix: " << d_prefix << endl;
904  strm << BESIndent::LMarg << "size (bytes): " << d_max_cache_size_in_bytes << endl;
906 }
virtual void unlock_cache()
Unlock the cache info file.
#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:46
exception thrown if inernal error encountered
time_t time
Definition: BESCache3.h:43
virtual bool create_and_lock(const string &target, int &fd)
Create a file in the cache and lock it for write access.
Definition: BESCache3.h:40
const string getCacheDirectory()
unsigned long long size
Definition: BESCache3.h:42
string name
Definition: BESCache3.h:41
virtual unsigned long long get_cache_size()
Get the cache size.
static void Indent()
Definition: BESIndent.cc:38
void initialize(const string &cache_dir, const string &prefix, unsigned long long size)
virtual void dump(ostream &strm) const
dumps information about this object
static ostream & LMarg(ostream &strm)
Definition: BESIndent.cc:73
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...
virtual void lock_cache_write()
Get an exclusive lock on the 'cache info' file.
virtual string get_cache_file_name(const string &src, bool mangle=true)
Build the name of file that will holds the uncompressed data from 'src' in the cache.
const string getCacheFilePrefix()
virtual bool get_read_lock(const string &target, int &fd)
Get a read-only lock on the file if it exists.
virtual void update_and_purge(const string &new_file)
Purge files from the cache.
virtual unsigned long long update_cache_info(const string &target)
Update the cache info file to include 'target'.
virtual void lock_cache_read()
Get a shared lock on the 'cache info' file.
virtual void exclusive_to_shared_lock(int fd)
Transfer from an exclusive lock to a shared lock.
#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 void unlock_and_close(const string &target)
Unlock the named file.