ADMB Documentation  11.5.3346
 All Classes Files Functions Variables Typedefs Friends Defines
df_file.cpp
Go to the documentation of this file.
00001 /*
00002  * $Id$
00003  *
00004  * Author: David Fournier
00005  * Copyright (c) 2008-2012 Regents of the University of California
00006  */
00011 #include "fvar.hpp"
00012 #include <fcntl.h>
00013 
00014 #ifdef _MSC_VER
00015   #define LSEEK _lseek
00016   #define  read _read
00017   #define write _write
00018   #include <sys\stat.h>
00019 #else
00020   #include <iostream>
00021   using namespace std;
00022   #include <memory.h>
00023   #include <sys/stat.h>
00024   #include <sys/types.h>
00025   #include <unistd.h>
00026 #endif
00027 
00028 #if defined(__TURBOC__)
00029   #pragma hdrstop
00030   #include <iostream.h>
00031   #include <iomanip.h>
00032   #include <sys\stat.h>
00033 #endif
00034 
00035 #ifdef __ZTC__
00036   #include <iostream.hpp>
00037   #define S_IREAD 0000400
00038   #define S_IWRITE 0000200
00039 #endif
00040 
00041 #ifdef __NDPX__
00042   #define O_RDONLY 0
00043   #define O_WRONLY 1
00044   #define O_RDWR 2
00045   extern "C"
00046   {
00047     int LSEEK(int, int, int);
00048     int open(const char*, int);
00049     int creat(const char*, int);
00050     int close(int);
00051     int write(int, char*, int);
00052     int read(int, char*, int);
00053   };
00054 #endif
00055 
00056 #ifdef __SUN__
00057 #include <memory.h>
00058 #include <iostream.h>
00059 #include <sys/stat.h>
00060 #include <sys/types.h>
00061 #ifndef _MSC_VER
00062 #include <unistd.h>
00063 #endif
00064 #endif
00065 
00066 #include <limits.h>
00067 #include <stdlib.h>
00068 #include <stdio.h>
00069 #include <string.h>
00070 
00071 #ifdef _MSC_VER
00072   #ifdef _M_X64
00073   typedef __int64 ssize_t;
00074   #else
00075   typedef int ssize_t;
00076   #endif
00077   #ifndef SSIZE_MAX
00078     #define SSIZE_MAX INT_MAX
00079   #endif
00080 #endif
00081 
00082 #if defined(__MINGW64__) || (defined(_WIN64) && defined(_MSC_VER))
00083   #include <cassert>
00084   #include <climits>
00085 #else
00086   #ifndef OPT_LIB
00087     #include <cassert>
00088   #endif
00089 #endif
00090 
00091 char lastchar(char*);
00092 
00093 void byte_copy(void* dest, void* source, const size_t num_bytes)
00094 {
00095 #if defined(__ADSGI__)
00096   char* pdest = (char*)dest;
00097   char* psource = (char*)source;
00098   int ii=0;
00099   while (ii < num_bytes)
00100   {
00101     //*((char *)dest)++ = *((char *)source)++;
00102     *pdest = *psource;
00103     pdest++;
00104     psource++;
00105     ii++;
00106   }
00107 #else
00108   memcpy((char*)dest, (char*)source, num_bytes);
00109 #endif
00110 }
00111 
00112 extern char ad_random_part[6];
00113 
00119 DF_FILE::DF_FILE(const size_t nbytes):
00120   buff_end(nbytes - sizeof(size_t) - 2),
00121   buff_size(nbytes)
00122 {
00123 #if defined(__BORLANDC__)
00124   if (nbytes > INT_MAX)
00125   {
00126     cout << "Error -- largest size for CMPDIF_BUFFER_SIZE is "
00127          << INT_MAX<<endl;
00128   }
00129 #endif
00130 
00131 #if defined(_M_IX86)
00132   if (nbytes > LONG_MAX)
00133   {
00134     cout << "Error -- largest size for CMPDIF_BUFFER_SIZE is "
00135          << LONG_MAX <<endl;
00136   }
00137 #endif
00138 
00139 #if defined(__GNC__) && defined(__i686__)
00140   if (nbytes > INT_MAX)
00141   {
00142     cout << "Error -- largest size for CMPDIF_BUFFER_SIZE is "
00143          << INT_MAX<<endl;
00144   }
00145 #endif
00146 
00148 /*
00149 #ifndef OPT_LIB
00150   assert(nbytes > sizeof(size_t) + 2);
00151 #endif
00152 */
00153 
00154   buff = new char[buff_size];
00155   if (buff == NULL)
00156   {
00157     cerr << "Error trying to allocate memory for DF_FILE buffer"<<endl;
00158     ad_exit(1);
00159   }
00160 #ifndef OPT_LIB
00161   memset(buff, 0, buff_size);
00162 #endif
00163 
00164   offset = 0;
00165   toffset = 0;
00166 
00167   char* path = getenv("ADTMP1"); // NULL if not defined
00168 
00169 #if defined(USE_ADPVM)
00170   adstring string_path;
00171   if (path) string_path=path;
00172 
00173   adstring currdir;
00174   ad_getcd(currdir);
00175   if (ad_comm::pvm_manager)
00176   {
00177     int on = 0;
00178     int nopt = 0;
00179     if ((on = option_match(ad_comm::argc,ad_comm::argv,"-slave",nopt)) > -1)
00180     {
00181       if (nopt == 1)
00182       {
00183         int ierr=make_sub_directory(ad_comm::argv[on+1]);
00184         ad_comm::subdir=ad_comm::argv[on+1];
00185         string_path+=ad_comm::subdir;
00186         path=(char*) string_path;
00187       }
00188       else
00189       {
00190         cerr << "Wrong number of options to -slave -- must be 1"
00191           " you have " << nopt << endl;
00192         ad_exit(1);
00193       }
00194     }
00195   }
00196 #endif
00197 
00198   if (path != NULL && strlen(path) <= 45)
00199 #if !defined (_WIN32)
00200   {
00201       sprintf(&cmpdif_file_name[0],"%s/cmpdiff.%s", path,
00202         ad_random_part);
00203   }
00204 #else
00205   {
00206     if (lastchar(path) != '\\')
00207     {
00208       sprintf(&cmpdif_file_name[0],"%s\\cmpdiff.%s", path,
00209         ad_random_part);
00210     }
00211     else
00212     {
00213       sprintf(&cmpdif_file_name[0],"%scmpdiff.%s", path,
00214         ad_random_part);
00215     }
00216   }
00217 #endif
00218   else
00219   {
00220     sprintf(&cmpdif_file_name[0],"cmpdiff.%s",ad_random_part);
00221   }
00222 #if defined (_MSC_VER) || defined (__WAT32__)
00223   file_ptr=open(cmpdif_file_name, O_RDWR | O_CREAT | O_TRUNC |
00224                      O_BINARY, S_IREAD | S_IWRITE);
00225 #elif defined (__TURBOC__)
00226   file_ptr=open(cmpdif_file_name, O_RDWR | O_CREAT | O_TRUNC |
00227                      O_BINARY, S_IREAD | S_IWRITE);
00228 #elif defined (__ZTC__)
00229   file_ptr=open(cmpdif_file_name, O_RDWR | O_CREAT | O_TRUNC ,
00230                      S_IREAD | S_IWRITE);
00231 #elif  defined (__NDPX__)
00232   file_ptr=creat(cmpdif_file_name, O_RDWR);
00233 #else
00234   file_ptr=open(cmpdif_file_name, O_RDWR | O_CREAT | O_TRUNC |
00235        O_BINARY, 0777);
00236 #endif
00237 
00238   if (file_ptr == -1)
00239   {
00240     if (ad_printf) (*ad_printf)("Error opening temporary gradient"
00241         " file %s\n", cmpdif_file_name );
00242     ad_exit(1);
00243   }
00244 }
00248 DF_FILE::~DF_FILE()
00249 {
00250   delete [] buff;
00251   buff=0;
00252 
00253   int repfs = option_match(ad_comm::argc,ad_comm::argv,"-fsize");
00254 
00255   if (ad_comm::global_logfile && repfs)
00256   {
00257     OFF_T pos = LSEEK(file_ptr, 0, SEEK_END);
00258     *ad_comm::global_logfile << "size of file " << cmpdif_file_name
00259         << " = " << pos << endl;
00260   }
00261   if (close(file_ptr))
00262   {
00263     cerr << "Error closing file " << cmpdif_file_name << "\n";
00264   }
00265 #if !defined (_WIN32)
00266   unlink(cmpdif_file_name);
00267 #else
00268   adstring currentdir;
00269   ad_getcd(currentdir);
00270   int xxx=remove(cmpdif_file_name);
00271   if (xxx)
00272   {
00273     cerr << "Error trying to delete file " << cmpdif_file_name << endl;
00274     xxx=unlink(cmpdif_file_name);
00275     cout << xxx << endl;
00276   }
00277 #endif
00278 }
00283 void DF_FILE::fread(void* s,const size_t num_bytes)
00284 {
00285   if (toffset < num_bytes)
00286   {
00287     OFF_T lpos = LSEEK(file_ptr, -((OFF_T)buff_size), SEEK_CUR);
00288     read_cmpdif_stack_buffer(lpos);
00289     offset -= num_bytes;
00290     toffset = offset;
00291   }
00292   else
00293   {
00294     toffset-=num_bytes; //decrement the temporary offset count
00295   }
00296   byte_copy((char*)s, buff+toffset,num_bytes);
00297   offset=toffset;
00298 }
00303 void DF_FILE::fwrite(const void* s, const size_t num_bytes)
00304 {
00305 #ifdef NO_DERIVS
00306   if (gradient_structure::no_derivatives)
00307   {
00308     return;
00309   }
00310 #endif
00311   toffset+=num_bytes; //increment the temporary offset count
00312   if (toffset>buff_end)
00313   {
00314     if (num_bytes > buff_end)
00315     {
00316       const size_t us = toffset + sizeof(size_t) + 2L;
00317       cerr << "Need to increase gradient_structure::CMPDIF_BUFFER_SIZE "
00318        "to at least" << us << endl;
00319     }
00320     write_cmpdif_stack_buffer();
00321     toffset=num_bytes;
00322     offset=0;
00323   }
00324   byte_copy(buff+offset,(char *) s,num_bytes);
00325   offset=toffset;
00326 }
00331 void DF_FILE::read_cmpdif_stack_buffer(OFF_T& lpos)
00332 {
00333   if (lpos == -1L)
00334   {
00335     cerr << "Error rewinding file in DF_FILE:fread"<<endl;
00336     ad_exit(1);
00337   }
00338 #if defined(__MINGW64__) || (defined(_WIN64) && defined(_MSC_VER))
00339   assert(buff_size <= UINT_MAX);
00340   if (read(file_ptr, buff, (unsigned int)buff_size) < 0)
00341 #else
00342   ssize_t bytes_read = read(file_ptr, buff, buff_size);
00343   if (bytes_read < 0)
00344 #endif
00345   {
00346     cerr << "End of file trying to read "<< cmpdif_file_name << endl;
00347     ad_exit(1);
00348   }
00349   lpos = LSEEK(file_ptr, -((OFF_T)buff_size),SEEK_CUR);
00350   for (size_t i = 0;i < sizeof(size_t); i++)
00351   {
00352     fourb[i] = *(buff+buff_end+1+i);
00353   }
00354 }
00359 void DF_FILE::write_cmpdif_stack_buffer(void)
00360 {
00361   // save the offset at the end of the used part of the buffer
00362   for (size_t i = 0; i < sizeof(size_t); i++)
00363   {
00364     *(buff+buff_end+1+i) = fourb[i];
00365   }
00366 #if defined(__MINGW64__) || (defined(_WIN64) && defined(_MSC_VER))
00367   assert(buff_size <= UINT_MAX);
00368   if (write(file_ptr, buff, (unsigned int)buff_size) < 0)
00369 #else
00370   if (write(file_ptr, buff, buff_size) < 0)
00371 #endif
00372   {
00373     cerr << "End of file trying to write to file "<< cmpdif_file_name << endl;
00374     cerr << "There is probably no more room on the TMP1 (if defined) device\n"
00375     "If possible set TMP1 environment string to a device with more room\n";
00376     ad_exit(1);
00377   }
00378 }