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 2628 2006-11-24 12:46:34Z sachiboo $
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__) || defined(_MSC_VER)
00151 #include <vector>
00152 #else
00153 #include <vector.h>
00154 #endif  /* compiler dependent part */
00155 
00156 
00157 #if defined(__BORLANDC__) || defined(_MSC_VER)
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__) || defined(_MSC_VER)
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 #ifndef _MSC_VER
00395           red_bytes = write( _fdw, _cacheWV, sizeof(T) * VVECTOR_WRITE_CACHE_SIZE );
00396 #else
00397           red_bytes = _write( _fdw, _cacheWV, sizeof(T) * VVECTOR_WRITE_CACHE_SIZE );
00398 #endif
00399         #ifdef OPEN_WHEN_ACCESS
00400           my_close_write();
00401     #endif /*OPEN_WHEN_ACCESS*/
00402 
00403           write_successful = ( red_bytes == sizeof(T) * VVECTOR_WRITE_CACHE_SIZE );
00404           if ( (!write_successful )  || ( _size == max_size ) )
00405             {
00406               if (end_policy == 0)
00407                 {
00408                   if (_size>0)
00409                     {
00410                       throw vvector_full();
00411                     }
00412                   else{
00413                     throw vvector_write_error();
00414                   }
00415                 }
00416               else 
00417                 {
00418                   size_fixed=true;
00419                   if ( !write_successful )
00420                     {
00421                       _size-=VVECTOR_WRITE_CACHE_SIZE;
00422                     }
00423                     
00424                 }
00425             }// if of write statment
00426         } //if of append condition
00427         
00428       if (size_fixed){
00429         //try to seek start offset
00430     #ifdef OPEN_WHEN_ACCESS
00431           my_open_to_append();
00432     #endif /*OPEN_WHEN_ACCESS*/
00433 
00434 #ifndef _MSC_VER
00435         if (lseek(_fdw, static_cast<off_t>((start_offset) * sizeof(T)), SEEK_SET) == static_cast<off_t>(-1)) 
00436 #else
00437         if (_lseeki64(_fdw, static_cast<off_t>((start_offset) * sizeof(T)), SEEK_SET) == static_cast<off_t>(-1))
00438 #endif
00439     {
00440           my_close_write();
00441             throw vvector_write_error();
00442           }
00443 
00444 #ifndef _MSC_VER
00445     red_bytes = write(_fdw, _cacheWV, sizeof(T) * VVECTOR_WRITE_CACHE_SIZE);
00446 #else
00447     red_bytes = _write(_fdw, _cacheWV, sizeof(T) * VVECTOR_WRITE_CACHE_SIZE);
00448 #endif
00449         #ifdef OPEN_WHEN_ACCESS
00450           my_close_write();
00451     #endif /*OPEN_WHEN_ACCESS*/
00452 
00453         if ( red_bytes != sizeof(T) * VVECTOR_WRITE_CACHE_SIZE) 
00454           {
00455             throw vvector_write_error();
00456           }
00457         start_offset += VVECTOR_WRITE_CACHE_SIZE;
00458         if (start_offset >= _size)
00459           { 
00460             start_offset -= _size;
00461           }
00462           
00463           
00464       }
00465       _cacheWNum = 0;
00466         
00467     }
00468 }
00469 
00470 
00471 template<class T>  T const & vvector<T>::operator [] (size_type i)
00472 {
00473   return at(i);
00474 }
00475 
00476 
00477 template<class T>  T const & vvector<T>::at(size_type i)
00478 {
00479 
00480   assert(i < _size);
00481   // read cache only makes sense when not fixed size
00482   if (!size_fixed){
00483     if (( i >= _cacheRI[0])&&(_cacheRI[1]>=i)){
00484       //calculate i's position
00485       return _cacheRV[i-_cacheRI[0]];
00486     }
00487   }
00488 
00489   if ((i>=_cacheWI[0])&&(_cacheWI[1]>=i)){
00490     //calculate i's position
00491 
00492     return _cacheWV[i-_cacheWI[0]];
00493   }
00494   size_type i2=i; //forward sequential read assumed
00495   size_type log_read_start, phys_read_start;
00496   size_t half_size,read_interval;
00497   read_interval=VVECTOR_READ_CACHE_SIZE;
00498   
00499   // detect sequential read ( only in case of not fixed read )
00500   if (!size_fixed){
00501     if ((i+1)==_cacheRI[0])
00502       {
00503         if (_cacheRI[0]>=read_interval)
00504           {
00505             i2=_cacheRI[0]-read_interval;
00506           }
00507         else 
00508           {
00509             i2=0; 
00510           }
00511       }
00512     else if((_cacheRI[1]+1)!=i){ //not forward sequential, therefore random access
00513       half_size=read_interval/2;
00514       if (i>half_size){i2=(i-half_size);} else {i2=0;}
00515     }
00516   }
00517   ssize_t num_red;
00518   size_type num_to_read = _size - i2 ;
00519   if (VVECTOR_READ_CACHE_SIZE < num_to_read) {
00520     num_to_read = VVECTOR_READ_CACHE_SIZE;
00521   }
00522   log_read_start=i2;
00523   if (size_fixed){
00524     phys_read_start=(i2+start_offset+_cacheWNum);
00525     if (phys_read_start>=_size){ phys_read_start-=_size;}
00526   }
00527   else{
00528     phys_read_start=i2;
00529   }
00530    #ifdef OPEN_WHEN_ACCESS
00531      my_open_to_read( off_t( phys_read_start * sizeof(T) ));
00532     #endif /*OPEN_WHEN_ACCESS*/
00533 #ifndef _MSC_VER
00534   num_red = read(_fdr, _cacheRV, num_to_read * sizeof(T));
00535 #else
00536   num_red = _read(_fdr, _cacheRV, static_cast<unsigned int>(num_to_read * sizeof(T)));
00537 #endif
00538    #ifdef OPEN_WHEN_ACCESS
00539   my_close_read();
00540     #endif /*OPEN_WHEN_ACCESS*/
00541   if (num_red < 0) {
00542     throw vvector_read_error();
00543 
00544   }
00545   num_red /= sizeof(T);
00546   _cacheRI[0]=log_read_start;
00547   _cacheRI[1]=log_read_start+num_red-1;
00548 
00549   _buf = _cacheRV[i-log_read_start];
00550   return _buf;
00551 }
00552 
00553 
00554 template<class T> void vvector<T>::clear()
00555 {
00556   unlinkfile();
00557 }
00558 
00559 
00560 #endif  /* __VVECOTOR_H__ */

Generated on Mon Dec 18 07:24:08 2006 for E-CELL C++ libraries (libecs and libemc) 3.1.105 by  doxygen 1.5.1