|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T t
Length: 10751 (0x29ff)
Types: TextFile
Names: »task_select.c«
└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0
└─⟦35176feda⟧ »EurOpenD22/isode/isode-6.tar.Z«
└─⟦de7628f85⟧
└─⟦this⟧ »isode-6.0/quipu/task_select.c«
/* task_select.c - tidy connection mesh and select next DSA activity */
#ifndef lint
static char *rcsid = "$Header: /f/osi/quipu/RCS/task_select.c,v 7.1 89/12/19 16:20:51 mrose Exp $";
#endif
/*
* $Header: /f/osi/quipu/RCS/task_select.c,v 7.1 89/12/19 16:20:51 mrose Exp $
*
*
* $Log: task_select.c,v $
* Revision 7.1 89/12/19 16:20:51 mrose
* sync
*
* Revision 7.0 89/11/23 22:18:15 mrose
* Release 6.0
*
*/
/*
* NOTICE
*
* Acquisition, use, and distribution of this module and related
* materials are subject to the restrictions of a license agreement.
* Consult the Preface in the User's Manual for the full terms of
* this agreement.
*
*/
#include "quipu/util.h"
#include "quipu/connection.h"
extern LLog * log_dsap;
extern time_t conn_timeout;
extern time_t nsap_timeout;
extern time_t slave_timeout;
extern time_t time();
time_t lastedb_update;
struct task_act * task_select(secs_p)
int * secs_p;
{
struct connection * cn;
struct connection * cn_tmp;
struct connection **next_cn;
struct task_act * tk;
struct task_act **next_tk;
struct oper_act * edbon;
struct oper_act **next_edbon = (struct oper_act **)NULL;
struct oper_act * on;
time_t time_now;
int timeout_tmp;
char process_edbs = TRUE;
char do_timeout;
int suspended = FALSE;
struct task_act * ret_tk = NULLTASK;
extern char startup_update;
time_now = time((time_t *) 0);
(*secs_p) = NOTOK;
conns_used = 0;
/*
DLOG(log_dsap, LLOG_DEBUG, ("task_select connections:"));
conn_list_log(connlist);
*/
for(cn=connlist; cn!=NULLCONN; cn=cn_tmp)
{
cn_tmp = cn->cn_next; /* Nasty but necessary in conn_extract()
manages to get itself called somehow */
do_timeout = FALSE;
conn_log(cn);
next_tk = &(cn->cn_tasklist);
for(tk=cn->cn_tasklist; tk!=NULLTASK; tk=(*next_tk))
{
if(tk->tk_timed)
{
if(tk->tk_timeout <= time_now)
{
#ifdef DEBUG
long clock;
struct UTCtime ut;
struct UTCtime ut2;
DLOG(log_dsap, LLOG_TRACE, ("task has timelimit of %ld", tk->tk_timeout));
tm2ut(gmtime(&(tk->tk_timeout)), &ut);
DLOG(log_dsap, LLOG_DEBUG, ("converted timelimit = %s", utct2str(&(ut))));
(void) time(&clock);
tm2ut(gmtime(&(clock)), &ut2);
DLOG(log_dsap, LLOG_DEBUG, ("time now = %s", utct2str(&(ut2))));
#endif
(*next_tk) = tk->tk_next;
timeout_task(tk);
continue;
}
else
{
timeout_tmp = (int) tk->tk_timeout - time_now;
if(((*secs_p) == NOTOK) || ((*secs_p) > timeout_tmp))
{
(*secs_p) = timeout_tmp;
}
}
}
next_tk = &(tk->tk_next);
}
if(cn->cn_state == CN_OPEN)
{
next_tk = &(cn->cn_tasklist);
for(tk=cn->cn_tasklist; tk!=NULLTASK; tk=(*next_tk))
{
next_tk = &(tk->tk_next);
if(tk->tk_state == TK_ACTIVE)
{
if( (ret_tk == NULLTASK)
|| (tk->tk_prio > ret_tk->tk_prio)
|| ( (tk->tk_prio == ret_tk->tk_prio)
&& ( (!ret_tk->tk_timed)
|| ( (tk->tk_timed)
&& (tk->tk_timeout < ret_tk->tk_timeout)
)
)
)
)
{
ret_tk = tk;
}
}
if(tk->tk_state == TK_SUSPEND)
{
/*
* A task suspended to allow the network to be polled.
* Set suspended to force polling.
*/
tk->tk_state = TK_ACTIVE;
suspended = TRUE;
}
}
if(cn->cn_tasklist == NULLTASK)
{
if(cn->cn_initiator == INITIATED_BY_THIS)
{
if(cn->cn_operlist == NULLOPER)
{
if((cn->cn_last_used + conn_timeout) <= time_now)
{
do_timeout = TRUE;
}
else
{
timeout_tmp = (int) (cn->cn_last_used + conn_timeout) - time_now;
if(((*secs_p) == NOTOK) || ((*secs_p) > timeout_tmp))
{
(*secs_p) = timeout_tmp;
}
}
}
else
{
timeout_tmp = conn_timeout; /* safety catch */
if ((tk = cn->cn_operlist->on_task) != NULLTASK) {
if (tk->tk_timed)
timeout_tmp = (int) tk->tk_timeout - time_now;
} else {
char alive = FALSE;
/* is there still an operation active ? */
for(on=cn->cn_operlist; on!=NULLOPER; on=on->on_next_conn) {
if (on->on_state != ON_ABANDONED) {
alive = TRUE;
break;
}
}
if (!alive) {
oper_free (cn->cn_operlist);
cn->cn_operlist = NULLOPER;
}
}
if(((*secs_p) == NOTOK) || ((*secs_p) > timeout_tmp))
{
(*secs_p) = timeout_tmp;
}
cn->cn_last_used = time_now;
}
}
}
else
{
cn->cn_last_used = time_now;
process_edbs = FALSE;
}
} else {
if((cn->cn_last_used + nsap_timeout) <= time_now)
{
if ((cn->cn_state == CN_CONNECTING1) || (cn->cn_state == CN_CONNECTING2))
conn_retry(cn);
else if (cn->cn_state == CN_CLOSING) {
if (conn_release_retry(cn) == NOTOK) {
/* had its chance - abort */
do_ds_unbind(cn);
conn_rel_abort (cn);
conn_extract(cn);
}
} else if (cn->cn_state == CN_OPENING) {
/* something started to associate - then gave up !!! */
conn_rel_abort (cn);
conn_extract (cn);
}
(*secs_p) = nsap_timeout;
}
else
{
timeout_tmp = (int) (cn->cn_last_used + nsap_timeout) - time_now;
if(((*secs_p) == NOTOK) || ((*secs_p) > timeout_tmp))
{
(*secs_p) = timeout_tmp;
}
}
}
if(do_timeout)
{
LLOG(log_dsap, LLOG_NOTICE, ("Timing out connection %d",cn->cn_ad));
if (conn_release(cn) == NOTOK) {
(*secs_p) = nsap_timeout;
conns_used++;
}
}
else
{
conns_used++;
}
}
/*
* Open the connection with the highest priority operation
* waiting on it...
*
* Get DSA Info operations are highest priority, followed by
* NameService, BIND_COMPARE, and X500, and finally GetEDB
* operations.
*/
next_cn = &(connwaitlist);
for(cn=connwaitlist; cn!=NULLCONN; cn=(*next_cn))
{
if(conns_used >= MAX_CONNS)
break;
for(on=cn->cn_operlist; on!=NULLOPER; on=on->on_next_conn)
{
if(on->on_type == ON_TYPE_GET_DSA_INFO)
{
(*next_cn) = cn->cn_next;
if(conn_request(cn) == OK)
{
conns_used++;
cn->cn_next = connlist;
connlist = cn;
cn->cn_last_used = time_now;
/* Do something with the operations */
}
else
{
/* Do something with the operations */
}
break;
}
}
if(on == NULLOPER)
next_cn = &(cn->cn_next);
}
next_cn = &(connwaitlist);
for(cn=connwaitlist; cn!=NULLCONN; cn=(*next_cn))
{
if(conns_used >= (MAX_CONNS - CONNS_RESERVED_DI))
break;
for(on=cn->cn_operlist; on!=NULLOPER; on=on->on_next_conn)
{
if(on->on_type != ON_TYPE_GET_EDB)
{
(*next_cn) = cn->cn_next;
if(conn_request(cn) == OK)
{
conns_used++;
cn->cn_next = connlist;
connlist = cn;
cn->cn_last_used = time_now;
/* Do something with the operations */
}
else
{
/* Do something with the operations */
}
break;
}
}
if(on == NULLOPER)
next_cn = &(cn->cn_next);
}
next_cn = &(connwaitlist);
for(cn=connwaitlist; cn!=NULLCONN; cn=(*next_cn))
{
if(conns_used >= (MAX_CONNS - CONNS_RESERVED_DI - CONNS_RESERVED_X500))
break;
(*next_cn) = cn->cn_next;
if(conn_request(cn) == OK)
{
conns_used++;
cn->cn_next = connlist;
connlist = cn;
cn->cn_last_used = time_now;
/* Do something with the operations */
}
else
{
/* Do something with the operations */
}
}
if(process_edbs)
{
/*
* Nothing is happening that would be disturbed by writing back
* a retrieved EDB so it is a good time to process them.
*/
next_edbon = &(get_edb_ops);
for(edbon=get_edb_ops; edbon!=NULLOPER; edbon=(*next_edbon))
{
if(edbon->on_state == ON_COMPLETE)
{
(*next_edbon) = edbon->on_next_task;
process_edb(edbon);
oper_conn_extract(edbon);
oper_free(edbon);
(*secs_p) = 0; /* Give edb op's conn a chance to time out */
continue;
} else if (edbon->on_state == ON_ABANDONED) {
LLOG (log_dsap,LLOG_NOTICE,("Get edb has been abandoned"));
(*next_edbon) = edbon->on_next_task;
oper_free(edbon);
}
next_edbon = &(edbon->on_next_task);
}
if ((get_edb_ops == NULLOPER) && startup_update ) {
/* see if cache timer has expired - if so resend edb ops... */
if ( (time_now - lastedb_update) >= slave_timeout )
slave_update();
}
}
if ((get_edb_ops == NULLOPER) && startup_update ) {
/* make sure we are awake for the next EDB update */
if ((timeout_tmp = lastedb_update + slave_timeout - time_now) >= 0)
if (((*secs_p) == NOTOK) || ((*secs_p) > timeout_tmp))
(*secs_p) = timeout_tmp;
}
if(suspended)
{
/*
* A task suspended in order for the network to be checked.
* Force this to happen by setting the selected task to NULL
* and the polling time of the network to 0 secs.
*/
ret_tk = NULLTASK;
(*secs_p) = 0;
}
return(ret_tk);
}
timeout_task(tk)
struct task_act * tk;
{
struct oper_act * on;
struct DSError * err = &(tk->tk_resp.resp_err);
struct ds_search_task *tmp;
DLOG(log_dsap, LLOG_TRACE, ("timeout_task"));
for(on=tk->tk_operlist; on!=NULLOPER; on=on->on_next_task)
{
/* Time out operations started by task */
on->on_state = ON_ABANDONED;
on->on_task = NULLTASK;
}
if(tk->tk_req.dca_dsarg.arg_type != OP_SEARCH)
{
err->dse_type = DSE_SERVICEERROR;
if (tk->tk_timed == TRUE)
err->ERR_SERVICE.DSE_sv_problem = DSE_SV_TIMELIMITEXCEEDED;
else /* tk->tk_timed == 2 */
err->ERR_SERVICE.DSE_sv_problem = DSE_SV_ADMINLIMITEXCEEDED;
task_error(tk);
task_extract(tk);
}
else
{
/* Do search collation */
if ((tk->tk_state == TK_ACTIVE) && (tk->local_st == NULL_ST)) {
/* nothing happened yet... */
err->dse_type = DSE_SERVICEERROR;
if (tk->tk_timed == TRUE)
err->ERR_SERVICE.DSE_sv_problem = DSE_SV_TIMELIMITEXCEEDED;
else /* tk->tk_timed == 2 */
err->ERR_SERVICE.DSE_sv_problem = DSE_SV_ADMINLIMITEXCEEDED;
task_error(tk);
} else {
/* send the results we have got... */
tk->tk_result = &(tk->tk_resp.resp_res);
tk->tk_result->dcr_dsres.result_type = tk->tk_req.dca_dsarg.arg_type;
tk->tk_resp.resp_type = RESP_TYPE_RET;
tk->tk_resp.ret_type = RET_TYPE_RES;
if (tk->tk_timed == TRUE)
tk->tk_resp.resp_res.dcr_dsres.res_sr.CSR_limitproblem = LSR_TIMELIMITEXCEEDED;
else /* tk->tk_timed == 2 */
tk->tk_resp.resp_res.dcr_dsres.res_sr.CSR_limitproblem = LSR_ADMINSIZEEXCEEDED;
/* Go through sub-tasks and add a POQ for each */
for(tmp=tk->referred_st; tmp!= NULL_ST; tmp=tmp->st_next)
add_cref2poq (&tk->tk_result->dcr_dsres.res_sr,tmp->st_cr);
task_result(tk);
}
task_extract(tk);
}
}