1/* 2 * merge.c: Program to take mutiple strand format logfiles, sort them, 3 * merge them, and prepend information to the final logfile. 4 * 5 * Algorithm: 6 * Copy all the negative events at the beginning of the logfiles to a 7 * temporary header file. 8 * Use the unix sort command to sort all the logfiles. 9 * Analyze the data, ignoring all events that are not > 0. 10 * Print to stdout the results of the analyzation, the header file, 11 * and the sorted log entries. 12 * 13 * Modified Summer 1990 by James Arthur Kohl 14 * to combine count collection more efficiently. 15 * 16 * Now it's REAL fast! 17 */ 18#include <stdio.h> 19#include <stdlib.h> 20#include <malloc.h> 21#include <ctype.h> /* for calling isdigit() */ 22#include "alog_evntdfs.h" /* Logfile definitions */ 23 24#define C_DATA_LEN 50 25 26#define DO_NEGATIVE 1 27#define IGNORE_NEGATIVE 2 28 29struct log_entry 30{ 31 int proc_id; 32 int task_id; 33 int event; 34 int i_data; 35 char c_data[C_DATA_LEN]; 36 int time_slot; 37 unsigned long time; 38}; 39 40struct list_struct 41{ 42 struct log_entry entry; 43 struct list_struct *next; 44} *log_table; 45 46struct list_struct *log_ptr; 47 48int entry_tot; 49 50main(argc,argv) 51int argc; 52char *argv[]; 53{ 54 FILE *headerfp; 55 56 char headerfile[255]; 57 58 int pid; 59 60 if ( argc <= 1 ) 61 usage(); 62 63 pid = getpid(); 64 65 sprintf(headerfile,"/usr/tmp/log.header.%d",pid); 66 67 if ( (headerfp=fopen(headerfile,"w")) == NULL ) 68 { 69 fprintf(stderr,"merge: unable to create temp file %s.\n",headerfile); 70 exit(0); 71 } 72 73 combine_files(argc,argv,headerfp); 74 75 if ( (headerfp=fopen(headerfile,"r")) == NULL ) 76 { 77 fprintf(stderr,"merge: unable to read temp file %s.\n",headerfile); 78 exit(0); 79 } 80 81 fprintf(stderr,"Analyzing.\n"); 82 analyze(headerfp); 83 84 fclose(headerfp); 85 unlink(headerfile); 86} /* main */ 87 88 89combine_files(argc,argv,headerfp) 90int argc; 91char *argv[]; 92FILE *headerfp; 93{ 94 FILE *in; 95 96 struct list_struct **files; 97 struct list_struct *last; 98 struct list_struct *ptr; 99 100 struct log_entry *entry; 101 102 unsigned long min_time; 103 104 int min_event; 105 int min_slot; 106 int min; 107 108 int all_eof; 109 int eof_flag; 110 int negflag; 111 int num; 112 int i; 113 114 num = argc - 1; 115 116 if ( (files=(struct list_struct **) 117 malloc(num * sizeof(struct list_struct *))) == NULL ) 118 { 119 fprintf(stderr,"merge: unable to allocate input data array.\n"); 120 exit(0); 121 } 122 123 for ( i=0 ; i < num ; i++ ) 124 { 125 fprintf(stderr,"Reading %s\n",argv[i+1]); 126 127 if ( (in=fopen(argv[i+1],"r")) == NULL ) 128 { 129 fprintf(stderr,"merge: unable to read data file %s.\n",argv[i+1]); 130 exit(0); 131 } 132 133 if ( (files[i]=(struct list_struct *) 134 malloc(sizeof(struct list_struct))) == NULL ) 135 { 136 fprintf(stderr,"merge: unable to allocate list struct.\n"); 137 exit(0); 138 } 139 140 ptr = files[i]; 141 142 last = NULL; 143 144 do 145 { 146 read_logentry(in,&(ptr->entry),DO_NEGATIVE); 147 148 if ( !(eof_flag=feof(in)) ) 149 { 150 if ( (ptr->next=(struct list_struct *) 151 malloc(sizeof(struct list_struct))) == NULL ) 152 { 153 fprintf(stderr,"merge: unable to allocate list struct.\n"); 154 exit(0); 155 } 156 157 last = ptr; 158 159 ptr = ptr->next; 160 } 161 162 else 163 { 164 if ( last != NULL ) 165 last->next = NULL; 166 167 else 168 files[i] = NULL; 169 170 free(ptr); 171 ptr = NULL; 172 } 173 } 174 while ( !eof_flag ); 175 176 fclose(in); 177 } 178 179 fprintf(stderr,"Sorting.\n"); 180 181 all_eof = 0; 182 183 do 184 { 185 negflag = 0; 186 187 for ( i=0 ; i < num ; i++ ) 188 { 189 if ( files[i] == NULL ) 190 continue; 191 192 entry = &(files[i]->entry); 193 194 if ( entry->event < 0 ) 195 { 196 negflag++; 197 198 fprintf(headerfp,"%d %d %d %d %d %lu %s\n",entry->event, 199 entry->proc_id,entry->task_id,entry->i_data, 200 entry->time_slot,entry->time,entry->c_data); 201 202 files[i] = files[i]->next; 203 204 if ( files[i] == NULL ) 205 all_eof++; 206 } 207 } 208 } 209 while ( negflag && all_eof < num ); 210 211 fclose(headerfp); 212 213 log_table = log_ptr = NULL; 214 215 entry_tot = 0; 216 217 while ( all_eof < num ) 218 { 219 min_event = 0; 220 min_time = 0; 221 min_slot = 0; 222 223 min = -1; 224 225 for ( i=0 ; i < num ; i++ ) 226 { 227 if ( files[i] == NULL ) 228 continue; 229 230 entry = &(files[i]->entry); 231 232 if ( 233 (entry->time_slot == min_slot && entry->time < min_time) 234 || entry->time_slot < min_slot 235 || min == -1 236 || (entry->time_slot == min_slot && entry->time == min_time 237 && entry->event < min_event) 238 ) 239 { 240 min_event = entry->event; 241 min_time = entry->time; 242 min_slot = entry->time_slot; 243 244 min = i; 245 } 246 } 247 248 if ( log_ptr == NULL ) 249 { 250 log_table = log_ptr = files[min]; 251 252 files[min] = files[min]->next; 253 } 254 255 else 256 { 257 log_ptr->next = files[min]; 258 259 files[min] = files[min]->next; 260 261 log_ptr = log_ptr->next; 262 } 263 264 log_ptr->next = NULL; 265 266 entry_tot++; 267 268 if ( files[min] == NULL ) 269 all_eof++; 270 } 271 272 fprintf(stderr, " %d total entries\n", entry_tot); 273} 274 275 276usage() 277{ 278 fprintf(stderr,"mergelogs: mergelogs infile1 infile2 ...\n"); 279 fprintf(stderr," writes to stdout\n"); 280 281 exit(0); 282} 283 284 285/* analyze: At this point, we have one large sorted file called :tname:. 286 * We want to prepend certain data to it. 287 * We also want to prepend the data from the file pointed to 288 * by :headerfp:. 289 * See balance:/usr/local/trace/README for info. 290 * 291 */ 292analyze(headerfp) 293FILE *headerfp; 294{ 295 struct log_entry *entry; 296 297 int proc_tot, task_tot, time_slot_tot, event_tot; 298 int i; 299 300 get_counts(&proc_tot,&task_tot,&event_tot,&time_slot_tot); 301 302 fprintf(stderr, " %d separate processors\n", proc_tot); 303 fprintf(stderr, " %d separate tasks\n", task_tot); 304 fprintf(stderr, " %d event types\n", event_tot); 305 306 fprintf(stdout,"%d %d %d %d %d %lu\n",NUM_EVENTS,0,0,entry_tot,0,0L); 307 fprintf(stdout,"%d %d %d %d %d %lu\n",NUM_PROCS,0,0,proc_tot,0,0L); 308 fprintf(stdout,"%d %d %d %d %d %lu\n",NUM_TASKS,0,0,task_tot,0,0L); 309 fprintf(stdout,"%d %d %d %d %d %lu\n",NUM_EVTYPES,0,0,event_tot,0,0L); 310 fprintf(stdout,"%d %d %d %d %d %lu\n",START_TIME,0,0,0,0, 311 log_table->entry.time); 312 fprintf(stdout,"%d %d %d %d %d %lu\n",END_TIME,0,0,0,0, 313 log_ptr->entry.time); 314 fprintf(stdout,"%d %d %d %d %d %lu\n",NUM_CYCLES,0,0,time_slot_tot,0,0L); 315 316 dump_header(headerfp); 317 318 log_ptr = log_table; 319 320 while ( log_ptr != NULL ) 321 { 322 entry = &(log_ptr->entry); 323 324 fprintf(stdout,"%d %d %d %d %d %lu %s\n",entry->event, 325 entry->proc_id,entry->task_id,entry->i_data, 326 entry->time_slot,entry->time,entry->c_data); 327 328 log_ptr = log_ptr->next; 329 } 330} /* analyze */ 331 332 333dump_header(headerfp) 334FILE *headerfp; 335{ 336 char buf[512]; 337 int len; 338 339 do 340 { 341 if ( len=fread(buf,sizeof(char),512,headerfp) ) 342 fwrite(buf,sizeof(char),len,stdout); 343 } 344 while ( !feof(headerfp) && len ); 345} /* dump_header */ 346 347 348read_logentry(fp,table,do_negs) 349FILE *fp; 350struct log_entry *table; 351int do_negs; 352{ 353 char buf[81]; 354 char *cp; 355 356 int i; 357 358 do 359 { 360 fscanf(fp,"%d %d %d %d %d %lu", 361 &(table->event),&(table->proc_id),&(table->task_id), 362 &(table->i_data),&(table->time_slot),&(table->time)); 363 364 cp = table->c_data; 365 366 i = 0; 367 368 do 369 { 370 fscanf(fp,"%c",cp); 371 } 372 while ( *cp == ' ' || *cp == '\t' ); 373 374 i++; 375 376 while ( *cp != '\n' && i < C_DATA_LEN ) 377 { 378 fscanf(fp,"%c",++cp); 379 380 i++; 381 } 382 383 *cp = '\0'; 384 385 /* 386 if ( !feof(fp) && table->event == 0 ) 387 fprintf(stderr,"0 reading in.\n"); 388 */ 389 } 390 while( table->event < 0 && do_negs == IGNORE_NEGATIVE && !feof(fp) ); 391} 392 393 394get_counts(ptot,ttot,etot,tstot) 395int *ptot,*ttot,*etot,*tstot; 396{ 397 struct list_struct *ptr; 398 399 struct log_entry *entry; 400 struct log_entry *last; 401 402 int *p, *t, *e; 403 404 int flag; 405 int val; 406 int i,j; 407 408 if ( (p=(int *)malloc(sizeof(int) * entry_tot)) == NULL ) 409 { 410 fprintf(stderr,"Not enough memory.\n"); 411 exit(0); 412 } 413 414 if ( (t=(int *)malloc(sizeof(int) * entry_tot)) == NULL ) 415 { 416 fprintf(stderr,"Not enough memory.\n"); 417 exit(0); 418 } 419 420 if ( (e=(int *)malloc(sizeof(int) * entry_tot)) == NULL ) 421 { 422 fprintf(stderr,"Not enough memory.\n"); 423 exit(0); 424 } 425 426 for ( i=0 ; i < entry_tot ; i++ ) 427 { 428 p[i] = t[i] = e[i] = 0; 429 } 430 431 *ptot = *ttot = *etot = 0; 432 433 *tstot = 1; 434 435 ptr = log_table; 436 437 last = NULL; 438 439 while ( ptr != NULL ) 440 { 441 entry = &(ptr->entry); 442 443 flag = 0; 444 445 val = entry->proc_id; 446 447 for ( j=0 ; j < *ptot && !flag ; j++ ) 448 { 449 if ( p[j] == val ) 450 flag++; 451 } 452 453 if ( !flag ) 454 { 455 p[(*ptot)++] = val; 456 } 457 458 flag = 0; 459 460 val = entry->task_id; 461 462 for ( j=0 ; j < *ttot && !flag ; j++ ) 463 { 464 if ( t[j] == val ) 465 flag++; 466 } 467 468 if ( !flag ) 469 { 470 t[(*ttot)++] = val; 471 } 472 473 flag = 0; 474 475 val = entry->event; 476 477 for ( j=0 ; j < *etot && !flag ; j++ ) 478 { 479 if ( e[j] == val ) 480 flag++; 481 } 482 483 if ( !flag ) 484 { 485 e[(*etot)++] = val; 486 } 487 488 /* printf("tstot=%d *tstot=%d\n",tstot,*tstot); */ 489 if ( (last != NULL) && (entry->time_slot != last->time_slot) ) 490 *tstot = *tstot + 1; 491 /* (*tstot)++; */ 492 493 last = entry; 494 495 ptr = ptr->next; 496 } 497 return(0); 498} 499