Start development on 386BSD 0.0
[unix-history] / .ref-BSD-4_3_Net_2 / usr / src / contrib / isode / quipu / shadow.c
CommitLineData
fc4ef1d0
C
1/* shadow.c - spot shadowing of entries */
2
3#ifndef lint
4static char *rcsid = "$Header: /f/osi/quipu/RCS/shadow.c,v 7.2 91/03/09 11:57:05 mrose Exp $";
5#endif
6
7/*
8 * $Header: /f/osi/quipu/RCS/shadow.c,v 7.2 91/03/09 11:57:05 mrose Exp $
9 *
10 *
11 * $Log: shadow.c,v $
12 * Revision 7.2 91/03/09 11:57:05 mrose
13 * update
14 *
15 * Revision 7.1 91/02/22 09:39:50 mrose
16 * Interim 6.8
17 *
18 * Revision 7.0 90/12/01 18:08:35 mrose
19 * *** empty log message ***
20 *
21 */
22
23/*
24 * NOTICE
25 *
26 * Acquisition, use, and distribution of this module and related
27 * materials are subject to the restrictions of a license agreement.
28 * Consult the Preface in the User's Manual for the full terms of
29 * this agreement.
30 *
31 */
32
33
34#include "quipu/util.h"
35#include "quipu/read.h"
36#include "quipu/dua.h"
37#include "quipu/connection.h"
38#include "quipu/malloc.h"
39
40#ifndef NO_STATS
41extern LLog * log_stat;
42#endif
43extern LLog * log_dsap;
44static struct dn_seq * shades = NULLDNSEQ;
45static struct dn_seq * dn_shades = NULLDNSEQ;
46extern struct dn_seq * dn_seq_push();
47extern struct di_block * di_alloc();
48extern struct oper_act * oper_alloc();
49extern DN mydsadn;
50extern LLog * log_dsap;
51extern Entry entry_cpy ();
52extern Entry database_root;
53extern char * new_version ();
54extern int dn_print ();
55extern Attr_Sequence as_comp_cpy ();
56extern Attr_Sequence entry_find_type ();
57extern struct access_point * ap_cpy();
58extern time_t timenow;
59extern Entry make_path();
60extern Entry local_find_entry_aux();
61
62extern AttributeType at_subord;
63extern AttributeType at_xref;
64extern AttributeType at_nssr;
65extern AttributeType at_objectclass;
66extern Attr_Sequence cpy_as_comp();
67extern short syntax_dn;
68
69typedef struct _atlist {
70 AttributeType at;
71 struct _atlist *next;
72} *atlist;
73#define NULLATL (atlist)NULL
74atlist at_list = NULLATL;
75
76shadow_entry (eptr)
77Entry eptr;
78{
79DN dn, ndn;
80Attr_Sequence as;
81AV_Sequence avs;
82atlist at;
83
84 /* All MASTER entries get passed through here. */
85 /* See if it need shadowing, if so, add to shades */
86
87 if (eptr->e_data == E_DATA_MASTER) {
88 if ((eptr->e_dsainfo) &&
89 (quipu_ctx_supported (eptr) == 2) &&
90 (quipu_version_7 (eptr))) {
91 /* Its a version 7 quipuDSA */
92
93 dn = get_copy_dn (eptr);
94
95 if (dn_cmp (dn, mydsadn) == 0) {
96 dn_free (dn);
97 return; /* can't shadow myself ! */
98 }
99
100 if ( check_dnseq (shades, dn) == NOTOK)
101 shades = dn_seq_push (dn,shades);
102
103 dn_free (dn);
104
105 } else if ((eptr->e_external) && (eptr->e_reftype != RT_NONSPECIFICSUBORDINATE)) {
106
107 dn = get_copy_dn (eptr);
108
109 if ( check_dnseq (shades, dn) == NOTOK)
110 shades = dn_seq_push (dn,shades);
111
112 dn_free (dn);
113 }
114 }
115
116 for (as = eptr->e_attributes; as != NULLATTR; as=as->attr_link)
117 if (as->attr_type->oa_syntax == syntax_dn)
118 for (at = at_list; at != NULLATL; at=at->next)
119 if (as->attr_type == at->at) {
120 for (avs = as->attr_value; avs != NULLAV; avs = avs->avseq_next) {
121 ndn = (DN)avs->avseq_av.av_struct;
122 if (check_dnseq (dn_shades, ndn) == NOTOK)
123 dn_shades = dn_seq_push (ndn,dn_shades);
124 }
125 }
126}
127
128shadow_attribute (s)
129char * s;
130{
131AttributeType at;
132atlist new_atl;
133
134 if (( at = AttrT_new (s)) == NULLAttrT)
135 LLOG (log_dsap, LLOG_EXCEPTIONS, ("Unknown shadow attr %s",s));
136 else {
137 new_atl = (atlist) smalloc (sizeof (*new_atl));
138 new_atl->at = at;
139 new_atl->next = at_list;
140 at_list = new_atl;
141 }
142}
143
144shadow_update ()
145{
146struct dn_seq * dnseq;
147struct oper_act * op;
148static struct ds_read_arg sarg =
149{
150 default_common_args,
151 NULLDN,
152 { /* entry info selection */
153 TRUE,
154 NULLATTR,
155 EIS_ATTRIBUTESANDVALUES
156 }
157};
158Entry eptr;
159DN tdn;
160struct access_point * aps;
161struct DSError err;
162
163 DLOG(log_dsap, LLOG_TRACE, ("shadow_update"));
164
165 for (dnseq = dn_shades; dnseq != NULLDNSEQ; dnseq = dnseq -> dns_next) {
166 if ((eptr = local_find_entry (dnseq -> dns_dn,FALSE)) == NULLENTRY) {
167 /* aliases !!! */
168 if ((eptr = local_find_entry (dnseq -> dns_dn,TRUE)) == NULLENTRY)
169 eptr = make_path (dnseq -> dns_dn);
170 else if ( eptr -> e_alias )
171 eptr = make_path (eptr -> e_alias);
172 }
173
174 else if ((eptr->e_data == E_TYPE_SLAVE) ||
175 (eptr->e_data == E_DATA_MASTER))
176 continue;
177
178 if ( check_dnseq (shades, dnseq -> dns_dn) == NOTOK)
179 shades = dn_seq_push (dnseq -> dns_dn,shades);
180 }
181
182 dn_seq_free (dn_shades);
183 dn_shades = NULLDNSEQ;
184
185 for (dnseq = shades; dnseq != NULLDNSEQ; dnseq = dnseq -> dns_next) {
186
187 if((op = oper_alloc()) == NULLOPER)
188 return;
189
190 op -> on_type = ON_TYPE_SHADOW;
191 op -> on_arg = &(op -> on_req);
192 op -> on_req.dca_dsarg.arg_type = OP_READ;
193
194 op -> on_req.dca_dsarg.arg_rd = sarg; /* struct copy */
195 op -> on_req.dca_dsarg.arg_rd.rda_object =
196 dn_cpy (dnseq -> dns_dn);
197
198 op -> on_req.dca_charg.cha_originator =
199 dn_cpy (mydsadn);
200
201 op -> on_req.dca_charg.cha_reftype = RT_SUBORDINATE;
202
203 op -> on_req.dca_charg.cha_progress.op_resolution_phase =
204 OP_PHASE_PROCEEDING;
205
206 op -> on_req.dca_charg.cha_progress.op_nextrdntoberesolved = -1;
207 for (tdn = dnseq -> dns_dn ; tdn != NULLDN ;
208 tdn = tdn -> dn_parent)
209 op ->
210 on_req.dca_charg.cha_progress.op_nextrdntoberesolved++;
211
212 op -> on_req.dca_charg.cha_trace =
213 (struct trace_info *) malloc (sizeof (struct trace_info));
214 op -> on_req.dca_charg.cha_trace -> ti_dsa =
215 dn_cpy (mydsadn);
216 op -> on_req.dca_charg.cha_trace -> ti_target =
217 dn_cpy (dnseq -> dns_dn);
218 op -> on_req.dca_charg.cha_trace -> ti_progress =
219 op -> on_req.dca_charg.cha_progress;
220 op -> on_req.dca_charg.cha_trace -> ti_next = NULLTRACEINFO;
221
222 op -> on_dsas = NULL_DI_BLOCK;
223
224 if ((eptr = local_find_entry_aux (dnseq -> dns_dn,FALSE)) == NULLENTRY) {
225 if ((eptr = local_find_entry_aux (dnseq -> dns_dn,TRUE)) == NULLENTRY) {
226 pslog (log_dsap,LLOG_EXCEPTIONS,"Shadow entry missing",
227 dn_print, (caddr_t) dnseq -> dns_dn);
228 oper_free (op);
229 continue;
230 }
231 } else if ( eptr -> e_external ) {
232 op -> on_dsas = di_alloc();
233 op -> on_dsas -> di_type = DI_TASK;
234
235 op -> on_dsas -> di_rdn_resolved = op ->
236 on_req.dca_charg.cha_progress.op_nextrdntoberesolved;
237 op -> on_dsas -> di_aliasedRDNs = CR_NOALIASEDRDNS;
238
239 op -> on_dsas -> di_oper = op;
240 op -> on_dsas -> di_type = DI_OPERATION;
241
242 op -> on_dsas -> di_target = dn_cpy (dnseq -> dns_dn);
243 op -> on_dsas -> di_reftype = eptr-> e_reftype;
244 aps = ap_cpy ((struct access_point *) eptr ->
245 e_reference -> avseq_av.av_struct);
246 op -> on_dsas -> di_dn = dn_cpy (aps->ap_name);
247 op -> on_dsas -> di_accesspoints = aps;
248 op -> on_dsas -> di_state = DI_ACCESSPOINT;
249
250 } else if ((eptr->e_data == E_TYPE_SLAVE) ||
251 (eptr->e_data == E_DATA_MASTER)) {
252 op -> on_dsas = di_alloc();
253 op -> on_dsas -> di_type = DI_TASK;
254
255 op -> on_dsas -> di_rdn_resolved = op ->
256 on_req.dca_charg.cha_progress.op_nextrdntoberesolved;
257 op -> on_dsas -> di_aliasedRDNs = CR_NOALIASEDRDNS;
258
259 op -> on_dsas -> di_oper = op;
260 op -> on_dsas -> di_type = DI_OPERATION;
261 op -> on_dsas -> di_dn = dn_cpy (dnseq -> dns_dn);
262 op -> on_dsas -> di_target = dn_cpy (dnseq -> dns_dn);
263 op -> on_dsas -> di_reftype = RT_SUBORDINATE;
264 op -> on_dsas -> di_entry = eptr;
265 eptr -> e_refcount++;
266 op -> on_dsas -> di_state = DI_COMPLETE;
267 } else
268 (void) constructor_dsa_info (dnseq -> dns_dn, NULLDNSEQ,
269 TRUE, eptr, &err, &(op -> on_dsas) );
270
271 if ( op -> on_dsas )
272 schedule_operation (op);
273 else
274 oper_free (op);
275 }
276}
277
278
279shadow_fail_wakeup (on)
280struct oper_act * on;
281{
282 struct oper_act * on_tmp;
283 struct oper_act **on_p;
284
285 DLOG (log_dsap, LLOG_NOTICE, ("Shadow fail wakeup"));
286
287 if (on -> on_resp.di_type == DI_ERROR) {
288 pslog (log_dsap,LLOG_EXCEPTIONS,"Remote shadow error",dn_print,
289 (caddr_t) on -> on_req.dca_dsarg.arg_rd.rda_object);
290 log_ds_error (& on -> on_resp.di_error.de_err);
291 }
292
293 on_p = &(get_edb_ops);
294 for(on_tmp = get_edb_ops; on_tmp != NULLOPER; on_tmp = on_tmp->on_next_task)
295 {
296 if(on_tmp == on)
297 break;
298
299 on_p = &(on_tmp->on_next_task);
300 }
301
302 if(on_tmp != NULLOPER)
303 {
304 (*on_p) = on_tmp->on_next_task;
305 }
306 else
307 {
308 LLOG(log_dsap, LLOG_EXCEPTIONS,
309 ("subtask_fail_wakeup - op escaped from get_edb_ops (the global list)"));
310 }
311
312 oper_conn_extract(on);
313 oper_free(on);
314}
315
316#ifdef TURBO_AVL
317/* ARGSUSED */
318inherit_link(e, parent)
319Entry e;
320Entry parent;
321{
322 set_inheritance (e);
323 return(OK);
324}
325#endif
326
327process_shadow (on)
328struct oper_act * on;
329{
330#ifndef TURBO_AVL
331Entry trail = NULLENTRY;
332#endif
333Entry eptr, ne;
334struct DSError err;
335Attr_Sequence new_as, as, tas;
336DN dn;
337
338 DLOG (log_dsap, LLOG_TRACE, ("Process shadow"));
339
340 dn = on -> on_resp.di_result.dr_res.dcr_dsres.res_rd.rdr_entry.ent_dn;
341
342 if ((eptr = local_find_entry_aux (dn,FALSE)) == NULLENTRY)
343 /* aliases on route !!! */
344 if ((eptr = local_find_entry_aux (dn,TRUE)) == NULLENTRY) {
345 pslog (log_dsap,LLOG_EXCEPTIONS,"Shadow has gone",
346 dn_print, (caddr_t) dn);
347 return;
348 }
349
350 new_as = on ->
351 on_resp.di_result.dr_res.dcr_dsres.res_rd.rdr_entry.ent_attr;
352
353 if (eptr -> e_external) {
354 /* Add in Quipu attributes */
355
356 if ( ((as = entry_find_type (eptr, at_subord)) == NULLATTR)
357 && ((as = entry_find_type (eptr, at_xref)) != NULLATTR)
358 && ((as = entry_find_type (eptr, at_nssr)) != NULLATTR)) {
359 LLOG (log_dsap, LLOG_EXCEPTIONS, (
360 "external reference missing"));
361 return;
362 }
363 new_as = as_merge (new_as, cpy_as_comp (as));
364
365 if ((as = as_find_type (new_as, at_objectclass)) == NULLATTR) {
366 LLOG (log_dsap, LLOG_EXCEPTIONS, (
367 "no objectclass in shadow entry"));
368 on -> on_resp.di_result.dr_res.
369 dcr_dsres.res_rd.rdr_entry.ent_attr = new_as;
370 return;
371 }
372
373 tas = as_comp_new (AttrT_cpy(at_objectclass),
374 str2avs(EXTERNOBJECT,at_objectclass),NULLACL_INFO);
375 new_as = as_merge (new_as,tas);
376
377 on -> on_resp.di_result.dr_res.
378 dcr_dsres.res_rd.rdr_entry.ent_attr = new_as;
379
380 }
381
382 if (as_cmp (eptr->e_attributes, new_as) == 0) {
383 DLOG (log_dsap, LLOG_NOTICE, ("Shadow: no change"));
384 eptr->e_age = timenow;
385 return;
386 }
387
388#ifndef TURBO_AVL
389 if (eptr->e_parent == NULLENTRY)
390 ne = database_root->e_child;
391 else
392 ne = eptr->e_parent->e_child;
393
394 /* bring shadow entry to the top */
395 for (; ne != eptr; ne=ne->e_sibling)
396 trail = ne;
397
398 if (trail) {
399 trail->e_sibling = eptr->e_sibling;
400 eptr->e_sibling = eptr->e_parent->e_child;
401 eptr->e_parent->e_child = eptr;
402 }
403#endif
404
405 DATABASE_HEAP;
406 ne = entry_cpy (eptr);
407 GENERAL_HEAP;
408
409 as_free ( ne -> e_attributes );
410 ne -> e_attributes = as_cpy ( new_as );
411
412 if (ne -> e_data == E_TYPE_CONSTRUCTOR) {
413 ne -> e_data = E_TYPE_CACHE_FROM_MASTER;
414 new_cacheEDB (dn);
415 }
416
417#ifdef TURBO_AVL
418#ifdef TURBO_INDEX
419 turbo_index_delete(eptr);
420#endif
421
422 if (unravel_attribute(ne, &err) != OK) {
423 pslog (log_dsap,LLOG_EXCEPTIONS,"shadow: unravel failure",
424 dn_print, (caddr_t) dn);
425 log_ds_error (&err);
426 ds_error_free (&err);
427 entry_free (ne);
428 return;
429 } else if ( ! check_oc_hierarchy(ne->e_oc)) {
430 pslog (log_dsap,LLOG_EXCEPTIONS,"shadow: objectclass failure",
431 dn_print, (caddr_t) dn);
432 entry_free (ne);
433 return;
434
435 } else if (check_schema (ne,NULLATTR,&err) != OK) {
436 pslog (log_dsap,LLOG_EXCEPTIONS,"shadow: schema failure",
437 dn_print, (caddr_t) dn);
438 log_ds_error (&err);
439 ds_error_free (&err);
440 entry_free (ne);
441 return;
442 }
443
444 if (ne->e_parent == NULLENTRY) {
445 entry_replace(database_root, ne);
446 } else {
447 entry_replace(eptr, ne);
448 }
449
450 entry_free (ne);
451 ne = eptr;
452
453 if (unravel_attribute(eptr, &err) != OK) {
454 log_ds_error (&err);
455 ds_error_free (&err);
456 return;
457 }
458 (void) avl_apply(eptr->e_children, inherit_link,
459 (caddr_t) eptr, NOTOK, AVL_PREORDER);
460
461 if (eptr->e_parent->e_edbversion)
462 free (eptr->e_parent->e_edbversion);
463 eptr->e_parent->e_edbversion = new_version();
464
465#ifdef TURBO_INDEX
466 /* add the new modified entry to the index */
467 turbo_add2index(eptr);
468#endif
469#else
470 if (unravel_attribute (ne,&err) != OK) {
471 log_ds_error (&err);
472 ds_error_free (&err);
473 entry_free (ne);
474 return;
475 } else if ( ! check_oc_hierarchy(ne->e_oc)) {
476 LLOG (log_dsap, LLOG_EXCEPTIONS, ("shadow: objectclass failure"));
477 entry_free (ne);
478 return;
479
480 } else if (check_schema (ne,NULLATTR,&err) != OK) {
481 log_ds_error (&err);
482 ds_error_free (&err);
483 entry_free (ne);
484 return;
485 }
486
487 /* slot into tree */
488 if (ne->e_parent == NULLENTRY) {
489 database_root = ne;
490 entry_free (eptr);
491 } else {
492 entry_free (eptr);
493 /* now alter all parent pointers */
494 ne->e_parent->e_child = ne;
495 for (eptr = ne->e_child; eptr!=NULLENTRY; eptr=eptr->e_sibling) {
496 eptr->e_parent = ne;
497 set_inheritance (eptr);
498 }
499
500 }
501
502#endif
503
504#ifdef TURBO_DISK
505 if (turbo_write(ne) != OK)
506 fatal (-33,"shadow rewrite failed - check database");
507#else
508 if (journal (ne) != OK)
509 fatal (-33,"shadow rewrite failed - check database");
510#endif
511#ifndef NO_STATS
512 pslog (log_stat,LLOG_TRACE,"Shadow update",dn_print, (caddr_t) on ->
513 on_resp.di_result.dr_res.dcr_dsres.res_rd.rdr_entry.ent_dn);
514#endif
515
516 ne->e_age = timenow;
517
518}
519
520