Add support for extended hash tables in the PTS database.

This commit is contained in:
Jeffrey Hutzelman 2006-08-03 03:51:24 +00:00 committed by Jeffrey Hutzleman
parent 0c8728f337
commit 5013288de5
8 changed files with 411 additions and 5 deletions

View File

@ -29,6 +29,8 @@ AC_ARG_ENABLE( namei-fileserver,
[ --enable-namei-fileserver force compilation of namei fileserver in preference to inode fileserver],, enable_namei_fileserver="no")
AC_ARG_ENABLE( supergroups,
[ --enable-supergroups enable support for nested pts groups],, enable_supergroups="no")
AC_ARG_ENABLE( prdb-extensions,
[ --enable-prdb-extensions enable support for pts database extensions],, enable_prdb_extensions="no")
AC_ARG_ENABLE( fast-restart,
[ --enable-fast-restart enable fast startup of file server without salvaging],, enable_fast_restart="no")
AC_ARG_ENABLE( bitmap-later,
@ -949,6 +951,10 @@ if test "$enable_supergroups" = "yes"; then
AC_DEFINE(SUPERGROUPS, 1, [define if you want to have support for nested pts groups])
fi
if test "$enable_prdb_extensions" = "yes"; then
AC_DEFINE(PRDB_EXTENSIONS, 1, [define if you want to have pts database extensions])
fi
if test "$enable_fast_restart" = "yes"; then
AC_DEFINE(FAST_RESTART, 1, [define if you want to have fast restart])
fi

View File

@ -87,8 +87,8 @@ ${TOP_INCDIR}/afs/ptserver.h: ptserver.h
#
# Build targets
#
ptserver: ptserver.o ptutils.o ptprocs.o ptint.ss.o ptint.xdr.o utils.o $(LIBS) ${TOP_LIBDIR}/libaudit.a map.o
$(CC) ${CFLAGS} -o ptserver ptserver.o ptutils.o ptprocs.o ptint.ss.o ptint.xdr.o utils.o map.o $(LIBS) ${XLIBS} ${TOP_LIBDIR}/libaudit.a
ptserver: ptserver.o ptutils.o ptprocs.o ptint.ss.o ptint.xdr.o utils.o $(LIBS) ${TOP_LIBDIR}/libaudit.a map.o xht.o
$(CC) ${CFLAGS} -o ptserver ptserver.o ptutils.o ptprocs.o ptint.ss.o ptint.xdr.o utils.o map.o xht.o $(LIBS) ${XLIBS} ${TOP_LIBDIR}/libaudit.a
ptserver.o: ptserver.c ${INCLS} AFS_component_version_number.c
@ -100,6 +100,8 @@ utils.o: utils.c ${INCLS}
map.o: map.c ${INCLS}
xht.o: xht.c ${INCLS}
ptint.ss.o: ptint.ss.c ptint.xdr.c ptint.xg
ptint.cs.o: ptint.cs.c ptint.xdr.c ptint.xg
ptint.xdr.o: ptint.xdr.c ptint.h ptint.xg
@ -177,8 +179,8 @@ testpt: testpt.o libprot.a ${TOP_LIBDIR}/libcmd.a $(LIBS)
testpt.o: testpt.c ${INCLS} ${TOP_INCDIR}/afs/cmd.h AFS_component_version_number.c
pt_util: pt_util.o ptutils.o ubik.o utils.o map.o libprot.a $(LIBS)
$(CC) ${CFLAGS} -o pt_util pt_util.o ptutils.o ubik.o utils.o map.o libprot.a ${TOP_LIBDIR}/libcmd.a $(LIBS) ${XLIBS}
pt_util: pt_util.o ptutils.o ubik.o utils.o map.o xht.o libprot.a $(LIBS)
$(CC) ${CFLAGS} -o pt_util pt_util.o ptutils.o ubik.o utils.o map.o xht.o libprot.a ${TOP_LIBDIR}/libcmd.a $(LIBS) ${XLIBS}
ubik.o: ubik.c ${INCLS}

View File

@ -99,10 +99,12 @@ pr_PrintEntry(FILE *f, int hostOrder, afs_int32 ea, struct prentry *e, int inden
if (e->cellid)
fprintf(f, "cellid == %d\n", host(e->cellid));
#if !(defined(PR_REMEMBER_TIMES) && defined(PRDB_EXTENSIONS))
for (i = 0; i < sizeof(e->reserved) / sizeof(e->reserved[0]); i++)
if (e->reserved[i])
fprintf(f, "reserved field [%d] not zero: %d\n", i,
host(e->reserved[i]));
#endif
fprintf(f, "%*s", indent, "");
fprintf(f, "Entry at %d: flags 0x%x, id %di, next %d.\n", ea,

View File

@ -42,5 +42,14 @@ extern afs_int32 RemoveFromOrphan(struct ubik_trans *at, afs_int32 gid);
extern afs_int32 IsOwnerOf(struct ubik_trans *at, afs_int32 aid, afs_int32 gid);
extern afs_int32 OwnerOf(struct ubik_trans *at, afs_int32 gid);
extern afs_int32 IsAMemberOf(struct ubik_trans *at, afs_int32 aid, afs_int32 gid);
#if defined(PRDB_EXTENSIONS)
extern int pr_XHTInit(void);
extern int pr_WriteXHTEntry(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, struct hashentry *tentry);
extern int pr_ReadXHTEntry(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, struct hashentry *tentry);
extern int pr_LoadXHTs(struct ubik_trans *tt);
extern int pr_CreateXHT(struct ubik_trans *tt, struct pr_xht *table);
extern afs_int32 RemoveFromExtendedHash(struct ubik_trans *tt, struct pr_xht *table, void *aname, int anamelen, afs_int32 *loc);
extern afs_int32 AddToExtendedHash(struct ubik_trans *tt, struct pr_xht *table, void *aname, int anamelen, afs_int32 loc);
#endif
#endif
/* vi:set cin noet sw=4 tw=70: */

View File

@ -429,6 +429,14 @@ main(int argc, char **argv)
OpenLog(AFSDIR_SERVER_PTLOG_FILEPATH); /* set up logging */
SetupLogSignals();
#if defined(PRDB_EXTENSIONS)
code = pr_XHTInit();
if (code) {
com_err(whoami, code, "XHT init failed");
PT_EXIT(1);
}
#endif
prdir = afsconf_Open(AFSDIR_SERVER_ETC_DIRPATH);
if (!prdir) {
fprintf(stderr, "ptserver: can't open configuration directory.\n");
@ -575,3 +583,4 @@ main(int argc, char **argv)
osi_audit(PTS_FinishEvent, -1, AUD_END);
exit(0);
}
/* vi:set cin noet sw=4 tw=70: */

View File

@ -43,7 +43,12 @@ struct prheader {
afs_int32 groupcount; /* num groups in system */
afs_int32 foreigncount; /* num registered foreign users NYI */
afs_int32 instcount; /* number of sub and super users NYI */
#if defined(PRDB_EXTENSIONS)
afs_int32 reserved[4]; /* just in case */
afs_int32 ext_hashtables; /* chain of extended hash tables */
#else
afs_int32 reserved[5]; /* just in case */
#endif
afs_int32 nameHash[HASHSIZE]; /* hash table for names */
afs_int32 idHash[HASHSIZE]; /* hash table for ids */
};
@ -67,13 +72,22 @@ extern struct prheader cheader;
#define PRCELL 8 /* 1 if cell entry */
#define PRFOREIGN 16 /* 1 if foreign user */
#define PRINST 32 /* 1 if sub/super instance */
#define PRHASHTBL 0x100 /* 1 if extended hash table */
#define PRAUTHNAME 0x200 /* 1 if auth name entry */
#if defined(PRDB_EXTENSIONS)
#define PRTYPE 0x33f /* type bits: only one should be set */
#else
#define PRTYPE 0x3f /* type bits: only one should be set */
#endif
#define PRUSER 0 /* all type bits 0 => user entry */
#define PRACCESS (1<<6) /* access checking enabled */
#define PRQUOTA (1<<7) /* group creation quota checking on */
/* extended hash table types */
#define PRTABLE_AUTHNAME 0
/* define the access bits for entries, they are stored in the left half of the
* entry's flags. The SetFields interface takes them in the right half. There
* are eight bits altogether defining access rights for status, owned, member,
@ -102,9 +116,18 @@ struct prentry {
afs_int32 next; /* next block same entry (or freelist) */
#ifdef PR_REMEMBER_TIMES
afs_uint32 createTime, addTime, removeTime, changeTime;
#ifdef PRDB_EXTENSIONS
afs_int32 authnames; /* chain of authentication names for this entry */
#else
afs_int32 reserved[1];
#endif
#else
#ifdef PRDB_EXTENSIONS
afs_int32 reserved[4];
afs_int32 authnames; /* chain of authentication names for this entry */
#else
afs_int32 reserved[5];
#endif
#endif
afs_int32 entries[PRSIZE]; /* groups a user is a member of (or list of members */
afs_int32 nextID; /* id hash table next pointer */
@ -166,6 +189,71 @@ struct contentry { /* continuation of entry */
afs_int32 entries[COSIZE];
};
/* prdb entry containing a portion of an extended hash table */
/* note that 40 buckets would fit, but only 32 are used. */
struct hashentry {
afs_int32 flags; /* random flags */
afs_int32 id; /* unused */
afs_int32 cellid; /* unused */
afs_int32 next; /* next entry this table */
afs_int32 nextTable; /* next table */
afs_int32 tableid; /* table type */
afs_int32 offset; /* first bucket # in this entry */
afs_int32 reserved;
afs_int32 buckets[32];
};
#define ANSIZE 160
struct authentry {
afs_int32 flags; /* random flags */
afs_int32 id; /* id of owning entry */
afs_int32 cellid; /* unused */
afs_int32 next; /* next block for this authname */
afs_int32 nextHash; /* next authname in this bucket */
afs_int32 nextAuthName; /* next authname for this entry */
afs_int32 kind; /* PRAUTHTYPE_* */
afs_int32 length; /* total length of auth data */
unsigned char data[ANSIZE];
};
/* The following are flags for PR_ListEntries() */
#define PRUSERS 0x1
#define PRGROUPS 0x2
#if defined(PRDB_EXTENSIONS)
struct pr_xht {
char *name; /* descriptive name of this table */
afs_int32 tableid; /* table ID in database file */
int nbuckets; /* number of buckets in table */
/* compute the hash bucket number for a key on this table */
afs_int32 (*hash)(void *name, int namelen);
/*
* check whether the entry at a specified location has the
* desired name. Returns 0 on success, error code on failure.
* On success, *next is set to the location of the next entry,
* and *found is set nonzero iff the name matches.
*/
afs_int32 (*ckname)(struct ubik_trans *tt, afs_int32 loc,
void *name, int namelen, afs_int32 *next, int *found);
/*
* Set the next-entry pointer in the entry at the specified location.
* Returns 0 on success, error code on failure.
*/
afs_int32 (*setnxt)(struct ubik_trans *tt, afs_int32 loc, afs_int32 next);
int flags; /* random flags */
int nparts; /* number of entries containing table */
afs_int32 *partids; /* array of entry locations */
struct hashentry *parts; /* array of parts */
};
#define XHT_INITED 1 /* hashtable has been inited */
#endif
/* vi:set cin noet sw=4 tw=70: */

View File

@ -1705,6 +1705,24 @@ read_DbHeader(struct ubik_trans *tt)
int pr_noAuth;
afs_int32 initd = 0;
#if defined(PRDB_EXTENSIONS)
afs_int32
InitDBExtensions(struct ubik_trans *tt)
{
afs_int32 code, entry;
struct hashentry hent;
code = pr_LoadXHTs(tt);
if (code)
return code;
code = ubik_EndTrans(tt);
if (code)
return code;
return PRSUCCESS;
}
#endif
afs_int32
Initdb()
{
@ -1744,10 +1762,14 @@ Initdb()
&& ntohl(cheader.eofPtr) != (afs_uint32) NULL
&& FindByID(tt, ANONYMOUSID) != 0) {
/* database exists, so we don't have to build it */
#if defined(PRDB_EXTENSIONS)
return InitDBExtensions(tt);
#else
code = ubik_EndTrans(tt);
if (code)
return code;
return PRSUCCESS;
#endif
}
/* else we need to build a database */
code = ubik_EndTrans(tt);
@ -1794,10 +1816,14 @@ Initdb()
&& ntohl(cheader.eofPtr) != (afs_uint32) NULL
&& FindByID(tt, ANONYMOUSID) != 0) {
/* database exists, so we don't have to build it */
#if defined(PRDB_EXTENSIONS)
return InitDBExtensions(tt);
#else
code = ubik_EndTrans(tt);
if (code)
return code;
return PRSUCCESS;
#endif
}
/* Initialize the database header */
@ -1837,10 +1863,14 @@ Initdb()
return code;
}
#if defined(PRDB_EXTENSIONS)
return InitDBExtensions(tt);
#else
code = ubik_EndTrans(tt);
if (code)
return code;
return PRSUCCESS;
#endif
}
afs_int32
@ -2187,3 +2217,4 @@ AddAuthGroup(struct prentry *tentry, prlist *alist, afs_int32 *size)
else
return PRSUCCESS;
}
/* vi:set cin noet sw=4 tw=70: */

