hdf_filecache.cpp

Go to the documentation of this file.
00001 
00005 /*
00006  * Author: Grant Tang, 05/01/2012 (gtang@bcm.edu)
00007  * Copyright (c) 2000-2006 Baylor College of Medicine
00008  *
00009  * This software is issued under a joint BSD/GNU license. You may use the
00010  * source code in this file under either license. However, note that the
00011  * complete EMAN2 and SPARX software packages have some GPL dependencies,
00012  * so you are responsible for compliance with the licenses of these packages
00013  * if you opt to use BSD licensing. The warranty disclaimer below holds
00014  * in either instance.
00015  *
00016  * This complete copyright notice must be included in any revised version of the
00017  * source code. Additional authorship citations may be added, but existing
00018  * author citations must be preserved.
00019  *
00020  * This program is free software; you can redistribute it and/or modify
00021  * it under the terms of the GNU General Public License as published by
00022  * the Free Software Foundation; either version 2 of the License, or
00023  * (at your option) any later version.
00024  *
00025  * This program is distributed in the hope that it will be useful,
00026  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00027  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00028  * GNU General Public License for more details.
00029  *
00030  * You should have received a copy of the GNU General Public License
00031  * along with this program; if not, write to the Free Software
00032  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00033  *
00034  * */
00035 
00036 #ifdef HDFIO_CACHE
00037 
00038 #include <list>
00039 #include "hdf_filecache.h"
00040 #include <boost/date_time.hpp>
00041 #include <sys/time.h>
00042 #include <sys/resource.h>
00043 
00044 using namespace EMAN;
00045 using std::list;
00046 
00047 FileItem::FileItem() :
00048                 _path(""), _imgio(0), _timestamp(0), _readonly(true)
00049 {
00050 }
00051 
00052 FileItem::FileItem(const string& fpath, ImageIO* const fimageio, const time_t& ftimestamp, bool freadonly) :
00053                 _path(fpath), _imgio(fimageio), _timestamp(ftimestamp), _readonly(freadonly)
00054 {
00055 }
00056 
00057 FileItem::~FileItem()
00058 {
00059         delete _imgio;
00060 }
00061 
00062 int FileItem::set_path(const string& fpath)
00063 {
00064         _path = fpath;
00065         return 0;
00066 }
00067 
00068 string FileItem::get_path() const
00069 {
00070         return _path;
00071 }
00072 
00073 int FileItem::set_imgio(ImageIO* const fimageio)
00074 {
00075         _imgio = fimageio;
00076         return 0;
00077 }
00078 
00079 ImageIO * FileItem::get_imgio() const
00080 {
00081         return _imgio;
00082 }
00083 
00084 int FileItem::set_timestamp(const time_t& ftimestamp)
00085 {
00086         _timestamp = ftimestamp;
00087         return 0;
00088 }
00089 
00090 time_t FileItem::get_timestamp() const
00091 {
00092         return _timestamp;
00093 }
00094 
00095 int FileItem::set_readonly(bool freadonly)
00096 {
00097         _readonly = freadonly;
00098         return 0;
00099 }
00100 
00101 bool FileItem::get_readonly() const
00102 {
00103         return _readonly;
00104 }
00105 
00106 
00107 HDFCache * HDFCache::_instance = 0;
00108 
00109 HDFCache::HDFCache()
00110 {
00111         _thread = boost::thread(&HDFCache::cache_routine, this);
00112 
00113         struct rlimit rl;
00114         getrlimit(RLIMIT_NOFILE, &rl);
00115         CACHESIZE = rl.rlim_cur/2;
00116 //      std::cout << "CACHESIZE = " << CACHESIZE << std::endl;
00117 }
00118 
00119 HDFCache * HDFCache::instance()
00120 {
00121         if(!_instance) {
00122                 _instance = new HDFCache();
00123         }
00124 
00125         return _instance;
00126 }
00127 
00128 void HDFCache::cache_routine()
00129 {
00130         boost::posix_time::seconds intervalTime(CHECK_INTERVAL);
00131 
00132         while(true) {
00133                 try {
00134                         force_clean();
00135                         purge_file();
00136                         boost::this_thread::sleep(intervalTime);
00137                 }
00138                 catch (std::exception& exc) {
00139                         std::cerr << "Very Bad Thing Happen in HDFCache routine: " << exc.what() << std::endl;
00140                 }
00141         }
00142 }
00143 
00144 FileItem * HDFCache::get_file(const string& filename)
00145 {
00146         boost::mutex::scoped_lock l(m_mutex);
00147 
00148         if(file_pool.find(filename) != file_pool.end()) {
00149                 FileItem * hdf_item = file_pool[filename];
00150                 hdf_item->set_timestamp(time(0));
00151                 return hdf_item;
00152         }
00153         else {
00154                 return 0;
00155         }
00156 }
00157 
00158 int HDFCache::add_file(FileItem * newfile)
00159 {
00160         if(file_pool.size() >= CACHESIZE) {
00161                 force_clean();
00162         }
00163 
00164         boost::mutex::scoped_lock l(m_mutex);
00165         file_pool[newfile->get_path()] = newfile;
00166         file_pool2.push_back(newfile);
00167 
00168         return 0;
00169 }
00170 
00173 int HDFCache::close_file(const string& filename)
00174 {
00175         FileItem * hdfitem = file_pool[filename];
00176 
00177         ImageIO * hdfio = hdfitem->get_imgio();
00178         delete hdfio;
00179         file_pool[filename]->set_imgio(0);
00180         file_pool.erase(filename);
00181 
00182         vector<FileItem *>::iterator it = find(file_pool2.begin(), file_pool2.end(), hdfitem);
00183         file_pool2.erase(it);
00184 
00185         return 0;
00186 }
00187 
00188 int HDFCache::purge_file()
00189 {
00190         boost::mutex::scoped_lock l(m_mutex);
00191 
00192         //close those files have access time over the threshold
00193         sort(file_pool2.begin(), file_pool2.end(), least_access());
00194 
00195         vector<FileItem *>::iterator it2 = lower_bound(file_pool2.begin(), file_pool2.end(), ACCESS_TIME_THRESHOLD, access_time_cmp());
00196 
00197         if(it2 != file_pool2.begin()) {
00198                 list<FileItem *> expired_file;
00199                 copy(file_pool2.begin(), it2, back_inserter(expired_file));
00200                 list<FileItem *>::const_iterator lit;
00201                 for(lit = expired_file.begin(); lit!=expired_file.end(); ++lit) {
00202                         string filename = (*lit)->get_path();
00203                         close_file(filename);
00204                 }
00205         }
00206 
00207         return 0;
00208 }
00209 
00210 int HDFCache::force_clean()
00211 {
00212         boost::mutex::scoped_lock l(m_mutex);
00213 
00214         //close 1/10 oldest files when cache size reach limit
00215         if(file_pool2.size() >= CACHESIZE) {
00216                 sort(file_pool2.begin(), file_pool2.end(), least_access());
00217                 for(size_t i=0; i<=CACHESIZE/10; ++i) {
00218                         close_file(file_pool2.front()->get_path());
00219                 }
00220         }
00221 
00222         return 0;
00223 }
00224 
00225 #endif  //HDFIO_CACHE

Generated on Tue Jun 11 12:40:22 2013 for EMAN2 by  doxygen 1.4.7