/* manyfiles.c
 *
 * $Id: manyfiles.c,v 1.8 2000/12/04 03:37:03 alderman Exp $
 *
 */
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>

#include "global.h"

/* This file appears to read several streams using several threads
 * using pthreads without scheduling to guarantee that pthreads
 * does intelligent stuff.  It reads one whole file, then the next...
 */

struct streamdata {		/* data structure for each stream / thread */
	pthread_t t_tid;	/* the thread id */
	int fileno;		/* The filenumber for this stream */
	int pos;		/* The position in the file */
	int fd;			/* The file's file descriptor */
	int done;               /* True when this thread is done. */
	char buf[NUMBYTES+1];   /* The thread's buffer. */
} threaddata[MAX_STREAMS];

void *readStream(void *fnp);
int readMeg(char *buf, int fd);

int main(int argc, char *argv[]) {
	int i = 0;
	int rv;

	pthread_attr_t attr;

	rv = pthread_attr_init(&attr);
	if(rv) {
		perror("Can't init pthread attributes.");
		exit(1);
	} 
	
	for (i = 0; i < MAX_STREAMS; i++) {
		threaddata[i].fileno = i;
		threaddata[i].done = 0;
		printf("Creating thread: %d\n",i);
		rv = pthread_create(&(threaddata[i].t_tid), 
					&attr, readStream, 
					(void *)&(threaddata[i].fileno));
		if(rv) {
			perror("Can't create thread");
			exit(1);
		}
	}
	

	for(i = 0; i < MAX_STREAMS; i++) {
		printf("Waiting for thread: %d\n",i);
		pthread_join(threaddata[i].t_tid, NULL);
	}
	exit(0);
}

void *readStream(void *fnp) {
        int fd, i, rv;
	char *filename;
	char *buf;

	int fn = *(int *)fnp;

	buf = threaddata[fn].buf;

	printf("Reading stream: %d\n", fn);

        memset(buf, '\0', NUMBYTES);

	filename = malloc(256);
	if(filename == NULL) {
		fprintf(stderr, "Can't malloc for filename.\n");
		exit(1);
	}

	rv = snprintf(filename, 255, "bf/%2.2d",fn);
	if(rv != 5) {
		fprintf(stderr, "Can't snprintf for filename.\n");
	}

        fd = open(filename, O_RDONLY, NULL);
        if(fd < 1) {
                printf("error: fd %d on %s\n",fd, filename);
        }

        for (i = 0; i < HOWBIG; i++) {
		printf("Reading chunk %d in stream %d.\n",i, fn);
                if(readMeg(buf, fd) < 0) {
                        fprintf(stderr, "Exiting with i = %d.\n", i);
                        exit(1);
                }
		fprintf (stderr, "Stream %d block %d.\n", fn, i);
        }
	return(0);
}
               

int readMeg(char *buf, int fd) {
        int curByte = 0;
        int rv;
        while(1) {
                rv = read(fd, buf, NUMBYTES - curByte);
                curByte += rv;
                if(rv > 0) {
                        // fprintf(stderr, "Read %d bytes.\n",rv);
                        if (curByte < NUMBYTES) {
                                continue;
                        } else {
				return curByte;
			}
                } else if (rv == 0) {
                        fprintf(stderr, "Read Zero bytes.\n");
                        return rv;
                } else {
                        fprintf(stderr, "Read returned negative: %d.\n", rv);
                        return rv;
                }
        }
        return rv;
}