259
src/ptserver/xht.c Normal file
View File

@ -0,0 +1,259 @@
/*
* Copyright 2000, International Business Machines Corporation and others.
* All Rights Reserved.
*
* This software has been released under the terms of the IBM Public
* License. For details, see the LICENSE file in the top-level source
* directory or online at http://www.openafs.org/dl/license10.html
*/
#include <afsconfig.h>
#include <afs/param.h>
RCSID
("$Header$");
#include <sys/types.h>
#include <lock.h>
#include <ubik.h>
#include <stdio.h>
#ifdef AFS_NT40_ENV
#include <winsock2.h>
#else
#include <netinet/in.h>
#include <netdb.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#else
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#endif
#include "ptserver.h"
#include "pterror.h"
#if defined(PRDB_EXTENSIONS)
struct pr_xht xtables[] = {
{ "authname", HASHSIZE, 0/*hash*/, 0/*ckname*/, 0/*setnxt*/ }
};
#define NTABLES (sizeof(xtables) / sizeof(xtables[0]))
int
pr_XHTInit(void) {
int i;
for (i = 0; i < NTABLES; i++) {
xtables[i].nparts = (xtables[i].nbuckets + 1) / 32;
xtables[i].partids = malloc(xtables[i].nparts * sizeof(afs_int32));
xtables[i].parts = malloc(xtables[i].nparts * sizeof(struct hashentry));
if (!xtables[i].partids || !xtables[i].parts)
return PRNOMEM;
memset(xtables[i].partids, 0, xtables[i].nparts * sizeof(afs_int32));
memset(xtables[i].parts, 0, xtables[i].nparts * sizeof(struct hashentry));
}
return PRSUCCESS;
}
int
pr_WriteXHTEntry(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, struct hashentry *tentry)
{
afs_int32 code;
register afs_int32 i;
struct hashentry nentry;
if (ntohl(1) != 1) { /* No need to swap */
memset(&nentry, 0, sizeof(nentry)); /* make reseved fields zero */
nentry.flags = htonl(tentry->flags);
nentry.id = htonl(tentry->id);
nentry.cellid = htonl(tentry->cellid);
nentry.next = htonl(tentry->next);
nentry.nextTable = htonl(tentry->nextTable);
nentry.tableid = htonl(tentry->tableid);
nentry.offset = htonl(tentry->offset);
for (i = 0; i < 32; i++)
nentry.buckets[i] = htonl(tentry->buckets[i]);
tentry = &nentry;
}
code = pr_Write(tt, afd, pos, (char *)tentry, sizeof(struct hashentry));
return (code);
}
int
pr_ReadXHTEntry(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, struct hashentry *tentry)
{
afs_int32 code;
register afs_int32 i;
struct hashentry nentry;
code = ubik_Seek(tt, afd, pos);
if (code)
return (code);
if (ntohl(1) == 1) { /* No swapping needed. */
code = ubik_Read(tt, (char *)tentry, sizeof(struct hashentry));
return (code);
}
code = ubik_Read(tt, (char *)&nentry, sizeof(struct hashentry));
if (code)
return (code);
memset(tentry, 0, sizeof(*tentry)); /* make reseved fields zero */
tentry->flags = ntohl(nentry.flags);
tentry->id = ntohl(nentry.id);
tentry->cellid = ntohl(nentry.cellid);
tentry->next = ntohl(nentry.next);
tentry->nextTable = ntohl(nentry.nextTable);
tentry->tableid = ntohl(nentry.tableid);
tentry->offset = ntohl(nentry.offset);
for (i = 0; i < 32; i++)
tentry->buckets[i] = ntohl(nentry.buckets[i]);
return (code);
}
int
pr_LoadXHTs(struct ubik_trans *tt)
{
int tbl, i;
afs_int32 code, loc, next_table;
struct hashentry tentry;
for (loc = ntohl(cheader.ext_hashtables); loc; loc = next_table) {
code = pr_ReadXHTEntry(tt, 0, loc, &tentry);
if (code)
return PRDBFAIL;
if ((tentry.flags & PRTYPE) != PRHASHTBL)
return PRINCONSISTENT;
next_table = tentry.nextTable;
tbl = tentry.tableid;
if (tbl < 0 || tbl >= NTABLES)
continue;
for (i = 0; i < xtables[tbl].nparts; i++) {
xtables[tbl].partids[i] = loc;
if (i) {
code = pr_ReadXHTEntry(tt, 0, loc, &xtables[tbl].parts[i]);
if (code)
return PRDBFAIL;
} else {
memcpy(&xtables[tbl].parts[i], &tentry, sizeof(tentry));
}
if (((xtables[tbl].parts[i].flags & PRTYPE) != PRHASHTBL) ||
(xtables[tbl].parts[i].tableid != tbl) ||
xtables[tbl].parts[i].offset != i >> 5) {
return PRINCONSISTENT;
}
loc = xtables[tbl].parts[i].next;
}
}
return PRSUCCESS;
}
int
pr_CreateXHT(struct ubik_trans *tt, struct pr_xht *table)
{
afs_int32 code, next;
int i;
if ((table->flags & XHT_INITED))
return PRSUCCESS;
next = 0;
for (i = table->nparts; i--;) {
memset(&table->parts[i], 0, sizeof(struct hashentry));
table->parts[i].flags = PRHASHTBL;
table->parts[i].next = next;
table->parts[i].nextTable = i ? 0 : ntohl(cheader.ext_hashtables);
table->parts[i].tableid = table - xtables;
table->parts[i].offset = i >> 5;
table->partids[i] = next = AllocBlock(tt);
if (!next)
return PRDBFAIL;
code = pr_WriteXHTEntry(tt, 0, next, &table->parts[i]);
if (code)
return PRDBFAIL;
}
cheader.ext_hashtables = htonl(next);
code = pr_Write(tt, 0, 68, (char *)&cheader.ext_hashtables,
sizeof(cheader.ext_hashtables));
if (code)
return PRDBFAIL;
table->flags |= XHT_INITED;
return PRSUCCESS;
}
/* Remove an entry from an extended hash table. */
afs_int32
RemoveFromExtendedHash(struct ubik_trans *tt, struct pr_xht *table,
void *aname, int anamelen, afs_int32 *loc)
{
afs_int32 code, current, next, trail, i, part, bucket;
int found;
if (!(table->flags & XHT_INITED))
return PRSUCCESS;
i = (table->hash)(aname, anamelen);
if (i < 0 || i >= table->nbuckets)
return PRINCONSISTENT;
part = i >> 5;
bucket = i & 0x1f;
current = table->parts[part].buckets[bucket];
trail = 0;
for (;;) {
if (current == 0)
return PRSUCCESS; /* already gone */
code = (table->ckname)(tt, current, aname, anamelen, &next, &found);
if (code)
return PRDBFAIL;
if (found) break;
trail = current;
current = next;
}
if (trail == 0) {
next = htonl(next);
code = pr_Write(tt, 0, table->partids[part] + 32 + 4*bucket,
(char *)&next, sizeof(next));
if (code)
return PRDBFAIL;
} else {
code = (table->setnxt)(tt, trail, next);
if (code)
return PRDBFAIL;
}
*loc = current;
return PRSUCCESS;
}
afs_int32
AddToExtendedHash(struct ubik_trans *tt, struct pr_xht *table,
void *aname, int anamelen, afs_int32 loc)
{
afs_int32 code, i, part, bucket, next;
if (!(table->flags & XHT_INITED)) {
code = pr_CreateXHT(tt, table);
if (code)
return PRDBFAIL;
}
i = (table->hash)(aname, anamelen);
if (i < 0 || i >= table->nbuckets)
return PRINCONSISTENT;
part = i >> 5;
bucket = i & 0x1f;
code = (table->setnxt)(tt, loc, table->parts[part].buckets[bucket]);
if (code)
return PRDBFAIL;
table->parts[part].buckets[bucket] = loc;
next = htonl(loc);
code = pr_Write(tt, 0, table->partids[part] + 32 + 4*bucket,
(char *)&next, sizeof(next));
if (code)
return PRDBFAIL;
return PRSUCCESS;
}
#endif
/* vi:set cin noet sw=4 tw=70: */