/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* DESCRIPTION: Contains the map update thread and related code.
*/
#include <unistd.h>
#include <syslog.h>
#include <ndbm.h>
#include <thread.h>
#include <unistd.h>
#include <strings.h>
#include "ypsym.h"
#include "ypdefs.h"
#include "shim.h"
#include "yptol.h"
#include "../ldap_util.h"
/* Enable standard YP code features defined in ypdefs.h */
/*
* Decs
*/
void * update_thread(void *);
/*
* Globals
*/
extern pid_t parent_pid;
/*
* FUNCTION: update_entry_if_required()
*
* DESCRIPTION: Determines if an entry is to be updated and if it is does the
* update.
*
* GIVEN : Pointer to the open map ctrl
* Pointer to the entry key
*
* RETURNS : SUCCESS = Entry is in a state to be returned to the client
* i.e. either got updated, did not need to be updated or we are
* in a mode where it is acceptable to return out of date
* information.
* FAILURE = Entry need an update but it could not be done.
*/
{
/* Only update individual entries if entire map is */
/* not being updated */
if (is_map_updating(map))
return (SUCCESS);
/*
* If we are being asked for the order then need to check if
* the map is in need of an update. If it is then fake a
* recent order. The client will then read the map, using
* dbm_firstkey and this will do the update.
*/
if (has_map_expired(map))
return (SUCCESS);
}
/* Never update special keys. Have no TTLs */
if (is_special_key(key))
return (SUCCESS);
/* Didn't need an update */
return (SUCCESS);
/* Do the update */
}
/*
* FUNCTION: update_from_dit()
*
* DESCRIPTION: Called to update an entry from the DIT
*
* INPUTS: Map control structure for an open map
* Entry key
*
* OUTPUTS: SUCCESS = Update complete or we are in a mode where it is
* acceptable to return out of date information.
* FAILURE = Update failed
*
*/
{
int ret;
/*
* Netgroup maps are a special case we cannot update just one entry so
* update the entire map instead.
*/
}
/* Read entry from the DIT */
/* Check that we got something */
if (0 == ret) {
/*
* In a mode where it is acceptable to return out of
* date information.
*/
"LDAP inaccessible returning old information");
return (SUCCESS);
} else {
/*
* In a mode where it is not acceptable to return out
* of date information.
*
* If the error positviely indicates that there is no
* such entry delete it. For errors where object may
* still exist in the DIT leave it.
*/
if (MAP_NO_MATCHING_KEY == ret) {
/*
* Don't log errors. If the entry was not
* already present then no problem. The user
* just asked us for a non existant entry.
*/
}
return (FAILURE);
}
}
/* Write it to DBM */
return (FAILURE);
/* Update TTL */
return (SUCCESS);
}
/*
* FUNCTION: update_map_if_required()
*
* DESCRIPTION: Called to update an entire map if it is out of date. Map ctrl
* must be locked before this is called. This handles checking if
* the map is already being updated. It is important that this is
* done atomically with obtaining the maps update lock.
*
* INPUTS: Map control structure for an open map
* Flag indication if we should wait for completion
*
* OUTPUTS: SUCCESS = Map update initiated
* FAILURE = Map update not initiated
*/
{
long flags;
if (wait) {
/*
* Actually get the lock
*
* May block so unlock map_ctrl while it is done
*/
"Could not lock map %s for update",
return (FAILURE);
}
} else {
/* If not waiting try to get the lock */
switch (try_lock_map_update(map)) {
case 0:
/*
* We got the lock. Continue to start an update.
*/
break;
case EBUSY:
/*
* Some one else got the lock. OK they are
* doing the update so we can just return.
*/
return (SUCCESS);
default:
/*
* Some serious problem with lock.
*/
return (FAILURE);
}
}
/*
* If we get here are holding the update lock. Make a final check that
* nobody beat us to the map update while we were getting it.
*/
if (!has_map_expired(map)) {
/* A big waste of time. Somebody else did the update */
return (SUCCESS);
}
/*
* We got the lock and nobody beat us to doing the update. Start our
* own update.
*
* Thread will free the update lock when update is complete.
*/
/*
* Make a copy of the map_ctrl structure so the update thread has an
* independent version to work with. Note: Must not be on stack.
*
* On exit the update thread must free this.
*/
return (FAILURE);
}
/*
* While thread is running unlock map so other processes can
* execute non update related accesses
*/
/*
* If we are not going to thr_join then need to create detached.
* This prevents a zombie being left when nobody joins us.
*/
flags |= THR_DETACHED;
/* Kick off update thread */
"Could not create NIS update thread");
return (FAILURE);
}
if (wait) {
/* May block but no problem map_ctrl is already unlocked. */
}
/* Re acquire lock */
return (FAILURE);
}
return (SUCCESS);
}
/*
* FUNCTION: update_thread()
*
* DESCRIPTION: The update thread this is called to update an entire NIS map.
* if several NIS maps are found to be out of date several
* instances of this may be running at the same time.
*
* Since we are using a duplicate map_ctrl we do not have to lock
* it. If we did would end up using the same mutex as the parent
* map ctrl an possibly deadlocking.
*
* INPUTS: Map handle (because we need access to name and lock)
*
* OUTPUTS: None exits when finished.
*/
void *
{
/* Cast argument pointer to correct type */
/* Actually do the work */
ret = 0;
/* Update complete or failed */
/* Free up duplicate copy of the map_ctrl */
}
/*
* FUNCTION : is_special_key()
*
* DESCRIPTION: Works out if a given key is one of the special ones. We just
* check for the "YP_" prefix. This is not 100% safe but if
* valid keys with a "YP_" prefix exist in the DIT then a lot of
* other parts of NIS wont work.
*/
{
return (TRUE);
return (FALSE);
}