mirror of
https://github.com/postgres/postgres.git
synced 2025-09-02 04:21:28 +03:00
Improve hash_create()'s API for some added robustness.
Invent a new flag bit HASH_STRINGS to specify C-string hashing, which
was formerly the default; and add assertions insisting that exactly
one of the bits HASH_STRINGS, HASH_BLOBS, and HASH_FUNCTION be set.
This is in hopes of preventing recurrences of the type of oversight
fixed in commit a1b8aa1e4
(i.e., mistakenly omitting HASH_BLOBS).
Also, when HASH_STRINGS is specified, insist that the keysize be
more than 8 bytes. This is a heuristic, but it should catch
accidental use of HASH_STRINGS for integer or pointer keys.
(Nearly all existing use-cases set the keysize to NAMEDATALEN or
more, so there's little reason to think this restriction should
be problematic.)
Tweak hash_create() to insist that the HASH_ELEM flag be set, and
remove the defaults it had for keysize and entrysize. Since those
defaults were undocumented and basically useless, no callers
omitted HASH_ELEM anyway.
Also, remove memset's zeroing the HASHCTL parameter struct from
those callers that had one. This has never been really necessary,
and while it wasn't a bad coding convention it was confusing that
some callers did it and some did not. We might as well save a few
cycles by standardizing on "not".
Also improve the documentation for hash_create().
In passing, improve reinit.c's usage of a hash table by storing
the key as a binary Oid rather than a string; and, since that's
a temporary hash table, allocate it in CurrentMemoryContext for
neatness.
Discussion: https://postgr.es/m/590625.1607878171@sss.pgh.pa.us
This commit is contained in:
@@ -2505,7 +2505,6 @@ InitBufferPoolAccess(void)
|
||||
|
||||
memset(&PrivateRefCountArray, 0, sizeof(PrivateRefCountArray));
|
||||
|
||||
MemSet(&hash_ctl, 0, sizeof(hash_ctl));
|
||||
hash_ctl.keysize = sizeof(int32);
|
||||
hash_ctl.entrysize = sizeof(PrivateRefCountEntry);
|
||||
|
||||
|
@@ -465,7 +465,6 @@ InitLocalBuffers(void)
|
||||
}
|
||||
|
||||
/* Create the lookup hash table */
|
||||
MemSet(&info, 0, sizeof(info));
|
||||
info.keysize = sizeof(BufferTag);
|
||||
info.entrysize = sizeof(LocalBufferLookupEnt);
|
||||
|
||||
|
@@ -30,7 +30,7 @@ static void ResetUnloggedRelationsInDbspaceDir(const char *dbspacedirname,
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char oid[OIDCHARS + 1];
|
||||
Oid reloid; /* hash key */
|
||||
} unlogged_relation_entry;
|
||||
|
||||
/*
|
||||
@@ -172,10 +172,11 @@ ResetUnloggedRelationsInDbspaceDir(const char *dbspacedirname, int op)
|
||||
* need to be reset. Otherwise, this cleanup operation would be
|
||||
* O(n^2).
|
||||
*/
|
||||
memset(&ctl, 0, sizeof(ctl));
|
||||
ctl.keysize = sizeof(unlogged_relation_entry);
|
||||
ctl.keysize = sizeof(Oid);
|
||||
ctl.entrysize = sizeof(unlogged_relation_entry);
|
||||
hash = hash_create("unlogged hash", 32, &ctl, HASH_ELEM);
|
||||
ctl.hcxt = CurrentMemoryContext;
|
||||
hash = hash_create("unlogged relation OIDs", 32, &ctl,
|
||||
HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
|
||||
|
||||
/* Scan the directory. */
|
||||
dbspace_dir = AllocateDir(dbspacedirname);
|
||||
@@ -198,9 +199,8 @@ ResetUnloggedRelationsInDbspaceDir(const char *dbspacedirname, int op)
|
||||
* Put the OID portion of the name into the hash table, if it
|
||||
* isn't already.
|
||||
*/
|
||||
memset(ent.oid, 0, sizeof(ent.oid));
|
||||
memcpy(ent.oid, de->d_name, oidchars);
|
||||
hash_search(hash, &ent, HASH_ENTER, NULL);
|
||||
ent.reloid = atooid(de->d_name);
|
||||
(void) hash_search(hash, &ent, HASH_ENTER, NULL);
|
||||
}
|
||||
|
||||
/* Done with the first pass. */
|
||||
@@ -224,7 +224,6 @@ ResetUnloggedRelationsInDbspaceDir(const char *dbspacedirname, int op)
|
||||
{
|
||||
ForkNumber forkNum;
|
||||
int oidchars;
|
||||
bool found;
|
||||
unlogged_relation_entry ent;
|
||||
|
||||
/* Skip anything that doesn't look like a relation data file. */
|
||||
@@ -238,14 +237,10 @@ ResetUnloggedRelationsInDbspaceDir(const char *dbspacedirname, int op)
|
||||
|
||||
/*
|
||||
* See whether the OID portion of the name shows up in the hash
|
||||
* table.
|
||||
* table. If so, nuke it!
|
||||
*/
|
||||
memset(ent.oid, 0, sizeof(ent.oid));
|
||||
memcpy(ent.oid, de->d_name, oidchars);
|
||||
hash_search(hash, &ent, HASH_FIND, &found);
|
||||
|
||||
/* If so, nuke it! */
|
||||
if (found)
|
||||
ent.reloid = atooid(de->d_name);
|
||||
if (hash_search(hash, &ent, HASH_FIND, NULL))
|
||||
{
|
||||
snprintf(rm_path, sizeof(rm_path), "%s/%s",
|
||||
dbspacedirname, de->d_name);
|
||||
|
@@ -292,7 +292,6 @@ void
|
||||
InitShmemIndex(void)
|
||||
{
|
||||
HASHCTL info;
|
||||
int hash_flags;
|
||||
|
||||
/*
|
||||
* Create the shared memory shmem index.
|
||||
@@ -304,11 +303,11 @@ InitShmemIndex(void)
|
||||
*/
|
||||
info.keysize = SHMEM_INDEX_KEYSIZE;
|
||||
info.entrysize = sizeof(ShmemIndexEnt);
|
||||
hash_flags = HASH_ELEM;
|
||||
|
||||
ShmemIndex = ShmemInitHash("ShmemIndex",
|
||||
SHMEM_INDEX_SIZE, SHMEM_INDEX_SIZE,
|
||||
&info, hash_flags);
|
||||
&info,
|
||||
HASH_ELEM | HASH_STRINGS);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -329,6 +328,11 @@ InitShmemIndex(void)
|
||||
* whose maximum size is certain, this should be equal to max_size; that
|
||||
* ensures that no run-time out-of-shared-memory failures can occur.
|
||||
*
|
||||
* *infoP and hash_flags must specify at least the entry sizes and key
|
||||
* comparison semantics (see hash_create()). Flag bits and values specific
|
||||
* to shared-memory hash tables are added here, except that callers may
|
||||
* choose to specify HASH_PARTITION and/or HASH_FIXED_SIZE.
|
||||
*
|
||||
* Note: before Postgres 9.0, this function returned NULL for some failure
|
||||
* cases. Now, it always throws error instead, so callers need not check
|
||||
* for NULL.
|
||||
|
@@ -81,7 +81,6 @@ InitRecoveryTransactionEnvironment(void)
|
||||
* Initialize the hash table for tracking the list of locks held by each
|
||||
* transaction.
|
||||
*/
|
||||
memset(&hash_ctl, 0, sizeof(hash_ctl));
|
||||
hash_ctl.keysize = sizeof(TransactionId);
|
||||
hash_ctl.entrysize = sizeof(RecoveryLockListsEntry);
|
||||
RecoveryLockLists = hash_create("RecoveryLockLists",
|
||||
|
@@ -419,7 +419,6 @@ InitLocks(void)
|
||||
* Allocate hash table for LOCK structs. This stores per-locked-object
|
||||
* information.
|
||||
*/
|
||||
MemSet(&info, 0, sizeof(info));
|
||||
info.keysize = sizeof(LOCKTAG);
|
||||
info.entrysize = sizeof(LOCK);
|
||||
info.num_partitions = NUM_LOCK_PARTITIONS;
|
||||
|
@@ -342,7 +342,6 @@ init_lwlock_stats(void)
|
||||
ALLOCSET_DEFAULT_SIZES);
|
||||
MemoryContextAllowInCriticalSection(lwlock_stats_cxt, true);
|
||||
|
||||
MemSet(&ctl, 0, sizeof(ctl));
|
||||
ctl.keysize = sizeof(lwlock_stats_key);
|
||||
ctl.entrysize = sizeof(lwlock_stats);
|
||||
ctl.hcxt = lwlock_stats_cxt;
|
||||
|
@@ -1096,7 +1096,6 @@ InitPredicateLocks(void)
|
||||
* Allocate hash table for PREDICATELOCKTARGET structs. This stores
|
||||
* per-predicate-lock-target information.
|
||||
*/
|
||||
MemSet(&info, 0, sizeof(info));
|
||||
info.keysize = sizeof(PREDICATELOCKTARGETTAG);
|
||||
info.entrysize = sizeof(PREDICATELOCKTARGET);
|
||||
info.num_partitions = NUM_PREDICATELOCK_PARTITIONS;
|
||||
@@ -1129,7 +1128,6 @@ InitPredicateLocks(void)
|
||||
* Allocate hash table for PREDICATELOCK structs. This stores per
|
||||
* xact-lock-of-a-target information.
|
||||
*/
|
||||
MemSet(&info, 0, sizeof(info));
|
||||
info.keysize = sizeof(PREDICATELOCKTAG);
|
||||
info.entrysize = sizeof(PREDICATELOCK);
|
||||
info.hash = predicatelock_hash;
|
||||
@@ -1212,7 +1210,6 @@ InitPredicateLocks(void)
|
||||
* Allocate hash table for SERIALIZABLEXID structs. This stores per-xid
|
||||
* information for serializable transactions which have accessed data.
|
||||
*/
|
||||
MemSet(&info, 0, sizeof(info));
|
||||
info.keysize = sizeof(SERIALIZABLEXIDTAG);
|
||||
info.entrysize = sizeof(SERIALIZABLEXID);
|
||||
|
||||
@@ -1853,7 +1850,6 @@ CreateLocalPredicateLockHash(void)
|
||||
|
||||
/* Initialize the backend-local hash table of parent locks */
|
||||
Assert(LocalPredicateLockHash == NULL);
|
||||
MemSet(&hash_ctl, 0, sizeof(hash_ctl));
|
||||
hash_ctl.keysize = sizeof(PREDICATELOCKTARGETTAG);
|
||||
hash_ctl.entrysize = sizeof(LOCALPREDICATELOCK);
|
||||
LocalPredicateLockHash = hash_create("Local predicate lock",
|
||||
|
@@ -154,7 +154,6 @@ smgropen(RelFileNode rnode, BackendId backend)
|
||||
/* First time through: initialize the hash table */
|
||||
HASHCTL ctl;
|
||||
|
||||
MemSet(&ctl, 0, sizeof(ctl));
|
||||
ctl.keysize = sizeof(RelFileNodeBackend);
|
||||
ctl.entrysize = sizeof(SMgrRelationData);
|
||||
SMgrRelationHash = hash_create("smgr relation table", 400,
|
||||
|
@@ -150,7 +150,6 @@ InitSync(void)
|
||||
ALLOCSET_DEFAULT_SIZES);
|
||||
MemoryContextAllowInCriticalSection(pendingOpsCxt, true);
|
||||
|
||||
MemSet(&hash_ctl, 0, sizeof(hash_ctl));
|
||||
hash_ctl.keysize = sizeof(FileTag);
|
||||
hash_ctl.entrysize = sizeof(PendingFsyncEntry);
|
||||
hash_ctl.hcxt = pendingOpsCxt;
|
||||
|
Reference in New Issue
Block a user