> On Mar 18, 2026, at 07:34, Robert Haas <[email protected]> wrote:
> 
> Hi,
> 
> For most memory allocation primitives, we offer a "no OOM" version.
> dshash_find_or_insert is an exception. Here's a small patch to fix
> that. I have some interest in slipping this into v19 even though I am
> submitting it quite late, because it would be useful for
> pg_stash_advice[1]. Let me know what you think about that.
> 
> -- 
> Robert Haas
> EDB: http://www.enterprisedb.com
> 
> [1]  As yet uncommitted. See pg_plan_advice thread.
> <v1-0001-dshash-Make-it-possible-to-suppress-out-of-memory.patch>


I think adding a DSHASH_INSERT_NO_OOM flag is the right choice. As you 
mentioned, we already have other _NO_OOM flags, so this feels consistent with 
existing patterns.

I don’t see any correctness issue with the patch. I just have a couple of minor 
nits.

1
```
@@ -477,14 +485,22 @@ restart:
                         * reacquire all the locks in the right order to avoid 
deadlocks.
                         */
                        LWLockRelease(PARTITION_LOCK(hash_table, 
partition_index));
-                       resize(hash_table, hash_table->size_log2 + 1);
+                       if (!resize(hash_table, hash_table->size_log2 + 1, 
flags))
+                               return NULL;
 
                        goto restart;
                }
 
                /* Finally we can try to insert the new item. */
                item = insert_into_bucket(hash_table, key,
-                                                                 
&BUCKET_FOR_HASH(hash_table, hash));
+                                                                 
&BUCKET_FOR_HASH(hash_table, hash),
+                                                                 flags);
+               if (item == NULL)
+               {
+                       Assert((flags & DSHASH_INSERT_NO_OOM) != 0);
+                       LWLockRelease(PARTITION_LOCK(hash_table, 
partition_index));
+                       return NULL;
+               }
```

When OOM happens, Assert((flags & DSHASH_INSERT_NO_OOM) != 0); makes sense. But 
for resize(), the assert is inside resize(), while for insert_into_bucket(), 
the assert is in the caller. That feels a bit inconsistent to me, and I think 
it hurts readability a little. A reader might wonder why there is no 
corresponding assert after resize() unless they go read the function body.

I think either style is fine, but using the same style in both places would be 
better.

2
```
        /* Allocate the space for the new table. */
-       new_buckets_shared =
-               dsa_allocate_extended(hash_table->area,
-                                                         sizeof(dsa_pointer) * 
new_size,
-                                                         DSA_ALLOC_HUGE | 
DSA_ALLOC_ZERO);
-       new_buckets = dsa_get_address(hash_table->area, new_buckets_shared);
+       {
+               int                     dsa_flags = DSA_ALLOC_HUGE | 
DSA_ALLOC_ZERO;
+
+               if (flags & DSHASH_INSERT_NO_OOM)
+                       dsa_flags |= DSA_ALLOC_NO_OOM;
+               new_buckets_shared =
+                       dsa_allocate_extended(hash_table->area,
+                                                                 
sizeof(dsa_pointer) * new_size,
+                                                                 dsa_flags);
+       }
```

Making this a nested block does have the benefit of keeping dsa_flags close to 
where it is used. But from my impression, this style is still fairly uncommon 
in the codebase. I worry it may implicitly signal to other hackers that this is 
an acceptable pattern. So unless we intentionally want to encourage that style, 
I would lean toward avoiding it here.

Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/






Reply via email to