Skip to content

Commit 0815e34

Browse files
committed
Added support for non-RDW format downloaded files
1 parent 6e813a2 commit 0815e34

File tree

10 files changed

+170
-87
lines changed

10 files changed

+170
-87
lines changed

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,10 @@ Oct 2017
7272
created; cannot rely on it being there
7373

7474
Jan 2018
75-
* QCTDNS structure is not initialised when there hae been no activity
76-
75+
* QCTDNS structure is not initialised when there has been no activity
76+
* Can now process files that have not been downloaded with the RDW option,
77+
as some sites do not have suitable ftp package available. New option
78+
is "-f NORDW".
7779

7880
Pull requests
7981
=============

bin/aix/convH

0 Bytes
Binary file not shown.

bin/aix/mqsmfcsv

216 KB
Binary file not shown.

bin/linux/mqsmfcsv

146 KB
Binary file not shown.

bin/win/mqsmfcsv.exe

1.5 KB
Binary file not shown.

mqsmfcsv.doc

100644100755
2 KB
Binary file not shown.

src/M

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,18 @@ plat=`uname`
44

55
if [ "$plat" = "AIX" ]
66
then
7-
flags="-q32 "
7+
flags="-q32"
88
cc="xlc"
99
targdir="../bin/aix"
1010
else
1111
flags="-m32 "
1212
cc="gcc"
1313
targdir="../bin/linux"
1414
fi
15+
if [ "$CCDEBUG" != "" ]
16+
then
17+
flags="$flags -g"
18+
fi
1519

1620
export PLATFLAGS=$flags CC=$cc VERS=904
1721
make -e -f Makefile.unix $*

src/mqsmf.c

Lines changed: 159 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,9 @@
8080
#include <io.h>
8181
#include <fcntl.h>
8282

83-
#define fstat _fstat64
84-
#define ftello _ftelli64
83+
#define fstat _fstat64
84+
#define ftello _ftelli64
85+
#define fseeko _fseeki64
8586
typedef signed long long myoff_t;
8687
typedef struct __stat64 mystat_t;
8788
#else
@@ -101,6 +102,7 @@ static void Usage();
101102
int debugLevel = 0;
102103
BOOL addEquals = TRUE;
103104
BOOL printHeaders = TRUE;
105+
BOOL useRDW = TRUE;
104106
BOOL sqlMode = FALSE;
105107
commonFields_t commonF = {0};
106108

@@ -148,6 +150,9 @@ int main( int argc, char *argv[] )
148150

149151
char *inputFile = NULL;
150152
FILE *fp;
153+
char *b;
154+
char *basename;
155+
myoff_t currentOffset = 0;
151156
myoff_t totalFileSize = 0;
152157
mystat_t statbuf;
153158
unsigned int totalRecords = 0;
@@ -160,6 +165,7 @@ int main( int argc, char *argv[] )
160165
char *p;
161166
qwhs *pqwhs;
162167
unsigned char correlid[16];
168+
int offsetCorrection;
163169

