Skip to content

Commit 927af4f

Browse files
committed
Tidyup checkpoint comments
1 parent 828f5e0 commit 927af4f

File tree

6 files changed

+80
-34
lines changed

6 files changed

+80
-34
lines changed

CHANGES.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,11 @@ Jan 2018
4848
* Can now process files that have not been downloaded with the RDW option,
4949
as some sites do not have suitable ftp package available. New option
5050
is "-f NORDW".
51+
52+
Feb 2018
53+
* Added a simple "checkpoint" manager to recover after failures of the
54+
formatter. This may help when you run out of disk space while formatting
55+
very large output - the program may be able to restart from a more recent
56+
checkpoint.
57+
* Discovered a few fields in the WTAS structure are not used in the way
58+
the documentation and product header files claim.

bin/aix/convH

0 Bytes
Binary file not shown.

bin/aix/mqsmfcsv

6 Bytes
Binary file not shown.

bin/linux/mqsmfcsv

24 Bytes
Binary file not shown.

bin/win/mqsmfcsv.exe

512 Bytes
Binary file not shown.

src/mqsmf.c

Lines changed: 72 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016 IBM Corporation and other Contributors.
2+
* Copyright (c) 2016,2018 IBM Corporation and other Contributors.
33
*
44
* All rights reserved. This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License v1.0
@@ -35,15 +35,19 @@
3535
/* necessary byte-swapping from big to little-endian */
3636
/* values. */
3737
/* */
38-
/* When downloading the SMF dump, make sure the RDW */
39-
/* (record descriptor word) is included in the file. */
38+
/* When downloading the SMF dump, it is preferred to */
39+
/* have the RDW (record descriptor word) included in */
40+
/* the file. */
4041
/* This is because the I/O on Windows and Unix */
4142
/* platforms does not understand the record-oriented */
4243
/* z/OS file format; instead we have to know how long */
4344
/* each record is - given by the RDW. This is not */
4445
/* the default option on many file transfer programs. */
4546
/* Check the documentation for your file manager on */
46-
/* how to include the RDW when downloading. */
47+
/* how to include the RDW when downloading. If you */
48+
/* cannot get the RDW included, then this program now */
49+
/* supports a mechanism that does not require it, but */
50+
/* is slightly slower when formatting the data. */
4751
/* */
4852
/* Structures are defined as "packed" which means that*/
4953
/* fields within a structure may not start on a */
@@ -118,15 +122,18 @@ char tmpHead[64]; /* Working space for a column heading*/
118122
unsigned int recordType;
119123
unsigned short recordSubType;
120124

125+
/********************************************************************/
126+
/* Structure and vars to control checkpoint recording and playback */
127+
/********************************************************************/
121128
typedef struct {
122129
char *name;
123130
FILE *fp;
124131
myoff_t offset;
125132
} checkPoint_t;
126133

127-
#define MAXCP (50)
134+
#define MAXCP (50) /* Maximum number of output files */
128135
checkPoint_t checkPoint[MAXCP] = {NULL,NULL,0};
129-
char *checkPointFileBaseName = "MQSMFCHKPT.txt";
136+
char *checkPointFileBaseName = "SMF-CKPT.txt";
130137
char checkPointFileName[PATH_MAX] = {0};
131138
BOOL checkPointTaken = FALSE;
132139

@@ -140,7 +147,7 @@ static char *directory = NULL;
140147
static unsigned int totalRecords = 0;
141148
static unsigned int startingRecords = 0;
142149

143-
static unsigned int Count115[256] = {0}; /* Max subtype is 255*/
150+
static unsigned int Count115[256] = {0}; /* Max subtype is 255 */
144151
static unsigned int Count116[256] = {0};
145152

146153
/********************************************************************/
@@ -152,6 +159,7 @@ static int mqoptind = 1; /* getopt index */
152159
static int mqoptopt; /* getopt option */
153160
static char* mqoptarg; /* getopt argument */
154161

162+
static BOOL debugBREAK = FALSE;
155163

