/*
 * this converts data in the trace to ascii form
 */

#include <stdio.h>
#include "iotrace.h"

main(argc, argv)
int argc;
char *argv[];
{
	char *tfile = "tracerecs";
	FILE *fp, *fopen();
	struct tracerecord record;
	unsigned name;
	unsigned time = 0;

	if (argc >= 2)
		tfile = argv[1];

	if (strcmp(tfile, "-") == 0) 
		fp = stdin;
	else 
		fp = fopen(tfile, "r");

	if (fp==NULL) {
		fprintf(stderr, "Can't open %s.\n", tfile);
		exit(1);
	}

	while (fread(&record, sizeof(struct tracerecord), 1, fp) != 0)  {

		/* last four chars of file name is in count field most of the
		time */
		name = (unsigned)(record.count);

		printf("pid = %d fileid = (%d, %d) time = %.2fms\t", 
			record.pid, record.i_dev, record.i_num, 
			(record.time - time) * 40.0 / 1e6 );

		time = record.time;

		switch (record.op) {

	case MYTRACE_REPLACE:
		printf("MYTRACE_REPLACE: decision dev= %d  blkno= %d  suggested dev= %d blkno= %d\n",
			record.i_num, record.i_dev, record.offset, record.count);
		break;
	case MYTRACE_CANDIDATE:
		printf("MYTRACE_CANDIDATE: decision dev= %d  blkno= %d \n",
			record.i_num, record.i_dev);
		break;

	case MYTRACE_RWEND:
		printf("%s: blkno = %d  realcount = %d sec = %d  usec = %d\n",
			"MYTRACE_RWEND", record.i_num, record.i_dev, 
				record.offset, record.count);
		break;

	case MYTRACE_RDHIT:
	case MYTRACE_BWREND:
	default:
		printf("%s: dev = %d  blkno = %d  sec = %d  usec = %d\n",
			record.op == MYTRACE_RDHIT ? "MYTRACE_RDHIT" : 
			record.op == MYTRACE_BWREND? "MYTRACE_BWREND" : 
			"unknown", 
			record.i_dev, record.i_num, record.offset, record.count);
		break;

	case MYTRACE_RDBEGIN2:
	case MYTRACE_RDBEGIN:
		printf("%s: dev = %d  blkno = %d  sec = %d  usec = %d\n",
			record.op == MYTRACE_RDBEGIN ? "MYTRACE_RDBEGIN" : "MYTRACE_RDBEGIN2", 
			record.i_dev, record.i_num, record.offset, record.count);
		break;

	case MYTRACE_RARDBEGIN:
		printf("MYTRACE_RARDBEGIN: dev = %d  blkno = %d  sec = %d  usec = %d\n",
			record.i_dev, record.i_num, record.offset, record.count);
		break;

	case MYTRACE_RDEND2:
	case MYTRACE_RDEND:
		printf("%s: dev = %d  blkno = %d  sec = %d  usec = %d\n",
			record.op == MYTRACE_RDEND ? "MYTRACE_RDEND" : "MYTRACE_RDEND2",
			record.i_dev, record.i_num, record.offset, record.count);
		break;

	case MYTRACE_BUSYWAIT:
		printf("MYTRACE_BUSYWAIT: dev = %d  blkno = %d  sec = %d  usec = %d\n",
			record.i_dev, record.i_num, record.offset, record.count);
		break;

	case MYTRACE_BUSYEND:
		printf("MYTRACE_BUSYEND: dev = %d  blkno = %d  sec = %d  usec = %d\n",
			record.i_dev, record.i_num, record.offset, record.count);
		break;

	case MYTRACE_TIMESTAMP:
		printf("begin of new records: %d.%d\n",
			record.count, record.offset);
		break;

	case MYTRACE_OPEN:
		printf("OPEN: fname = *%c%c%c%c, mode = 0x%x\n",
                        name>>24, (name>>16)&0xff, (name>>8)&0xff, name & 0xff,
			record.offset);
		break;
	case MYTRACE_CREATE:
		printf("CREATE: fname = *%c%c%c%c, mode = 0x%x\n",
                        name>>24, (name>>16)&0xff, (name>>8)&0xff, name & 0xff,
			record.offset);
		break;
	case MYTRACE_FDOPEN:
		printf("OPEN-FD: fname = *%c%c%c%c, mode = 0x%x\n",
                        name>>24, (name>>16)&0xff, (name>>8)&0xff, name & 0xff,
			record.offset);
		break;
	case MYTRACE_FDCREATE:
		printf("CREATE-FD: fname = *%c%c%c%c, mode = 0x%x\n",
                        name>>24, (name>>16)&0xff, (name>>8)&0xff, name & 0xff,
			record.offset);
		break;

	case MYTRACE_READ:
		printf("READ: offset = %d, count = %d\n",
			record.offset, record.count);
		break;
	case MYTRACE_WRITE:
		printf("WRITE: offset = %d, count = %d\n",
			record.offset, record.count);
		break;

	case MYTRACE_LSEEK:
		printf("LSEEK: sbase = %d, off = %d\n",
			record.offset, record.count);
		break;
	case MYTRACE_CLOSE:
		printf("CLOSE: fd = %d\n", record.offset);
		break;

	case MYTRACE_FCNTL:
		printf("FCNTL: cmd = 0x%x, arg = %d\n",
			record.offset, record.count);
		break;

	case MYTRACE_UNLINK:
		printf("UNLINK: fname = *%c%c%c%c\n",
                        name>>24, (name>>16)&0xff, (name>>8)&0xff, name & 0xff);
		break;

	case MYTRACE_FTRUNCATE:
		printf("FTRUNCATE: fd = %d, length = %d\n",
			record.count, record.offset);
		break;
	case MYTRACE_TRUNCATE:
		printf("TRUNCATE: name= *%c%c%c%c, length = %d\n",
                        name>>24, (name>>16)&0xff, (name>>8)&0xff, name & 0xff,
			record.offset);
		break;
	case MYTRACE_STAT:
		printf("STAT: fname= *%c%c%c%c, ub = 0x%x\n",
                        name>>24, (name>>16)&0xff, (name>>8)&0xff, name & 0xff,
			record.offset);
		break;

	case MYTRACE_FORK:
		printf("FORK: PROCESS ID = %d\n", record.pid);
		break;
	case MYTRACE_EXIT:
		printf("EXIT: PROCESS ID = %d\n", record.pid);
		break;

	case MYTRACE_BREADHIT:
		printf("BREAD-HIT: blkno = %d, size= %d\n",
			record.offset, record.count);
		break;
	case MYTRACE_BREADMISS:
		printf("BREAD-MISS: blkno = %d, size = %d\n",
			record.offset, record.count);
		break;
		}
	}

}
