00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "config.h"
00019
00020 #include <math.h>
00021 #include <time.h>
00022 #include <sys/types.h>
00023 #include <sys/param.h>
00024 #include <string.h>
00025 #include <unistd.h>
00026 #include <float.h>
00027 #include <assert_pp.h>
00028
00029 #include "instrumentation.h"
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #define IP_HISTORY_START_ADD(ip, amount) \
00041 ((ip)->ip_History.start + (amount)) % (ip)->ip_History.length
00042
00043
00044
00045
00046 static const char *DEFAULT_INSTRUMENTATION_FILE_NAME =
00047 PACKAGE "-instrumentation-%d.txt";
00048
00049 struct iInstrumentationData instrumentation_data;
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 static void iInitPoint(struct iPoint *ip)
00062 {
00063 require(ip != NULL);
00064 require(ip->ip_Name != NULL);
00065
00066
00067 ip->ip_Minimum = FLT_MAX;
00068 ip->ip_Maximum = FLT_MIN;
00069 if( ip->ip_Format == NULL )
00070 {
00071 ip->ip_Format = "%10.2f ";
00072 }
00073
00074 if( ip->ip_Succ == NULL )
00075 {
00076 if( instrumentation_data.iid_FirstPoint == NULL )
00077 {
00078 instrumentation_data.iid_FirstPoint =
00079 &instrumentation_data.iid_NullPoint;
00080 }
00081 ip->ip_Succ = instrumentation_data.iid_FirstPoint;
00082 instrumentation_data.iid_FirstPoint = ip;
00083 }
00084 }
00085
00086 void iPostFloatData(struct iPoint *ip, double value)
00087 {
00088 require(ip != NULL);
00089 require(ip->ip_Name != NULL);
00090
00091
00092 if( ip->ip_Count == 0 )
00093 {
00094 iInitPoint(ip);
00095 }
00096
00097 if( ip->ip_History.data != NULL )
00098 {
00099 if( ip->ip_Count >= ip->ip_History.length )
00100 {
00101 ip->ip_History.lost += 1;
00102 if( ip->ip_Flags & IPF_DROP_HISTORY_START )
00103 {
00104 ip->ip_History.data[ip->ip_History.start] = value;
00105 ip->ip_History.start = IP_HISTORY_START_ADD(ip, 1);
00106 }
00107 }
00108 else
00109 {
00110 ip->ip_History.data[ip->ip_Count] = value;
00111 }
00112 }
00113
00114 ip->ip_Count += 1;
00115 ip->ip_Total += value;
00116 if( value < ip->ip_Minimum )
00117 {
00118 ip->ip_Minimum = value;
00119 }
00120 if( value > ip->ip_Maximum )
00121 {
00122 ip->ip_Maximum = value;
00123 }
00124 }
00125
00126 void iPrintPoint(FILE *file, struct iPoint *ip)
00127 {
00128 double stddev = 0.0;
00129
00130 require(file != NULL);
00131 require(ip != NULL);
00132 require(ip->ip_Name != NULL);
00133 require(ip->ip_Format != NULL);
00134 require(ip->ip_Count > 0);
00135 require((ip->ip_Flags & ~IPF_MASK) == 0);
00136
00137
00138 if( ip->ip_History.data != NULL )
00139 {
00140 double minimum = FLT_MAX, maximum = FLT_MIN, total = 0.0, avg;
00141 double stddev_total = 0.0;
00142 int lpc;
00143
00144
00145 for( lpc = 0;
00146 (lpc < ip->ip_Count) && (lpc < ip->ip_History.length);
00147 lpc++ )
00148 {
00149 double value = ip->ip_History.data[IP_HISTORY_START_ADD(ip, lpc)];
00150
00151 if( value < minimum )
00152 {
00153 minimum = value;
00154 }
00155 if( value > maximum )
00156 {
00157 maximum = value;
00158 }
00159 total += value;
00160 }
00161 avg = total / ((double)lpc);
00162 for( lpc = 0;
00163 (lpc < ip->ip_Count) && (lpc < ip->ip_History.length);
00164 lpc++ )
00165 {
00166 double value = ip->ip_History.data[IP_HISTORY_START_ADD(ip, lpc)];
00167
00168 stddev_total += (value - avg) * (value - avg);
00169 }
00170 stddev = sqrt(stddev_total / ((double)lpc));
00171
00172 fprintf(file,
00173 "%s: "
00174 "count=%d/%qd total=%f min=%f max=%f avg=%f stddev=%f '%s'\n",
00175 ip->ip_Name,
00176 lpc, ip->ip_Count,
00177 total,
00178 minimum,
00179 maximum,
00180 avg,
00181 stddev,
00182 ip->ip_Description != NULL ? ip->ip_Description : "");
00183
00184 if( ip->ip_Flags & IPF_PRINT_HISTORY )
00185 {
00186 int lpc;
00187
00188 if( ip->ip_History.lost > 0 )
00189 {
00190 fprintf(file,
00191 "\tLost %d data points at the start\n",
00192 ip->ip_History.lost);
00193 }
00194 for( lpc = 0;
00195 (lpc < ip->ip_Count) && (lpc < ip->ip_History.length);
00196 )
00197 {
00198 int row_count;
00199
00200 fprintf(file, "\t");
00201 for( row_count = 0;
00202 (row_count < 5) &&
00203 (lpc < ip->ip_Count) &&
00204 (lpc < ip->ip_History.length);
00205 row_count++, lpc++ )
00206 {
00207 fprintf(file,
00208 ip->ip_Format,
00209 ip->ip_History.data[IP_HISTORY_START_ADD(ip,
00210 lpc)]);
00211 }
00212 fprintf(file, "\n");
00213 }
00214 }
00215 }
00216
00217 else
00218 {
00219 fprintf(file,
00220 "%s: count=%qd total=%f min=%f max=%f avg=%f '%s'\n",
00221 ip->ip_Name,
00222 ip->ip_Count,
00223 ip->ip_Total,
00224 ip->ip_Minimum,
00225 ip->ip_Maximum,
00226 ip->ip_Total / ((double)ip->ip_Count),
00227 ip->ip_Description != NULL ? ip->ip_Description : "");
00228 }
00229 }
00230
00231 void iPrintPoints(FILE *file)
00232 {
00233 struct iPoint *ip;
00234
00235 require(file != NULL);
00236
00237
00238 ip = instrumentation_data.iid_FirstPoint;
00239 while( (ip != NULL) && (ip != &instrumentation_data.iid_NullPoint) )
00240 {
00241 iPrintPoint(file, ip);
00242 ip = ip->ip_Succ;
00243 }
00244 }
00245
00246 void iPrintPointsAtExit(void)
00247 {
00248
00249 if( instrumentation_data.iid_FirstPoint != NULL )
00250 {
00251 const char *file_name;
00252 FILE *file;
00253
00254
00255 if( ((file_name = getenv(INSTR_FILE_NAME_ENV)) != NULL) ||
00256 ((file_name = instrumentation_data.iid_OutputFileName) != NULL) )
00257 {
00258 if( strcmp("-", file_name) == 0 )
00259 {
00260 file = stdout;
00261 }
00262 else
00263 {
00264 file = fopen(file_name, "a");
00265 }
00266 }
00267
00268 else
00269 {
00270 static char formatted_filename[PATH_MAX];
00271
00272 sprintf(formatted_filename,
00273 DEFAULT_INSTRUMENTATION_FILE_NAME,
00274 getpid());
00275 file = fopen(formatted_filename, "a");
00276 }
00277
00278
00279 if( file != NULL )
00280 {
00281 time_t cl;
00282
00283 cl = time(NULL);
00284 fprintf(file, "\n** %s", ctime(&cl));
00285 iPrintPoints(file);
00286 fclose(file);
00287 }
00288 else
00289 {
00290 fprintf(stderr,
00291 "Warning: unable to create instrumentation file.\n");
00292 }
00293
00294
00295 instrumentation_data.iid_FirstPoint = NULL;
00296 }
00297 }