/*
 * Test program to exercise the message_service routines.
 *
 * Usage: mstverify action [repeat] [pool-size]
 *
 * A service thread is created with the action argument as it's info argument.
 * 
 * The first letter of action string determines action of service thread:
 *
 *    a - write "hello world" to link and exit
 *    b - read message from link and write status
 *    c - recursively connect to service routine, arg it remainder of action
 *        string.
 *    d - Enter write loop, remainder of info argument is write size
 *	  as a decimal number.  Write's continue until error occurs.
 *    e - Close connection.
 *
 * Repeat count is number of reads to perform if positive and connects to
 * perform is negative.
 */
#include "pthread_1c_np.h"
#include "tutil.h"
#include <stdio.h>
#include <stdlib.h>
#ifndef D_SIZE
#define D_SIZE 24
#endif

#include "message_service.h"
int (*tlog_putlog_cb) ( int, char *, ... );
int tlog_putlog(int, char *, ...), tlog_init();
/***************************************************************************/
/* Define service thread routine for repeated connect test, simply exit.
 * (also verifies multiple service definitions).
 */
int howdy_world ( mst_link_t link, char *port, char *info, int ndx, int avail )
{
   int status, length, length2;
   char message[128], buffer[1000];

   status = mst_close (link );
   return status;
}
/***************************************************************************/
/* Primary service thread (hello).
 */
int hello_world ( mst_link_t link, char *port, char *info, int ndx, int avail )
{
   int wsize, status, length, length2;
   char message[128], buffer[1000];
   mst_link_t link2;
printf("/hello_world/ connection %s/%d avail: %d, info: '%s'\n", port,
 ndx, avail, info );

    switch ( *info ) {
      case 'a':		/* write test */
	status = mst_write ( link, "hello world", 12, &length );
   	mst_format_error ( status, message, sizeof(message) );
   	printf("/hello_world/ status of write: %d/%d -> '%s' (%d)\n", status, 
		length, message, message );
	break;
      case 'b'		/* read test */:
	status = mst_read ( link, buffer, sizeof(buffer), &length );
   	mst_format_error ( status, message, sizeof(message) );
   	printf("/hello_world/ status of read: %d/%d -> '%s'\n", status, 
		length, message );
	break;
      case 'c':		/* recursion test */
	status = mst_connect ( "hello", &info[1], &link2 );
	printf("/hello_world/ status of subconect: %d, (%d)\n", status,
		message );
	status = mst_read ( link2, buffer, sizeof(buffer), &length2 );
	printf("/hello_wrold/ staus of subread: %d %d\n", status, length2 );
	if ( status = MST_NORMAL ) {
		status = mst_write ( link, buffer, length2, &length );
	    printf("/hello_world/ status of subwrite: %d %d\n", status, length );
	}
	break;
	case 'd':	/* multiple write test */
	    tu_strcpy ( buffer, "Did this sink in yet" );
	    wsize = tu_strlen ( buffer );
	    if ( info[1] ) wsize = atoi(&info[1]);
	    while ( MST_NORMAL == (status =mst_write ( link, buffer, wsize,
		&length )) );
   	    mst_format_error ( status, message, sizeof(message) );
	    printf("/hello_world/ error write: %d ->'%s'\n",status,message);
	status = mst_close ( link );
   	    mst_format_error ( status, message, sizeof(message) );
	    printf("/hello_world/ close status: %d ->'%s'\n",status,message);
	
	break;
	case 'e':	/* close test */
	status = mst_close (link );
	break;
    }
   return 1;
}