156164
/********************************************************************/
157165
/* MAIN */
@@ -290,6 +298,10 @@ int main( int argc, char *argv[] )
290298
exit(1);
291299
}
292300

301+
/* Set up any special debug processing */
302+
if (getenv("MQSMFCSV_BREAK")) {
303+
debugBREAK=TRUE;
304+
}
293305

294306
/*********************************************************************/
295307
/* Open the input file */
@@ -315,6 +327,7 @@ int main( int argc, char *argv[] )
315327
printf("Total File Size = %lld\n",totalFileSize);
316328

317329
convInit(); /* Decide whether this is a big or little endian machine*/
330+
318331
b = strrchr(inputFile,'/');
319332
if (!b)
320333
b = strrchr(inputFile,'\\');
@@ -927,10 +940,10 @@ int main( int argc, char *argv[] )
927940
takeCheckPoint(checkPointFileName,pos);
928941
}
929942

930-
if (getenv("MQSMFCSV_BREAK") != NULL) /* for testing purposes */
943+
if (debugBREAK) /* for testing purposes */
931944
{
932945
/* Want to force an abend at some point after a checkpoint */
933-
if (totalRecords % ticker == 0 && checkPointTaken)
946+
if (totalRecords % ticker == 3 && checkPointTaken)
934947
{
935948
printf("Testing: Exiting after %d records processed\n",totalRecords);
936949
exit(0);
@@ -939,7 +952,8 @@ int main( int argc, char *argv[] )
939952
} while (0 != bytesRead && totalRecords < maxRecords);
940953

941954
/***********************************************************************/
942-
/* Cleanup and exit. */
955+
/* Cleanup and exit. If we get here normally, then the checkpoint */
956+
/* file is not needed any more, so it is deleted. */
943957
/***********************************************************************/
944958
if (debugLevel >= 1) {
945959
printf("Removing checkpoint file\n");
@@ -957,21 +971,27 @@ int main( int argc, char *argv[] )
957971
}
958972

959973
printf("Processed %u records total\n",totalRecords);
960-
if (unknownCount >0)
961-
printf(" Unknown record count: %u\n",unknownCount);
962-
if (ignoredCount >0)
963-
printf(" Ignored record count: %u\n",ignoredCount);
964-
for (i=0;i<256;i++)
965-
{
966-
if (Count115[i] > 0)
967-
printf(" Formatted 115 subtype %3d record count: %u\n",i,Count115[i]);
968-
}
969-
for (i=0;i<256;i++)
970-
{
971-
if (Count116[i] > 0)
972-
printf(" Formatted 116 subtype %3d record count: %u\n",i,Count116[i]);
973-
}
974974

975+
/**********************************************************************/
976+
/* If the program has been restarted via checkpoint, these counts are */
977+
/* not accurate, so don't bother printing them */
978+
/**********************************************************************/
979+
if (!resumeCheckPoint) {
980+
if (unknownCount >0)
981+
printf(" Unknown record count: %u\n",unknownCount);
982+
if (ignoredCount >0)
983+
printf(" Ignored record count: %u\n",ignoredCount);
984+
for (i=0;i<256;i++)
985+
{
986+
if (Count115[i] > 0)
987+
printf(" Formatted 115 subtype %3d record count: %u\n",i,Count115[i]);
988+
}
989+
for (i=0;i<256;i++)
990+
{
991+
if (Count116[i] > 0)
992+
printf(" Formatted 116 subtype %3d record count: %u\n",i,Count116[i]);
993+
}
994+
}
975995
exit(0);
976996
}
977997

