Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / lib / tt / README
1 /* $TOG: README /main/4 1999/08/30 10:44:07 mgreess $ */
2         1.8 10/27/92
3 Copyright (c) 1992 by Sun Microsystems, Inc.
4
5
6 TOOLTALK IMPLEMENTATION OVERVIEW
7
8
9 This document presents a roadmap to understanding the implementation
10 of the main message-passing features of ToolTalk 1.0.1. It does not
11 aim to describe the details of the algorithms used. In order to find
12 these out it is necessary to read the source code as well as the
13 comments. This document should give the reader an overall picture of
14 how all the various objects that implement message-passing fit
15 together as well as familiarity with where to find the code that
16 implements a particular feature. Finally some naming conventions used
17 throughout the code are given.
18
19
20 ********** Please update this document as the code is changed **********
21
22
23
24 MEMORY MANAGEMENT
25
26 The only memory management policy used througout the code is
27 reference-counting. This is an automatic sort of memory management
28 since objects are "magically" deleted when there are no longer
29 references to them. This functionality is implemented by way of
30 pointer classes that behave just like normal pointers except that they
31 maintain a reference count in the object they point to. It is
32 important *not* to mix normal pointers with counted pointers.
33
34 MIXING POINTERS
35
36 You should never use a C pointer with refcounted objects (i.e., those
37 inheriting from _Tt_object (actually, from _Tt_new; I have no idea why
38 _Tt_new and _Tt_object are different)).  You should always use
39 refcounting pointers ("ptrs") with _Tt_objects.  The danger is as
40 follows:
41
42         _Tt_object *evilRef;
43         {
44                 evilRef = new _Tt_object;
45                 //
46                 // refCount is now zero, but evilRef is pointing at our
47                 // object!
48                 //
49                 ...
50                 _Tt_object_ptr goodRef = evilRef;
51                 //
52                 // refCount is now 1
53                 //
54                 ...
55                 //
56                 // goodRef goes out of scope.
57                 // goodRef::~_Tt_object_ptr() decrements the refCount
58                 // to zero, and deletes our object because the
59                 // refCount is now zero.
60                 //
61         }
62         int foo = evilRef->dataMember;  // core dump
63
64 If you need a static pointer to a _Tt_object, you cannot have a static
65 _Tt_object_ptr, because static C++ instances aren't allowed.  But you
66 don't want to have a static _Tt_object *, because then you have to
67 eternally worry about never showing it to a refcounting pointer (which
68 would try to delete it when it was done with it).
69
70 The best thing to do is have a static _Tt_object_ptr *:
71
72         static _Tt_object_ptr *ppGlobalObj;
73         ppGlobalObj = new _Tt_object_ptr;
74         *ppGlobalObj = new _Tt_object;
75
76 Now you can use *ppGlobalObj wherever you would have used your static
77 _Tt_object_ptr.  The _Tt_object you allocated is safely refcounted, so
78 you can let refcounting pointers do whatever they want with it.
79 When it's time to clean up, you just
80
81         delete ppGlobalObj;
82
83 This is a call to ppGlobalObj->~_Tt_object_ptr(), which decrements the
84 refcount of your object, and *optionally* deletes it if the refcount
85 is zero.  This way, you don't delete your object out from under anyone
86 who still has a reference to it.
87
88 REFCOUNTING INSIDE CONSTRUCTORS
89
90 Inside a constructor, never assign the 'this' pointer of a refcounted
91 object to an automatic refcounting pointer.  Inside the constructor,
92 the refcount is still zero.  Assigning 'this' into a refcounting
93 pointer will increment the refcount to 1.  But before the constructor
94 returns, the automatic refcounting pointer on the stack will be
95 destructed.  The destructor will decrement the object's refcount back
96 to zero, and therefore delete the object -- before the constructor
97 even returns!
98
99         _Tt_foo::_Tt_foo()
100         {
101                 // On entry, _Tt_foo::_refcount_ == 0
102                 _Tt_foo_ptr evilRef = this;
103                 // Now, _Tt_foo::_refcount_ == 1
104                 ...
105                 // On exit, evilRef->~_Tt_foo_ptr() will be called.
106                 // It will decrement the refcount to zero, and
107                 // then delete this object under construction!
108         }
109
110 Also, be sure not to pass the 'this' pointer to any routine that might
111 hold a temporary reference to the object while the routine runs.
112 (Here, "hold a temporary reference to" means "increment the refcount
113 and then decrement it".)  If you must pass the 'this' pointer anywhere
114 from within the constructor, cast it to const first so that the
115 compiler will protect you from any routine with an intention of
116 modifying its refcount.  If you absolutely must pass the 'this'
117 pointer to a routine that might only temporarily reference it, then
118 manually increment the refcount before doing so, and then manually
119 decrement the refcount before returning from the constructor
120
121 CYCLICAL REFERENCES
122
123 Avoid creating data structures that permit cyclical references.
124 A single reference cycle can cause a massive memory leak.
125
126 COMMENT CONVENTIONS
127
128 Throughout the code, any comments preceded by XXX: denote notes to the
129 reader of problems or suggestions for the code they describe. 
130
131
132
133 DESCRIPTION OF OBJECT CLASSES
134
135 This section presents all the object classes used to implement the
136 message-passing portion of ToolTalk along with a brief description of
137 what each class represents and in which files it can be found. Before
138 describing the classes we need to mention some important naming
139 conventions as well as some general comments about client/server
140 conventions.
141
142 Many of the object classes described below have client-side and
143 server-side implementations. For example, a client-side version of a
144 ToolTalk message has methods to send the message to the server. On the
145 server-side there is a corresponding _Tt_message that processes the
146 new message. In the 1.0 version of ToolTalk, these methods were
147 roughly coded as:
148
149                 void _Tt_some_object::
150                 sample_method(...)
151                 {
152                         if (_tt_mp->in_server()) {
153                                 ... do server-specific actions ...
154                         } else {
155                                 ... do client-specific actions ...
156                         }       
157                 }
158
159 where the "in_server" method for the _Tt_mp class returns 1 if the
160 environment is in server mode (which is true if the method is
161 executing on behalf of ttsession). The problem with this scheme is
162 that the library was excessively big because the code to implement the
163 server, ttsession, was contained in the library even though it wasn't
164 needed for the clients.
165
166 Because of this, the 1.0.1 version split up this method in one of two
167 ways. The first method is to create two subclasses of the object. One
168 of the subclasses, named with a "_c_" infix, represents the
169 client-side state and methods for the object. The other subclass,
170 named with a "_s_" infix, represents the server-side state and methods
171 for the object.  Each of these subclasses then contains the
172 corresponding method which now doesn't need the conditional test. The
173 example above then becomes:
174
175                 void _Tt_c_some_object::
176                 sample_method(...)
177                 {
178                         ... do client-specific actions ...
179                 }
180
181
182                 void _Tt_s_some_object::
183                 sample_method(...)
184                 {
185                         ... do server-specific actions ...
186                 }
187
188 The other mechanism is to still have one object class but name the
189 object with a "c_" prefix for the client-specific method, and an "s_"
190 prefix for the server-specific method.
191
192 In the 4/93 version of ToolTalk, more classes were split up so that
193 no references to server-only classes would appear in client code.
194 As part of this, the client-to-server XDR methods were slightly
195 changed.  You will see (in mp_rpc_implement.C) that apparently
196 the server uses a XDR function to decode the arguments of some
197 RPCs which is different from the encoding XDR function.  This
198 seemingly violates the central dogma of XDR, but it really isn't
199 as bad as it looks.  What is happpening is that we have class
200 hierarchies like:
201
202           _Tt_pattern
203                |
204        ------------------
205        |                |
206   _Tt_s_pattern     _Tt_c_pattern          
207
208 Only _Tt_pattern has an XDR method -- that is, the data that appears
209 on the wire is only the common data. A client would create a _Tt_c_pattern
210 and XDR it out; the server then XDR's it in as a _Tt_s_pattern, but
211 the _Tt_pattern::XDR routine does all the work and the only difference
212 is the virtual function table (and any private _Tt_s_pattern data,
213 which would be initialized by the _Tt_s_pattern constructor.)
214
215
216 The following classes are related to the main message-passing
217 functionality in ToolTalk. Details on what methods they implement and
218 precise algorithms are in the source code along with the comments
219 throughout the code.
220
221
222 Class: _Tt_arg
223 File: tt/lib/mp/mp_arg.C (client/server methods)
224       tt/lib/mp/mp_s_arg.C (server-only methods)
225
226 This class represents an argument to a message or pattern. Its methods
227 implement matching arguments with other arguments and constructing and
228 updating arguments.
229
230
231 Class: _Tt_auth
232 File: tt/lib/mp/mp_auth.C (client/server methods)
233       tt/lib/mp/mp_auth_functions.C (utility functions copied from libICE)
234
235 This class maintains the authorization level being used by the server
236 (cookie, des, unix, none).  In the case of the cookie authorization
237 scheme, this class also is responsible for generating the cookie and
238 writing it to and reading it from the authority file.
239
240 Class: _Tt_desktop
241 File: tt/lib/mp/mp_desktop.C
242
243 This class represents "desktop" sessions. Currently this means X11
244 server sessions but the methods reflect an interface that is largely
245 independent of X11. As a result, all X11-dependent code is isolated in
246 this one module.
247
248
249 Class:  _Tt_c_message (subclass of _Tt_message)
250 File:   tt/lib/mp/mp_c_message.C
251
252 This class represents client-only view of ToolTalk messages. It
253 contains methods for sending messages to the ttsession server.
254
255
256 Class:  _Tt_c_procid (subclass of _Tt_procid)
257 File:   tt/lib/mp/mp_c_procid.C
258
259 This class implements client-only methods needed to reply to messages
260 and to retrieve new messages for the ToolTalk client represented by
261 this class.
262
263
264 Class:  _Tt_file
265 File:   tt/lib/mp/mp_file.C (server/client methods)
266         tt/lib/mp/mp_s_file.C (server-only methods)
267
268 This class represents file objects. The functionality implemented is
269 for querying for specs contained in the file, joining and quitting
270 file scopes, and queuing and de-queueing messages on file objects.
271
272
273 Class:  _Tt_message
274 File:   tt/lib/mp/mp_message.C
275
276 This class represents a ToolTalk message. This class represents
277 methods that are common to both clients and ttsession. Its subclasses,
278 _Tt_s_message and _Tt_c_message described below implement methods
279 specific to client manipulation and server manipulation respectively.
280 The code is structured so that _Tt_message objects contain the methods
281 to do delivery to other clients.
282
283
284 Class: _Tt_mp 
285 File:  tt/lib/mp/mp_mp.C
286
287 This class represents the global state needed by the message-passing
288 objects. In particular, this object contains many object caches that
289 are needed by the system as well as holds references to some important
290 objects such as the default session object.
291
292
293 Class:  _Tt_node
294 File:   tt/lib/mp/mp_node.C
295
296 This class represents a ToolTalk spec. Its methods create/destroy
297 specs in a database and add properties to an existing spec.
298
299
300 Class:  _Tt_observer
301 File:   tt/lib/mp/mp_observer.C
302
303 This class is a very simple class that basically just stores some
304 message fields that can change for static observers of a message. It
305 is used only by the _Tt_s_message class. This class is mainly used as
306 to hold the information necessary to honor static observer "promises"
307 for message disposition processing.
308
309
310 Class:  _Tt_otype
311 File:   tt/lib/mp/mp_otype.C
312
313 This class implements methods needed to deal with otype definitions.
314 In general the operations needed are for setting and returning the
315 observer, inherited, and handler signatures for this otype definition
316 as well as printing out the otype definition which, in addition to
317 debugging, is used to print out the definition for storage under the
318 Classing Engine and also for dumping out compiled type databases in
319 source format.
320
321
322 Class:  _Tt_pattern
323 File:   tt/lib/mp/mp_pattern.C (server/client methods)
324         tt/lib/mp/mp_s_pattern.C (server-only methods)
325
326 This class represents a ToolTalk pattern. Client-side methods
327 implement adding/deleting fields to the pattern and
328 registering/unregistering the pattern by invoking the proper rpc
329 routines on the server. Server-side methods implement the appropiate
330 actions for registering/unregistering patterns as well as matching
331 patterns to messages.
332
333
334 Class:  _Tt_procid
335 File:   tt/lib/mp/mp_procid.C
336
337 This class represents a ToolTalk client. It represents all of the
338 methods and data necessary for sending a message to a ToolTalk client.
339 Its subclasses, _Tt_s_procid and _Tt_c_procid, implement the needed
340 server-only and client-only methods.
341
342
343 Class:  _Tt_ptype
344 File:   tt/lib/mp/mp_ptype.C
345
346 This class implements methods needed to deal with ptype definitions
347 and with starting new instances of ptypes which is functionality
348 needed to implement the start disposition options for ToolTalk
349 messages. Also, as with _Tt_otype objects, printing methods are also
350 defined that are used for storage in type databases and dumping out
351 ptype definitions in source format.
352
353
354 Class:  _Tt_rpc_client
355 File:   tt/lib/mp/mp_rpc_client.C
356
357 This class represents a client rpc connection. The methods implemented
358 are basically wrappers around the rpc interfaces with the important
359 difference that the api to this object is the same regardless of
360 whether tli rpc or non-tli rpc is used. The methods for this object
361 are ifdefed to use tli rpc or not.
362
363
364 Class:  _Tt_rpc_server
365 File:   tt/lib/mp/mp_rpc_server.C
366
367 This class represents an rpc server. The methods implemented are
368 wrappers around the rpc server interfaces with the difference that
369 both tli and non-tli rpc is supported by ifdefing the implementation
370 code for the methods to select which rpc interface to use.
371
372
373 Class:  _Tt_s_message (subclass of _Tt_message)
374 File:   tt/lib/mp/mp_s_message.C
375
376 This class represents a ToolTalk message with some specialized methods
377 that are specific to server-side manipulation of messages. In
378 particular this class implements methods to dispatch a message (ie.
379 match the message against static patterns), and deliver the message to
380 ToolTalk clients with patterns that match it. There are also methods
381 to implement the reliability for messages that don't match any active
382 client's patterns.
383
384
385 Class: _Tt_s_mp
386 File:  tt/lib/mp/mp_s_mp.C
387
388 This class represents the global server-only state needed by the
389 message-passing objects. It contains object caches that are relevant
390 to the server module as well as the ptypes and otypes that were read
391 in from the type database.
392
393
394 Class:  _Tt_s_procid (subclass of _Tt_procid)
395 File:   tt/lib/mp/mp_s_procid.C
396
397 This class implements server-only methods needed to send messages to
398 ToolTalk clients and also methods which process replies to previously
399 sent messages.
400
401
402 Class:  _Tt_session
403 File:   tt/lib/mp/mp_session.C (server/client methods)
404         tt/lib/mp/mp_s_session.C (server-only methods)
405
406 This class represents a ToolTalk session. It has methods that apply in
407 client-side and server-side environments. The main functionality
408 required is establishing ToolTalk sessions, advertising the addressing
409 information to contact the session, and methods for connecting to a
410 session given its addressing information and auto-starting a session
411 if necessary.
412
413
414 Class: _Tt_signature
415 File: tt/lib/mp/mp_signature.C
416
417 This class represents a ToolTalk signature which can be either an
418 otype or ptype signature. The main methods for this object allow one
419 to create a signature, match the signature against an operation name
420 and a list of arguments, and match the signature against relevant
421 message fields.
422
423
424 Class:  _Tt_stream_socket
425 File:   tt/lib/mp/mp_stream_socket.C
426
427 This class represents a stream connection. Its methods are ifdefed
428 depending on whether TCP sockets are to be used or TLI streams.
429
430
431 Class:  _Tt_typedb
432 File:   tt/lib/mp/mp_typedb.C
433
434 This class represents the ToolTalk type database. It has methods for
435 reading and writing the database in either a native xdr format or to
436 the Classing Engine. Important Note: since  the typedb on disk is
437 a table_ptr and not just a table, it's possible to have a null
438 table and a non-null _ptr, which if xdr-decoded will crash the
439 _Tt_object_table xdr method, because the default constructor
440 for that class tries to decode a null table.
441
442
443 Class: _Tt_global
444 File:  tt/lib/util/tt_global_env.C
445
446 This class is where any global information that is not specific to
447 message-passing is kept. In particular any global flags or caches are
448 kept in this object. This class also keeps the number representing the
449 current xdr version to be used by all xdr methods.
450
451
452 Class: _Tt_host
453 File:  tt/lib/util/tt_host.C
454
455 This class packages up methods for mapping host addresses to host
456 names and viceversa.
457
458
459 Class: _Tt_xdr_version
460 File: tt/lib/util/tt_xdr_version.C
461
462 This class provides a mechanism for temporarily setting the default
463 xdr version. It sets the version to a given number in the constructor
464 and then resets the default to the previous value in the destructor.
465
466
467 Class: _Tt_new_ptr
468 File: tt/lib/util/tt_new_ptr.C
469
470 Generic version of a pointer class. This implements the
471 reference-counting machinery. See declare_ptr_to and implement_ptr_to
472 in tt/lib/util/tt_ptr.h to see how a specialized pointer class is
473 derived from this generic class.
474
475
476 Class: _Tt_object_list
477 File: tt/lib/util/tt_object_list.C
478
479 Generic version of a list class. See declare_list_of and
480 implement_list_of in tt/lib/util/tt_list.h to see how a specialized
481 list class is derived from the generic one.
482
483
484 Class: _Tt_object_table
485 File: tt/lib/util/tt_object_table.C
486
487 Generic version of a table class. See declare_table_of and
488 implement_table_of in tt/lib/util/tt_table.h to see how a specialized
489 list class is derived from the generic one.  Important note: unfortunately
490 you can crash this method by trying to de-xdr on online db because
491 the default constructor for that class tries to decode a null table.
492
493
494 FINDING ONE'S WAY AROUND
495
496 The rich functionality offered by ToolTalk is implemented partly in
497 the client library, partly in the server (which itself is implemented
498 by objects contained in a server library). Thus it isn't always
499 trivial to find which code implements a certain feature. A good
500 heuristic to use is to decide whether the particular feature is likely
501 to be implemented on the client side or server side. If it is likely a
502 client-side feature then it is accessible through one of the tooltalk
503 api calls. These are all implemented in the tt/lib/api/c directory
504 where the files are named api_<noun> where <noun> is the name of the
505 entity being operated on by the api call. For example,
506 tt_pattern_create can be found in "api_pattern.C". The api calls that
507 don't operate on a particular entity are found in "api_mp.C". For
508 example, tt_open and tt_fd can be found there. 
509
510 Once the code for the api is located, the way the feature is
511 implemented can be traced through the code. Occasionally the api call
512 may interact with the server-side code. This is usually in the form of
513 an api call such as:
514
515         ...
516         rstatus = call(TT_RPC_JOIN_SESSION,
517                        (xdrproc_t)tt_xdr_procid,
518                        (char *)&procid,
519                        (xdrproc_t)xdr_int,
520                        (char *)&status);
521         ...            
522
523
524 This will cause an rpc stub to be invoked which then invokes the
525 appropiate methods on the server side. All the rpc stubs are
526 implemented in tt/lib/mp/mp_rpc_implement.C. Furthermore, the naming
527 scheme for these stubs is to add an underscore to the front of the
528 enum used to make the call on the client side and then turn all the
529 letters into lower case. In the example above, one would then look for
530 the "_tt_rpc_join_session" function in tt/lib/mp/mp_rpc_implement.C. 
531
532 The details of how the call is mapped to this rpc stub and what
533 processing goes on before the rpc stub is invoked can be found in the
534 _tt_service_rpc function which does the actual rpc dispatching.
535
536 Since most of the functionality is initiated by an api call (the
537 exception being the initializiation of the server itself), this
538 strategy usually succeeds in finding the code one is looking for. 
539
540
541 We now list some guides into the code implementing some of the major
542 features in ToolTalk.  For each piece of functionality some important
543 methods and/or files are listed which represent the main code that
544 implements the given functionality. Looking at the code for the given
545 methods and their associated comments should give a good idea as to
546 how the functionality is implemented.
547
548
549                 ********** Please add to this list **********   
550
551 - RPC REQUEST HANDLING 
552
553 (client) _Tt_session::call - single method that all other methods use
554 when they want to invoke an rpc call.
555
556 (server) tt/lib/mp/mp_rpc_implement.C contains all of the rpc stubs
557 that get invoked on the server side in response to an rpc request from
558 a client. The dispatch function in this file "_tt_service_rpc" does
559 the actual dispatching of the rpc request (_tt_service_rpc is actually
560 invoked by the rpc function svc_getreqset which is called from
561 _Tt_s_mp::main_loop by calling _Tt_rpc_server::run).
562
563 Looking at the various rpc stubs in mp_rpc_implement.C is an
564 excellent way of navigating the code to find out how each particular
565 rpc call is used. In particular, a good strategy for finding out how
566 an api call is implemented is by looking at the definition of the api
567 call and tracing through the code until _Tt_session::call invocations
568 are found. Using the rpc procedure number passed into the
569 _Tt_session::call method one can then look in mp_rpc_implement.C to
570 see what happens on the server side.
571
572
573 - NULL MESSAGE SENDING/RECEIVING LOOP
574
575 This loop consists of a client sending a request message to ttsession
576 when no patterns match the message. The message gets failed and
577 returned to the sender. Understanding the code involved in this loop
578 means that one understands the basic low-level mechanism by which the
579 messages sent to and received from ttsession. The major methods
580 involved here are:
581
582 (client) _Tt_c_message::dispatch - send message to ttsession
583 (server) _Tt_s_message::dispatch - match message with static patterns. 
584 (server) _Tt_s_message::deliver - match message with dynamic patterns. 
585 (server) _Tt_s_procid::add_message - add a message to procid's message
586                                      queue. 
587 (server) _Tt_s_procid::signal_new_message - signal a procid that it has
588                                             a new message.
589 (client) _Tt_c_procid::next_message - get next message from ttsession
590 (server) _Tt_s_procid::next_message - return next message from ttsession
591
592
593 - DISPATCHING AND DELIVERING A MESSAGE
594
595 (server) _Tt_s_message::dispatch
596 (server) _Tt_s_message::deliver
597
598
599
600 - STARTING A NEW PTYPE
601
602 (server) _Tt_s_message::handle_no_recipients
603 (server) _Tt_s_message::change_state
604 (server) _Tt_ptype::start
605
606
607 - PROCESSING THE REPLY TO A MESSAGE
608
609 (client) _Tt_c_procid::update_msg
610 (server) _Tt_s_procid::update_msg
611 (server) _Tt_message::update_msg
612 (server) _Tt_s_message::change_state
613
614
615 - HONORING START AND QUEUE RELIABILITY OPTIONS
616
617 _Tt_s_message::deliver
618 _Tt_s_message::handle_no_recipients
619
620 For file-scope messages, queueing is actually handled on the client
621 side. For more details look in:
622
623 _Tt_c_message::c_dispatch
624 _Tt_file::q_message
625 _Tt_file::dq_message
626 _Tt_file::c_join
627
628
629 - READING IN CLASSING ENGINE DATABASES
630
631 _Tt_typedb::init_ce
632
633 - ADDING/MERGING NEW TYPES TO A TYPE DATABASE
634
635 _Tt_typedb::begin_write
636 _Tt_typedb::end_write
637 _Tt_typedb::insert_ptype
638 _Tt_typedb::insert_otype
639
640
641 - DECLARING A PTYPE
642
643 _tt_rpc_declare_ptype
644 _Tt_s_procid::declare_ptype
645
646
647 - DETECTING PTYPE LAUNCH FAILURE
648
649 sig_handler (in tt/bin/ttsession/mp_server.C)
650 notify_launch_failure (in tt/bin/ttsession/mp_server.C)
651 _Tt_ptype::launch_failed
652
653
654 - AUTO-STARTING A SESSION 
655
656 tt_open (tt/lib/api/c/api_mp.C)
657 _Tt_mp::init
658 _Tt_session::init
659 _Tt_session::c_init
660
661
662 - ESTABLISHING RPC CONNECTION TO THE SERVER
663
664 _Tt_session::client_session_init - client-side processing
665 _Tt_s_mp::main_loop - unix and network rpc connection
666 _Tt_session::u_rpc_init - unix socket rpc connection
667
668
669 - XDR/RPC VERSIONING SCHEME
670
671 _tt_service_rpc (tt/lib/mp/mp_rpc_implement.C)
672 _Tt_xdr_version (tt/lib/util/tt_xdr_version)
673 _Tt_global::set_xdr_version (tt/lib/util/tt_global_env.C)
674 _Tt_global::xdr_version (tt/lib/util/tt_global_env.C)
675
676
677 - TRACE/DEBUG/ERROR OUTPUT
678
679 For trace output in ttsession and in slib, use the _Tt_trace
680 class.
681
682 For debug output in the old dm code, do it according to the
683 $TT_DM_DEBUG level.  No other module has a similar debug output
684 facility.
685
686 When an error is detected in the client library and a Tt_status
687 other than TT_ERR_INTERNAL is going to be passed up through
688 the API to diagnose it, then the client library should not
689 emit any message anywhere.  That's the job of the application using
690 libtt.
691
692 _tt_syslog( 0, LOG_ERR, ) should be used in the client library when:
693   - a TT_ERR_INTERNAL (bug) arises and we want to diagnose what happened;
694   - a partial failure of an API call occurs, but the API call is still
695     considered to have succeeded.  For example, when tt_message_send()
696     for a file-scoped message cannot contact one of the interested
697     sessions.
698
699 The daemons (ttsession and dbserver) should pass either 0 or stderr
700 to _tt_syslog(), depending on whether they are in daemon mode or not.
701
702 In CDE, certain parts (tt_type_comp, ttrm et al.) of ToolTalk are
703 likely to be run from tools that have stderr aimed at /dev/null.
704 These parts of ToolTalk should never write to stderr directly, nor
705 call perror(), nc_perror(), t_error(), etc.  Instead, they should pass
706 stderr to _tt_syslog(), and use strerror() (or %m), nc_strerror(),
707 t_strerror(), etc.  _tt_syslog() will prefix, route, suppress, and
708 multiplex the output appropriately. For example, in CDE we will
709 probably multiplex our error output onto ~/.dt/errorlog.  For
710 suppression, _tt_syslog() obeys _tt_global->silent.
711
712 No output should include un-internationalized English.  The output
713 should include only ToolTalk-ese and catgets() strings.  (ToolTalk-ese
714 can be C/C++ use of the ToolTalk API, or the ToolTalk types language.)
715 All modules that call catgets() should include "util/tt_gettext.h", so
716 that they are really calling _tt_catgets() instead of the one in
717 /usr/lib.  This lets us map catgets() to something else on platforms
718 where it is not supported.
719
720 It is OK to write normal output to stdout.
721
722 ASSIGNING NEW CATGETS MESSAGE IDS
723
724 When you code up a new call to catgets(), choose your message set out
725 of util/tt_gettext.h, and use -1 as the message id.  Then follow this
726 procedure to update the message catalog:
727
728 0. Make sure your source file(s) is(are) checked in; ttgenmsg will
729    refuse to work on checked-out files.
730 0a. Make sure /home/tooltalk/tools/bin is in your PATH
731 1. Check out SUNW_TOOLTALK.msg and SUNW_TOOLTALK.sets
732 2. Run "make msgs" from the top of the tree.
733 2a. Run msgfix which will sort and clean up "msgs" into "msgs.fixed"
734 3. Check in SUNW_TOOLTALK.sets (which now has been updated).
735 4. Copy "msgs.fixed" to SUNW_TOOLTALK.msg and check it in.
736 5. Check in your updated source files.
737
738 Note to source customers: ttgenmsg depends on genmsg, an internal
739 SunSoft tool, and so ttgenmsg is not included in the ToolTalk source
740 distribution.  If you add any new catgets() messages, you will have to
741 manually assign message ids and update the message catalog.
742
743 Note to ToolTalk developers: ttgenmsg and genmsg are in
744 /home/tooltalk/tools/bin.
745
746 THREADING ISSUES
747
748  - Locking granularity:
749     ToolTalk API calls acquire a global lock which they hold as long
750     as they are doing operations that can't block.  The original
751     intention was to drop the locks around RPC calls and re-acquire
752     them immediately after returning from such calls.  This proved to
753     be unworkable because it resulted in crashes in the RPC library.
754     As of the time of this writing, locks are held around RPC calls,
755     which introduces the danger of a blocking call causing a deadlock
756     in the entire TT library, since only one thread is actually
757     manipulating TT structures at any particular time in a process.
758
759  - ttsession threading
760     Currently ttsession only uses a thread for registering as a client
761     of itself.  This is an atomic operation and its success or failure
762     doesn't have a significant effect on ttsession's ability to serve
763     client processes.  ttsession tracing won't work until the
764     thread completes successfully.
765
766  - ALL thread-specific storage should be from malloc calls, NEVER local
767     storage.  Also, all storage obtained from tt_malloc-type calls is
768     thread-specific.
769
770  - Calling tt_message_receive and receiving the same message simultaneously
771     in different threads causes the message object to be updated from under
772     the calling code.  This happens, for instance, when one thread has a
773     handle pattern registered and another has an observe pattern registered,
774     and they both match the same message.  The biggest danger here is
775     if one thread deletes a message while another thread is accessing
776     data from the message.  It is up to the client program to regulate
777     access to TT message data.