164170
BOOL error = FALSE;
165171
BOOL knownSubType = TRUE;
@@ -195,7 +201,7 @@ int main( int argc, char *argv[] )
195201
/* Parse command-line parameters */
196202
/******************************************************************/
197203
printf("MQ SMF CSV - Build %s %s\n",__DATE__,__TIME__);
198-
while((c = mqgetopt(argc, argv, "ad:h:i:m:o:rst:")) != EOF)
204+
while((c = mqgetopt(argc, argv, "ad:f:h:i:m:o:rst:")) != EOF)
199205
{
200206
switch(c)
201207
{
@@ -205,6 +211,16 @@ int main( int argc, char *argv[] )
205211
case 'd':
206212
debugLevel = atoi(mqoptarg);
207213
break;
214+
case 'f':
215+
for (i=0;i<strlen(mqoptarg);i++)
216+
mqoptarg[i] = toupper(mqoptarg[i]);
217+
if (!strcmp(mqoptarg,"NORDW"))
218+
useRDW = FALSE;
219+
else if (!strcmp(mqoptarg,"RDW"))
220+
useRDW = TRUE;
221+
else
222+
error = TRUE;
223+
break;
208224
case 'h':
209225
for (i=0;i<strlen(mqoptarg);i++)
210226
mqoptarg[i] = toupper(mqoptarg[i]);
@@ -272,84 +288,110 @@ int main( int argc, char *argv[] )
272288
printf("Total File Size = %lld\n",totalFileSize);
273289

274290
convInit(); /* Decide whether this is a big or little endian machine*/
291+
b = strrchr(inputFile,'/');
292+
if (!b)
293+
b = strrchr(inputFile,'\\');
294+
if (!b)
295+
basename = inputFile;
296+
else
297+
basename = b+1;
298+
printf("Input file: %s. Format: %s.\n",basename, useRDW?"RDW":"Without RDW");
275299

276300
/********************************************************************/
277301
/* Loop until we have no more data or enough records have been read */
278302
/********************************************************************/
303+
currentOffset = 0;
279304
pSMFRecord = (SMFRecord_t *)&dataBuf;
280305
do
281306
{
282-
/********************************************************************/
283-
/* Start reading data and processing the MQ records */
284-
/* First, read the length of this file record (not necessarily the */
285-
/* same as the SMF record length). It comes from the first two */
286-
/* bytes of the Record Descriptor Word (RDW). */
287-
/********************************************************************/
288-
289-
bytesRead = fread(&pSMFRecord->Header.SMFLEN,1,2,fp);
290-
if (bytesRead < 2)
291-
continue;
292-
293-
/********************************************************************/
294-
/* The second half-word is the segment indicator. */
295-
/********************************************************************/
296-
fread(&pSMFRecord->Header.SMFSEG ,1,2,fp);
297-
298-
/********************************************************************/
299-
/* And then read the actual data, starting at the RECFLG field in */
300-
/* the structure. The amount of data to read is given by the length */
301-
/* minus the 4 bytes of the RDW. Check that we have read the right */
302-
/* amount. */
303-
/********************************************************************/
304-
nextLength = conv16(pSMFRecord->Header.SMFLEN) - 4;
305-
if (debugLevel >=3)
306-
printf(" NextLen = %d bytes \n",nextLength);
307-
308-
bytesRead = fread(&pSMFRecord->Header.SMFRECFLG, 1, nextLength , fp);
309-
if (bytesRead != nextLength)
307+
/**********************************************************************/
308+
/* The mechanism for reading the file depends on whether the RDW */
309+
/* field is available. If it is, we know how long to read for each */
310+
/* record. If it is not, then we read the maximum length each time and*/
311+
/* reset the pointer for the next read once we have parsed the record.*/
312+
/**********************************************************************/
313+
memset(dataBuf,0,sizeof(dataBuf));
314+
if (useRDW)
310315
{
311-
printf("Error reading full record from input file\n");
312-
goto mod_exit;
313-
}
314-
offset = bytesRead + 4;
315-
316-
/********************************************************************/
317-
/* If the segment indicator is non-zero, then we need to continue */
318-
/* reading the next record into the same buffer. There is no */
319-
/* SMF header on the subsequent segments, it's just raw data. So */
320-
/* we read the length of the next partial record, and its segment */
321-
/* value. Then the data itself. And loop until we get to */
322-
/* end-of-record indicator in the segment field. Regardless of */
323-
/* segmentation, no SMF record is meant to be >32768 bytes, so we */
324-
/* need to check that. Once again, ignore the RDW when working */
325-
/* out how much real data there is. */
326-
/********************************************************************/
327-
if (pSMFRecord->Header.SMFSEG[0] != 0)
328-
{
329-
do
316+
/********************************************************************/
317+
/* Start reading data and processing the MQ records */
318+
/* First, read the length of this file record (not necessarily the */
319+
/* same as the SMF record length). It comes from the first two */
320+
/* bytes of the Record Descriptor Word (RDW). */
321+
/********************************************************************/
322+
323+
bytesRead = fread(&pSMFRecord->Header.SMFLEN,1,2,fp);
324+
if (bytesRead < 2)
325+
continue;
326+
327+
/********************************************************************/
328+
/* The second half-word is the segment indicator. */
329+
/********************************************************************/
330+
fread(&pSMFRecord->Header.SMFSEG ,1,2,fp);
331+
332+
/********************************************************************/
333+
/* And then read the actual data, starting at the RECFLG field in */
334+
/* the structure. The amount of data to read is given by the length */
335+
/* minus the 4 bytes of the RDW. Check that we have read the right */
336+
/* amount. */
337+
/********************************************************************/
338+
nextLength = conv16(pSMFRecord->Header.SMFLEN) - 4;
339+
if (debugLevel >=3)
340+
printf(" NextLen = %d bytes \n",nextLength);
341+
342+
bytesRead = fread(&pSMFRecord->Header.SMFRECFLG, 1, nextLength , fp);
343+
if (bytesRead != nextLength)
330344
{
345+
printf("Error reading full record from input file\n");
346+
goto mod_exit;
347+
}
348+
offset = bytesRead + 4;
349+
350+
/********************************************************************/
351+
/* If the segment indicator is non-zero, then we need to continue */
352+
/* reading the next record into the same buffer. There is no */
353+
/* SMF header on the subsequent segments, it's just raw data. So */
354+
/* we read the length of the next partial record, and its segment */
355+
/* value. Then the data itself. And loop until we get to */
356+
/* end-of-record indicator in the segment field. Regardless of */
357+
/* segmentation, no SMF record is meant to be >32768 bytes, so we */
358+
/* need to check that. Once again, ignore the RDW when working */
359+
/* out how much real data there is. */
360+
/********************************************************************/
361+
if (pSMFRecord->Header.SMFSEG[0] != 0)
362+
{
363+
do
364+
{
331365

332-
fread(&nextLength ,1,2,fp);
333-
nextLength = conv16(nextLength);
334-
fread(&pSMFRecord->Header.SMFSEG ,1,2,fp);
366+
fread(&nextLength ,1,2,fp);
367+
nextLength = conv16(nextLength);
368+
fread(&pSMFRecord->Header.SMFSEG ,1,2,fp);
335369

336-
if (debugLevel >=3)
337-
printf(" NextLen = %d bytes \n",nextLength);
370+
if (debugLevel >=3)
371+
printf(" NextLen = %d bytes \n",nextLength);
338372

339-
if (offset+nextLength > sizeof(dataBuf))
340-
{
341-
printf("SMF record appears to be too large for buffer\n");
342-
goto mod_exit;
343-
}
373+
if (offset+nextLength > sizeof(dataBuf))
374+
{
375+
printf("SMF record appears to be too large for buffer\n");
376+
goto mod_exit;
377+
}
344378

345-
bytesRead = fread(&dataBuf[offset], 1, nextLength-4 , fp );
346-
offset += bytesRead;
347-
} while (pSMFRecord->Header.SMFSEG[0] != 0x02);/* end of record indicator*/
379+
bytesRead = fread(&dataBuf[offset], 1, nextLength-4 , fp );
380+
offset += bytesRead;
381+
} while (pSMFRecord->Header.SMFSEG[0] != 0x02);/* end of record indicator*/
348382

383+
}
384+
offsetCorrection = 0;
385+
}
386+
else
387+
{
388+
fseeko(fp,currentOffset,SEEK_SET);
389+
bytesRead = fread(&pSMFRecord->Header.SMFRECFLG,1,32768,fp);
390+
offset = bytesRead;
391+
offsetCorrection = 4;
392+
if (bytesRead <= 0)
393+
break;
349394
}
350-
351-
if (debugLevel >=3)
352-
printf("Read a full record of %d bytes \n",offset);
353395

354396
totalRecords++;
355397

@@ -360,7 +402,11 @@ int main( int argc, char *argv[] )
360402
/*********************************************************************/
361403
recordType = pSMFRecord->Header.SMFRECRTY;
362404

363-
subTypesValid = (pSMFRecord->Header.SMFRECFLG & 0x02);
405+
/*********************************************************************/
406+
/* zOS refers to bits from the left - reversed from what you might */
407+
/* expect. So "bit 1" indicating subtypes is '0100 0000' == 0x40 */
408+
/*********************************************************************/
409+
subTypesValid = ((pSMFRecord->Header.SMFRECFLG & 0x40) == 0x40);
364410
if (subTypesValid)
365411
recordSubType = conv16(pSMFRecord->Header.SMFRECSTY);
366412
else
@@ -442,9 +488,6 @@ int main( int argc, char *argv[] )
442488
hund);
443489
}
444490

