Files
cdesktop/cde/lib/tt/lib/mp/mp_mp.C
T
2018-04-28 12:30:20 -06:00

316 lines
7.5 KiB
C++

/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these libraries and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $TOG: mp_mp.C /main/7 1999/09/21 08:43:02 mgreess $
/*
*
* mp_mp.cc -- Server and client state object for the Message Passer
*
* Copyright (c) 1990,1992 by Sun Microsystems, Inc.
*/
#include "mp/mp_global.h"
#include "mp/mp_mp.h"
#include "mp/mp_file.h"
#include "mp/mp_session.h"
#include "mp/mp_c_session.h"
#include "mp/mp_procid.h"
#include "mp/mp_rpc_client.h"
#include "mp/mp_xdr_functions.h"
#include "util/tt_base64.h"
#include "util/tt_port.h"
#include "util/tt_path.h"
#include "api/c/api_error.h"
#include <errno.h>
#include <sys/resource.h>
#include <stdlib.h>
#include "tt_options.h"
#if defined(_AIX)
/* AIX's FD_ZERO macro uses bzero() without declaring it. */
#include <strings.h>
#endif
//
// This file contains methods for the _Tt_mp object which is an object
// whose only function is to serve as a placeholder for global
// data/objects relevant to the message-passer routines. Another major
// use is to hold the various object caches that map object ids to a
// single object of the given class.
//
// Really, the _Tt_mp object as we see it here should go away, being
// replaced by _Tt_c_mp, which should represent the client's idea
// of the ttsession server it's connected to, and _Tt_s_mp, which
// represents the global state of a ttsession server.
//
//
// Global pointer to *the* _Tt_mp object. There should only be one
// _Tt_mp object per tooltalk client.
//
_Tt_mp *_tt_mp = (_Tt_mp *)0;
//
// Constructs a _Tt_mp object in the indicated mode.
//
_Tt_mp::
_Tt_mp()
{
_flags = 0;
FD_ZERO(&_session_fds);
_session_cache = new _Tt_session_table(_tt_session_address);
active_messages = 0;
_current_message_id = _current_pattern_id = 0;
active_procs = new _Tt_procid_table(_tt_procid_id, 50);
}
_Tt_mp::
~_Tt_mp()
{
}
//
// Returns the value of a counter and then increments the counter. Used
// to make different messages sent by the same sender unique.
//
int _Tt_mp::
generate_message_id()
{
return(_current_message_id++);
}
//
// Returns the value of a counter and then increments the counter. Used
// to make different patterns registered by the same sender unique.
//
int _Tt_mp::
generate_pattern_id()
{
return(_current_pattern_id++);
}
//
// Finds the _Tt_file object associated with the network pathname <path>.
// Optionally creates the _Tt_file object. Returns:
// TT_OK but: if (! createIfNot), then fp.is_null() is possible
// TT_ERR_FILE
// TT_ERR_PATH
// TT_ERR_DBAVAIL
// TT_ERR_DBEXIST
// TT_ERR_INTERNAL can mean ENOMEM
//
Tt_status
_Tt_mp::find_file(
_Tt_string path,
_Tt_file_ptr &file,
int createIfNot
)
{
_Tt_string network_path;
if (_tt_is_network_path(path)) {
network_path = path;
}
else {
network_path = _Tt_db_file::getNetworkPath(path);
}
if (_file_cache.is_null()) {
if (!createIfNot) {
return TT_OK;
}
else {
_file_cache = new _Tt_file_table(_Tt_file::networkPath_);
if (_file_cache.is_null()) {
return TT_ERR_NOMEM;
}
}
}
else {
file = _file_cache->lookup( network_path );
if (! file.is_null()) {
return TT_OK;
}
}
// If we get to this point, the file is not in the cache
Tt_status status = TT_OK;
if (createIfNot) {
file = new _Tt_file( path );
if (file.is_null()) {
return TT_ERR_NOMEM;
}
_Tt_db_results dbStatus = file->getDBResults();
status = _tt_get_api_error( dbStatus, _TT_API_FILE );
if (status == TT_OK) {
_file_cache->insert( file );
} else if (status == TT_ERR_INTERNAL) {
_tt_syslog( 0, LOG_ERR,
"_Tt_db_file::_Tt_db_file(): %d", dbStatus);
}
}
return status;
}
void _Tt_mp::remove_file(_Tt_string path)
{
_Tt_string network_path = _Tt_db_file::getNetworkPath(path);
_file_cache->remove(network_path);
}
void _Tt_mp::
remove_session(_Tt_string id)
{
_session_cache->remove(id);
}
//
// Attempts to find the _Tt_session object associated with the given
// session id. If not found and create_ifnot is 1 then a new session is
// created and initialized. When it is initialized, the auto_start
// parameter is examined. If it is 1 then the new session will be
// initialized with the c_init method that will do an auto-start of the
// session if it isn't running. Otherwise, the "client_session_init"
// method is used which just tries to connect to a running session.
//
// Note that the server does use _Tt_c_session since servers can
// act as clients for one another when passing file scoped messages.
//
Tt_status _Tt_mp::
find_session(_Tt_string id, _Tt_session_ptr &sp,
int create_ifnot, int auto_start)
{
Tt_status result = TT_OK;
_Tt_session_ptr s;
if (_session_cache->lookup(id,s)) {
sp = s;
result = TT_OK;
} else {
// If this is a session address, try the X session ID
// XXX - this is a kludge to deal with X session
// IDs now that we use addres_strings as the lookup
// key. This should be removed if/when we expunge
// our internal use of X session IDs.
_Tt_session_table_cursor sc(_session_cache);
while (sc.next()) {
if (sc->has_id(id)) {
sp = *sc;
// Note: we return right here!
return TT_OK;
}
}
}
if (! create_ifnot || id.len() <= 0) {
result = TT_ERR_SESSION;
} else {
_Tt_c_session_ptr s = new _Tt_c_session();
result = s->set_id(id);
if (result != TT_OK) return result;
if (auto_start) result = s->c_init();
if (result != TT_OK) return result;
if (result == TT_OK) result = s->client_session_init();
if (result != TT_OK) return result;
_session_cache->insert(s);
sp = s;
result = TT_OK;
}
return result;
}
void _Tt_mp::
save_session_fd(int fd)
{
FD_SET(fd, &_session_fds);
}
int _Tt_mp::
find_session_by_fd(int fd, _Tt_session_ptr &sp)
{
_Tt_rpc_client_ptr rpc_client;
_Tt_session_table_cursor sc(_session_cache);
while (sc.next()) {
rpc_client = sc->_rpc_client;
if (rpc_client->socket() == fd) {
sp = *sc;
return(1);
}
}
return(0);
}
void _Tt_mp::
check_if_sessions_alive()
{
fd_set s_fds;
int fd, maxfds, n;
timeval tmout;
_Tt_session_ptr s;
_Tt_string id;
tmout.tv_sec = 0;
tmout.tv_usec = 0;
s_fds = _session_fds;
maxfds = _tt_getdtablesize();
n = select(maxfds, (fd_set *) 0, &s_fds, (fd_set *) 0, &tmout);
if (n < 0) {
return;
}
fd = 0;
while (n > 0) {
if (FD_ISSET(fd, &s_fds)) {
if (! find_session_by_fd(fd, s)) {
FD_CLR(fd, &_session_fds);
} else if (s->ping() != TT_OK) {
id = s->process_tree_id();
_tt_mp->remove_session(id);
FD_CLR(fd, &_session_fds);
}
n--;
}
fd++;
}
}