int main ( int argc, char **argv )
{
    mst_link_t link;
    int status, pool, pool2, length, repeat;
    char message[128], buffer[1000], guard[1000];
    pthread_attr_t def_attr;
    /*
     * Setup thread service 'hello', wait flag false.
     */
    tlog_init ( "sys$output" );
    tlog_putlog_cb = tlog_putlog;
    printf("MSTVERIFY startup\n");
    INITIALIZE_THREAD_ATTR(&def_attr);
    buffer[0] = '\0';
    status = mst_create_service_pool ( def_attr, 5, 0, &pool );
    mst_format_error ( status, message, sizeof(message) );
    printf("Pool create status: %d -> '%s', id: %d\n", status, message, pool );

    status = mst_register_service ( "hello", hello_world, "main thread", pool);
    mst_format_error ( status, message, sizeof(message) );
    printf("register service status: %d -> '%s'\n", status, message );
    /*
     * Check for repeat count on command line.
     */
    if ( argc > 2 ) repeat = atoi ( argv[2] ); else repeat = 0;
	printf("repeat count: %d\n", repeat );
    if ( repeat > 0 ) {
	/*
	 * Positive repeat is times multiple writes.
	 */
	int LIB$INIT_TIMER(), LIB$SHOW_TIMER();
        status = mst_connect ( "hello", argv[1][0] == 'd' ? argv[1] : "d", 
		&link );
        mst_format_error ( status, message, sizeof(message) );
        printf("connect status: %d -> '%s'\n", status, message );
	status = mst_read ( link, buffer, 1000, &length );
	LIB$INIT_TIMER();
	if ( status == MST_NORMAL ) for ( ; repeat > 0; --repeat ) {
	   status = mst_read ( link, buffer, 1000, &length );
	    if ( status != MST_NORMAL ) break;
	}
	LIB$SHOW_TIMER();
	buffer[length > 999 ? 999 : length] = '\0';
	printf("buffer: %s\n", buffer );

    } else if ( repeat < 0 ) {
	/*
	 * Negative repeat count times thread connects.  Use alternate
	 * service (howdy) with pool that waits for available threads.
	 */
	int LIB$INIT_TIMER(), LIB$SHOW_TIMER();
        status = mst_create_service_pool ( def_attr, 
	    argc > 3 ? atoi(argv[3]) : 50, 1, &pool2 );
        mst_format_error ( status, message, sizeof(message) );
        printf("Pool create status: %d -> '%s', id: %d\n", status, message, 
		pool2 );
        status = mst_register_service ( "howdy", howdy_world, "main thread", 
		pool2 );
        mst_format_error ( status, message, sizeof(message) );
        printf("register service status: %d -> '%s'\n", status, message );
	LIB$INIT_TIMER();
	for ( repeat = (-repeat); repeat > 0; --repeat ) {
            status = mst_connect ( "howdy", "e", &link );
	    if ( status != MST_NORMAL ) break;
	    status = mst_close ( link );
	    if ( status != MST_NORMAL ) break;
	}
	LIB$SHOW_TIMER();
        mst_format_error ( status, message, sizeof(message) );
        printf("final status: %d -> '%s'\n", status, message );
    }
    /*
     * Do basic tests, first connect to service and write one line.
     */
    status = mst_connect ( "hello", argc  > 1 ? argv[1] : "b", &link );
    mst_format_error ( status, message, sizeof(message) );
    printf("connect status 1: %d -> '%s'\n", status, message );

    status = mst_write ( link, buffer, sizeof(buffer), &length );
    mst_format_error ( status, message, sizeof(message) );
    printf("write status 1: %d -> '%s', length: %d\n", 
	status, message, length );
    buffer[length>999 ? 999 : length] = '\0';
    if ( status == MST_NORMAL ) printf ( "data read: '%s'\n", buffer );

    status = mst_close ( link );
    status = mst_close ( link );
    mst_format_error ( status, message, sizeof(message) );
    printf("close status 1: %d -> '%s'\n", status, message );
    /*
     * Connect to service and read
     */
    status = mst_connect ( "hello", argc > 1 ? argv[1] : "a", &link );
    mst_format_error ( status, message, sizeof(message) );
    printf("connect status 2: %d -> '%s'\n", status, message );

    status = mst_read ( link, buffer, sizeof(buffer), &length );
    mst_format_error ( status, message, sizeof(message) );
    buffer[length>999 ? 999 : length] = '\0';
    printf("read status 2: %d -> '%s', length: %d\n", status, message, length );
    if ( status == MST_NORMAL ) printf ( "data read: '%s'\n", buffer );
    /*
     */
    return 1;
}

int ts_tcp_stack_used() { return 0; }
