]> granicus.if.org Git - postgresql/commitdiff
Add flags argument to dsm_create.
authorRobert Haas <rhaas@postgresql.org>
Thu, 19 Mar 2015 17:02:16 +0000 (13:02 -0400)
committerRobert Haas <rhaas@postgresql.org>
Thu, 19 Mar 2015 17:03:03 +0000 (13:03 -0400)
Right now, there's only one flag, DSM_CREATE_NULL_IF_MAXSEGMENTS,
which suppresses the error that would normally be thrown when the
maximum number of segments already exists, instead returning NULL.
It might be useful to add more flags in the future, such as one to
ignore allocation errors, but I haven't done that here.

src/backend/storage/ipc/dsm.c
src/include/storage/dsm.h
src/test/modules/test_shm_mq/setup.c

index 983d0fa744f7e46f4af2ecec0a3be05ca4c70c89..d2b231f7895e4be67b1cfdfae027ca8bd712c4a6 100644 (file)
@@ -454,9 +454,9 @@ dsm_set_control_handle(dsm_handle h)
  * Create a new dynamic shared memory segment.
  */
 dsm_segment *
-dsm_create(Size size)
+dsm_create(Size size, int flags)
 {
-       dsm_segment *seg = dsm_create_descriptor();
+       dsm_segment *seg;
        uint32          i;
        uint32          nitems;
 
@@ -466,6 +466,21 @@ dsm_create(Size size)
        if (!dsm_init_done)
                dsm_backend_startup();
 
+       /* 
+        * If we've been instructed to return NULL when it's not possible to
+        * register another segment, check whether we seem to be at the limit.
+        * This allows us to avoid the overhead of creating a new segment only to
+        * immediately destroy it again.  Since we don't take the lock here, the
+        * value we read might be slightly stale, but the remote possibility of
+        * an unnecessary failure here shouldn't trouble anyone too much.
+        */
+       if ((flags & DSM_CREATE_NULL_IF_MAXSEGMENTS) != 0
+               && dsm_control->nitems >= dsm_control->maxitems)
+               return NULL;
+
+       /* Create a new segment descriptor. */
+       seg = dsm_create_descriptor();
+
        /* Loop until we find an unused segment identifier. */
        for (;;)
        {
@@ -496,9 +511,21 @@ dsm_create(Size size)
 
        /* Verify that we can support an additional mapping. */
        if (nitems >= dsm_control->maxitems)
+       {
+               if ((flags & DSM_CREATE_NULL_IF_MAXSEGMENTS) != 0)
+               {
+                       dsm_impl_op(DSM_OP_DESTROY, seg->handle, 0, &seg->impl_private,
+                                               &seg->mapped_address, &seg->mapped_size, WARNING);
+                       if (seg->resowner != NULL)
+                               ResourceOwnerForgetDSM(seg->resowner, seg);
+                       dlist_delete(&seg->node);
+                       pfree(seg);
+                       return NULL;
+               }
                ereport(ERROR,
                                (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
                                 errmsg("too many dynamic shared memory segments")));
+       }
 
        /* Enter the handle into a new array slot. */
        dsm_control->item[nitems].handle = seg->handle;
index 2bf12ce531312c1e92bf8754c4ad83590f072ecf..beee105a6bda677a1ac174d8ce33edb9cccadeb5 100644 (file)
@@ -17,6 +17,8 @@
 
 typedef struct dsm_segment dsm_segment;
 
+#define DSM_CREATE_NULL_IF_MAXSEGMENTS                 0x0001
+
 /* Startup and shutdown functions. */
 struct PGShmemHeader;                  /* avoid including pg_shmem.h */
 extern void dsm_cleanup_using_control_segment(dsm_handle old_control_handle);
@@ -29,7 +31,7 @@ extern void dsm_set_control_handle(dsm_handle h);
 #endif
 
 /* Functions that create, update, or remove mappings. */
-extern dsm_segment *dsm_create(Size size);
+extern dsm_segment *dsm_create(Size size, int flags);
 extern dsm_segment *dsm_attach(dsm_handle h);
 extern void *dsm_resize(dsm_segment *seg, Size size);
 extern void *dsm_remap(dsm_segment *seg);
index 195099095de59f27ecea4dbc11c7d8fcb527701d..7f2f5fd3ff72efb784c5c399fb43b17ed889465b 100644 (file)
@@ -125,7 +125,7 @@ setup_dynamic_shared_memory(int64 queue_size, int nworkers,
        segsize = shm_toc_estimate(&e);
 
        /* Create the shared memory segment and establish a table of contents. */
-       seg = dsm_create(shm_toc_estimate(&e));
+       seg = dsm_create(shm_toc_estimate(&e), 0);
        toc = shm_toc_create(PG_TEST_SHM_MQ_MAGIC, dsm_segment_address(seg),
                                                 segsize);