>From 43ae2a5397fba3b83afced6ec813449a1c87f8c0 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Tue, 6 May 2014 19:42:36 +0200
Subject: [PATCH 1/2] Associate names to created dynamic shared memory
 segments.

At some later point we want to add a view show all allocated dynamic
shared memory segments so admins can understand resource usage. To
avoid breaking the API in 9.5 add the necessary name now.
---
 contrib/test_shm_mq/setup.c   |  2 +-
 src/backend/storage/ipc/dsm.c | 60 ++++++++++++++++++++++++++-----------------
 src/include/storage/dsm.h     |  2 +-
 3 files changed, 39 insertions(+), 25 deletions(-)

diff --git a/contrib/test_shm_mq/setup.c b/contrib/test_shm_mq/setup.c
index 572cf88..897c47b 100644
--- a/contrib/test_shm_mq/setup.c
+++ b/contrib/test_shm_mq/setup.c
@@ -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("test_shm_mq", shm_toc_estimate(&e));
 	toc = shm_toc_create(PG_TEST_SHM_MQ_MAGIC, dsm_segment_address(seg),
 						 segsize);
 
diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c
index a5c0084..66e24f0 100644
--- a/src/backend/storage/ipc/dsm.c
+++ b/src/backend/storage/ipc/dsm.c
@@ -80,8 +80,10 @@ struct dsm_segment
 /* Shared-memory state for a dynamic shared memory segment. */
 typedef struct dsm_control_item
 {
-	dsm_handle	handle;
+	dsm_handle	handle;			/* segment identifier */
 	uint32		refcnt;			/* 2+ = active, 1 = moribund, 0 = gone */
+	Size		size;			/* current size */
+	char		name[SHMEM_INDEX_KEYSIZE]; /* informational name */
 } dsm_control_item;
 
 /* Layout of the dynamic shared memory control segment. */
@@ -454,14 +456,16 @@ dsm_set_control_handle(dsm_handle h)
  * Create a new dynamic shared memory segment.
  */
 dsm_segment *
-dsm_create(Size size)
+dsm_create(const char *name, Size size)
 {
 	dsm_segment *seg = dsm_create_descriptor();
-	uint32		i;
-	uint32		nitems;
+	dsm_control_item *item;
+	uint32		slot;
 
 	/* Unsafe in postmaster (and pointless in a stand-alone backend). */
 	Assert(IsUnderPostmaster);
+	Assert(name != NULL && strlen(name) > 0 &&
+		   strlen(name) < SHMEM_INDEX_KEYSIZE);
 
 	if (!dsm_init_done)
 		dsm_backend_startup();
@@ -479,33 +483,39 @@ dsm_create(Size size)
 	/* Lock the control segment so we can register the new segment. */
 	LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE);
 
-	/* Search the control segment for an unused slot. */
-	nitems = dsm_control->nitems;
-	for (i = 0; i < nitems; ++i)
+	/*
+	 * Search the control segment for an unused slot that's previously been
+	 * used. If we don't find one initialize a new one if there's still space.
+	 */
+	for (slot = 0; slot < dsm_control->nitems; ++slot)
 	{
-		if (dsm_control->item[i].refcnt == 0)
-		{
-			dsm_control->item[i].handle = seg->handle;
-			/* refcnt of 1 triggers destruction, so start at 2 */
-			dsm_control->item[i].refcnt = 2;
-			seg->control_slot = i;
-			LWLockRelease(DynamicSharedMemoryControlLock);
-			return seg;
-		}
+		if (dsm_control->item[slot].refcnt == 0)
+			break;
 	}
 
-	/* Verify that we can support an additional mapping. */
-	if (nitems >= dsm_control->maxitems)
+	/* Verify that we can support the mapping. */
+	if (slot >= dsm_control->maxitems)
 		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;
+	item = &dsm_control->item[slot];
+	item->handle = seg->handle;
 	/* refcnt of 1 triggers destruction, so start at 2 */
-	dsm_control->item[nitems].refcnt = 2;
-	seg->control_slot = nitems;
-	dsm_control->nitems++;
+	item->refcnt = 2;
+	item->size = size;
+	strncpy(item->name, name, SHMEM_INDEX_SIZE - 1);
+	item->name[SHMEM_INDEX_SIZE] = 0;
+
+	seg->control_slot = slot;
+
+	/*
+	 * Increase number of initilized slots if we didn't reuse a previously
+	 * used one.
+	 */
+	if (slot >= dsm_control->nitems)
+		dsm_control->nitems++;
+
 	LWLockRelease(DynamicSharedMemoryControlLock);
 
 	return seg;
@@ -658,6 +668,10 @@ dsm_resize(dsm_segment *seg, Size size)
 	Assert(seg->control_slot != INVALID_CONTROL_SLOT);
 	dsm_impl_op(DSM_OP_RESIZE, seg->handle, size, &seg->impl_private,
 				&seg->mapped_address, &seg->mapped_size, ERROR);
+
+	/* persist the changed size */
+	dsm_control->item[seg->control_slot].size = size;
+
 	return seg->mapped_address;
 }
 
diff --git a/src/include/storage/dsm.h b/src/include/storage/dsm.h
index 1d0110d..3dbe53b 100644
--- a/src/include/storage/dsm.h
+++ b/src/include/storage/dsm.h
@@ -29,7 +29,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(const char *name, Size size);
 extern dsm_segment *dsm_attach(dsm_handle h);
 extern void *dsm_resize(dsm_segment *seg, Size size);
 extern void *dsm_remap(dsm_segment *seg);
-- 
1.8.5.rc2.dirty

