1
1
/*
2
- * Copyright (c) 2016 IBM Corporation and other Contributors.
2
+ * Copyright (c) 2016,2018 IBM Corporation and other Contributors.
3
3
*
4
4
* All rights reserved. This program and the accompanying materials
5
5
* are made available under the terms of the Eclipse Public License v1.0
35
35
/* necessary byte-swapping from big to little-endian */
36
36
/* values. */
37
37
/* */
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. */
40
41
/* This is because the I/O on Windows and Unix */
41
42
/* platforms does not understand the record-oriented */
42
43
/* z/OS file format; instead we have to know how long */
43
44
/* each record is - given by the RDW. This is not */
44
45
/* the default option on many file transfer programs. */
45
46
/* 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. */
47
51
/* */
48
52
/* Structures are defined as "packed" which means that*/
49
53
/* fields within a structure may not start on a */
@@ -118,15 +122,18 @@ char tmpHead[64]; /* Working space for a column heading*/
118
122
unsigned int recordType ;
119
123
unsigned short recordSubType ;
120
124
125
+ /********************************************************************/
126
+ /* Structure and vars to control checkpoint recording and playback */
127
+ /********************************************************************/
121
128
typedef struct {
122
129
char * name ;
123
130
FILE * fp ;
124
131
myoff_t offset ;
125
132
} checkPoint_t ;
126
133
127
- #define MAXCP (50)
134
+ #define MAXCP (50) /* Maximum number of output files */
128
135
checkPoint_t checkPoint [MAXCP ] = {NULL ,NULL ,0 };
129
- char * checkPointFileBaseName = "MQSMFCHKPT .txt" ;
136
+ char * checkPointFileBaseName = "SMF-CKPT .txt" ;
130
137
char checkPointFileName [PATH_MAX ] = {0 };
131
138
BOOL checkPointTaken = FALSE;
132
139
@@ -140,7 +147,7 @@ static char *directory = NULL;
140
147
static unsigned int totalRecords = 0 ;
141
148
static unsigned int startingRecords = 0 ;
142
149
143
- static unsigned int Count115 [256 ] = {0 }; /* Max subtype is 255*/
150
+ static unsigned int Count115 [256 ] = {0 }; /* Max subtype is 255 */
144
151
static unsigned int Count116 [256 ] = {0 };
145
152
146
153
/********************************************************************/
@@ -152,6 +159,7 @@ static int mqoptind = 1; /* getopt index */
152
159
static int mqoptopt ; /* getopt option */
153
160
static char * mqoptarg ; /* getopt argument */
154
161
162
+ static BOOL debugBREAK = FALSE;
155
163
156
164
/********************************************************************/
157
165
/* MAIN */
@@ -290,6 +298,10 @@ int main( int argc, char *argv[] )
290
298
exit (1 );
291
299
}
292
300
301
+ /* Set up any special debug processing */
302
+ if (getenv ("MQSMFCSV_BREAK" )) {
303
+ debugBREAK = TRUE;
304
+ }
293
305
294
306
/*********************************************************************/
295
307
/* Open the input file */
@@ -315,6 +327,7 @@ int main( int argc, char *argv[] )
315
327
printf ("Total File Size = %lld\n" ,totalFileSize );
316
328
317
329
convInit (); /* Decide whether this is a big or little endian machine*/
330
+
318
331
b = strrchr (inputFile ,'/' );
319
332
if (!b )
320
333
b = strrchr (inputFile ,'\\' );
@@ -927,10 +940,10 @@ int main( int argc, char *argv[] )
927
940
takeCheckPoint (checkPointFileName ,pos );
928
941
}
929
942
930
- if (getenv ( "MQSMFCSV_BREAK" ) != NULL ) /* for testing purposes */
943
+ if (debugBREAK ) /* for testing purposes */
931
944
{
932
945
/* Want to force an abend at some point after a checkpoint */
933
- if (totalRecords % ticker == 0 && checkPointTaken )
946
+ if (totalRecords % ticker == 3 && checkPointTaken )
934
947
{
935
948
printf ("Testing: Exiting after %d records processed\n" ,totalRecords );
936
949
exit (0 );
@@ -939,7 +952,8 @@ int main( int argc, char *argv[] )
939
952
} while (0 != bytesRead && totalRecords < maxRecords );
940
953
941
954
/***********************************************************************/
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. */
943
957
/***********************************************************************/
944
958
if (debugLevel >= 1 ) {
945
959
printf ("Removing checkpoint file\n" );
@@ -957,21 +971,27 @@ int main( int argc, char *argv[] )
957
971
}
958
972
959
973
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
- }
974
974
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
+ }
975
995
exit (0 );
976
996
}
977
997
@@ -1008,7 +1028,8 @@ FILE * fopencsv(const char * basename, BOOL *newFile)
1008
1028
return fp ;
1009
1029
}
1010
1030
}
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 */
1012
1033
for (i = 0 ;i < MAXCP ;i ++ ) {
1013
1034
if (checkPoint [i ].name == NULL ) {
1014
1035
checkPoint [i ].name = strdup (basename );
@@ -1019,7 +1040,8 @@ FILE * fopencsv(const char * basename, BOOL *newFile)
1019
1040
}
1020
1041
}
1021
1042
if (!foundGap ) {
1022
- printf ("Need to increase MAXCP\n" );
1043
+ printf ("Need to increase MAXCP and rebuild.\n" );
1044
+ exit (1 );
1023
1045
}
1024
1046
return fp ;
1025
1047
}
@@ -1029,7 +1051,7 @@ FILE * fopenext(const char * basename, const char *ext, BOOL *newFile)
1029
1051
FILE * fp = NULL ;
1030
1052
char filename [PATH_MAX ] = {0 };
1031
1053
char * mode = (append )?"a" :"w" ;
1032
- if (resumeCheckPoint && append )
1054
+ if (resumeCheckPoint && append && ! strcmp ( ext , "csv" ) )
1033
1055
mode = "r+" ;
1034
1056
1035
1057
snprintf (filename ,sizeof (filename )- 1 ,
@@ -1085,17 +1107,19 @@ void takeCheckPoint(char *f, myoff_t pos) {
1085
1107
exit (1 );
1086
1108
}
1087
1109
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 );
1090
1114
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 */
1092
1116
if (checkPoint [i ].name ) {
1093
1117
b = fprintf (fp ,"%s %lld\n" ,checkPoint [i ].name ,ftello (checkPoint [i ].fp ));
1094
1118
}
1095
1119
}
1096
1120
fflush (fp );
1097
1121
fclose (fp );
1098
- checkPointTaken = TRUE; /* Use this during testing */
1122
+ checkPointTaken = TRUE; /* This is used during testing */
1099
1123
return ;
1100
1124
}
1101
1125
@@ -1104,6 +1128,9 @@ void takeCheckPoint(char *f, myoff_t pos) {
1104
1128
/* PURPOSE: Work out where we were on the previous execution of the */
1105
1129
/* formatter. It causes us to reset the input file and all of the */
1106
1130
/* 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. */
1107
1134
/*************************************************************************/
1108
1135
myoff_t readCheckPoint (FILE * fp ) {
1109
1136
myoff_t inputOffset = 0 ;
@@ -1117,10 +1144,21 @@ myoff_t readCheckPoint(FILE *fp) {
1117
1144
printf ("Error reading from recovery checkpoint file\n" );
1118
1145
exit (1 );
1119
1146
}
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 );
1121
1152
printf ("Reading from recovery checkpoint.\n" );
1122
- printf ("InputOffset: %lld Processed records: %d\n" ,inputOffset , startingRecords );
1123
1153
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
+ /************************************************************************/
1124
1162
do {
1125
1163
memset (line ,0 ,sizeof (line ));
1126
1164
c = fgets (line ,sizeof (line )- 1 ,fp );
@@ -1130,7 +1168,7 @@ myoff_t readCheckPoint(FILE *fp) {
1130
1168
sscanf (line ,"%s %lld" ,field ,& offset );
1131
1169
checkPoint [i ].name = strdup (field );
1132
1170
checkPoint [i ].offset = offset ;
1133
- if (debugLevel >=1 ) {
1171
+ if (debugLevel >=2 ) {
1134
1172
printf ("Loaded status[%d] for %s as offset %lld\n" ,i ,field ,offset );
1135
1173
}
1136
1174
i ++ ;
0 commit comments