4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2015 Gary Mills
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
26 * Copyright 2015 RackTop Systems.
29 #include <sys/types.h>
36 #include "db_headers.h"
38 #include "db_mindex.h"
39 #include "db_dictionary.h"
42 #include "ldap_glob.h"
43 #include "ldap_util.h"
46 extern db_dictionary
*InUseDictionary
;
53 __nis_table_mapping_t
*t
;
60 } __entries_from_ldap_arg_t
;
62 static void *entriesFromLDAPthread(void *);
66 int entriesFromLDAPreal(__entries_from_ldap_arg_t
*);
68 #ifdef SET_ENTRY_FLAGS
70 entryFlagsFromTable(uint_t tf
) {
73 if ((tf
& TA_BINARY
) != 0)
75 if ((tf
& TA_CRYPT
) != 0)
77 if ((tf
& TA_XDR
) != 0)
79 if ((tf
& TA_ASN1
) != 0)
84 #endif /* SET_ENTRY_FLAGS */
86 static void setOid(nis_object
*obj
);
89 * Retrieve container entries from LDAP per 't' and 'qin'/'q'.
90 * This is a helper function for db_mindex::queryLDAP(); see
91 * that function for details of the parameters (except doAsynch).
93 * If 'doAsynch' is set, and the retrieval is an enumeration
94 * (qin == NULL), the retrieval is performed in a detached
95 * thread. In this case, the return code just reflects the
96 * setup and launch of the detached thread. Retrieval will
97 * complete asynchronously.
100 db_mindex::entriesFromLDAP(__nis_table_mapping_t
*t
, db_query
*qin
, db_query
*q
,
101 char *dbId
, nis_object
*dirObj
, int doAsynch
) {
102 __entries_from_ldap_arg_t
*arg
;
105 const char *myself
= "db_mindex::entriesFromLDAP";
107 arg
= (__entries_from_ldap_arg_t
*)am(myself
, sizeof (*arg
));
111 nis_destroy_object(dirObj
);
112 return (LDAP_NO_MEMORY
);
120 arg
->dirObj
= dirObj
;
121 arg
->tableName
= t
->objName
;
124 * Check if an enumeration thread is running; if so, then regardless
125 * of whether or not the current operation is an enumeration, we
126 * just return success, and let our caller get the data from the
127 * existing (deferred) DB.
129 (void) mutex_lock(&table
->mapping
.enumLock
);
130 if (table
->mapping
.enumTid
!= 0) {
133 stat
= pthread_kill(table
->mapping
.enumTid
, 0);
135 logmsg(MSG_NOTIMECHECK
, LOG_WARNING
,
136 "%s: Enumeration thread %d not found for \"%s\"; exit status = %d (%s)",
137 myself
, table
->mapping
.enumTid
,
138 NIL(t
->objName
), table
->mapping
.enumStat
,
139 ldap_err2string(table
->mapping
.enumStat
));
140 /* Reflect the fact that no enum thread is running */
141 table
->mapping
.enumTid
= 0;
142 table
->mapping
.enumStat
= -1;
143 /* Cleanup deferred mode */
144 if (table
->mapping
.enumDeferred
) {
145 dstat
= InUseDictionary
->commit(t
->objPath
);
146 if (dstat
== DB_SUCCESS
) {
147 table
->mapping
.enumDeferred
= 0;
149 logmsg(MSG_NOTIMECHECK
, LOG_ERR
,
150 "%s: DB error %d committing \"%s\"",
151 myself
, dstat
, NIL(t
->objName
));
154 } else if (stat
== 0) {
155 logmsg(MSG_NOTIMECHECK
, LOG_INFO
,
156 "%s: Enumeration thread %d already running for \"%s\"",
157 myself
, table
->mapping
.enumTid
,
162 logmsg(MSG_NOTIMECHECK
, LOG_INFO
,
163 "%s: Error %d looking for enumeration thread %d for \"%s\"",
164 myself
, stat
, table
->mapping
.enumTid
,
167 stat
= LDAP_OPERATIONS_ERROR
;
170 (void) mutex_unlock(&table
->mapping
.enumLock
);
174 nis_destroy_object(dirObj
);
180 * If we're enumerating (and hence expect that retrieving all data,
181 * and updating the local DB, might take a while), create a deferred-
182 * update table that clients can use while we are updating the real
185 if (doAsynch
&& qin
== 0) {
186 if ((dstat
= InUseDictionary
->defer(t
->objPath
)) ==
189 table
->mapping
.enumDeferred
= 1;
191 logmsg(MSG_NOTIMECHECK
, LOG_WARNING
,
192 "%s: Unable to defer updates for \"%s\" (status=%d);"
193 " updating in place",
194 myself
, NIL(t
->objName
), dstat
);
196 table
->mapping
.enumDeferred
= 0;
200 table
->mapping
.enumDeferred
= 0;
203 /* If enumerating, perform the operation in a separate thread */
204 if (doAsynch
&& qin
== 0) {
208 (void) pthread_attr_init(&attr
);
209 #ifdef FORCE_SYNCHRONOUS
211 (void) pthread_attr_setdetachstate(&attr
,
212 PTHREAD_CREATE_DETACHED
);
213 #endif /* FORCE_SYNCHRONOUS */
214 stat
= pthread_create(&tid
, &attr
, entriesFromLDAPthread
, arg
);
216 (void) mutex_unlock(&table
->mapping
.enumLock
);
217 logmsg(MSG_NOTIMECHECK
, LOG_WARNING
,
218 "%s: Error %d creating new thread; using current one",
220 stat
= entriesFromLDAPreal(arg
);
224 table
->mapping
.enumTid
= tid
;
225 table
->mapping
.enumStat
= -1;
228 * We're now returning to the caller, who will get data
231 * The deferred DB, if an enumeration thread already
232 * was running, and deferred mode was on, or
234 * The original DB, if we just started an enumeration
235 * thread. In this case, our caller (several levels up)
236 * is holding a lock on the db_mindex/db_table, which
237 * means that the enum thread will have to wait for
238 * our caller once it's done the LDAP retrieval, and
239 * wants to update the DB.
241 (void) mutex_unlock(&table
->mapping
.enumLock
);
243 #ifdef FORCE_SYNCHRONOUS
247 stat
= pthread_join(tid
, (void **)&tstat
);
250 logmsg(MSG_NOTIMECHECK
, LOG_WARNING
,
251 "%s: thread %d => %d",
254 logmsg(MSG_NOTIMECHECK
, LOG_ERR
,
255 "%s: pthread_join(%d) => %d",
257 stat
= LDAP_OPERATIONS_ERROR
;
260 #endif /* FORCE_SYNCHRONOUS */
262 (void) mutex_unlock(&table
->mapping
.enumLock
);
263 stat
= entriesFromLDAPreal(arg
);
272 * We use this 'extern "C"' function in order to make sure that
273 * pthread_create() doesn't have any problems trying to invoke a
277 entriesFromLDAPthread(void *voidarg
) {
278 __entries_from_ldap_arg_t
*arg
;
280 db_table_desc
*tbl
= 0;
283 arg
= (__entries_from_ldap_arg_t
*)voidarg
;
285 /* Lock to prevent removal */
286 (void) __nis_lock_db_table(arg
->tableName
, 1, 0,
287 "entriesFromLDAPthread");
290 * It's possible that the db_mindex for the table has changed,
291 * or disappeared, between now and the time when our parent
292 * thread released its lock on the table. Hence, we search the
293 * dictionary to re-acquire the 'db', and the db_mindex.
295 tableName
= internalTableName(arg
->tableName
);
296 if (tableName
!= 0) {
297 #ifdef NISDB_LDAP_DEBUG
298 db_mindex
*oldMindex
= arg
->mindex
;
299 #endif /* NISDB_LDAP_DEBUG */
301 dbase
= InUseDictionary
->find_table(tableName
, &tbl
, FALSE
);
303 arg
->mindex
= dbase
->mindex();
306 #ifdef NISDB_LDAP_DEBUG
307 logmsg(MSG_NOTIMECHECK
, LOG_WARNING
,
308 "entriesFromLDAPthread: %s -> %s -> 0x%x (0x%x)",
309 NIL(arg
->tableName
), NIL(tableName
),
310 arg
->mindex
, oldMindex
);
311 #endif /* NISDB_LDAP_DEBUG */
316 (void) entriesFromLDAPreal(arg
);
318 (void) __nis_ulock_db_table(arg
->tableName
, 1, 0,
319 "entriesFromLDAPthread");
322 if (arg
->dirObj
!= 0)
323 nis_destroy_object(arg
->dirObj
);
331 entriesFromLDAPreal(__entries_from_ldap_arg_t
*arg
) {
334 __nis_table_mapping_t
*t
;
338 int i
, na
, nau
, nq
= 0, xid
= 0;
339 int ret
, stat
= LDAP_SUCCESS
, stat2
, stat3
;
341 __nis_obj_attr_t
**oa
= 0;
347 struct timeval start
;
349 "db_mindex::entriesFromLDAPreal";
352 return (LDAP_PARAM_ERROR
);
353 mindex
= arg
->mindex
;
358 dirObj
= arg
->dirObj
;
360 table
= (mindex
!= 0) ? mindex
->getTable() : 0;
362 if (mindex
== 0 || t
== 0 || table
== 0) {
363 /* We haven't done anything, so rollback should be OK */
364 if (arg
->isDeferred
&& t
!= 0) {
365 dstat
= InUseDictionary
->rollback(t
->objPath
);
366 if (dstat
!= DB_SUCCESS
) {
367 logmsg(MSG_NOTIMECHECK
, LOG_WARNING
,
368 "%s: DB error %d rolling back \"%s\"",
369 myself
, dstat
, NIL(t
->objName
));
371 * Had rollback succeeded, the 'table'
372 * would have disappeared. However, since
373 * rollback failed, we need to update the
374 * table->mapping.enum* fields.
377 (void) mutex_lock(&table
->
379 table
->mapping
.enumStat
=
381 table
->mapping
.enumTime
= 0;
382 table
->mapping
.enumEntries
= 0;
383 table
->mapping
.enumTid
= 0;
384 (void) mutex_unlock(&table
->
389 return (LDAP_PARAM_ERROR
);
393 logmsg(MSG_NOTIMECHECK
, LOG_INFO
, "%s: enumerating \"%s%s%s\"",
394 myself
, dbId
? dbId
: "", dbId
? ":" : "",
397 (void) gettimeofday(&start
, 0);
399 /* Getting table entries */
400 res
= mapFromLDAP(t
, q
, &nq
, dbId
, &stat
, &oa
);
401 #ifdef NISDB_LDAP_DEBUG
402 logmsg(MSG_ALWAYS
, LOG_INFO
,
403 "%s: mapFromLDAP() => 0x%x, status=%d %s; nq = %d",
404 myself
, res
, stat
, stat
== LDAP_SUCCESS
? "" :
405 ldap_err2string(stat
), nq
);
406 #endif /* NISDB_LDAP_DEBUG */
409 * Keep track of the number of NIS+ entries we got back;
410 * note that the number of LDAP entries may have been
413 (void) mutex_lock(&table
->mapping
.enumLock
);
414 table
->mapping
.enumEntries
= nq
;
415 (void) mutex_unlock(&table
->mapping
.enumLock
);
418 * If we get LDAP_NO_SUCH_OBJECT, we need to delete the entries
419 * in the table, so we can't just return.
421 if (res
== 0 && stat
!= LDAP_NO_SUCH_OBJECT
) {
422 logmsg(MSG_NOTIMECHECK
, LOG_INFO
,
423 "%s: mapFromLDAP() => 0x0, status=%d (%s)",
424 myself
, stat
, ldap_err2string(stat
));
425 if (arg
->isDeferred
) {
426 dstat
= InUseDictionary
->rollback(t
->objPath
);
427 if (dstat
!= DB_SUCCESS
) {
430 logmsg(MSG_NOTIMECHECK
, LOG_WARNING
,
431 "%s: DB error %d rolling back \"%s\"",
432 myself
, dstat
, NIL(t
->objName
));
434 * Had rollback succeeded, the 'table'
435 * would have disappeared. However, since
436 * rollback failed, we need to update the
437 * table->mapping.enum* fields.
439 (void) mutex_lock(&table
->mapping
.enumLock
);
440 table
->mapping
.enumStat
= stat
;
441 (void) gettimeofday(&end
, 0);
442 end
.tv_sec
-= start
.tv_sec
;
443 end
.tv_usec
-= start
.tv_usec
;
444 if (end
.tv_usec
< 0) {
445 end
.tv_usec
+= 1000000;
448 table
->mapping
.enumTime
=
449 1000000*end
.tv_sec
+ end
.tv_usec
;
450 table
->mapping
.enumTid
= 0;
451 (void) mutex_unlock(&table
->mapping
.enumLock
);
458 * Need to disable write-through to LDAP, for which we need a lock
459 * on our db_mindex ('mindex'); we're also updating the table, so
460 * we need a write lock on that as well. However, before locking the
461 * mindex, we need to maintain lock integrity by acquiring the
462 * trans log lock. Note that actually beginning a transaction is
463 * expensive, so we defer that until we know that we really need
466 lstat
= lockTransLog(myself
, 1, 1);
469 logmsg(MSG_NOTIMECHECK
, LOG_INFO
,
470 "%s: transaction log busy; no LDAP update for \"%s\"",
471 myself
, NIL(t
->objName
));
473 logmsg(MSG_NOTIMECHECK
, LOG_ERR
,
474 "%s: Error %d locking transaction log; no LDAP update for \"%s\"",
475 myself
, lstat
, NIL(t
->objName
));
476 if (arg
->isDeferred
) {
477 dstat
= InUseDictionary
->rollback(t
->objPath
);
478 if (dstat
!= DB_SUCCESS
) {
481 logmsg(MSG_NOTIMECHECK
, LOG_WARNING
,
482 "%s: DB error %d rolling back \"%s\"",
483 myself
, dstat
, NIL(t
->objName
));
485 * Had rollback succeeded, the 'table'
486 * would have disappeared. However, since
487 * rollback failed, we need to update the
488 * table->mapping.enum* fields.
490 (void) mutex_lock(&table
->mapping
.enumLock
);
491 table
->mapping
.enumStat
= LDAP_OPERATIONS_ERROR
;
492 (void) gettimeofday(&end
, 0);
493 end
.tv_sec
-= start
.tv_sec
;
494 end
.tv_usec
-= start
.tv_usec
;
495 if (end
.tv_usec
< 0) {
496 end
.tv_usec
+= 1000000;
499 table
->mapping
.enumTime
= 1000000*end
.tv_sec
+
501 table
->mapping
.enumTid
= 0;
502 (void) mutex_unlock(&table
->mapping
.enumLock
);
505 return (LDAP_OPERATIONS_ERROR
);
509 * If we have any updates, we'll call db::sync_log, which write-
510 * locks the 'db' instance. In order to avoid a dead-lock with
511 * threads performing a DB lookup (which will lock the 'db' and
512 * then the 'db_mindex'), we need hence need to lock in the
515 * trans.log (already holding that one)
520 TRYWRITELOCK(((db
*)mindex
->getDbPtr()), stat
,
521 "w db db_mindex::entriesFromLDAPreal");
523 TRYWRITELOCK(mindex
, stat2
, "w db_mindex::entriesFromLDAPreal");
525 TRYWRITELOCK(table
, stat3
,
526 "table w db_mindex::entriesFromLDAPreal");
530 if (stat
!= 0 || stat2
!= 0 || stat3
!= 0) {
533 logmsg(MSG_NOTIMECHECK
, LOG_INFO
,
534 "%s: 'db' busy; no LDAP update for \"%s\"",
535 myself
, NIL(t
->objName
));
537 logmsg(MSG_NOTIMECHECK
, LOG_ERR
,
538 "%s: 'db' lock error %d; no LDAP update for \"%s\"",
539 myself
, stat
, NIL(t
->objName
));
540 } else if (stat2
!= 0) {
542 logmsg(MSG_NOTIMECHECK
, LOG_INFO
,
543 "%s: 'db_mindex' busy; no LDAP update for \"%s\"",
544 myself
, NIL(t
->objName
));
546 logmsg(MSG_NOTIMECHECK
, LOG_ERR
,
547 "%s: 'db_mindex' lock error %d; no LDAP update for \"%s\"",
548 myself
, stat2
, NIL(t
->objName
));
551 logmsg(MSG_NOTIMECHECK
, LOG_INFO
,
552 "%s: 'db_table' busy; no LDAP update for \"%s\"",
553 myself
, NIL(t
->objName
));
555 logmsg(MSG_NOTIMECHECK
, LOG_ERR
,
556 "%s: 'db_table' lock error %d; no LDAP update for \"%s\"",
557 myself
, stat3
, NIL(t
->objName
));
559 freeQueries(res
, nq
);
560 if (arg
->isDeferred
) {
561 dstat
= InUseDictionary
->rollback(t
->objPath
);
562 if (dstat
!= DB_SUCCESS
) {
563 logmsg(MSG_NOTIMECHECK
, LOG_WARNING
,
564 "%s: DB error %d rolling back \"%s\"",
565 myself
, dstat
, NIL(t
->objName
));
567 * Had rollback succeeded, the 'table'
568 * would have disappeared. However, since
569 * rollback failed, we need to update the
570 * table->mapping.enum* fields.
572 (void) mutex_lock(&table
->mapping
.enumLock
);
573 table
->mapping
.enumStat
= LDAP_OPERATIONS_ERROR
;
574 table
->mapping
.enumTid
= 0;
575 (void) mutex_unlock(&table
->mapping
.enumLock
);
580 WRITEUNLOCK2(mindex
, ((db
*)mindex
->getDbPtr()),
581 LDAP_OPERATIONS_ERROR
,
582 LDAP_OPERATIONS_ERROR
,
583 "db_mindex::entriesFromLDAPreal wu",
584 "db_mindex::entriesFromLDAPreal wu db");
586 WRITEUNLOCK(((db
*)mindex
->getDbPtr()),
587 LDAP_OPERATIONS_ERROR
,
588 "db_mindex::entriesFromLDAPreal wu db");
591 unlockTransLog(myself
, 1);
592 return (LDAP_OPERATIONS_ERROR
);
596 mindex
->setNoWriteThrough();
597 mindex
->setNoLDAPquery();
599 table
->setEnumMode(0);
603 * If there is no non-indexed table mapping, we must filter
604 * the enum mode (i.e., deletion candidates) array to only
605 * contain those entries that match the indexes.
607 if (haveIndexedMapping(t
)) {
608 entry_object
**tea
= table
->gettab();
609 long i
, ntea
= table
->getsize();
613 * Walk through the entry array, and remove any enum
614 * array entry that _doesn't_ match the index(es).
616 for (i
= 0; i
< ntea
; i
++) {
618 __nis_table_mapping_t
**tp
;
624 q
= pseudoEntryObj2Query(tea
[i
], 0, 0);
628 tp
= selectTableMapping(t
, q
, 0, 0, dbId
,
630 if (tp
== 0 || numMatches
<= 0)
639 logmsg(MSG_NOTIMECHECK
, LOG_INFO
, "%s: %d entries from LDAP",
642 db_index_entry
*dbie
;
647 * Find the entries in the DB that currently match the
648 * query, and add them to the enum array. Those that
649 * remain untouched when we've processed the LDAP data
650 * don't currently exist in LDAP, and should be deleted
653 dbie
= mindex
->satisfy_query_dbonly(qin
, &count
, FALSE
, &valid
);
654 if (dbie
!= 0 && valid
&& count
> 0) {
655 table
->setEnumMode(count
);
657 for (i
= 0; i
< count
; i
++) {
658 table
->enumSetup(dbie
->getlocation(), i
);
659 dbie
= dbie
->getnextresult();
668 entry_col ec
[NIS_MAXCOLUMNS
+1];
669 for (i
= 0, na
= 0; i
< nq
; i
++) {
679 #ifdef NISDB_LDAP_DEBUG
680 printQuery(res
[i
], t
);
682 #endif /* NISDB_LDAP_DEBUG */
684 /* Assemble an object from the query and attributes */
685 (void) memset(&o
, 0, sizeof (o
));
687 o
.zo_owner
= oa
[i
]->zo_owner
;
688 o
.zo_group
= oa
[i
]->zo_group
;
689 o
.zo_domain
= oa
[i
]->zo_domain
;
690 o
.zo_access
= oa
[i
]->zo_access
;
691 o
.zo_ttl
= oa
[i
]->zo_ttl
;
693 if ((to
= t
->obj
) != 0) {
694 o
.zo_name
= to
->zo_name
;
695 o
.zo_data
.objdata_u
.en_data
.en_type
=
696 to
->zo_data
.objdata_u
.ta_data
.ta_type
;
697 tc
= to
->zo_data
.objdata_u
.ta_data
.ta_cols
.ta_cols_val
;
698 if (to
->zo_data
.objdata_u
.ta_data
.ta_cols
.ta_cols_len
702 o
.zo_owner
= to
->zo_owner
;
704 o
.zo_group
= to
->zo_group
;
705 if (o
.zo_domain
== 0)
706 o
.zo_domain
= to
->zo_domain
;
707 if (o
.zo_access
== 0)
708 o
.zo_access
= to
->zo_access
;
710 o
.zo_ttl
= to
->zo_ttl
;
713 o
.zo_owner
= (nis_name
)"";
714 o
.zo_group
= (nis_name
)"";
715 o
.zo_domain
= (nis_name
)"";
718 o
.zo_data
.zo_type
= NIS_ENTRY_OBJ
;
719 o
.zo_data
.objdata_u
.en_data
.en_cols
.en_cols_len
=
721 o
.zo_data
.objdata_u
.en_data
.en_cols
.en_cols_val
= ec
;
723 (void) memset(&ec
, 0, sizeof (ec
));
725 qc
= res
[i
]->queryloc();
730 for (j
= 0; j
< nc
; j
++) {
731 int ic
= 1+ qc
[j
].which_index
;
732 if (ic
< 1 || ic
> t
->numColumns
)
734 #ifdef SET_ENTRY_FLAGS
737 entryFlagsFromTable(tc
[ic
-1].tc_flags
);
740 * In theory, the entry flags should be derived
741 * from the table flags. However, that doesn't
742 * seem to be the way that the DB code has done
743 * things so far, so leave the entry flags unset.
745 #endif /* SET_ENTRY_FLAGS */
746 qc
[j
].index_value
->get_value(
747 &ec
[ic
].ec_value
.ec_value_val
,
748 (int *)&ec
[ic
].ec_value
.ec_value_len
);
752 e
= makePseudoEntryObj(&o
, &eo
, t
->obj
);
759 * 'o' is currently a pseudo-object of type entry, with
760 * column zero used for an XDR:ed version of the entry_obj,
761 * column one the real column zero of the entry, etc.
762 * We now need a real NIS_ENTRY_OBJ object, so move the
763 * entry_col array one step left.
765 o
.zo_data
.objdata_u
.en_data
.en_cols
.en_cols_len
= t
->numColumns
;
766 o
.zo_data
.objdata_u
.en_data
.en_cols
.en_cols_val
= &ec
[1];
768 stat
= mindex
->updateTableEntry(e
, 1, t
->objName
, &o
, t
->obj
,
769 o
.zo_oid
.mtime
, &xid
);
771 * LDAP_SUCCESS => Entry added or modified
772 * LDAP_COMPARE_TRUE => Entry same as existing one
775 if (stat
== LDAP_SUCCESS
) {
777 } else if (stat
== LDAP_COMPARE_TRUE
) {
780 logmsg(MSG_NOTIMECHECK
, LOG_WARNING
,
781 "%s: Error adding entry to \"%s\": %s",
782 myself
, NIL(t
->objName
),
783 ldap_err2string(stat
));
786 if (e
->en_cols
.en_cols_val
!= 0)
787 sfree(e
->en_cols
.en_cols_val
[0].ec_value
.ec_value_val
);
794 /* Take care of deletes if we enumerated the table */
796 ea
= table
->endEnumMode(&numEa
);
797 logmsg(MSG_NOTIMECHECK
, LOG_INFO
,
798 "%s: %d entries added/updated", myself
, na
);
803 uint32_t nowt
= time(0);
805 for (i
= 0; i
< numEa
; i
++) {
811 st
= mindex
->updateTableEntry(ea
[i
], 0, t
->objName
, 0,
813 if (st
== LDAP_SUCCESS
) {
816 logmsg(MSG_NOTIMECHECK
, LOG_WARNING
,
817 "%s: Error removing directory entry for \"%s\": %s",
818 myself
, NIL(t
->objName
),
819 ldap_err2string(st
));
820 if (stat
== LDAP_SUCCESS
)
824 if (stat
== LDAP_SUCCESS
) {
826 (void) gettimeofday(&now
, 0);
827 table
->mapping
.enumExpire
= now
.tv_sec
+
831 logmsg(MSG_NOTIMECHECK
, LOG_INFO
,
832 "%s: %d entries deleted", myself
, na
-nau
);
837 /* If we called log_action() successfully, we need to sync the log */
839 (void) ((db
*)mindex
->getDbPtr())->sync_log();
841 if (xid
!= 0 && na
> 0 && stat
== LDAP_SUCCESS
)
842 ret
= endTransaction(xid
, dirObj
);
844 ret
= abort_transaction(xid
);
848 logmsg(MSG_NOTIMECHECK
, LOG_ERR
,
849 "%s: Error %s transaction for \"%s\"",
850 myself
, (na
> 0 && stat
== LDAP_SUCCESS
) ?
851 "ending" : "aborting",
853 stat
= LDAP_OPERATIONS_ERROR
;
856 mindex
->clearNoLDAPquery();
857 mindex
->clearNoWriteThrough();
860 #ifdef NISDB_LDAP_DEBUG
862 #endif /* NISDB_LDAP_DEBUG */
865 logmsg(MSG_NOTIMECHECK
, LOG_INFO
,
866 "%s: enumeration \"%s\" done", myself
, NIL(t
->objName
));
868 if (arg
->isDeferred
) {
870 * Rollback doesn't recover data written to disk, so
871 * we should commit even if we're returning failure.
873 dstat
= InUseDictionary
->commit(t
->objPath
);
874 if (dstat
!= DB_SUCCESS
) {
875 logmsg(MSG_NOTIMECHECK
, LOG_WARNING
,
876 "%s: DB error %d committing \"%s\"",
877 myself
, dstat
, NIL(t
->objName
));
880 (void) mutex_lock(&table
->mapping
.enumLock
);
881 if (arg
->isDeferred
&& dstat
== DB_SUCCESS
)
882 table
->mapping
.enumDeferred
= 0;
883 table
->mapping
.enumStat
= stat
;
887 (void) gettimeofday(&end
, 0);
888 end
.tv_sec
-= start
.tv_sec
;
889 end
.tv_usec
-= start
.tv_usec
;
890 if (end
.tv_usec
< 0) {
891 end
.tv_usec
+= 1000000;
894 table
->mapping
.enumTime
= 1000000*end
.tv_sec
+ end
.tv_usec
;
895 logmsg(MSG_NOTIMECHECK
,
896 #ifdef NISDB_LDAP_DEBUG
900 #endif /* NISDB_LDAP_DEBUG */
901 "%s: %d entries in %ld usec => %ld usec/entry",
902 NIL(t
->objName
), table
->mapping
.enumEntries
,
903 table
->mapping
.enumTime
,
904 table
->mapping
.enumTime
/
905 (table
->mapping
.enumEntries
!= 0 ?
906 table
->mapping
.enumEntries
: 1));
908 table
->mapping
.enumTid
= 0;
909 (void) mutex_unlock(&table
->mapping
.enumLock
);
911 WRITEUNLOCKNR(table
, stat3
, "table wu db_mindex::entriesFromLDAPreal");
912 WRITEUNLOCKNR(mindex
, stat2
, "db_mindex::entriesFromLDAPreal wu");
913 WRITEUNLOCKNR(((db
*)mindex
->getDbPtr()), lstat
,
914 "db db_mindex::entriesFromLDAPreal wu");
915 unlockTransLog(myself
, 1);
917 logmsg(MSG_NOTIMECHECK
, LOG_WARNING
,
918 "%s: Error %d unlocking db_table", myself
, stat3
);
920 logmsg(MSG_NOTIMECHECK
, LOG_WARNING
,
921 "%s: Error %d unlocking db_mindex", myself
, stat2
);
923 logmsg(MSG_NOTIMECHECK
, LOG_WARNING
,
924 "%s: Error %d unlocking db", myself
, lstat
);
929 * Sets the oid (i.e., the creation and modification times) for the
930 * specified object. In order to avoid retrieving the old incarnation
931 * (if any) from the DB first, we're punting and setting both mtime
932 * and ctime to the current time.
935 setOid(nis_object
*obj
) {
937 obj
->zo_oid
.ctime
= obj
->zo_oid
.mtime
= time(0);