// $Id$ //----------------------------------------------------------------------- // The GSI Online Offline Object Oriented (Go4) Project // Experiment Data Processing at EE department, GSI //----------------------------------------------------------------------- // Copyright (C) 2000- GSI Helmholtzzentrum für Schwerionenforschung GmbH // Planckstr. 1, 64291 Darmstadt, Germany // Contact: http://go4.gsi.de //----------------------------------------------------------------------- // This software can be used under the license agreements as stated // in Go4License.txt file which is part of the distribution. //----------------------------------------------------------------------- #include #include #include #include #include #include #include #ifdef Lynx /* LynxOS */ #include #include #include #endif #ifdef Linux /* Linux */ #include #include #include #endif #ifdef Solaris /* Solaris */ #include #include #include #endif #ifdef Darwin /* Max OS X */ #include #include #include #define fgetpos64 fgetpos #define fopen64 fopen #define fseeko64 fseek #define fpos64_t fpos_t /* just some dummies for compilation, we will never write lmd with time header in go4*/ #define CLOCK_REALTIME 1 int clock_gettime(int clockid, struct timespec *tp) { return 0; } #endif #ifdef WIN32 #include #include #define fgetpos64 fgetpos #define fopen64 fopen #define fseeko64 fseek #define fpos64_t fpos_t struct timespec { long tv_sec; /* seconds */ long tv_nsec; /* nanoseconds */ }; #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64 #else #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL #endif #define CLOCK_REALTIME 1 int clock_gettime(int clockid, struct timespec *tp) { FILETIME ft; unsigned __int64 tmpres = 0; tp->tv_sec = 0; tp->tv_nsec = 0; GetSystemTimeAsFileTime(&ft); tmpres |= ft.dwHighDateTime; tmpres <<= 32; tmpres |= ft.dwLowDateTime; /*converting file time to unix epoch*/ tmpres /= 10; /*convert into microseconds*/ tmpres -= DELTA_EPOCH_IN_MICROSECS; tp->tv_sec = (long)(tmpres / 1000000UL); tp->tv_nsec = (long)(tmpres % 1000000UL) * 1000; return 0; } #endif #include "fLmd.h" int32_t fLmdWriteBuffer(sLmdControl *, char *, uint32_t); uint32_t fLmdCleanup(sLmdControl *); void fLmdOffsetResize(sLmdControl *, uint32_t); uint32_t fLmdOffsetSet(sLmdControl *, uint32_t ); uint32_t fLmdOffsetRead(sLmdControl *); uint32_t fLmdOffsetWrite(sLmdControl *); lmdoff_t fLmdOffsetGet(sLmdControl *, uint32_t); void fLmdOffsetElements(sLmdControl *, uint32_t, uint32_t *, uint32_t *); #define OFFSET__ENTRIES 250000 //=============================================================== uint32_t fLmdPutOpen( sLmdControl *pLmdControl, char *Filename, sMbsFileHeader *pBuffHead, // LMD__STANDARD_HEADER (NULL) or address uint32_t iBytes, // LMD__NO_BUFFER (0) or buffer size uint32_t iOver, // LMD__[NO_]OVERWRITE uint32_t iUseOffset, // LMD__[NO_]INDEX uint32_t iLargeFile){ // LMD__[NO_]LARGE_FILE int32_t iReturn; struct timespec clock; memset(pLmdControl,0,sizeof(sLmdControl)); // allocate header or take extern if(pBuffHead == LMD__STANDARD_HEADER){ pLmdControl->pMbsFileHeader= (sMbsFileHeader *)malloc(sizeof(sMbsFileHeader)); memset(pLmdControl->pMbsFileHeader,0,sizeof(sMbsFileHeader)); pLmdControl->iInternHeader=1; } else { pLmdControl->pMbsFileHeader= pBuffHead; pLmdControl->iInternHeader=0; } clock_gettime(CLOCK_REALTIME,&clock); pLmdControl->pMbsFileHeader->iTimeSpecSec=clock.tv_sec; pLmdControl->pMbsFileHeader->iTimeSpecNanoSec=clock.tv_nsec; pLmdControl->pMbsFileHeader->iType=LMD__TYPE_FILE_HEADER_101_1; pLmdControl->pMbsFileHeader->iEndian=1; strcpy(pLmdControl->cFile,Filename); // optionally allocate buffer if(iBytes > 0){ pLmdControl->pBuffer=(int16_t *)malloc(iBytes); pLmdControl->iInternBuffer=1; } pLmdControl->iBufferWords=iBytes/2; pLmdControl->iLeftWords=iBytes/2; // open file if(iOver == LMD__NO_OVERWRITE){ // do not overwrite if((pLmdControl->fFile=(FILE *)fopen64(Filename,"r") )!=NULL){ printf("fLmdPutOpen: File exists: %s\n",Filename); fLmdCleanup(pLmdControl); fclose(pLmdControl->fFile); return(PUTLMD__FILE_EXIST); }} if((pLmdControl->fFile=(FILE *)fopen64(Filename,"w+") )== NULL){ printf("fLmdPutOpen: Error open file %s\n",Filename); fLmdCleanup(pLmdControl); return(PUTLMD__OPEN_ERR); } if(iLargeFile == LMD__LARGE_FILE)pLmdControl->iOffsetSize=8; else pLmdControl->iOffsetSize=4; pLmdControl->pMbsFileHeader->iOffsetSize=pLmdControl->iOffsetSize; // write header iReturn=fLmdWriteBuffer(pLmdControl,(char *)pLmdControl->pMbsFileHeader, (pLmdControl->pMbsFileHeader->iUsedWords)*2+sizeof(sMbsFileHeader)); pLmdControl->iBytes+=iReturn; if(iUseOffset == LMD__INDEX)fLmdOffsetResize(pLmdControl,iReturn/4); // create and set first value printf("fLmdPutOpen: %s. Bytes:%d over:%d table:%d large:%d.\n", Filename,iBytes,iOver,iUseOffset,iLargeFile); return(LMD__SUCCESS); } //=============================================================== uint32_t fLmdPutElement( sLmdControl *pLmdControl, sMbsHeader *pHeader){ uint32_t *ps, *pd, i, elements; int64_t fileleft,used; int32_t iReturn; // enough space left? if(pLmdControl->iOffsetEntries && (pLmdControl->iOffsetSize == 4)){ elements=pLmdControl->iElements+2; used=pLmdControl->iBytes/4; fileleft=0xffffffff - used - (4+elements); // size of table if((int64_t)(pHeader->iWords/2+2) > fileleft){ printf("fLmdPutElement: File size exceed\n"); return(PUTLMD__EXCEED); } } // save largest size in header if((pHeader->iWords+4) > pLmdControl->pMbsFileHeader->iMaxWords) pLmdControl->pMbsFileHeader->iMaxWords=pHeader->iWords+4; // no buffer, write element directly if(pLmdControl->iBufferWords == 0){ pLmdControl->pMbsHeader=pHeader; iReturn=fLmdWriteBuffer(pLmdControl,(char *)pHeader,(pHeader->iWords+4)*2); pLmdControl->iBytes+=iReturn; if(iReturn != (pHeader->iWords+4)*2){ printf("fLmdPutElement: Write error \n"); return(LMD__FAILURE); } pLmdControl->pMbsFileHeader->iElements++; pLmdControl->iElements++; if(pLmdControl->iOffsetEntries)fLmdOffsetSet(pLmdControl,iReturn/4); return(LMD__SUCCESS); } // end no buffer if((pHeader->iWords+4) > pLmdControl->iLeftWords){ // flash buffer to file iReturn=fLmdWriteBuffer(pLmdControl, (char *)pLmdControl->pBuffer, (pLmdControl->iBufferWords-pLmdControl->iLeftWords)*2); pLmdControl->iBytes+=iReturn; if(iReturn != (pLmdControl->iBufferWords-pLmdControl->iLeftWords)*2)return(LMD__FAILURE); pLmdControl->iLeftWords=pLmdControl->iBufferWords; // buffer free } if((pHeader->iWords+4) > pLmdControl->iLeftWords){ // element too big for buffer printf("fLmdPutElement: Element too big: %d words\n",pHeader->iWords+4); return(PUTLMD__TOOBIG); } // copy to buffer ps=(uint32_t *)pHeader; pd=(uint32_t *)pLmdControl->pBuffer+(pLmdControl->iBufferWords-pLmdControl->iLeftWords)/2; iReturn=(pHeader->iWords+4)/2; // here 32b words for(i=0;ipMbsFileHeader->iElements++; pLmdControl->iElements++; pLmdControl->iLeftWords -= (pHeader->iWords+4); if(pLmdControl->iOffsetEntries)fLmdOffsetSet(pLmdControl,iReturn); return(LMD__SUCCESS); } //=============================================================== uint32_t fLmdPutBuffer( sLmdControl *pLmdControl, sMbsHeader *pHeader, uint32_t Items){ sMbsHeader *pH; uint32_t Bytes=0,TotalBytes=0,i, elements; int64_t fileleft,used; int32_t iReturn; // check if total buffer fits in file if(pLmdControl->iOffsetEntries && (pLmdControl->iOffsetSize == 4)){ pH=pHeader; // SL 16.11.2009 - pH was not initialized in this branch elements=pLmdControl->iElements+Items+2; used=pLmdControl->iBytes/4; fileleft=0xffffffff - used - (4+elements); // size of table for(i=0;iiWords)*2; TotalBytes += Bytes; pH=(sMbsHeader *)((int16_t*)pH + Bytes/2); } if((int64_t)TotalBytes/4 > fileleft){ printf("fLmdPutElement: File size exceed\n"); return(PUTLMD__EXCEED); } Bytes=0; TotalBytes=0; } pH=pHeader; for(i=0;iiElements++; Bytes = (4+pH->iWords)*2; TotalBytes += Bytes; if(pLmdControl->iOffsetEntries)fLmdOffsetSet(pLmdControl,Bytes/4); if((pH->iWords+4) > pLmdControl->pMbsFileHeader->iMaxWords) pLmdControl->pMbsFileHeader->iMaxWords=pH->iWords+4; pH=(sMbsHeader *)((int16_t *)pH+Bytes/2); } iReturn=fLmdWriteBuffer(pLmdControl,(char *)pHeader,TotalBytes); pLmdControl->iBytes+=iReturn; if(iReturn != TotalBytes)return(LMD__FAILURE); else { pLmdControl->pMbsFileHeader->iElements += Items; return(LMD__SUCCESS); } } //=============================================================== uint32_t fLmdPutClose( sLmdControl *pLmdControl){ int32_t iReturn,i; lmdoff_t current,c; if(pLmdControl->iBufferWords > pLmdControl->iLeftWords){ // write last buffer iReturn=fLmdWriteBuffer(pLmdControl, (char *)pLmdControl->pBuffer, (pLmdControl->iBufferWords-pLmdControl->iLeftWords)*2); pLmdControl->iBytes+=iReturn; if(iReturn != (pLmdControl->iBufferWords-pLmdControl->iLeftWords)*2){ printf("fLmdPutClose: Error writing last buffer. Closing file.\n"); // rewind file and rewrite header rewind(pLmdControl->fFile); /* rewind file, rewrite header */ fLmdWriteBuffer(pLmdControl, (char *)pLmdControl->pMbsFileHeader, sizeof(sMbsFileHeader)); fLmdCleanup(pLmdControl); return(LMD__FAILURE); } } if(pLmdControl->iOffsetEntries) if(fLmdOffsetWrite(pLmdControl) != LMD__SUCCESS) pLmdControl->pMbsFileHeader->iTableOffset=0; // table could not be written // rewind file and rewrite header rewind(pLmdControl->fFile); /* rewind file, rewrite header */ fLmdWriteBuffer(pLmdControl, (char *)pLmdControl->pMbsFileHeader, sizeof(sMbsFileHeader)); return(fLmdGetClose(pLmdControl)); } #ifndef FILEONLY //=============================================================== uint32_t fLmdConnectMbs( sLmdControl *pLmdControl, char *Nodename, uint32_t iPort, uint32_t *iBufferBytes){ // LMD__GET_EVENTS (NULL) or address to return buffer size int32_t stat; sMbsTransportInfo sMbs; if(iPort == 0) pLmdControl->iPort=PORT__TRANS; else pLmdControl->iPort=iPort; memset(pLmdControl,0,sizeof(sLmdControl)); pLmdControl->pTCP=(struct s_tcpcomm *)malloc(sizeof(struct s_tcpcomm)); pLmdControl->iTCPowner=1; if(pLmdControl->iPort==PORT__TRANS) printf("fLmdConnectMbs: Connect to transport server %s port %d\n",Nodename,pLmdControl->iPort); if(pLmdControl->iPort==PORT__STREAM) printf("fLmdConnectMbs: Connect to stream server %s port %d\n",Nodename,pLmdControl->iPort); stat=f_stc_connectserver(Nodename,pLmdControl->iPort,&pLmdControl->iTCP,pLmdControl->pTCP); if (stat != STC__SUCCESS) { printf ("fLmdConnectMbs: Error connect to %s \n",Nodename); fLmdCleanup(pLmdControl); return(LMD__FAILURE); } stat=f_stc_read((int32_t *)&sMbs, sizeof(sMbsTransportInfo),pLmdControl->iTCP,3); if (stat != STC__SUCCESS) { printf ("fLmdConnectMbs: Error read info from %s \n",Nodename); fLmdCleanup(pLmdControl); return(LMD__FAILURE); } if(sMbs.iEndian != 1)pLmdControl->iSwap=1; if(pLmdControl->iSwap)fLmdSwap4((uint32_t *)&sMbs,sizeof(sMbsTransportInfo)/4); if(sMbs.iBuffers > 1){ printf("fLmdConnectMbs: Event spanning not supported!\n"); fLmdCleanup(pLmdControl); return(LMD__FAILURE); } if(sMbs.iStreams > 0){ printf("fLmdConnectMbs: MBS not in DABC mode!\n"); fLmdCleanup(pLmdControl); return(LMD__FAILURE); } strcpy(pLmdControl->cFile,Nodename); if(iBufferBytes == LMD__GET_EVENTS){ // use internal buffer for fLmdGetMbsEvent pLmdControl->pBuffer = (int16_t *) malloc(sMbs.iMaxBytes); pLmdControl->iBufferWords=sMbs.iMaxBytes/2; pLmdControl->iInternBuffer=1; } else *iBufferBytes=sMbs.iMaxBytes; return(LMD__SUCCESS); } //=============================================================== uint32_t fLmdInitMbs( sLmdControl *pLmdControl, char *Nodename, uint32_t iMaxBytes, uint32_t iBuffers, uint32_t iStreams, uint32_t iPort, uint32_t iTimeout){ int32_t stat; if(iBuffers > 1){printf("fLmdInitMbs: Event spanning not supported!\n");return(LMD__FAILURE);} if(iStreams > 0){printf("fLmdInitMbs: MBS not in DABC mode!\n");return(LMD__FAILURE);} pLmdControl->iPort=iPort; strcpy(pLmdControl->cFile,Nodename); if(pLmdControl->pBuffer == NULL)pLmdControl->pBuffer= (int16_t *) malloc(iMaxBytes); pLmdControl->iBufferWords=iMaxBytes/2; pLmdControl->iInternBuffer=1; pLmdControl->iTCP=pLmdControl->pTCP->socket; pLmdControl->iTcpTimeout=iTimeout; pLmdControl->iTCPowner=0; return(LMD__SUCCESS); } //=============================================================== uint32_t fLmdCloseMbs(sLmdControl *pLmdControl){ int32_t stat; const char cClose[12] = "CLOSE"; // send request buffer for stream server if(pLmdControl->iPort == PORT__STREAM) stat=f_stc_write(cClose,12,pLmdControl->iTCP); stat=f_stc_close(pLmdControl->pTCP); pLmdControl->pMbsFileHeader = NULL; // was reference only if(pLmdControl->iTCPowner==0)pLmdControl->pTCP=NULL; // was reference only fLmdCleanup(pLmdControl); return(stat); } //=============================================================== uint32_t fLmdGetMbsEvent(sLmdControl *pLmdControl, sMbsHeader** event){ uint32_t stat; sMbsHeader *pM; *event=NULL; if(pLmdControl->iLeftWords == 0){ // get new buffer stat=fLmdGetMbsBuffer(pLmdControl,NULL,0,NULL,NULL); if(stat != LMD__SUCCESS){ return(stat); } // first event behind header: pLmdControl->pMbsHeader=(sMbsHeader *)(pLmdControl->pBuffer+sizeof(sMbsBufferHeader)/2); } pM=pLmdControl->pMbsHeader; // current to be returned pLmdControl->iLeftWords -= (pLmdControl->pMbsHeader->iWords+4); pLmdControl->pMbsHeader = (sMbsHeader *)((int16_t *)pLmdControl->pMbsHeader + pLmdControl->pMbsHeader->iWords+4); pLmdControl->iElements++; *event=pM; return(LMD__SUCCESS); } //=============================================================== uint32_t fLmdGetMbsBuffer( sLmdControl *pLmdControl, sMbsBufferHeader *pBuffer, uint32_t iBytes, uint32_t *iElements, uint32_t *iBytesUsed){ sMbsHeader *pm; sMbsBufferHeader *pBuf; uint32_t *ps, *pd, i,ii, elem=0, size=0, usedBytes=0,leftBytes=0; int32_t iReturn; const char cRequest[12] = "GETEVT"; leftBytes=iBytes; pBuf=pBuffer; if(pBuf == NULL){ pBuf=(sMbsBufferHeader *)pLmdControl->pBuffer; // internal buffer leftBytes=pLmdControl->iBufferWords*2; // size of this buffer } if(pBuf == NULL){ printf("fLmdGetMbsBuffer: Need buffer to read\n"); return(LMD__FAILURE); } if(leftBytes < sizeof(sMbsBufferHeader)){ printf("fLmdGetMbsBuffer: %s buffer size %d too small for %d bytes\n", pLmdControl->cFile,leftBytes,sizeof(sMbsBufferHeader)); return(LMD__FAILURE); } // send request buffer for stream server if(pLmdControl->iPort == PORT__STREAM) iReturn=f_stc_write(cRequest,12,pLmdControl->iTCP); iReturn=f_stc_read((int32_t *)pBuf,sizeof(sMbsBufferHeader),pLmdControl->iTCP,pLmdControl->iTcpTimeout); if(iReturn == STC__TIMEOUT) return(LMD__TIMEOUT); if(iReturn != STC__SUCCESS) return(LMD__FAILURE); if(pLmdControl->iSwap)fLmdSwap4((uint32_t *)pBuf,sizeof(sMbsBufferHeader)/4); if(leftBytes < (sizeof(sMbsBufferHeader)+2*pBuf->iUsedWords)){ printf("fLmdGetMbsBuffer: %s buffer size %d too small for %d bytes\n", pLmdControl->cFile,leftBytes,sizeof(sMbsBufferHeader)+2*pBuf->iMaxWords); return(LMD__FAILURE); } usedBytes=pBuf->iUsedWords*2; if((pBuf->iType&0xffff) == 100) iReturn=f_stc_read((int32_t *)(pBuf+1),usedBytes,pLmdControl->iTCP,-1); if(iReturn == STC__TIMEOUT) return(LMD__TIMEOUT); if(iReturn != STC__SUCCESS) return(LMD__FAILURE); if(pLmdControl->iSwap)fLmdSwap4((uint32_t *)(pBuf+1),usedBytes/4); if(iBytesUsed != NULL)*iBytesUsed =usedBytes+sizeof(sMbsBufferHeader); if(iElements != NULL)*iElements =pBuf->iElements; pLmdControl->iBytes += usedBytes; pLmdControl->iLeftWords = usedBytes/2; // without header pLmdControl->pMbsFileHeader = (sMbsFileHeader *)pBuf; return(LMD__SUCCESS); } #endif // endif FILEONLY //=============================================================== uint32_t fLmdGetOpen( sLmdControl *pLmdControl, char *Filename, sMbsFileHeader *pBuffHead, // LMD__INTERNAL_HEADER (NULL) or address of file header uint32_t iBytes, // LMD__NO_BUFFER (0) or LMD__MIN_BUFFER or internal buffersize uint32_t iUseOffset){ // LMD__[NO_]INDEX int32_t iReturn; uint32_t l=0,i,bufferBytes=0,h[12]; lmdoff_t to; memset(pLmdControl,0,sizeof(sLmdControl)); if(pBuffHead == LMD__INTERNAL_HEADER){ pLmdControl->pMbsFileHeader= (sMbsFileHeader *)malloc(sizeof(sMbsFileHeader)); pLmdControl->iInternHeader=1; } else { pLmdControl->pMbsFileHeader= pBuffHead; pLmdControl->iInternHeader=0; } memset(pLmdControl->pMbsFileHeader,0,sizeof(sMbsFileHeader)); // copy file name to control structure strcpy(pLmdControl->cFile,Filename); if((pLmdControl->fFile=(FILE *)fopen64(Filename,"r"))== NULL) { printf("fLmdGetOpen: File not found: %d\n",Filename); fLmdCleanup(pLmdControl); return(GETLMD__NOFILE); } /* read header */ iReturn=fLmdReadBuffer(pLmdControl, (char *)pLmdControl->pMbsFileHeader, sizeof(sMbsFileHeader)); if(iReturn!=sizeof(sMbsFileHeader)) { printf("fLmdGetOpen: LMD format error: no LMD file: %s\n",Filename); fLmdGetClose(pLmdControl); return(GETLMD__NOLMDFILE); } // check type and subtype, and endian if(pLmdControl->pMbsFileHeader->iEndian != 1) pLmdControl->iSwap=1; if(pLmdControl->iSwap){ printf("do swap !!!\n"); fLmdSwap4((uint32_t *)pLmdControl->pMbsFileHeader,sizeof(sMbsFileHeader)/4); fLmdSwap8((uint64_t *)&pLmdControl->pMbsFileHeader->iTableOffset,1); } if(pLmdControl->pMbsFileHeader->iType != LMD__TYPE_FILE_HEADER_101_1){ printf("fLmdGetOpen: LMD format error: no LMD file: %s, type is %0x\n", Filename,pLmdControl->pMbsFileHeader->iType); fLmdGetClose(pLmdControl); return(GETLMD__NOLMDFILE); } if((iUseOffset == LMD__INDEX)&&(pLmdControl->pMbsFileHeader->iTableOffset > 0)){ // printf("fLmdGetOpen: use table in file: %s\n",Filename); pLmdControl->iOffsetSize=pLmdControl->pMbsFileHeader->iOffsetSize; iReturn=fLmdOffsetRead(pLmdControl); // read offset table if(iReturn != LMD__SUCCESS){ printf("fLmdGetOpen: Index format error: %s\n",Filename); fLmdGetClose(pLmdControl); return(iReturn); } } pLmdControl->iBytes+=iReturn; // more of header? if(pLmdControl->pMbsFileHeader->iUsedWords > 0) { // Read this additional information without swapping. // Could be mostly strings. Caller must know. pLmdControl->cHeader=malloc(pLmdControl->pMbsFileHeader->iUsedWords*2); iReturn=fLmdReadBuffer(pLmdControl,pLmdControl->cHeader, pLmdControl->pMbsFileHeader->iUsedWords*2 ); if(iReturn!=pLmdControl->pMbsFileHeader->iUsedWords*2) { printf("fLmdGetOpen: LMD format error: no LMD file: %s\n",Filename); fLmdGetClose(pLmdControl); return(GETLMD__NOLMDFILE); } } bufferBytes=iBytes; if(bufferBytes < pLmdControl->pMbsFileHeader->iMaxWords*2) bufferBytes=pLmdControl->pMbsFileHeader->iMaxWords*2; fLmdPrintFileHeader(1,pLmdControl->pMbsFileHeader); pLmdControl->pBuffer=(int16_t *)malloc(bufferBytes); pLmdControl->iBufferWords=bufferBytes/2; // will be increased if necessary printf("fLmdGetOpen: %s words %u\n", Filename, pLmdControl->iBufferWords); pLmdControl->iLeftWords = 0; // buffer empty, read with first fLmdGetElement pLmdControl->pMbsHeader = NULL; return(LMD__SUCCESS); } //=============================================================== uint32_t fLmdGetBuffer( sLmdControl *pLmdControl, sMbsHeader *pMbsHeader, uint32_t iBytes, uint32_t *iElements, uint32_t *iBytesUsed){ sMbsHeader *pm; uint32_t *ps, *pd, i,ii, elem=0, size=0, leftBytes=0, used, elem_sz; int32_t iReturn; if(iBytes < pLmdControl->pMbsFileHeader->iMaxWords){ printf("fLmdGetBuffer: %s buffer size %d too small for %d bytes\n", pLmdControl->cFile,iBytes,pLmdControl->pMbsFileHeader->iMaxWords); return(LMD__FAILURE); } if(pMbsHeader == NULL){ printf("fLmdGetBuffer: Need buffer to read\n"); return(LMD__FAILURE); } *iBytesUsed=0; *iElements=0; if(pLmdControl->iElements == pLmdControl->pMbsFileHeader->iElements) return(GETLMD__EOFILE); // Offset table if(pLmdControl->iOffsetEntries){ // use offsets to read elements fitting in buffer fLmdOffsetElements(pLmdControl,iBytes, &elem, &used); //printf("Read %d bytes of %d, elements %d\n",used,iBytes,elem); iReturn=fLmdReadBuffer(pLmdControl,(char *)pMbsHeader,used); if(iReturn <= 0){ printf("fLmdGetBuffer: EOF: %s\n",pLmdControl->cFile); return(GETLMD__EOFILE); } if(iReturn!=used) { printf("fLmdGetBuffer: LMD read error: unexpected EOF: %s %u %u\n", pLmdControl->cFile, iReturn, used); return(GETLMD__NOLMDFILE); } *iBytesUsed=used; *iElements=elem; if(pLmdControl->iSwap)fLmdSwap4((uint32_t *)pMbsHeader,iReturn/4); pLmdControl->iBytes+=iReturn; return(LMD__SUCCESS); } // no offset table // do we have fragment stored? leftBytes = pLmdControl->iLeftWords*2; if(leftBytes>0) { if (leftBytes > iBytes) { printf("fLmdGetBuffer: stored piece of data (%u) larger than provided buffer (%u)\n", leftBytes, iBytes); return(LMD__FAILURE); } if (pLmdControl->pMbsHeader==0) { printf("fLmdGetBuffer: Internal error pMbsHeader==0\n"); return(LMD__FAILURE); } memcpy(pMbsHeader, pLmdControl->pMbsHeader, leftBytes); } iReturn = fLmdReadBuffer(pLmdControl,(char *)pMbsHeader+leftBytes, iBytes-leftBytes); if(iReturn <= 0) { printf("fLmdGetBuffer: EOF: %s\n",pLmdControl->cFile); if (leftBytes>0) printf("fLmdGetBuffer: EOF while we have some rest data (%u)\n", leftBytes); else return(GETLMD__EOFILE); } if(iReturn > (iBytes-leftBytes)) { printf("fLmdGetBuffer: LMD read error %s - too many bytes read %u wants %u", pLmdControl->cFile, iReturn, iBytes-leftBytes); return(GETLMD__NOLMDFILE); } if(pLmdControl->iSwap)fLmdSwap4((uint32_t *)pMbsHeader+leftBytes/4,iReturn/4); pLmdControl->iBytes += iReturn; leftBytes += iReturn; // thats what is in the buffer // step through buffer to get number of elements and size pm=pMbsHeader; while(leftBytes >=8){ if(pm->iType == LMD__TYPE_FILE_INDEX_101_2) break; // file index is last elem_sz = (pm->iWords+4)*2; if(elem_sz > leftBytes) break; // pm valid but incomplete data *iBytesUsed += elem_sz; *iElements += 1; pLmdControl->iElements++; pm = (sMbsHeader *)((char*)pm + elem_sz); leftBytes -= elem_sz; } //printf("Read %d bytes of %d, elements %d\n",*iBytesUsed,iBytes,*iElements); // fragment left? copy to internal buffer if(leftBytes>0){ if(leftBytes > pLmdControl->iBufferWords*2){ printf("fLmdGetBuffer: ERROR: internal buffer overflow. Needed:%d available:%d\n", leftBytes,pLmdControl->iBufferWords*2); return(LMD__FAILURE); } else { memcpy(pLmdControl->pBuffer,pm,leftBytes); } } pLmdControl->iLeftWords = leftBytes/2; if (pLmdControl->iLeftWords>0) pLmdControl->pMbsHeader = (sMbsHeader*)pLmdControl->pBuffer; else pLmdControl->pMbsHeader = 0; return(LMD__SUCCESS); } //=============================================================== uint32_t fLmdGetElement(sLmdControl *pLmdControl, uint32_t iEvent, sMbsHeader **event){ sMbsHeader *pM; uint32_t *ps, *pd, i, evsz; int32_t iReturn; *event=NULL; if(iEvent == LMD__NO_INDEX) { if(pLmdControl->pBuffer==NULL) return(GETLMD__NOBUFFER); // internal buffer needed if(pLmdControl->pMbsFileHeader->iElements==0) return(GETLMD__NOMORE); // check if we need to read extra data if ((pLmdControl->iLeftWords < 4) || (pLmdControl->pMbsHeader == 0) || (pLmdControl->pMbsHeader->iWords+4 > pLmdControl->iLeftWords)) { // first copy old data, if it exists if (pLmdControl->iLeftWords > 0) { memmove(pLmdControl->pBuffer, pLmdControl->pMbsHeader, pLmdControl->iLeftWords*2); // printf("copy to the begin rest %u bytes", pLmdControl->iLeftWords*2); } // second, try to read more bytes iReturn = fLmdReadBuffer(pLmdControl, (char *)(pLmdControl->pBuffer+pLmdControl->iLeftWords), (pLmdControl->iBufferWords-pLmdControl->iLeftWords)*2); if(iReturn <= 0) { printf("fLmdGetElement: EOF\n"); return(GETLMD__EOFILE); } if(pLmdControl->iSwap) fLmdSwap4((uint32_t *)(pLmdControl->pBuffer+pLmdControl->iLeftWords),iReturn/4); pLmdControl->iBytes += iReturn; pLmdControl->pMbsHeader=(sMbsHeader *)pLmdControl->pBuffer; pLmdControl->iLeftWords += iReturn/2; } // check if read buffer enough for event evsz = (pLmdControl->pMbsHeader->iWords + 4) * 2; if (evsz > pLmdControl->iLeftWords*2) { printf ("fLmdGetElement: Error, full element %u does not fit in buffer %u", evsz, pLmdControl->iLeftWords*2); return (GETLMD__TOOBIG); } pLmdControl->pMbsFileHeader->iElements--; pM = pLmdControl->pMbsHeader; pLmdControl->pMbsHeader = (sMbsHeader *) ((char*) pM + evsz); pLmdControl->iLeftWords -= evsz/2; pLmdControl->iElements++; *event=pM; return(LMD__SUCCESS); } // get indexed event if(pLmdControl->iOffsetEntries){ if(iEvent >= pLmdControl->iOffsetEntries)return(GETLMD__OUTOF_RANGE); fseeko64(pLmdControl->fFile,fLmdOffsetGet(pLmdControl,iEvent-1)*4,SEEK_SET); i=(fLmdOffsetGet(pLmdControl,iEvent)-fLmdOffsetGet(pLmdControl,iEvent-1)); iReturn=fLmdReadBuffer(pLmdControl,(char *)pLmdControl->pBuffer,i*4); if(iReturn <= 0) {printf("fLmdGetElement: EOF\n");return(GETLMD__EOFILE);} if(iReturn!=(i*4)) { printf("fLmdGetBuffer: LMD read error: unexpected EOF: %s\n",pLmdControl->cFile); return(GETLMD__EOFILE); } if(pLmdControl->iSwap)fLmdSwap4((uint32_t *)pLmdControl->pBuffer,iReturn/4); pLmdControl->pMbsHeader=(sMbsHeader *)pLmdControl->pBuffer; if((pLmdControl->pMbsHeader->iWords+4) != i*2){ printf("fLmdGetElement: Error Event %d: size from table is %d, header %d\n", iEvent,i/2,pLmdControl->pMbsHeader->iWords+4); return(GETLMD__SIZE_ERROR); } pLmdControl->iBytes+=iReturn; *event=pLmdControl->pMbsHeader; return(LMD__SUCCESS); } else return(GETLMD__NOMORE); // return zero if no more events } //=============================================================== uint32_t fLmdGetClose(sLmdControl *pLmdControl){ fLmdCleanup(pLmdControl); // cleanup except fFile if(fclose(pLmdControl->fFile)!=0) { pLmdControl->fFile=NULL; return(LMD__CLOSE_ERR); } pLmdControl->fFile=NULL; return(LMD__SUCCESS); } //=============================================================== int32_t fLmdReadBuffer(sLmdControl *pLmdControl, char *buffer, uint32_t bytes){ int32_t IObytes; IObytes=(int32_t)fread(buffer,1,bytes,pLmdControl->fFile); //if(IObytes < bytes) printf("Read %s: request %d bytes, got %d\n",pLmdControl->cFile,bytes,IObytes); return(IObytes); } //=============================================================== int32_t fLmdWriteBuffer(sLmdControl *pLmdControl, char *buffer, uint32_t bytes){ int32_t IObytes; IObytes=(int32_t)fwrite(buffer,1,bytes,pLmdControl->fFile); //if(IObytes < bytes) printf("Write %s: request %d bytes, put %d\n", // pLmdControl->cFile,bytes,IObytes); return(IObytes); } //=============================================================== uint64_t fLmdGetBytesWritten(sLmdControl *pLmdControl){ uint64_t bytes; bytes=pLmdControl->iBytes; // add pending data size in current buffer if(pLmdControl->iBufferWords > pLmdControl->iLeftWords) bytes += (pLmdControl->iBufferWords - pLmdControl->iLeftWords)*2; // add table size which will be written at close if ((pLmdControl->pOffset4!=NULL)||(pLmdControl->pOffset8!=NULL)) bytes += (pLmdControl->iElements+1)*pLmdControl->iOffsetSize; return(bytes); } //=============================================================== uint32_t fLmdCleanup(sLmdControl *pLmdControl){ // do not clean fFile if(pLmdControl->pTCP != NULL)free(pLmdControl->pTCP); if(pLmdControl->cHeader != NULL)free(pLmdControl->cHeader); if(pLmdControl->pOffset4 != NULL)free(pLmdControl->pOffset4); if(pLmdControl->pOffset8 != NULL)free(pLmdControl->pOffset8); if(pLmdControl->pBuffer != NULL && pLmdControl->iInternBuffer) free(pLmdControl->pBuffer); if(pLmdControl->pMbsFileHeader != NULL && pLmdControl->iInternHeader) free(pLmdControl->pMbsFileHeader); pLmdControl->pTCP=NULL; pLmdControl->cHeader=NULL; pLmdControl->pBuffer=NULL; pLmdControl->pOffset4=NULL; pLmdControl->pOffset8=NULL; pLmdControl->pMbsFileHeader=NULL; pLmdControl->pMbsHeader=NULL; return (LMD__SUCCESS); } //=============================================================== // can be called after GetOpen or ConnectMbs uint32_t fLmdGetSwap(sLmdControl *pLmdControl){ if(pLmdControl != NULL) return(pLmdControl->iSwap); else return(-1); } //=============================================================== // can be called after PutOpen or before PutClose void fLmdSetWrittenEndian(sLmdControl *pLmdControl,uint32_t iE){ if(pLmdControl->pMbsFileHeader != NULL) pLmdControl->pMbsFileHeader->iWrittenEndian=iE; else printf("fLmdSetWrittenEndian: No file header allocated!"); } //=============================================================== // can be called after GetOpen or GetMbsEvent uint32_t fLmdGetWrittenEndian(sLmdControl *pLmdControl){ if(pLmdControl->pMbsFileHeader != NULL) return(pLmdControl->pMbsFileHeader->iWrittenEndian); else printf("fLmdGetWrittenEndian: No file header allocated!"); return(LMD__ENDIAN_UNKNOWN); } //=============================================================== sLmdControl * fLmdAllocateControl(){ sLmdControl *x; x=(sLmdControl *)malloc(sizeof(sLmdControl)); memset(x,0,sizeof(sLmdControl)); return(x); } //=============================================================== void fLmdOffsetElements(sLmdControl *pLmdControl, uint32_t bytes, uint32_t *elements, uint32_t *used){ lmdoff_t *off1,*off2; uint32_t elem=0,i,*iff1,*iff2; if(pLmdControl->iOffsetSize == 4){ iff1=pLmdControl->pOffset4+pLmdControl->iElements; iff2=iff1; for(i=pLmdControl->iElements;iiOffsetEntries-1;i++){ if((*(iff1+1)-*iff2)>bytes/4) break; iff1++; elem++; pLmdControl->iElements++; } *used=(*iff1-*iff2)*4; *elements=elem; } else if(pLmdControl->iOffsetSize == 8){ off1=pLmdControl->pOffset8+pLmdControl->iElements; off2=off1; for(i=pLmdControl->iElements;iiOffsetEntries-1;i++){ if((*(off1+1)-*off2)>bytes/4) break; off1++; elem++; pLmdControl->iElements++; } *used=(*off1-*off2)*4; *elements=elem; } } //=============================================================== uint32_t fLmdOffsetRead(sLmdControl *pLmdControl) { int32_t iReturn; sMbsHeader *pTableHead; pTableHead=(sMbsHeader *)malloc(16); // header with 8 bytes data for future use. fseeko64(pLmdControl->fFile,(lmdoff_t)pLmdControl->pMbsFileHeader->iTableOffset*4,SEEK_SET); iReturn=fLmdReadBuffer(pLmdControl, (char *)pTableHead,16); if(iReturn!=16) { printf("fLmdGetBuffer: LMD read error: unexpected EOF: %s\n",pLmdControl->cFile); free(pTableHead); return(GETLMD__NOLMDFILE); } if(pLmdControl->iSwap)fLmdSwap4((uint32_t *)pTableHead,4); if(pTableHead->iType != LMD__TYPE_FILE_INDEX_101_2){ printf("fLmdOffsetTable: LMD format error: no index table: %s, type %0x\n", pLmdControl->cFile,pTableHead->iType); free(pTableHead); return(GETLMD__NOLMDFILE); } //printf("Table: words:%d type:%08x\n",pTableHead->iWords,pTableHead->iType); free(pTableHead); pLmdControl->iOffsetEntries=pLmdControl->pMbsFileHeader->iElements+1; pLmdControl->pOffset8=(lmdoff_t *)malloc(pLmdControl->iOffsetEntries*pLmdControl->iOffsetSize); iReturn=fLmdReadBuffer(pLmdControl, (char *)pLmdControl->pOffset8, pLmdControl->iOffsetEntries*pLmdControl->iOffsetSize); if(iReturn!=pLmdControl->iOffsetEntries*pLmdControl->iOffsetSize) { printf("fLmdOffsetTable: LMD format error: no index table: %s\n",pLmdControl->cFile); pLmdControl->iOffsetEntries=0; free(pTableHead); return(GETLMD__NOLMDFILE); } if(pLmdControl->iSwap){ fLmdSwap4((uint32_t *)pLmdControl->pOffset8,iReturn/4); if(pLmdControl->iOffsetSize == 8) fLmdSwap8((uint64_t *)pLmdControl->pOffset8,iReturn/8); } // go back behing header fseeko64(pLmdControl->fFile,(lmdoff_t)sizeof(sMbsFileHeader),SEEK_SET); // use small table if(pLmdControl->iOffsetSize == 4){ pLmdControl->pOffset4= (uint32_t *)pLmdControl->pOffset8; pLmdControl->pOffset8=NULL; } return(LMD__SUCCESS); } //=============================================================== uint32_t fLmdOffsetWrite(sLmdControl *pLmdControl) { int32_t iReturn; char *pbuf; lmdoff_t current; sMbsHeader *pTableHead; pTableHead=(sMbsHeader *)malloc(16); // header with 8 bytes data for future use. memset(pTableHead,0,16); pTableHead->iWords=(pLmdControl->iElements+1)*pLmdControl->iOffsetSize/2+4; pTableHead->iType=LMD__TYPE_FILE_INDEX_101_2; /* printf("Table: words:%d type:%08x offbytes:%d\n", */ /* pTableHead->iWords,pTableHead->iType,pLmdControl->iOffsetSize); */ iReturn=fgetpos64(pLmdControl->fFile,(fpos64_t *) ¤t); iReturn=fLmdWriteBuffer(pLmdControl, (char *)pTableHead,16); free(pTableHead); pbuf=(char *)pLmdControl->pOffset4; // try short table if(pbuf == NULL) pbuf=(char *)pLmdControl->pOffset8; iReturn=fLmdWriteBuffer(pLmdControl, pbuf, (pLmdControl->iElements+1)*pLmdControl->iOffsetSize); if(pLmdControl->pOffset8) pLmdControl->pMbsFileHeader->iTableOffset = *(pLmdControl->pOffset8+pLmdControl->iElements); if(pLmdControl->pOffset4) pLmdControl->pMbsFileHeader->iTableOffset = *(pLmdControl->pOffset4+pLmdControl->iElements); if(current/4 != pLmdControl->pMbsFileHeader->iTableOffset){ printf("Table offset mismatch: current:%lld calculated:%lld, cur-cal %lld\n", current/4,pLmdControl->pMbsFileHeader->iTableOffset, current/4-pLmdControl->pMbsFileHeader->iTableOffset); return(LMD__FAILURE); } if(iReturn != (pLmdControl->iElements+1)*pLmdControl->iOffsetSize){ printf("Table write error \n"); return(LMD__FAILURE); } return(LMD__SUCCESS); } //=============================================================== uint32_t fLmdOffsetSet(sLmdControl *pLmdControl, uint32_t lwords) { int32_t iReturn; if(pLmdControl->iElements >= pLmdControl->iOffsetEntries)fLmdOffsetResize(pLmdControl,0); if(pLmdControl->pOffset8){ *(pLmdControl->pOffset8+pLmdControl->iElements)= *(pLmdControl->pOffset8+pLmdControl->iElements-1)+(lmdoff_t)lwords; } if(pLmdControl->pOffset4){ *(pLmdControl->pOffset4+pLmdControl->iElements)= *(pLmdControl->pOffset4+pLmdControl->iElements-1)+lwords; } return(LMD__SUCCESS); } //=============================================================== lmdoff_t fLmdOffsetGet(sLmdControl *pLmdControl, uint32_t index){ if(pLmdControl->pOffset8) return(*(pLmdControl->pOffset8+index)); if(pLmdControl->pOffset4) return((lmdoff_t)*(pLmdControl->pOffset4+index)); return 0; } //=============================================================== void fLmdOffsetResize(sLmdControl *pLmdControl, uint32_t firstValue){ lmdoff_t *new; uint32_t oldEntries,newEntries; oldEntries=pLmdControl->iOffsetEntries; newEntries=oldEntries+OFFSET__ENTRIES; new=(lmdoff_t *)malloc(newEntries*pLmdControl->iOffsetSize); memset(new,0,newEntries*pLmdControl->iOffsetSize); if(oldEntries > 0){ //table was expanded //printf("Resize table %d to %d entries\n",oldEntries,newEntries); if(pLmdControl->pOffset8){ memcpy(new,pLmdControl->pOffset8,oldEntries*pLmdControl->iOffsetSize); free(pLmdControl->pOffset8); pLmdControl->pOffset8=new; } if(pLmdControl->pOffset4){ memcpy(new,pLmdControl->pOffset4,oldEntries*pLmdControl->iOffsetSize); free(pLmdControl->pOffset4); pLmdControl->pOffset4=(uint32_t *)new; } } else { // table was new //printf("Create table %d entries, first offset %d\n",newEntries,firstValue); if(pLmdControl->iOffsetSize==8){ pLmdControl->pOffset8=new; *pLmdControl->pOffset8=(lmdoff_t)firstValue; } if(pLmdControl->iOffsetSize==4){ pLmdControl->pOffset4=(uint32_t *)new; *pLmdControl->pOffset4=firstValue; } } pLmdControl->iOffsetEntries=newEntries; } //=============================================================== void fLmdPrintBufferHeader(uint32_t iVerbose, sMbsBufferHeader *pMbsBufferHeader) { if(iVerbose){ if(pMbsBufferHeader){ printf("BfHd: # %d, DataWords:%d Type:%08x Elements:%d sec:%d.%d MaxWords:%d\n", pMbsBufferHeader->iBuffer, pMbsBufferHeader->iUsedWords, pMbsBufferHeader->iType, pMbsBufferHeader->iElements, pMbsBufferHeader->iTimeSpecSec, pMbsBufferHeader->iTimeSpecNanoSec/1000, pMbsBufferHeader->iMaxWords); }}} //=============================================================== void fLmdPrintFileHeader(uint32_t iVerbose, sMbsFileHeader *pMbsFileHeader) { if(iVerbose){ if(pMbsFileHeader){ printf("FiHd: DataWords:%d Type:%d.%d Elements:%d sec:%d.%d MaxWords:%d Index: %llx[%d]\n", pMbsFileHeader->iUsedWords, pMbsFileHeader->iType&0xffff, pMbsFileHeader->iType>>16, pMbsFileHeader->iElements, pMbsFileHeader->iTimeSpecSec, pMbsFileHeader->iTimeSpecNanoSec/1000, pMbsFileHeader->iMaxWords, pMbsFileHeader->iTableOffset, pMbsFileHeader->iOffsetSize); }}} //=============================================================== void fLmdPrintHeader(uint32_t iVerbose, sMbsHeader *pMbsHeader) { if(iVerbose){ if(pMbsHeader){ printf("ElHd: words:%d type:%08x\n", pMbsHeader->iWords, pMbsHeader->iType); }}} //=============================================================== void fLmdPrintEvent(uint32_t iVerbose, sMbsEventHeader *pMbsEventHeader) { if(iVerbose){ if(pMbsEventHeader){ printf("EvHd: words:%6d type:%08x trigger:%2d #:%4d\n", pMbsEventHeader->iWords, pMbsEventHeader->iType, pMbsEventHeader->iTrigger>>16, pMbsEventHeader->iEventNumber); }}} //=============================================================== void fLmdPrintControl(uint32_t iVerbose, sLmdControl *pLmdControl) { if(iVerbose){ printf("Ctrl: file:%s words:%d left:%d bytes read:%lld elements:%d\n", pLmdControl->cFile, pLmdControl->iBufferWords, pLmdControl->iLeftWords, pLmdControl->iBytes, pLmdControl->iElements ); fLmdPrintFileHeader(iVerbose,pLmdControl->pMbsFileHeader); fLmdPrintEvent(iVerbose,(sMbsEventHeader *)pLmdControl->pMbsHeader); }} //=============================================================== void fLmdSwap4(uint32_t *array, uint32_t items){ uint32_t i, *pp; pp=array; for(i=0;i> 24) + ((*pp >> 8)&0x0000ff00) + ((*pp << 8)&0x00ff0000) + (*pp << 24); //printf("to %08x \n",*pp); pp++; }} //=============================================================== void fLmdSwap8(uint64_t *array, uint32_t items){ uint64_t *pp; uint32_t i,x; pp=array; for(i=0;i> 32); //printf("to %016llx\n",*pp,*(pp+1)); pp++; }}