file_cache_manager.h

00001 /*
00002  *  Copyright (C) 2005 M.J. Zaki <zaki@cs.rpi.edu> Rensselaer Polytechnic Institute
00003  *  Written by salems@cs.rpi.edu
00004  *  Modifications:
00005  *           added file cache deleting, and name passing -- Zaki 7/25/06
00006  *
00007  *  This program is free software; you can redistribute it and/or
00008  *  modify it under the terms of the GNU General Public License
00009  *  as published by the Free Software Foundation; either version 2
00010  *  of the License, or (at your option) any later version.
00011  *
00012  *  This program is distributed in the hope that it will be useful,
00013  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  *  GNU General Public License for more details.
00016  *
00017  *  You should have received a copy of the GNU General Public License along
00018  *  with this program; if not, write to the Free Software Foundation, Inc.,
00019  *  59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
00020  */
00021 #ifndef FILE_CACHE_MANAGER_H
00022 #define FILE_CACHE_MANAGER_H
00023 
00024 #include<cstdio>
00025 #include<map>
00026 using namespace std;
00027 
00034 template <typename Key, typename Data>
00035 class cache_manager {
00036 
00037  public:
00040   typedef Key key_type;
00041 
00044   typedef Data data_type;
00045 
00046   typedef std::map<Key, std::pair<bool,data_type*> > storage_type;
00047 
00050   typedef unsigned long long size_type;
00051 
00054   typedef std::map< key_type, std::pair<unsigned long long,unsigned long long> , std::less< key_type > > FileMap;
00055     
00056   typedef typename FileMap::iterator File_Map_iter;
00062   typedef typename storage_type::iterator storage_iterator;    
00063     
00066   typedef typename storage_type::const_iterator storage_const_iterator;
00067     
00070   typedef typename storage_type::value_type storage_entry_type;
00071 
00072   
00075   storage_iterator begin() { return istorage_.begin(); }
00076 
00079   storage_iterator end() { return istorage_.end(); }
00080 
00083   storage_const_iterator begin() const { return istorage_.begin(); }
00084 
00087   storage_const_iterator end() const { return istorage_.end(); }
00088 
00096   // C can be equal 0.
00097   explicit cache_manager(size_type C = 0,const char* filename)
00098     : size_(0), capacity_(C), istorage_(), offset(0), file_name(filename){
00099     my_file_.open(file_name.c_str(), 
00100                   std::ios::in|std::ios::out|std::ios::binary|ios::trunc);   
00101 
00102   } // explicit cache_manager
00103     
00104     
00105   ~cache_manager() {
00106     my_file_.close();
00107     
00108     if (remove(file_name.c_str()) < 0){
00109       cerr << "Unable to remove backend file " << file_name << endl;
00110     }
00111   }
00112   
00115   void clear() {
00116     
00117     size_ = 0;
00118     istorage_.clear();
00119     file_map_.clear();
00120   } // clear
00121 
00124   size_type size() const { 
00125     size_type S = size_;
00126     return S; 
00127   } // size
00128 
00129     
00132   size_type capacity() const {
00133     size_type S = capacity_;
00134     return S;
00135   } // capacity
00136 
00139   size_type mem_entries() const {
00140     size_type S = istorage_.size();
00141     return S;
00142   } // no_entries
00143 
00146   void print_stats() const {
00147     //cout<<"size:"<<size_<<"offset:"<<offset<<endl;
00148   } 
00151   size_type file_entries() const {
00152     size_type S = file_map_.size();
00153     return S;
00154   } // no_entries
00155 
00156 
00157     
00160   storage_const_iterator find(const key_type& k) const {
00161     storage_const_iterator iter(istorage_.find(k));
00162     return iter;
00163   } // find
00164   
00165   void lock_vat(const key_type& k) {
00166     storage_iterator iter(istorage_.find(k));
00167     if (iter != istorage_.end()) {
00168         iter->second.first=1;
00169     } //if
00170   } //lock_vat
00171 
00172   void unlock_vat(const key_type& k) {
00173     storage_iterator iter(istorage_.find(k));
00174     if (iter != istorage_.end()) {
00175       iter->second.first=0;
00176     } //if
00177   } //unlock_vat
00178 
00182   void  delete_vat(const key_type& k){
00183     storage_iterator iter(istorage_.find(k));
00184     if (iter != istorage_.end()){ //found in the memory_map
00185       size_ -= iter->second.second->byte_size();
00186       data_type* v =iter->second.second;
00187       if(v){
00188         delete v; //reclaim memory for vat
00189       }
00190       else 
00191         std::cout<<"cache_manager.delete_vat: vat is null"<<endl;
00192       
00193       istorage_.erase(iter); 
00194     } // if end
00195     file_map_iter = file_map_.find(k);
00196     if(file_map_iter != file_map_.end()){   //found in the file_map
00197       file_map_.erase(file_map_iter);
00198     }
00199 
00200   }
00201 
00206   bool find_vat ( const key_type& k ){
00207     storage_iterator iter(istorage_.find(k));  // TODO: For compilation sake: Added * before k.
00208     if (iter != istorage_.end()){ //found in the memory_map    
00209       return true;
00210     }
00211     file_map_iter = file_map_.find(k);  // TODO: For compilation sake: Added * before k.
00212     if(file_map_iter != file_map_.end()){   //found in the file_map        
00213       return true;
00214     }
00215     return false; 
00216   } 
00217   
00221   data_type * get_vat_point(const key_type& k) {
00222     storage_iterator iter(istorage_.find(k));
00223     if (iter != istorage_.end()) {
00224       return iter->second.second;
00225     } //if found
00226     else { 
00227       file_map_iter = file_map_.find(k);
00228       if(file_map_iter != file_map_.end()){
00229         my_file_.seekg(file_map_iter->second.second);
00230         data_type* temp_object=new data_type();
00231         temp_object->read_file(my_file_,file_map_iter->second.first); 
00232         insert(k,temp_object);
00233         //delete temp_object;
00234         return get_vat_point(k);          
00235       } //if in file
00236       else{
00237         cout <<"Inside file_cache_manager::get_vat_point. Vat is neither in mem nor in file!!"<<endl;
00238       }//else not even in file
00239     } //else
00240 
00241     return 0;
00242   }
00243 
00251   bool insert(const key_type& k, data_type* e) {
00252     if (capacity_ < size_ + e->byte_size()) {
00253       if (update(e->byte_size(),0) == false) {
00254         cout<<"insert: update problem\n" << ".bytesize: " << e->byte_size()<<endl;
00255         return false;
00256       }
00257     }
00258     istorage_.insert(entry_type(k,std::pair<bool,data_type*>(0,e)));
00259     size_ += e->byte_size();
00260     return true;
00261   } // insert
00262 
00263   /* update the the memory by the requested size.. 
00264    * evict some entries untill the memory has free memory >= rq_size
00265    */
00266   bool update(size_type req_size = 0,int levelone=1) {
00267     if (istorage_.empty()) {    
00268       cout<<"Nothing in the memory..Update Failed"<<endl;
00269       return false;
00270     }
00271 
00272     long int S = 0;
00273     if (req_size > 0) S = capacity_ - size_ - req_size;
00274 
00275     storage_iterator iter;
00276     do {
00277     iter = istorage_.begin();    
00278     //find an entry which we can evict..
00279     while (iter->second.first ==1 && iter != istorage_.end())  {
00280       iter++;
00281     }
00282 
00283     if (iter == istorage_.end()){
00284       cout <<"Nothing can be evicted from memory"<<endl;
00285       return false;
00286     }
00287     
00288     S += iter->second.second->byte_size();
00289     size_ =  size_ - iter->second.second->byte_size();
00290     //check if it is already in the file, if not write it to the file
00291     
00292     file_map_iter = file_map_.find( iter->first); 
00293     //not in the file .. or it is level one vat .
00294     if( file_map_iter == file_map_.end() || levelone ){
00295       my_file_.seekp(offset);
00296       std::pair<size_type, size_type> file_offset_info(iter->second.second->byte_size(),offset);
00297       file_map_[iter->first]=file_offset_info; 
00298       offset += iter->second.second->byte_size();
00299       iter->second.second->write_file(my_file_);
00300     }
00301      
00302     if(iter->second.second)
00303        delete iter->second.second; //reclaim memory for vat
00304      else 
00305        std::cout<<"cache_manager.update: vat is null"<<endl;
00306       
00307     istorage_.erase(iter);
00308     // keep key list as a heap      
00309     if ((istorage_.empty()) && (S < 0)) {
00310       cout<<"Nothing in the memory..Update Failed"<<endl;
00311       return false;
00312     }
00313   }
00314   while (S <= 0);
00315   return true;
00316     
00317 } // update
00318 
00319 private:
00320 
00321 // not defined (cache_manager is not assignable)
00322 cache_manager(const cache_manager&);
00323 cache_manager& operator=(const cache_manager&);
00324 typedef std::pair<storage_iterator, bool> result_type;
00325 typedef std::pair<size_type, size_type> pair_type;           
00326 typedef std::pair<key_type, std::pair<bool,data_type*> > entry_type;
00327 
00328 File_Map_iter file_map_iter;  
00329 
00330 size_type size_; // cache size
00331 size_type capacity_; // cache capacity
00332 storage_type istorage_; // internal storage   
00333 FileMap  file_map_; //file map to store where each record is stored in the file if it is in the file.
00334 size_type offset;  //offset in the file    
00335 std::fstream my_file_; //file to be used for writing back..
00336  string file_name; //name of the cache file
00337 
00338 }; // class cache_manager
00339 
00340 #endif // FILE_CACHE_MANAGER_H

Generated on Wed Jul 26 14:01:08 2006 for DMTL by  doxygen 1.4.7