ADMB Documentation  11.1.1016
 All Classes Files Functions Variables Typedefs Friends Defines
smartbuf.cpp
Go to the documentation of this file.
00001 /*
00002  * $Id: smartbuf.cpp 542 2012-07-10 21:04:06Z johnoel $
00003  *
00004  * Author: David Fournier
00005  * Copyright (c) 2008-2012 Regents of the University of California 
00006  */
00011 #define HOME_VERSION
00012 #include "fvar.hpp"
00013 #include "smartbuf.h"
00014 #ifdef __MSVC32__
00015   #define lseek _lseek
00016   #define  read _read
00017   #define write _write 
00018   #include <sys\stat.h>
00019 #endif
00020 
00021 #if defined (__WAT32__)
00022   #include <fcntl.h>
00023 #endif
00024 
00025 #if  defined(__GNU__) || defined(__linux__)
00026 #include <memory.h>
00027   #if (__GNUC__ >3)
00028      #include <iostream>
00029      using namespace std;
00030   #else   
00031     #include <iostream.h>
00032   #endif
00033 #include <fcntl.h>
00034 #include <sys/stat.h>
00035 #include <sys/types.h>
00036 #include <unistd.h>
00037 #endif
00038 
00039 #if defined(__TURBOC__) && !defined(__linux__)
00040   #pragma hdrstop
00041   #include <iostream.h>
00042   #include <sys\stat.h>
00043   #include <fcntl.h>
00044 #endif
00045 
00046 #ifdef __ZTC__
00047   #include <iostream.hpp>
00048   #define S_IREAD 0000400
00049   #define S_IWRITE 0000200
00050   #include <fcntl.h>
00051 #endif
00052 
00053 #ifdef __NDPX__
00054   #define O_RDONLY 0
00055   #define O_WRONLY 1
00056   #define O_RDWR 2
00057   extern "C"
00058   {
00059     int lseek(int, int, int);
00060     int open(const char*, int);
00061     int creat(const char*, int);
00062     int close(int);
00063     int write(int, char*, int);
00064     int read(int, char*, int);
00065   };
00066 #endif
00067 
00068 #ifdef __GNU__
00069 #include <memory.h>
00070   #if (__GNUC__ >3)
00071      #include <iostream>
00072      using namespace std;
00073   #else   
00074     #include <iostream.h>
00075   #endif
00076 #include <fcntl.h>
00077 #include <sys/stat.h>
00078 #include <sys/types.h>
00079 #include <unistd.h>
00080 #endif
00081 
00082 #ifdef __SUN__
00083 #include <memory.h>
00084 #include <iostream.h>
00085 #include <fcntl.h>
00086 #include <sys/stat.h>
00087 #include <sys/types.h>
00088 #ifndef __MSVC32__
00089 #include <unistd.h>
00090 #endif
00091 #endif
00092 
00093 #include <limits.h>
00094 #include <stdlib.h>
00095 #include <stdio.h>
00096 #include <string.h>
00097   char lastchar(char *);
00098 
00099   void byte_copy(void * dest,void * source, unsigned num_bytes);
00100   extern char ad_random_part[6];
00101 
00106   ad_sbuffer::ad_sbuffer(unsigned long int sz,const char * froot)
00107   {
00108     // need some code here to decide where to put the file
00109     file_name=froot;
00110 
00111     const int us=sizeof(unsigned int);
00112     if (sz > UINT_MAX)
00113     {
00114       cout << "Error -- largest size for CMPDIF_BUFFER_SIZE is "
00115         << INT_MAX<<endl;
00116     }
00117     if ( (buff=new char[sz])==NULL)
00118     {
00119       cerr << "Error trying to allocate memory for ad_sbuffer buffer"<<endl;
00120       ad_exit(1);
00121     }
00122     buff_size=sz;
00123     buff_end=sz-us-2;
00124     offset=0;
00125     toffset=0;
00126 
00127 
00128 #if defined(USE_ADPVM)
00129     char * path = getenv("ADTMP1"); // NULL if not defined
00130     adstring string_path;
00131     if (path) string_path=path;
00132     int on=0;
00133     int nopt=0;
00134     adstring currdir;
00135     ad_getcd(currdir);
00136     if (ad_comm::pvm_manager)
00137     {
00138       if ( (on=option_match(ad_comm::argc,ad_comm::argv,"-slave",nopt))>-1)
00139       {
00140         if (nopt ==1)     
00141         {       
00142           {
00143             int ierr=make_sub_directory(ad_comm::argv[on+1]);
00144             ad_comm::subdir=ad_comm::argv[on+1];
00145             string_path+=ad_comm::subdir;
00146             path=(char*) string_path;
00147           }
00148         }
00149         else
00150         {
00151           cerr << "Wrong number of options to -slave -- must be 1"
00152             " you have " << nopt << endl;   
00153           ad_exit(1);
00154         } 
00155       }   
00156     }
00157 #endif
00158 
00159   #ifdef __GNU__
00160     file_ptr=open(file_name, O_RDWR | O_CREAT | O_TRUNC, 0777 );
00161   #else
00162     file_ptr=open(file_name, O_RDWR | O_CREAT | O_TRUNC );
00163   #endif
00164 
00165     if (file_ptr == -1)
00166     {
00167       if (ad_printf) (*ad_printf)("Error opening temporary gradient"
00168         " file %s\n", (char*)file_name );
00169       ad_exit(1);
00170     }
00171   }
00172 
00173 
00174 
00175   ad_sbuffer::~ad_sbuffer()
00176   {
00177     delete buff;
00178     buff=0;
00179     buff_end=0;
00180 
00181     if (close(file_ptr))
00182     {
00183       cerr << "Error closing file " << cmpdif_file_name << "\n";
00184     }
00185 #   if defined ( __SUN__) ||  defined ( __GNU__)
00186       unlink(cmpdif_file_name);
00187 #else
00188       adstring currentdir;
00189       ad_getcd(currentdir);
00190       int xxx=remove(cmpdif_file_name);
00191       if (xxx) {
00192         cerr << "Error trying to delete file " << cmpdif_file_name << endl;
00193         xxx=unlink(cmpdif_file_name);
00194         cout << xxx << endl;
00195       }
00196 #endif
00197   }
00198 
00199 
00204 void ad_sbuffer::fread(void* s,const size_t num_bytes)
00205 {
00206   if (toffset < num_bytes)
00207   {
00208     long lpos = lseek(file_ptr,-((long int) buff_size),SEEK_CUR);
00209     //cout << "In fread filepos = " << lpos << endl;
00210     read_cmpdif_stack_buffer(lpos);
00211 /*
00212     for(int i=0;i<sizeof(unsigned int);i++)
00213     {
00214        fourb[i] = *(buff+buff_end+1+i);
00215     }
00216 */
00217    // cout << "roffset: " << offset << endl;
00218     offset -= num_bytes;
00219     toffset = offset;
00220   }
00221   else
00222   {
00223     toffset-=num_bytes; //decrement the temporary offset count
00224   }
00225   byte_copy((char *)s,buff+toffset,num_bytes);
00226   offset=toffset;
00227 }
00228 
00233 void ad_sbuffer::fwrite(void* s, const size_t num_bytes)
00234 {
00235   #ifdef NO_DERIVS
00236     if (gradient_structure::no_derivatives)
00237     {
00238       return;
00239     }
00240   #endif
00241   toffset+=num_bytes; //increment the temporary offset count
00242   if (toffset>buff_end)
00243   {
00244     if (num_bytes > buff_end)
00245     {
00246       const int us=sizeof(unsigned int);
00247       cerr << "Need to increase gradient_structure::CMPDIF_BUFFER_SIZE "
00248        "to at least" << long (toffset)+long(us)+2L << endl;
00249     }
00250     write_cmpdif_stack_buffer();
00251     toffset=num_bytes;
00252     offset=0;
00253   }
00254   byte_copy(buff+offset,(char *) s,num_bytes);
00255   offset=toffset;
00256 }
00257 
00262 void ad_sbuffer::read_cmpdif_stack_buffer(long int& lpos)
00263 {
00264   if (lpos == -1L)
00265   { cerr << "Error rewinding file in ad_sbuffer:fread"<<endl;
00266     ad_exit(1);
00267   }
00268     //cout << " trying to read buff_size = " << buff_size 
00269       //   << " from cmpdif file" << endl;
00270   //cout << "offset before read is " << lseek(file_ptr,0,SEEK_CUR)<< endl;
00271   if (read(file_ptr,buff,buff_size)<buff_size)
00272   {
00273     cerr << "End of file trying to read "<< cmpdif_file_name << endl;
00274     ad_exit(1);
00275   }
00276   lpos = lseek(file_ptr,-((long int) buff_size),SEEK_CUR);
00277   //cout << "offset after read is " << lseek(file_ptr,0,SEEK_CUR)<< endl;
00278   for(unsigned int i=0;i<sizeof(unsigned int);i++)
00279   {
00280      fourb[i] = *(buff+buff_end+1+i);
00281   }
00282 }
00283 
00288   void ad_sbuffer::write_cmpdif_stack_buffer(void)
00289   {
00290     //cout << " trying to write buff_size = " << buff_size 
00291       //   << " into cmpdif file" << endl;
00292     //clogf << " trying to write buff_size = " << buff_size 
00293          //<< " into cmpdif file" << endl;
00294     //cout << "offset before write is " << lseek(file_ptr,0,SEEK_CUR)<< endl;
00295     //if (write(file_ptr,buff,buff_size)<buff_size)
00296     for(unsigned int i=0;i<sizeof(unsigned int);i++)
00297     {
00298    *(buff+buff_end+1+i)=fourb[i]; // save the offset at the
00299       //end of the used part of the buffer
00300     }
00301     if (write(file_ptr,buff,buff_size)<buff_size)
00302     {
00303       cerr << "End of file trying to write to file "<< cmpdif_file_name << endl;
00304       cerr << "There is probably no more room on the TMP1 (if defined) device\n"
00305       "If possible set TMP1 environment string to a device with more room\n";
00306       ad_exit(1);
00307     }
00308     //cout << "offset after write is " << lseek(file_ptr,0,SEEK_CUR)<< endl;
00309     //clogf << "offset after write is " << lseek(file_ptr,0,SEEK_CUR)<< endl;
00310   }
00311 
00316 void byte_copy(void * dest,void * source, unsigned num_bytes)
00317 {
00318 #if !defined (__SUN__) && !defined (__WAT32__) && !defined(__ADSGI__) && !defined (__MSVC32__) && !defined(linux)
00319   char* pdest = (char*)dest;
00320   char* psource = (char*)source;
00321   int ii=0;
00322   while (ii < num_bytes)
00323   {
00324     //*((char *)dest)++ = *((char *)source)++;
00325     *pdest = *psource;
00326     pdest++;
00327     psource++;
00328     ii++;
00329   }
00330 #else
00331   memcpy((char*)dest, (char*)source, num_bytes);
00332 #endif
00333  }