diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2020-12-15 11:38:53 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2020-12-15 11:38:53 -0500 |
commit | b3817f5f774663d55931dd4fab9c5a94a15ae7ab (patch) | |
tree | 2a74193a670d8409ff4c8ff86d58cbbfa1e6a4ce /src/backend/storage | |
parent | a58db3aa10e62e4228aa409ba006014fa07a8ca2 (diff) | |
download | postgresql-b3817f5f774663d55931dd4fab9c5a94a15ae7ab.tar.gz postgresql-b3817f5f774663d55931dd4fab9c5a94a15ae7ab.zip |
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
Diffstat (limited to 'src/backend/storage')
-rw-r--r-- | src/backend/storage/buffer/bufmgr.c | 1 | ||||
-rw-r--r-- | src/backend/storage/buffer/localbuf.c | 1 | ||||
-rw-r--r-- | src/backend/storage/file/reinit.c | 25 | ||||
-rw-r--r-- | src/backend/storage/ipc/shmem.c | 10 | ||||
-rw-r--r-- | src/backend/storage/ipc/standby.c | 1 | ||||
-rw-r--r-- | src/backend/storage/lmgr/lock.c | 1 | ||||
-rw-r--r-- | src/backend/storage/lmgr/lwlock.c | 1 | ||||
-rw-r--r-- | src/backend/storage/lmgr/predicate.c | 4 | ||||
-rw-r--r-- | src/backend/storage/smgr/smgr.c | 1 | ||||
-rw-r--r-- | src/backend/storage/sync/sync.c | 1 |
10 files changed, 17 insertions, 29 deletions
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index ad0d1a9abc0..c5e87071517 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -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); diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c index 6ffd7b33062..cd3475e9e1d 100644 --- a/src/backend/storage/buffer/localbuf.c +++ b/src/backend/storage/buffer/localbuf.c @@ -465,7 +465,6 @@ InitLocalBuffers(void) } /* Create the lookup hash table */ - MemSet(&info, 0, sizeof(info)); info.keysize = sizeof(BufferTag); info.entrysize = sizeof(LocalBufferLookupEnt); diff --git a/src/backend/storage/file/reinit.c b/src/backend/storage/file/reinit.c index 0c2094f7663..8700f7f19a4 100644 --- a/src/backend/storage/file/reinit.c +++ b/src/backend/storage/file/reinit.c @@ -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); diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c index 97716f6aefd..4ef8b18656d 100644 --- a/src/backend/storage/ipc/shmem.c +++ b/src/backend/storage/ipc/shmem.c @@ -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. diff --git a/src/backend/storage/ipc/standby.c b/src/backend/storage/ipc/standby.c index 52b2809dac0..4ea3cf1f5cb 100644 --- a/src/backend/storage/ipc/standby.c +++ b/src/backend/storage/ipc/standby.c @@ -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", diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index d86566f4554..53472dd21ec 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -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; diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index 108e6521796..26bcce97350 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -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; diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index 8a365b400c6..e42e131543a 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -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", diff --git a/src/backend/storage/smgr/smgr.c b/src/backend/storage/smgr/smgr.c index dcc09df0c77..072bdd118fd 100644 --- a/src/backend/storage/smgr/smgr.c +++ b/src/backend/storage/smgr/smgr.c @@ -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, diff --git a/src/backend/storage/sync/sync.c b/src/backend/storage/sync/sync.c index 1d635d596ca..a49588f6b9e 100644 --- a/src/backend/storage/sync/sync.c +++ b/src/backend/storage/sync/sync.c @@ -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; |