/****************************************************************************
 *                                                                          *
 * The contents of this file are subject to the WebStone Public License     *
 * Version 1.0 (the "License"); you may not use this file except in         *
 * compliance with the License. You may obtain a copy of the License        *
 * at http://www.mindcraft.com/webstone/license10.html                      *
 *                                                                          *
 * Software distributed under the License is distributed on an "AS IS"      *
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See      *
 * the License for the specific language governing rights and limitations   *
 * under the License.                                                       *
 *                                                                          *
 * The Original Code is WebStone 2.5.                                       *
 *                                                                          *
 * The Initial Developer of the Original Code is Silicon Graphics, Inc.     *
 * and Mindcraft, Inc.. Portions created by Silicon Graphics. and           *
 * Mindcraft. are Copyright (C) 1995-1998 Silicon Graphics, Inc. and        *
 * Mindcraft, Inc. All Rights Reserved.                                     *
 *                                                                          *
 * Contributor(s): ______________________________________.                  *
 *                                                                          *
 * @(#) bench.c 2.4@(#)                                                     *
 ***************************************************************************/


#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>

#ifndef WIN32
#include <netdb.h>
#include <sys/param.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/errno.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#else /* defined(WIN32) */
#include <windows.h>
#include <process.h>
#include <time.h>
#include <winsock.h>
#endif /* WIN32 */

#include "sysdep.h"
#include "bench.h"

/* 
 * parse_file_list()
 * given a filename, a pointer to a page list, and pointers to integers
 * for the number of pages and the number of files, parse its contents.
 */

