diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 4cae914cf41fb0c8c76087805a77f5deb1e2e484..8bd55026d42e76fa34f0fa52609741c85987598a 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Header: /cvsroot/pgsql/src/backend/access/transam/xlogutils.c,v 1.18 2001/08/25 18:52:41 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/transam/xlogutils.c,v 1.19 2001/10/01 05:36:13 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -228,9 +228,9 @@ _xl_init_rel_cache(void)
 	_xlrelarr[0].moreRecently = &(_xlrelarr[0]);
 	_xlrelarr[0].lessRecently = &(_xlrelarr[0]);
 
-	memset(&ctl, 0, (int) sizeof(ctl));
+	memset(&ctl, 0, sizeof(ctl));
 	ctl.keysize = sizeof(RelFileNode);
-	ctl.datasize = sizeof(XLogRelDesc *);
+	ctl.entrysize = sizeof(XLogRelCacheEntry);
 	ctl.hash = tag_hash;
 
 	_xlrelcache = hash_create(_XLOG_RELCACHESIZE, &ctl,
@@ -249,7 +249,7 @@ _xl_remove_hash_entry(XLogRelDesc **edata, Datum dummy)
 	rdesc->moreRecently->lessRecently = rdesc->lessRecently;
 
 	hentry = (XLogRelCacheEntry *) hash_search(_xlrelcache,
-				(char *) &(rdesc->reldata.rd_node), HASH_REMOVE, &found);
+				(void *) &(rdesc->reldata.rd_node), HASH_REMOVE, &found);
 
 	if (hentry == NULL)
 		elog(STOP, "_xl_remove_hash_entry: can't delete from cache");
@@ -321,7 +321,7 @@ XLogOpenRelation(bool redo, RmgrId rmid, RelFileNode rnode)
 	bool		found;
 
 	hentry = (XLogRelCacheEntry *)
-		hash_search(_xlrelcache, (char *) &rnode, HASH_FIND, &found);
+		hash_search(_xlrelcache, (void *) &rnode, HASH_FIND, &found);
 
 	if (hentry == NULL)
 		elog(STOP, "XLogOpenRelation: error in cache");
@@ -345,7 +345,7 @@ XLogOpenRelation(bool redo, RmgrId rmid, RelFileNode rnode)
 		res->reldata.rd_node = rnode;
 
 		hentry = (XLogRelCacheEntry *)
-			hash_search(_xlrelcache, (char *) &rnode, HASH_ENTER, &found);
+			hash_search(_xlrelcache, (void *) &rnode, HASH_ENTER, &found);
 
 		if (hentry == NULL)
 			elog(STOP, "XLogOpenRelation: can't insert into cache");
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index 298e3470d9680c1c3ea137d8c2cf779a7b3a8fc5..6c8ed373a873053705e31c51f9fe85690c4f5984 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -16,7 +16,7 @@
  *
  *	Copyright (c) 2001, PostgreSQL Global Development Group
  *
- *	$Header: /cvsroot/pgsql/src/backend/postmaster/pgstat.c,v 1.7 2001/08/23 23:06:37 tgl Exp $
+ *	$Header: /cvsroot/pgsql/src/backend/postmaster/pgstat.c,v 1.8 2001/10/01 05:36:13 tgl Exp $
  * ----------
  */
 #include "postgres.h"
@@ -511,7 +511,8 @@ pgstat_vacuum_tabstat(void)
 	 * Lookup our own database entry
 	 */
 	dbentry = (PgStat_StatDBEntry *)hash_search(pgStatDBHash,
-					(char *)&MyDatabaseId, HASH_FIND, &found);
+												(void *) &MyDatabaseId,
+												HASH_FIND, &found);
 	if (!found || dbentry == NULL)
 		return -1;
 
@@ -926,8 +927,9 @@ pgstat_fetch_stat_dbentry(Oid dbid)
 	/*
 	 * Lookup the requested database
 	 */
-	dbentry = (PgStat_StatDBEntry *)hash_search(pgStatDBHash,
-					(char *)&dbid, HASH_FIND, &found);
+	dbentry = (PgStat_StatDBEntry *) hash_search(pgStatDBHash,
+												 (void *) &dbid,
+												 HASH_FIND, &found);
 	if (!found || dbentry == NULL)
 		return NULL;
 
@@ -966,8 +968,9 @@ pgstat_fetch_stat_tabentry(Oid relid)
 	/*
 	 * Lookup our database.
 	 */
-	dbentry = (PgStat_StatDBEntry *)hash_search(pgStatDBHash,
-					(char *)&MyDatabaseId, HASH_FIND, &found);
+	dbentry = (PgStat_StatDBEntry *) hash_search(pgStatDBHash,
+												 (void *) &MyDatabaseId,
+												 HASH_FIND, &found);
 	if (!found || dbentry == NULL)
 		return NULL;
 
@@ -976,8 +979,9 @@ pgstat_fetch_stat_tabentry(Oid relid)
 	 */
 	if (dbentry->tables == NULL)
 		return NULL;
-	tabentry = (PgStat_StatTabEntry *)hash_search(dbentry->tables,
-					(char *)&relid, HASH_FIND, &found);
+	tabentry = (PgStat_StatTabEntry *) hash_search(dbentry->tables,
+												   (void *) &relid,
+												   HASH_FIND, &found);
 	if (!found || tabentry == NULL)
 		return NULL;
 
@@ -1197,9 +1201,9 @@ pgstat_main(int real_argc, char *real_argv[])
 	 * Create the dead backend hashtable
 	 */
 	memset(&hash_ctl, 0, sizeof(hash_ctl));
-	hash_ctl.keysize  = sizeof(int);
-	hash_ctl.datasize = sizeof(PgStat_StatBeDead);
-	hash_ctl.hash     = tag_hash;
+	hash_ctl.keysize   = sizeof(int);
+	hash_ctl.entrysize = sizeof(PgStat_StatBeDead);
+	hash_ctl.hash      = tag_hash;
 	pgStatBeDead = hash_create(PGSTAT_BE_HASH_SIZE, &hash_ctl, 
 							HASH_ELEM | HASH_FUNCTION);
 	if (pgStatBeDead == NULL)
@@ -1720,8 +1724,9 @@ pgstat_add_backend(PgStat_MsgHdr *msg)
 	 *
 	 * If the backend is known to be dead, we ignore this add.
 	 */
