###############################################################################
#
# @(#)79	1.4  src/examples/timop/readme, examples.src, os2dce21.dss, 960602a.1  5/12/96  10:13:13
#
# COMPONENT_NAME:  examples.src
#
# FUNCTIONS: timop readme file
#
# ORIGINS: 72/27
#
# (C) COPYRIGHT International Business Machines Corp. 1995
#  All Rights Reserved
#  Licensed Materials - Property of IBM
#
#  US Government Users Restricted Rights - Use, duplication or
#  disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
#
#
# (c) Copyright 1990, 1991 OPEN SOFTWARE FOUNDATION, INC.
#
# Permission is hereby granted to use, copy, modify and freely distribute
# the software in this file and its documentation for any purpose without
# fee, provided that the above copyright notice appears in all copies and
# that both the copyright notice and this permission notice appear in
# supporting documentation.  Further, provided that the name of Open
# Software Foundation, Inc. ("OSF") not be used in advertising or
# publicity pertaining to distribution of the software without prior
# written permission from OSF.  OSF makes no representations about the
# suitability of this software for any purpose.  It is provided "as is"
# without express or implied warranty.
#
#
###############################################################################


I. TIMOP DESCRIPTION
--------------------


				 TIMOP
		DCE Time Operations Sample Application

The timop program is a tutorial DCE application example.  It exercises
the basic DCE technologies: threads, RPC, security, directory and time.
It doesn't try to be particularly careful -- industrial-strength
programs do better fault management, use getopt(), have a nice Motif
interface, are internationalized, are performance tuned, etc., etc.,
none of which are really important for this tutorial.  Timop just tries
to do things in a straightforward illustrative way (insofar as that is
possible given the complexity of the technologies involved!).

We assume, of course, that you have a DCE cell up and running.  This
means, in particular, your system must support thread-safe system
interfaces (e.g., printf()).  You must also be registered as a DCE
principal (or at least know the password of a principal) in your cell in
order to do authenticated RPCs, and you must be authorized to use
certain of the cell's facilities (e.g., execute rgy_edit, and place
objects in the namespace).

What timop does is the following.  It has two parts, a client and a
server, implemented by the client and server processes.  The
server manages just one operation: to get the span of time it takes the
server do a certain job (the particular job our server does is calculate
the factorial of a random number specified by the client, but it could
be anything).  The client spawns a bunch of threads, which make parallel
RPC service calls to designated servers.  The namespace is used to
identify the servers and to mediate the RPC binding between client and
servers.  The client prints out the name, invocation order and time
spans reported by the servers, and the random numbers it asked the
servers to take the factorial of.  It also prints out a total time span
that encompasses all the job events at the servers, and the sum of the
random numbers.  We use only UDP, as a least common denominator
transport provider.  We use authentication and integrity-secure RPC to
make sure the communicated data is right, and we use a tiny bit of
authorization (named-based, not ACLs).  Note that, in general, all the
server and client clocks are different physical clocks, but they are all
commensurable with one another because they're synchronized by the time
service.  Finally, we do all our work in UTC with TDF = 0 (the "Z"
("Zulu") or "UTC Reference" time zone, corresponding to and generally
equivalent with the classical UT GMT time zone), not local civil time,
because the client(s) and server(s) may be in different time zones.