@@ -1008,7 +1028,8 @@ FILE * fopencsv(const char * basename, BOOL *newFile)
10081028
return fp;
10091029
}
10101030
}
1011-
/* Get here if we've not read an offset */
1031+
1032+
/* Get here if we've not read an offset from the checkpoint recovery file */
10121033
for (i=0;i<MAXCP;i++) {
10131034
if (checkPoint[i].name == NULL) {
10141035
checkPoint[i].name = strdup(basename);
@@ -1019,7 +1040,8 @@ FILE * fopencsv(const char * basename, BOOL *newFile)
10191040
}
10201041
}
10211042
if (!foundGap) {
1022-
printf("Need to increase MAXCP\n");
1043+
printf("Need to increase MAXCP and rebuild.\n");
1044+
exit(1);
10231045
}
10241046
return fp;
10251047
}
@@ -1029,7 +1051,7 @@ FILE * fopenext(const char * basename, const char *ext, BOOL *newFile)
10291051
FILE * fp = NULL;
10301052
char filename[PATH_MAX] = {0};
10311053
char *mode = (append)?"a":"w";
1032-
if (resumeCheckPoint && append)
1054+
if (resumeCheckPoint && append && !strcmp(ext,"csv"))
10331055
mode = "r+";
10341056

10351057
snprintf(filename,sizeof(filename)-1,
@@ -1085,17 +1107,19 @@ void takeCheckPoint(char *f, myoff_t pos) {
10851107
exit(1);
10861108
}
10871109

1088-
/* Offset and current status for the input file */
1089-
b = fprintf(fp, "%lld %d\n",pos,totalRecords);
1110+
/********************************************************************/
1111+
/* Record offset and current status for the input file */
1112+
/********************************************************************/
1113+
b = fprintf(fp, "%d %lld %d\n",totalRecords,pos);
10901114
for (i=0;i<MAXCP;i++) {
1091-
/* Name and offset for all the output files */
1115+
/* Record name and offset for all the output files */
10921116
if (checkPoint[i].name) {
10931117
b = fprintf(fp,"%s %lld\n",checkPoint[i].name,ftello(checkPoint[i].fp));
10941118
}
10951119
}
10961120
fflush(fp);
10971121
fclose(fp);
1098-
checkPointTaken = TRUE; /* Use this during testing */
1122+
checkPointTaken = TRUE; /* This is used during testing */
10991123
return;
11001124
}
11011125

@@ -1104,6 +1128,9 @@ void takeCheckPoint(char *f, myoff_t pos) {
11041128
/* PURPOSE: Work out where we were on the previous execution of the */
11051129
/* formatter. It causes us to reset the input file and all of the */
11061130
/* output streams to wherever we had got to. */
1131+
/* There is not a lot of validation on the input format of the file so */
1132+
/* if it goes wrong, you have to restart the formatting from the */
1133+
/* beginning. */
11071134
/*************************************************************************/
11081135
myoff_t readCheckPoint(FILE *fp) {
11091136
myoff_t inputOffset = 0;
@@ -1117,10 +1144,21 @@ myoff_t readCheckPoint(FILE *fp) {
11171144
printf("Error reading from recovery checkpoint file\n");
11181145
exit(1);
11191146
}
1120-
sscanf(line,"%lld %d",&inputOffset,&startingRecords);
1147+
1148+
/************************************************************************/
1149+
/* First line has two fields for the input file starting state */
1150+
/************************************************************************/
1151+
sscanf(line,"%d %lld",&startingRecords,&inputOffset);
11211152
printf("Reading from recovery checkpoint.\n");
1122-
printf("InputOffset: %lld Processed records: %d\n",inputOffset, startingRecords);
11231153

1154+
if (debugLevel >=1) {
1155+
printf("InputOffset: %lld Processed records: %d\n",inputOffset, startingRecords);
1156+
}
1157+
1158+
/************************************************************************/
1159+
/* Subsequent lines have two fields naming the output structure and how */
1160+
/* far it's been written. */
1161+
/************************************************************************/
11241162
do {
11251163
memset(line,0,sizeof(line));
11261164
c = fgets(line,sizeof(line)-1,fp);
@@ -1130,7 +1168,7 @@ myoff_t readCheckPoint(FILE *fp) {
11301168
sscanf(line,"%s %lld",field,&offset);
11311169
checkPoint[i].name = strdup(field);
11321170
checkPoint[i].offset = offset;
1133-
if (debugLevel >=1) {
1171+
if (debugLevel >=2) {
11341172
printf("Loaded status[%d] for %s as offset %lld\n",i,field,offset);
11351173
}
11361174
i++;

0 commit comments

Comments
 (0)