1 #include	"unpthread.h"
2 #include	<thread.h>		/* Solaris threads */
3 
4 #define	MAXFILES	20
5 #define	SERV		"80"	/* port number or service name */
6 
7 struct file {
8   char	*f_name;			/* filename */
9   char	*f_host;			/* hostname or IP address */
10   int    f_fd;				/* descriptor */
11   int	 f_flags;			/* F_xxx below */
12   int	 f_tid;				/* thread ID */
13 } file[MAXFILES];
14 #define	F_CONNECTING	1	/* connect() in progress */
15 #define	F_READING		2	/* connect() complete; now reading */
16 #define	F_DONE			4	/* all done */
17 #define	F_JOINED		8	/* main has pthread_join'ed */
18 
19 #define	GET_CMD		"GET %s HTTP/1.0\r\n\r\n"
20 
21 int		nconn, nfiles, nlefttoconn, nlefttoread;
22 
23 int				ndone;		/* number of terminated threads */
24 pthread_mutex_t	ndone_mutex = PTHREAD_MUTEX_INITIALIZER;
25 pthread_cond_t	ndone_cond = PTHREAD_COND_INITIALIZER;
26 
27 void	*do_get_read(void *);
28 void	home_page(const char *, const char *);
29 void	write_get_cmd(struct file *);
30 
31 int
main(int argc,char ** argv)32 main(int argc, char **argv)
33 {
34 	int			i, maxnconn;
35 	pthread_t	tid;
36 	struct file	*fptr;
37 
38 	if (argc < 5)
39 		err_quit("usage: web <#conns> <IPaddr> <homepage> file1 ...");
40 	maxnconn = atoi(argv[1]);
41 
42 	nfiles = min(argc - 4, MAXFILES);
43 	for (i = 0; i < nfiles; i++) {
44 		file[i].f_name = argv[i + 4];
45 		file[i].f_host = argv[2];
46 		file[i].f_flags = 0;
47 	}
48 	printf("nfiles = %d\n", nfiles);
49 
50 	home_page(argv[2], argv[3]);
51 
52 	nlefttoread = nlefttoconn = nfiles;
53 	nconn = 0;
54 /* include web2 */
55 	while (nlefttoread > 0) {
56 		while (nconn < maxnconn && nlefttoconn > 0) {
57 				/* 4find a file to read */
58 			for (i = 0 ; i < nfiles; i++)
59 				if (file[i].f_flags == 0)
60 					break;
61 			if (i == nfiles)
62 				err_quit("nlefttoconn = %d but nothing found", nlefttoconn);
63 
64 			Pthread_create(&tid, NULL, &do_get_read, &file[i]);
65 			file[i].f_tid = tid;
66 			file[i].f_flags = F_CONNECTING;
67 			nconn++;
68 			nlefttoconn--;
69 		}
70 
71 			/* 4Wait for one of the threads to terminate */
72 		Pthread_mutex_lock(&ndone_mutex);
73 		while (ndone == 0)
74 			Pthread_cond_wait(&ndone_cond, &ndone_mutex);
75 
76 		for (i = 0; i < nfiles; i++) {
77 			if (file[i].f_flags & F_DONE) {
78 				Pthread_join(file[i].f_tid, (void **) &fptr);
79 
80 				if (&file[i] != fptr)
81 					err_quit("file[i] != fptr");
82 				fptr->f_flags = F_JOINED;	/* clears F_DONE */
83 				ndone--;
84 				nconn--;
85 				nlefttoread--;
86 				printf("thread %d for %s done\n", fptr->f_tid, fptr->f_name);
87 			}
88 		}
89 		Pthread_mutex_unlock(&ndone_mutex);
90 	}
91 
92 	exit(0);
93 }
94 /* end web2 */
95 
96 void *
do_get_read(void * vptr)97 do_get_read(void *vptr)
98 {
99 	int					fd, n;
100 	char				line[MAXLINE];
101 	struct file			*fptr;
102 
103 	fptr = (struct file *) vptr;
104 
105 	fd = Tcp_connect(fptr->f_host, SERV);
106 	fptr->f_fd = fd;
107 	printf("do_get_read for %s, fd %d, thread %d\n",
108 			fptr->f_name, fd, fptr->f_tid);
109 
110 	write_get_cmd(fptr);	/* write() the GET command */
111 
112 		/* 4Read server's reply */
113 	for ( ; ; ) {
114 		if ( (n = Read(fd, line, MAXLINE)) == 0)
115 			break;		/* server closed connection */
116 
117 		printf("read %d bytes from %s\n", n, fptr->f_name);
118 	}
119 	printf("end-of-file on %s\n", fptr->f_name);
120 	Close(fd);
121 	fptr->f_flags = F_DONE;		/* clears F_READING */
122 
123 	Pthread_mutex_lock(&ndone_mutex);
124 	ndone++;
125 	Pthread_cond_signal(&ndone_cond);
126 	Pthread_mutex_unlock(&ndone_mutex);
127 
128 	return(fptr);		/* terminate thread */
129 }
130 
131 void
write_get_cmd(struct file * fptr)132 write_get_cmd(struct file *fptr)
133 {
134 	int		n;
135 	char	line[MAXLINE];
136 
137 	n = snprintf(line, sizeof(line), GET_CMD, fptr->f_name);
138 	Writen(fptr->f_fd, line, n);
139 	printf("wrote %d bytes for %s\n", n, fptr->f_name);
140 
141 	fptr->f_flags = F_READING;			/* clears F_CONNECTING */
142 }
143 
144 void
home_page(const char * host,const char * fname)145 home_page(const char *host, const char *fname)
146 {
147 	int		fd, n;
148 	char	line[MAXLINE];
149 
150 	fd = Tcp_connect(host, SERV);	/* blocking connect() */
151 
152 	n = snprintf(line, sizeof(line), GET_CMD, fname);
153 	Writen(fd, line, n);
154 
155 	for ( ; ; ) {
156 		if ( (n = Read(fd, line, MAXLINE)) == 0)
157 			break;		/* server closed connection */
158 
159 		printf("read %d bytes of home page\n", n);
160 		/* do whatever with data */
161 	}
162 	printf("end-of-file on home page\n");
163 	Close(fd);
164 }
165