summaryrefslogtreecommitdiff
path: root/usr.sbin/ypserv/yp_dblookup.c
diff options
context:
space:
mode:
authorBill Paul <wpaul@FreeBSD.org>1996-04-28 04:38:52 +0000
committerBill Paul <wpaul@FreeBSD.org>1996-04-28 04:38:52 +0000
commitb2264be812244e197925dcdce14cd1b394118ae5 (patch)
tree8a812c67e9e63f836246125cbbd49d43a685fe54 /usr.sbin/ypserv/yp_dblookup.c
parent6290107b024e489db5fb29729c650b42a85941a2 (diff)
downloadsrc-test2-b2264be812244e197925dcdce14cd1b394118ae5.tar.gz
src-test2-b2264be812244e197925dcdce14cd1b394118ae5.zip
Notes
Diffstat (limited to 'usr.sbin/ypserv/yp_dblookup.c')
-rw-r--r--usr.sbin/ypserv/yp_dblookup.c323
1 files changed, 292 insertions, 31 deletions
diff --git a/usr.sbin/ypserv/yp_dblookup.c b/usr.sbin/ypserv/yp_dblookup.c
index 3f2415b9195c..0cffdb341f52 100644
--- a/usr.sbin/ypserv/yp_dblookup.c
+++ b/usr.sbin/ypserv/yp_dblookup.c
@@ -29,7 +29,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: yp_dblookup.c,v 1.3 1996/02/04 05:39:35 wpaul Exp $
+ * $Id: yp_dblookup.c,v 1.7 1996/04/27 17:50:18 wpaul Exp wpaul $
*
*/
#include <stdio.h>
@@ -40,9 +40,10 @@
#include <unistd.h>
#include <db.h>
#include <sys/stat.h>
+#include <sys/param.h>
#include <errno.h>
#include <paths.h>
-#include "yp.h"
+#include <rpcsvc/yp.h>
#include "yp_extern.h"
int ypdb_debug = 0;
@@ -52,22 +53,212 @@ int yp_errno = YP_TRUE;
HASHINFO openinfo = {
4096, /* bsize */
32, /* ffactor */
- 256, /* nelem */
- 2048 * 1024, /* cachesize */
+ 512, /* nelem */
+ 2048 * 512, /* cachesize */
NULL, /* hash */
0, /* lorder */
};
+#ifdef DB_CACHE
+#define MAXDBS 20
+#define LASTDB (MAXDBS - 1)
+
+struct dbent {
+ DB *dbp;
+ char *name;
+ char *key;
+ int size;
+};
+
+static struct dbent *dbs[MAXDBS];
+static int numdbs = 0;
+
/*
- * Open a DB database
+ * Make sure all the DB entries are NULL to start with.
*/
-DB *yp_open_db(domain, map)
+void yp_init_dbs()
+{
+ register int i;
+
+ for (i = 0; i < MAXDBS; i++);
+ dbs[i] = NULL;
+ return;
+}
+
+static inline void yp_flush(i)
+ register int i;
+{
+ (void)(dbs[i]->dbp->close)(dbs[i]->dbp);
+ dbs[i]->dbp = NULL;
+ free(dbs[i]->name);
+ dbs[i]->name = NULL;
+ dbs[i]->key = NULL;
+ dbs[i]->size = 0;
+ free(dbs[i]);
+ dbs[i] = NULL;
+ numdbs--;
+}
+
+/*
+ * Close all databases and erase all database names.
+ * Don't free the memory allocated for each DB entry though: we
+ * can just reuse it later.
+ */
+void yp_flush_all()
+{
+ register int i;
+
+ for (i = 0; i < MAXDBS; i++) {
+ if (dbs[i] != NULL && dbs[i]->dbp != NULL) {
+ yp_flush(i);
+ }
+ }
+}
+
+
+/*
+ * Add a DB handle and database name to the cache. We only maintain
+ * fixed number of entries in the cache, so if we're asked to store
+ * a new entry when all our slots are already filled, we have to kick
+ * out the entry in the last slot to make room.
+ */
+static inline void yp_add_db(dbp, name, size)
+ DB *dbp;
+ char *name;
+ int size;
+{
+ register int i;
+ register struct dbent *tmp;
+ static int count = 0;
+
+
+ tmp = dbs[LASTDB];
+
+ /* Rotate */
+ for (i = LASTDB; i > 0; i--)
+ dbs[i] = dbs[i - 1];
+
+ dbs[0] = tmp;
+
+ if (dbs[0]) {
+ if (ypdb_debug)
+ yp_error("table overflow -- releasing last slot");
+ yp_flush(0);
+ }
+
+ /*
+ * Add the new entry. We allocate memory for the dbent
+ * structure if we need it. We shoudly only end up calling
+ * malloc(2) MAXDB times. Once all the slots are filled, we
+ * hold onto the memory and recycle it.
+ */
+ if (dbs[0] == NULL) {
+ count++;
+ if (ypdb_debug)
+ yp_error("allocating new DB member (%d)", count);
+ dbs[0] = (struct dbent *)malloc(sizeof(struct dbent));
+ bzero((char *)dbs[0], sizeof(struct dbent));
+ }
+
+ numdbs++;
+ dbs[0]->dbp = dbp;
+ dbs[0]->name = strdup(name);
+ dbs[0]->size = size;
+ return;
+}
+
+/*
+ * Search the list for a database matching 'name.' If we find it,
+ * move it to the head of the list and return its DB handle. If
+ * not, just fail: yp_open_db_cache() will subsequently try to open
+ * the database itself and call yp_add_db() to add it to the
+ * list.
+ *
+ * The search works like this:
+ *
+ * - The caller specifies the name of a database to locate. We try to
+ * find an entry in our list with a matching name.
+ *
+ * - If the caller doesn't specify a key or size, we assume that the
+ * first entry that we encounter with a matching name is returned.
+ * This will result in matches regardless of the pointer index.
+ *
+ * - If the caller also specifies a key and length, we check name
+ * matches to see if their saved key indexes and lengths also match.
+ * This lets us return a DB handle that's already positioned at the
+ * correct location within a database.
+ *
+ * - Once we have a match, it gets migrated to the top of the list
+ * array so that it will be easier to find if another request for
+ * the same database comes in later.
+ */
+static inline DB *yp_find_db(name, key, size)
+ char *name;
+ char *key;
+{
+ register int i, j;
+ register struct dbent *tmp;
+
+ for (i = 0; i < numdbs; i++) {
+ if (dbs[i]->name != NULL && !strcmp(dbs[i]->name, name)) {
+ if (size) {
+ if (size != dbs[i]->size ||
+ strncmp(dbs[i]->key, key, size))
+ continue;
+ } else {
+ if (dbs[i]->size) {
+ continue;
+ }
+ }
+ if (i > 0) {
+ tmp = dbs[i];
+ for (j = i; j > 0; j--)
+ dbs[j] = dbs[j - 1];
+ dbs[0] = tmp;
+ }
+ return(dbs[0]->dbp);
+ }
+ }
+ return(NULL);
+}
+
+/*
+ * Open a DB database and cache the handle for later use. We first
+ * check the cache to see if the required database is already open.
+ * If so, we fetch the handle from the cache. If not, we try to open
+ * the database and save the handle in the cache for later use.
+ */
+DB *yp_open_db_cache(domain, map, key, size)
const char *domain;
const char *map;
+ const char *key;
+ const int size;
{
- DB *dbp;
- char buf[1025];
+ DB *dbp = NULL;
+ char buf[MAXPATHLEN + 2];
+ snprintf(buf, sizeof(buf), "%s/%s", domain, map);
+
+ if ((dbp = yp_find_db((char *)&buf, key, size)) != NULL) {
+ return(dbp);
+ } else {
+ if ((dbp = yp_open_db(domain, map)) != NULL)
+ yp_add_db(dbp, (char *)&buf, size);
+ }
+
+ return (dbp);
+}
+#endif
+
+/*
+ * Open a DB database.
+ */
+DB *yp_open_db(domain, map)
+ const char *domain;
+ const char *map;
+{
+ DB *dbp = NULL;
+ char buf[MAXPATHLEN + 2];
yp_errno = YP_TRUE;
@@ -76,12 +267,32 @@ DB *yp_open_db(domain, map)
return (NULL);
}
+#ifdef DB_CACHE
+ if (yp_validdomain(domain)) {
+ yp_errno = YP_NODOM;
+ return(NULL);
+ }
+#endif
snprintf(buf, sizeof(buf), "%s/%s/%s", yp_dir, domain, map);
- dbp = dbopen(buf,O_RDONLY|O_EXCL, PERM_SECURE, DB_HASH, NULL);
+#ifdef DB_CACHE
+again:
+#endif
+ dbp = dbopen(buf,O_RDONLY, PERM_SECURE, DB_HASH, NULL);
if (dbp == NULL) {
switch(errno) {
+#ifdef DB_CACHE
+ case ENFILE:
+ /*
+ * We ran out of file descriptors. Nuke an
+ * open one and try again.
+ */
+ yp_error("ran out of file descriptors");
+ yp_flush(numdbs - 1);
+ goto again;
+ break;
+#endif
case ENOENT:
yp_errno = YP_NOMAP;
break;
@@ -117,7 +328,7 @@ int yp_get_record(domain,map,key,data,allow)
int allow;
{
DB *dbp;
- int rval;
+ int rval = 0;
if (ypdb_debug)
yp_error("Looking up key [%.*s] in map [%s]",
@@ -131,31 +342,47 @@ int yp_get_record(domain,map,key,data,allow)
if (!allow && !strncmp(key->data, "YP_", 3))
return(YP_NOKEY);
+#ifdef DB_CACHE
+ if ((dbp = yp_open_db_cache(domain, map, NULL, 0)) == NULL) {
+#else
if ((dbp = yp_open_db(domain, map)) == NULL) {
+#endif
return(yp_errno);
}
- if ((rval = (dbp->get)(dbp,key,data,0)) != 0) {
+ if ((rval = (dbp->get)(dbp, key, data, 0)) != 0) {
+#ifdef DB_CACHE
+ dbs[0]->size = 0;
+#else
(void)(dbp->close)(dbp);
+#endif
if (rval == 1)
return(YP_NOKEY);
else
return(YP_BADDB);
}
- (void)(dbp->close)(dbp);
-
if (ypdb_debug)
yp_error("Result of lookup: key: [%.*s] data: [%.*s]",
key->size, key->data, data->size, data->data);
+#ifdef DB_CACHE
+ if (dbs[0]->size) {
+ dbs[0]->key = key->data;
+ dbs[0]->size = key->size;
+ }
+#else
+ (void)(dbp->close)(dbp);
+#endif
+
return(YP_TRUE);
}
-int yp_first_record(dbp,key,data)
+int yp_first_record(dbp,key,data,allow)
const DB *dbp;
DBT *key;
DBT *data;
+ int allow;
{
int rval;
@@ -163,6 +390,9 @@ int yp_first_record(dbp,key,data)
yp_error("Retrieving first key in map.");
if ((rval = (dbp->seq)(dbp,key,data,R_FIRST)) != 0) {
+#ifdef DB_CACHE
+ dbs[0]->size = 0;
+#endif
if (rval == 1)
return(YP_NOKEY);
else
@@ -170,8 +400,11 @@ int yp_first_record(dbp,key,data)
}
/* Avoid passing back magic "YP_*" records. */
- while (!strncmp(key->data, "YP_", 3)) {
+ while (!strncmp(key->data, "YP_", 3) && !allow) {
if ((rval = (dbp->seq)(dbp,key,data,R_NEXT)) != 0) {
+#ifdef DB_CACHE
+ dbs[0]->size = 0;
+#endif
if (rval == 1)
return(YP_NOKEY);
else
@@ -183,20 +416,29 @@ int yp_first_record(dbp,key,data)
yp_error("Result of lookup: key: [%.*s] data: [%.*s]",
key->size, key->data, data->size, data->data);
+#ifdef DB_CACHE
+ if (dbs[0]->size) {
+ dbs[0]->key = key->data;
+ dbs[0]->size = key->size;
+ }
+#endif
+
return(YP_TRUE);
}
-int yp_next_record(dbp,key,data,all)
+int yp_next_record(dbp,key,data,all,allow)
const DB *dbp;
DBT *key;
DBT *data;
int all;
+ int allow;
{
- DBT lkey, ldata;
+ static DBT lkey = { NULL, 0 };
+ static DBT ldata = { NULL, 0 };
int rval;
if (key == NULL || key->data == NULL) {
- rval = yp_first_record(dbp,key,data);
+ rval = yp_first_record(dbp,key,data,allow);
if (rval == YP_NOKEY)
return(YP_NOMORE);
else
@@ -208,29 +450,48 @@ int yp_next_record(dbp,key,data,all)
key->size, key->data);
if (!all) {
- (dbp->seq)(dbp,&lkey,&ldata,R_FIRST);
- while(strncmp((char *)key->data,lkey.data,(int)key->size) ||
- key->size != lkey.size)
- (dbp->seq)(dbp,&lkey,&ldata,R_NEXT);
+#ifndef DB_CACHE
+ if (key->size != lkey.size ||
+ strncmp(key->data, lkey.data, key->size)) {
+#else
+ if (!dbs[0]->size) {
+#endif
+ (dbp->seq)(dbp,&lkey,&ldata,R_FIRST);
+ while(strncmp((char *)key->data,lkey.data,
+ (int)key->size) || key->size != lkey.size)
+ (dbp->seq)(dbp,&lkey,&ldata,R_NEXT);
+ }
}
- if ((dbp->seq)(dbp,&lkey,&ldata,R_NEXT))
+ if ((dbp->seq)(dbp,key,data,R_NEXT)) {
+#ifdef DB_CACHE
+ dbs[0]->size = 0;
+#endif
return(YP_NOMORE);
+ }
/* Avoid passing back magic "YP_*" records. */
- while (!strncmp(lkey.data, "YP_", 3))
- if ((dbp->seq)(dbp,&lkey,&ldata,R_NEXT))
+ while (!strncmp(key->data, "YP_", 3) && !allow)
+ if ((dbp->seq)(dbp,key,data,R_NEXT)) {
+#ifdef DB_CACHE
+ dbs[0]->size = 0;
+#endif
return(YP_NOMORE);
-
- if ((dbp->get)(dbp,&lkey,&ldata,0))
- return(YP_FALSE);
-
- *key = lkey;
- *data = ldata;
+ }
if (ypdb_debug)
yp_error("Result of lookup: key: [%.*s] data: [%.*s]",
key->size, key->data, data->size, data->data);
+#ifdef DB_CACHE
+ if (dbs[0]->size) {
+ dbs[0]->key = key->data;
+ dbs[0]->size = key->size;
+ }
+#else
+ lkey.data = key->data;
+ lkey.size = key->size;
+#endif
+
return(YP_TRUE);
}