void
parse_file_list (FILE *fp, page_list_t *page_list, 
		 long int *num_of_pages, long int *num_of_files)
{
	int		filenum;
	int		returnval;
	int		loadnum;
	char	a_line[BUFSIZ];
	char	tempbuf[BUFSIZ];
	char	*textvalue;
	char	*tmpptr;
	int		numfiles = 1;
	int		numpages = 0;
	int		maxpages = *num_of_pages;
	page_list_t	*pp;
	int		j;
	extern int	randomize;

	extern int		haveproxyserver;
	extern NETPORT	portnum;

	TRACE("parse_file_list(): entering\n");
	/* 
	 * GRAB A LINE. FORMAT IS: URL WEIGHTINGFACTOR 
	 * EXAMPLE: http://www/file.html 1
	 */
	D_PRINTF( "About to parse UILs and weights.\n" );
	while(fgets(a_line, BUFSIZ, fp) != NULL)
	{
		textvalue = a_line;
		/* If we're reading from a socket, ENDTOKEN ends the list */
		if (!strcmp(textvalue, ENDTOKEN))
		{
			fflush(fp);
			break;
		}

		/* check for comments */
		if ((tmpptr = strchr(textvalue, '#')) != NULL)
		{
			/* throw out anything after a '#' */
			D_PRINTF( "Stripping comment from line: %s\n", textvalue );
			returnval = strcspn(textvalue, "#");
			D_PRINTF( "Found first # at %d\n", returnval );
			if (returnval == 0) 
				continue;
			for (tmpptr--; isspace(*tmpptr) && tmpptr != textvalue; tmpptr--);
			if (tmpptr == textvalue)
				continue;	/* line was just white space and comment */
		}
		for (tmpptr = a_line; *tmpptr && isspace(*tmpptr); tmpptr++);
		if (*tmpptr == '\0')
			continue;	/* line was white space only */

		if (numpages >= MAXNUMOFPAGES)
			errexit("Out of space in parse_file_list()\n");

		pp = &page_list[numpages];
		for (j=0; j<MAXNUMOFFILES; j++)
		{
			pp->servername[j] = (char *)mymalloc(URL_SIZE);
			pp->filename[j] = (char *)mymalloc(URL_SIZE);
		}

		D_PRINTF( "Processing page %ld\n", numpages );
		loadnum = 0;

		if (textvalue != NULL) /* is there more? */
		{
			/* check for weighting factor */
			D_PRINTF( "Setting page values from: %s\n", textvalue );
			returnval = sscanf(textvalue, "%s%d", tempbuf, &loadnum);
			D_PRINTF( "Scan for weighting returns %d, %d\n", returnval, 
					loadnum );
			if (returnval == EOF || loadnum <= 0)
				errexit("parse_file_list(): Entry %d in URL list is corrupt\n",
					numpages);
			else if (returnval == 1)
				pp->load_num = 1;
			else
			{
				pp->load_num = loadnum;
				randomize = 1;
			}
			D_PRINTF( "Setting load=%d for line: %s\n", pp->load_num, 
					textvalue );

			/* placeholder for grouping multiple files 
			 * onto one page 
			 */
			pp->num_of_files = 1;
			filenum = 0;

			textvalue = tempbuf;
			D_PRINTF( "Line is now: %s\n", textvalue );

			/* 
			 * if we've got a proxy server, we'll assume 
			 * that the remaining text is a valid URL, and 
			 * stuff it into 
			 * page_list[numpages].filename[filenum]
			 * Otherwise, we'll have to parse it out.
			 */
			if (haveproxyserver)
			{
				pp->servername[filenum] = NULL;
				pp->port_number[filenum] = 0;
				strcpy(pp->filename[filenum], textvalue);
			}
			else /* no proxy server, so we have to parse it out... */
			{
				/* try http://server(:port)/file */
				D_PRINTF( "Trying http://server(:port)/filename\n" );
				returnval = sscanf(textvalue, "http://%[^/]%s",  tempbuf, 
									a_line);
				/* check server string for :port */
				if (returnval != 0 && returnval != EOF) 
				{
					D_PRINTF( "Setting filename %s\n", a_line );
					strcpy(pp->filename[filenum], a_line);

					D_PRINTF( "Checking %s for :portnumber\n", tempbuf );
					returnval = sscanf(tempbuf, "%[^:]:%d", a_line,
							&pp->port_number[filenum]);

					if (returnval < 2)
						pp->port_number[filenum] = portnum;
					if (returnval == EOF)
						pp->servername[filenum] = NULL;
					else
					{
						D_PRINTF( "Port number %d, setting server %s\n", 
								pp->port_number[filenum], a_line );
						strcpy(pp->servername[filenum], a_line);
					}

					D_PRINTF( "Server %s, port number %d\n", 
							pp->servername[filenum],
							pp->port_number[filenum] );
				}
				else /* no good - try straight filename */
				{
					pp->port_number[filenum] = portnum;
					D_PRINTF( "Trying filename, returnval=%d\n",returnval );
					pp->servername[filenum] = NULL;
					/*
					 * On some systems trying to printf("%s") a NULL 
					 * will cause a segmentation fault.
					 */
					D_PRINTF( "Server %s, port number %d\n", 
								D_STRVAL(pp->servername[filenum]),
										 pp->port_number[filenum] );
					returnval = sscanf(textvalue, "%s", a_line);
					D_PRINTF( "Scan returned filename %s\n", a_line );

					strcpy(pp->filename[filenum], a_line);
				} 
			} 

			D_PRINTF( "Done parsing line\n" );
			D_PRINTF( "Got server %s, port %d, file %s, returnval %d\n",
						D_STRVAL(pp->servername[filenum]),
						pp->port_number[filenum],
						D_STRVAL(pp->filename[filenum]), returnval );
		} 
		numpages++;
	} 

	if (numpages < 1)
		(void) returnerr("No files are specified by filelist\n");

	*num_of_pages = numpages;
	*num_of_files = numfiles;
	TRACE("parse_file_list(): leaving: returning %ld pages and %ld files\n", 
			numpages, numfiles);
}


long int
load_percent(page_list_t *page_list, long int number_of_pages)
{
	int 	 i;
	long int index_number = 0;

	TRACE("load_percent(): entering\n");
	for (i = 0; i < number_of_pages; i++)
		index_number += page_list[i].load_num;

	if (index_number > RAND_MAX)
		errexit("Sum of weights in filelist greater than RAND_MAX (%ld)\n",
			RAND_MAX);

	TRACE( "load_percent(): returning %d\n", index_number );
	return index_number;
}
