mapped_cache.cc revision 7b1b42816975f5b0069dff7932115ba672ad125c
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (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 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include "mt.h"
#include <unistd.h>
#include <values.h>
#include <string.h>
#include <syslog.h>
#include <errno.h>
#include <malloc.h>
#include "mapped_cache.h"
#include "cold_start.h"
#include "nis_cache.h"
#include <rpcsvc/daemon_utils.h>
#define CACHE_VERSION 3
#define CACHE_MAGIC 0xbabeeeeeU
union semun {
int val;
} arg;
{
err = NIS_SUCCESS;
serverMode = mode;
mapBase = (char *)-1;
mapSize = -1;
if (serverMode) {
up = 0;
if (!checkUID()) {
return;
}
if (!createSemaphores()) {
return;
}
(void) lockExclusive();
if (discardOldCache || !mapCache()) {
if (!createCache()) {
return;
}
if (!mapCache()) {
return;
}
}
} else {
if (!getSemaphores()) {
return;
}
/* lockShared() will map in the cache */
if (!lockShared()) {
return;
}
unlockShared();
}
}
{
}
int
{
return (0);
}
return (1);
}
int
{
int st;
int semflg;
// get writer semaphore
return (0);
}
// get writer semaphore value
return (0);
}
// check to see if a manager is already handling the cache
if (w_array[NIS_SEM_MGR_UP] != 0) {
if (st == -1) {
return (0);
}
}
return (1);
}
int
{
int semflg = 0;
// get writer semaphore
return (0);
}
return (1);
}
int
{
const char *name;
int open_mode;
int map_mode;
int status = 0;
int fd = -1;
if (serverMode) {
} else {
name = CACHE_FILE;
}
if (fd == -1)
goto done;
goto done;
}
if (mapBase == (char *)-1) {
mapSize = -1;
goto done;
}
/* Record time of mapping */
(void) gettimeofday(&now, 0);
goto done;
}
if (serverMode) {
goto done;
} else {
/*
* If the header is not valid and the cache manager
* is not running, then all is lost.
*/
if (!checkUp())
goto done;
}
}
if (serverMode)
status = 1;
done:
if (fd != -1)
if (status == 0) {
if (mapBase != (char *)-1) {
mapBase = (char *)-1;
mapSize = -1;
}
}
return (status);
}
void
{
if (mapBase != (char *)-1)
}
int
{
int i;
int fd;
int st;
int status = 0;
/*
* Remove any left-over private cache file. The shared cache
* file (if any) will be marked invalid and replaced when we're
* done recreating the private cache.
*/
(void) unlink(PRIVATE_CACHE_FILE);
if (fd == -1) {
goto done;
}
for (i = 0; i < NUM_SECTIONS; i++) {
}
if (st == -1) {
goto done;
goto done;
}
status = 1;
done:
if (status == 0) {
if (fd != -1)
/* Remove broken private cache; mark shared cache invalid. */
(void) unlink(PRIVATE_CACHE_FILE);
}
return (status);
}
int
{
int size;
int offset;
int length;
if (!lockExclusive())
return (0);
return (0);
}
return (1);
}
char *
{
int offset;
int length;
char *uaddr;
if (!lockShared())
return (0);
if (uaddr) {
}
unlockShared();
return (uaddr);
}
void
{
}
up = 1;
}
void
{
/* if we never successfully started, just return */
if (!up)
return;
/*
* Sync the cache file in case we were in the middle
* of an update.
*/
if (mapBase != (char *)-1) {
/* what should we do here? */
}
}
}
}
int
{
if (sem_writer == -1)
return (FALSE);
return (FALSE);
if (w_array[NIS_SEM_MGR_UP] == 0) {
// cache manager not running
return (FALSE);
}
return (TRUE);
}
{
int i;
int distance;
int minDistance = MAXINT;
char **target;
int target_levels;
int found = 0;
found_entry.broken_name = 0;
if (target == 0)
return (NIS_NOMEMORY);
if (!lockShared()) {
return (NIS_SYSTEMERROR);
}
if (i == 0)
firstBinding(&scan);
else
nextBinding(&scan);
if (distance <= minDistance) {
// if two directories are at the same distance
// then we want to select the directory closer to
// the root.
if (distance == minDistance &&
continue;
}
/*
* Free broken name of old saved entry.
*/
if (found)
/*
* Save this entry.
*/
found = 1;
found_entry = scan;
/*
* If we got an exact match, then we are done.
*/
if (distance == 0)
break;
} else {
}
}
if (found == 0) {
// cache is empty (no coldstart even)
unlockShared();
// we wanted an exact match, but it's not there
unlockShared();
err = NIS_NOTFOUND;
} else {
// we got an exact match or something near target
err = NIS_SUCCESS;
unlockShared();
err = NIS_NOMEMORY;
else
}
return (err);
}
void
{
int i;
char *dname;
int is_coldstart = 0;
return;
is_coldstart = 1;
if (!lockExclusive())
return;
if (i == 0)
firstBinding(&scan);
else
nextBinding(&scan);
break;
}
}
if (is_coldstart)
else
return;
}
if (is_coldstart)
}
void
{
int i;
int levels;
char **broken_name;
if (!lockExclusive())
return;
if (broken_name == NULL) {
return;
}
if (i == 0)
firstBinding(&scan);
else
nextBinding(&scan);
break;
}
}
}
void
{
int i;
if (!lockShared())
return;
if (i == 0)
firstBinding(&scan);
else
nextBinding(&scan);
// hack for special format in nisshowcache
if (__nis_debuglevel != 6) {
if (i == 0)
(void) printf("\nCold Start directory:\n");
else
(void) printf("\nNisSharedCacheEntry[%d]:\n",
i);
}
if (__nis_debuglevel == 1) {
(void) printf("\tdir_name:'");
(void) printf("'\n");
}
if (__nis_debuglevel > 2) {
}
}
}
(void) printf("\nActive servers:\n");
if (i == 0)
else
}
unlockShared();
}
int
{
int i;
int n;
int extra;
int fd = -1;
char *buf = 0;
int status = 0;
char *src;
char *dst;
int amount;
/* need to increase the size of the cache file */
if (buf == 0) {
goto done;
}
if (fd == -1) {
goto done;
}
if (n == -1) {
goto done;
} else if (n != extra) {
goto done;
}
if (mapBase == (char *)-1) {
mapSize = -1;
goto done;
}
}
}
status = 1;
done:
if (fd != -1)
return (status);
}
void
{
int i;
char *src;
char *dst;
int amount;
}
}
void
{
}
int
{
int i;
int size;
int offset;
int levels;
char **broken_name;
void *packed;
int packed_len;
char *buf;
char *name_start;
int status = 0;
goto done;
if (broken_name == NULL)
goto done;
/* determine space needed to store entry */
size = 0;
size += sizeof (int); /* entry length */
size += sizeof (int); /* levels in directory name */
for (i = 0; i < levels; i++) {
}
size += sizeof (int); /* data length */
/* create buffer to hold data */
goto done;
/* write data to buffer */
offset = 0;
offset += sizeof (int);
offset += sizeof (int);
for (i = 0; i < levels; i++) {
}
offset += sizeof (int);
entry->broken_name = (char **)
}
status = 1;
done:
if (broken_name)
return (status);
}
void
{
}
void
{
}
void
{
int i;
char *p;
if (magic != CACHE_MAGIC) {
return;
}
p += sizeof (int);
p += sizeof (int);
p += sizeof (uint32_t);
p += sizeof (int);
entry->broken_name = (char **)
entry->broken_name[i] = p;
p += strlen(p) + 1;
}
entry->binding_len = *(int *)p;
p += sizeof (int);
}
int
{
int size;
int offset;
char *buf;
void *packed;
int packed_len;
int status = 0;
goto done;
/* determine space needed to store entry */
size = 0;
size += sizeof (int); /* entry length */
size += sizeof (int); /* data length */
/* create buffer to hold data */
goto done;
/* write data to buffer */
offset = 0;
offset += sizeof (int);
offset += sizeof (int);
offset += packed_len;
status = 1;
done:
return (status);
}
void
{
char *p;
if (magic != CACHE_MAGIC) {
return;
}
p += sizeof (u_int);
p += sizeof (int);
p += strlen(p) + 1;
p += strlen(p) + 1;
p += strlen(p) + 1;
entry->active_len = *(int *)p;
p += sizeof (int);
}
void
{
}
void
{
}
void
{
if (!lockExclusive())
return;
return;
}
return;
}
}
void
{
int i;
if (!lockExclusive())
return;
if (i == 0)
else
/*
* If we are getting rid of all servers regardless
* of protocol, then we need to restart the
* search because removing an entry invalidates
* our "iteration". If we are just removing
* a single server, then we are done.
*/
if (all)
goto restart;
break;
}
}
}
int
{
int ret = 0;
if (!lockShared())
return (ret);
unlockShared();
return (ret);
}
int
{
int i;
if (i == 0)
else
return (1);
}
}
return (0);
}
int
{
int ret = 0;
if (!lockShared())
return (ret);
unlockShared();
return (ret);
}
int
{
int i;
if (i == 0)
else
if (*act)
return (1);
else
return (0);
}
}
return (0);
}
int
{
int i;
int stale_count = 0;
if (!lockShared()) {
*bindings = 0;
return (0);
}
/*
* We allocate more than we need so that we don't have to
* figure out how many stale entries there are ahead of time.
*/
*bindings = (nis_bound_directory **)
unlockShared();
return (0);
}
if (i == 0)
firstBinding(&scan);
else
nextBinding(&scan);
/*
* Unpack the binding, but don't bother adding
* the bound addresses, because purging doesn't
* need them.
*/
(*bindings)[stale_count] =
stale_count++;
}
}
unlockShared();
return (stale_count);
}
int
{
int i;
int n;
if (!lockShared()) {
*bindings = 0;
return (0);
}
*bindings = (nis_bound_directory **)
unlockShared();
return (0);
}
n = 0;
if (i == 0)
firstBinding(&scan);
else
nextBinding(&scan);
/*
* Unpack the binding, but don't bother adding
* the bound addresses, because we don't
* need them.
*/
(*bindings)[n] =
n++;
}
unlockShared();
return (n);
}
int
{
int i;
if (!lockShared()) {
*actlist = 0;
return (0);
}
*actlist = (nis_active_endpoint **)
unlockShared();
return (0);
}
if (i == 0)
else
/*
* Unpack the entry, but don't bother adding
* the bound addresses, because we don't
* need them.
*/
}
unlockShared();
return (i);
}
int
{
int i;
int diff;
int min = -1;
if (!lockShared()) {
return (-1);
}
if (i == 0)
firstBinding(&scan);
else
nextBinding(&scan);
if (diff < 0)
diff = 0;
}
unlockShared();
return (min);
}
int
NisMappedCache::align(int n)
{
return ((n + 3) & ~3);
}
/*
* The mapped cache is shared by both ILP32 and LP64 processes.
* Both need to see the mapped cache identically, hence all
* padding is aligned to an int i.e 4 byte boundary.
*/
{
asize = (sizeof (int) - 1);
}
{
int fd;
if (fd >= 0) {
"mapSharedCacheHeader: mmap(\"%s\"): %m",
}
}
return (hdr);
}
void
{
-1) {
"markSharedCacheInvalid: msync(\"%s\"): %m",
}
"markSharedCacheInvalid: munmap<old>: %m");
}
}
}
int
{
int fd;
char *buf;
int st;
int count;
/*
* Create a copy of the private cache in TMP_CACHE_FILE.
*/
(void) unlink(TMP_CACHE_FILE);
if (fd == -1) {
return (0);
}
while (count > 0) {
if (st == -1) {
(void) unlink(TMP_CACHE_FILE);
return (0);
}
}
if (st == -1) {
(void) unlink(TMP_CACHE_FILE);
return (0);
}
/*
* Open the current public cache file and map in the
* header so that we will be able to mark it invalid
* even after we clobber it with the new cache file.
*/
pub = mapSharedCacheHeader();
/*
* Rename the tmp cache file to the new name. This is an
* atomic operation; other processes opening CACHE_FILE will
* either get the old one or the new one.
*/
if (st == -1) {
(void) unlink(TMP_CACHE_FILE);
return (FALSE);
}
/*
* Now mark the old incarnation of the public cache invalid.
* We delay doing this until after the rename that replaces
* the old file, so that any process that (re-)opens the public
* cache will always get a valid file.
*/
return (1);
}
int
{
return (1);
}
void
{
if (serverMode)
}
int
{
int save_errno;
while (1) {
/*
* Make sure that we have mapped the whole cache. It is
* okay to map more than the size of the cache; we won't
* read that far. We release our shared lock and then
* grab an exclusive lock. This will prevent any
* interaction between threads on the cache pointers.
*/
(void) gettimeofday(&now, 0);
if (mapBase == (char *)-1 ||
unlockShared();
(void) lockExclusive();
unmapCache();
if (!mapCache()) {
return (0);
}
continue;
}
break;
}
return (1);
}
void
{
}