00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
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
00155
00156
00157 #if defined(__BORLANDC__)
00158 typedef int ssize_t;
00159 #endif
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
00224 public:
00225 typedef void (*cbfp_t)();
00226
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
00242 protected:
00243 int _myNumber;
00244 char *_file_name;
00245 int _fdr,_fdw;
00246 void unlinkfile();
00247
00248
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
00256 public:
00257 vvectorbase();
00258 ~vvectorbase();
00259
00260
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; };
00266 };
00267
00268
00269 template<class T> class vvector : public vvectorbase {
00270
00271 public:
00272 typedef T value_type;
00273 typedef size_t size_type;
00274
00275
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
00293 public:
00294 vvector();
00295 ~vvector();
00296
00297
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
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
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
00389 if (!size_fixed)
00390 {
00391 #ifdef OPEN_WHEN_ACCESS
00392 my_open_to_append();
00393 #endif
00394 red_bytes = write( _fdw, _cacheWV, sizeof(T) * VVECTOR_WRITE_CACHE_SIZE );
00395 #ifdef OPEN_WHEN_ACCESS
00396 my_close_write();
00397 #endif
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 }
00422 }
00423
00424 if (size_fixed){
00425
00426 #ifdef OPEN_WHEN_ACCESS
00427 my_open_to_append();
00428 #endif
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
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
00470 if (!size_fixed){
00471 if (( i >= _cacheRI[0])&&(_cacheRI[1]>=i)){
00472
00473 return _cacheRV[i-_cacheRI[0]];
00474 }
00475 }
00476
00477 if ((i>=_cacheWI[0])&&(_cacheWI[1]>=i)){
00478
00479
00480 return _cacheWV[i-_cacheWI[0]];
00481 }
00482 size_type i2=i;
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
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){
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
00521 num_red = read(_fdr, _cacheRV, num_to_read * sizeof(T));
00522 #ifdef OPEN_WHEN_ACCESS
00523 my_close_read();
00524 #endif
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