FairRoot
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
fLmd.c
Go to the documentation of this file.
1 /********************************************************************************
2  * Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
3  * *
4  * This software is distributed under the terms of the *
5  * GNU Lesser General Public Licence (LGPL) version 3, *
6  * copied verbatim in the file "LICENSE" *
7  ********************************************************************************/
8 #include <fcntl.h>
9 #include <memory.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <sys/stat.h>
13 #include <sys/types.h>
14 #include <time.h>
15 
16 #ifdef Lynx /* LynxOS */
17 #include <pwd.h>
18 #include <timeb.h>
19 #include <unistd.h>
20 #endif
21 
22 #ifdef Linux /* Linux */
23 #include <pwd.h>
24 #include <sys/timeb.h>
25 #include <unistd.h>
26 #endif
27 
28 #ifdef Solaris /* Solaris */
29 #include <pwd.h>
30 #include <sys/timeb.h>
31 #include <unistd.h>
32 #endif
33 
34 #ifdef Darwin /* Max OS X */
35 #include <pwd.h>
36 #include <sys/timeb.h>
37 #include <unistd.h>
38 #define fgetpos64 fgetpos
39 #define fopen64 fopen
40 #define fseeko64 fseek
41 #define fpos64_t fpos_t
42 
43 #ifndef _HAS_CLOCK_REALTIME
44 /* just some dummies for compilation, we will never write lmd with time header in go4*/
45 #define CLOCK_REALTIME 1
46 int clock_gettime(int clockid, struct timespec* tp) { return 0; }
47 #endif
48 #endif
49 
50 #ifdef WIN32
51 #include <WTypes.h>
52 #include <wchar.h>
53 
54 #define fgetpos64 fgetpos
55 #define fopen64 fopen
56 #define fseeko64 fseek
57 #define fpos64_t fpos_t
58 
59 struct timespec
60 {
61  long tv_sec; /* seconds */
62  long tv_nsec; /* nanoseconds */
63 };
64 
65 #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
66 #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
67 #else
68 #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
69 #endif
70 
71 #define CLOCK_REALTIME 1
72 
73 int clock_gettime(int clockid, struct timespec* tp)
74 {
75  FILETIME ft;
76  unsigned __int64 tmpres = 0;
77 
78  tp->tv_sec = 0;
79  tp->tv_nsec = 0;
80 
81  GetSystemTimeAsFileTime(&ft);
82 
83  tmpres |= ft.dwHighDateTime;
84  tmpres <<= 32;
85  tmpres |= ft.dwLowDateTime;
86 
87  /*converting file time to unix epoch*/
88  tmpres /= 10; /*convert into microseconds*/
89  tmpres -= DELTA_EPOCH_IN_MICROSECS;
90  tp->tv_sec = (long)(tmpres / 1000000UL);
91  tp->tv_nsec = (long)(tmpres % 1000000UL) * 1000;
92 
93  return 0;
94 }
95 #endif
96 
97 #include "fLmd.h"
98 
99 int32_t fLmdWriteBuffer(sLmdControl*, char*, uint32_t);
107 #define OFFSET__ENTRIES 250000
108 
109 //===============================================================
111  char* Filename,
112  sMbsFileHeader* pBuffHead, // LMD__STANDARD_HEADER (NULL) or address
113  uint32_t iBytes, // LMD__NO_BUFFER (0) or buffer size
114  uint32_t iOver, // LMD__[NO_]OVERWRITE
115  uint32_t iUseOffset, // LMD__[NO_]INDEX
116  uint32_t iLargeFile) // LMD__[NO_]LARGE_FILE
117 {
118 
119  int32_t iReturn;
120  struct timespec clock;
121 
122  memset(pLmdControl, 0, sizeof(sLmdControl));
123 
124  // allocate header or take extern
125  if (pBuffHead == LMD__STANDARD_HEADER) {
126  pLmdControl->pMbsFileHeader = (sMbsFileHeader*)malloc(sizeof(sMbsFileHeader));
127  memset(pLmdControl->pMbsFileHeader, 0, sizeof(sMbsFileHeader));
128  pLmdControl->iInternHeader = 1;
129  } else {
130  pLmdControl->pMbsFileHeader = pBuffHead;
131  pLmdControl->iInternHeader = 0;
132  }
133 
134  clock_gettime(CLOCK_REALTIME, &clock);
135  pLmdControl->pMbsFileHeader->iTimeSpecSec = clock.tv_sec;
136  pLmdControl->pMbsFileHeader->iTimeSpecNanoSec = clock.tv_nsec;
137 
139  pLmdControl->pMbsFileHeader->iEndian = 1;
140  size_t len = strlen(Filename);
141  if (len < sizeof(pLmdControl->cFile)) {
142  strncpy(pLmdControl->cFile, Filename, len);
143  } else {
144  strncpy(pLmdControl->cFile, Filename, sizeof(pLmdControl->cFile) - 1);
145  }
146  // optionally allocate buffer
147  if (iBytes > 0) {
148  pLmdControl->pBuffer = (int16_t*)malloc(iBytes);
149  pLmdControl->iInternBuffer = 1;
150  }
151  pLmdControl->iBufferWords = iBytes / 2;
152  pLmdControl->iLeftWords = iBytes / 2;
153  // open file
154  if (iOver == LMD__NO_OVERWRITE) { // do not overwrite
155  if ((pLmdControl->fFile = (FILE*)fopen64(Filename, "r")) != NULL) {
156  printf("fLmdPutOpen: File exists: %s\n", Filename);
157  fLmdCleanup(pLmdControl);
158  fclose(pLmdControl->fFile);
159  return (PUTLMD__FILE_EXIST);
160  }
161  }
162 
163  if ((pLmdControl->fFile = (FILE*)fopen64(Filename, "w+")) == NULL) {
164  printf("fLmdPutOpen: Error open file %s\n", Filename);
165  fLmdCleanup(pLmdControl);
166  return (PUTLMD__OPEN_ERR);
167  }
168 
169  if (iLargeFile == LMD__LARGE_FILE) {
170  pLmdControl->iOffsetSize = 8;
171  } else {
172  pLmdControl->iOffsetSize = 4;
173  }
174  pLmdControl->pMbsFileHeader->iOffsetSize = pLmdControl->iOffsetSize;
175 
176  // write header
177  iReturn = fLmdWriteBuffer(pLmdControl,
178  (char*)pLmdControl->pMbsFileHeader,
179  (pLmdControl->pMbsFileHeader->iUsedWords) * 2 + sizeof(sMbsFileHeader));
180  pLmdControl->iBytes += iReturn;
181 
182  if (iUseOffset == LMD__INDEX) {
183  fLmdOffsetResize(pLmdControl, iReturn / 4);
184  } // create and set first value
185  printf("fLmdPutOpen: %s. Bytes:%d over:%d table:%d large:%d.\n", Filename, iBytes, iOver, iUseOffset, iLargeFile);
186  return (LMD__SUCCESS);
187 }
188 
189 //===============================================================
191 {
192  uint32_t *ps, *pd, i, elements;
193  int64_t fileleft, used;
194  int32_t iReturn;
195 
196  // enough space left?
197  if (pLmdControl->iOffsetEntries && (pLmdControl->iOffsetSize == 4)) {
198  elements = pLmdControl->iElements + 2;
199  used = pLmdControl->iBytes / 4;
200  fileleft = 0xffffffff - used - (4 + elements); // size of table
201  if ((int64_t)(pHeader->iWords / 2 + 2) > fileleft) {
202  printf("fLmdPutElement: File size exceed\n");
203  return (PUTLMD__EXCEED);
204  }
205  }
206  // save largest size in header
207  if ((pHeader->iWords + 4) > pLmdControl->pMbsFileHeader->iMaxWords) {
208  pLmdControl->pMbsFileHeader->iMaxWords = pHeader->iWords + 4;
209  }
210  // no buffer, write element directly
211  if (pLmdControl->iBufferWords == 0) {
212  pLmdControl->pMbsHeader = pHeader;
213  iReturn = fLmdWriteBuffer(pLmdControl, (char*)pHeader, (pHeader->iWords + 4) * 2);
214  pLmdControl->iBytes += iReturn;
215  if (iReturn != (pHeader->iWords + 4) * 2) {
216  printf("fLmdPutElement: Write error \n");
217  return (LMD__FAILURE);
218  }
219  pLmdControl->pMbsFileHeader->iElements++;
220  pLmdControl->iElements++;
221  if (pLmdControl->iOffsetEntries) {
222  fLmdOffsetSet(pLmdControl, iReturn / 4);
223  }
224  return (LMD__SUCCESS);
225 
226  } // end no buffer
227  if ((pHeader->iWords + 4) > pLmdControl->iLeftWords) { // flash buffer to file
228  iReturn = fLmdWriteBuffer(
229  pLmdControl, (char*)pLmdControl->pBuffer, (pLmdControl->iBufferWords - pLmdControl->iLeftWords) * 2);
230  pLmdControl->iBytes += iReturn;
231  if (iReturn != (pLmdControl->iBufferWords - pLmdControl->iLeftWords) * 2) {
232  return (LMD__FAILURE);
233  }
234  pLmdControl->iLeftWords = pLmdControl->iBufferWords; // buffer free
235  }
236  if ((pHeader->iWords + 4) > pLmdControl->iLeftWords) { // element too big for buffer
237  printf("fLmdPutElement: Element too big: %d words\n", pHeader->iWords + 4);
238  return (PUTLMD__TOOBIG);
239  }
240  // copy to buffer
241  ps = (uint32_t*)pHeader;
242  pd = (uint32_t*)pLmdControl->pBuffer + (pLmdControl->iBufferWords - pLmdControl->iLeftWords) / 2;
243  iReturn = (pHeader->iWords + 4) / 2; // here 32b words
244  for (i = 0; i < iReturn; i++) {
245  *pd++ = *ps++;
246  }
247  pLmdControl->pMbsFileHeader->iElements++;
248  pLmdControl->iElements++;
249  pLmdControl->iLeftWords -= (pHeader->iWords + 4);
250  if (pLmdControl->iOffsetEntries) {
251  fLmdOffsetSet(pLmdControl, iReturn);
252  }
253  return (LMD__SUCCESS);
254 }
255 
256 //===============================================================
257 uint32_t fLmdPutBuffer(sLmdControl* pLmdControl, sMbsHeader* pHeader, uint32_t Items)
258 {
259 
260  sMbsHeader* pH;
261  uint32_t Bytes = 0, TotalBytes = 0, i, elements;
262  int64_t fileleft, used;
263  int32_t iReturn;
264 
265  // check if total buffer fits in file
266  if (pLmdControl->iOffsetEntries && (pLmdControl->iOffsetSize == 4)) {
267  pH = pHeader; // SL 16.11.2009 - pH was not initialized in this branch
268  elements = pLmdControl->iElements + Items + 2;
269  used = pLmdControl->iBytes / 4;
270  fileleft = 0xffffffff - used - (4 + elements); // size of table
271  for (i = 0; i < Items; i++) {
272  Bytes = (4 + pH->iWords) * 2;
273  TotalBytes += Bytes;
274  pH = (sMbsHeader*)((int16_t*)pH + Bytes / 2);
275  }
276  if ((int64_t)TotalBytes / 4 > fileleft) {
277  printf("fLmdPutElement: File size exceed\n");
278  return (PUTLMD__EXCEED);
279  }
280  Bytes = 0;
281  TotalBytes = 0;
282  }
283  pH = pHeader;
284  for (i = 0; i < Items; i++) {
285  pLmdControl->iElements++;
286  Bytes = (4 + pH->iWords) * 2;
287  TotalBytes += Bytes;
288  if (pLmdControl->iOffsetEntries) {
289  fLmdOffsetSet(pLmdControl, Bytes / 4);
290  }
291  if ((pH->iWords + 4) > pLmdControl->pMbsFileHeader->iMaxWords) {
292  pLmdControl->pMbsFileHeader->iMaxWords = pH->iWords + 4;
293  }
294  pH = (sMbsHeader*)((int16_t*)pH + Bytes / 2);
295  }
296  iReturn = fLmdWriteBuffer(pLmdControl, (char*)pHeader, TotalBytes);
297  pLmdControl->iBytes += iReturn;
298  if (iReturn != TotalBytes) {
299  return (LMD__FAILURE);
300  } else {
301  pLmdControl->pMbsFileHeader->iElements += Items;
302  return (LMD__SUCCESS);
303  }
304 }
305 
306 //===============================================================
308 {
309  int32_t iReturn; //,i;
310  // lmdoff_t current,c;
311 
312  if (pLmdControl->iBufferWords > pLmdControl->iLeftWords) { // write last buffer
313  iReturn = fLmdWriteBuffer(
314  pLmdControl, (char*)pLmdControl->pBuffer, (pLmdControl->iBufferWords - pLmdControl->iLeftWords) * 2);
315  pLmdControl->iBytes += iReturn;
316  if (iReturn != (pLmdControl->iBufferWords - pLmdControl->iLeftWords) * 2) {
317  printf("fLmdPutClose: Error writing last buffer. Closing file.\n");
318  // rewind file and rewrite header
319  rewind(pLmdControl->fFile); /* rewind file, rewrite header */
320  fLmdWriteBuffer(pLmdControl, (char*)pLmdControl->pMbsFileHeader, sizeof(sMbsFileHeader));
321  fLmdCleanup(pLmdControl);
322  return (LMD__FAILURE);
323  }
324  }
325  if (pLmdControl->iOffsetEntries)
326  if (fLmdOffsetWrite(pLmdControl) != LMD__SUCCESS) {
327  pLmdControl->pMbsFileHeader->iTableOffset = 0; // table could not be written
328  }
329 
330  // rewind file and rewrite header
331  rewind(pLmdControl->fFile); /* rewind file, rewrite header */
332  fLmdWriteBuffer(pLmdControl, (char*)pLmdControl->pMbsFileHeader, sizeof(sMbsFileHeader));
333  return (fLmdGetClose(pLmdControl));
334 }
335 
336 #ifndef FILEONLY
337 //===============================================================
339  char* Nodename,
340  uint32_t iPort,
341  uint32_t* iBufferBytes) // LMD__GET_EVENTS (NULL) or address to return buffer size
342 {
343 
344  int32_t stat;
345  sMbsTransportInfo sMbs;
346 
347  if (iPort == 0) {
348  pLmdControl->iPort = PORT__TRANS;
349  } else {
350  pLmdControl->iPort = iPort;
351  }
352  memset(pLmdControl, 0, sizeof(sLmdControl));
353  pLmdControl->pTCP = (struct s_tcpcomm*)malloc(sizeof(struct s_tcpcomm));
354  pLmdControl->iTCPowner = 1;
355  if (pLmdControl->iPort == PORT__TRANS) {
356  printf("fLmdConnectMbs: Connect to transport server %s port %d\n", Nodename, pLmdControl->iPort);
357  }
358  if (pLmdControl->iPort == PORT__STREAM) {
359  printf("fLmdConnectMbs: Connect to stream server %s port %d\n", Nodename, pLmdControl->iPort);
360  }
361  stat = f_stc_connectserver(Nodename, pLmdControl->iPort, &pLmdControl->iTCP, pLmdControl->pTCP);
362  if (stat != STC__SUCCESS) {
363  printf("fLmdConnectMbs: Error connect to %s \n", Nodename);
364  fLmdCleanup(pLmdControl);
365  return (LMD__FAILURE);
366  }
367  stat = f_stc_read((int32_t*)&sMbs, sizeof(sMbsTransportInfo), pLmdControl->iTCP, 3);
368  if (stat != STC__SUCCESS) {
369  printf("fLmdConnectMbs: Error read info from %s \n", Nodename);
370  fLmdCleanup(pLmdControl);
371  return (LMD__FAILURE);
372  }
373  if (sMbs.iEndian != 1) {
374  pLmdControl->iSwap = 1;
375  }
376  if (pLmdControl->iSwap) {
377  fLmdSwap4((uint32_t*)&sMbs, sizeof(sMbsTransportInfo) / 4);
378  }
379  if (sMbs.iBuffers > 1) {
380  printf("fLmdConnectMbs: Event spanning not supported!\n");
381  fLmdCleanup(pLmdControl);
382  return (LMD__FAILURE);
383  }
384  if (sMbs.iStreams > 0) {
385  printf("fLmdConnectMbs: MBS not in DABC mode!\n");
386  fLmdCleanup(pLmdControl);
387  return (LMD__FAILURE);
388  }
389  size_t len = strlen(Nodename);
390  if (len < sizeof(pLmdControl->cFile)) {
391  strncpy(pLmdControl->cFile, Nodename, len);
392  } else {
393  strncpy(pLmdControl->cFile, Nodename, sizeof(pLmdControl->cFile) - 1);
394  }
395  if (iBufferBytes == LMD__GET_EVENTS) { // use internal buffer for fLmdGetMbsEvent
396  pLmdControl->pBuffer = (int16_t*)malloc(sMbs.iMaxBytes);
397  pLmdControl->iBufferWords = sMbs.iMaxBytes / 2;
398  pLmdControl->iInternBuffer = 1;
399  } else {
400  *iBufferBytes = sMbs.iMaxBytes;
401  }
402  return (LMD__SUCCESS);
403 }
404 //===============================================================
406  char* Nodename,
407  uint32_t iMaxBytes,
408  uint32_t iBuffers,
409  uint32_t iStreams,
410  uint32_t iPort,
411  uint32_t iTimeout)
412 {
413 
414  // int32_t stat;
415 
416  if (iBuffers > 1) {
417  printf("fLmdInitMbs: Event spanning not supported!\n");
418  return (LMD__FAILURE);
419  }
420  if (iStreams > 0) {
421  printf("fLmdInitMbs: MBS not in DABC mode!\n");
422  return (LMD__FAILURE);
423  }
424  pLmdControl->iPort = iPort;
425  size_t len = strlen(Nodename);
426  if (len < sizeof(pLmdControl->cFile)) {
427  strncpy(pLmdControl->cFile, Nodename, len);
428  } else {
429  strncpy(pLmdControl->cFile, Nodename, sizeof(pLmdControl->cFile) - 1);
430  }
431  if (pLmdControl->pBuffer == NULL) {
432  pLmdControl->pBuffer = (int16_t*)malloc(iMaxBytes);
433  }
434  pLmdControl->iBufferWords = iMaxBytes / 2;
435  pLmdControl->iInternBuffer = 1;
436  pLmdControl->iTCP = pLmdControl->pTCP->socket;
437  pLmdControl->iTcpTimeout = iTimeout;
438  pLmdControl->iTCPowner = 0;
439  return (LMD__SUCCESS);
440 }
441 //===============================================================
443 {
444 
445  int32_t stat;
446  const char cClose[12] = "CLOSE";
447  // send request buffer for stream server
448  if (pLmdControl->iPort == PORT__STREAM) {
449  stat = f_stc_write(cClose, 12, pLmdControl->iTCP);
450  if (stat != STC__SUCCESS) {
451  printf("fLmdCloseMbs: Error writing CLOSE with f_stc_write!\n");
452  }
453  }
454  stat = f_stc_close(pLmdControl->pTCP);
455  pLmdControl->pMbsFileHeader = NULL; // was reference only
456  if (pLmdControl->iTCPowner == 0) {
457  pLmdControl->pTCP = NULL;
458  } // was reference only
459  fLmdCleanup(pLmdControl);
460  return (stat);
461 }
462 //===============================================================
464 {
465  uint32_t stat;
466  sMbsHeader* pM;
467  *event = NULL;
468  if (pLmdControl->iLeftWords == 0) { // get new buffer
469  stat = fLmdGetMbsBuffer(pLmdControl, NULL, 0, NULL, NULL);
470  if (stat != LMD__SUCCESS) {
471  return (stat);
472  }
473  // first event behind header:
474  pLmdControl->pMbsHeader = (sMbsHeader*)(pLmdControl->pBuffer + sizeof(sMbsBufferHeader) / 2);
475  }
476  pM = pLmdControl->pMbsHeader; // current to be returned
477  pLmdControl->iLeftWords -= (pLmdControl->pMbsHeader->iWords + 4);
478  pLmdControl->pMbsHeader = (sMbsHeader*)((int16_t*)pLmdControl->pMbsHeader + pLmdControl->pMbsHeader->iWords + 4);
479  pLmdControl->iElements++;
480  *event = pM;
481  return (LMD__SUCCESS);
482 }
483 //===============================================================
485  sMbsBufferHeader* pBuffer,
486  uint32_t iBytes,
487  uint32_t* iElements,
488  uint32_t* iBytesUsed)
489 {
490 
491  // sMbsHeader* pm;
492  sMbsBufferHeader* pBuf;
493  uint32_t usedBytes = 0, leftBytes = 0; //, *ps, *pd, i,ii, elem=0, size=0;
494  int32_t iReturn;
495  const char cRequest[12] = "GETEVT";
496 
497  leftBytes = iBytes;
498  pBuf = pBuffer;
499  if (pBuf == NULL) {
500  pBuf = (sMbsBufferHeader*)pLmdControl->pBuffer; // internal buffer
501  leftBytes = pLmdControl->iBufferWords * 2; // size of this buffer
502  }
503  if (pBuf == NULL) {
504  printf("fLmdGetMbsBuffer: Need buffer to read\n");
505  return (LMD__FAILURE);
506  }
507  if (leftBytes < sizeof(sMbsBufferHeader)) {
508  printf("fLmdGetMbsBuffer: %s buffer size %d too small for %lx bytes\n",
509  pLmdControl->cFile,
510  leftBytes,
511  sizeof(sMbsBufferHeader));
512  return (LMD__FAILURE);
513  }
514  // send request buffer for stream server
515  if (pLmdControl->iPort == PORT__STREAM) {
516  iReturn = f_stc_write(cRequest, 12, pLmdControl->iTCP);
517  if (iReturn != STC__SUCCESS) {
518  return (LMD__FAILURE);
519  }
520  }
521  iReturn = f_stc_read((int32_t*)pBuf, sizeof(sMbsBufferHeader), pLmdControl->iTCP, pLmdControl->iTcpTimeout);
522  if (iReturn == STC__TIMEOUT) {
523  return (LMD__TIMEOUT);
524  }
525  if (iReturn != STC__SUCCESS) {
526  return (LMD__FAILURE);
527  }
528  if (pLmdControl->iSwap) {
529  fLmdSwap4((uint32_t*)pBuf, sizeof(sMbsBufferHeader) / 4);
530  }
531  if (leftBytes < (sizeof(sMbsBufferHeader) + 2 * pBuf->iUsedWords)) {
532  printf("fLmdGetMbsBuffer: %s buffer size %d too small for %lx bytes\n",
533  pLmdControl->cFile,
534  leftBytes,
535  sizeof(sMbsBufferHeader) + 2 * pBuf->iMaxWords);
536  return (LMD__FAILURE);
537  }
538  usedBytes = pBuf->iUsedWords * 2;
539  if ((pBuf->iType & 0xffff) == 100) {
540  iReturn = f_stc_read((int32_t*)(pBuf + 1), usedBytes, pLmdControl->iTCP, -1);
541  }
542  if (iReturn == STC__TIMEOUT) {
543  return (LMD__TIMEOUT);
544  }
545  if (iReturn != STC__SUCCESS) {
546  return (LMD__FAILURE);
547  }
548  if (pLmdControl->iSwap) {
549  fLmdSwap4((uint32_t*)(pBuf + 1), usedBytes / 4);
550  }
551  if (iBytesUsed != NULL) {
552  *iBytesUsed = usedBytes + sizeof(sMbsBufferHeader);
553  }
554  if (iElements != NULL) {
555  *iElements = pBuf->iElements;
556  }
557  pLmdControl->iBytes += usedBytes;
558  pLmdControl->iLeftWords = usedBytes / 2; // without header
559  pLmdControl->pMbsFileHeader = (sMbsFileHeader*)pBuf;
560  return (LMD__SUCCESS);
561 }
562 #endif
563 // endif FILEONLY
564 
565 //===============================================================
567  char* Filename,
568  sMbsFileHeader* pBuffHead, // LMD__INTERNAL_HEADER (NULL) or address of file header
569  uint32_t iBytes, // LMD__NO_BUFFER (0) or LMD__MIN_BUFFER or internal buffersize
570  uint32_t iUseOffset) // LMD__[NO_]INDEX
571 {
572 
573  int32_t iReturn;
574  uint32_t bufferBytes = 0; //,l=0,i,h[12];
575  // lmdoff_t to;
576 
577  memset(pLmdControl, 0, sizeof(sLmdControl));
578  if (pBuffHead == LMD__INTERNAL_HEADER) {
579  pLmdControl->pMbsFileHeader = (sMbsFileHeader*)malloc(sizeof(sMbsFileHeader));
580  pLmdControl->iInternHeader = 1;
581  } else {
582  pLmdControl->pMbsFileHeader = pBuffHead;
583  pLmdControl->iInternHeader = 0;
584  }
585  memset(pLmdControl->pMbsFileHeader, 0, sizeof(sMbsFileHeader));
586 
587  // copy file name to control structure
588  size_t len = strlen(Filename);
589  if (len < sizeof(pLmdControl->cFile)) {
590  strncpy(pLmdControl->cFile, Filename, len);
591  } else {
592  strncpy(pLmdControl->cFile, Filename, sizeof(pLmdControl->cFile) - 1);
593  }
594  if ((pLmdControl->fFile = (FILE*)fopen64(Filename, "r")) == NULL) {
595  printf("fLmdGetOpen: File not found: %s\n", Filename);
596  fLmdCleanup(pLmdControl);
597  return (GETLMD__NOFILE);
598  }
599 
600  /* read header */
601  iReturn = fLmdReadBuffer(pLmdControl, (char*)pLmdControl->pMbsFileHeader, sizeof(sMbsFileHeader));
602  if (iReturn != sizeof(sMbsFileHeader)) {
603  printf("fLmdGetOpen: LMD format error: no LMD file: %s\n", Filename);
604  fLmdGetClose(pLmdControl);
605  return (GETLMD__NOLMDFILE);
606  }
607  // check type and subtype, and endian
608  if (pLmdControl->pMbsFileHeader->iEndian != 1) {
609  pLmdControl->iSwap = 1;
610  }
611  if (pLmdControl->iSwap) {
612  printf("do swap !!!\n");
613  fLmdSwap4((uint32_t*)pLmdControl->pMbsFileHeader, sizeof(sMbsFileHeader) / 4);
614  fLmdSwap8((uint64_t*)&pLmdControl->pMbsFileHeader->iTableOffset, 1);
615  }
616  if (pLmdControl->pMbsFileHeader->iType != LMD__TYPE_FILE_HEADER_101_1) {
617  printf("fLmdGetOpen: LMD format error: no LMD file: %s, type is %0x\n",
618  Filename,
619  pLmdControl->pMbsFileHeader->iType);
620  fLmdGetClose(pLmdControl);
621  return (GETLMD__NOLMDFILE);
622  }
623 
624  if ((iUseOffset == LMD__INDEX) && (pLmdControl->pMbsFileHeader->iTableOffset > 0)) {
625  // printf("fLmdGetOpen: use table in file: %s\n",Filename);
626  pLmdControl->iOffsetSize = pLmdControl->pMbsFileHeader->iOffsetSize;
627  iReturn = fLmdOffsetRead(pLmdControl); // read offset table
628  if (iReturn != LMD__SUCCESS) {
629  printf("fLmdGetOpen: Index format error: %s\n", Filename);
630  fLmdGetClose(pLmdControl);
631  return (iReturn);
632  }
633  }
634 
635  pLmdControl->iBytes += iReturn;
636  // more of header?
637  if ((pLmdControl->pMbsFileHeader->iUsedWords > 0) && (pLmdControl->pMbsFileHeader->iUsedWords < UINT32_MAX / 2)) {
638  // Read this additional information without swapping.
639  // Could be mostly strings. Caller must know.
640  pLmdControl->cHeader = malloc(pLmdControl->pMbsFileHeader->iUsedWords * 2);
641  iReturn = fLmdReadBuffer(pLmdControl, pLmdControl->cHeader, pLmdControl->pMbsFileHeader->iUsedWords * 2);
642  if (iReturn != pLmdControl->pMbsFileHeader->iUsedWords * 2) {
643  printf("fLmdGetOpen: LMD format error: no LMD file: %s\n", Filename);
644  fLmdGetClose(pLmdControl);
645  return (GETLMD__NOLMDFILE);
646  }
647  }
648 
649  bufferBytes = iBytes;
650  if (bufferBytes < pLmdControl->pMbsFileHeader->iMaxWords * 2
651  && (pLmdControl->pMbsFileHeader->iMaxWords < UINT32_MAX / 2)) {
652  bufferBytes = pLmdControl->pMbsFileHeader->iMaxWords * 2;
653  }
654  fLmdPrintFileHeader(1, pLmdControl->pMbsFileHeader);
655  pLmdControl->pBuffer = (int16_t*)malloc(bufferBytes);
656  pLmdControl->iBufferWords = bufferBytes / 2; // will be increased if necessary
657 
658  printf("fLmdGetOpen: %s words %u\n", Filename, pLmdControl->iBufferWords);
659 
660  pLmdControl->iLeftWords = 0; // buffer empty, read with first fLmdGetElement
661  pLmdControl->pMbsHeader = NULL;
662  return (LMD__SUCCESS);
663 }
664 //===============================================================
666  sMbsHeader* pMbsHeader,
667  uint32_t iBytes,
668  uint32_t* iElements,
669  uint32_t* iBytesUsed)
670 {
671 
672  sMbsHeader* pm;
673  uint32_t elem = 0, leftBytes = 0, used, elem_sz; //, *ps, *pd, i,ii, size=0;
674  int32_t iReturn;
675 
676  if (iBytes < pLmdControl->pMbsFileHeader->iMaxWords) {
677  printf("fLmdGetBuffer: %s buffer size %d too small for %d bytes\n",
678  pLmdControl->cFile,
679  iBytes,
680  pLmdControl->pMbsFileHeader->iMaxWords);
681  return (LMD__FAILURE);
682  }
683  if (pMbsHeader == NULL) {
684  printf("fLmdGetBuffer: Need buffer to read\n");
685  return (LMD__FAILURE);
686  }
687  *iBytesUsed = 0;
688  *iElements = 0;
689  if (pLmdControl->iElements == pLmdControl->pMbsFileHeader->iElements) {
690  return (GETLMD__EOFILE);
691  }
692 
693  // Offset table
694  if (pLmdControl->iOffsetEntries) { // use offsets to read elements fitting in buffer
695  fLmdOffsetElements(pLmdControl, iBytes, &elem, &used);
696  // printf("Read %d bytes of %d, elements %d\n",used,iBytes,elem);
697  iReturn = fLmdReadBuffer(pLmdControl, (char*)pMbsHeader, used);
698  if (iReturn <= 0) {
699  printf("fLmdGetBuffer: EOF: %s\n", pLmdControl->cFile);
700  return (GETLMD__EOFILE);
701  }
702  if (iReturn != used) {
703  printf("fLmdGetBuffer: LMD read error: unexpected EOF: %s %u %u\n", pLmdControl->cFile, iReturn, used);
704  return (GETLMD__NOLMDFILE);
705  }
706  *iBytesUsed = used;
707  *iElements = elem;
708  if (pLmdControl->iSwap) {
709  fLmdSwap4((uint32_t*)pMbsHeader, iReturn / 4);
710  }
711  pLmdControl->iBytes += iReturn;
712  return (LMD__SUCCESS);
713  }
714  // no offset table
715  // do we have fragment stored?
716  leftBytes = pLmdControl->iLeftWords * 2;
717  if (leftBytes > 0) {
718  if (leftBytes > iBytes) {
719  printf("fLmdGetBuffer: stored piece of data (%u) larger than provided buffer (%u)\n", leftBytes, iBytes);
720  return (LMD__FAILURE);
721  }
722 
723  if (pLmdControl->pMbsHeader == 0) {
724  printf("fLmdGetBuffer: Internal error pMbsHeader==0\n");
725  return (LMD__FAILURE);
726  }
727 
728  memcpy(pMbsHeader, pLmdControl->pMbsHeader, leftBytes);
729  }
730  iReturn = fLmdReadBuffer(pLmdControl, (char*)pMbsHeader + leftBytes, iBytes - leftBytes);
731  if (iReturn <= 0) {
732  printf("fLmdGetBuffer: EOF: %s\n", pLmdControl->cFile);
733  if (leftBytes > 0) {
734  printf("fLmdGetBuffer: EOF while we have some rest data (%u)\n", leftBytes);
735  } else {
736  return (GETLMD__EOFILE);
737  }
738  }
739 
740  if (iReturn > (iBytes - leftBytes)) {
741  printf("fLmdGetBuffer: LMD read error %s - too many bytes read %u wants %u",
742  pLmdControl->cFile,
743  iReturn,
744  iBytes - leftBytes);
745  return (GETLMD__NOLMDFILE);
746  }
747 
748  if (pLmdControl->iSwap) {
749  fLmdSwap4((uint32_t*)pMbsHeader + leftBytes / 4, iReturn / 4);
750  }
751  pLmdControl->iBytes += iReturn;
752  leftBytes += iReturn; // thats what is in the buffer
753  // step through buffer to get number of elements and size
754  pm = pMbsHeader;
755  while (leftBytes >= 8) {
756  if (pm->iType == LMD__TYPE_FILE_INDEX_101_2) {
757  break;
758  } // file index is last
759  elem_sz = (pm->iWords + 4) * 2;
760  if (elem_sz > leftBytes) {
761  break;
762  } // pm valid but incomplete data
763 
764  *iBytesUsed += elem_sz;
765  *iElements += 1;
766  pLmdControl->iElements++;
767  pm = (sMbsHeader*)((char*)pm + elem_sz);
768  leftBytes -= elem_sz;
769  }
770  // printf("Read %d bytes of %d, elements %d\n",*iBytesUsed,iBytes,*iElements);
771  // fragment left? copy to internal buffer
772  if (leftBytes > 0) {
773  if (leftBytes > pLmdControl->iBufferWords * 2) {
774  printf("fLmdGetBuffer: ERROR: internal buffer overflow. Needed:%d available:%d\n",
775  leftBytes,
776  pLmdControl->iBufferWords * 2);
777  return (LMD__FAILURE);
778  } else {
779  memcpy(pLmdControl->pBuffer, pm, leftBytes);
780  }
781  }
782  pLmdControl->iLeftWords = leftBytes / 2;
783  if (pLmdControl->iLeftWords > 0) {
784  pLmdControl->pMbsHeader = (sMbsHeader*)pLmdControl->pBuffer;
785  } else {
786  pLmdControl->pMbsHeader = 0;
787  }
788 
789  return (LMD__SUCCESS);
790 }
791 //===============================================================
792 uint32_t fLmdGetElement(sLmdControl* pLmdControl, uint32_t iEvent, sMbsHeader** event)
793 {
794  sMbsHeader* pM;
795  uint32_t i, evsz; //, *ps, *pd;
796  int32_t iReturn;
797  *event = NULL;
798 
799  if (iEvent == LMD__NO_INDEX) {
800  if (pLmdControl->pBuffer == NULL) {
801  return (GETLMD__NOBUFFER);
802  } // internal buffer needed
803  if (pLmdControl->pMbsFileHeader->iElements == 0) {
804  return (GETLMD__NOMORE);
805  }
806 
807  if (pLmdControl->pMbsHeader == 0) {
808  // second, try to read more bytes
809 
810  iReturn = fLmdReadBuffer(pLmdControl,
811  (char*)(pLmdControl->pBuffer + pLmdControl->iLeftWords),
812  (pLmdControl->iBufferWords - pLmdControl->iLeftWords) * 2);
813 
814  if (iReturn <= 0) {
815  printf("fLmdGetElement: EOF\n");
816  return (GETLMD__EOFILE);
817  }
818 
819  if (pLmdControl->iSwap) {
820  fLmdSwap4((uint32_t*)(pLmdControl->pBuffer + pLmdControl->iLeftWords), iReturn / 4);
821  }
822 
823  pLmdControl->iBytes += iReturn;
824  pLmdControl->pMbsHeader = (sMbsHeader*)pLmdControl->pBuffer;
825  pLmdControl->iLeftWords += iReturn / 2;
826  }
827  // check if we need to read extra data
828  else if ((pLmdControl->iLeftWords < 4) || (pLmdControl->pMbsHeader->iWords + 4 > pLmdControl->iLeftWords)) {
829  // first copy old data, if it exists
830  if (pLmdControl->iLeftWords > 0) {
831  memmove(pLmdControl->pBuffer, pLmdControl->pMbsHeader, pLmdControl->iLeftWords * 2);
832  // printf("copy to the begin rest %u bytes", pLmdControl->iLeftWords*2);
833  }
834 
835  // second, try to read more bytes
836 
837  iReturn = fLmdReadBuffer(pLmdControl,
838  (char*)(pLmdControl->pBuffer + pLmdControl->iLeftWords),
839  (pLmdControl->iBufferWords - pLmdControl->iLeftWords) * 2);
840 
841  if (iReturn <= 0) {
842  printf("fLmdGetElement: EOF\n");
843  return (GETLMD__EOFILE);
844  }
845 
846  if (pLmdControl->iSwap) {
847  fLmdSwap4((uint32_t*)(pLmdControl->pBuffer + pLmdControl->iLeftWords), iReturn / 4);
848  }
849 
850  pLmdControl->iBytes += iReturn;
851  pLmdControl->pMbsHeader = (sMbsHeader*)pLmdControl->pBuffer;
852  pLmdControl->iLeftWords += iReturn / 2;
853  }
854 
855  // check if read buffer enough for event
856 
857  evsz = (pLmdControl->pMbsHeader->iWords + 4) * 2;
858 
859  if (evsz > pLmdControl->iLeftWords * 2) {
860  printf(
861  "fLmdGetElement: Error, full element %u does not fit in buffer %u", evsz, pLmdControl->iLeftWords * 2);
862  return (GETLMD__TOOBIG);
863  }
864 
865  pLmdControl->pMbsFileHeader->iElements--;
866  pM = pLmdControl->pMbsHeader;
867  pLmdControl->pMbsHeader = (sMbsHeader*)((char*)pM + evsz);
868  pLmdControl->iLeftWords -= evsz / 2;
869  pLmdControl->iElements++;
870  *event = pM;
871  return (LMD__SUCCESS);
872  }
873  // get indexed event
874  if (pLmdControl->iOffsetEntries) {
875  if (iEvent >= pLmdControl->iOffsetEntries) {
876  return (GETLMD__OUTOF_RANGE);
877  }
878  int val = fseeko64(pLmdControl->fFile, fLmdOffsetGet(pLmdControl, iEvent - 1) * 4, SEEK_SET);
879  if (0 != val) {
880  return (GETLMD__EOFILE);
881  }
882  i = (fLmdOffsetGet(pLmdControl, iEvent) - fLmdOffsetGet(pLmdControl, iEvent - 1));
883  iReturn = fLmdReadBuffer(pLmdControl, (char*)pLmdControl->pBuffer, i * 4);
884  if (iReturn <= 0) {
885  printf("fLmdGetElement: EOF\n");
886  return (GETLMD__EOFILE);
887  }
888  if (iReturn != (i * 4)) {
889  printf("fLmdGetBuffer: LMD read error: unexpected EOF: %s\n", pLmdControl->cFile);
890  return (GETLMD__EOFILE);
891  }
892  if (pLmdControl->iSwap) {
893  fLmdSwap4((uint32_t*)pLmdControl->pBuffer, iReturn / 4);
894  }
895  pLmdControl->pMbsHeader = (sMbsHeader*)pLmdControl->pBuffer;
896  if ((pLmdControl->pMbsHeader->iWords + 4) != i * 2) {
897  printf("fLmdGetElement: Error Event %d: size from table is %d, header %d\n",
898  iEvent,
899  i / 2,
900  pLmdControl->pMbsHeader->iWords + 4);
901  return (GETLMD__SIZE_ERROR);
902  }
903  pLmdControl->iBytes += iReturn;
904  *event = pLmdControl->pMbsHeader;
905  return (LMD__SUCCESS);
906  } else {
907  return (GETLMD__NOMORE);
908  }
909  // return zero if no more events
910 }
911 //===============================================================
913 {
914  fLmdCleanup(pLmdControl); // cleanup except fFile
915  if (fclose(pLmdControl->fFile) != 0) {
916  pLmdControl->fFile = NULL;
917  return (LMD__CLOSE_ERR);
918  }
919  pLmdControl->fFile = NULL;
920  return (LMD__SUCCESS);
921 }
922 //===============================================================
923 int32_t fLmdReadBuffer(sLmdControl* pLmdControl, char* buffer, uint32_t bytes)
924 {
925  int32_t IObytes;
926  IObytes = (int32_t)fread(buffer, 1, bytes, pLmdControl->fFile);
927  // if(IObytes < bytes) printf("Read %s: request %d bytes, got %d\n",pLmdControl->cFile,bytes,IObytes);
928  return (IObytes);
929 }
930 //===============================================================
931 int32_t fLmdWriteBuffer(sLmdControl* pLmdControl, char* buffer, uint32_t bytes)
932 {
933  int32_t IObytes;
934  IObytes = (int32_t)fwrite(buffer, 1, bytes, pLmdControl->fFile);
935  // if(IObytes < bytes) printf("Write %s: request %d bytes, put %d\n",
936  // pLmdControl->cFile,bytes,IObytes);
937  return (IObytes);
938 }
939 //===============================================================
940 uint64_t fLmdGetBytesWritten(sLmdControl* pLmdControl)
941 {
942  uint64_t bytes;
943  bytes = pLmdControl->iBytes;
944  // add pending data size in current buffer
945  if (pLmdControl->iBufferWords > pLmdControl->iLeftWords) {
946  bytes += (pLmdControl->iBufferWords - pLmdControl->iLeftWords) * 2;
947  }
948  // add table size which will be written at close
949  if ((pLmdControl->pOffset4 != NULL) || (pLmdControl->pOffset8 != NULL)) {
950  bytes += (pLmdControl->iElements + 1) * pLmdControl->iOffsetSize;
951  }
952  return (bytes);
953 }
954 //===============================================================
956 {
957  // do not clean fFile
958  if (pLmdControl->pTCP != NULL) {
959  free(pLmdControl->pTCP);
960  }
961  if (pLmdControl->cHeader != NULL) {
962  free(pLmdControl->cHeader);
963  }
964  if (pLmdControl->pOffset4 != NULL) {
965  free(pLmdControl->pOffset4);
966  }
967  if (pLmdControl->pOffset8 != NULL) {
968  free(pLmdControl->pOffset8);
969  }
970  if (pLmdControl->pBuffer != NULL && pLmdControl->iInternBuffer) {
971  free(pLmdControl->pBuffer);
972  }
973  if (pLmdControl->pMbsFileHeader != NULL && pLmdControl->iInternHeader) {
974  free(pLmdControl->pMbsFileHeader);
975  }
976  pLmdControl->pTCP = NULL;
977  pLmdControl->cHeader = NULL;
978  pLmdControl->pBuffer = NULL;
979  pLmdControl->pOffset4 = NULL;
980  pLmdControl->pOffset8 = NULL;
981  pLmdControl->pMbsFileHeader = NULL;
982  pLmdControl->pMbsHeader = NULL;
983  return (LMD__SUCCESS);
984 }
985 //===============================================================
986 // can be called after GetOpen or ConnectMbs
988 {
989  if (pLmdControl != NULL) {
990  return (pLmdControl->iSwap);
991  } else {
992  return (-1);
993  }
994 }
995 //===============================================================
996 // can be called after PutOpen or before PutClose
998 {
999  if (pLmdControl->pMbsFileHeader != NULL) {
1000  pLmdControl->pMbsFileHeader->iWrittenEndian = iE;
1001  } else {
1002  printf("fLmdSetWrittenEndian: No file header allocated!");
1003  }
1004 }
1005 //===============================================================
1006 // can be called after GetOpen or GetMbsEvent
1008 {
1009  if (pLmdControl->pMbsFileHeader != NULL) {
1010  return (pLmdControl->pMbsFileHeader->iWrittenEndian);
1011  } else {
1012  printf("fLmdGetWrittenEndian: No file header allocated!");
1013  }
1014  return (LMD__ENDIAN_UNKNOWN);
1015 }
1016 //===============================================================
1018 {
1019  sLmdControl* x;
1020  x = (sLmdControl*)malloc(sizeof(sLmdControl));
1021  memset(x, 0, sizeof(sLmdControl));
1022  return (x);
1023 }
1024 //===============================================================
1025 void fLmdOffsetElements(sLmdControl* pLmdControl, uint32_t bytes, uint32_t* elements, uint32_t* used)
1026 {
1027  lmdoff_t *off1, *off2;
1028  uint32_t elem = 0, i, *iff1, *iff2;
1029 
1030  if (pLmdControl->iOffsetSize == 4) {
1031  iff1 = pLmdControl->pOffset4 + pLmdControl->iElements;
1032  iff2 = iff1;
1033  for (i = pLmdControl->iElements; i < pLmdControl->iOffsetEntries - 1; i++) {
1034  if ((*(iff1 + 1) - *iff2) > bytes / 4) {
1035  break;
1036  }
1037  iff1++;
1038  elem++;
1039  pLmdControl->iElements++;
1040  }
1041  *used = (*iff1 - *iff2) * 4;
1042  *elements = elem;
1043  } else if (pLmdControl->iOffsetSize == 8) {
1044  off1 = pLmdControl->pOffset8 + pLmdControl->iElements;
1045  off2 = off1;
1046  for (i = pLmdControl->iElements; i < pLmdControl->iOffsetEntries - 1; i++) {
1047  if ((*(off1 + 1) - *off2) > bytes / 4) {
1048  break;
1049  }
1050  off1++;
1051  elem++;
1052  pLmdControl->iElements++;
1053  }
1054  *used = (*off1 - *off2) * 4;
1055  *elements = elem;
1056  }
1057 }
1058 //===============================================================
1060 {
1061  int32_t iReturn;
1062  sMbsHeader* pTableHead;
1063 
1064  pTableHead = (sMbsHeader*)malloc(16); // header with 8 bytes data for future use.
1065 
1066  int val = fseeko64(pLmdControl->fFile, (lmdoff_t)pLmdControl->pMbsFileHeader->iTableOffset * 4, SEEK_SET);
1067  if (0 != val) {
1068  free(pTableHead);
1069  return (GETLMD__NOLMDFILE);
1070  }
1071  iReturn = fLmdReadBuffer(pLmdControl, (char*)pTableHead, 16);
1072  if (iReturn != 16) {
1073  printf("fLmdGetBuffer: LMD read error: unexpected EOF: %s\n", pLmdControl->cFile);
1074  free(pTableHead);
1075  return (GETLMD__NOLMDFILE);
1076  }
1077  if (pLmdControl->iSwap) {
1078  fLmdSwap4((uint32_t*)pTableHead, 4);
1079  }
1080  if (pTableHead->iType != LMD__TYPE_FILE_INDEX_101_2) {
1081  printf(
1082  "fLmdOffsetTable: LMD format error: no index table: %s, type %0x\n", pLmdControl->cFile, pTableHead->iType);
1083  free(pTableHead);
1084  return (GETLMD__NOLMDFILE);
1085  }
1086  // printf("Table: words:%d type:%08x\n",pTableHead->iWords,pTableHead->iType);
1087  free(pTableHead);
1088  pLmdControl->iOffsetEntries = pLmdControl->pMbsFileHeader->iElements + 1;
1089  pLmdControl->pOffset8 = (lmdoff_t*)malloc(pLmdControl->iOffsetEntries * pLmdControl->iOffsetSize);
1090  iReturn = fLmdReadBuffer(
1091  pLmdControl, (char*)pLmdControl->pOffset8, pLmdControl->iOffsetEntries * pLmdControl->iOffsetSize);
1092  if (iReturn != pLmdControl->iOffsetEntries * pLmdControl->iOffsetSize) {
1093  printf("fLmdOffsetTable: LMD format error: no index table: %s\n", pLmdControl->cFile);
1094  pLmdControl->iOffsetEntries = 0;
1095  return (GETLMD__NOLMDFILE);
1096  }
1097  if (pLmdControl->iSwap) {
1098  fLmdSwap4((uint32_t*)pLmdControl->pOffset8, iReturn / 4);
1099  if (pLmdControl->iOffsetSize == 8) {
1100  fLmdSwap8((uint64_t*)pLmdControl->pOffset8, iReturn / 8);
1101  }
1102  }
1103  // go back behing header
1104  val = fseeko64(pLmdControl->fFile, (lmdoff_t)sizeof(sMbsFileHeader), SEEK_SET);
1105  if (0 != val) {
1106  return (GETLMD__NOLMDFILE);
1107  }
1108  // use small table
1109  if (pLmdControl->iOffsetSize == 4) {
1110  pLmdControl->pOffset4 = (uint32_t*)pLmdControl->pOffset8;
1111  pLmdControl->pOffset8 = NULL;
1112  }
1113  return (LMD__SUCCESS);
1114 }
1115 //===============================================================
1117 {
1118  int32_t iReturn;
1119  char* pbuf;
1120  lmdoff_t current;
1121  sMbsHeader* pTableHead;
1122  pTableHead = (sMbsHeader*)malloc(16); // header with 8 bytes data for future use.
1123  memset(pTableHead, 0, 16);
1124  pTableHead->iWords = (pLmdControl->iElements + 1) * pLmdControl->iOffsetSize / 2 + 4;
1125  pTableHead->iType = LMD__TYPE_FILE_INDEX_101_2;
1126  /* printf("Table: words:%d type:%08x offbytes:%d\n", */
1127  /* pTableHead->iWords,pTableHead->iType,pLmdControl->iOffsetSize); */
1128  iReturn = fgetpos64(pLmdControl->fFile, (fpos64_t*)&current);
1129  iReturn = fLmdWriteBuffer(pLmdControl, (char*)pTableHead, 16);
1130  free(pTableHead);
1131  pbuf = (char*)pLmdControl->pOffset4; // try short table
1132  if (pbuf == NULL) {
1133  pbuf = (char*)pLmdControl->pOffset8;
1134  }
1135  iReturn = fLmdWriteBuffer(pLmdControl, pbuf, (pLmdControl->iElements + 1) * pLmdControl->iOffsetSize);
1136  if (pLmdControl->pOffset8) {
1137  pLmdControl->pMbsFileHeader->iTableOffset = *(pLmdControl->pOffset8 + pLmdControl->iElements);
1138  }
1139  if (pLmdControl->pOffset4) {
1140  pLmdControl->pMbsFileHeader->iTableOffset = *(pLmdControl->pOffset4 + pLmdControl->iElements);
1141  }
1142  if (current / 4 != pLmdControl->pMbsFileHeader->iTableOffset) {
1143  printf("Table offset mismatch: current:%lld calculated:%lld, cur-cal %lld\n",
1144  (long long int)(current / 4),
1145  (long long int)(pLmdControl->pMbsFileHeader->iTableOffset),
1146  (long long int)(current / 4 - pLmdControl->pMbsFileHeader->iTableOffset));
1147  return (LMD__FAILURE);
1148  }
1149  if (iReturn != (pLmdControl->iElements + 1) * pLmdControl->iOffsetSize) {
1150  printf("Table write error \n");
1151  return (LMD__FAILURE);
1152  }
1153  return (LMD__SUCCESS);
1154 }
1155 //===============================================================
1157 {
1158  // int32_t iReturn;
1159  if (pLmdControl->iElements >= pLmdControl->iOffsetEntries) {
1160  fLmdOffsetResize(pLmdControl, 0);
1161  }
1162  if (pLmdControl->pOffset8) {
1163  *(pLmdControl->pOffset8 + pLmdControl->iElements) =
1164  *(pLmdControl->pOffset8 + pLmdControl->iElements - 1) + (lmdoff_t)lwords;
1165  }
1166  if (pLmdControl->pOffset4) {
1167  *(pLmdControl->pOffset4 + pLmdControl->iElements) =
1168  *(pLmdControl->pOffset4 + pLmdControl->iElements - 1) + lwords;
1169  }
1170  return (LMD__SUCCESS);
1171 }
1172 //===============================================================
1174 {
1175  if (pLmdControl->pOffset8) {
1176  return (*(pLmdControl->pOffset8 + index));
1177  }
1178  if (pLmdControl->pOffset4) {
1179  return ((lmdoff_t) * (pLmdControl->pOffset4 + index));
1180  }
1181  return 0;
1182 }
1183 //===============================================================
1184 void fLmdOffsetResize(sLmdControl* pLmdControl, uint32_t firstValue)
1185 {
1186  lmdoff_t* new;
1187  uint32_t oldEntries, newEntries;
1188 
1189  oldEntries = pLmdControl->iOffsetEntries;
1190  newEntries = oldEntries + OFFSET__ENTRIES;
1191  new = (lmdoff_t*)malloc(newEntries * pLmdControl->iOffsetSize);
1192  memset(new, 0, newEntries * pLmdControl->iOffsetSize);
1193  if (oldEntries > 0) { // table was expanded
1194  // printf("Resize table %d to %d entries\n",oldEntries,newEntries);
1195  if (pLmdControl->pOffset8) {
1196  memcpy(new, pLmdControl->pOffset8, oldEntries * pLmdControl->iOffsetSize);
1197  free(pLmdControl->pOffset8);
1198  // pLmdControl->pOffset8=new;
1199  pLmdControl->pOffset8 = (lmdoff_t*)malloc(newEntries * pLmdControl->iOffsetSize);
1200  memcpy(pLmdControl->pOffset8, new, newEntries * pLmdControl->iOffsetSize);
1201  }
1202  if (pLmdControl->pOffset4) {
1203  memcpy(new, pLmdControl->pOffset4, oldEntries * pLmdControl->iOffsetSize);
1204  free(pLmdControl->pOffset4);
1205  // pLmdControl->pOffset4=(uint32_t*)new;
1206  pLmdControl->pOffset4 = (uint32_t*)malloc(newEntries * pLmdControl->iOffsetSize);
1207  memcpy(pLmdControl->pOffset4, new, newEntries * pLmdControl->iOffsetSize);
1208  }
1209  } else { // table was new
1210  // printf("Create table %d entries, first offset %d\n",newEntries,firstValue);
1211  if (pLmdControl->iOffsetSize == 8) {
1212  // pLmdControl->pOffset8=new;
1213  pLmdControl->pOffset8 = (lmdoff_t*)malloc(newEntries * pLmdControl->iOffsetSize);
1214  memcpy(pLmdControl->pOffset8, new, newEntries * pLmdControl->iOffsetSize);
1215  *pLmdControl->pOffset8 = (lmdoff_t)firstValue;
1216  }
1217  if (pLmdControl->iOffsetSize == 4) {
1218  // pLmdControl->pOffset4=(uint32_t*)new;
1219  pLmdControl->pOffset4 = (uint32_t*)malloc(newEntries * pLmdControl->iOffsetSize);
1220  memcpy(pLmdControl->pOffset4, new, newEntries * pLmdControl->iOffsetSize);
1221  *pLmdControl->pOffset4 = firstValue;
1222  }
1223  }
1224  free(new);
1225  pLmdControl->iOffsetEntries = newEntries;
1226 }
1227 //===============================================================
1228 void fLmdPrintBufferHeader(uint32_t iVerbose, sMbsBufferHeader* pMbsBufferHeader)
1229 {
1230  if (iVerbose) {
1231  if (pMbsBufferHeader) {
1232  printf("BfHd: # %d, DataWords:%d Type:%08x Elements:%d sec:%d.%d MaxWords:%d\n",
1233  pMbsBufferHeader->iBuffer,
1234  pMbsBufferHeader->iUsedWords,
1235  pMbsBufferHeader->iType,
1236  pMbsBufferHeader->iElements,
1237  pMbsBufferHeader->iTimeSpecSec,
1238  pMbsBufferHeader->iTimeSpecNanoSec / 1000,
1239  pMbsBufferHeader->iMaxWords);
1240  }
1241  }
1242 }
1243 //===============================================================
1244 void fLmdPrintFileHeader(uint32_t iVerbose, sMbsFileHeader* pMbsFileHeader)
1245 {
1246  if (iVerbose) {
1247  if (pMbsFileHeader) {
1248  printf("FiHd: DataWords:%d Type:%d.%d Elements:%d sec:%d.%d MaxWords:%d Index: %llx[%d]\n",
1249  pMbsFileHeader->iUsedWords,
1250  pMbsFileHeader->iType & 0xffff,
1251  pMbsFileHeader->iType >> 16,
1252  pMbsFileHeader->iElements,
1253  pMbsFileHeader->iTimeSpecSec,
1254  pMbsFileHeader->iTimeSpecNanoSec / 1000,
1255  pMbsFileHeader->iMaxWords,
1256  (long long unsigned int)(pMbsFileHeader->iTableOffset),
1257  pMbsFileHeader->iOffsetSize);
1258  }
1259  }
1260 }
1261 //===============================================================
1262 void fLmdPrintHeader(uint32_t iVerbose, sMbsHeader* pMbsHeader)
1263 {
1264  if (iVerbose) {
1265  if (pMbsHeader) {
1266  printf("ElHd: words:%d type:%08x\n", pMbsHeader->iWords, pMbsHeader->iType);
1267  }
1268  }
1269 }
1270 //===============================================================
1271 void fLmdPrintEvent(uint32_t iVerbose, sMbsEventHeader* pMbsEventHeader)
1272 {
1273  if (iVerbose) {
1274  if (pMbsEventHeader) {
1275  printf("EvHd: words:%6d type:%08x trigger:%2d #:%4d\n",
1276  pMbsEventHeader->iWords,
1277  pMbsEventHeader->iType,
1278  pMbsEventHeader->iTrigger >> 16,
1279  pMbsEventHeader->iEventNumber);
1280  }
1281  }
1282 }
1283 //===============================================================
1284 void fLmdPrintControl(uint32_t iVerbose, sLmdControl* pLmdControl)
1285 {
1286  if (iVerbose) {
1287  printf("Ctrl: file:%s words:%d left:%d bytes read:%lld elements:%d\n",
1288  pLmdControl->cFile,
1289  pLmdControl->iBufferWords,
1290  pLmdControl->iLeftWords,
1291  (long long int)(pLmdControl->iBytes),
1292  pLmdControl->iElements);
1293  fLmdPrintFileHeader(iVerbose, pLmdControl->pMbsFileHeader);
1294  fLmdPrintEvent(iVerbose, (sMbsEventHeader*)pLmdControl->pMbsHeader);
1295  }
1296 }
1297 //===============================================================
1298 void fLmdSwap4(uint32_t* array, uint32_t items)
1299 {
1300  uint32_t i, *pp;
1301  pp = array;
1302  for (i = 0; i < items; i++) {
1303  // printf("Swap 4 %08x ",*pp);
1304  *pp = (*pp >> 24) + ((*pp >> 8) & 0x0000ff00) + ((*pp << 8) & 0x00ff0000) + (*pp << 24);
1305  // printf("to %08x \n",*pp);
1306  pp++;
1307  }
1308 }
1309 //===============================================================
1310 void fLmdSwap8(uint64_t* array, uint32_t items)
1311 {
1312  uint64_t* pp;
1313  uint32_t i; //,x;
1314  pp = array;
1315  for (i = 0; i < items; i++) {
1316  // printf("Swap 8 %016llx ",*pp);
1317  *pp = (*pp << 32) + (*pp >> 32);
1318  // printf("to %016llx\n",*pp,*(pp+1));
1319  pp++;
1320  }
1321 }
uint32_t fLmdOffsetWrite(sLmdControl *)
Definition: fLmd.c:1116
#define LMD__SUCCESS
Definition: fLmd.h:19
#define LMD__STANDARD_HEADER
Definition: sMbs.h:18
INTS4 socket
Definition: f_stccomm.h:308
INTS4 f_stc_close(struct s_tcpcomm *ps_tcp)
Definition: f_stccomm.c:1095
#define GETLMD__EOFILE
Definition: fLmd.h:24
uint32_t iTrigger
Definition: sMbs.h:116
#define LMD__INDEX
Definition: sMbs.h:20
uint32_t iElements
Definition: sMbs.h:64
int32_t fLmdWriteBuffer(sLmdControl *, char *, uint32_t)
Definition: fLmd.c:931
#define PORT__STREAM
Definition: fLmd.h:36
#define LMD__LARGE_FILE
Definition: sMbs.h:22
uint32_t iTimeSpecSec
Definition: sMbs.h:66
#define LMD__ENDIAN_UNKNOWN
Definition: sMbs.h:35
#define GETLMD__NOMORE
Definition: fLmd.h:25
sMbsHeader * pMbsHeader
Definition: fLmd.h:58
#define LMD__NO_OVERWRITE
Definition: sMbs.h:29
uint32_t iType
Definition: sMbs.h:80
#define LMD__NO_INDEX
Definition: sMbs.h:28
#define PUTLMD__FILE_EXIST
Definition: fLmd.h:31
uint32_t fLmdOffsetSet(sLmdControl *, uint32_t)
Definition: fLmd.c:1156
uint32_t iMaxWords
Definition: sMbs.h:60
uint32_t fLmdCleanup(sLmdControl *)
Definition: fLmd.c:955
uint32_t iBuffer
Definition: sMbs.h:63
int16_t * pBuffer
Definition: fLmd.h:41
lmdoff_t iTableOffset
Definition: sMbs.h:81
void fLmdOffsetElements(sLmdControl *, uint32_t, uint32_t *, uint32_t *)
Definition: fLmd.c:1025
uint64_t iBytes
Definition: fLmd.h:47
uint32_t iWords
Definition: sMbs.h:106
uint32_t iTimeSpecSec
Definition: sMbs.h:84
void fLmdPrintFileHeader(uint32_t iVerbose, sMbsFileHeader *pMbsFileHeader)
Definition: fLmd.c:1244
uint32_t iType
Definition: sMbs.h:61
#define OFFSET__ENTRIES
Definition: fLmd.c:107
uint32_t fLmdGetMbsEvent(sLmdControl *pLmdControl, sMbsHeader **event)
Definition: fLmd.c:463
uint32_t iTCP
Definition: fLmd.h:60
#define LMD__GET_EVENTS
Definition: sMbs.h:17
uint32_t iType
Definition: sMbs.h:115
uint32_t iInternBuffer
Definition: fLmd.h:45
uint32_t fLmdGetElement(sLmdControl *pLmdControl, uint32_t iEvent, sMbsHeader **event)
Definition: fLmd.c:792
uint32_t iTimeSpecNanoSec
Definition: sMbs.h:85
uint32_t iElements
Definition: fLmd.h:46
uint64_t lmdoff_t
Definition: sMbs.h:39
uint32_t * pOffset4
Definition: fLmd.h:52
uint32_t iMaxWords
Definition: sMbs.h:79
#define STC__TIMEOUT
Definition: f_stccomm.h:373
#define PUTLMD__OPEN_ERR
Definition: fLmd.h:33
uint32_t fLmdInitMbs(sLmdControl *pLmdControl, char *Nodename, uint32_t iMaxBytes, uint32_t iBuffers, uint32_t iStreams, uint32_t iPort, uint32_t iTimeout)
Definition: fLmd.c:405
uint32_t fLmdPutClose(sLmdControl *pLmdControl)
Definition: fLmd.c:307
uint32_t fLmdGetClose(sLmdControl *pLmdControl)
Definition: fLmd.c:912
uint32_t iPort
Definition: fLmd.h:61
INTS4 f_stc_connectserver(CHARS *c_node, INTS4 l_port, INTS4 *pi_channel, struct s_tcpcomm *ps_client)
Definition: f_stccomm.c:486
#define LMD__TYPE_FILE_INDEX_101_2
Definition: sMbs.h:13
#define STC__SUCCESS
Definition: f_stccomm.h:368
uint32_t iElements
Definition: sMbs.h:82
void fLmdSwap4(uint32_t *array, uint32_t items)
Definition: fLmd.c:1298
uint32_t iOffsetSize
Definition: fLmd.h:55
#define LMD__TIMEOUT
Definition: fLmd.h:30
uint64_t fLmdGetBytesWritten(sLmdControl *pLmdControl)
Definition: fLmd.c:940
#define GETLMD__OUTOF_RANGE
Definition: fLmd.h:28
void fLmdSetWrittenEndian(sLmdControl *pLmdControl, uint32_t iE)
Definition: fLmd.c:997
uint32_t iType
Definition: sMbs.h:107
#define PORT__TRANS
Definition: fLmd.h:35
uint32_t fLmdGetBuffer(sLmdControl *pLmdControl, sMbsHeader *pMbsHeader, uint32_t iBytes, uint32_t *iElements, uint32_t *iBytesUsed)
Definition: fLmd.c:665
#define PUTLMD__EXCEED
Definition: fLmd.h:34
#define GETLMD__TOOBIG
Definition: fLmd.h:27
uint32_t iOffsetEntries
Definition: fLmd.h:56
uint32_t iTimeSpecNanoSec
Definition: sMbs.h:67
#define GETLMD__SIZE_ERROR
Definition: fLmd.h:29
uint32_t iTCPowner
Definition: fLmd.h:63
#define GETLMD__NOFILE
Definition: fLmd.h:22
uint32_t fLmdGetWrittenEndian(sLmdControl *pLmdControl)
Definition: fLmd.c:1007
uint32_t iUsedWords
Definition: sMbs.h:71
uint32_t iEventNumber
Definition: sMbs.h:117
void fLmdPrintEvent(uint32_t iVerbose, sMbsEventHeader *pMbsEventHeader)
Definition: fLmd.c:1271
uint32_t fLmdGetOpen(sLmdControl *pLmdControl, char *Filename, sMbsFileHeader *pBuffHead, uint32_t iBytes, uint32_t iUseOffset)
Definition: fLmd.c:566
uint32_t iMaxBytes
Definition: sMbs.h:51
void fLmdPrintHeader(uint32_t iVerbose, sMbsHeader *pMbsHeader)
Definition: fLmd.c:1262
int32_t fLmdReadBuffer(sLmdControl *pLmdControl, char *buffer, uint32_t bytes)
Definition: fLmd.c:923
uint32_t fLmdCloseMbs(sLmdControl *pLmdControl)
Definition: fLmd.c:442
#define GETLMD__NOLMDFILE
Definition: fLmd.h:23
void fLmdPrintControl(uint32_t iVerbose, sLmdControl *pLmdControl)
Definition: fLmd.c:1284
uint32_t iOffsetSize
Definition: sMbs.h:83
lmdoff_t fLmdOffsetGet(sLmdControl *, uint32_t)
Definition: fLmd.c:1173
uint32_t iLeftWords
Definition: fLmd.h:43
INTS4 f_stc_write(INTS1 *p_buffer, INTS4 i_buflen, INTS4 i_channel)
Definition: f_stccomm.c:324
sLmdControl * fLmdAllocateControl()
Definition: fLmd.c:1017
uint32_t fLmdOffsetRead(sLmdControl *)
Definition: fLmd.c:1059
void fLmdOffsetResize(sLmdControl *, uint32_t)
Definition: fLmd.c:1184
FILE * fFile
Definition: fLmd.h:40
uint32_t iUsedWords
Definition: sMbs.h:89
lmdoff_t * pOffset8
Definition: fLmd.h:53
uint32_t iInternHeader
Definition: fLmd.h:44
unsigned int uint32_t
uint32_t fLmdPutElement(sLmdControl *pLmdControl, sMbsHeader *pHeader)
Definition: fLmd.c:190
#define LMD__TYPE_FILE_HEADER_101_1
Definition: sMbs.h:11
#define PUTLMD__TOOBIG
Definition: fLmd.h:32
char cFile[512]
Definition: fLmd.h:48
uint32_t fLmdGetMbsBuffer(sLmdControl *pLmdControl, sMbsBufferHeader *pBuffer, uint32_t iBytes, uint32_t *iElements, uint32_t *iBytesUsed)
Definition: fLmd.c:484
uint32_t iSwap
Definition: fLmd.h:49
uint32_t iWords
Definition: sMbs.h:114
uint32_t fLmdPutOpen(sLmdControl *pLmdControl, char *Filename, sMbsFileHeader *pBuffHead, uint32_t iBytes, uint32_t iOver, uint32_t iUseOffset, uint32_t iLargeFile)
Definition: fLmd.c:110
uint32_t iEndian
Definition: sMbs.h:50
struct s_tcpcomm * pTCP
Definition: fLmd.h:59
INTS4 f_stc_read(INTS1 *p_buffer, INTS4 i_buflen, INTS4 i_channel, INTS4 i_timeout)
Definition: f_stccomm.c:123
#define GETLMD__NOBUFFER
Definition: fLmd.h:26
uint32_t fLmdGetSwap(sLmdControl *pLmdControl)
Definition: fLmd.c:987
uint32_t iEndian
Definition: sMbs.h:87
uint32_t iTcpTimeout
Definition: fLmd.h:62
char * cHeader
Definition: fLmd.h:51
uint32_t iBuffers
Definition: sMbs.h:52
#define LMD__FAILURE
Definition: fLmd.h:20
sMbsFileHeader * pMbsFileHeader
Definition: fLmd.h:57
uint32_t fLmdConnectMbs(sLmdControl *pLmdControl, char *Nodename, uint32_t iPort, uint32_t *iBufferBytes)
Definition: fLmd.c:338
#define LMD__INTERNAL_HEADER
Definition: sMbs.h:19
uint32_t fLmdPutBuffer(sLmdControl *pLmdControl, sMbsHeader *pHeader, uint32_t Items)
Definition: fLmd.c:257
uint32_t iStreams
Definition: sMbs.h:53
#define LMD__CLOSE_ERR
Definition: fLmd.h:21
uint32_t iBufferWords
Definition: fLmd.h:42
void fLmdPrintBufferHeader(uint32_t iVerbose, sMbsBufferHeader *pMbsBufferHeader)
Definition: fLmd.c:1228
void fLmdSwap8(uint64_t *array, uint32_t items)
Definition: fLmd.c:1310
uint32_t iWrittenEndian
Definition: sMbs.h:88