BSD 4_3_Net_2 development
[unix-history] / usr / src / contrib / isode / quipu / shadow.c
/* shadow.c - spot shadowing of entries */
#ifndef lint
static char *rcsid = "$Header: /f/osi/quipu/RCS/shadow.c,v 7.2 91/03/09 11:57:05 mrose Exp $";
#endif
/*
* $Header: /f/osi/quipu/RCS/shadow.c,v 7.2 91/03/09 11:57:05 mrose Exp $
*
*
* $Log: shadow.c,v $
* Revision 7.2 91/03/09 11:57:05 mrose
* update
*
* Revision 7.1 91/02/22 09:39:50 mrose
* Interim 6.8
*
* Revision 7.0 90/12/01 18:08:35 mrose
* *** empty log message ***
*
*/
/*
* 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/read.h"
#include "quipu/dua.h"
#include "quipu/connection.h"
#include "quipu/malloc.h"
#ifndef NO_STATS
extern LLog * log_stat;
#endif
extern LLog * log_dsap;
static struct dn_seq * shades = NULLDNSEQ;
static struct dn_seq * dn_shades = NULLDNSEQ;
extern struct dn_seq * dn_seq_push();
extern struct di_block * di_alloc();
extern struct oper_act * oper_alloc();
extern DN mydsadn;
extern LLog * log_dsap;
extern Entry entry_cpy ();
extern Entry database_root;
extern char * new_version ();
extern int dn_print ();
extern Attr_Sequence as_comp_cpy ();
extern Attr_Sequence entry_find_type ();
extern struct access_point * ap_cpy();
extern time_t timenow;
extern Entry make_path();
extern Entry local_find_entry_aux();
extern AttributeType at_subord;
extern AttributeType at_xref;
extern AttributeType at_nssr;
extern AttributeType at_objectclass;
extern Attr_Sequence cpy_as_comp();
extern short syntax_dn;
typedef struct _atlist {
AttributeType at;
struct _atlist *next;
} *atlist;
#define NULLATL (atlist)NULL
atlist at_list = NULLATL;
shadow_entry (eptr)
Entry eptr;
{
DN dn, ndn;
Attr_Sequence as;
AV_Sequence avs;
atlist at;
/* All MASTER entries get passed through here. */
/* See if it need shadowing, if so, add to shades */
if (eptr->e_data == E_DATA_MASTER) {
if ((eptr->e_dsainfo) &&
(quipu_ctx_supported (eptr) == 2) &&
(quipu_version_7 (eptr))) {
/* Its a version 7 quipuDSA */
dn = get_copy_dn (eptr);
if (dn_cmp (dn, mydsadn) == 0) {
dn_free (dn);
return; /* can't shadow myself ! */
}
if ( check_dnseq (shades, dn) == NOTOK)
shades = dn_seq_push (dn,shades);
dn_free (dn);
} else if ((eptr->e_external) && (eptr->e_reftype != RT_NONSPECIFICSUBORDINATE)) {
dn = get_copy_dn (eptr);
if ( check_dnseq (shades, dn) == NOTOK)
shades = dn_seq_push (dn,shades);
dn_free (dn);
}
}
for (as = eptr->e_attributes; as != NULLATTR; as=as->attr_link)
if (as->attr_type->oa_syntax == syntax_dn)
for (at = at_list; at != NULLATL; at=at->next)
if (as->attr_type == at->at) {
for (avs = as->attr_value; avs != NULLAV; avs = avs->avseq_next) {
ndn = (DN)avs->avseq_av.av_struct;
if (check_dnseq (dn_shades, ndn) == NOTOK)
dn_shades = dn_seq_push (ndn,dn_shades);
}
}
}
shadow_attribute (s)
char * s;
{
AttributeType at;
atlist new_atl;
if (( at = AttrT_new (s)) == NULLAttrT)
LLOG (log_dsap, LLOG_EXCEPTIONS, ("Unknown shadow attr %s",s));
else {
new_atl = (atlist) smalloc (sizeof (*new_atl));
new_atl->at = at;
new_atl->next = at_list;
at_list = new_atl;
}
}
shadow_update ()
{
struct dn_seq * dnseq;
struct oper_act * op;
static struct ds_read_arg sarg =
{
default_common_args,
NULLDN,
{ /* entry info selection */
TRUE,
NULLATTR,
EIS_ATTRIBUTESANDVALUES
}
};
Entry eptr;
DN tdn;
struct access_point * aps;
struct DSError err;
DLOG(log_dsap, LLOG_TRACE, ("shadow_update"));
for (dnseq = dn_shades; dnseq != NULLDNSEQ; dnseq = dnseq -> dns_next) {
if ((eptr = local_find_entry (dnseq -> dns_dn,FALSE)) == NULLENTRY) {
/* aliases !!! */
if ((eptr = local_find_entry (dnseq -> dns_dn,TRUE)) == NULLENTRY)
eptr = make_path (dnseq -> dns_dn);
else if ( eptr -> e_alias )
eptr = make_path (eptr -> e_alias);
}
else if ((eptr->e_data == E_TYPE_SLAVE) ||
(eptr->e_data == E_DATA_MASTER))
continue;
if ( check_dnseq (shades, dnseq -> dns_dn) == NOTOK)
shades = dn_seq_push (dnseq -> dns_dn,shades);
}
dn_seq_free (dn_shades);
dn_shades = NULLDNSEQ;
for (dnseq = shades; dnseq != NULLDNSEQ; dnseq = dnseq -> dns_next) {
if((op = oper_alloc()) == NULLOPER)
return;
op -> on_type = ON_TYPE_SHADOW;
op -> on_arg = &(op -> on_req);
op -> on_req.dca_dsarg.arg_type = OP_READ;
op -> on_req.dca_dsarg.arg_rd = sarg; /* struct copy */
op -> on_req.dca_dsarg.arg_rd.rda_object =
dn_cpy (dnseq -> dns_dn);
op -> on_req.dca_charg.cha_originator =
dn_cpy (mydsadn);
op -> on_req.dca_charg.cha_reftype = RT_SUBORDINATE;
op -> on_req.dca_charg.cha_progress.op_resolution_phase =
OP_PHASE_PROCEEDING;
op -> on_req.dca_charg.cha_progress.op_nextrdntoberesolved = -1;
for (tdn = dnseq -> dns_dn ; tdn != NULLDN ;
tdn = tdn -> dn_parent)
op ->
on_req.dca_charg.cha_progress.op_nextrdntoberesolved++;
op -> on_req.dca_charg.cha_trace =
(struct trace_info *) malloc (sizeof (struct trace_info));
op -> on_req.dca_charg.cha_trace -> ti_dsa =
dn_cpy (mydsadn);
op -> on_req.dca_charg.cha_trace -> ti_target =
dn_cpy (dnseq -> dns_dn);
op -> on_req.dca_charg.cha_trace -> ti_progress =
op -> on_req.dca_charg.cha_progress;
op -> on_req.dca_charg.cha_trace -> ti_next = NULLTRACEINFO;
op -> on_dsas = NULL_DI_BLOCK;
if ((eptr = local_find_entry_aux (dnseq -> dns_dn,FALSE)) == NULLENTRY) {
if ((eptr = local_find_entry_aux (dnseq -> dns_dn,TRUE)) == NULLENTRY) {
pslog (log_dsap,LLOG_EXCEPTIONS,"Shadow entry missing",
dn_print, (caddr_t) dnseq -> dns_dn);
oper_free (op);
continue;
}
} else if ( eptr -> e_external ) {
op -> on_dsas = di_alloc();
op -> on_dsas -> di_type = DI_TASK;
op -> on_dsas -> di_rdn_resolved = op ->
on_req.dca_charg.cha_progress.op_nextrdntoberesolved;
op -> on_dsas -> di_aliasedRDNs = CR_NOALIASEDRDNS;
op -> on_dsas -> di_oper = op;
op -> on_dsas -> di_type = DI_OPERATION;
op -> on_dsas -> di_target = dn_cpy (dnseq -> dns_dn);
op -> on_dsas -> di_reftype = eptr-> e_reftype;
aps = ap_cpy ((struct access_point *) eptr ->
e_reference -> avseq_av.av_struct);
op -> on_dsas -> di_dn = dn_cpy (aps->ap_name);
op -> on_dsas -> di_accesspoints = aps;
op -> on_dsas -> di_state = DI_ACCESSPOINT;
} else if ((eptr->e_data == E_TYPE_SLAVE) ||
(eptr->e_data == E_DATA_MASTER)) {
op -> on_dsas = di_alloc();
op -> on_dsas -> di_type = DI_TASK;
op -> on_dsas -> di_rdn_resolved = op ->
on_req.dca_charg.cha_progress.op_nextrdntoberesolved;
op -> on_dsas -> di_aliasedRDNs = CR_NOALIASEDRDNS;
op -> on_dsas -> di_oper = op;
op -> on_dsas -> di_type = DI_OPERATION;
op -> on_dsas -> di_dn = dn_cpy (dnseq -> dns_dn);
op -> on_dsas -> di_target = dn_cpy (dnseq -> dns_dn);
op -> on_dsas -> di_reftype = RT_SUBORDINATE;
op -> on_dsas -> di_entry = eptr;
eptr -> e_refcount++;
op -> on_dsas -> di_state = DI_COMPLETE;
} else
(void) constructor_dsa_info (dnseq -> dns_dn, NULLDNSEQ,
TRUE, eptr, &err, &(op -> on_dsas) );
if ( op -> on_dsas )
schedule_operation (op);
else
oper_free (op);
}
}
shadow_fail_wakeup (on)
struct oper_act * on;
{
struct oper_act * on_tmp;
struct oper_act **on_p;
DLOG (log_dsap, LLOG_NOTICE, ("Shadow fail wakeup"));
if (on -> on_resp.di_type == DI_ERROR) {
pslog (log_dsap,LLOG_EXCEPTIONS,"Remote shadow error",dn_print,
(caddr_t) on -> on_req.dca_dsarg.arg_rd.rda_object);
log_ds_error (& on -> on_resp.di_error.de_err);
}
on_p = &(get_edb_ops);
for(on_tmp = get_edb_ops; on_tmp != NULLOPER; on_tmp = on_tmp->on_next_task)
{
if(on_tmp == on)
break;
on_p = &(on_tmp->on_next_task);
}
if(on_tmp != NULLOPER)
{
(*on_p) = on_tmp->on_next_task;
}
else
{
LLOG(log_dsap, LLOG_EXCEPTIONS,
("subtask_fail_wakeup - op escaped from get_edb_ops (the global list)"));
}
oper_conn_extract(on);
oper_free(on);
}
#ifdef TURBO_AVL
/* ARGSUSED */
inherit_link(e, parent)
Entry e;
Entry parent;
{
set_inheritance (e);
return(OK);
}
#endif
process_shadow (on)
struct oper_act * on;
{
#ifndef TURBO_AVL
Entry trail = NULLENTRY;
#endif
Entry eptr, ne;
struct DSError err;
Attr_Sequence new_as, as, tas;
DN dn;
DLOG (log_dsap, LLOG_TRACE, ("Process shadow"));
dn = on -> on_resp.di_result.dr_res.dcr_dsres.res_rd.rdr_entry.ent_dn;
if ((eptr = local_find_entry_aux (dn,FALSE)) == NULLENTRY)
/* aliases on route !!! */
if ((eptr = local_find_entry_aux (dn,TRUE)) == NULLENTRY) {
pslog (log_dsap,LLOG_EXCEPTIONS,"Shadow has gone",
dn_print, (caddr_t) dn);
return;
}
new_as = on ->
on_resp.di_result.dr_res.dcr_dsres.res_rd.rdr_entry.ent_attr;
if (eptr -> e_external) {
/* Add in Quipu attributes */
if ( ((as = entry_find_type (eptr, at_subord)) == NULLATTR)
&& ((as = entry_find_type (eptr, at_xref)) != NULLATTR)
&& ((as = entry_find_type (eptr, at_nssr)) != NULLATTR)) {
LLOG (log_dsap, LLOG_EXCEPTIONS, (
"external reference missing"));
return;
}
new_as = as_merge (new_as, cpy_as_comp (as));
if ((as = as_find_type (new_as, at_objectclass)) == NULLATTR) {
LLOG (log_dsap, LLOG_EXCEPTIONS, (
"no objectclass in shadow entry"));
on -> on_resp.di_result.dr_res.
dcr_dsres.res_rd.rdr_entry.ent_attr = new_as;
return;
}
tas = as_comp_new (AttrT_cpy(at_objectclass),
str2avs(EXTERNOBJECT,at_objectclass),NULLACL_INFO);
new_as = as_merge (new_as,tas);
on -> on_resp.di_result.dr_res.
dcr_dsres.res_rd.rdr_entry.ent_attr = new_as;
}
if (as_cmp (eptr->e_attributes, new_as) == 0) {
DLOG (log_dsap, LLOG_NOTICE, ("Shadow: no change"));
eptr->e_age = timenow;
return;
}
#ifndef TURBO_AVL
if (eptr->e_parent == NULLENTRY)
ne = database_root->e_child;
else
ne = eptr->e_parent->e_child;
/* bring shadow entry to the top */
for (; ne != eptr; ne=ne->e_sibling)
trail = ne;
if (trail) {
trail->e_sibling = eptr->e_sibling;
eptr->e_sibling = eptr->e_parent->e_child;
eptr->e_parent->e_child = eptr;
}
#endif
DATABASE_HEAP;
ne = entry_cpy (eptr);
GENERAL_HEAP;
as_free ( ne -> e_attributes );
ne -> e_attributes = as_cpy ( new_as );
if (ne -> e_data == E_TYPE_CONSTRUCTOR) {
ne -> e_data = E_TYPE_CACHE_FROM_MASTER;
new_cacheEDB (dn);
}
#ifdef TURBO_AVL
#ifdef TURBO_INDEX
turbo_index_delete(eptr);
#endif
if (unravel_attribute(ne, &err) != OK) {
pslog (log_dsap,LLOG_EXCEPTIONS,"shadow: unravel failure",
dn_print, (caddr_t) dn);
log_ds_error (&err);
ds_error_free (&err);
entry_free (ne);
return;
} else if ( ! check_oc_hierarchy(ne->e_oc)) {
pslog (log_dsap,LLOG_EXCEPTIONS,"shadow: objectclass failure",
dn_print, (caddr_t) dn);
entry_free (ne);
return;
} else if (check_schema (ne,NULLATTR,&err) != OK) {
pslog (log_dsap,LLOG_EXCEPTIONS,"shadow: schema failure",
dn_print, (caddr_t) dn);
log_ds_error (&err);
ds_error_free (&err);
entry_free (ne);
return;
}
if (ne->e_parent == NULLENTRY) {
entry_replace(database_root, ne);
} else {
entry_replace(eptr, ne);
}
entry_free (ne);
ne = eptr;
if (unravel_attribute(eptr, &err) != OK) {
log_ds_error (&err);
ds_error_free (&err);
return;
}
(void) avl_apply(eptr->e_children, inherit_link,
(caddr_t) eptr, NOTOK, AVL_PREORDER);
if (eptr->e_parent->e_edbversion)
free (eptr->e_parent->e_edbversion);
eptr->e_parent->e_edbversion = new_version();
#ifdef TURBO_INDEX
/* add the new modified entry to the index */
turbo_add2index(eptr);
#endif
#else
if (unravel_attribute (ne,&err) != OK) {
log_ds_error (&err);
ds_error_free (&err);
entry_free (ne);
return;
} else if ( ! check_oc_hierarchy(ne->e_oc)) {
LLOG (log_dsap, LLOG_EXCEPTIONS, ("shadow: objectclass failure"));
entry_free (ne);
return;
} else if (check_schema (ne,NULLATTR,&err) != OK) {
log_ds_error (&err);
ds_error_free (&err);
entry_free (ne);
return;
}
/* slot into tree */
if (ne->e_parent == NULLENTRY) {
database_root = ne;
entry_free (eptr);
} else {
entry_free (eptr);
/* now alter all parent pointers */
ne->e_parent->e_child = ne;
for (eptr = ne->e_child; eptr!=NULLENTRY; eptr=eptr->e_sibling) {
eptr->e_parent = ne;
set_inheritance (eptr);
}
}
#endif
#ifdef TURBO_DISK
if (turbo_write(ne) != OK)
fatal (-33,"shadow rewrite failed - check database");
#else
if (journal (ne) != OK)
fatal (-33,"shadow rewrite failed - check database");
#endif
#ifndef NO_STATS
pslog (log_stat,LLOG_TRACE,"Shadow update",dn_print, (caddr_t) on ->
on_resp.di_result.dr_res.dcr_dsres.res_rd.rdr_entry.ent_dn);
#endif
ne->e_age = timenow;
}