707 lines
18 KiB
C
707 lines
18 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.
|
|
//%% $XConsortium: mp_s_mp.C /main/6 1996/05/09 20:30:03 drk $
|
|
/*
|
|
*
|
|
* @(#)mp_s_mp.C 1.42 95/09/18
|
|
*
|
|
* Copyright 1990,1993 Sun Microsystems, Inc. All rights reserved.
|
|
*/
|
|
#include "mp_s_global.h"
|
|
#include "mp_s_mp.h"
|
|
#include "mp/mp_mp.h"
|
|
#include "mp_s_procid.h"
|
|
#include "mp_self_procid.h"
|
|
#include "mp_rpc_implement.h"
|
|
#include "mp_rpc_server.h"
|
|
#include "mp_s_session.h"
|
|
#include "mp/mp_xdr_functions.h"
|
|
#include "mp_ptype.h"
|
|
#include "mp_otype.h"
|
|
#include "mp/mp_arg.h"
|
|
#include "mp_s_pattern.h"
|
|
#include "mp_signature.h"
|
|
#include "mp_s_message.h"
|
|
#include "mp_typedb.h"
|
|
#include "mp/mp_file.h"
|
|
#include "util/tt_global_env.h"
|
|
#include "util/tt_base64.h"
|
|
#include "util/tt_host.h"
|
|
#include "util/tt_port.h"
|
|
#include <errno.h>
|
|
#include <sys/resource.h>
|
|
#include <time.h>
|
|
#include <unistd.h>
|
|
#include <nl_types.h>
|
|
#include <util/tt_gettext.h>
|
|
#include <tt_const.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
|
|
// global pointer to the _Tt_s_mp object. There should only be one
|
|
// instance of this object.
|
|
_Tt_s_mp *_tt_s_mp = (_Tt_s_mp *)0;
|
|
|
|
_Tt_s_mp::
|
|
_Tt_s_mp() : _Tt_mp()
|
|
{
|
|
_flags |= (1<<_TT_MP_IN_SERVER);
|
|
initial_session = initial_s_session = new _Tt_s_session;
|
|
|
|
_active_fds = new _Tt_int_rec_list();
|
|
_active_fds_procids = new _Tt_string_list();
|
|
_mp_start_time = (int)time(0);
|
|
|
|
_min_timeout = -1;
|
|
_next_procid_key = 0;
|
|
xfd = -1;
|
|
exit_main_loop = 0;
|
|
max_active_messages = 2000;
|
|
fin = 0;
|
|
fout = 0;
|
|
ptable = new _Tt_ptype_table(_tt_ptype_ptid, 50);
|
|
otable = new _Tt_otype_table(_tt_otype_otid, 50);
|
|
sigs = new _Tt_sigs_by_op_table(_tt_sigs_by_op_op, 250);
|
|
opful_pats = new _Tt_patlist_table(_tt_patlist_op, 250);
|
|
opless_pats = new _Tt_pattern_list();
|
|
active_procs = new _Tt_s_procid_table(_tt_procid_id, 250);
|
|
now = 1;
|
|
when_last_observer_registered = 1;
|
|
update_args.message = new _Tt_s_message();
|
|
_self = (_Tt_s_procid *)new _Tt_self_procid();
|
|
|
|
map_ptypes = 0;
|
|
unix_cred_chk_flag = 0;
|
|
garbage_collector_pid = 0;
|
|
_next_garbage_run = 0;
|
|
}
|
|
|
|
|
|
_Tt_s_mp::
|
|
~_Tt_s_mp()
|
|
{
|
|
//
|
|
// Emulate a tt_close() for _self.
|
|
// XXX Commented out because currently s_remove_procid() neither:
|
|
// - deletes this session from the interest list, nor
|
|
// - sends an on_exit message (since _self submits none)
|
|
//
|
|
// if (! _self.is_null()) {
|
|
// s_remove_procid( _self );
|
|
// }
|
|
}
|
|
|
|
//
|
|
// Initializes a _Tt_s_mp object. This entails initializing
|
|
// the initial session which is the default session that other clients
|
|
// connect to. This method will also initialize the global _Tt_s_mp
|
|
// object if the session is initialized. This is important since the
|
|
// _Tt_s_mp::init method assumes that the session has been initialized.
|
|
// XXX: the existence of the s_init and init methods is left over from
|
|
// an earlier incomplete split of _Tt_mp into server and client subclasses.
|
|
// Really, there should be just one virtual init method.
|
|
//
|
|
Tt_status _Tt_s_mp::
|
|
s_init()
|
|
{
|
|
Tt_status status;
|
|
|
|
active_messages = 0;
|
|
|
|
// initialize "initial" session which is the server session in
|
|
// server mode and the "default" session in client mode.
|
|
|
|
status = initial_s_session->s_init();
|
|
if (status == TT_OK) {
|
|
status = init();
|
|
}
|
|
|
|
return(status);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
// Initializes the _Tt_s_mp object. This entails putting the two special
|
|
// "pseudo-procids" into the _active_fds and _active_fds_procids lists
|
|
// (see comment for _Tt_s_mp::find_proc)
|
|
//
|
|
Tt_status _Tt_s_mp::
|
|
init()
|
|
{
|
|
if (xfd != -1) {
|
|
// put in fd for X connection
|
|
_active_fds->push(new _Tt_int_rec(xfd));
|
|
_active_fds_procids->push(_Tt_string("X"));
|
|
}
|
|
#ifdef OPT_UNIX_SOCKET_RPC
|
|
/* XXX: UNIX_SOCKET */
|
|
if (unix_fd != -1) {
|
|
// put in fd for local rpc connections
|
|
_active_fds->push(new _Tt_int_rec(unix_fd));
|
|
_active_fds_procids->push(_Tt_string("U"));
|
|
}
|
|
/* XXX: UNIX_SOCKET */
|
|
#endif // OPT_UNIX_SOCKET_RPC
|
|
|
|
return(TT_OK);
|
|
}
|
|
|
|
//
|
|
// Initialize our _Tt_self_procid and register patterns for the
|
|
// messages we are interested in.
|
|
//
|
|
Tt_status
|
|
_Tt_s_mp::init_self()
|
|
{
|
|
// Grab the global mutex to lock out other threads
|
|
|
|
_tt_global->grab_mutex();
|
|
|
|
// Increment the counter for the number of RPC calls
|
|
// handled during the life of this process. This has
|
|
// to be done here since init_self() ultimately calls
|
|
// something which calls updateFileSystemEntries(),
|
|
// yet it's not done through an API or RPC call. Thus,
|
|
// this line here is somewhat of a bandaid. XXX
|
|
_tt_global->event_counter++;
|
|
|
|
// Use the lame do-loop hack to avoid repeating the drop_mutex
|
|
// code after every possible failure...
|
|
|
|
Tt_status status = TT_OK;;
|
|
|
|
do {
|
|
//
|
|
// tt_open(), tt_fd()
|
|
//
|
|
Tt_status status = _self->init();
|
|
if (status != TT_OK) {
|
|
break;
|
|
}
|
|
status = add_procid( _self );
|
|
if (status != TT_OK) {
|
|
break;
|
|
}
|
|
_self->set_fd();
|
|
status = _handle_Session_Trace();
|
|
if (status != TT_OK) {
|
|
break;
|
|
}
|
|
status = _observe_Saved();
|
|
if (status != TT_OK) {
|
|
break;
|
|
}
|
|
} while (0);
|
|
|
|
_tt_global->drop_mutex();
|
|
|
|
return TT_OK;
|
|
}
|
|
|
|
Tt_status
|
|
_Tt_s_mp::_handle_Session_Trace()
|
|
{
|
|
//
|
|
// tt_pattern_create(), tt_pattern_category_set(),
|
|
// tt_pattern_scope_add(), tt_pattern_session_add(),
|
|
// tt_pattern_op_add(), tt_pattern_arg_add()
|
|
//
|
|
_Tt_s_pattern_ptr pat = _Tt_self_procid::s_pattern_create();
|
|
Tt_status status = pat->set_category( TT_HANDLE );
|
|
if (status != TT_OK) {
|
|
return status;
|
|
}
|
|
status = pat->add_message_class( TT_REQUEST );
|
|
if (status != TT_OK) {
|
|
return status;
|
|
}
|
|
status = pat->add_scope( TT_SESSION );
|
|
if (status != TT_OK) {
|
|
return status;
|
|
}
|
|
status = pat->add_session( _tt_s_mp->initial_s_session->address_string() );
|
|
if (status != TT_OK) {
|
|
return status;
|
|
}
|
|
status = pat->add_op( "Session_Trace" );
|
|
if (status != TT_OK) {
|
|
return status;
|
|
}
|
|
_Tt_arg_ptr arg = new _Tt_arg( TT_IN, "string" );
|
|
status = pat->add_arg( arg );
|
|
if (status != TT_OK) {
|
|
return status;
|
|
}
|
|
pat->server_callback = _Tt_self_procid::handle_Session_Trace;
|
|
//
|
|
// tt_pattern_register()
|
|
//
|
|
status = _self->add_pattern( pat );
|
|
if (status != TT_OK) {
|
|
return status;
|
|
}
|
|
//
|
|
// tt_session_join()
|
|
//
|
|
// _Tt_s_procid_ptr s_proc = (_Tt_s_procid *)_self.c_pointer();
|
|
// status = _tt_s_mp->initial_s_session->s_join( s_proc );
|
|
// if (status != TT_OK) {
|
|
// return status;
|
|
// }
|
|
return TT_OK;
|
|
}
|
|
|
|
Tt_status
|
|
_Tt_s_mp::_observe_Saved()
|
|
{
|
|
//
|
|
// tt_pattern_create(), tt_pattern_category_set(),
|
|
// tt_pattern_scope_add(), tt_pattern_op_add(), tt_pattern_arg_add()
|
|
//
|
|
_Tt_s_pattern_ptr pat = _Tt_self_procid::s_pattern_create();
|
|
Tt_status status = pat->set_category( TT_OBSERVE );
|
|
if (status != TT_OK) {
|
|
return status;
|
|
}
|
|
status = pat->add_message_class( TT_NOTICE );
|
|
if (status != TT_OK) {
|
|
return status;
|
|
}
|
|
status = pat->add_scope( TT_BOTH );
|
|
if (status != TT_OK) {
|
|
return status;
|
|
}
|
|
status = pat->add_session( _tt_s_mp->initial_s_session->address_string() );
|
|
if (status != TT_OK) {
|
|
return status;
|
|
}
|
|
_Tt_string_list_ptr ttpath = _Tt_typedb::tt_path();
|
|
if (ttpath.is_null()) {
|
|
return TT_ERR_NOMEM;
|
|
}
|
|
_Tt_string_list_cursor pathC( ttpath );
|
|
while (pathC.next()) {
|
|
status = pat->add_netfile( *pathC, 1 );
|
|
if (status != TT_OK) {
|
|
return status;
|
|
}
|
|
}
|
|
status = pat->add_op( "Saved" );
|
|
if (status != TT_OK) {
|
|
return status;
|
|
}
|
|
_Tt_arg_ptr arg = new _Tt_arg( TT_IN, "File" );
|
|
status = pat->add_arg( arg );
|
|
if (status != TT_OK) {
|
|
return status;
|
|
}
|
|
pat->server_callback = _Tt_self_procid::observe_Saved;
|
|
//
|
|
// tt_pattern_register()
|
|
//
|
|
status = _self->add_pattern( pat );
|
|
if (status != TT_OK) {
|
|
return status;
|
|
}
|
|
status = pat->join_files(_tt_s_mp->initial_s_session->process_tree_id());
|
|
if (status != TT_OK) {
|
|
return status;
|
|
}
|
|
return TT_OK;
|
|
}
|
|
|
|
|
|
//
|
|
// Installs a list of signatures. Each signature is installed in a table
|
|
// called sigs_table that maps op names to lists of signatures with that
|
|
// same opname. This cuts down on the number of signatures that need to
|
|
// be examined to dispatch a message.
|
|
//
|
|
void _Tt_s_mp::
|
|
install_signatures(_Tt_signature_list_ptr &s)
|
|
{
|
|
_Tt_signature_list_cursor sigC(s);
|
|
_Tt_sigs_by_op_ptr sigs_byop;
|
|
|
|
while (sigC.next()) {
|
|
sigs_byop = (_Tt_sigs_by_op *)0;
|
|
if (! sigs->lookup(sigC->op(),sigs_byop)) {
|
|
sigs_byop = new _Tt_sigs_by_op(sigC->op());
|
|
sigs_byop->sigs = new _Tt_signature_list();
|
|
sigs->insert(sigs_byop);
|
|
}
|
|
sigs_byop->sigs->push(*sigC);
|
|
}
|
|
}
|
|
|
|
void _Tt_s_mp::
|
|
remove_signatures(const _Tt_ptype &ptype)
|
|
{
|
|
_Tt_sigs_by_op_table_cursor sigs_byopC(sigs);
|
|
|
|
while (sigs_byopC.next()) {
|
|
_Tt_signature_list_cursor sigC(sigs_byopC->sigs);
|
|
while (sigC.next()) {
|
|
if (sigC->ptid() == ptype.ptid()) {
|
|
sigC.remove();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void _Tt_s_mp::
|
|
remove_signatures(const _Tt_otype &otype)
|
|
{
|
|
_Tt_sigs_by_op_table_cursor sigs_byopC(sigs);
|
|
|
|
while (sigs_byopC.next()) {
|
|
_Tt_signature_list_cursor sigC(sigs_byopC->sigs);
|
|
while (sigC.next()) {
|
|
if (sigC->otid() == otype.otid()) {
|
|
sigC.remove();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Iterates through the given table of ptypes and installs all the
|
|
// signatures contained in each ptype.
|
|
//
|
|
void _Tt_s_mp::
|
|
install_ptable(_Tt_ptype_table_ptr &p)
|
|
{
|
|
_Tt_ptype_table_cursor ptypes;
|
|
|
|
ptable = p;
|
|
ptypes.reset(ptable);
|
|
while (ptypes.next()) {
|
|
remove_signatures(**ptypes);
|
|
install_signatures(ptypes->hsigs());
|
|
install_signatures(ptypes->osigs());
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Iterates through the given table of otypes and installs all the
|
|
// signatures contained in each otype.
|
|
//
|
|
void _Tt_s_mp::
|
|
install_otable(_Tt_otype_table_ptr &o)
|
|
{
|
|
_Tt_otype_table_cursor otypes;
|
|
|
|
otable = o;
|
|
otypes.reset(otable);
|
|
while (otypes.next()) {
|
|
remove_signatures(**otypes);
|
|
install_signatures(otypes->hsigs());
|
|
install_signatures(otypes->osigs());
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// It is important that the mp contain exactly one object for each
|
|
// procid that is registered because there is state that is contained
|
|
// in this instance of a procid that shouldn't be duplicated. This
|
|
// method takes a generic \(neither server nor client\) procid and
|
|
// returns either
|
|
// the _Tt_s_procid object that the mp has for the given id or else creates
|
|
// a new object if create_ifnot is equal to 1. When a procid is
|
|
// initialized, it's signalling fd is added to two parallel lists,
|
|
// _active_fds and _active_fds_procids. _active_fds contains a list
|
|
// of fds whereas _active_fds_procids contains a list of procid ids.
|
|
// Each position in the two lists corresponds to each other. This is
|
|
// equivalent to having a single list of records where each record
|
|
// contains an fd and a procid id. These lists are used by the
|
|
// _Tt_s_mp::main_loop to poll all the fds in the list and match them
|
|
// with their respective procids.
|
|
//
|
|
// The _active_fds_procids list can contain two "pseudo-procids" that
|
|
// are used to keep track of some special fds. These can be "U" for
|
|
// the special unix socket fd (used if OPT_UNIX_SOCKET_RPC is defined)
|
|
// that clients use to establish a unix socket rpc connection, and "X"
|
|
// for the fd that represents the connection to our desktop session.
|
|
// See _Tt_s_mp::main_loop to see how they are used.
|
|
//
|
|
// XXX: Replacing the parallel list structure with a list of records
|
|
// would increase readability.
|
|
//
|
|
int
|
|
_Tt_s_mp::find_proc(
|
|
const _Tt_procid_ptr &procid,
|
|
_Tt_s_procid_ptr &proc_returned,
|
|
int create_ifnot
|
|
)
|
|
{
|
|
_Tt_s_procid_ptr sp;
|
|
|
|
if (! procid.is_null()) {
|
|
if (! _last_proc_hit.is_null()) {
|
|
if (_last_proc_hit->is_equal(procid)) {
|
|
proc_returned = _last_proc_hit;
|
|
return(1);
|
|
}
|
|
}
|
|
active_procs->lookup(procid->id(),sp);
|
|
}
|
|
if (!sp.is_null()) {
|
|
_last_proc_hit = sp;
|
|
proc_returned = sp;
|
|
return(1);
|
|
}
|
|
if (create_ifnot) {
|
|
sp = new _Tt_s_procid(procid);
|
|
|
|
/* procid not found, add it to list */
|
|
if (sp->init() == TT_OK) {
|
|
proc_returned = sp;
|
|
add_procid( sp );
|
|
return(1);
|
|
} else {
|
|
return(0);
|
|
}
|
|
} else {
|
|
return(0);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Called in order to generate a unique key for a new procid. This key is
|
|
// prepended to a procid's session in order to form an id that is unique
|
|
// among all procids joined to the server's session.
|
|
//
|
|
_Tt_string _Tt_s_mp::
|
|
alloc_procid_key()
|
|
{
|
|
int key = _next_procid_key++;
|
|
_Tt_string result(_tt_base64_encode((unsigned long)key));
|
|
|
|
result = result.cat(".").cat(_tt_base64_encode((unsigned long)_mp_start_time));
|
|
return(result);
|
|
}
|
|
|
|
|
|
//
|
|
// This is the main loop of the message server. This method is
|
|
// responsible for servicing events such as rpc requests, disconnect
|
|
// signals from procids, connection requests for unix socket rpc
|
|
// requests, and events generated from our desktop connection (if
|
|
// applicable). The main loop checks for the values of exit_main_loop
|
|
// and of fin and fout (see comments in bin/ttsession/mp_server.C)
|
|
// before invoking the _Tt_rpc_server::run method which will block on
|
|
// rpc requests and polling on the supplied list of file descriptors
|
|
// supplied in the _active_fds list.
|
|
//
|
|
void _Tt_s_mp::
|
|
main_loop()
|
|
{
|
|
_Tt_int_rec_list_cursor fds;
|
|
_Tt_string_list_cursor fd_procid;
|
|
_Tt_s_procid_ptr sp;
|
|
|
|
while (! exit_main_loop && (fin == fout)) {
|
|
switch (initial_s_session->_rpc_server->run_until(&exit_main_loop,
|
|
_min_timeout,
|
|
_active_fds)) {
|
|
case _TT_RPCSRV_ERR:
|
|
case _TT_RPCSRV_OK:
|
|
break;
|
|
case _TT_RPCSRV_TMOUT:
|
|
break;
|
|
case _TT_RPCSRV_FDERR:
|
|
// this error code is returned if any of the
|
|
// file descriptors in _active_fds has input
|
|
// pending. In the case of file descriptors
|
|
// associated with procid signalling channels
|
|
// this means that the connection to them was
|
|
// lost, in the case of the file descriptor
|
|
// being associated with the desktop
|
|
// connection this means that there was an
|
|
// event generated by the desktop server.
|
|
// Otherwise, if the file descriptor was the
|
|
// one associated with the unix socket rpc
|
|
// socket then this is a new connection
|
|
// request.
|
|
//
|
|
// Note that the _Tt_rpc_server::run method
|
|
// will indicate which fd was active by
|
|
// negating its value thus the test for being
|
|
// less than zero indicates that was the fd we
|
|
// were looking for.
|
|
|
|
fds.reset(_active_fds);
|
|
fd_procid.reset(_active_fds_procids);
|
|
while (fds.next() && fd_procid.next()) {
|
|
if (fds->val < 0) {
|
|
if (*fd_procid == "X") {
|
|
// X event came in
|
|
fds->val *= -1;
|
|
if (initial_session->desktop_event_callback()==-1) {
|
|
exit_main_loop = 1;
|
|
xfd = -2;
|
|
break;
|
|
}
|
|
#ifdef OPT_UNIX_SOCKET_RPC
|
|
} else if ((0 - fds->val)==unix_fd) {
|
|
// connection request
|
|
// for local rpc transport.
|
|
|
|
fds->val = unix_fd;
|
|
initial_s_session->u_rpc_init();
|
|
#endif // OPT_UNIX_SOCKET_RPC
|
|
} else {
|
|
// signalling channel
|
|
// became active for
|
|
// some procid. This
|
|
// means the
|
|
// connection was lost
|
|
// since the
|
|
// signalling channel
|
|
// is a write-only
|
|
// connection.
|
|
if (active_procs->lookup(*fd_procid,sp)) {
|
|
// Before cleaning up,
|
|
// send any on_exit
|
|
// messages.
|
|
sp->send_on_exit_messages();
|
|
sp->set_active(-1);
|
|
active_procs->remove(sp->id());
|
|
}
|
|
fds.remove();
|
|
fd_procid.remove();
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Returns 1 if there exist file-scope patterns for the given pathname.
|
|
// Uses the two parallel lists _file_scope_paths and
|
|
// _file_scope_refcounts which form a logical list of records of file
|
|
// pathnames to number of patterns registered.
|
|
//
|
|
// XXX: Use of parallel lists is confusing. Recoding using a single list
|
|
// of records would improve readability.
|
|
//
|
|
int _Tt_s_mp::
|
|
in_file_scope(const _Tt_string &f)
|
|
{
|
|
if (_file_scope_refcounts.is_null()) {
|
|
return(0);
|
|
}
|
|
_Tt_int_rec_list_cursor refcounts(_file_scope_refcounts);
|
|
_Tt_string_list_cursor paths(_file_scope_paths);
|
|
|
|
while (refcounts.next() && paths.next()) {
|
|
if (*paths == f) {
|
|
return(1);
|
|
}
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
|
|
//
|
|
// Adds (subtracts) number of file-scope patterns registered for the
|
|
// given pathname if add_scope is 1 (0). If the refcount of patterns goes
|
|
// to 0 then the pathname is removed from the _file_scope_refcounts and
|
|
// _file_scope_paths lists. See comment for _Tt_s_mp::in_file_scope for
|
|
// an explanation of these lists.
|
|
//
|
|
void _Tt_s_mp::
|
|
mod_file_scope(const _Tt_string &f, int add_scope)
|
|
{
|
|
if (_file_scope_refcounts.is_null()) {
|
|
_file_scope_refcounts = new _Tt_int_rec_list();
|
|
_file_scope_paths = new _Tt_string_list();
|
|
}
|
|
|
|
_Tt_int_rec_list_cursor refcounts(_file_scope_refcounts);
|
|
_Tt_string_list_cursor paths(_file_scope_paths);
|
|
|
|
while (refcounts.next() && paths.next()) {
|
|
if (*paths == f) {
|
|
refcounts->val += (add_scope ? 1 : -1);
|
|
if (refcounts->val == 0) {
|
|
refcounts.remove();
|
|
paths.remove();
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
if (add_scope) {
|
|
_file_scope_refcounts->push(new _Tt_int_rec(1));
|
|
_file_scope_paths->push(f);
|
|
}
|
|
}
|
|
|
|
|
|
Tt_status
|
|
_Tt_s_mp::add_procid(
|
|
_Tt_s_procid_ptr &proc
|
|
)
|
|
{
|
|
_active_fds->push(new _Tt_int_rec(-1));
|
|
_active_fds_procids->push(proc->id());
|
|
active_procs->insert(proc);
|
|
_last_proc_hit = proc;
|
|
return TT_OK;
|
|
}
|
|
|
|
|
|
//
|
|
// Called in response to a client invoking the tt_close api call. This
|
|
// method will deallocate any resources that this procid holds and will
|
|
// remove the procid reference from any global data-structures.
|
|
//
|
|
Tt_status _Tt_s_mp::
|
|
s_remove_procid(_Tt_s_procid &proc)
|
|
{
|
|
proc.cancel_on_exit_messages();
|
|
// de-activate this procid
|
|
proc.set_active(0);
|
|
// remove from list of active procs
|
|
active_procs->remove(proc.id());
|
|
|
|
return(TT_OK);
|
|
}
|