Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

RotoSocket.cxx

Go to the documentation of this file.
00001 
00002 // $Id: RotoSocket.cxx,v 1.8 2006/06/21 05:02:32 rhatcher Exp $
00003 //
00004 // An object for emulating a Tsocket using a binary file.
00005 //
00006 // Nick West
00008 
00009 #include "Rotorooter/RotoSocket.h"
00010 
00011 #include "MessageService/MsgService.h"
00012 
00013 #include <cassert>
00014 
00015 ClassImp(RotoSocket)
00016 CVSID("$Id: RotoSocket.cxx,v 1.8 2006/06/21 05:02:32 rhatcher Exp $");
00017 
00018 //_____________________________________________________________________________
00019 
00020 //
00021 //  Purpose:  Create a RotoServer
00022 //            Open binary file fpr input ready to serve it.
00023 //
00024 //  Argument: fileName   Name of binary file.
00025 //
00026 //  Return:   (none)
00027 //
00028 //  Contact:  N. West
00029 
00030 RotoSocket::RotoSocket(const char* fileName) :
00031 fCommand(INITIALISE),
00032 fAction(PREPARE_NEXT_COMMAND),
00033 fTransCmd(0),
00034 fTransLen(0),
00035 fTransAlloc(MAXBUFFER),
00036 fTransData(new long[MAXBUFFER / sizeof(long)]),
00037 fFileName(fileName),
00038 fFile(0)
00039 {
00040 
00041   MsgService::Instance()->GetStream("Roto")->SetLogLevel(Msg::kInfo);
00042   
00043   MSG("Roto",Msg::kInfo) << "Opening: " << fileName << endl;
00044 
00045   fFile=fopen(fileName,"rb");
00046   if (fFile==NULL) {
00047     printf("Failed to open input file: '%s'\n",fileName);
00048     fCommand = SEND_SHUTDOWN;
00049   }
00050 
00051 }
00052 //_____________________________________________________________________________
00053 
00054 RotoSocket::~RotoSocket()  {
00055 
00056   delete [] fTransData;
00057   if ( fFile ) fclose(fFile);
00058   fFile = 0;
00059 
00060 }
00061 
00062 //_____________________________________________________________________________
00063 
00064 void RotoSocket::NotImp(const char* method) const {
00065 
00066   MSG("Roto",Msg::kError) << "RotoSocket: Attempting to use un implimented"
00067                           << "  method: " << method << endl;
00068 }
00069 //_____________________________________________________________________________
00070 
00071 Int_t RotoSocket::RecvRaw(void *buffer, Int_t length,
00072                           ESendRecvOptions /* opt */) {
00073 //
00074 //  Purpose:  Construct and pass raw command.
00075 //
00076 //  Argument:  buffer        address of receivin
00077 //             length        size of buffer
00078 //             opt           ignored.
00079 //
00080 //  Return:    number of bytes transferred to buffer.
00081 //
00082 //  Contact:  N. West
00083 
00084   if ( fAction == PREPARE_NEXT_COMMAND ) PrepareCommand();
00085   return Transmit(buffer,length);
00086 
00087 }
00088 //_____________________________________________________________________________
00089 
00090 void RotoSocket::PrepareCommand()  {
00091 //
00092 //  Purpose:  
00093 //
00094 //  Argument: buffer        address of receiving buffer
00095 //            length        size of buffer
00096 //            
00097 //
00098 //  Return:    
00099 //
00100 //  Contact:  N. West
00101 
00102   static int  nRecords =0;
00103   const int bitDataToFollow = (1 << 15);
00104   Int_t   instr = 0;
00105 
00106   
00107 // Select next command.
00108 
00109   switch ( fCommand ) {
00110   case INITIALISE:   fCommand = OPEN_SOCKET; break;
00111   case OPEN_SOCKET:  fCommand = OPEN_FILE;   break;
00112   case OPEN_FILE:    fCommand = SEND_DATA;   break;
00113   case SEND_DATA:    break;  // do nothing
00114   default:
00115      cout << " fCommand was " << (int)fCommand << endl;
00116      assert(0);
00117   }
00118   
00119 // Prepare next command
00120 
00121   switch ( fCommand ) {
00122 
00123   case OPEN_SOCKET:
00124     instr     = MINOS_ROOTER_OPENSOCKET;
00125     fTransLen = 0;
00126     break;
00127 
00128   case OPEN_FILE:
00129     instr     = MINOS_ROOTER_OPENFILE;
00130     {
00131       int*  iptr = (int*) fTransData;
00132       char* cptr = (char*) fTransData + sizeof(int);
00133       
00134 // Signal that we are sending file name.
00135       *iptr      = MINOS_DCS | bitDataToFollow;
00136 // Remove directory path from file name and store
00137       const char* lastslash = strrchr(fFileName.c_str(),'/');
00138       if (lastslash) lastslash++;  // move past slash to next char
00139       else lastslash = fFileName.c_str();  // no slash, use whole thing
00140       sprintf(cptr,"%s",lastslash);
00141       int fnlen = strlen(cptr);
00142       cptr[fnlen] = 0;   
00143       fTransLen = sizeof(int) + fnlen + 1;
00144       
00145     }
00146     break;
00147 
00148   case SEND_DATA:
00149     instr     = MINOS_ROOTER_SHUTDOWN;  //The default if we cannot read record!
00150     fTransLen = 0;
00151     if ( feof(fFile) )  {
00152       printf("Seen EOF after record %d Quiting ...\n",nRecords);
00153       break;
00154     }
00155     if ( fread(&fTransLen,sizeof(long),1,fFile) !=1 ) {
00156       if ( feof(fFile) )  {
00157         printf("Seen EOF after record %d Quiting ...\n",nRecords);
00158       }
00159       else {
00160       printf("Read error on record %d Quiting ...\n",nRecords);
00161       }
00162       break;
00163     }
00164     nRecords++;
00165     fTransLen -= sizeof(long);  // byte count is inclusive 
00166     if ( fTransLen > fTransAlloc ) {
00167       if ( ! ReallocateBuffer(fTransLen) ) {
00168         printf("Record %d Size %ld bytes too large for buffer (%ld) Quiting ...\n",
00169                nRecords,fTransLen,fTransAlloc);
00170         fTransLen = 0;
00171       }
00172       else {
00173         printf("Record %d Size %ld bytes, buffer reallocated to %ld.\n",
00174                nRecords,fTransLen,fTransAlloc);
00175       }
00176     }
00177     if ( fread(fTransData,fTransLen,1,fFile) != 1 ) {
00178       printf("Read error on record %d Quiting ...\n",nRecords);
00179       fTransLen = 0;
00180       break;
00181     }
00182     instr     = MINOS_ROOTER_RECBUFFER;
00183     break;
00184 
00185   case SEND_SHUTDOWN:
00186     instr     = MINOS_ROOTER_SHUTDOWN;
00187     fTransLen = 0;
00188     break;
00189 
00190   default:
00191      assert(0);
00192 
00193   }
00194 
00195 
00196   fTransCmd = RotoRcCmd(MINOS_DCP,
00197                         MINOS_ROOTER,
00198                         MINOS_ROOTER_COMMAND,
00199                         instr, 
00200                         fTransLen > 0);
00201   
00202 
00203   fAction = TRANSMIT_COMMAND;
00204 
00205 }
00206 
00207 //_____________________________________________________________________________
00208 
00209 Int_t RotoSocket::Transmit(void* buffer,Int_t length) {
00210 //
00211 //  Purpose:  
00212 //
00213 //  Argument: buffer        address of receiving buffer
00214 //             length        size of buffer
00215 //            
00216 //
00217 //  Return:    
00218 //
00219 //  Contact:  N. West
00220 
00221  switch ( fAction ) {
00222  int nbytes;
00223 
00224  case  TRANSMIT_COMMAND: 
00225    memcpy(buffer,&fTransCmd.fEncoded,sizeof(long));
00226    fAction = ( fTransLen > 0 ) ? TRANSMIT_LENGTH : PREPARE_NEXT_COMMAND;
00227    return sizeof(long);
00228 
00229  case  TRANSMIT_LENGTH: 
00230    nbytes = fTransLen + sizeof(int);// Compute total length with byte count
00231    memcpy(buffer,&nbytes,sizeof(long));
00232    fAction = TRANSMIT_DATA;
00233    return sizeof(long);
00234 
00235  case  TRANSMIT_DATA: 
00236    nbytes = ( fTransLen < length ) ? fTransLen : length;
00237    memcpy(buffer,fTransData,nbytes);
00238    fAction = PREPARE_NEXT_COMMAND;
00239    return nbytes;
00240 
00241  default:
00242     assert(0);
00243  }
00244 
00245  return -1;
00246 }
00247 
00248 //_____________________________________________________________________________
00249 
00250 Bool_t RotoSocket::ReallocateBuffer(long minBytes) {
00251 //
00252 //  Purpose:  Reallocate the fTransData buffer so it is at least minBytes
00253 //            in length.
00254 //
00255 //  Argument: minBytes       minimum size of buffer
00256 //
00257 //  Return:   true if successful
00258 //
00259 //  Contact:  R. Hatcher
00260 
00261   long oldsize  = fTransAlloc;
00262   long mrequest = minBytes;
00263   int  failures = 0;
00264 
00265   // release existing buffer
00266   if (fTransData) {
00267     delete [] fTransData;
00268     fTransData = 0;
00269   }
00270 
00271   // set absolute mimimum size
00272   if ( mrequest < MAXBUFFER ) mrequest = MAXBUFFER;
00273 
00274   // round up to even 1M bytes
00275   mrequest = ((mrequest >> 20) + 1 ) << 20;
00276 
00277   while ( ! fTransData ) {
00278     fTransData = new long[mrequest / sizeof(long)];
00279     if ( fTransData ) break; // success
00280     failures++;
00281     mrequest -= 1024*sizeof(char);  // failed, try smaller size
00282   }
00283   fTransAlloc = mrequest;
00284 
00285   if ( fTransAlloc >= minBytes ) return true;
00286   
00287   printf("RotoSocket::ReallocateBuffer was unable to allocate requested "
00288          "%ld bytes \n  from initial size %ld, only got final size %ld.",
00289          minBytes,oldsize,fTransAlloc);
00290   return false;
00291 }
00292 
00293 /*
00294 
00295 //_____________________________________________________________________________
00296 
00297 RotoSocket:: {
00298 //
00299 //  Purpose:  
00300 //
00301 //  Argument: 
00302 //            
00303 //
00304 //  Return:    
00305 //
00306 //  Contact:  N. West
00307 {
00308 
00309 
00310 }
00311 
00312 */

Generated on Mon Feb 15 11:07:32 2010 for loon by  doxygen 1.3.9.1