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

231 lines
6.9 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_c_file.C /main/3 1995/10/23 10:19:32 rswiston $
/*
* Tool Talk Message Passer (MP) - mp_c_file.cc
*
* Copyright (c) 1990,1992 by Sun Microsystems, Inc.
*
* Implementation of the _Tt_file class representing a document.
*/
#include <stdio.h>
#include <unistd.h>
#include "mp/mp_c_file.h"
#include "mp/mp_c_mp.h"
#include "mp/mp_c_global.h"
#include "mp/mp_rpc_interface.h"
#include "mp/mp_c_session.h"
#include "mp/mp_c_procid.h"
#include "mp/mp_c_message.h"
#include "api/c/api_error.h"
#include "util/tt_port.h"
//
// Use parent class (_Tt_file) for construction and destruction.
//
_Tt_c_file::_Tt_c_file()
{
}
_Tt_c_file::_Tt_c_file(
_Tt_string path
) :
_Tt_file( path )
{
}
_Tt_c_file::~_Tt_c_file()
{
}
//
// Joins the indicated file on behalf of the default procid. Joining a file
// means that any file-scoped patterns for this procid are updated to
// contain this file. It also means we have to indicated to procids in
// other sessions that this procid is interested in messages addressed to
// this file. This is done by storing the session for this procid in a
// persistent property on this file. The details of that are in
// _Tt_file::add_joined_file. Another responsibility of this method is to
// process any queued messages that are destined for any ptype declared
// by p. This client/server division in the way file-scope queued
// messages are implemented reflects a goal of offloading any
// computation from the server to its clients. This is specially true
// of any computation that involves communicating with the database
// servers.
//
// XXX: it's misleading to have a _Tt_procid_ptr input arg here when
// in fact the default procid joins the file, not the specified
// procid. Either figure out how to join the specified procid or
// remove the parameter.
//
Tt_status
_Tt_c_file::c_join(
_Tt_procid_ptr &
)
{
Tt_status status;
Tt_status rs;
_Tt_db_results dbStatus;
_Tt_file_join_args args;
_Tt_session_ptr d_session;
_Tt_c_procid *sp;
sp = (_Tt_c_procid *)_tt_c_mp->default_procid().c_pointer();
args.procid = _tt_c_mp->default_procid();
args.path = getNetworkPath();
d_session = sp->default_session();
rs = d_session->call(TT_RPC_JOIN_FILE,
(xdrproc_t)tt_xdr_file_join_args,
(char *)&args,
(xdrproc_t)xdr_int,
(char *)&status);
if (status == TT_WRN_NOTFOUND) {
// No file patterns updated on the server side.
status = TT_OK;
} else {
sp->add_joined_file(getNetworkPath());
// add our session to the list of sessions
// interested in this file.
if (status == TT_WRN_STALE_OBJID) {
dbStatus = addSession(d_session->process_tree_id());
status = _tt_get_api_error( dbStatus, _TT_API_FILE );
if (status == TT_ERR_INTERNAL) {
_tt_syslog( 0, LOG_WARNING,
"_Tt_db_file::addSession(): %d",
dbStatus );
}
}
if (status != TT_OK) {
return status;
}
// process any queued messages on this file
// for any of the ptypes we've declared.
process_message_queue();
}
return((rs == TT_OK) ? status : rs);
}
//
// Removes the session for the given procid from the list of interested
// sessions in this file. This method also invokes an rpc on the server
// session to remove this file from the patterns registered by this
// procid. The rpc call to the session will return a special status code
// TT_WRN_STALE_OBJID if this method is to actually remove the session
// from the file property of interested sessions. This is because the
// server session keeps a counter of how many procids are interested in
// each file.
//
Tt_status
_Tt_c_file::c_quit(
_Tt_procid_ptr &p
)
{
_Tt_file_join_args args;
Tt_status rs;
Tt_status status;
_Tt_session_ptr d_session;
if (p.is_null()) {
return(TT_ERR_PROCID);
}
d_session = ((_Tt_c_procid *)p.c_pointer())->default_session();
if (d_session.is_null()) {
return(TT_ERR_SESSION);
}
args.procid = p;
args.path = getNetworkPath();
rs = d_session->call(TT_RPC_QUIT_FILE,
(xdrproc_t)tt_xdr_file_join_args,
(char *)&args,
(xdrproc_t)xdr_int,
(char *)&status);
if (status == TT_WRN_NOTFOUND) {
status = TT_OK;
} else if (status == TT_WRN_STALE_OBJID) {
_Tt_db_results dbStatus;
dbStatus = deleteSession( d_session->process_tree_id() );
if (dbStatus == TT_DB_ERR_NO_SUCH_PROPERTY) {
status = TT_OK;
} else {
status = _tt_get_api_error( dbStatus, _TT_API_FILE );
}
if (status == TT_ERR_INTERNAL) {
_tt_syslog( 0, LOG_WARNING,
"_Tt_db_file::deleteSession(): %d",
dbStatus );
status = TT_ERR_INTERNAL;
}
}
p->del_joined_file(getNetworkPath());
return((status == TT_OK) ? rs : status);
}
//
// Proces any queued messages in this file. If so, then for each
// message destined for a ptype declared by the current default
// procid, retrieve the message and dispatch it to our current
// session. Note that messages are stored only once even if they're
// destined for multiple ptypes so we only de-queue the message if
// there are no destination ptypes once we're done dispatching the
// message.
//
// The exact layout of how messages are stored is described in
// _Tt_file::q_message below.
//
Tt_status
_Tt_c_file::process_message_queue(
int dispatch_msgs
)
{
_Tt_message_list_ptr msgs;
Tt_status status;
_Tt_db_results dbStatus;
dbStatus = dequeueMessages( _tt_c_mp->default_procid()->ptypes(),
msgs );
status = _tt_get_api_error( dbStatus, _TT_API_FILE );
if (status != TT_OK) {
if (status == TT_ERR_INTERNAL) {
_tt_syslog( 0, LOG_WARNING,
"_Tt_db_file::dequeueMessages(): %d",
dbStatus );
}
return status;
}
if (! dispatch_msgs) {
return TT_OK;
}
_Tt_message_list_cursor msg( msgs );
while (msg.next()) {
msg->set_state( TT_QUEUED );
(void)((_Tt_c_message *)(*msg).c_pointer())->dispatch( 1 );
}
return TT_OK;
}