Since timop uses the security service, the timop clients and servers
must run as security principals.  But, consistent with the tutorial
goals of this example, we make just a minimal usage of security.  We run
client as a principal named "/.../mycell/tclient", and
server as a principal named "/.../mycell/tserver"; these names
should be changed to suit your environment by modifying aux.h (for
example, both tclient and tserver could be the programmer exploring this
example).  We use the default login contexts of tclient and tserver
(i.e., when you execute client or server you must be
dcelogin'd as the principal tclient or tserver, respectively), and we
run server with the key of tserver (i.e., you need to install the
key of tserver into the key file, say /tmp/tkeyfile).  Finally, we just
use a simple-minded form of authorization, based on principal names, not
ACLs; it is an "exercise for the programmer" to implement an ACL manager
and use ACL-based authorization.  Example source code for ACL management is
supplied with the DCE, but to have used it in this example would have
allowed the tail to wag the dog.


II. TIMOP Files:
----------------

Files are:

	readme              -- this file
	makefile.wat		-- makefile for the WATCOM compiler
	makefile.os2		-- makefile for the CSET++ compiler
	makefile.vc3		-- makefile for the Visual Age 3.0 compiler
	makefile.bor		-- makefile for the BORLAND compiler
	timop.idl		-- the IDL file
	timop.acf		-- the ACF file
   The following files are included if you have a HPFS file system:
	timop_aux.h		-- auxiliary header file
	timop_client.h		-- client header file
	timop_client.def		-- linker definition file
	timop_client.c		-- client program
	timop_server.h		-- server header file
	timop_server.def		-- linker definition file
	timop_server.c		-- server program
	timop_manager.c		-- manager routines
	timop_refmon.c		-- server reference monitor



III. Building TIMOP:
--------------------

Refer to the main Examples Readme file in opt\dcelocal\examples
for information on how to build these examples.


IV. Set-up TIMOP:
-----------------

Install timop_client and timop_server on the machines you want
to use, and issue commands something like the following (with names
chosen to suit your environment):

    On one machine:

	timop_server \.:\foo	# "\.:\foo", say, is the name (in the
			#     namespace) you want this server to
			#     have; you should do this either in
			#     the background (&), or on another
			#     terminal, or in another window
	# wait until you get the "Server \.:\foo ready." message
	timop_client \.:\foo	# this will print out results forever

    On multiple machines in the same cell (if not in same cell, must use
    fully-qualified names beginning with "\...", not "\.:"):

	timop_server \.:\foo		# on machine A
	timop_server \.:\bar		# on machine B
	timop_server \.:\zot		# on machine C
	client \.:\foo \.:\bar \.:\zot	# on machine D
	client \.:\zot \.:\bar \.:\foo	# on machine E

You have to kill clients and servers by hand, by using the interrupt
key, or the "ps" and "kill" commands (this leaves server binding info in
the endpoint map and namespace, which is normal for persistent servers
-- it can always be removed by hand at some point).

V. TIMOP Steps:
---------------

1) dcelogin as cell_admin and use rgy_edit to add principals and accounts
   for your timop client and server.

    # dcelogin cell_admin -dce-

    # rgy_edit
    Current site is: registry server at /.../mycell/subsys/dce/sec/master
    rgy_edit=> do p
    Domain changed to: principal
    rgy_edit=> add tserver
    rgy_edit=> add tclient
    rgy_edit=> do a
    rgy_edit=> add tserver -g none -o none -pw -dce- -mp -dce-
    rgy_edit=> add tclient -g none -o none -pw -dce- -mp -dce-
    rgy_edit=> quit
    bye.

2) Install the key of your timop server into a key file:
   Make sure you have a \tmp directory on the drive where dce is installed.

    # rgy_edit
    Current site is: registry server at /.../mycell/subsys/dce/sec/master
    rgy_edit=> ktadd -p tserver -pw -dce- -f \tmp\tkeyfile
    rgy_edit=> quit
    bye.

3) Add your timop server principal to the CDS security group so it can create
   entries in the namespace:

    # rgy_edit
    Current site is: registry server at /.../mycell/subsys/dce/sec/master
    rgy_edit=> do g
    Domain changed to: group
    rgy_edit=> member subsys/dce/cds-admin -a tserver
    rgy_edit=> quit
    bye.

4) Run the timop server:

    dcelogin tserver -dce-
    timop_server /.:/foo	    # "/.:/foo" is the name (in the
				    # namespace) you want this server to have
    # wait until you get the "Server /.:/foo ready." message

5) In another window, run the timop client:

    dcelogin tclient -dce-
    timop_client /.:/foo	    # this will print out results forever

6) To terminate either the timop server or client, ctrl-C the
    window where its running in.



VI. OTHER:
----------
After getting everything running, it would be a good exercise for you to
figure out how it all works by modifying timop in various ways and
starting to write your own applications.  Some suggestions (other than
improved error-checking, etc., that were mentioned above):

	- Get timop running over some transports other than UDP.

	- Intentionally introduce some threads race conditions, to
	  experiment with the meaning of reentrancy.  While you're at
	  it, fix the asctime() bug intentionally left in the code
	  (non-AIX platforms).

	- Parallelize the client in a different way, say by using
	  pthread_exit()/pthread_join() instead of
	  pthread_cond_signal()/pthread_cond_wait().

	- Just receive one reply from one server, canceling the other
	  outstanding jobs when the first reply arrives.

	- Handle server returns from the listen loop, cleaning binding
	  info out of the endpoint map and namespace.  You may want to
	  experiment with pthread_signal_to_cancel_np() and exceptions
	  (TRY/FINALLY/ENDTRY).

	- Create a namespace service group, instead of a collection of
	  individually named server instances.

	- Create version 1.1, containing an additional operation that
	  implements an additive version of the multiplicative factorial
	  job ("n += i" instead of "n *= i").

	- Use context handles and some time service primitives to return
	  per-client cumulative job times.

	- Create a server that supports two managers managing two
	  implementations of the factorial job, the new implementation
	  (which is accessed by a new object UUID) computing the
	  factorial in decreasing order.

	- Working with some other users, make the clients and servers
	  run under several principal identities.  Or, better, do this
	  by having your security administrator create some extra
	  identities for you to play with.  (The extra identities are
	  also useful in the following exercise.)

	- Implement an ACL manager for the service being offered by
	  the servers, and add ACL entries for several principals and
	  groups.

	- Instead of the no-op factorial jobs, dream up some application
	  that would be really useful in your environment.

