VVector.h

00001 /*
00002 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
00003 //
00004 //        This file is a part of E-CELL Simulation Environment package
00005 //
00006 //                Copyright (C) 1996-2001 Keio university
00007 //   Copyright (C) 1998-2001 Japan Science and Technology Corporation (JST)
00008 //
00009 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
00010 //
00011 //
00012 // E-CELL is free software; you can redistribute it and/or
00013 // modify it under the terms of the GNU General Public
00014 // License as published by the Free Software Foundation; either
00015 // version 2 of the License, or (at your option) any later version.
00016 // 
00017 // E-CELL is distributed in the hope that it will be useful,
00018 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00020 // See the GNU General Public License for more details.
00021 // 
00022 // You should have received a copy of the GNU General Public
00023 // License along with E-CELL -- see the file COPYING.
00024 // If not, write to the Free Software Foundation, Inc.,
00025 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00026 // 
00027 //END_HEADER
00028 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
00029 //      This file is a part of E-CELL2.
00030 //      Original codes of E-CELL1 core were written by Koichi TAKAHASHI
00031 //      <shafi@e-cell.org>.
00032 //      Some codes of E-CELL2 core are minor changed from E-CELL1
00033 //      by Naota ISHIKAWA <naota@mag.keio.ac.jp>.
00034 //      Other codes of E-CELL2 core and all of E-CELL2 UIMAN are newly
00035 //      written by Naota ISHIKAWA.
00036 //      All codes of E-CELL2 GUI are written by
00037 //      Mitsui Knowledge Industry Co., Ltd. <http://bio.mki.co.jp/>
00038 //
00039 //      Latest version is availabe on <http://bioinformatics.org/>
00040 //      and/or <http://www.e-cell.org/>.
00041 //END_V2_HEADER
00042 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
00043 */
00044 /*
00045  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
00046  *      $Id: VVector.h 2528 2005-11-19 09:23:59Z shafi $
00047  :      $Log$
00048  :      Revision 1.21  2005/11/19 09:23:59  shafi
00049  :      Kouichi -> Koichi
00050  :
00051  :      Revision 1.20  2005/04/29 01:38:50  shafi
00052  :      for gcc4.  more necessary.
00053  :      
00054  :      Revision 1.19  2004/07/29 03:52:02  bgabor
00055  :      Fixing bug [ 994313 ] vvector should close files after read and write.
00056  :      
00057  :      Revision 1.18  2004/07/13 18:29:34  shafi
00058  :      extensive logger code cleanup. remaining things are: replace DataPointVector with boost::multi_array, and understand, reconsider and rename getData( s,e,i )
00059  :      
00060  :      Revision 1.17  2004/07/04 10:36:15  bgabor
00061  :      Code cleanup.
00062  :      
00063  :      Revision 1.16  2004/06/14 17:53:15  bgabor
00064  :      Bugfixing in LogginPolicy
00065  :      
00066  :      Revision 1.15  2004/06/10 14:29:11  bgabor
00067  :      New logger policy API introduced.
00068  :      Logger policy is now four element long.
00069  :      First: minimum step between logs (0-no lag )
00070  :      Second: mimimum interval between logs ( 0-no logs )
00071  :      Third: policy at end of disk space or available space ( 0- throw ex, 1 overwrite old data )
00072  :      Fourth: available space for the logger in kbytes ( 0- no limit )
00073  :      
00074  :      Revision 1.14  2004/05/29 11:54:51  bgabor
00075  :      Introducing logger policy .
00076  :      User cen set and get the policy for a certain logger either when the logger is creater or anytime later.
00077  :      logger policy is a 3 element list of numbers.
00078  :      first element:  0-log all
00079  :                      1-log every xth step
00080  :                      2-log at the passing of x secs
00081  :      second element: policy at the end
00082  :                      0-throw exception when disk space is used up
00083  :                      1-start overwriting earliest data
00084  :      third element:  x parameter for minimum step or time interval for first element
00085  :      
00086  :      Revision 1.13  2004/03/14 19:19:54  satyanandavel
00087  :      minor fix
00088  :      
00089  :      Revision 1.12  2004/03/14 19:11:57  satyanandavel
00090  :      sys/io.h is not available in IBM p650
00091  :      
00092  :      Revision 1.11  2003/09/28 06:17:23  satyanandavel
00093  :      MinGW version 3 already defines ssize_t
00094  :      
00095  :      Revision 1.10  2003/09/27 13:00:58  bgabor
00096  :      Windows compatibility fix.
00097  :      
00098  :      Revision 1.9  2003/09/27 12:39:15  satyanandavel
00099  :      more compatibility issues in Windows
00100  :      
00101  :      Revision 1.8  2003/09/22 04:28:44  bgabor
00102  :      Fixed a serious undefined reference to my_open_to_read bug in VVector.
00103  :      
00104  :      Revision 1.7  2003/08/08 13:13:09  satyanandavel
00105  :      Added support for MinGW to define type of ssize_t
00106  :      
00107  :      Revision 1.6  2003/07/20 06:06:06  bgabor
00108  :      
00109  :      Added support for large files.
00110  :      
00111  :      Revision 1.5  2003/04/02 11:42:18  shafi
00112  :      my_open_to_read( off_t )
00113  :      
00114  :      Revision 1.4  2003/03/18 09:06:36  shafi
00115  :      logger performance improvement by gabor
00116  :      
00117  :      Revision 1.2  2003/02/03 15:31:56  shafi
00118  :      changed vvector cache sizes to 1024
00119  :      
00120  :      Revision 1.1  2002/04/30 11:21:53  shafi
00121  :      gabor's vvector logger patch + modifications by shafi
00122  :      
00123  :      Revision 1.6  2001/10/15 17:18:26  ishikawa
00124  :      improved program interface
00125  :      
00126  :      Revision 1.5  2001/08/10 19:10:34  naota
00127  :      can be compiled using g++ on Linux and Solaris
00128  :      
00129  :      Revision 1.4  2001/03/23 18:51:17  naota
00130  :      comment for credit
00131  :
00132  :      Revision 1.3  2001/01/19 21:18:42  naota
00133  :      Can be comiled g++ on Linux.
00134  :
00135  :      Revision 1.2  2001/01/10 11:44:46  naota
00136  :      batch mode running.
00137  :
00138  :      Revision 1.1  2000/12/30 15:09:46  naota
00139  :      Initial revision
00140  :
00141  //END_RCS_HEADER
00142  *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
00143  */
00144 
00145 
00146 #ifndef __VVECOTOR_H__
00147 #define __VVECOTOR_H__
00148 #include "ecell/config.h"
00149 #include <sys/types.h>
00150 #if     defined(__GNUC__)
00151 #include <vector>
00152 #else
00153 #include <vector.h>
00154 #endif  /* compiler dependent part */
00155 
00156 
00157 #if defined(__BORLANDC__)
00158 typedef int ssize_t;
00159 #endif /* __BORLANDC__ */
00160 
00161 
00162 #include <string.h>
00163 #include <memory.h>
00164 #include <stdio.h>
00165 #include <assert.h>
00166 #include <errno.h>
00167 #if     defined(__BORLANDC__)
00168 #include <io.h>
00169 #elif   defined(__linux__) && !defined(__powerpc__)
00170 #include <unistd.h>
00171 #include <sys/io.h>
00172 #else
00173 #include <unistd.h>
00174 #endif 
00175 
00176 #include "Exceptions.hpp"
00177 
00178 #define OPEN_WHEN_ACCESS
00179 
00180 const unsigned int VVECTOR_READ_CACHE_SIZE = 2048;
00181 const unsigned int VVECTOR_WRITE_CACHE_SIZE = 2048;
00182 const unsigned int VVECTOR_READ_CACHE_INDEX_SIZE = 2;
00183 const unsigned int VVECTOR_WRITE_CACHE_INDEX_SIZE = 2;
00184 
00185 class vvector_full : public std::exception { 
00186   public:
00187 
00188    virtual char const* what() throw()
00189         {
00190             return "Total disk space or allocated space is full.\n";
00191         } 
00192     };
00193 
00194 class vvector_write_error : public std::exception { 
00195   public:
00196 
00197    virtual char const* what() throw()
00198         {
00199             return "I/O error while attempting to write on disk.\n";
00200         } 
00201     };
00202 
00203 class vvector_read_error : public std::exception { 
00204   public:
00205 
00206    virtual char const* what() throw()
00207         {
00208             return "I/O error while attempting to read from disk.\n";
00209         } 
00210     };
00211 
00212 
00213 class vvector_init_error : public std::exception { 
00214   public:
00215 
00216    virtual char const* what() throw()
00217         {
00218             return "VVector initialization error.\n";
00219         } 
00220     };
00221 
00222 class vvectorbase {
00223   // types
00224  public:
00225   typedef void (*cbfp_t)(); // pointer to call back function
00226   // private valiables
00227  private:
00228   static int _serialNumber;
00229   static char const *_defaultDirectory;
00230   static int _directoryPriority;
00231 
00232   static std::vector<char const *> _tmp_name;
00233   static std::vector<int> _file_desc_read;
00234   static std::vector<int> _file_desc_write;
00235 
00236   static bool _atexitSet;
00237   static cbfp_t _cb_full;
00238   static cbfp_t _cb_error;
00239   static long _margin;
00240 
00241   // protected variables
00242  protected:
00243   int _myNumber;
00244   char *_file_name;
00245   int _fdr,_fdw;
00246   void unlinkfile();
00247 
00248   // protected methods
00249   void initBase(char const * const dirname);
00250   void my_open_to_append();
00251   void my_open_to_read(off_t offset);
00252   void my_close_read();
00253   void my_close_write();
00254 
00255   // constructor, destructor
00256  public:
00257   vvectorbase();
00258   ~vvectorbase();
00259 
00260   // other public method
00261   static void setTmpDir(char const * const dirname, int);
00262   static void removeTmpFile();
00263   static void setCBFull(cbfp_t __c) { _cb_full = __c; };
00264   static void cbFull();
00265   static void margin(long __m) { _margin = __m; }; // by K bytes
00266 };
00267 
00268 
00269 template<class T> class vvector : public vvectorbase {
00270   // types
00271  public:
00272   typedef T value_type;
00273   typedef size_t size_type;
00274 
00275   // private valiables
00276  private:
00277   size_type _size;
00278   value_type _buf;
00279   value_type _cacheRV[VVECTOR_READ_CACHE_SIZE];
00280   size_type _cacheRI[VVECTOR_READ_CACHE_INDEX_SIZE];
00281   value_type _cacheWV[VVECTOR_WRITE_CACHE_SIZE];
00282   size_type _cacheWI[VVECTOR_WRITE_CACHE_INDEX_SIZE];
00283   size_type _cacheWNum;
00284   bool size_fixed;
00285   int end_policy;
00286   size_type max_size;
00287   size_type start_offset;
00288 
00289 
00290   libecs::Real LastTime, diff, lastRead;
00291 
00292   // constructor, destructor
00293  public:
00294   vvector();
00295   ~vvector();
00296 
00297   // other public methods
00298  public:
00299   void push_back(const value_type & x);
00300   value_type const & operator [] (size_type i);
00301   value_type const & at(size_type i);
00302   size_type size() const { return _size; };
00303   void clear();
00304   static void setDiskFullCB(void(*)());
00305   void setEndPolicy( int );
00306   int  getEndPolicy();
00307   void setMaxSize( int aMaxSize );
00308 };
00309 
00310 
00311 //////////////////////////////////////////////////////////////////////
00312 //      implemetation
00313 //////////////////////////////////////////////////////////////////////
00314 
00315 
00316 template<class T> vvector<T>::vvector()
00317 {
00318   size_fixed = false;
00319   end_policy = 0;
00320   max_size = 0;
00321   start_offset = 0;
00322   initBase(NULL);
00323   int counter = VVECTOR_READ_CACHE_INDEX_SIZE;
00324   do {
00325     _cacheRI[counter] = -1;
00326   } while (0 <= --counter);
00327   counter = VVECTOR_WRITE_CACHE_INDEX_SIZE;
00328   do {
00329     _cacheWI[counter] = -1;
00330   } while (0 <= --counter);
00331   _cacheWNum = 0;
00332   _size = 0;
00333 }
00334 
00335 
00336 template<class T> vvector<T>::~vvector()
00337 {
00338   // do nothing
00339 }
00340 
00341 template<class T> void vvector<T>::setEndPolicy( int anEndPolicy)
00342 {
00343   end_policy=anEndPolicy;
00344 }
00345 
00346 template<class T> int vvector<T>::getEndPolicy()
00347 {
00348   return end_policy;
00349 }
00350 
00351 template<class T> void vvector<T>::setMaxSize( int aMaxSize )
00352 {
00353   if (aMaxSize == 0) {
00354     max_size = 0;
00355   }
00356   else{
00357     max_size = ((aMaxSize/VVECTOR_WRITE_CACHE_SIZE)+1)*VVECTOR_WRITE_CACHE_SIZE;
00358   }
00359 }
00360 
00361 template<class T> void vvector<T>::push_back(const T & x)
00362 {
00363   ssize_t red_bytes; 
00364   bool write_successful;
00365   if(VVECTOR_WRITE_CACHE_SIZE <= _cacheWNum)
00366     { 
00367       throw vvector_write_error();
00368     }
00369     
00370   _cacheWV[_cacheWNum] = x;
00371   if (_cacheWNum==0)
00372     {
00373       _cacheWI[0]=_size;
00374     }
00375   _cacheWI[1] = _size;
00376   if (size_fixed)
00377     {
00378       _cacheWI[0]--;
00379     }
00380   else
00381     {
00382       _size++;
00383     }
00384   _cacheWNum++;
00385 
00386   if ( VVECTOR_WRITE_CACHE_SIZE <= _cacheWNum )  
00387     {
00388       // first try to append
00389       if (!size_fixed)
00390         {
00391         #ifdef OPEN_WHEN_ACCESS
00392            my_open_to_append();
00393         #endif /*OPEN_WHEN_ACCESS*/
00394           red_bytes = write( _fdw, _cacheWV, sizeof(T) * VVECTOR_WRITE_CACHE_SIZE );
00395         #ifdef OPEN_WHEN_ACCESS
00396           my_close_write();
00397     #endif /*OPEN_WHEN_ACCESS*/
00398 
00399           write_successful = ( red_bytes == sizeof(T) * VVECTOR_WRITE_CACHE_SIZE );
00400           if ( (!write_successful )  || ( _size == max_size ) )
00401             {
00402               if (end_policy == 0)
00403                 {
00404                   if (_size>0)
00405                     {
00406                       throw vvector_full();
00407                     }
00408                   else{
00409                     throw vvector_write_error();
00410                   }
00411                 }
00412               else 
00413                 {
00414                   size_fixed=true;
00415                   if ( !write_successful )
00416                     {
00417                       _size-=VVECTOR_WRITE_CACHE_SIZE;
00418                     }
00419                     
00420                 }
00421             }// if of write statment
00422         } //if of append condition
00423         
00424       if (size_fixed){
00425         //try to seek start offset
00426     #ifdef OPEN_WHEN_ACCESS
00427           my_open_to_append();
00428     #endif /*OPEN_WHEN_ACCESS*/
00429 
00430         if (lseek(_fdw, static_cast<off_t>((start_offset) * sizeof(T)), SEEK_SET) == static_cast<off_t>(-1)) 
00431           {
00432           my_close_write();
00433             throw vvector_write_error();
00434           }
00435 
00436     red_bytes = write(_fdw, _cacheWV, sizeof(T) * VVECTOR_WRITE_CACHE_SIZE);
00437         #ifdef OPEN_WHEN_ACCESS
00438           my_close_write();
00439     #endif /*OPEN_WHEN_ACCESS*/
00440 
00441         if ( red_bytes != sizeof(T) * VVECTOR_WRITE_CACHE_SIZE) 
00442           {
00443             throw vvector_write_error();
00444           }
00445         start_offset += VVECTOR_WRITE_CACHE_SIZE;
00446         if (start_offset >= _size)
00447           { 
00448             start_offset -= _size;
00449           }
00450           
00451           
00452       }
00453       _cacheWNum = 0;
00454         
00455     }
00456 }
00457 
00458 
00459 template<class T>  T const & vvector<T>::operator [] (size_type i)
00460 {
00461   return at(i);
00462 }
00463 
00464 
00465 template<class T>  T const & vvector<T>::at(size_type i)
00466 {
00467 
00468   assert(i < _size);
00469   // read cache only makes sense when not fixed size
00470   if (!size_fixed){
00471     if (( i >= _cacheRI[0])&&(_cacheRI[1]>=i)){
00472       //calculate i's position
00473       return _cacheRV[i-_cacheRI[0]];
00474     }
00475   }
00476 
00477   if ((i>=_cacheWI[0])&&(_cacheWI[1]>=i)){
00478     //calculate i's position
00479 
00480     return _cacheWV[i-_cacheWI[0]];
00481   }
00482   size_type i2=i; //forward sequential read assumed
00483   size_type log_read_start, phys_read_start;
00484   size_t half_size,read_interval;
00485   read_interval=VVECTOR_READ_CACHE_SIZE;
00486   
00487   // detect sequential read ( only in case of not fixed read )
00488   if (!size_fixed){
00489     if ((i+1)==_cacheRI[0])
00490       {
00491         if (_cacheRI[0]>=read_interval)
00492           {
00493             i2=_cacheRI[0]-read_interval;
00494           }
00495         else 
00496           {
00497             i2=0; 
00498           }
00499       }
00500     else if((_cacheRI[1]+1)!=i){ //not forward sequential, therefore random access
00501       half_size=read_interval/2;
00502       if (i>half_size){i2=(i-half_size);} else {i2=0;}
00503     }
00504   }
00505   ssize_t num_red;
00506   size_type num_to_read = _size - i2 ;
00507   if (VVECTOR_READ_CACHE_SIZE < num_to_read) {
00508     num_to_read = VVECTOR_READ_CACHE_SIZE;
00509   }
00510   log_read_start=i2;
00511   if (size_fixed){
00512     phys_read_start=(i2+start_offset+_cacheWNum);
00513     if (phys_read_start>=_size){ phys_read_start-=_size;}
00514   }
00515   else{
00516     phys_read_start=i2;
00517   }
00518    #ifdef OPEN_WHEN_ACCESS
00519      my_open_to_read( off_t( phys_read_start * sizeof(T) ));
00520     #endif /*OPEN_WHEN_ACCESS*/
00521   num_red = read(_fdr, _cacheRV, num_to_read * sizeof(T));
00522    #ifdef OPEN_WHEN_ACCESS
00523   my_close_read();
00524     #endif /*OPEN_WHEN_ACCESS*/
00525   if (num_red < 0) {
00526     throw vvector_read_error();
00527 
00528   }
00529   num_red /= sizeof(T);
00530   _cacheRI[0]=log_read_start;
00531   _cacheRI[1]=log_read_start+num_red-1;
00532 
00533   _buf = _cacheRV[i-log_read_start];
00534   return _buf;
00535 }
00536 
00537 
00538 template<class T> void vvector<T>::clear()
00539 {
00540   unlinkfile();
00541 }
00542 
00543 
00544 #endif  /* __VVECOTOR_H__ */

Generated on Fri Apr 28 10:38:30 2006 for E-CELL C++ libraries (libecs and libemc) 3.1.105 by  doxygen 1.4.6