445-
if (debugLevel >= 2)
446-
printDEBUG("FULL RECORD",dataBuf,offset);
447-
448491
if (recordType == 116 || recordType == 115)
449492
{
450493
/*******************************************************************/
@@ -509,12 +552,49 @@ int main( int argc, char *argv[] )
509552
/* into a local array, doing the endianness conversion on the way. */
510553
/* That makes it look a bit easier rather than than having convxxx */
511554
/* function calls everywhere else. */
555+
/* We do not need to correct for the offset in non-RDW files as that */
556+
/* space is still allocated at the front of the buffer. */
512557
/*********************************************************************/
513-
for (i=0;i<sectionCount;i++)
514558
{
515-
triplet[i].offset = conv32(pSMFRecord->s[i].offset);
516-
triplet[i].l = conv16(pSMFRecord->s[i].l);
517-
triplet[i].n = conv16(pSMFRecord->s[i].n);
559+
int highestOffset = 0;
560+
int h = -1;
561+
int recLength = 0;
562+
memset(triplet,0,sizeof(triplet));
563+
for (i=0;i<sectionCount;i++)
564+
{
565+
triplet[i].offset = conv32(pSMFRecord->s[i].offset);
566+
triplet[i].l = conv16(pSMFRecord->s[i].l);
567+
triplet[i].n = conv16(pSMFRecord->s[i].n);
568+
if (triplet[i].offset > highestOffset &&
569+
triplet[i].offset > 0 &&
570+
triplet[i].n > 0)
571+
{
572+
highestOffset = triplet[i].offset;
573+
h = i;
574+
}
575+
}
576+
if (h < 0) {
577+
if (subTypesValid)
578+
{
579+
recLength = sizeof(SMFHeader_t) - offsetCorrection;
580+
}
581+
else
582+
{
583+
recLength = offsetof(SMFHeader_t,SMFRECSSID) - offsetCorrection;
584+
}
585+
} else {
586+
recLength = triplet[h].offset + triplet[h].l * triplet[h].n - offsetCorrection;
587+
}
588+
currentOffset += recLength;
589+
590+
if (debugLevel >= 3)
591+
{
592+
printf("Highest triple = %d RecLength = %d New Offset = %lld\n",
593+
h, recLength,currentOffset);
594+
}
595+
596+
if (debugLevel >= 2)
597+
printDEBUG("FULL RECORD",dataBuf + offsetCorrection,recLength);
518598
}
519599

520600

@@ -667,7 +747,7 @@ int main( int argc, char *argv[] )
667747
/* If nothing has been done with DNS in this interval, the
668748
record seems to be present but contain garbage.
669749
*/
670-
case 5: if (triplet[i].l == sizeof(qct_dns))
750+
case 5: if (triplet[i].l == sizeof(qct_dns))
671751
printQCTDNS((qct_dns *)p);
672752
break;
673753
default: break;
@@ -853,7 +933,8 @@ FILE * fopenext(const char * basename, const char *ext, BOOL *newFile)
853933

854934
fseek(fp,0,SEEK_END);
855935
pos = ftell(fp);
856-
/*setbuf(fp,0); */ /* useful to have this line when debugging */
936+
if (debugLevel >= 0)
937+
setbuf(fp,0); /* useful to have this line when debugging */
857938

858939
if (pos == 0) /* Have we just created the file, even for "append" mode */
859940
*newFile = TRUE;
@@ -935,9 +1016,10 @@ static void Usage(void)
9351016
{
9361017
printf("Usage: mqsmfcsv [-o <output dir>] [-a] [ -d <level> ]\n");
9371018
printf(" [-h yes|no] [ -i <input file> [-m <max records>]\n");
938-
printf(" [-r ] [-t <ticker>]\n");
1019+
printf(" [-f RDW | NORDW] [-r ] [-t <ticker>]\n");
9391020
printf(" -a Append to files if they exist. Default is overwrite.\n");
9401021
printf(" -d <Level> Debug by dumping binary records (Level = 1 or 2).\n");
1022+
printf(" -f RDW | NORDW Input file format. Default is RDW.\n");
9411023
printf(" -h yes|no Print column headers for new output files. Default is yes.\n");
9421024
printf(" -i <Input file> Default is to read from stdin.\n");
9431025
printf(" -m <Max records> End after formatting M records. Default to process all.\n");

src/printQJST.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ void printQJST(qjst *p)
4747
ADDS32("Log_Write_Threshold" ,p->qjstthrw);
4848
ADDS32("Log_Write_Buffer_Paged",p->qjstbpag);
4949

50-
if (conv32(p->qjstll)>=offsetof(qjst,qjstio))
50+
if (conv16(p->qjstll)>=offsetof(qjst,qjstio))
5151
{
5252
/* Array of 1 entry! Reserved space follows for 2 more, but they */
5353
/* are not currently used. */
@@ -67,7 +67,7 @@ void printQJST(qjst *p)
6767
}
6868
}
6969

70-
if (conv32(p->qjstll)>=sizeof(qjst))
70+
if (conv16(p->qjstll)>=sizeof(qjst))
7171
{
7272
for (i=0;i<2;i++)
7373
{

0 commit comments

Comments
 (0)