/*
* 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 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* This module contains a cache used to optimized scope and DA
* discovery. Entries live for a short duration only (about 10 seconds),
* although their lifetime can be advanced somewhat by frequent use.
* The intent is that the canonical source for DAs will always be slpd,
* so the short lifetime of cache entries is designed to force clients
* to consult slpd frequently so as to pick up the latest DA state
* quickly.
*
* The cache is managed by a thread which monitors calls into the cache.
* If the cache has been unused for a certain amount of time, the thread
* frees the cache and exits.
*
* The cache is keyed on the queries sent to slpd to access slpd's DA
* table. Associated with each query is a reply (in the format of an
* on-the-wire SLP SRVRPLY message).
* The cache is accessed by the following two functions:
*
* slp_find_das_cached: searches the cache
* slp_put_das_cached: adds a reply to the cache
*
* All parameters added to the cache are copied in first, and all results
* read from the cache are copied out, so all memory must be freed by
* the caller.
*/
#include <stdio.h>
#include <stdlib.h>
#include <thread.h>
#include <synch.h>
#include <syslog.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <slp-internal.h>
/* These constants control the behaviour of the cache */
/* Management thread components */
static int cache_thr_running;
static int cache_called;
static SLPError start_cache_thr();
static void cache_thr();
/* The cache and cache synchronization */
static void *da_cache;
struct cache_entry {
const char *query;
const char *reply;
unsigned int reply_len;
};
/* cache management and searching */
static int compare_entries(const void *, const void *);
static void free_cache_entry(void *, VISIT);
/*
* Searches the cache for the reply to 'query'. Returns the reply if
* found, otherwise NULL.
* The caller must free the result.
*/
if (!cache_thr_running) {
if (start_cache_thr() != SLP_OK) {
return (NULL);
}
}
(void) mutex_lock(&cache_lock);
if (ans) {
goto done;
}
/* copy out the reply */
"out of memory");
goto done;
}
}
/* notify cache thread of call */
(void) mutex_lock(&cache_called_lock);
cache_called = 1;
(void) cond_signal(&cache_called_cond);
(void) mutex_unlock(&cache_called_lock);
done:
(void) mutex_unlock(&cache_lock);
return (reply);
}
/*
* Adds 'reply' to the cache under the index 'query'. Both parameters
* are copied in first, so the caller may free them after the call.
* 'len' is the length of 'reply' in bytes.
*/
unsigned int len) {
if (!cache_thr_running) {
if (start_cache_thr() != SLP_OK) {
return;
}
}
/* create the cache entry for this reply */
return;
}
return;
}
return;
}
/* write to the cache */
(void) mutex_lock(&cache_lock);
/* overwrite existing entry */
}
(void) mutex_unlock(&cache_lock);
}
}
}
}
int terr;
(void) mutex_lock(&start_lock);
if (cache_thr_running) {
goto start_done;
}
if ((terr = thr_create(
goto start_done;
}
cache_thr_running = 1;
(void) mutex_unlock(&start_lock);
return (err);
}
static void cache_thr() {
(void) mutex_lock(&cache_called_lock);
cache_called = 0;
while (cache_called == 0) {
int err;
&cache_called_lock, &timeout);
(void) mutex_lock(&cache_lock);
/* free cache */
if (da_cache) {
(void (*)(void *, VISIT, int, void *))free_cache_entry,
0, NULL);
}
(void) mutex_unlock(&cache_lock);
cache_thr_running = 0;
(void) mutex_unlock(&cache_called_lock);
} else {
cache_called = 0;
}
}
}