|
|
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 d
Length: 14058 (0x36ea)
Types: TextFile
Names: »di_block.c«
└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0
└─⟦35176feda⟧ »EurOpenD22/isode/isode-6.tar.Z«
└─⟦de7628f85⟧
└─⟦this⟧ »isode-6.0/quipu/di_block.c«
/* di_block.c - routines to handle operation activity blocks */
#ifndef lint
static char *rcsid = "$Header: /f/osi/quipu/RCS/di_block.c,v 7.1 89/12/19 16:20:09 mrose Exp $";
#endif
/*
* $Header: /f/osi/quipu/RCS/di_block.c,v 7.1 89/12/19 16:20:09 mrose Exp $
*
*
* $Log: di_block.c,v $
* Revision 7.1 89/12/19 16:20:09 mrose
* sync
*
* Revision 7.0 89/11/23 22:17:00 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"
#include "tsap.h"
#include "tailor.h"
extern LLog * log_dsap;
struct di_block *di_alloc()
{
struct di_block * di_ret;
di_ret = (struct di_block *) calloc(1,sizeof(struct di_block));
return(di_ret);
}
di_free(di)
struct di_block *di;
{
DLOG(log_dsap, LLOG_TRACE, ("di_free()"));
switch (di->di_state) {
case DI_GLOBAL: break;
case DI_TASK: break;
case DI_OPERATION: break;
default:
DLOG(log_dsap, LLOG_TRACE, ("di_free() of unknown type %d",di->di_state));
return;
}
dn_free(di->di_dn);
dn_free(di->di_target);
if(di->di_accesspoints != NULLACCESSPOINT)
aps_free(di->di_accesspoints);
di->di_state = -1;
free((char *)di);
}
di_extract(old_di)
struct di_block * old_di;
{
struct di_block * di;
struct di_block **next_di;
LLOG(log_dsap, LLOG_TRACE, ("di_extract"));
#ifdef DEBUG
di_log(old_di);
#endif
switch(old_di->di_type)
{
case DI_GLOBAL:
next_di = &(deferred_dis);
for(di=deferred_dis; di!=NULL_DI_BLOCK; di=di->di_next)
{
if(di == old_di)
break;
next_di = &(di->di_next);
}
if(di == NULL_DI_BLOCK)
{
LLOG(log_dsap, LLOG_EXCEPTIONS, ("di_block has escaped from global list"));
}
else
{
(*next_di) = di->di_next;
}
break;
case DI_OPERATION:
break;
case DI_TASK:
break;
default:
break;
}
di_free(old_di);
}
di_desist(di)
struct di_block * di;
{
struct di_block * di_tmp1;
struct di_block * di_tmp1_next;
struct di_block * di_tmp2;
struct di_block **di_p2;
DLOG(log_dsap, LLOG_TRACE, ("di_desist()"));
for(di_tmp1=di; di_tmp1 != NULL_DI_BLOCK; di_tmp1 = di_tmp1_next)
{
di_tmp1_next = di_tmp1->di_next;
switch(di->di_state)
{
case DI_ACCESSPOINT:
case DI_COMPLETE:
break;
case DI_DEFERRED:
di_p2 = &(di_tmp1->di_perform->on_wake_list);
for(di_tmp2=di_tmp1->di_perform->on_wake_list; di_tmp2!=NULL_DI_BLOCK; di_tmp2=di_tmp2->di_wake_next)
{
if(di_tmp2 == di_tmp1)
break;
di_p2 = &(di_tmp2->di_wake_next);
}
if(di_tmp2 == NULL_DI_BLOCK)
{
LLOG(log_dsap, LLOG_EXCEPTIONS, ("di_desist - di_block lost from performing operations wake up list"));
}
else
{
(*di_p2) = di_tmp2->di_wake_next;
}
break;
}
di_free(di_tmp1);
}
}
di_log(di)
struct di_block * di;
{
DLOG (log_dsap,LLOG_DEBUG, ("di_block [%x] , state = %d, type = %d",
di, di->di_state, di->di_type));
}
di_list_log(di)
struct di_block *di;
{
struct di_block * di_tmp;
DLOG(log_dsap, LLOG_DEBUG, ("di_list:"));
#ifdef DEBUG
for(di_tmp = di; di_tmp!=NULL_DI_BLOCK; di_tmp=di_tmp->di_next)
{
di_log(di_tmp);
}
#endif
DLOG(log_dsap, LLOG_DEBUG, ("di_list ends."));
}
static struct dn_seq * prefer_dsa_list = NULLDNSEQ;
prefer_dsa (str)
char * str;
{
struct dn_seq * dsa, *loop;
if (( dsa=str2dnseq(str)) == NULLDNSEQ) {
LLOG (log_dsap,LLOG_EXCEPTIONS,("Invalid prefered DSA name %s",str));
return;
}
if (prefer_dsa_list == NULLDNSEQ)
prefer_dsa_list = dsa;
else {
for (loop = prefer_dsa_list; loop->dns_next != NULLDNSEQ; loop=loop->dns_next)
;
loop->dns_next = dsa;
}
}
static di_prefer_dsa (a,b)
DN a,b;
{
int x,y;
if (prefer_dsa_list == NULLDNSEQ) {
DLOG (log_dsap,LLOG_TRACE,("NO DSAs to chose from"));
return 0; /* not fussy !!! */
}
if ((b == NULLDN) || (a == NULLDN)) {
DLOG (log_dsap,LLOG_NOTICE,("di_pref DNs NULL"));
return 0; /* safty catch - don't think it can happen */
}
if ((x = dn_in_dnseq (a,prefer_dsa_list)) == 0)
if ((y = dn_in_dnseq (b,prefer_dsa_list)) == 0)
return 0;
else {
DLOG (log_dsap,LLOG_TRACE,("DSA selected on preference"));
return -1;
}
if ((y = dn_in_dnseq (b,prefer_dsa_list)) == 0) {
DLOG (log_dsap,LLOG_TRACE,("DSA selected on preference"));
return 1;
}
if ( x != y ) {
DLOG (log_dsap,LLOG_TRACE,("DSA selected on preference"));
return ( x > y ? -1 : 1 );
}
return 0;
}
static di_ap2comp (di)
struct di_block **di;
{
struct di_block *loop;
Entry eptr;
/* replace DI_ACCESSPOINT with DI_COMPLETE if possible... */
/* (data may have been cached since creating DI_ACCESSPOINT) */
for (loop= *di; loop!=NULL_DI_BLOCK; loop=loop->di_next) {
if (loop->di_state != DI_ACCESSPOINT)
continue;
if (loop->di_reftype == RT_NONSPECIFICSUBORDINATE)
continue; /* can't split these - all must be followed... */
if (loop->di_accesspoints->ap_next == NULLACCESSPOINT) {
(void) dn_decode (loop->di_accesspoints->ap_name);
if ((eptr=local_find_entry (loop->di_accesspoints->ap_name,FALSE)) != NULLENTRY)
if (eptr->e_dsainfo != NULLDSA) {
loop->di_entry = eptr;
loop->di_state = DI_COMPLETE;
aps_free (loop->di_accesspoints);
loop->di_accesspoints = NULLACCESSPOINT;
}
} else
LLOG (log_dsap,LLOG_EXCEPTIONS,("Many access points, but not a RT_NONSPECIFICSUBORDINATE"));
}
}
dsa_reliable (cn,good,when)
struct connection * cn;
char good;
time_t when;
{
Entry ptr;
if ( (ptr=local_find_entry(cn->cn_what,FALSE)) == NULLENTRY)
return;
if (ptr->e_dsainfo == NULLDSA)
return;
ptr->e_dsainfo->dsa_last_attempt = when;
if (good) {
ptr->e_dsainfo->dsa_last_success = when;
ptr->e_dsainfo->dsa_failures = 0;
} else
ptr->e_dsainfo->dsa_failures++;
}
static di_cmp_reliability (a,b)
struct di_block *a, *b;
{
time_t timenow;
extern time_t retry_timeout, time();
struct dsa_info *da, *db;
/* If we have used a DSA recently, with no failures - use it again */
if ((da = a->di_entry->e_dsainfo) == NULLDSA)
return 0;
if ((db = b->di_entry->e_dsainfo) == NULLDSA)
return 0;
timenow = time((time_t *) 0);
if (da->dsa_last_attempt == (time_t)0) {
if (db->dsa_failures == 0) {
if ((db->dsa_last_success != (time_t)0)
&& (timenow - db->dsa_last_attempt < retry_timeout))
return -1; /* b worked recently */
} else if (timenow - db->dsa_last_attempt < retry_timeout)
return 1; /* b failed recently */
return 0; /* have not tried either recently */
} else if (db->dsa_last_attempt == (time_t)0) {
if (da->dsa_failures == 0) {
if ((da->dsa_last_success != (time_t)0)
&& (timenow - da->dsa_last_attempt < retry_timeout))
return 1; /* a worked recentdlry */
} else if (timenow - da->dsa_last_attempt < retry_timeout)
return -1; /* a failed recently */
return 0; /* have not tried either recently */
}
if (da->dsa_failures == 0) {
if (db->dsa_failures == 0)
return 0; /* both OK */
return 1; /* a worked last time, b failed - use a */
}
if (db->dsa_failures == 0)
return -1; /* b worked last time, a failed - use b */
/* both failed last time - see if either have suceeded recently */
if ((timenow - da->dsa_last_success) > retry_timeout ) {
if ((timenow - db->dsa_last_success) > retry_timeout)
return 0; /* too long ago to tell */
return -1; /* use b it worked not that long ago... */
}
if ((timenow - db->dsa_last_success) > retry_timeout)
return 1; /* use a it worked not that long ago... */
/* neither has worked recently chose some other way */
return 0;
}
static di_cmp_address (a,b)
struct di_block *a, *b;
{
struct NSAPaddr *na;
struct NSAPaddr *nb;
struct NSAPaddr nas;
struct TSAPaddr *ta2norm();
struct TSAPaddr *ta;
struct TSAPaddr *tb;
int *ip;
extern DN mydsadn;
DN dnptr, mydnptr, dna,dnb;
int ma,mb;
/* select DSA with best looking address !!! */
if (a->di_state == DI_COMPLETE) {
ta = &(a->di_entry->e_dsainfo->dsa_addr->pa_addr.sa_addr);
tb = &(b->di_entry->e_dsainfo->dsa_addr->pa_addr.sa_addr);
dna = a->di_dn;
dnb = b->di_dn;
} else {
/* Use 1 access point only */
ta = &(a->di_accesspoints->ap_address->pa_addr.sa_addr);
tb = &(b->di_accesspoints->ap_address->pa_addr.sa_addr);
(void) dn_decode (dna = a->di_accesspoints->ap_name);
(void) dn_decode (dnb = b->di_accesspoints->ap_name);
}
/* ta2norm return a static buffer */
ta = ta2norm (ta);
nas = *(ta->ta_addrs); /* struct copy */
na = &nas;
tb = ta2norm (tb);
nb = tb->ta_addrs;
/* normalised, so look for first "na" match with ts_communities */
for (ip = ts_communities; *ip; ip++) {
if (*ip == na->na_subnet) {
if (*ip == nb->na_subnet)
break; /* same primary community */
return 1; /* 'a' preferred */
}
if (*ip == nb->na_subnet)
return -1; /* 'b' preferred */
}
/* Look at the DSA name to detect locality */
ma=0;
for (dnptr=dna, mydnptr=mydsadn ;
(dnptr!=NULLDN) && (mydnptr!=NULLDN) ;
dnptr=dnptr->dn_parent, mydnptr=mydnptr->dn_parent) {
if (rdn_cmp(dnptr->dn_rdn,mydnptr->dn_rdn) == 0)
ma++;
}
mb=0;
for (dnptr=dnb, mydnptr=mydsadn ;
(dnptr!=NULLDN) && (mydnptr!=NULLDN) ;
dnptr=dnptr->dn_parent, mydnptr=mydnptr->dn_parent) {
if (rdn_cmp(dnptr->dn_rdn,mydnptr->dn_rdn) == 0)
mb++;
}
if (ma != mb)
return (ma > mb ? 1 : -1);
/* check the DMD - NYI */
return 0;
}
static di_cmp (a,b)
struct di_block *a, *b;
/*
* Select best di_block
* rule 1: deferred dsa infos have lowest preference,
* complete have highest.
*
* If two block have same state, select using
* preference 1: quipu DSAs with quipu context
* preference 2: quipu DSAs
* preference 3: reliable DSAs
* preference 4: local DSAs
*/
{
int x,y;
if (a->di_state != b->di_state)
return (a->di_state > b->di_state ? -1 : 1); /* rule 1 */
switch (a->di_state) {
case DI_DEFERRED:
break;
case DI_ACCESSPOINT:
if ((x = di_cmp_address(a,b)) != 0) {
DLOG (log_dsap,LLOG_TRACE,("AP selected on address"));
return x; /* preference 4 - no info to asses 1,2 or 3 */
}
break;
case DI_COMPLETE:
x = quipu_ctx_supported (a->di_entry);
y = quipu_ctx_supported (b->di_entry);
if ( x != y ) {
DLOG (log_dsap,LLOG_TRACE,("DSA selected on context"));
return ( x > y ? 1 : -1); /* preference 1 or 2 */
}
if ((x=di_cmp_reliability (a,b)) != 0) {
DLOG (log_dsap,LLOG_TRACE,("DSA selected on relibility"));
return x; /* preference 3 */
}
if ((x=di_cmp_address(a,b)) != 0) {
DLOG (log_dsap,LLOG_TRACE,("DSA selected on address"));
return x; /* preference 4 */
}
break;
}
return (di_prefer_dsa(a->di_dn, b->di_dn));
}
sort_dsa_list (dsas)
struct di_block **dsas;
{
struct di_block *trail;
struct di_block *old_di, *new_di;
struct di_block *result;
char changed = FALSE;
/* turn access point into complete references if possible */
di_ap2comp (dsas);
result = *dsas;
if ((old_di = result->di_next) == NULL_DI_BLOCK)
return; /* only 1 - must be sorted !!! */
result->di_next = NULL_DI_BLOCK;
for(; old_di != NULL_DI_BLOCK; ) {
trail = NULL_DI_BLOCK;
for(new_di = result; new_di != NULL_DI_BLOCK; new_di= new_di->di_next) {
if ( di_cmp (old_di,new_di) > 0 ) {
if (trail == NULL_DI_BLOCK) {
result = old_di;
old_di = old_di->di_next;
result->di_next = new_di;
} else {
trail->di_next = old_di;
old_di = old_di->di_next;
trail->di_next->di_next = new_di;
}
changed = TRUE;
break;
}
trail = new_di;
}
if (new_di == NULL_DI_BLOCK) {
trail->di_next = old_di;
old_di = old_di->di_next;
trail->di_next->di_next = NULL_DI_BLOCK;
}
}
*dsas = result;
if (changed) {
LLOG (log_dsap,LLOG_TRACE,("DSA order changed"));
#ifdef DEBUG
di_list_log (result);
#endif
} else
DLOG (log_dsap,LLOG_TRACE,("DSA order not changed"));
}
static common_address (a,tb)
struct di_block *a;
struct TSAPaddr *tb;
{
struct TSAPaddr *ta;
struct NSAPaddr *na;
struct NSAPaddr *nb;
int x,y;
/* select DSA with best looking address !!! */
if (a->di_state == DI_DEFERRED)
return FALSE;
if (a->di_state == DI_COMPLETE)
ta = &(a->di_entry->e_dsainfo->dsa_addr->pa_addr.sa_addr);
else
/* Use 1 access point only */
ta = &(a->di_accesspoints->ap_address->pa_addr.sa_addr);
/* compare ta and tb to see if they have a network in common */
for (na=ta->ta_addrs , x = ta->ta_naddr - 1 ;
x >= 0;
na++, x-- ) {
for (nb=tb->ta_addrs , y = tb->ta_naddr - 1 ;
y >= 0;
nb++, y-- ) {
if (na->na_subnet == nb->na_subnet)
return TRUE;
}
}
return FALSE;
}
struct di_block * select_refer_dsa(di,tk)
struct di_block *di;
struct task_act *tk;
{
struct di_block *best;
struct di_block *loop;
Entry eptr;
struct TSAPaddr *ta;
DN rdsa;
/* return the di block of the best DSA the other end should be
to contact...
If it can't contact any - return NULL
*/
if (di != NULL_DI_BLOCK)
best = di;
else
best = NULL_DI_BLOCK;
/* First set - find out who the remote end is... */
if (tk->tk_conn->cn_ctx == CN_CTX_X500_DAP)
return best; /* we will chain anyway - unless prevented by service control... */
/* Its a DSA - find its entry */
if (tk->tk_conn->cn_initiator == INITIATED_BY_THIS)
rdsa = tk->tk_conn->cn_what;
else
rdsa = tk->tk_conn->cn_who;
(void) dn_decode (rdsa);
if ((eptr=local_find_entry (rdsa,FALSE)) == NULLENTRY)
return best; /* no way of knowing */
if (eptr->e_dsainfo == NULLDSA)
return best; /* no way of knowing */
ta = &(eptr->e_dsainfo->dsa_addr->pa_addr.sa_addr);
ta = ta2norm (ta); /* calculate subnets... */
for (loop=di; loop!=NULL_DI_BLOCK; loop=loop->di_next)
if (common_address (loop,ta))
return loop;
/* nothing on the same network - chain if possible !!! */
return NULL_DI_BLOCK;
}