TMidasFile.cxx

Go to the documentation of this file.
00001 //
00002 //  TMidasFile.cxx.
00003 //
00004 
00005 #include <stdio.h>
00006 #include <string.h>
00007 #include <sys/types.h>
00008 #include <sys/stat.h>
00009 #include <fcntl.h>
00010 #include <errno.h>
00011 #include <assert.h>
00012 
00013 #ifdef HAVE_ZLIB
00014 #include <zlib.h>
00015 #endif
00016 
00017 #include "TMidasFile.h"
00018 #include "TMidasEvent.h"
00019 
00020 TMidasFile::TMidasFile()
00021 {
00022   uint32_t endian = 0x12345678;
00023 
00024   fFile = -1;
00025   fGzFile = NULL;
00026   fPoFile = NULL;
00027   fLastErrno = 0;
00028 
00029   fOutFile = -1;
00030   fOutGzFile = NULL;
00031 
00032   fDoByteSwap = *(char*)(&endian) != 0x78;
00033 }
00034 
00035 TMidasFile::~TMidasFile()
00036 {
00037   Close();
00038   OutClose();
00039 }
00040 
00041 static int hasSuffix(const char*name,const char*suffix)
00042 {
00043   const char* s = strstr(name,suffix);
00044   if (s == NULL)
00045     return 0;
00046 
00047   return (s-name)+strlen(suffix) == strlen(name);
00048 }
00049 
00050 bool TMidasFile::Open(const char *filename)
00051 {
00052   /// Open a midas .mid file with given file name.
00053   ///
00054   /// Remote files can be accessed using these special file names:
00055   /// - pipein://command - read data produced by given command, see examples below
00056   /// - ssh://username\@hostname/path/file.mid - read remote file through an ssh pipe
00057   /// - ssh://username\@hostname/path/file.mid.gz and file.mid.bz2 - same for compressed files
00058   /// - dccp://path/file.mid (also file.mid.gz and file.mid.bz2) - read data from dcache, requires dccp in the PATH
00059   ///
00060   /// Examples:
00061   /// - ./event_dump.exe /ladd/data9/t2km11/data/run02696.mid.gz - read normal compressed file
00062   /// - ./event_dump.exe ssh://ladd09//ladd/data9/t2km11/data/run02696.mid.gz - read compressed file through ssh to ladd09 (note double "/")
00063   /// - ./event_dump.exe pipein://"cat /ladd/data9/t2km11/data/run02696.mid.gz | gzip -dc" - read data piped from a command or script (note quotes)
00064   /// - ./event_dump.exe pipein://"gzip -dc /ladd/data9/t2km11/data/run02696.mid.gz" - another way to read compressed files
00065   /// - ./event_dump.exe dccp:///pnfs/triumf.ca/data/t2km11/aug2008/run02837.mid.gz - read file directly from a dcache pool (note triple "/")
00066   ///
00067   /// \param [in] filename The file to open.
00068   /// \returns "true" for succes, "false" for error, use GetLastError() to see why
00069 
00070   if (fFile > 0)
00071     Close();
00072 
00073   fFilename = filename;
00074 
00075   std::string pipe;
00076 
00077   // Do we need these?
00078   //signal(SIGPIPE,SIG_IGN); // crash if reading from closed pipe
00079   //signal(SIGXFSZ,SIG_IGN); // crash if reading from file >2GB without O_LARGEFILE
00080 
00081   if (strncmp(filename, "ssh://", 6) == 0)
00082     {
00083       const char* name = filename + 6;
00084       const char* s = strstr(name, "/");
00085 
00086       if (s == NULL)
00087         {
00088           fLastErrno = -1;
00089           fLastError = "TMidasFile::Open: Invalid ssh:// URI. Should be: ssh://user@host/file/path/...";
00090           return false;
00091         }
00092 
00093       const char* remoteFile = s + 1;
00094 
00095       std::string remoteHost;
00096       for (s=name; *s != '/'; s++)
00097         remoteHost += *s;
00098 
00099       pipe = "ssh -e none -T -x -n ";
00100       pipe += remoteHost;
00101       pipe += " dd if=";
00102       pipe += remoteFile;
00103       pipe += " bs=1024k";
00104 
00105       if (hasSuffix(remoteFile,".gz"))
00106         pipe += " | gzip -dc";
00107       else if (hasSuffix(remoteFile,".bz2"))
00108         pipe += " | bzip2 -dc";
00109     }
00110   else if (strncmp(filename, "dccp://", 7) == 0)
00111     {
00112       const char* name = filename + 7;
00113 
00114       pipe = "dccp ";
00115       pipe += name;
00116       pipe += " /dev/fd/1";
00117 
00118       if (hasSuffix(filename,".gz"))
00119         pipe += " | gzip -dc";
00120       else if (hasSuffix(filename,".bz2"))
00121         pipe += " | bzip2 -dc";
00122     }
00123   else if (strncmp(filename, "pipein://", 9) == 0)
00124     {
00125       pipe = filename + 9;
00126     }
00127 #if 0 // read compressed files using the zlib library
00128   else if (hasSuffix(filename, ".gz"))
00129     {
00130       pipe = "gzip -dc ";
00131       pipe += filename;
00132     }
00133 #endif
00134   else if (hasSuffix(filename, ".bz2"))
00135     {
00136       pipe = "bzip2 -dc ";
00137       pipe += filename;
00138     }
00139   else if (hasSuffix(filename, ".lz4"))
00140     {
00141       pipe = "lz4 -d ";
00142       pipe += filename;
00143     }
00144 
00145   if (pipe.length() > 0)
00146     {
00147       fprintf(stderr,"TMidasFile::Open: Reading from pipe: %s\n", pipe.c_str());
00148 
00149       fPoFile = popen(pipe.c_str(), "r");
00150 
00151       if (fPoFile == NULL)
00152         {
00153           fLastErrno = errno;
00154           fLastError = strerror(errno);
00155           return false;
00156         }
00157 
00158       fFile = fileno((FILE*)fPoFile);
00159     }
00160   else
00161     {
00162 #ifndef O_LARGEFILE
00163 #define O_LARGEFILE 0
00164 #endif
00165 
00166       fFile = open(filename, O_RDONLY | O_LARGEFILE);
00167 
00168       if (fFile <= 0)
00169         {
00170           fLastErrno = errno;
00171           fLastError = strerror(errno);
00172           return false;
00173         }
00174 
00175       if (hasSuffix(filename, ".gz"))
00176         {
00177           // this is a compressed file
00178 #ifdef HAVE_ZLIB
00179           fGzFile = new gzFile;
00180           (*(gzFile*)fGzFile) = gzdopen(fFile,"rb");
00181           if ((*(gzFile*)fGzFile) == NULL)
00182             {
00183               fLastErrno = -1;
00184               fLastError = "zlib gzdopen() error";
00185               return false;
00186             }
00187 #else
00188           fLastErrno = -1;
00189           fLastError = "Do not know how to read compressed MIDAS files";
00190           return false;
00191 #endif
00192         }
00193     }
00194 
00195   return true;
00196 }
00197 
00198 bool TMidasFile::OutOpen(const char *filename)
00199 {
00200   /// Open a midas .mid file for OUTPUT with given file name.
00201   ///
00202   /// Remote files not yet implemented
00203   ///
00204   /// \param [in] filename The file to open.
00205   /// \returns "true" for succes, "false" for error, use GetLastError() to see why
00206 
00207   if (fOutFile > 0)
00208     OutClose();
00209   
00210   fOutFilename = filename;
00211   
00212   printf ("Attempting normal open of file %s\n", filename);
00213   //fOutFile = open(filename, O_CREAT |  O_WRONLY | O_LARGEFILE , S_IRUSR| S_IWUSR | S_IRGRP | S_IROTH );
00214   //fOutFile = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, 0644);
00215   fOutFile = open (filename, O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE, 0644);
00216   
00217   if (fOutFile <= 0)
00218     {
00219       fLastErrno = errno;
00220       fLastError = strerror(errno);
00221       return false;
00222     }
00223   
00224   printf("Opened output file %s ; return fOutFile is %i\n",filename,fOutFile);
00225 
00226   if (hasSuffix(filename, ".gz"))
00227     // (hasSuffix(filename, ".dummy"))
00228     {
00229       // this is a compressed file
00230 #ifdef HAVE_ZLIB
00231       fOutGzFile = new gzFile;
00232       *(gzFile*)fOutGzFile = gzdopen(fOutFile,"wb");
00233       if ((*(gzFile*)fOutGzFile) == NULL)
00234         {
00235           fLastErrno = -1;
00236           fLastError = "zlib gzdopen() error";
00237           return false;
00238         }
00239       printf("Opened gz file successfully\n");
00240       if (1) 
00241         {
00242           if (gzsetparams(*(gzFile*)fOutGzFile, 1, Z_DEFAULT_STRATEGY) != Z_OK) {
00243             printf("Cannot set gzparams\n");
00244             fLastErrno = -1;
00245             fLastError = "zlib gzsetparams() error";
00246             return false;
00247           }
00248           printf("setparams for gz file successfully\n");  
00249         }
00250 #else
00251       fLastErrno = -1;
00252       fLastError = "Do not know how to write compressed MIDAS files";
00253       return false;
00254 #endif
00255     }
00256   return true;
00257 }
00258 
00259 
00260 static int readpipe(int fd, char* buf, int length)
00261 {
00262   int count = 0;
00263   while (length > 0)
00264     {
00265       int rd = read(fd, buf, length);
00266       if (rd > 0)
00267         {
00268           buf += rd;
00269           length -= rd;
00270           count += rd;
00271         }
00272       else if (rd == 0)
00273         {
00274           return count;
00275         }
00276       else
00277         {
00278           return -1;
00279         }
00280     }
00281   return count;
00282 }
00283 
00284 bool TMidasFile::Read(TMidasEvent *midasEvent)
00285 {
00286   /// \param [in] midasEvent Pointer to an empty TMidasEvent 
00287   /// \returns "true" for success, "false" for failure, see GetLastError() to see why
00288 
00289   midasEvent->Clear();
00290 
00291   int rd = 0;
00292 
00293   if (fGzFile)
00294 #ifdef HAVE_ZLIB
00295     rd = gzread(*(gzFile*)fGzFile, (char*)midasEvent->GetEventHeader(), sizeof(TMidas_EVENT_HEADER));
00296 #else
00297     assert(!"Cannot get here");
00298 #endif
00299   else
00300     rd = readpipe(fFile, (char*)midasEvent->GetEventHeader(), sizeof(TMidas_EVENT_HEADER));
00301 
00302   if (rd == 0)
00303     {
00304       fLastErrno = 0;
00305       fLastError = "EOF";
00306       return false;
00307     }
00308   else if (rd != sizeof(TMidas_EVENT_HEADER))
00309     {
00310       fLastErrno = errno;
00311       fLastError = strerror(errno);
00312       return false;
00313     }
00314 
00315   if (fDoByteSwap)
00316     midasEvent->SwapBytesEventHeader();
00317 
00318   if (!midasEvent->IsGoodSize())
00319     {
00320       fLastErrno = -1;
00321       fLastError = "Invalid event size";
00322       return false;
00323     }
00324 
00325   if (fGzFile)
00326 #ifdef HAVE_ZLIB
00327     rd = gzread(*(gzFile*)fGzFile, midasEvent->GetData(), midasEvent->GetDataSize());
00328 #else
00329     assert(!"Cannot get here");
00330 #endif
00331   else
00332     rd = readpipe(fFile, midasEvent->GetData(), midasEvent->GetDataSize());
00333 
00334   if (rd != (int)midasEvent->GetDataSize())
00335     {
00336       fLastErrno = errno;
00337       fLastError = strerror(errno);
00338       return false;
00339     }
00340 
00341   midasEvent->SwapBytes(false);
00342 
00343   return true;
00344 }
00345 
00346 bool TMidasFile::Write(TMidasEvent *midasEvent)
00347 {
00348   int wr = -2;
00349 
00350   if (fOutGzFile)
00351 #ifdef HAVE_ZLIB
00352     wr = gzwrite(*(gzFile*)fOutGzFile, (char*)midasEvent->GetEventHeader(), sizeof(TMidas_EVENT_HEADER));
00353 #else
00354     assert(!"Cannot get here");
00355 #endif
00356   else
00357     wr = write(fOutFile, (char*)midasEvent->GetEventHeader(), sizeof(TMidas_EVENT_HEADER));
00358 
00359   if(wr !=  sizeof(TMidas_EVENT_HEADER)){
00360     printf("TMidasFile: error on write event header, return %i, size requested %lu\n",wr,sizeof(TMidas_EVENT_HEADER));
00361     return false;
00362   }
00363 
00364   printf("Written event header to outfile , return is %i\n",wr);
00365 
00366   if (fOutGzFile)
00367 #ifdef HAVE_ZLIB
00368     wr = gzwrite(*(gzFile*)fOutGzFile, (char*)midasEvent->GetData(), midasEvent->GetDataSize());
00369 #else
00370     assert(!"Cannot get here");
00371 #endif
00372   else
00373     wr = write(fOutFile, (char*)midasEvent->GetData(), midasEvent->GetDataSize());
00374   printf("Written event to outfile , return is %d\n",wr);
00375 
00376   return wr;
00377 }
00378 
00379 void TMidasFile::Close()
00380 {
00381   if (fPoFile)
00382     pclose((FILE*)fPoFile);
00383   fPoFile = NULL;
00384 #ifdef HAVE_ZLIB
00385   if (fGzFile)
00386     gzclose(*(gzFile*)fGzFile);
00387   fGzFile = NULL;
00388 #endif
00389   if (fFile > 0)
00390     close(fFile);
00391   fFile = -1;
00392   fFilename = "";
00393 }
00394 
00395 void TMidasFile::OutClose()
00396 {
00397 #ifdef HAVE_ZLIB
00398   if (fOutGzFile) {
00399     gzflush(*(gzFile*)fOutGzFile, Z_FULL_FLUSH);
00400     gzclose(*(gzFile*)fOutGzFile);
00401   }
00402   fOutGzFile = NULL;
00403 #endif
00404   if (fOutFile > 0)
00405     close(fOutFile);
00406   fOutFile = -1;
00407   fOutFilename = "";
00408 }
00409 
00410 // end

Generated on 12 Feb 2016 for ROOT Analyzer by  doxygen 1.6.1