Sample DCE/Motif/Threads program


/*
** From: ruddock@mwblan.bellcore.com (David Ruddock)
**    The program accepts CDS names as arguments, creates a label/value
**    window for each CDS name, creates a thread to "monitor" each
**    cds entry and reports on the number of RPCs received by the server
**    being monitored in the respective X/11 window.
**
**    There is little/no error checking done since the point of the
**    program is to demonstrate threads and X/11 working together.
**    So, the whole thing crashes and burns at the first hint of trouble.
**
**    There are many other things that can be done for server monitoring
**    and reporting. But I wanted to keep the example simple.
**	Dave
**
*/

/*
**  Sample make rules (for Solaris 5.5.1):
**	INCLUDES= -I/usr/dt/share/include -I/usr/openwin/share/include
**	LIBS=-ldce -lpthread -lm 
**	CFLAGS=-D_TIMESPEC_T_ -D_REENTRANT -g $(INCLUDES)
**	mtperf:	mtperf.c
**		cc $(CFLAGS) -o mtperf mtperf.c $(LIBS) -lXm -lXt -lX11 -lgen
*/


/*************************  mtperf.c  ***************************/

/* X include files */

#include <Xm/LabelG.h>
#include <Xm/RowColumn.h>
#include <Xm/Text.h>

/* DCE include files */

#include <stdio.h>
#include <dce/rpc.h> 
#include <dce/pthread.h>

/* application defines, prototypes, etc */

struct  server_info  {
	int	RPCs_In;
	int	RPCs_Out;
	int	Pkts_In;
	int	Pkts_Out;
	int     GUI_fd;
	Widget  this_widget;
	char   *CDSname;
} Info[10];
void DoMonitor( struct server_info * );
void ShowCB( Widget, XtPointer, XmPushButtonCallbackStruct *);

/* main processing */
int 	 pipe_channel[2];

main(int argc, char **argv )
{

    Widget 	 toplevel, rowcol;
    XtAppContext application;
    int 	 ctr;
    pthread_t	 thread_id[10];
 
    pipe(pipe_channel);

    toplevel = XtVaAppInitialize( &application, "Simple DCE X based monitor",
			 (XrmOptionDescList) NULL, 0, &argc, argv,
			 NULL, NULL, NULL);

    rowcol = XtVaCreateWidget("rowcol", 
		xmRowColumnWidgetClass,	toplevel,
		XmNpacking,		XmPACK_COLUMN,
		XmNnumColumns,		argc -1,
		XmNorientation,		XmHORIZONTAL,
		XmNentryAlignment,	XmALIGNMENT_END,
		XmNisAligned,		True,
		NULL);

    for ( ctr = 1; ctr <= argc - 1; ctr ++ ) {
	XtVaCreateManagedWidget( argv[ctr],
		xmLabelGadgetClass, rowcol,
		NULL);
	Info[ctr - 1].this_widget =
		XtVaCreateManagedWidget( argv[ctr],
		xmTextWidgetClass,  rowcol,
		NULL);
	Info[ctr - 1].GUI_fd = pipe_channel[1]; /* write end */
	Info[ctr - 1].CDSname = argv[ctr];
     
	if( pthread_create( &thread_id[ctr], pthread_attr_default,
        	  (pthread_startroutine_t) DoMonitor,
        	 &Info[ctr - 1]) != 0 ) {
		perror("Oh darn!");
		exit( 1 );
		}
    }
    XtManageChild(rowcol);
    XtRealizeWidget(toplevel);
    XtAppAddInput(application, pipe_channel[0], XtInputReadMask, ShowCB, NULL);
    XtAppMainLoop( application );
}
void
DoMonitor( struct server_info *info )
{
    handle_t  		bh;		/* Servers binding handle	*/
    rpc_stats_vector_t *stats;		/* Server performance stats	*/
    error_status_t   	status;		/* house keeping stuff		*/
    uuid_t          	obj_uuid;	/* Servers object UUID		*/
    rpc_ns_handle_t 	obj_inq_context, 
			import_context;
    rpc_ns_entry_object_inq_begin(
		 rpc_c_ns_syntax_default,
	        (unsigned_char_p_t) info->CDSname,
		&obj_inq_context,
		&status);

    rpc_ns_entry_object_inq_next(
		 obj_inq_context,
		&obj_uuid,
		&status);

    rpc_ns_entry_object_inq_done(&obj_inq_context, &status);

    rpc_ns_binding_import_begin(
		rpc_c_ns_syntax_default,
		(unsigned_char_p_t) info->CDSname,
		NULL,
		&obj_uuid,
		&import_context,
		&status);

    /* Import only the first binding */
    rpc_ns_binding_import_next(import_context, &bh, &status);

    rpc_mgmt_is_server_listening(bh, &status);

    while( status == rpc_s_ok ) { 
	rpc_mgmt_inq_stats(bh, &stats, &status);
	info->RPCs_In   = stats->stats[rpc_c_stats_calls_in];
	info->RPCs_Out  = stats->stats[rpc_c_stats_calls_out];
	info->Pkts_In   = stats->stats[rpc_c_stats_pkts_in];
	info->Pkts_Out  = stats->stats[rpc_c_stats_pkts_out];
	rpc_mgmt_stats_vector_free( &stats, &status);
	if ( write(info->GUI_fd, &info, sizeof(struct server_info *)) != 4 ) {
		fprintf(stderr,"Write failed!\n");
	}
	sleep(60);
    }
    pthread_exit(0);
}
void
ShowCB( Widget w, XtPointer client_data, XmPushButtonCallbackStruct * cbs)
{
    struct server_info *ptr;
    int length;
    char text[200];

    length = read(pipe_channel[0], &ptr, sizeof(struct server_info *));
    if( length != sizeof(struct server_info *) ) {
	fprintf(stderr,"Read failed!\n");
	exit(-1);
    }
    else {
	sprintf( text,"%d RPCs received", ptr->RPCs_In);
	XmTextSetString(ptr->this_widget, text);
    }
	
return;
}