Commit | Line | Data |
---|---|---|
fc4ef1d0 C |
1 | /* shadow.c - spot shadowing of entries */ |
2 | ||
3 | #ifndef lint | |
4 | static 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 | |
41 | extern LLog * log_stat; | |
42 | #endif | |
43 | extern LLog * log_dsap; | |
44 | static struct dn_seq * shades = NULLDNSEQ; | |
45 | static struct dn_seq * dn_shades = NULLDNSEQ; | |
46 | extern struct dn_seq * dn_seq_push(); | |
47 | extern struct di_block * di_alloc(); | |
48 | extern struct oper_act * oper_alloc(); | |
49 | extern DN mydsadn; | |
50 | extern LLog * log_dsap; | |
51 | extern Entry entry_cpy (); | |
52 | extern Entry database_root; | |
53 | extern char * new_version (); | |
54 | extern int dn_print (); | |
55 | extern Attr_Sequence as_comp_cpy (); | |
56 | extern Attr_Sequence entry_find_type (); | |
57 | extern struct access_point * ap_cpy(); | |
58 | extern time_t timenow; | |
59 | extern Entry make_path(); | |
60 | extern Entry local_find_entry_aux(); | |
61 | ||
62 | extern AttributeType at_subord; | |
63 | extern AttributeType at_xref; | |
64 | extern AttributeType at_nssr; | |
65 | extern AttributeType at_objectclass; | |
66 | extern Attr_Sequence cpy_as_comp(); | |
67 | extern short syntax_dn; | |
68 | ||
69 | typedef struct _atlist { | |
70 | AttributeType at; | |
71 | struct _atlist *next; | |
72 | } *atlist; | |
73 | #define NULLATL (atlist)NULL | |
74 | atlist at_list = NULLATL; | |
75 | ||
76 | shadow_entry (eptr) | |
77 | Entry eptr; | |
78 | { | |
79 | DN dn, ndn; | |
80 | Attr_Sequence as; | |
81 | AV_Sequence avs; | |
82 | atlist 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 | ||
128 | shadow_attribute (s) | |
129 | char * s; | |
130 | { | |
131 | AttributeType at; | |
132 | atlist 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 | ||
144 | shadow_update () | |
145 | { | |
146 | struct dn_seq * dnseq; | |
147 | struct oper_act * op; | |
148 | static 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 | }; | |
158 | Entry eptr; | |
159 | DN tdn; | |
160 | struct access_point * aps; | |
161 | struct 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 | ||
279 | shadow_fail_wakeup (on) | |
280 | struct 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 */ | |
318 | inherit_link(e, parent) | |
319 | Entry e; | |
320 | Entry parent; | |
321 | { | |
322 | set_inheritance (e); | |
323 | return(OK); | |
324 | } | |
325 | #endif | |
326 | ||
327 | process_shadow (on) | |
328 | struct oper_act * on; | |
329 | { | |
330 | #ifndef TURBO_AVL | |
331 | Entry trail = NULLENTRY; | |
332 | #endif | |
333 | Entry eptr, ne; | |
334 | struct DSError err; | |
335 | Attr_Sequence new_as, as, tas; | |
336 | DN 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 |