2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License (the "License"). 2N/A * You may not use this file except in compliance with the License. 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. 2N/A#
endif /* SET_ENTRY_FLAGS */ 2N/A * Retrieve container entries from LDAP per 't' and 'qin'/'q'. 2N/A * This is a helper function for db_mindex::queryLDAP(); see 2N/A * that function for details of the parameters (except doAsynch). 2N/A * If 'doAsynch' is set, and the retrieval is an enumeration 2N/A * (qin == NULL), the retrieval is performed in a detached 2N/A * thread. In this case, the return code just reflects the 2N/A * setup and launch of the detached thread. Retrieval will 2N/A * complete asynchronously. 2N/A const char *
myself =
"db_mindex::entriesFromLDAP";
2N/A * Check if an enumeration thread is running; if so, then regardless 2N/A * of whether or not the current operation is an enumeration, we 2N/A * just return success, and let our caller get the data from the 2N/A * existing (deferred) DB. 2N/A "%s: Enumeration thread %d not found for \"%s\"; exit status = %d (%s)",
2N/A /* Reflect the fact that no enum thread is running */ 2N/A /* Cleanup deferred mode */ 2N/A "%s: DB error %d committing \"%s\"",
2N/A "%s: Enumeration thread %d already running for \"%s\"",
2N/A "%s: Error %d looking for enumeration thread %d for \"%s\"",
2N/A * If we're enumerating (and hence expect that retrieving all data, 2N/A * and updating the local DB, might take a while), create a deferred- 2N/A * update table that clients can use while we are updating the real 2N/A "%s: Unable to defer updates for \"%s\" (status=%d);" 2N/A " updating in place",
2N/A /* If enumerating, perform the operation in a separate thread */ 2N/A#
endif /* FORCE_SYNCHRONOUS */ 2N/A "%s: Error %d creating new thread; using current one",
2N/A * We're now returning to the caller, who will get data 2N/A * The deferred DB, if an enumeration thread already 2N/A * was running, and deferred mode was on, or 2N/A * The original DB, if we just started an enumeration 2N/A * thread. In this case, our caller (several levels up) 2N/A * means that the enum thread will have to wait for 2N/A * our caller once it's done the LDAP retrieval, and 2N/A * wants to update the DB. 2N/A "%s: thread %d => %d",
2N/A "%s: pthread_join(%d) => %d",
2N/A#
endif /* FORCE_SYNCHRONOUS */ 2N/A * We use this 'extern "C"' function in order to make sure that 2N/A * pthread_create() doesn't have any problems trying to invoke a 2N/A /* Lock to prevent removal */ 2N/A "entriesFromLDAPthread");
2N/A * It's possible that the db_mindex for the table has changed, 2N/A * or disappeared, between now and the time when our parent 2N/A * thread released its lock on the table. Hence, we search the 2N/A * dictionary to re-acquire the 'db', and the db_mindex. 2N/A#
endif /* NISDB_LDAP_DEBUG */ 2N/A "entriesFromLDAPthread: %s -> %s -> 0x%x (0x%x)",
2N/A#
endif /* NISDB_LDAP_DEBUG */ 2N/A "entriesFromLDAPthread");
2N/A "db_mindex::entriesFromLDAPreal";
2N/A /* We haven't done anything, so rollback should be OK */ 2N/A "%s: DB error %d rolling back \"%s\"",
2N/A * Had rollback succeeded, the 'table' 2N/A * would have disappeared. However, since 2N/A * rollback failed, we need to update the 2N/A * table->mapping.enum* fields. 2N/A /* Getting table entries */ 2N/A "%s: mapFromLDAP() => 0x%x, status=%d %s; nq = %d",
2N/A#
endif /* NISDB_LDAP_DEBUG */ 2N/A * Keep track of the number of NIS+ entries we got back; 2N/A * note that the number of LDAP entries may have been 2N/A * smaller or larger. 2N/A * If we get LDAP_NO_SUCH_OBJECT, we need to delete the entries 2N/A * in the table, so we can't just return. 2N/A "%s: mapFromLDAP() => 0x0, status=%d (%s)",
2N/A "%s: DB error %d rolling back \"%s\"",
2N/A * Had rollback succeeded, the 'table' 2N/A * would have disappeared. However, since 2N/A * rollback failed, we need to update the 2N/A * table->mapping.enum* fields. 2N/A * Need to disable write-through to LDAP, for which we need a lock 2N/A * on our db_mindex ('mindex'); we're also updating the table, so 2N/A * we need a write lock on that as well. However, before locking the 2N/A * mindex, we need to maintain lock integrity by acquiring the 2N/A * trans log lock. Note that actually beginning a transaction is 2N/A * expensive, so we defer that until we know that we really need 2N/A "%s: transaction log busy; no LDAP update for \"%s\"",
2N/A "%s: Error %d locking transaction log; no LDAP update for \"%s\"",
2N/A "%s: DB error %d rolling back \"%s\"",
2N/A * Had rollback succeeded, the 'table' 2N/A * would have disappeared. However, since 2N/A * rollback failed, we need to update the 2N/A * table->mapping.enum* fields. 2N/A * If we have any updates, we'll call db::sync_log, which write- 2N/A * locks the 'db' instance. In order to avoid a dead-lock with 2N/A * threads performing a DB lookup (which will lock the 'db' and 2N/A * then the 'db_mindex'), we need hence need to lock in the 2N/A * trans.log (already holding that one) 2N/A "w db db_mindex::entriesFromLDAPreal");
2N/A "table w db_mindex::entriesFromLDAPreal");
2N/A "%s: 'db' busy; no LDAP update for \"%s\"",
2N/A "%s: 'db' lock error %d; no LDAP update for \"%s\"",
2N/A "%s: 'db_mindex' busy; no LDAP update for \"%s\"",
2N/A "%s: 'db_mindex' lock error %d; no LDAP update for \"%s\"",
2N/A "%s: 'db_table' busy; no LDAP update for \"%s\"",
2N/A "%s: 'db_table' lock error %d; no LDAP update for \"%s\"",
2N/A "%s: DB error %d rolling back \"%s\"",
2N/A * Had rollback succeeded, the 'table' 2N/A * would have disappeared. However, since 2N/A * rollback failed, we need to update the 2N/A * table->mapping.enum* fields. 2N/A "db_mindex::entriesFromLDAPreal wu",
2N/A "db_mindex::entriesFromLDAPreal wu db");
2N/A "db_mindex::entriesFromLDAPreal wu db");
2N/A * If there is no non-indexed table mapping, we must filter 2N/A * the enum mode (i.e., deletion candidates) array to only 2N/A * contain those entries that match the indexes. 2N/A * Walk through the entry array, and remove any enum 2N/A * array entry that _doesn't_ match the index(es). 2N/A * Find the entries in the DB that currently match the 2N/A * query, and add them to the enum array. Those that 2N/A * remain untouched when we've processed the LDAP data 2N/A * don't currently exist in LDAP, and should be deleted 2N/A#
endif /* NISDB_LDAP_DEBUG */ 2N/A /* Assemble an object from the query and attributes */ 2N/A for (j = 0; j <
nc; j++) {
2N/A * In theory, the entry flags should be derived 2N/A * from the table flags. However, that doesn't 2N/A * seem to be the way that the DB code has done 2N/A * things so far, so leave the entry flags unset. 2N/A#
endif /* SET_ENTRY_FLAGS */ 2N/A * 'o' is currently a pseudo-object of type entry, with 2N/A * column zero used for an XDR:ed version of the entry_obj, 2N/A * column one the real column zero of the entry, etc. 2N/A * We now need a real NIS_ENTRY_OBJ object, so move the 2N/A * entry_col array one step left. 2N/A * LDAP_SUCCESS => Entry added or modified 2N/A * LDAP_COMPARE_TRUE => Entry same as existing one 2N/A "%s: Error adding entry to \"%s\": %s",
2N/A /* Take care of deletes if we enumerated the table */ 2N/A "%s: Error removing directory entry for \"%s\": %s",
2N/A /* If we called log_action() successfully, we need to sync the log */ 2N/A "%s: Error %s transaction for \"%s\"",
2N/A "ending" :
"aborting",
2N/A#
endif /* NISDB_LDAP_DEBUG */ 2N/A * Rollback doesn't recover data written to disk, so 2N/A * we should commit even if we're returning failure. 2N/A "%s: DB error %d committing \"%s\"",
2N/A#
endif /* NISDB_LDAP_DEBUG */ 2N/A "db db_mindex::entriesFromLDAPreal wu");
2N/A * Sets the oid (i.e., the creation and modification times) for the 2N/A * specified object. In order to avoid retrieving the old incarnation 2N/A * (if any) from the DB first, we're punting and setting both mtime 2N/A * and ctime to the current time.