-	deadbe = (PgStat_StatBeDead *)hash_search(pgStatBeDead,
-						(char *)&(msg->m_procpid), HASH_FIND, &found);
+	deadbe = (PgStat_StatBeDead *) hash_search(pgStatBeDead,
+											   (void *) &(msg->m_procpid),
+											   HASH_FIND, &found);
 	if (deadbe == NULL)
 	{
 		fprintf(stderr, "PGSTAT: Dead backend table corrupted - abort\n");
@@ -1747,9 +1752,9 @@ pgstat_add_backend(PgStat_MsgHdr *msg)
 	/*
 	 * Lookup or create the database entry for this backends DB.
 	 */
-	dbentry = (PgStat_StatDBEntry *)hash_search(pgStatDBHash,
-					(char *)&(msg->m_databaseid), HASH_ENTER,
-					&found);
+	dbentry = (PgStat_StatDBEntry *) hash_search(pgStatDBHash,
+												 (void *) &(msg->m_databaseid),
+												 HASH_ENTER, &found);
     if (dbentry == NULL)
 	{
 		fprintf(stderr, "PGSTAT: DB hash table corrupted - abort\n");
@@ -1772,9 +1777,9 @@ pgstat_add_backend(PgStat_MsgHdr *msg)
 		dbentry->destroy			= 0;
 
 		memset(&hash_ctl, 0, sizeof(hash_ctl));
-		hash_ctl.keysize  = sizeof(Oid);
-		hash_ctl.datasize = sizeof(PgStat_StatTabEntry);
-		hash_ctl.hash     = tag_hash;
+		hash_ctl.keysize   = sizeof(Oid);
+		hash_ctl.entrysize = sizeof(PgStat_StatTabEntry);
+		hash_ctl.hash      = tag_hash;
 		dbentry->tables = hash_create(PGSTAT_TAB_HASH_SIZE, &hash_ctl,
 							HASH_ELEM | HASH_FUNCTION);
 		if (dbentry->tables == NULL)
@@ -1827,8 +1832,9 @@ pgstat_sub_backend(int procpid)
 			 * the counting of backends, not the table access stats they
 			 * sent).
 			 */
-			deadbe = (PgStat_StatBeDead *)hash_search(pgStatBeDead,
-							(char *)&procpid, HASH_ENTER, &found);
+			deadbe = (PgStat_StatBeDead *) hash_search(pgStatBeDead,
+													   (void *) &procpid,
+													   HASH_ENTER, &found);
 			if (deadbe == NULL)
 			{
 				fprintf(stderr, "PGSTAT: dead backend hash table corrupted "
@@ -1914,8 +1920,8 @@ pgstat_write_statsfile(void)
 					hash_destroy(dbentry->tables);
 
 				hentry = hash_search(pgStatDBHash, 
-								(char *)&(dbentry->databaseid),
-								HASH_REMOVE, &found);
+									 (void *) &(dbentry->databaseid),
+									 HASH_REMOVE, &found);
 				if (hentry == NULL)
 				{
 					fprintf(stderr, "PGSTAT: database hash table corrupted "
@@ -1959,7 +1965,7 @@ pgstat_write_statsfile(void)
 				if (--(tabentry->destroy) == 0)
 				{
 					hentry = hash_search(dbentry->tables,
-									(char *)&(tabentry->tableid),
+									(void *) &(tabentry->tableid),
 									HASH_REMOVE, &found);
 					if (hentry == NULL)
 					{
@@ -2047,7 +2053,8 @@ pgstat_write_statsfile(void)
 		 */
 		if (--(deadbe->destroy) <= 0)
 		{
-			hentry = hash_search(pgStatBeDead, (char *)&(deadbe->procpid),
+			hentry = hash_search(pgStatBeDead,
+								 (void *) &(deadbe->procpid),
 							HASH_REMOVE, &found);
 			if (hentry == NULL)
 			{
@@ -2107,10 +2114,10 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb,
 	 * Create the DB hashtable
 	 */
 	memset(&hash_ctl, 0, sizeof(hash_ctl));
-	hash_ctl.keysize  = sizeof(Oid);
-	hash_ctl.datasize = sizeof(PgStat_StatDBEntry);
-	hash_ctl.hash     = tag_hash;
-	hash_ctl.hcxt     = use_mcxt;
+	hash_ctl.keysize   = sizeof(Oid);
+	hash_ctl.entrysize = sizeof(PgStat_StatDBEntry);
+	hash_ctl.hash      = tag_hash;
+	hash_ctl.hcxt      = use_mcxt;
 	*dbhash = hash_create(PGSTAT_DB_HASH_SIZE, &hash_ctl, 
 							HASH_ELEM | HASH_FUNCTION | mcxt_flags);
 	if (pgStatDBHash == NULL)
@@ -2175,8 +2182,8 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb,
 				/*
 				 * Add to the DB hash
 				 */
-				dbentry = (PgStat_StatDBEntry *)hash_search(*dbhash,
-								(char *)&dbbuf.databaseid,
+				dbentry = (PgStat_StatDBEntry *) hash_search(*dbhash,
+								(void *) &dbbuf.databaseid,
 								HASH_ENTER, &found);
 				if (dbentry == NULL)
 				{
@@ -2222,10 +2229,10 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb,
 
 
 				memset(&hash_ctl, 0, sizeof(hash_ctl));
-				hash_ctl.keysize  = sizeof(Oid);
-				hash_ctl.datasize = sizeof(PgStat_StatTabEntry);
-				hash_ctl.hash     = tag_hash;
-				hash_ctl.hcxt     = use_mcxt;
+				hash_ctl.keysize   = sizeof(Oid);
+				hash_ctl.entrysize = sizeof(PgStat_StatTabEntry);
+				hash_ctl.hash      = tag_hash;
+				hash_ctl.hcxt      = use_mcxt;
 				dbentry->tables = hash_create(PGSTAT_TAB_HASH_SIZE, &hash_ctl,
 									HASH_ELEM | HASH_FUNCTION | mcxt_flags);
 				if (dbentry->tables == NULL)
@@ -2286,8 +2293,8 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb,
 				if (tabhash == NULL)
 					break;
 
-				tabentry = (PgStat_StatTabEntry *)hash_search(tabhash,
-								(char *)&tabbuf.tableid,
+				tabentry = (PgStat_StatTabEntry *) hash_search(tabhash,
+								(void *) &tabbuf.tableid,
 								HASH_ENTER, &found);
 				if (tabentry == NULL)
 				{
@@ -2411,7 +2418,7 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb,
 				 * Count backends per database here.
 				 */
 				dbentry = (PgStat_StatDBEntry *)hash_search(*dbhash,
-								(char *)&((*betab)[havebackends].databaseid),
+								(void *) &((*betab)[havebackends].databaseid),
 								HASH_FIND, &found);
 				if (found)
 					dbentry->n_backends++;
@@ -2525,8 +2532,8 @@ pgstat_recv_tabstat(PgStat_MsgTabstat *msg, int len)
 	/*
 	 * Lookup the database in the hashtable.
 	 */
-	dbentry = (PgStat_StatDBEntry *)hash_search(pgStatDBHash,
-							(char *)&(msg->m_hdr.m_databaseid),
+	dbentry = (PgStat_StatDBEntry *) hash_search(pgStatDBHash,
+							(void *) &(msg->m_hdr.m_databaseid),
 							HASH_FIND, &found);
 	if (dbentry == NULL)
 	{
@@ -2551,8 +2558,8 @@ pgstat_recv_tabstat(PgStat_MsgTabstat *msg, int len)
 	 */
 	for (i = 0; i < msg->m_nentries; i++)
 	{
-		tabentry = (PgStat_StatTabEntry *)hash_search(dbentry->tables,
-						(char *)&(tabmsg[i].t_id), 
+		tabentry = (PgStat_StatTabEntry *) hash_search(dbentry->tables,
+						(void *) &(tabmsg[i].t_id), 
 						HASH_ENTER, &found);
 		if (tabentry == NULL)
 		{
@@ -2625,8 +2632,8 @@ pgstat_recv_tabpurge(PgStat_MsgTabpurge *msg, int len)
 	/*
 	 * Lookup the database in the hashtable.
 	 */
-	dbentry = (PgStat_StatDBEntry *)hash_search(pgStatDBHash,
-							(char *)&(msg->m_hdr.m_databaseid),
+	dbentry = (PgStat_StatDBEntry *) hash_search(pgStatDBHash,
+							(void *) &(msg->m_hdr.m_databaseid),
 							HASH_FIND, &found);
 	if (dbentry == NULL)
 	{
@@ -2648,8 +2655,8 @@ pgstat_recv_tabpurge(PgStat_MsgTabpurge *msg, int len)
 	 */
 	for (i = 0; i < msg->m_nentries; i++)
 	{
-		tabentry = (PgStat_StatTabEntry *)hash_search(dbentry->tables,
-						(char *)&(msg->m_tableid[i]), 
+		tabentry = (PgStat_StatTabEntry *) hash_search(dbentry->tables,
+						(void *) &(msg->m_tableid[i]), 
 						HASH_FIND, &found);
 		if (tabentry == NULL)
 		{
@@ -2685,8 +2692,8 @@ pgstat_recv_dropdb(PgStat_MsgDropdb *msg, int len)
 	/*
 	 * Lookup the database in the hashtable.
 	 */
-	dbentry = (PgStat_StatDBEntry *)hash_search(pgStatDBHash,
-							(char *)&(msg->m_databaseid),
+	dbentry = (PgStat_StatDBEntry *) hash_search(pgStatDBHash,
+							(void *) &(msg->m_databaseid),
 							HASH_FIND, &found);
 	if (dbentry == NULL)
 	{
@@ -2725,8 +2732,8 @@ pgstat_recv_resetcounter(PgStat_MsgResetcounter *msg, int len)
 	/*
 	 * Lookup the database in the hashtable.
 	 */
-	dbentry = (PgStat_StatDBEntry *)hash_search(pgStatDBHash,
-							(char *)&(msg->m_hdr.m_databaseid),
+	dbentry = (PgStat_StatDBEntry *) hash_search(pgStatDBHash,
+							(void *) &(msg->m_hdr.m_databaseid),
 							HASH_FIND, &found);
 	if (dbentry == NULL)
 	{
@@ -2753,7 +2760,7 @@ pgstat_recv_resetcounter(PgStat_MsgResetcounter *msg, int len)
 
 	memset(&hash_ctl, 0, sizeof(hash_ctl));
 	hash_ctl.keysize  = sizeof(Oid);
-	hash_ctl.datasize = sizeof(PgStat_StatTabEntry);
+	hash_ctl.entrysize = sizeof(PgStat_StatTabEntry);
 	hash_ctl.hash     = tag_hash;
 	dbentry->tables = hash_create(PGSTAT_TAB_HASH_SIZE, &hash_ctl,
 						HASH_ELEM | HASH_FUNCTION);
diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c
index 45a2e4aa160a85efe37432cb8477c1c59f0629b1..322c45b03194528cc0f8d1c21e7cbbb9c4987640 100644
--- a/src/backend/storage/buffer/buf_init.c
+++ b/src/backend/storage/buffer/buf_init.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.44 2001/09/29 04:02:22 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.45 2001/10/01 05:36:13 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -280,9 +280,7 @@ BufferShmemSize(void)
 	int			size = 0;
 
 	/* size of shmem index hash table */
-	size += hash_estimate_size(SHMEM_INDEX_SIZE,
-							   SHMEM_INDEX_KEYSIZE,
-							   SHMEM_INDEX_DATASIZE);
+	size += hash_estimate_size(SHMEM_INDEX_SIZE, sizeof(ShmemIndexEnt));
 
 	/* size of buffer descriptors */
 	size += MAXALIGN((NBuffers + 1) * sizeof(BufferDesc));
@@ -291,9 +289,7 @@ BufferShmemSize(void)
 	size += NBuffers * MAXALIGN(BLCKSZ);
 
 	/* size of buffer hash table */
-	size += hash_estimate_size(NBuffers,
-							   sizeof(BufferTag),
-							   sizeof(Buffer));
+	size += hash_estimate_size(NBuffers, sizeof(BufferLookupEnt));
 
 #ifdef BMTRACE
 	size += (BMT_LIMIT * sizeof(bmtrace)) + sizeof(long);
diff --git a/src/backend/storage/buffer/buf_table.c b/src/backend/storage/buffer/buf_table.c
index 671b13efa0f036193d1068e82190208a00e3dd10..85b747b442f8f08bb5acbb9bc366a37e40e392b3 100644
--- a/src/backend/storage/buffer/buf_table.c
+++ b/src/backend/storage/buffer/buf_table.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_table.c,v 1.22 2001/09/29 04:02:22 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_table.c,v 1.23 2001/10/01 05:36:13 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -33,54 +33,42 @@
 
 static HTAB *SharedBufHash;
 
-typedef struct lookup
-{
-	BufferTag	key;
-	Buffer		id;
-} LookupEnt;
 
 /*
  * Initialize shmem hash table for mapping buffers
  */
 void
-InitBufTable()
+InitBufTable(void)
 {
 	HASHCTL		info;
-	int			hash_flags;
 
 	/* assume lock is held */
 
 	/* BufferTag maps to Buffer */
 	info.keysize = sizeof(BufferTag);
-	info.datasize = sizeof(Buffer);
+	info.entrysize = sizeof(BufferLookupEnt);
 	info.hash = tag_hash;
 
-	hash_flags = (HASH_ELEM | HASH_FUNCTION);
-
-
-	SharedBufHash = (HTAB *) ShmemInitHash("Shared Buffer Lookup Table",
-										   NBuffers, NBuffers,
-										   &info, hash_flags);
+	SharedBufHash = ShmemInitHash("Shared Buffer Lookup Table",
+								  NBuffers, NBuffers,
+								  &info,
+								  HASH_ELEM | HASH_FUNCTION);
 
 	if (!SharedBufHash)
-	{
 		elog(FATAL, "couldn't initialize shared buffer pool Hash Tbl");
-		exit(1);
-	}
-
 }
 
 BufferDesc *
 BufTableLookup(BufferTag *tagPtr)
 {
-	LookupEnt  *result;
+	BufferLookupEnt  *result;
 	bool		found;
 
 	if (tagPtr->blockNum == P_NEW)
 		return NULL;
 
-	result = (LookupEnt *)
-		hash_search(SharedBufHash, (char *) tagPtr, HASH_FIND, &found);
+	result = (BufferLookupEnt *)
+		hash_search(SharedBufHash, (void *) tagPtr, HASH_FIND, &found);
 
 	if (!result)
 	{
@@ -98,7 +86,7 @@ BufTableLookup(BufferTag *tagPtr)
 bool
 BufTableDelete(BufferDesc *buf)
 {
-	LookupEnt  *result;
+	BufferLookupEnt  *result;
 	bool		found;
 
 	/*
@@ -110,8 +98,8 @@ BufTableDelete(BufferDesc *buf)
 
 	buf->flags |= BM_DELETED;
 
-	result = (LookupEnt *)
-		hash_search(SharedBufHash, (char *) &(buf->tag), HASH_REMOVE, &found);
+	result = (BufferLookupEnt *)
+		hash_search(SharedBufHash, (void *) &(buf->tag), HASH_REMOVE, &found);
 
 	if (!(result && found))
 	{
@@ -134,15 +122,15 @@ BufTableDelete(BufferDesc *buf)
 bool
 BufTableInsert(BufferDesc *buf)
 {
-	LookupEnt  *result;
+	BufferLookupEnt  *result;
 	bool		found;
 
 	/* cannot insert it twice */
 	Assert(buf->flags & BM_DELETED);
 	buf->flags &= ~(BM_DELETED);
 
-	result = (LookupEnt *)
-		hash_search(SharedBufHash, (char *) &(buf->tag), HASH_ENTER, &found);
+	result = (BufferLookupEnt *)
+		hash_search(SharedBufHash, (void *) &(buf->tag), HASH_ENTER, &found);
 
 	if (!result)
 	{
diff --git a/src/backend/storage/freespace/freespace.c b/src/backend/storage/freespace/freespace.c
index b20e8086157eb063cf0dced844c8de0b0f37d022..f8fefee8a09d97f6d1169984c02847e4ffa4d19e 100644
--- a/src/backend/storage/freespace/freespace.c
+++ b/src/backend/storage/freespace/freespace.c
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/freespace/freespace.c,v 1.5 2001/09/29 04:02:23 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/freespace/freespace.c,v 1.6 2001/10/01 05:36:14 tgl Exp $
  *
  *
  * NOTES:
@@ -100,9 +100,6 @@ struct FSMRelation
 	FSMChunk   *relChunks;		/* linked list of page info chunks */
 };
 
-#define SHMEM_FSMHASH_KEYSIZE  sizeof(RelFileNode)
-#define SHMEM_FSMHASH_DATASIZE (sizeof(FSMRelation) - SHMEM_FSMHASH_KEYSIZE)
-
 /*
  * Info about individual pages in a relation is stored in chunks to reduce
  * allocation overhead.  Note that we allow any chunk of a relation's list
@@ -180,8 +177,8 @@ InitFreeSpaceMap(void)
 	MemSet(FreeSpaceMap, 0, sizeof(FSMHeader));
 
 	/* Create hashtable for FSMRelations */
-	info.keysize = SHMEM_FSMHASH_KEYSIZE;
-	info.datasize = SHMEM_FSMHASH_DATASIZE;
+	info.keysize = sizeof(RelFileNode);
+	info.entrysize = sizeof(FSMRelation);
 	info.hash = tag_hash;
 
 	FreeSpaceMap->relHash = ShmemInitHash("Free Space Map Hash",
@@ -224,9 +221,7 @@ FreeSpaceShmemSize(void)
 	size = MAXALIGN(sizeof(FSMHeader));
 
 	/* hash table, including the FSMRelation objects */
-	size += hash_estimate_size(MaxFSMRelations,
-							   SHMEM_FSMHASH_KEYSIZE,
-							   SHMEM_FSMHASH_DATASIZE);
+	size += hash_estimate_size(MaxFSMRelations, sizeof(FSMRelation));
 
 	/* FSMChunk objects */
 	nchunks = (MaxFSMPages - 1) / CHUNKPAGES + 1;
@@ -498,7 +493,7 @@ lookup_fsm_rel(RelFileNode *rel)
 	bool		found;
 
 	fsmrel = (FSMRelation *) hash_search(FreeSpaceMap->relHash,
-										 (Pointer) rel,
+										 (void *) rel,
 										 HASH_FIND,
 										 &found);
 	if (!fsmrel)
@@ -524,7 +519,7 @@ create_fsm_rel(RelFileNode *rel)
 	bool		found;
 
 	fsmrel = (FSMRelation *) hash_search(FreeSpaceMap->relHash,
-										 (Pointer) rel,
+										 (void *) rel,
 										 HASH_ENTER,
 										 &found);
 	if (!fsmrel)
@@ -595,7 +590,7 @@ delete_fsm_rel(FSMRelation *fsmrel)
 	unlink_fsm_rel(fsmrel);
 	FreeSpaceMap->numRels--;
 	result = (FSMRelation *) hash_search(FreeSpaceMap->relHash,
-										 (Pointer) &(fsmrel->key),
+										 (void *) &(fsmrel->key),
 										 HASH_REMOVE,
 										 &found);
 	if (!result || !found)
diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c
index 0ad168680a193bd7bc5068763731d242455f7e60..024db5bd5334dbfe41f1df79f0161f0577d2117f 100644
--- a/src/backend/storage/ipc/shmem.c
+++ b/src/backend/storage/ipc/shmem.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/ipc/shmem.c,v 1.59 2001/09/29 04:02:23 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/ipc/shmem.c,v 1.60 2001/10/01 05:36:14 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -191,7 +191,7 @@ InitShmemIndex(void)
 
 	/* create the shared memory shmem index */
 	info.keysize = SHMEM_INDEX_KEYSIZE;
-	info.datasize = SHMEM_INDEX_DATASIZE;
+	info.entrysize = sizeof(ShmemIndexEnt);
 	hash_flags = HASH_ELEM;
 
 	/* This will acquire the shmem index lock, but not release it. */
@@ -208,7 +208,7 @@ InitShmemIndex(void)
 	strncpy(item.key, "ShmemIndex", SHMEM_INDEX_KEYSIZE);
 
 	result = (ShmemIndexEnt *)
-		hash_search(ShmemIndex, (char *) &item, HASH_ENTER, &found);
+		hash_search(ShmemIndex, (void *) &item, HASH_ENTER, &found);
 	if (!result)
 		elog(FATAL, "InitShmemIndex: corrupted shmem index");
 
@@ -248,17 +248,15 @@ ShmemInitHash(char *name,		/* table string name for shmem index */
 	 * can't grow or other backends wouldn't be able to find it. So, make
 	 * sure we make it big enough to start with.
 	 *
-	 * The segbase is for calculating pointer values. The shared memory
-	 * allocator must be specified too.
+	 * The shared memory allocator must be specified too.
 	 */
 	infoP->dsize = infoP->max_dsize = hash_select_dirsize(max_size);
-	infoP->segbase = (long *) ShmemBase;
 	infoP->alloc = ShmemAlloc;
 	hash_flags |= HASH_SHARED_MEM | HASH_DIRSIZE;
 
 	/* look it up in the shmem index */
 	location = ShmemInitStruct(name,
-						sizeof(HHDR) + infoP->dsize * sizeof(SEG_OFFSET),
+						sizeof(HASHHDR) + infoP->dsize * sizeof(HASHSEGMENT),
 							   &found);
 
 	/*
@@ -266,18 +264,18 @@ ShmemInitHash(char *name,		/* table string name for shmem index */
 	 * message since they have more information
 	 */
 	if (location == NULL)
-		return 0;
+		return NULL;
 
 	/*
-	 * it already exists, attach to it rather than allocate and initialize
+	 * if it already exists, attach to it rather than allocate and initialize
 	 * new space
 	 */
 	if (found)
 		hash_flags |= HASH_ATTACH;
 
 	/* Now provide the header and directory pointers */
-	infoP->hctl = (long *) location;
-	infoP->dir = (long *) (((char *) location) + sizeof(HHDR));
+	infoP->hctl = (HASHHDR *) location;
+	infoP->dir = (HASHSEGMENT *) (((char *) location) + sizeof(HASHHDR));
 
 	return hash_create(init_size, infoP, hash_flags);
 }
@@ -325,7 +323,7 @@ ShmemInitStruct(char *name, Size size, bool *foundPtr)
 
 	/* look it up in the shmem index */
 	result = (ShmemIndexEnt *)
-		hash_search(ShmemIndex, (char *) &item, HASH_ENTER, foundPtr);
+		hash_search(ShmemIndex, (void *) &item, HASH_ENTER, foundPtr);
 
 	if (!result)
 	{
@@ -359,7 +357,7 @@ ShmemInitStruct(char *name, Size size, bool *foundPtr)
 		{
 			/* out of memory */
 			Assert(ShmemIndex);
-			hash_search(ShmemIndex, (char *) &item, HASH_REMOVE, foundPtr);
+			hash_search(ShmemIndex, (void *) &item, HASH_REMOVE, foundPtr);
 			LWLockRelease(ShmemIndexLock);
 			*foundPtr = FALSE;
 
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 34f3c66e617ec7db22664481ac064062111a1262..84204411faccbed630da2759f4974f6f700e705d 100644
--- a/src/backend/storage/lmgr/lock.c
+++ b/src/backend/storage/lmgr/lock.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.98 2001/09/30 00:45:47 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.99 2001/10/01 05:36:14 tgl Exp $
  *
  * NOTES
  *	  Outside modules can create a lock table and acquire/release
@@ -308,8 +308,8 @@ LockMethodTableInit(char *tabName,
 	 * allocate a hash table for LOCK structs.	This is used to store
 	 * per-locked-object information.
 	 */
-	info.keysize = SHMEM_LOCKTAB_KEYSIZE;
-	info.datasize = SHMEM_LOCKTAB_DATASIZE;
+	info.keysize = sizeof(LOCKTAG);
+	info.entrysize = sizeof(LOCK);
 	info.hash = tag_hash;
 	hash_flags = (HASH_ELEM | HASH_FUNCTION);
 
@@ -328,8 +328,8 @@ LockMethodTableInit(char *tabName,
 	 * allocate a hash table for HOLDER structs.  This is used to store
 	 * per-lock-holder information.
 	 */
-	info.keysize = SHMEM_HOLDERTAB_KEYSIZE;
-	info.datasize = SHMEM_HOLDERTAB_DATASIZE;
+	info.keysize = sizeof(HOLDERTAG);
+	info.entrysize = sizeof(HOLDER);
 	info.hash = tag_hash;
 	hash_flags = (HASH_ELEM | HASH_FUNCTION);
 
@@ -485,7 +485,8 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
 	 * Find or create a lock with this tag
 	 */
 	Assert(lockMethodTable->lockHash->hash == tag_hash);
-	lock = (LOCK *) hash_search(lockMethodTable->lockHash, (Pointer) locktag,
+	lock = (LOCK *) hash_search(lockMethodTable->lockHash,
+								(void *) locktag,
 								HASH_ENTER, &found);
 	if (!lock)
 	{
@@ -530,7 +531,8 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
 	 * Find or create a holder entry with this tag
 	 */
 	holderTable = lockMethodTable->holderHash;
-	holder = (HOLDER *) hash_search(holderTable, (Pointer) &holdertag,
+	holder = (HOLDER *) hash_search(holderTable,
+									(void *) &holdertag,
 									HASH_ENTER, &found);
 	if (!holder)
 	{
@@ -655,7 +657,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
 				SHMQueueDelete(&holder->lockLink);
 				SHMQueueDelete(&holder->procLink);
 				holder = (HOLDER *) hash_search(holderTable,
-												(Pointer) holder,
+												(void *) holder,
 												HASH_REMOVE, &found);
 				if (!holder || !found)
 					elog(NOTICE, "LockAcquire: remove holder, table corrupted");
@@ -1019,7 +1021,8 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag,
 	 * Find a lock with this tag
 	 */
 	Assert(lockMethodTable->lockHash->hash == tag_hash);
-	lock = (LOCK *) hash_search(lockMethodTable->lockHash, (Pointer) locktag,
+	lock = (LOCK *) hash_search(lockMethodTable->lockHash,
+								(void *) locktag,
 								HASH_FIND, &found);
 
 	/*
@@ -1051,7 +1054,8 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag,
 	TransactionIdStore(xid, &holdertag.xid);
 
 	holderTable = lockMethodTable->holderHash;
-	holder = (HOLDER *) hash_search(holderTable, (Pointer) &holdertag,
+	holder = (HOLDER *) hash_search(holderTable,
+									(void *) &holdertag,
 									HASH_FIND_SAVE, &found);
 	if (!holder || !found)
 	{
@@ -1124,7 +1128,7 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag,
 		 */
 		Assert(lockMethodTable->lockHash->hash == tag_hash);
 		lock = (LOCK *) hash_search(lockMethodTable->lockHash,
-									(Pointer) &(lock->tag),
+									(void *) &(lock->tag),
 									HASH_REMOVE,
 									&found);
 		if (!lock || !found)
@@ -1153,7 +1157,8 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag,
 		HOLDER_PRINT("LockRelease: deleting", holder);
 		SHMQueueDelete(&holder->lockLink);
 		SHMQueueDelete(&holder->procLink);
-		holder = (HOLDER *) hash_search(holderTable, (Pointer) &holder,
+		holder = (HOLDER *) hash_search(holderTable,
+										(void *) &holder,
 										HASH_REMOVE_SAVED, &found);
 		if (!holder || !found)
 		{
@@ -1306,7 +1311,7 @@ LockReleaseAll(LOCKMETHOD lockmethod, PROC *proc,
 		 * remove the holder entry from the hashtable
 		 */
 		holder = (HOLDER *) hash_search(lockMethodTable->holderHash,
-										(Pointer) holder,
+										(void *) holder,
 										HASH_REMOVE,
 										&found);
 		if (!holder || !found)
@@ -1326,7 +1331,7 @@ LockReleaseAll(LOCKMETHOD lockmethod, PROC *proc,
 			LOCK_PRINT("LockReleaseAll: deleting", lock, 0);
 			Assert(lockMethodTable->lockHash->hash == tag_hash);
 			lock = (LOCK *) hash_search(lockMethodTable->lockHash,
-										(Pointer) &(lock->tag),
+										(void *) &(lock->tag),
 										HASH_REMOVE, &found);
 			if (!lock || !found)
 			{
@@ -1364,14 +1369,10 @@ LockShmemSize(int maxBackends)
 																 * lockMethodTable->ctl */
 
 	/* lockHash table */
-	size += hash_estimate_size(max_table_size,
-							   SHMEM_LOCKTAB_KEYSIZE,
-							   SHMEM_LOCKTAB_DATASIZE);
+	size += hash_estimate_size(max_table_size, sizeof(LOCK));
 
 	/* holderHash table */
-	size += hash_estimate_size(max_table_size,
-							   SHMEM_HOLDERTAB_KEYSIZE,
-							   SHMEM_HOLDERTAB_DATASIZE);
+	size += hash_estimate_size(max_table_size, sizeof(HOLDER));
 
 	/*
 	 * Since the lockHash entry count above is only an estimate, add 10%
diff --git a/src/backend/storage/smgr/mm.c b/src/backend/storage/smgr/mm.c
index 43da08b19c8d1e40eed46a74067f247cde7e756e..c6d084dada58159a478e8cbad3481569acf65518 100644
--- a/src/backend/storage/smgr/mm.c
+++ b/src/backend/storage/smgr/mm.c
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/smgr/Attic/mm.c,v 1.25 2001/09/29 04:02:25 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/smgr/Attic/mm.c,v 1.26 2001/10/01 05:36:15 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -103,12 +103,12 @@ mminit()
 	}
 
 	info.keysize = sizeof(MMCacheTag);
-	info.datasize = sizeof(MMHashEntry) - sizeof(MMCacheTag);
+	info.entrysize = sizeof(MMHashEntry);
 	info.hash = tag_hash;
 
-	MMCacheHT = (HTAB *) ShmemInitHash("Main memory store HT",
-									   MMNBUFFERS, MMNBUFFERS,
-									 &info, (HASH_ELEM | HASH_FUNCTION));
+	MMCacheHT = ShmemInitHash("Main memory store HT",
+							  MMNBUFFERS, MMNBUFFERS,
+							  &info, (HASH_ELEM | HASH_FUNCTION));
 
 	if (MMCacheHT == (HTAB *) NULL)
 	{
@@ -117,12 +117,12 @@ mminit()
 	}
 
 	info.keysize = sizeof(MMRelTag);
-	info.datasize = sizeof(MMRelHashEntry) - sizeof(MMRelTag);
+	info.entrysize = sizeof(MMRelHashEntry);
 	info.hash = tag_hash;
 
-	MMRelCacheHT = (HTAB *) ShmemInitHash("Main memory rel HT",
-										  MMNRELATIONS, MMNRELATIONS,
-									 &info, (HASH_ELEM | HASH_FUNCTION));
+	MMRelCacheHT = ShmemInitHash("Main memory rel HT",
+								 MMNRELATIONS, MMNRELATIONS,
+								 &info, (HASH_ELEM | HASH_FUNCTION));
 
 	if (MMRelCacheHT == (HTAB *) NULL)
 	{
@@ -180,7 +180,8 @@ mmcreate(Relation reln)
 		tag.mmrt_dbid = MyDatabaseId;
 
 	entry = (MMRelHashEntry *) hash_search(MMRelCacheHT,
-									  (char *) &tag, HASH_ENTER, &found);
+										   (void *) &tag,
+										   HASH_ENTER, &found);
 
 	if (entry == (MMRelHashEntry *) NULL)
 	{
@@ -224,7 +225,7 @@ mmunlink(RelFileNode rnode)
 			&& MMBlockTags[i].mmct_relid == rnode.relNode)
 		{
 			entry = (MMHashEntry *) hash_search(MMCacheHT,
-												(char *) &MMBlockTags[i],
+												(void *) &MMBlockTags[i],
 												HASH_REMOVE, &found);
 			if (entry == (MMHashEntry *) NULL || !found)
 			{
@@ -239,7 +240,8 @@ mmunlink(RelFileNode rnode)
 	rtag.mmrt_dbid = rnode.tblNode;
 	rtag.mmrt_relid = rnode.relNode;
 
-	rentry = (MMRelHashEntry *) hash_search(MMRelCacheHT, (char *) &rtag,
+	rentry = (MMRelHashEntry *) hash_search(MMRelCacheHT,
+											(void *) &rtag,
 											HASH_REMOVE, &found);
 
 	if (rentry == (MMRelHashEntry *) NULL || !found)
@@ -302,7 +304,8 @@ mmextend(Relation reln, BlockNumber blocknum, char *buffer)
 		(*MMCurTop)++;
 	}
 
-	rentry = (MMRelHashEntry *) hash_search(MMRelCacheHT, (char *) &rtag,
+	rentry = (MMRelHashEntry *) hash_search(MMRelCacheHT,
+											(void *) &rtag,
 											HASH_FIND, &found);
 	if (rentry == (MMRelHashEntry *) NULL || !found)
 	{
@@ -312,7 +315,8 @@ mmextend(Relation reln, BlockNumber blocknum, char *buffer)
 
 	tag.mmct_blkno = rentry->mmrhe_nblocks;
 
-	entry = (MMHashEntry *) hash_search(MMCacheHT, (char *) &tag,
+	entry = (MMHashEntry *) hash_search(MMCacheHT,
+										(void *) &tag,
 										HASH_ENTER, &found);
 	if (entry == (MMHashEntry *) NULL || found)
 	{
@@ -381,7 +385,8 @@ mmread(Relation reln, BlockNumber blocknum, char *buffer)
 	tag.mmct_blkno = blocknum;
 
 	LWLockAcquire(MMCacheLock, LW_EXCLUSIVE);
-	entry = (MMHashEntry *) hash_search(MMCacheHT, (char *) &tag,
+	entry = (MMHashEntry *) hash_search(MMCacheHT,
+										(void *) &tag,
 										HASH_FIND, &found);
 
 	if (entry == (MMHashEntry *) NULL)
@@ -428,7 +433,8 @@ mmwrite(Relation reln, BlockNumber blocknum, char *buffer)
 	tag.mmct_blkno = blocknum;
 
 	LWLockAcquire(MMCacheLock, LW_EXCLUSIVE);
-	entry = (MMHashEntry *) hash_search(MMCacheHT, (char *) &tag,
+	entry = (MMHashEntry *) hash_search(MMCacheHT,
+										(void *) &tag,
 										HASH_FIND, &found);
 
 	if (entry == (MMHashEntry *) NULL)
@@ -502,7 +508,8 @@ mmnblocks(Relation reln)
 
 	LWLockAcquire(MMCacheLock, LW_EXCLUSIVE);
 
-	rentry = (MMRelHashEntry *) hash_search(MMRelCacheHT, (char *) &rtag,
+	rentry = (MMRelHashEntry *) hash_search(MMRelCacheHT,
+											(void *) &rtag,
 											HASH_FIND, &found);
 
 	if (rentry == (MMRelHashEntry *) NULL)
@@ -558,16 +565,12 @@ MMShmemSize()
 	/*
 	 * first compute space occupied by the (dbid,relid,blkno) hash table
 	 */
-	size += hash_estimate_size(MMNBUFFERS,
-							   0,		/* MMHashEntry includes key */
-							   sizeof(MMHashEntry));
+	size += hash_estimate_size(MMNBUFFERS, sizeof(MMHashEntry));
 
 	/*
 	 * now do the same for the rel hash table
 	 */
-	size += hash_estimate_size(MMNRELATIONS,
-							   0,		/* MMRelHashEntry includes key */
-							   sizeof(MMRelHashEntry));
+	size += hash_estimate_size(MMNRELATIONS, sizeof(MMRelHashEntry));
 
 	/*
 	 * finally, add in the memory block we use directly
diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c
index dc5f7c8495d44a6dfe9903a47b7039a609f0c910..6ab9871648e1be6f39f86f9885dd0cd1019a2c6d 100644
--- a/src/backend/utils/adt/ri_triggers.c
+++ b/src/backend/utils/adt/ri_triggers.c
@@ -18,7 +18,7 @@
  * Portions Copyright (c) 2000-2001, PostgreSQL Global Development Group
  * Copyright 1999 Jan Wieck
  *
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.25 2001/05/31 17:32:33 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.26 2001/10/01 05:36:16 tgl Exp $
  *
  * ----------
  */
@@ -2988,12 +2988,13 @@ ri_InitHashTables(void)
 
 	memset(&ctl, 0, sizeof(ctl));
 	ctl.keysize = sizeof(RI_QueryKey);
-	ctl.datasize = sizeof(void *);
-	ri_query_cache = hash_create(RI_INIT_QUERYHASHSIZE, &ctl, HASH_ELEM);
+	ctl.entrysize = sizeof(RI_QueryHashEntry);
+	ctl.hash = tag_hash;
+	ri_query_cache = hash_create(RI_INIT_QUERYHASHSIZE, &ctl,
+								 HASH_ELEM | HASH_FUNCTION);
 
-	memset(&ctl, 0, sizeof(ctl));
 	ctl.keysize = sizeof(Oid);
-	ctl.datasize = sizeof(Oid) + sizeof(FmgrInfo);
+	ctl.entrysize = sizeof(RI_OpreqHashEntry);
 	ctl.hash = tag_hash;
 	ri_opreq_cache = hash_create(RI_INIT_OPREQHASHSIZE, &ctl,
 								 HASH_ELEM | HASH_FUNCTION);
@@ -3023,7 +3024,8 @@ ri_FetchPreparedPlan(RI_QueryKey *key)
 	 * Lookup for the key
 	 */
 	entry = (RI_QueryHashEntry *) hash_search(ri_query_cache,
-										(char *) key, HASH_FIND, &found);
+											  (void *) key,
+											  HASH_FIND, &found);
 	if (entry == NULL)
 		elog(FATAL, "error in RI plan cache");
 	if (!found)
@@ -3054,7 +3056,8 @@ ri_HashPreparedPlan(RI_QueryKey *key, void *plan)
 	 * Add the new plan.
 	 */
 	entry = (RI_QueryHashEntry *) hash_search(ri_query_cache,
-									   (char *) key, HASH_ENTER, &found);
+											  (void *) key,
+											  HASH_ENTER, &found);
 	if (entry == NULL)
 		elog(FATAL, "can't insert into RI plan cache");
 	entry->plan = plan;
@@ -3224,14 +3227,15 @@ ri_AttributesEqual(Oid typeid, Datum oldvalue, Datum newvalue)
 	/*
 	 * On the first call initialize the hashtable
 	 */
-	if (!ri_query_cache)
+	if (!ri_opreq_cache)
 		ri_InitHashTables();
 
 	/*
 	 * Try to find the '=' operator for this type in our cache
 	 */
 	entry = (RI_OpreqHashEntry *) hash_search(ri_opreq_cache,
-									(char *) &typeid, HASH_FIND, &found);
+											  (void *) &typeid,
+											  HASH_FIND, &found);
 	if (entry == NULL)
 		elog(FATAL, "error in RI operator cache");
 
@@ -3271,9 +3275,8 @@ ri_AttributesEqual(Oid typeid, Datum oldvalue, Datum newvalue)
 		MemoryContextSwitchTo(oldcontext);
 
 		entry = (RI_OpreqHashEntry *) hash_search(ri_opreq_cache,
-												  (char *) &typeid,
-												  HASH_ENTER,
-												  &found);
+												  (void *) &typeid,
+												  HASH_ENTER, &found);
 		if (entry == NULL)
 			elog(FATAL, "can't insert into RI operator cache");
 
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index c626cd6de8ccd3ff9f2266f03affe50a5045e6aa..628e96842d851313c01b8e0d534ac491c2464f6e 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.143 2001/08/25 18:52:42 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.144 2001/10/01 05:36:16 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -132,7 +132,7 @@ typedef struct relnodecacheent
 } RelNodeCacheEnt;
 
 /*
- *		macros to manipulate name cache and id cache
+ *		macros to manipulate the lookup hashtables
  */
 #define RelationCacheInsert(RELATION)	\
 do { \
@@ -149,7 +149,7 @@ do { \
 		/* used to give notice -- now just keep quiet */ ; \
 	namehentry->reldesc = RELATION; \
 	idhentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \
-										   (char *)&(RELATION->rd_id), \
+										   (void *) &(RELATION->rd_id), \
 										   HASH_ENTER, \
 										   &found); \
 	if (idhentry == NULL) \
@@ -158,7 +158,7 @@ do { \
 		/* used to give notice -- now just keep quiet */ ; \
 	idhentry->reldesc = RELATION; \
 	nodentry = (RelNodeCacheEnt*)hash_search(RelationNodeCache, \
-										   (char *)&(RELATION->rd_node), \
+										   (void *) &(RELATION->rd_node), \
 										   HASH_ENTER, \
 										   &found); \
 	if (nodentry == NULL) \
@@ -172,7 +172,7 @@ do { \
 do { \
 	RelNameCacheEnt *hentry; bool found; \
 	hentry = (RelNameCacheEnt*)hash_search(RelationNameCache, \
-										   (char *)NAME,HASH_FIND,&found); \
+										   (void *) (NAME),HASH_FIND,&found); \
 	if (hentry == NULL) \
 		elog(FATAL, "error in CACHE"); \
 	if (found) \
@@ -186,7 +186,7 @@ do { \
 	RelIdCacheEnt *hentry; \
 	bool found; \
 	hentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \
-										 (char *)&(ID),HASH_FIND, &found); \
+										 (void *)&(ID),HASH_FIND, &found); \
 	if (hentry == NULL) \
 		elog(FATAL, "error in CACHE"); \
 	if (found) \
@@ -200,7 +200,7 @@ do { \
 	RelNodeCacheEnt *hentry; \
 	bool found; \
 	hentry = (RelNodeCacheEnt*)hash_search(RelationNodeCache, \
-									 (char *)&(NODE),HASH_FIND, &found); \
+									 (void *)&(NODE),HASH_FIND, &found); \
 	if (hentry == NULL) \
 		elog(FATAL, "error in CACHE"); \
 	if (found) \
@@ -223,14 +223,14 @@ do { \
 	if (!found) \
 		elog(NOTICE, "trying to delete a reldesc that does not exist."); \
 	idhentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \
-										   (char *)&(RELATION->rd_id), \
+										   (void *)&(RELATION->rd_id), \
 										   HASH_REMOVE, &found); \
 	if (idhentry == NULL) \
 		elog(FATAL, "can't delete from relation descriptor cache"); \
 	if (!found) \
 		elog(NOTICE, "trying to delete a reldesc that does not exist."); \
 	nodentry = (RelNodeCacheEnt*)hash_search(RelationNodeCache, \
-										   (char *)&(RELATION->rd_node), \
+										   (void *)&(RELATION->rd_node), \
 										   HASH_REMOVE, &found); \
 	if (nodentry == NULL) \
 		elog(FATAL, "can't delete from relation descriptor cache"); \
@@ -2092,17 +2092,19 @@ RelationCacheInitialize(void)
 	/*
 	 * create global caches
 	 */
-	MemSet(&ctl, 0, (int) sizeof(ctl));
+	MemSet(&ctl, 0, sizeof(ctl));
 	ctl.keysize = sizeof(NameData);
-	ctl.datasize = sizeof(Relation);
+	ctl.entrysize = sizeof(RelNameCacheEnt);
 	RelationNameCache = hash_create(INITRELCACHESIZE, &ctl, HASH_ELEM);
 
 	ctl.keysize = sizeof(Oid);
+	ctl.entrysize = sizeof(RelIdCacheEnt);
 	ctl.hash = tag_hash;
 	RelationIdCache = hash_create(INITRELCACHESIZE, &ctl,
 								  HASH_ELEM | HASH_FUNCTION);
 
 	ctl.keysize = sizeof(RelFileNode);
+	ctl.entrysize = sizeof(RelNodeCacheEnt);
 	ctl.hash = tag_hash;
 	RelationNodeCache = hash_create(INITRELCACHESIZE, &ctl,
 									HASH_ELEM | HASH_FUNCTION);
@@ -2182,17 +2184,19 @@ CreateDummyCaches(void)
 
 	oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
 
-	MemSet(&ctl, 0, (int) sizeof(ctl));
+	MemSet(&ctl, 0, sizeof(ctl));
 	ctl.keysize = sizeof(NameData);
-	ctl.datasize = sizeof(Relation);
+	ctl.entrysize = sizeof(RelNameCacheEnt);
 	RelationNameCache = hash_create(INITRELCACHESIZE, &ctl, HASH_ELEM);
 
 	ctl.keysize = sizeof(Oid);
+	ctl.entrysize = sizeof(RelIdCacheEnt);
 	ctl.hash = tag_hash;
 	RelationIdCache = hash_create(INITRELCACHESIZE, &ctl,
 								  HASH_ELEM | HASH_FUNCTION);
 
 	ctl.keysize = sizeof(RelFileNode);
+	ctl.entrysize = sizeof(RelNodeCacheEnt);
 	ctl.hash = tag_hash;
 	RelationNodeCache = hash_create(INITRELCACHESIZE, &ctl,
 									HASH_ELEM | HASH_FUNCTION);
diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c
index fd9b11ba98e52be57c435482f2585c1be1fbbca9..92e775bfe86e334e894e3d868bde088adf70d678 100644
--- a/src/backend/utils/hash/dynahash.c
+++ b/src/backend/utils/hash/dynahash.c
@@ -1,14 +1,15 @@
 /*-------------------------------------------------------------------------
  *
  * dynahash.c
- *	  dynamic hashing
+ *	  dynamic hash tables
+ *
  *
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/hash/dynahash.c,v 1.36 2001/06/22 19:16:23 wieck Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/hash/dynahash.c,v 1.37 2001/10/01 05:36:16 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -40,46 +41,40 @@
  * Modified by sullivan@postgres.berkeley.edu April 1990
  *		changed ctl structure for shared memory
  */
-#include <sys/types.h>
 
 #include "postgres.h"
+
+#include <sys/types.h>
+
 #include "utils/dynahash.h"
 #include "utils/hsearch.h"
 #include "utils/memutils.h"
 
 /*
- * Fast MOD arithmetic, assuming that y is a power of 2 !
+ * Key (also entry) part of a HASHELEMENT
  */
+#define ELEMENTKEY(helem)  (((char *)(helem)) + MAXALIGN(sizeof(HASHELEMENT)))
 
+/*
+ * Fast MOD arithmetic, assuming that y is a power of 2 !
+ */
 #define MOD(x,y)			   ((x) & ((y)-1))
 
 /*
  * Private function prototypes
  */
 static void *DynaHashAlloc(Size size);
-static uint32 call_hash(HTAB *hashp, char *k);
-static SEG_OFFSET seg_alloc(HTAB *hashp);
-static int	bucket_alloc(HTAB *hashp);
-static int	dir_realloc(HTAB *hashp);
-static int	expand_table(HTAB *hashp);
-static int	hdefault(HTAB *hashp);
-static int	init_htab(HTAB *hashp, int nelem);
+static uint32 call_hash(HTAB *hashp, void *k);
+static HASHSEGMENT seg_alloc(HTAB *hashp);
+static bool	element_alloc(HTAB *hashp);
+static bool	dir_realloc(HTAB *hashp);
+static bool	expand_table(HTAB *hashp);
+static bool	hdefault(HTAB *hashp);
+static bool	init_htab(HTAB *hashp, long nelem);
 
 
-/* ----------------
+/*
  * memory allocation routines
- *
- * for postgres: all hash elements have to be in
- * the global cache context.  Otherwise the postgres
- * garbage collector is going to corrupt them. -wei
- *
- * ??? the "cache" memory context is intended to store only
- *	   system cache information.  The user of the hashing
- *	   routines should specify which context to use or we
- *	   should create a separate memory context for these
- *	   hash routines.  For now I have modified this code to
- *	   do the latter -cim 1/19/91
- * ----------------
  */
 static MemoryContext DynaHashCxt = NULL;
 static MemoryContext CurrentDynaHashCxt = NULL;
@@ -95,39 +90,22 @@ DynaHashAlloc(Size size)
 #define MEM_FREE		pfree
 
 
-/*
- * pointer access macros.  Shared memory implementation cannot
- * store pointers in the hash table data structures because
- * pointer values will be different in different address spaces.
- * these macros convert offsets to pointers and pointers to offsets.
- * Shared memory need not be contiguous, but all addresses must be
- * calculated relative to some offset (segbase).
- */
-
-#define GET_SEG(hp,seg_num)\
-  (SEGMENT) (((unsigned long) (hp)->segbase) + (hp)->dir[seg_num])
-
-#define GET_BUCKET(hp,bucket_offs)\
-  (ELEMENT *) (((unsigned long) (hp)->segbase) + bucket_offs)
-
-#define MAKE_HASHOFFSET(hp,ptr)\
-  ( ((unsigned long) ptr) - ((unsigned long) (hp)->segbase) )
-
 #if HASH_STATISTICS
 static long hash_accesses,
 			hash_collisions,
 			hash_expansions;
-
 #endif
 
+
 /************************** CREATE ROUTINES **********************/
 
 HTAB *
-hash_create(int nelem, HASHCTL *info, int flags)
+hash_create(long nelem, HASHCTL *info, int flags)
 {
-	HHDR	   *hctl;
 	HTAB	   *hashp;
+	HASHHDR	   *hctl;
 
+	/* First time through, create a memory context for hash tables */
 	if (!DynaHashCxt)
 		DynaHashCxt = AllocSetContextCreate(TopMemoryContext,
 											"DynaHash",
@@ -135,62 +113,57 @@ hash_create(int nelem, HASHCTL *info, int flags)
 											ALLOCSET_DEFAULT_INITSIZE,
 											ALLOCSET_DEFAULT_MAXSIZE);
 
+	/* Select allocation context for this hash table */
 	if (flags & HASH_CONTEXT)
 		CurrentDynaHashCxt = info->hcxt;
 	else
 		CurrentDynaHashCxt = DynaHashCxt;
 
+	/* Initialize the hash header */
 	hashp = (HTAB *) MEM_ALLOC(sizeof(HTAB));
+	if (!hashp)
+		return NULL;
 	MemSet(hashp, 0, sizeof(HTAB));
 
 	if (flags & HASH_FUNCTION)
 		hashp->hash = info->hash;
 	else
-	{
-		/* default */
-		hashp->hash = string_hash;
-	}
+		hashp->hash = string_hash; /* default hash function */
 
 	if (flags & HASH_SHARED_MEM)
 	{
-
 		/*
 		 * ctl structure is preallocated for shared memory tables. Note
 		 * that HASH_DIRSIZE had better be set as well.
 		 */
-
-		hashp->hctl = (HHDR *) info->hctl;
-		hashp->segbase = (char *) info->segbase;
+		hashp->hctl = info->hctl;
+		hashp->dir = info->dir;
 		hashp->alloc = info->alloc;
-		hashp->dir = (SEG_OFFSET *) info->dir;
 		hashp->hcxt = NULL;
 
 		/* hash table already exists, we're just attaching to it */
 		if (flags & HASH_ATTACH)
 			return hashp;
-
 	}
 	else
 	{
 		/* setup hash table defaults */
-
 		hashp->hctl = NULL;
-		hashp->alloc = MEM_ALLOC;
 		hashp->dir = NULL;
-		hashp->segbase = NULL;
+		hashp->alloc = MEM_ALLOC;
 		hashp->hcxt = DynaHashCxt;
-
 	}
 
 	if (!hashp->hctl)
 	{
-			hashp->hctl = (HHDR *) hashp->alloc(sizeof(HHDR));
+		hashp->hctl = (HASHHDR *) hashp->alloc(sizeof(HASHHDR));
 		if (!hashp->hctl)
-			return 0;
+			return NULL;
 	}
 
 	if (!hdefault(hashp))
-		return 0;
+		return NULL;
+
 	hctl = hashp->hctl;
 #ifdef HASH_STATISTICS
 	hctl->accesses = hctl->collisions = 0;
@@ -222,24 +195,26 @@ hash_create(int nelem, HASHCTL *info, int flags)
 	if (flags & HASH_ELEM)
 	{
 		hctl->keysize = info->keysize;
-		hctl->datasize = info->datasize;
+		hctl->entrysize = info->entrysize;
 	}
+
 	if (flags & HASH_ALLOC)
 		hashp->alloc = info->alloc;
 	else
 	{
 		if (flags & HASH_CONTEXT)
 		{
+			/* hash table structures live in child of given context */
 			CurrentDynaHashCxt = AllocSetContextCreate(info->hcxt,
 											"DynaHashTable",
 											ALLOCSET_DEFAULT_MINSIZE,
 											ALLOCSET_DEFAULT_INITSIZE,
 											ALLOCSET_DEFAULT_MAXSIZE);
-			
 			hashp->hcxt = CurrentDynaHashCxt;
 		}
 		else
 		{
+			/* hash table structures live in child of DynaHashCxt */
 			CurrentDynaHashCxt = AllocSetContextCreate(DynaHashCxt,
 											"DynaHashTable",
 											ALLOCSET_DEFAULT_MINSIZE,
@@ -249,57 +224,54 @@ hash_create(int nelem, HASHCTL *info, int flags)
 		}
 	}
 
-	if (init_htab(hashp, nelem))
+	if (!init_htab(hashp, nelem))
 	{
 		hash_destroy(hashp);
-		return 0;
+		return NULL;
 	}
 	return hashp;
 }
 
 /*
- * Set default HHDR parameters.
+ * Set default HASHHDR parameters.
  */
-static int
+static bool
 hdefault(HTAB *hashp)
 {
-	HHDR	   *hctl;
+	HASHHDR	   *hctl = hashp->hctl;
 
-	MemSet(hashp->hctl, 0, sizeof(HHDR));
+	MemSet(hctl, 0, sizeof(HASHHDR));
 
-	hctl = hashp->hctl;
 	hctl->ssize = DEF_SEGSIZE;
 	hctl->sshift = DEF_SEGSIZE_SHIFT;
 	hctl->dsize = DEF_DIRSIZE;
 	hctl->ffactor = DEF_FFACTOR;
-	hctl->nkeys = 0;
+	hctl->nentries = 0;
 	hctl->nsegs = 0;
 
 	/* I added these MS. */
 
-	/* default memory allocation for hash buckets */
+	/* rather pointless defaults for key & entry size */
 	hctl->keysize = sizeof(char *);
-	hctl->datasize = sizeof(char *);
+	hctl->entrysize = 2 * sizeof(char *);
 
 	/* table has no fixed maximum size */
 	hctl->max_dsize = NO_MAX_DSIZE;
 
 	/* garbage collection for HASH_REMOVE */
-	hctl->freeBucketIndex = INVALID_INDEX;
+	hctl->freeList = NULL;
 
-	return 1;
+	return true;
 }
 
 
-static int
-init_htab(HTAB *hashp, int nelem)
+static bool
+init_htab(HTAB *hashp, long nelem)
 {
-	SEG_OFFSET *segp;
+	HASHHDR	   *hctl = hashp->hctl;
+	HASHSEGMENT *segp;
 	int			nbuckets;
 	int			nsegs;
-	HHDR	   *hctl;
-
-	hctl = hashp->hctl;
 
 	/*
 	 * Divide number of elements by the fill factor to determine a desired
@@ -329,29 +301,29 @@ init_htab(HTAB *hashp, int nelem)
 		if (!(hashp->dir))
 			hctl->dsize = nsegs;
 		else
-			return -1;
+			return false;
 	}
 
 	/* Allocate a directory */
 	if (!(hashp->dir))
 	{
 		CurrentDynaHashCxt = hashp->hcxt;
-		hashp->dir = (SEG_OFFSET *)
-			hashp->alloc(hctl->dsize * sizeof(SEG_OFFSET));
+		hashp->dir = (HASHSEGMENT *)
+			hashp->alloc(hctl->dsize * sizeof(HASHSEGMENT));
 		if (!hashp->dir)
-			return -1;
+			return false;
 	}
 
 	/* Allocate initial segments */
 	for (segp = hashp->dir; hctl->nsegs < nsegs; hctl->nsegs++, segp++)
 	{
 		*segp = seg_alloc(hashp);
-		if (*segp == (SEG_OFFSET) 0)
-			return -1;
+		if (*segp == NULL)
+			return false;
 	}
 
 #if HASH_DEBUG
-	fprintf(stderr, "%s\n%s%x\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%x\n%s%x\n%s%d\n%s%d\n",
+	fprintf(stderr, "%s\n%s%p\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%x\n%s%x\n%s%d\n%s%d\n",
 			"init_htab:",
 			"TABLE POINTER   ", hashp,
 			"DIRECTORY SIZE  ", hctl->dsize,
@@ -362,9 +334,9 @@ init_htab(HTAB *hashp, int nelem)
 			"HIGH MASK       ", hctl->high_mask,
 			"LOW  MASK       ", hctl->low_mask,
 			"NSEGS           ", hctl->nsegs,
-			"NKEYS           ", hctl->nkeys);
+			"NENTRIES        ", hctl->nentries);
 #endif
-	return 0;
+	return true;
 }
 
 /*
@@ -375,14 +347,14 @@ init_htab(HTAB *hashp, int nelem)
  * NB: assumes that all hash structure parameters have default values!
  */
 long
-hash_estimate_size(long num_entries, long keysize, long datasize)
+hash_estimate_size(long num_entries, long entrysize)
 {
 	long		size = 0;
 	long		nBuckets,
 				nSegments,
 				nDirEntries,
-				nRecordAllocs,
-				recordSize;
+				nElementAllocs,
+				elementSize;
 
 	/* estimate number of buckets wanted */
 	nBuckets = 1L << my_log2((num_entries - 1) / DEF_FFACTOR + 1);
@@ -394,16 +366,15 @@ hash_estimate_size(long num_entries, long keysize, long datasize)
 		nDirEntries <<= 1;		/* dir_alloc doubles dsize at each call */
 
 	/* fixed control info */
-	size += MAXALIGN(sizeof(HHDR));		/* but not HTAB, per above */
+	size += MAXALIGN(sizeof(HASHHDR));		/* but not HTAB, per above */
 	/* directory */
-	size += MAXALIGN(nDirEntries * sizeof(SEG_OFFSET));
+	size += MAXALIGN(nDirEntries * sizeof(HASHSEGMENT));
 	/* segments */
-	size += nSegments * MAXALIGN(DEF_SEGSIZE * sizeof(BUCKET_INDEX));
-	/* records --- allocated in groups of BUCKET_ALLOC_INCR */
-	recordSize = sizeof(BUCKET_INDEX) + keysize + datasize;
-	recordSize = MAXALIGN(recordSize);
-	nRecordAllocs = (num_entries - 1) / BUCKET_ALLOC_INCR + 1;
-	size += nRecordAllocs * BUCKET_ALLOC_INCR * recordSize;
+	size += nSegments * MAXALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET));
+	/* elements --- allocated in groups of HASHELEMENT_ALLOC_INCR */
+	elementSize = MAXALIGN(sizeof(HASHELEMENT)) + MAXALIGN(entrysize);
+	nElementAllocs = (num_entries - 1) / HASHELEMENT_ALLOC_INCR + 1;
+	size += nElementAllocs * HASHELEMENT_ALLOC_INCR * elementSize;
 
 	return size;
 }
@@ -439,40 +410,11 @@ hash_select_dirsize(long num_entries)
 
 /********************** DESTROY ROUTINES ************************/
 
-/*
- * XXX this sure looks thoroughly broken to me --- tgl 2/99.
- * It's freeing every entry individually --- but they weren't
- * allocated individually, see bucket_alloc!!  Why doesn't it crash?
- * ANSWER: it probably does crash, but is never invoked in normal
- * operations...
- *
- * Thomas is right, it does crash. Therefore I changed the code
- * to use a separate memory context which is a child of the DynaHashCxt
- * by default. And the HASHCTL structure got extended with a hcxt
- * field, where someone can specify an explicit context (giving new
- * flag HASH_CONTEXT) and forget about hash_destroy() completely.
- * The shmem operations aren't changed, but in shmem mode a destroy
- * doesn't work anyway. Jan Wieck 03/2001.
- */
-
 void
 hash_destroy(HTAB *hashp)
 {
 	if (hashp != NULL)
 	{
-#if 0
-		SEG_OFFSET	segNum;
-		SEGMENT		segp;
-		int			nsegs = hashp->hctl->nsegs;
-		int			j;
-		BUCKET_INDEX *elp,
-					p,
-					q;
-		ELEMENT    *curr;
-#endif
-
-		/* cannot destroy a shared memory hash table */
-		Assert(!hashp->segbase);
 		/* allocation method must be one we know how to free, too */
 		Assert(hashp->alloc == MEM_ALLOC);
 		/* so this hashtable must have it's own context */
@@ -481,40 +423,18 @@ hash_destroy(HTAB *hashp)
 		hash_stats("destroy", hashp);
 
 		/*
-		 * Free buckets, dir etc. by destroying the hash tables
+		 * Free buckets, dir etc. by destroying the hash table's
 		 * memory context.
 		 */
 		MemoryContextDelete(hashp->hcxt);
 
-#if 0
-		/*
-		 * Dead code - replaced by MemoryContextDelete() above
-		 */
-		for (segNum = 0; nsegs > 0; nsegs--, segNum++)
-		{
-
-			segp = GET_SEG(hashp, segNum);
-			for (j = 0, elp = segp; j < hashp->hctl->ssize; j++, elp++)
-			{
-				for (p = *elp; p != INVALID_INDEX; p = q)
-				{
-					curr = GET_BUCKET(hashp, p);
-					q = curr->next;
-					MEM_FREE((char *) curr);
-				}
-			}
-			MEM_FREE((char *) segp);
-		}
-		MEM_FREE((char *) hashp->dir);
-#endif
-
 		/*
 		 * Free the HTAB and control structure, which are allocated
 		 * in the parent context (DynaHashCxt or the context given
-		 * by the caller of hash_create().
+		 * by the caller of hash_create()).
 		 */
-		MEM_FREE((char *) hashp->hctl);
-		MEM_FREE((char *) hashp);
+		MEM_FREE(hashp->hctl);
+		MEM_FREE(hashp);
 	}
 }
 
@@ -526,8 +446,8 @@ hash_stats(char *where, HTAB *hashp)
 	fprintf(stderr, "%s: this HTAB -- accesses %ld collisions %ld\n",
 			where, hashp->hctl->accesses, hashp->hctl->collisions);
 
-	fprintf(stderr, "hash_stats: keys %ld keysize %ld maxp %d segmentcount %d\n",
-			hashp->hctl->nkeys, hashp->hctl->keysize,
+	fprintf(stderr, "hash_stats: entries %ld keysize %ld maxp %d segmentcount %d\n",
+			hashp->hctl->nentries, hashp->hctl->keysize,
 			hashp->hctl->max_bucket, hashp->hctl->nsegs);
 	fprintf(stderr, "%s: total accesses %ld total collisions %ld\n",
 			where, hash_accesses, hash_collisions);
@@ -541,9 +461,9 @@ hash_stats(char *where, HTAB *hashp)
 /*******************************SEARCH ROUTINES *****************************/
 
 static uint32
-call_hash(HTAB *hashp, char *k)
+call_hash(HTAB *hashp, void *k)
 {
-	HHDR	   *hctl = hashp->hctl;
+	HASHHDR	   *hctl = hashp->hctl;
 	long		hash_val,
 				bucket;
 
@@ -553,7 +473,7 @@ call_hash(HTAB *hashp, char *k)
 	if (bucket > hctl->max_bucket)
 		bucket = bucket & hctl->low_mask;
 
-	return bucket;
+	return (uint32) bucket;
 }
 
 /*
@@ -566,31 +486,34 @@ call_hash(HTAB *hashp, char *k)
  *		foundPtr is TRUE if we found an element in the table
  *		(FALSE if we entered one).
  */
-long *
+void *
 hash_search(HTAB *hashp,
-			char *keyPtr,
+			void *keyPtr,
 			HASHACTION action,	/* HASH_FIND / HASH_ENTER / HASH_REMOVE
 								 * HASH_FIND_SAVE / HASH_REMOVE_SAVED */
 			bool *foundPtr)
 {
+	HASHHDR	   *hctl;
 	uint32		bucket;
 	long		segment_num;
 	long		segment_ndx;
-	SEGMENT		segp;
-	ELEMENT    *curr;
-	HHDR	   *hctl;
-	BUCKET_INDEX currIndex;
-	BUCKET_INDEX *prevIndexPtr;
-	char	   *destAddr;
+	HASHSEGMENT	segp;
+	HASHBUCKET currBucket;
+	HASHBUCKET *prevBucketPtr;
+
 	static struct State
 	{
-		ELEMENT    *currElem;
-		BUCKET_INDEX currIndex;
-		BUCKET_INDEX *prevIndex;
+		HASHBUCKET currBucket;
+		HASHBUCKET *prevBucketPtr;
 	}			saveState;
 
-	Assert((hashp && keyPtr));
-	Assert((action == HASH_FIND) || (action == HASH_REMOVE) || (action == HASH_ENTER) || (action == HASH_FIND_SAVE) || (action == HASH_REMOVE_SAVED));
+	Assert(hashp);
+	Assert(keyPtr);
+	Assert((action == HASH_FIND) ||
+		   (action == HASH_REMOVE) ||
+		   (action == HASH_ENTER) ||
+		   (action == HASH_FIND_SAVE) ||
+		   (action == HASH_REMOVE_SAVED));
 
 	hctl = hashp->hctl;
 
@@ -598,16 +521,16 @@ hash_search(HTAB *hashp,
 	hash_accesses++;
 	hashp->hctl->accesses++;
 #endif
+
 	if (action == HASH_REMOVE_SAVED)
 	{
-		curr = saveState.currElem;
-		currIndex = saveState.currIndex;
-		prevIndexPtr = saveState.prevIndex;
+		currBucket = saveState.currBucket;
+		prevBucketPtr = saveState.prevBucketPtr;
 
 		/*
 		 * Try to catch subsequent errors
 		 */
-		Assert(saveState.currElem && !(saveState.currElem = 0));
+		Assert(currBucket && !(saveState.currBucket = NULL));
 	}
 	else
 	{
@@ -615,25 +538,22 @@ hash_search(HTAB *hashp,
 		segment_num = bucket >> hctl->sshift;
 		segment_ndx = MOD(bucket, hctl->ssize);
 
-		segp = GET_SEG(hashp, segment_num);
+		segp = hashp->dir[segment_num];
 
 		Assert(segp);
 
-		prevIndexPtr = &segp[segment_ndx];
-		currIndex = *prevIndexPtr;
+		prevBucketPtr = &segp[segment_ndx];
+		currBucket = *prevBucketPtr;
 
 		/*
-		 * Follow collision chain
+		 * Follow collision chain looking for matching key
 		 */
-		for (curr = NULL; currIndex != INVALID_INDEX;)
+		while (currBucket != NULL)
 		{
-			/* coerce bucket index into a pointer */
-			curr = GET_BUCKET(hashp, currIndex);
-
-			if (!memcmp((char *) &(curr->key), keyPtr, hctl->keysize))
+			if (memcmp(ELEMENTKEY(currBucket), keyPtr, hctl->keysize) == 0)
 				break;
-			prevIndexPtr = &(curr->next);
-			currIndex = *prevIndexPtr;
+			prevBucketPtr = &(currBucket->link);
+			currBucket = *prevBucketPtr;
 #if HASH_STATISTICS
 			hash_collisions++;
 			hashp->hctl->collisions++;
@@ -645,48 +565,52 @@ hash_search(HTAB *hashp,
 	 * if we found an entry or if we weren't trying to insert, we're done
 	 * now.
 	 */
-	*foundPtr = (bool) (currIndex != INVALID_INDEX);
+	*foundPtr = (bool) (currBucket != NULL);
+
 	switch (action)
 	{
 		case HASH_ENTER:
-			if (currIndex != INVALID_INDEX)
-				return &(curr->key);
+			if (currBucket != NULL)
+				return (void *) ELEMENTKEY(currBucket);
 			break;
+
 		case HASH_REMOVE:
 		case HASH_REMOVE_SAVED:
-			if (currIndex != INVALID_INDEX)
+			if (currBucket != NULL)
 			{
-				Assert(hctl->nkeys > 0);
-				hctl->nkeys--;
+				Assert(hctl->nentries > 0);
+				hctl->nentries--;
 
 				/* remove record from hash bucket's chain. */
-				*prevIndexPtr = curr->next;
+				*prevBucketPtr = currBucket->link;
 
 				/* add the record to the freelist for this table.  */
-				curr->next = hctl->freeBucketIndex;
-				hctl->freeBucketIndex = currIndex;
+				currBucket->link = hctl->freeList;
+				hctl->freeList = currBucket;
 
 				/*
 				 * better hope the caller is synchronizing access to this
 				 * element, because someone else is going to reuse it the
 				 * next time something is added to the table
 				 */
-				return &(curr->key);
+				return (void *) ELEMENTKEY(currBucket);
 			}
-			return (long *) TRUE;
+			return (void *) TRUE;
+
 		case HASH_FIND:
-			if (currIndex != INVALID_INDEX)
-				return &(curr->key);
-			return (long *) TRUE;
+			if (currBucket != NULL)
+				return (void *) ELEMENTKEY(currBucket);
+			return (void *) TRUE;
+
 		case HASH_FIND_SAVE:
-			if (currIndex != INVALID_INDEX)
+			if (currBucket != NULL)
 			{
-				saveState.currElem = curr;
-				saveState.prevIndex = prevIndexPtr;
-				saveState.currIndex = currIndex;
-				return &(curr->key);
+				saveState.currBucket = currBucket;
+				saveState.prevBucketPtr = prevBucketPtr;
+				return (void *) ELEMENTKEY(currBucket);
 			}
-			return (long *) TRUE;
+			return (void *) TRUE;
+
 		default:
 			/* can't get here */
 			return NULL;
@@ -696,39 +620,36 @@ hash_search(HTAB *hashp,
 	 * If we got here, then we didn't find the element and we have to
 	 * insert it into the hash table
 	 */
-	Assert(currIndex == INVALID_INDEX);
+	Assert(currBucket == NULL);
 
 	/* get the next free bucket */
-	currIndex = hctl->freeBucketIndex;
-	if (currIndex == INVALID_INDEX)
+	currBucket = hctl->freeList;
+	if (currBucket == NULL)
 	{
 		/* no free elements.  allocate another chunk of buckets */
-		if (!bucket_alloc(hashp))
+		if (!element_alloc(hashp))
 			return NULL;
-		currIndex = hctl->freeBucketIndex;
+		currBucket = hctl->freeList;
 	}
-	Assert(currIndex != INVALID_INDEX);
+	Assert(currBucket != NULL);
 
-	curr = GET_BUCKET(hashp, currIndex);
-	hctl->freeBucketIndex = curr->next;
+	hctl->freeList = currBucket->link;
 
 	/* link into chain */
-	*prevIndexPtr = currIndex;
+	*prevBucketPtr = currBucket;
+	currBucket->link = NULL;
 
 	/* copy key into record */
-	destAddr = (char *) &(curr->key);
-	memmove(destAddr, keyPtr, hctl->keysize);
-	curr->next = INVALID_INDEX;
+	memcpy(ELEMENTKEY(currBucket), keyPtr, hctl->keysize);
 
 	/*
 	 * let the caller initialize the data field after hash_search returns.
 	 */
-	/* memmove(destAddr,keyPtr,hctl->keysize+hctl->datasize); */
 
 	/*
 	 * Check if it is time to split the segment
 	 */
-	if (++hctl->nkeys / (hctl->max_bucket + 1) > hctl->ffactor)
+	if (++hctl->nentries / (hctl->max_bucket + 1) > hctl->ffactor)
 	{
 
 		/*
@@ -737,14 +658,15 @@ hash_search(HTAB *hashp,
 		 */
 		expand_table(hashp);
 	}
-	return &(curr->key);
+
+	return (void *) ELEMENTKEY(currBucket);
 }
 
 /*
  * hash_seq_init/_search
  *			Sequentially search through hash table and return
  *			all the elements one by one, return NULL on error and
- *			return (long *) TRUE in the end.
+ *			return (void *) TRUE in the end.
  *
  * NOTE: caller may delete the returned element before continuing the scan.
  * However, deleting any other element while the scan is in progress is
@@ -757,31 +679,31 @@ hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
 {
 	status->hashp = hashp;
 	status->curBucket = 0;
-	status->curIndex = INVALID_INDEX;
+	status->curEntry = NULL;
 }
 
-long *
+void *
 hash_seq_search(HASH_SEQ_STATUS *status)
 {
 	HTAB	   *hashp = status->hashp;
-	HHDR	   *hctl = hashp->hctl;
+	HASHHDR	   *hctl = hashp->hctl;
 
 	while (status->curBucket <= hctl->max_bucket)
 	{
 		long		segment_num;
 		long		segment_ndx;
-		SEGMENT		segp;
+		HASHSEGMENT	segp;
 
-		if (status->curIndex != INVALID_INDEX)
+		if (status->curEntry != NULL)
 		{
 			/* Continuing scan of curBucket... */
-			ELEMENT    *curElem;
+			HASHELEMENT *curElem;
 
-			curElem = GET_BUCKET(hashp, status->curIndex);
-			status->curIndex = curElem->next;
-			if (status->curIndex == INVALID_INDEX)		/* end of this bucket */
+			curElem = status->curEntry;
+			status->curEntry = curElem->link;
+			if (status->curEntry == NULL) /* end of this bucket */
 				++status->curBucket;
-			return &(curElem->key);
+			return (void *) ELEMENTKEY(curElem);
 		}
 
 		/*
@@ -793,10 +715,10 @@ hash_seq_search(HASH_SEQ_STATUS *status)
 		/*
 		 * first find the right segment in the table directory.
 		 */
-		segp = GET_SEG(hashp, segment_num);
+		segp = hashp->dir[segment_num];
 		if (segp == NULL)
 			/* this is probably an error */
-			return (long *) NULL;
+			return NULL;
 
 		/*
 		 * now find the right index into the segment for the first item in
@@ -806,13 +728,13 @@ hash_seq_search(HASH_SEQ_STATUS *status)
 		 * directory of valid stuff.  if there are elements in the bucket
 		 * chains that point to the freelist we're in big trouble.
 		 */
-		status->curIndex = segp[segment_ndx];
+		status->curEntry = segp[segment_ndx];
 
-		if (status->curIndex == INVALID_INDEX)	/* empty bucket */
+		if (status->curEntry == NULL) /* empty bucket */
 			++status->curBucket;
 	}
 
-	return (long *) TRUE;		/* out of buckets */
+	return (void *) TRUE;		/* out of buckets */
 }
 
 
@@ -821,11 +743,11 @@ hash_seq_search(HASH_SEQ_STATUS *status)
 /*
  * Expand the table by adding one more hash bucket.
  */
-static int
+static bool
 expand_table(HTAB *hashp)
 {
-	HHDR	   *hctl;
-	SEGMENT		old_seg,
+	HASHHDR	   *hctl = hashp->hctl;
+	HASHSEGMENT	old_seg,
 				new_seg;
 	long		old_bucket,
 				new_bucket;
@@ -833,18 +755,15 @@ expand_table(HTAB *hashp)
 				new_segndx;
 	long		old_segnum,
 				old_segndx;
-	ELEMENT    *chain;
-	BUCKET_INDEX *old,
-			   *newbi;
-	BUCKET_INDEX chainIndex,
-				nextIndex;
+	HASHBUCKET *oldlink,
+			   *newlink;
+	HASHBUCKET currElement,
+				nextElement;
 
 #ifdef HASH_STATISTICS
 	hash_expansions++;
 #endif
 
-	hctl = hashp->hctl;
-
 	new_bucket = hctl->max_bucket + 1;
 	new_segnum = new_bucket >> hctl->sshift;
 	new_segndx = MOD(new_bucket, hctl->ssize);
@@ -854,9 +773,9 @@ expand_table(HTAB *hashp)
 		/* Allocate new segment if necessary -- could fail if dir full */
 		if (new_segnum >= hctl->dsize)
 			if (!dir_realloc(hashp))
-				return 0;
+				return false;
 		if (!(hashp->dir[new_segnum] = seg_alloc(hashp)))
-			return 0;
+			return false;
 		hctl->nsegs++;
 	}
 
@@ -890,137 +809,118 @@ expand_table(HTAB *hashp)
 	old_segnum = old_bucket >> hctl->sshift;
 	old_segndx = MOD(old_bucket, hctl->ssize);
 
-	old_seg = GET_SEG(hashp, old_segnum);
-	new_seg = GET_SEG(hashp, new_segnum);
+	old_seg = hashp->dir[old_segnum];
+	new_seg = hashp->dir[new_segnum];
 
-	old = &old_seg[old_segndx];
-	newbi = &new_seg[new_segndx];
-	for (chainIndex = *old;
-		 chainIndex != INVALID_INDEX;
-		 chainIndex = nextIndex)
+	oldlink = &old_seg[old_segndx];
+	newlink = &new_seg[new_segndx];
+
+	for (currElement = *oldlink;
+		 currElement != NULL;
+		 currElement = nextElement)
 	{
-		chain = GET_BUCKET(hashp, chainIndex);
-		nextIndex = chain->next;
-		if ((long) call_hash(hashp, (char *) &(chain->key)) == old_bucket)
+		nextElement = currElement->link;
+		if ((long) call_hash(hashp, (void *) ELEMENTKEY(currElement))
+			== old_bucket)
 		{
-			*old = chainIndex;
-			old = &chain->next;
+			*oldlink = currElement;
+			oldlink = &currElement->link;
 		}
 		else
 		{
-			*newbi = chainIndex;
-			newbi = &chain->next;
+			*newlink = currElement;
+			newlink = &currElement->link;
 		}
 	}
 	/* don't forget to terminate the rebuilt hash chains... */
-	*old = INVALID_INDEX;
-	*newbi = INVALID_INDEX;
-	return 1;
+	*oldlink = NULL;
+	*newlink = NULL;
+
+	return true;
 }
 
 
-static int
+static bool
 dir_realloc(HTAB *hashp)
 {
-	char	   *p;
-	char	   *old_p;
+	HASHSEGMENT *p;
+	HASHSEGMENT *old_p;
 	long		new_dsize;
 	long		old_dirsize;
 	long		new_dirsize;
 
 	if (hashp->hctl->max_dsize != NO_MAX_DSIZE)
-		return 0;
+		return false;
 
 	/* Reallocate directory */
 	new_dsize = hashp->hctl->dsize << 1;
-	old_dirsize = hashp->hctl->dsize * sizeof(SEG_OFFSET);
-	new_dirsize = new_dsize * sizeof(SEG_OFFSET);
+	old_dirsize = hashp->hctl->dsize * sizeof(HASHSEGMENT);
+	new_dirsize = new_dsize * sizeof(HASHSEGMENT);
 
+	old_p = hashp->dir;
 	CurrentDynaHashCxt = hashp->hcxt;
-	old_p = (char *) hashp->dir;
-	p = (char *) hashp->alloc((Size) new_dirsize);
+	p = (HASHSEGMENT *) hashp->alloc((Size) new_dirsize);
 
 	if (p != NULL)
 	{
-		memmove(p, old_p, old_dirsize);
-		MemSet(p + old_dirsize, 0, new_dirsize - old_dirsize);
+		memcpy(p, old_p, old_dirsize);
+		MemSet(((char *) p) + old_dirsize, 0, new_dirsize - old_dirsize);
 		MEM_FREE((char *) old_p);
-		hashp->dir = (SEG_OFFSET *) p;
+		hashp->dir = p;
 		hashp->hctl->dsize = new_dsize;
-		return 1;
+		return true;
 	}
-	return 0;
+
+	return false;
 }
 
 
-static SEG_OFFSET
+static HASHSEGMENT
 seg_alloc(HTAB *hashp)
 {
-	SEGMENT		segp;
-	SEG_OFFSET	segOffset;
+	HASHSEGMENT	segp;
 
 	CurrentDynaHashCxt = hashp->hcxt;
-	segp = (SEGMENT) hashp->alloc(sizeof(BUCKET_INDEX) * hashp->hctl->ssize);
+	segp = (HASHSEGMENT) hashp->alloc(sizeof(HASHBUCKET) * hashp->hctl->ssize);
 
 	if (!segp)
-		return 0;
+		return NULL;
 
-	MemSet((char *) segp, 0,
-		   (long) sizeof(BUCKET_INDEX) * hashp->hctl->ssize);
+	MemSet(segp, 0, sizeof(HASHBUCKET) * hashp->hctl->ssize);
 
-	segOffset = MAKE_HASHOFFSET(hashp, segp);
-	return segOffset;
+	return segp;
 }
 
 /*
- * allocate some new buckets and link them into the free list
+ * allocate some new elements and link them into the free list
  */
-static int
-bucket_alloc(HTAB *hashp)
+static bool
+element_alloc(HTAB *hashp)
 {
+	HASHHDR	   *hctl = hashp->hctl;
+	Size		elementSize;
+	HASHELEMENT *tmpElement;
 	int			i;
-	ELEMENT    *tmpBucket;
-	long		bucketSize;
-	BUCKET_INDEX tmpIndex,
-				lastIndex;
-
-	/* Each bucket has a BUCKET_INDEX header plus user data. */
-	bucketSize = sizeof(BUCKET_INDEX) + hashp->hctl->keysize + hashp->hctl->datasize;
 
-	/* make sure its aligned correctly */
-	bucketSize = MAXALIGN(bucketSize);
+	/* Each element has a HASHELEMENT header plus user data. */
+	elementSize = MAXALIGN(sizeof(HASHELEMENT)) + MAXALIGN(hctl->entrysize);
 
 	CurrentDynaHashCxt = hashp->hcxt;
-	tmpBucket = (ELEMENT *) hashp->alloc(BUCKET_ALLOC_INCR * bucketSize);
-
-	if (!tmpBucket)
-		return 0;
+	tmpElement = (HASHELEMENT *)
+		hashp->alloc(HASHELEMENT_ALLOC_INCR * elementSize);
 
-	/* tmpIndex is the shmem offset into the first bucket of the array */
-	tmpIndex = MAKE_HASHOFFSET(hashp, tmpBucket);
+	if (!tmpElement)
+		return false;
 
-	/* set the freebucket list to point to the first bucket */
-	lastIndex = hashp->hctl->freeBucketIndex;
-	hashp->hctl->freeBucketIndex = tmpIndex;
-
-	/*
-	 * initialize each bucket to point to the one behind it. NOTE: loop
-	 * sets last bucket incorrectly; we fix below.
-	 */
-	for (i = 0; i < BUCKET_ALLOC_INCR; i++)
+	/* link all the new entries into the freelist */
+	for (i = 0; i < HASHELEMENT_ALLOC_INCR; i++)
 	{
-		tmpBucket = GET_BUCKET(hashp, tmpIndex);
-		tmpIndex += bucketSize;
-		tmpBucket->next = tmpIndex;
+		tmpElement->link = hctl->freeList;
+		hctl->freeList = tmpElement;
+		tmpElement = (HASHELEMENT *) (((char *) tmpElement) + elementSize);
 	}
 
-	/*
-	 * the last bucket points to the old freelist head (which is probably
-	 * invalid or we wouldn't be here)
-	 */
-	tmpBucket->next = lastIndex;
-
-	return 1;
+	return true;
 }
 
 /* calculate ceil(log base 2) of num */
diff --git a/src/backend/utils/hash/hashfn.c b/src/backend/utils/hash/hashfn.c
index 889837b528d7610b9e4ee1e2c29473bc10eee285..958deee804f8133b28bec6fbb5a45b436016a2ae 100644
--- a/src/backend/utils/hash/hashfn.c
+++ b/src/backend/utils/hash/hashfn.c
@@ -1,6 +1,7 @@
 /*-------------------------------------------------------------------------
  *
  * hashfn.c
+ *		Hash functions for use in dynahash.c hashtables
  *
  *
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
@@ -8,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/hash/hashfn.c,v 1.13 2001/01/24 19:43:15 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/hash/hashfn.c,v 1.14 2001/10/01 05:36:16 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -17,155 +18,100 @@
 #include "utils/hsearch.h"
 
 /*
- * Assume that we've already split the bucket to which this
- * key hashes, calculate that bucket, and check that in fact
- * we did already split it.
+ * string_hash: hash function for keys that are null-terminated strings.
+ *
+ * NOTE: since dynahash.c backs this up with a fixed-length memcmp(),
+ * the key must actually be zero-padded to the specified maximum length
+ * to work correctly.  However, if it is known that nothing after the
+ * first zero byte is interesting, this is the right hash function to use.
+ *
+ * NOTE: this is the default hash function if none is specified.
  */
 long
-string_hash(char *key, int keysize)
+string_hash(void *key, int keysize)
 {
-	int			h;
 	unsigned char *k = (unsigned char *) key;
+	long		h = 0;
 
-	h = 0;
-
-	/*
-	 * Convert string to integer
-	 */
 	while (*k)
-		h = h * PRIME1 ^ (*k++ - ' ');
+		h = (h * PRIME1) ^ (*k++);
+
 	h %= PRIME2;
 
 	return h;
 }
 
-
+/*
+ * tag_hash: hash function for fixed-size tag values
+ *
+ * NB: we assume that the supplied key is aligned at least on an 'int'
+ * boundary, if its size is >= sizeof(int).
+ */
 long
-tag_hash(int *key, int keysize)
+tag_hash(void *key, int keysize)
 {
+	int		   *k = (int *) key;
 	long		h = 0;
 
 	/*
-	 * Convert tag to integer;	Use four byte chunks in a "jump table" to
-	 * go a little faster.	Currently the maximum keysize is 16 (mar 17
-	 * 1992) I have put in cases for up to 24.	Bigger than this will
-	 * resort to the old behavior of the for loop. (see the default case).
+	 * Use four byte chunks in a "jump table" to go a little faster.
+	 *
+	 * Currently the maximum keysize is 16 (mar 17 1992).  I have put in
+	 * cases for up to 32.  Bigger than this will resort to a for loop
+	 * (see the default case).
 	 */
 	switch (keysize)
 	{
+		case 8 * sizeof(int):
+			h = (h * PRIME1) ^ (*k++);
+			/* fall through */
+
+		case 7 * sizeof(int):
+			h = (h * PRIME1) ^ (*k++);
+			/* fall through */
+
 		case 6 * sizeof(int):
-			h = h * PRIME1 ^ (*key);
-			key++;
+			h = (h * PRIME1) ^ (*k++);
 			/* fall through */
 
 		case 5 * sizeof(int):
-			h = h * PRIME1 ^ (*key);
-			key++;
+			h = (h * PRIME1) ^ (*k++);
 			/* fall through */
 
 		case 4 * sizeof(int):
-			h = h * PRIME1 ^ (*key);
-			key++;
+			h = (h * PRIME1) ^ (*k++);
 			/* fall through */
 
 		case 3 * sizeof(int):
-			h = h * PRIME1 ^ (*key);
-			key++;
+			h = (h * PRIME1) ^ (*k++);
 			/* fall through */
 
 		case 2 * sizeof(int):
-			h = h * PRIME1 ^ (*key);
-			key++;
+			h = (h * PRIME1) ^ (*k++);
 			/* fall through */
 
 		case sizeof(int):
-			h = h * PRIME1 ^ (*key);
-			key++;
+			h = (h * PRIME1) ^ (*k++);
 			break;
 
 		default:
-			for (; keysize >= (int) sizeof(int); keysize -= sizeof(int), key++)
-				h = h * PRIME1 ^ (*key);
-
-			/*
-			 * now let's grab the last few bytes of the tag if the tag has
-			 * (size % 4) != 0 (which it sometimes will on a sun3).
-			 */
-			if (keysize)
+			/* Do an int at a time */
+			for (; keysize >= (int) sizeof(int); keysize -= sizeof(int))
+				h = (h * PRIME1) ^ (*k++);
+
+			/* Cope with any partial-int leftover bytes */
+			if (keysize > 0)
 			{
-				char	   *keytmp = (char *) key;
-
-				switch (keysize)
-				{
-					case 3:
-						h = h * PRIME1 ^ (*keytmp);
-						keytmp++;
-						/* fall through */
-					case 2:
-						h = h * PRIME1 ^ (*keytmp);
-						keytmp++;
-						/* fall through */
-					case 1:
-						h = h * PRIME1 ^ (*keytmp);
-						break;
-				}
+				unsigned char   *keybyte = (unsigned char *) k;
+
+				do
+					h = (h * PRIME1) ^ (*keybyte++);
+				while (--keysize > 0);
 			}
 			break;
 	}
 
 	h %= PRIME2;
-	return h;
-}
-
-/*
- * This is INCREDIBLY ugly, but fast.
- * We break the string up into 8 byte units.  On the first time
- * through the loop we get the "leftover bytes" (strlen % 8).
- * On every other iteration, we perform 8 HASHC's so we handle
- * all 8 bytes.  Essentially, this saves us 7 cmp & branch
- * instructions.  If this routine is heavily used enough, it's
- * worth the ugly coding
- */
-#ifdef NOT_USED
-long
-disk_hash(char *key)
-{
-	int			n = 0;
-	char	   *str = key;
-	int			len = strlen(key);
-	int			loop;
 
-#define HASHC	n = *str++ + 65599 * n
-
-	if (len > 0)
-	{
-		loop = (len + 8 - 1) >> 3;
-
-		switch (len & (8 - 1))
-		{
-			case 0:
-				do
-				{				/* All fall throughs */
-					HASHC;
-			case 7:
-					HASHC;
-			case 6:
-					HASHC;
-			case 5:
-					HASHC;
-			case 4:
-					HASHC;
-			case 3:
-					HASHC;
-			case 2:
-					HASHC;
-			case 1:
-					HASHC;
-				} while (--loop);
-		}
-
-	}
-	return n;
+	return h;
 }
-
-#endif
diff --git a/src/backend/utils/mmgr/portalmem.c b/src/backend/utils/mmgr/portalmem.c
index a5534dc1cded1233521e2e3307e0d84e2c8cf68a..7e1aac193632f3a9017a612a9794657f9610414e 100644
--- a/src/backend/utils/mmgr/portalmem.c
+++ b/src/backend/utils/mmgr/portalmem.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/mmgr/portalmem.c,v 1.41 2001/03/22 04:00:08 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/mmgr/portalmem.c,v 1.42 2001/10/01 05:36:16 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -123,7 +123,7 @@ EnablePortalManager(void)
 										 ALLOCSET_DEFAULT_MAXSIZE);
 
 	ctl.keysize = MAX_PORTALNAME_LEN;
-	ctl.datasize = sizeof(Portal);
+	ctl.entrysize = sizeof(PortalHashEnt);
 
 	/*
 	 * use PORTALS_PER_USER, defined in utils/portal.h as a guess of how
diff --git a/src/include/storage/buf_internals.h b/src/include/storage/buf_internals.h
index f85a93c258ae5a0d4098ba1cd819a804fd3792e0..aa468905bff76f54466a0058f057e8e93da55690 100644
--- a/src/include/storage/buf_internals.h
+++ b/src/include/storage/buf_internals.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: buf_internals.h,v 1.50 2001/09/29 04:02:26 tgl Exp $
+ * $Id: buf_internals.h,v 1.51 2001/10/01 05:36:17 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -115,6 +115,13 @@ typedef struct sbufdesc
 #define BL_IO_IN_PROGRESS	(1 << 0)	/* unimplemented */
 #define BL_PIN_COUNT_LOCK	(1 << 1)
 
+/* entry for buffer hashtable */
+typedef struct
+{
+	BufferTag	key;
+	Buffer		id;
+} BufferLookupEnt;
+
 /*
  *	mao tracing buffer allocation
  */
diff --git a/src/include/storage/lock.h b/src/include/storage/lock.h
index f61f085e191631a739a1e62f62037a6993842b68..7ff9fab32eeca9a9be9df3da987f24623a4b32f5 100644
--- a/src/include/storage/lock.h
+++ b/src/include/storage/lock.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: lock.h,v 1.55 2001/09/30 00:45:48 momjian Exp $
+ * $Id: lock.h,v 1.56 2001/10/01 05:36:17 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -169,9 +169,6 @@ typedef struct LOCK
 	int			nGranted;		/* total of granted[] array */
 } LOCK;
 
-#define SHMEM_LOCKTAB_KEYSIZE  sizeof(LOCKTAG)
-#define SHMEM_LOCKTAB_DATASIZE (sizeof(LOCK) - SHMEM_LOCKTAB_KEYSIZE)
-
 #define LOCK_LOCKMETHOD(lock) ((lock).tag.lockmethod)
 
 
@@ -222,9 +219,6 @@ typedef struct HOLDER
 	SHM_QUEUE	procLink;		/* list link for process's list of holders */
 } HOLDER;
 
-#define SHMEM_HOLDERTAB_KEYSIZE  sizeof(HOLDERTAG)
-#define SHMEM_HOLDERTAB_DATASIZE (sizeof(HOLDER) - SHMEM_HOLDERTAB_KEYSIZE)
-
 #define HOLDER_LOCKMETHOD(holder) \
 		(((LOCK *) MAKE_PTR((holder).tag.lock))->tag.lockmethod)
 
diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h
index 1043beb63489f1a7c146eb289b30bec49c9e596b..a7ca140382dfea02970500af54c411d6973e7b67 100644
--- a/src/include/storage/shmem.h
+++ b/src/include/storage/shmem.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: shmem.h,v 1.31 2001/09/29 04:02:27 tgl Exp $
+ * $Id: shmem.h,v 1.32 2001/10/01 05:36:17 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -73,9 +73,7 @@ extern void *ShmemInitStruct(char *name, Size size, bool *foundPtr);
 
 /* size constants for the shmem index table */
  /* max size of data structure string name */
-#define SHMEM_INDEX_KEYSIZE (50)
- /* data in shmem index table hash bucket */
-#define SHMEM_INDEX_DATASIZE (sizeof(ShmemIndexEnt) - SHMEM_INDEX_KEYSIZE)
+#define SHMEM_INDEX_KEYSIZE		 (48)
  /* maximum size of the shmem index table */
 #define SHMEM_INDEX_SIZE		 (100)
 
diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h
index 2f9d99e037447d2c257a9e84a45d8a3e98840580..5b65e3ee23e5eca1691369edbda5631a3600d7ab 100644
--- a/src/include/utils/hsearch.h
+++ b/src/include/utils/hsearch.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: hsearch.h,v 1.20 2001/06/22 19:16:24 wieck Exp $
+ * $Id: hsearch.h,v 1.21 2001/10/01 05:36:17 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -31,31 +31,32 @@
  * tables, the initial directory size can be left at the default.
  */
 #define DEF_SEGSIZE			   256
-#define DEF_SEGSIZE_SHIFT	   8/* must be log2(DEF_SEGSIZE) */
+#define DEF_SEGSIZE_SHIFT	   8		/* must be log2(DEF_SEGSIZE) */
 #define DEF_DIRSIZE			   256
-#define DEF_FFACTOR			   1/* default fill factor */
+#define DEF_FFACTOR			   1		/* default fill factor */
 
 #define PRIME1				   37		/* for the hash function */
 #define PRIME2				   1048583
 
 
 /*
- * Hash bucket is actually bigger than this.  Key field can have
- * variable length and a variable length data field follows it.
+ * HASHELEMENT is the private part of a hashtable entry.  The caller's data
+ * follows the HASHELEMENT structure (on a MAXALIGN'd boundary).  The hash key
+ * is expected to be at the start of the caller's hash entry structure.
  */
-typedef struct element
+typedef struct HASHELEMENT
 {
-	unsigned long next;			/* secret from user */
-	long		key;
-} ELEMENT;
+	struct HASHELEMENT *link;	/* link to next entry in same bucket */
+} HASHELEMENT;
 
-typedef unsigned long BUCKET_INDEX;
+/* A hash bucket is a linked list of HASHELEMENTs */
+typedef HASHELEMENT *HASHBUCKET;
 
-/* segment is an array of bucket pointers */
-typedef BUCKET_INDEX *SEGMENT;
-typedef unsigned long SEG_OFFSET;
+/* A hash segment is an array of bucket headers */
+typedef HASHBUCKET *HASHSEGMENT;
 
-typedef struct hashhdr
+/* Header structure for a hash table --- contains all changeable info */
+typedef struct HASHHDR
 {
 	long		dsize;			/* Directory Size */
 	long		ssize;			/* Segment Size --- must be power of 2 */
@@ -64,65 +65,66 @@ typedef struct hashhdr
 	long		high_mask;		/* Mask to modulo into entire table */
 	long		low_mask;		/* Mask to modulo into lower half of table */
 	long		ffactor;		/* Fill factor */
-	long		nkeys;			/* Number of keys in hash table */
+	long		nentries;		/* Number of entries in hash table */
 	long		nsegs;			/* Number of allocated segments */
 	long		keysize;		/* hash key length in bytes */
-	long		datasize;		/* elem data length in bytes */
+	long		entrysize;		/* total user element size in bytes */
 	long		max_dsize;		/* 'dsize' limit if directory is fixed
 								 * size */
-	BUCKET_INDEX freeBucketIndex;		/* index of first free bucket */
+	HASHELEMENT *freeList;		/* linked list of free elements */
 #ifdef HASH_STATISTICS
 	long		accesses;
 	long		collisions;
 #endif
-} HHDR;
+} HASHHDR;
 
-typedef struct htab
+/*
+ * Top control structure for a hashtable --- need not be shared, since
+ * no fields change at runtime
+ */
+typedef struct HTAB
 {
-	HHDR	   *hctl;			/* shared control information */
-	long		(*hash) ();		/* Hash Function */
-	char	   *segbase;		/* segment base address for calculating
-								 * pointer values */
-	SEG_OFFSET *dir;			/* 'directory' of segm starts */
+	HASHHDR	   *hctl;			/* shared control information */
+	long		(*hash) (void *key, int keysize); /* Hash Function */
+	HASHSEGMENT *dir;			/* directory of segment starts */
 	void	   *(*alloc) (Size);/* memory allocator */
 	MemoryContext hcxt;			/* memory context if default allocator used */
 } HTAB;
 
-typedef struct hashctl
+/* Parameter data structure for hash_create */
+/* Only those fields indicated by hash_flags need be set */
+typedef struct HASHCTL
 {
 	long		ssize;			/* Segment Size */
-	long		dsize;			/* Dirsize Size */
+	long		dsize;			/* (initial) Directory Size */
 	long		ffactor;		/* Fill factor */
-	long		(*hash) ();		/* Hash Function */
+	long		(*hash) (void *key, int keysize); /* Hash Function */
 	long		keysize;		/* hash key length in bytes */
-	long		datasize;		/* elem data length in bytes */
+	long		entrysize;		/* total user element size in bytes */
 	long		max_dsize;		/* limit to dsize if directory size is
 								 * limited */
-	long	   *segbase;		/* base for calculating bucket + seg ptrs */
 	void	   *(*alloc) (Size);/* memory allocation function */
-	long	   *dir;			/* directory if allocated already */
-	long	   *hctl;			/* location of header information in shd
-								 * mem */
-	MemoryContext hcxt;			/* memory context to use for all allocations */
+	HASHSEGMENT *dir;			/* directory of segment starts */
+	HASHHDR	   *hctl;			/* location of header in shared mem */
+	MemoryContext hcxt;			/* memory context to use for allocations */
 } HASHCTL;
 
-/* Flags to indicate action for hctl */
+/* Flags to indicate which parameters are supplied */
 #define HASH_SEGMENT	0x002	/* Setting segment size */
 #define HASH_DIRSIZE	0x004	/* Setting directory size */
 #define HASH_FFACTOR	0x008	/* Setting fill factor */
 #define HASH_FUNCTION	0x010	/* Set user defined hash function */
-#define HASH_ELEM		0x020	/* Setting key/data size */
+#define HASH_ELEM		0x020	/* Setting key/entry size */
 #define HASH_SHARED_MEM 0x040	/* Setting shared mem const */
 #define HASH_ATTACH		0x080	/* Do not initialize hctl */
 #define HASH_ALLOC		0x100	/* Setting memory allocator */
 #define HASH_CONTEXT	0x200	/* Setting explicit memory context */
 
 
-/* seg_alloc assumes that INVALID_INDEX is 0 */
-#define INVALID_INDEX			(0)
+/* max_dsize value to indicate expansible directory */
 #define NO_MAX_DSIZE			(-1)
-/* number of hash buckets allocated at once */
-#define BUCKET_ALLOC_INCR		(30)
+/* number of hash elements allocated at once */
+#define HASHELEMENT_ALLOC_INCR	(32)
 
 /* hash_search operations */
 typedef enum
@@ -138,27 +140,27 @@ typedef enum
 typedef struct
 {
 	HTAB	   *hashp;
-	long		curBucket;
-	BUCKET_INDEX curIndex;
+	long		curBucket;		/* index of current bucket */
+	HASHELEMENT *curEntry;		/* current entry in bucket */
 } HASH_SEQ_STATUS;
 
 /*
- * prototypes from functions in dynahash.c
+ * prototypes for functions in dynahash.c
  */
-extern HTAB *hash_create(int nelem, HASHCTL *info, int flags);
+extern HTAB *hash_create(long nelem, HASHCTL *info, int flags);
 extern void hash_destroy(HTAB *hashp);
 extern void hash_stats(char *where, HTAB *hashp);
-extern long *hash_search(HTAB *hashp, char *keyPtr, HASHACTION action,
+extern void *hash_search(HTAB *hashp, void *keyPtr, HASHACTION action,
 			bool *foundPtr);
 extern void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp);
-extern long *hash_seq_search(HASH_SEQ_STATUS *status);
-extern long hash_estimate_size(long num_entries, long keysize, long datasize);
+extern void *hash_seq_search(HASH_SEQ_STATUS *status);
+extern long hash_estimate_size(long num_entries, long entrysize);
 extern long hash_select_dirsize(long num_entries);
 
 /*
- * prototypes from functions in hashfn.c
+ * prototypes for functions in hashfn.c
  */
-extern long string_hash(char *key, int keysize);
-extern long tag_hash(int *key, int keysize);
+extern long string_hash(void *key, int keysize);
+extern long tag_hash(void *key, int keysize);
 
 #endif	 /* HSEARCH_H */