Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / lib / tt / lib / mp / mp_mp.C
1 //%%  (c) Copyright 1993, 1994 Hewlett-Packard Company                  
2 //%%  (c) Copyright 1993, 1994 International Business Machines Corp.    
3 //%%  (c) Copyright 1993, 1994 Sun Microsystems, Inc.                   
4 //%%  (c) Copyright 1993, 1994 Novell, Inc.                             
5 //%%  $TOG: mp_mp.C /main/7 1999/09/21 08:43:02 mgreess $                                                       
6 /*
7  *
8  * mp_mp.cc -- Server and client state object for the Message Passer
9  *
10  * Copyright (c) 1990,1992 by Sun Microsystems, Inc.
11  */
12
13 #include "mp/mp_global.h"
14 #include "mp/mp_mp.h"
15 #include "mp/mp_file.h"
16 #include "mp/mp_session.h"
17 #include "mp/mp_c_session.h"
18 #include "mp/mp_procid.h"
19 #include "mp/mp_rpc_client.h"
20 #include "mp/mp_xdr_functions.h"
21 #include "util/tt_base64.h"
22 #include "util/tt_port.h"
23 #include "util/tt_path.h"
24 #include "api/c/api_error.h"
25 #include <errno.h>
26 #include <sys/resource.h>
27 #include <malloc.h>
28 #include "tt_options.h"
29
30 #if defined(_AIX)
31 /* AIX's FD_ZERO macro uses bzero() without declaring it. */
32 #include <strings.h>
33 #endif
34
35 // 
36 // This file contains methods for the _Tt_mp object which is an object
37 // whose only function is to serve as a placeholder for global
38 // data/objects relevant to the message-passer routines. Another major
39 // use is to hold the various object caches that map object ids to a
40 // single object of the given class.
41 //
42 // Really, the _Tt_mp object as we see it here should go away, being
43 // replaced by _Tt_c_mp, which should represent the client's idea
44 // of the ttsession server it's connected to, and _Tt_s_mp, which
45 // represents the global state of a ttsession server.
46 // 
47
48 //
49 // Global pointer to *the* _Tt_mp object. There should only be one
50 // _Tt_mp object per tooltalk client.
51 //
52 _Tt_mp          *_tt_mp = (_Tt_mp *)0;
53
54 //
55 // Constructs a _Tt_mp object in the indicated mode.
56 //
57 _Tt_mp::
58 _Tt_mp()
59 {
60         _flags = 0;
61         FD_ZERO(&_session_fds);
62         _session_cache = new _Tt_session_table(_tt_session_address);
63         active_messages = 0;
64         _current_message_id = _current_pattern_id = 0;
65         active_procs = new _Tt_procid_table(_tt_procid_id, 50);
66 }
67
68 _Tt_mp::
69 ~_Tt_mp()
70 {
71 }
72
73
74
75 // 
76 // Returns the value of a counter and then increments the counter. Used
77 // to make different messages sent by the same sender unique.
78 //
79 int _Tt_mp::
80 generate_message_id()
81 {
82         return(_current_message_id++);
83 }
84
85
86 // 
87 // Returns the value of a counter and then increments the counter. Used
88 // to make different patterns registered by the same sender unique.
89 //
90 int _Tt_mp::
91 generate_pattern_id()
92 {
93         return(_current_pattern_id++);
94 }
95
96
97
98
99 // 
100 // Finds the _Tt_file object associated with the network pathname <path>.
101 // Optionally creates the _Tt_file object.  Returns:
102 //      TT_OK           but: if (! createIfNot), then fp.is_null() is possible
103 //      TT_ERR_FILE
104 //      TT_ERR_PATH
105 //      TT_ERR_DBAVAIL
106 //      TT_ERR_DBEXIST
107 //      TT_ERR_INTERNAL can mean ENOMEM
108 // 
109 Tt_status
110 _Tt_mp::find_file(
111         _Tt_string      path,
112         _Tt_file_ptr   &file,
113         int             createIfNot
114 )
115 {
116         _Tt_string network_path;
117         if (_tt_is_network_path(path)) {
118                 network_path = path;
119         }
120         else {
121                 network_path = _Tt_db_file::getNetworkPath(path);
122         }
123
124         if (_file_cache.is_null()) {
125                 if (!createIfNot) {
126                         return TT_OK;
127                 }
128                 else {
129                         _file_cache = new _Tt_file_table(_Tt_file::networkPath_);
130                         if (_file_cache.is_null()) {
131                                 return TT_ERR_NOMEM;
132                         }
133                 }
134         }
135         else {
136                 file = _file_cache->lookup( network_path );
137                 if (! file.is_null()) {
138                         return TT_OK;
139                 }
140         }
141
142         // If we get to this point, the file is not in the cache
143
144         Tt_status status = TT_OK;
145         if (createIfNot) {
146                 file = new _Tt_file( path );
147                 if (file.is_null()) {
148                         return TT_ERR_NOMEM;
149                 }
150                 _Tt_db_results dbStatus = file->getDBResults();
151                 status = _tt_get_api_error( dbStatus, _TT_API_FILE );
152                 if (status == TT_OK) {
153                         _file_cache->insert( file );
154                 } else if (status == TT_ERR_INTERNAL) {
155                         _tt_syslog( 0, LOG_ERR,
156                                     "_Tt_db_file::_Tt_db_file(): %d", dbStatus);
157                 }
158         }
159         return status;
160 }
161
162 void _Tt_mp::remove_file(_Tt_string path)
163 {
164         _Tt_string network_path = _Tt_db_file::getNetworkPath(path);
165         _file_cache->remove(network_path);
166 }
167
168 void _Tt_mp::
169 remove_session(_Tt_string id)
170 {
171         _session_cache->remove(id);
172 }
173
174
175 // 
176 // Attempts to find the _Tt_session object associated with the given
177 // session id. If not found and create_ifnot is 1 then a new session is
178 // created and initialized. When it is initialized, the auto_start
179 // parameter is examined. If it is 1 then the new session will be
180 // initialized with the c_init method that will do an auto-start of the
181 // session if it isn't running. Otherwise, the "client_session_init"
182 // method is used which just tries to connect to a running session.
183 //
184 // Note that the server does use _Tt_c_session since servers can
185 // act as clients for one another when passing file scoped messages.
186 // 
187 Tt_status _Tt_mp::
188 find_session(_Tt_string id, _Tt_session_ptr &sp,
189              int create_ifnot, int auto_start)
190 {
191         Tt_status result = TT_OK;
192
193         _Tt_session_ptr         s;
194         if (_session_cache->lookup(id,s)) {
195                 sp = s;
196                 result = TT_OK;
197         } else {
198                 // If this is a session address, try the X session ID
199                 // XXX - this is a kludge to deal with X session
200                 // IDs  now  that we use addres_strings as the lookup
201                 // key.  This should be removed if/when we expunge
202                 // our internal use of X session IDs.
203                 _Tt_session_table_cursor sc(_session_cache);
204
205                 while (sc.next()) {
206                         if (sc->has_id(id)) {
207                                 sp = *sc;
208
209                                 // Note: we return right here!
210                                 return TT_OK;
211                         }
212                 }
213         }
214
215         if (! create_ifnot || id.len() <= 0) {
216                 result = TT_ERR_SESSION;
217         } else {
218                 _Tt_c_session_ptr s = new _Tt_c_session();
219
220                 result = s->set_id(id);
221                 if (result != TT_OK) return result;
222
223                 if (auto_start) result = s->c_init();
224                 if (result != TT_OK) return result;
225
226                 if (result == TT_OK) result = s->client_session_init();
227                 if (result != TT_OK) return result;
228
229                 _session_cache->insert(s);
230                 sp = s;
231                 result = TT_OK;
232         }
233         return result;
234 }
235
236
237 void _Tt_mp::
238 save_session_fd(int fd)
239 {
240         FD_SET(fd, &_session_fds);
241 }
242
243
244 int _Tt_mp::
245 find_session_by_fd(int fd, _Tt_session_ptr &sp)
246 {
247         _Tt_rpc_client_ptr              rpc_client;
248         _Tt_session_table_cursor        sc(_session_cache);
249
250         while (sc.next()) {
251                 rpc_client = sc->_rpc_client;
252                 if (rpc_client->socket() == fd) {
253                         sp = *sc;
254                         return(1);
255                 }
256         }
257         return(0);
258 }
259
260
261 void _Tt_mp::
262 check_if_sessions_alive()
263 {
264         fd_set                  s_fds;
265         int                     fd, maxfds, n;
266         timeval                 tmout;
267         _Tt_session_ptr         s;
268         _Tt_string              id;
269
270         tmout.tv_sec = 0;
271         tmout.tv_usec = 0;
272         s_fds = _session_fds;
273         maxfds = _tt_getdtablesize();
274         n = select(maxfds, (fd_set *) 0, &s_fds, (fd_set *) 0, &tmout);
275
276         if (n < 0) {
277                 return;
278         }
279         fd = 0;
280         while (n > 0) {
281                 if (FD_ISSET(fd, &s_fds)) {
282                         if (! find_session_by_fd(fd, s)) {
283                                 FD_CLR(fd, &_session_fds);
284                         } else if (s->ping() != TT_OK) {
285                                 id = s->process_tree_id();
286                                 _tt_mp->remove_session(id);
287                                 FD_CLR(fd, &_session_fds);
288                         }
289                         n--;
290                 }
291                 fd++;
292         }
293 }