/* shadow.c - spot shadowing of entries */
static char *rcsid
= "$Header: /f/osi/quipu/RCS/shadow.c,v 7.2 91/03/09 11:57:05 mrose Exp $";
* $Header: /f/osi/quipu/RCS/shadow.c,v 7.2 91/03/09 11:57:05 mrose Exp $
* Revision 7.2 91/03/09 11:57:05 mrose
* Revision 7.1 91/02/22 09:39:50 mrose
* Revision 7.0 90/12/01 18:08:35 mrose
* *** empty log message ***
* 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
#include "quipu/connection.h"
#include "quipu/malloc.h"
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 Entry
entry_cpy ();
extern Entry database_root
;
extern char * new_version ();
extern Attr_Sequence
as_comp_cpy ();
extern Attr_Sequence
entry_find_type ();
extern struct access_point
* ap_cpy();
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();
#define NULLATL (atlist)NULL
atlist at_list
= NULLATL
;
/* All MASTER entries get passed through here. */
/* See if it need shadowing, if so, add to shades */
if (eptr
->e_data
== E_DATA_MASTER
) {
(quipu_ctx_supported (eptr
) == 2) &&
(quipu_version_7 (eptr
))) {
/* Its a version 7 quipuDSA */
if (dn_cmp (dn
, mydsadn
) == 0) {
return; /* can't shadow myself ! */
if ( check_dnseq (shades
, dn
) == NOTOK
)
shades
= dn_seq_push (dn
,shades
);
} else if ((eptr
->e_external
) && (eptr
->e_reftype
!= RT_NONSPECIFICSUBORDINATE
)) {
if ( check_dnseq (shades
, dn
) == NOTOK
)
shades
= dn_seq_push (dn
,shades
);
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
);
if (( at
= AttrT_new (s
)) == NULLAttrT
)
LLOG (log_dsap
, LLOG_EXCEPTIONS
, ("Unknown shadow attr %s",s
));
new_atl
= (atlist
) smalloc (sizeof (*new_atl
));
static struct ds_read_arg sarg
=
{ /* entry info selection */
struct access_point
* aps
;
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
) {
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
))
if ( check_dnseq (shades
, dnseq
-> dns_dn
) == NOTOK
)
shades
= dn_seq_push (dnseq
-> dns_dn
,shades
);
for (dnseq
= shades
; dnseq
!= NULLDNSEQ
; dnseq
= dnseq
-> dns_next
) {
if((op
= oper_alloc()) == NULLOPER
)
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
=
op
-> on_req
.dca_charg
.cha_reftype
= RT_SUBORDINATE
;
op
-> on_req
.dca_charg
.cha_progress
.op_resolution_phase
=
op
-> on_req
.dca_charg
.cha_progress
.op_nextrdntoberesolved
= -1;
for (tdn
= dnseq
-> dns_dn
; tdn
!= NULLDN
;
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
=
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
);
} 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
;
op
-> on_dsas
-> di_state
= DI_COMPLETE
;
(void) constructor_dsa_info (dnseq
-> dns_dn
, NULLDNSEQ
,
TRUE
, eptr
, &err
, &(op
-> on_dsas
) );
struct oper_act
* on_tmp
;
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
);
for(on_tmp
= get_edb_ops
; on_tmp
!= NULLOPER
; on_tmp
= on_tmp
->on_next_task
)
on_p
= &(on_tmp
->on_next_task
);
(*on_p
) = on_tmp
->on_next_task
;
LLOG(log_dsap
, LLOG_EXCEPTIONS
,
("subtask_fail_wakeup - op escaped from get_edb_ops (the global list)"));
Attr_Sequence new_as
, as
, tas
;
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",
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"));
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
;
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"));
if (eptr
->e_parent
== NULLENTRY
)
ne
= database_root
->e_child
;
ne
= eptr
->e_parent
->e_child
;
/* bring shadow entry to the top */
for (; ne
!= eptr
; ne
=ne
->e_sibling
)
trail
->e_sibling
= eptr
->e_sibling
;
eptr
->e_sibling
= eptr
->e_parent
->e_child
;
eptr
->e_parent
->e_child
= eptr
;
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
;
turbo_index_delete(eptr
);
if (unravel_attribute(ne
, &err
) != OK
) {
pslog (log_dsap
,LLOG_EXCEPTIONS
,"shadow: unravel failure",
} else if ( ! check_oc_hierarchy(ne
->e_oc
)) {
pslog (log_dsap
,LLOG_EXCEPTIONS
,"shadow: objectclass failure",
} else if (check_schema (ne
,NULLATTR
,&err
) != OK
) {
pslog (log_dsap
,LLOG_EXCEPTIONS
,"shadow: schema failure",
if (ne
->e_parent
== NULLENTRY
) {
entry_replace(database_root
, ne
);
if (unravel_attribute(eptr
, &err
) != OK
) {
(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();
/* add the new modified entry to the index */
if (unravel_attribute (ne
,&err
) != OK
) {
} else if ( ! check_oc_hierarchy(ne
->e_oc
)) {
LLOG (log_dsap
, LLOG_EXCEPTIONS
, ("shadow: objectclass failure"));
} else if (check_schema (ne
,NULLATTR
,&err
) != OK
) {
if (ne
->e_parent
== NULLENTRY
) {
/* now alter all parent pointers */
ne
->e_parent
->e_child
= ne
;
for (eptr
= ne
->e_child
; eptr
!=NULLENTRY
; eptr
=eptr
->e_sibling
) {
if (turbo_write(ne
) != OK
)
fatal (-33,"shadow rewrite failed - check database");
fatal (-33,"shadow rewrite failed - check database");
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
);