Commit 8722017b authored by Robert Haas's avatar Robert Haas

Allow dynamic shared memory segments to be kept until shutdown.

Amit Kapila, reviewed by Kyotaro Horiguchi, with some further
changes by me.
parent 5a991ef8
...@@ -885,6 +885,33 @@ dsm_keep_mapping(dsm_segment *seg) ...@@ -885,6 +885,33 @@ dsm_keep_mapping(dsm_segment *seg)
} }
} }
/*
* Keep a dynamic shared memory segment until postmaster shutdown.
*
* This function should not be called more than once per segment;
* on Windows, doing so will create unnecessary handles which will
* consume system resources to no benefit.
*
* Note that this function does not arrange for the current process to
* keep the segment mapped indefinitely; if that behavior is desired,
* dsm_keep_mapping() should be used from each process that needs to
* retain the mapping.
*/
void
dsm_keep_segment(dsm_segment *seg)
{
/*
* Bump reference count for this segment in shared memory. This will
* ensure that even if there is no session which is attached to this
* segment, it will remain until postmaster shutdown.
*/
LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE);
dsm_control->item[seg->control_slot].refcnt++;
LWLockRelease(DynamicSharedMemoryControlLock);
dsm_impl_keep_segment(seg->handle, seg->impl_private);
}
/* /*
* Find an existing mapping for a shared memory segment, if there is one. * Find an existing mapping for a shared memory segment, if there is one.
*/ */
......
...@@ -67,6 +67,7 @@ ...@@ -67,6 +67,7 @@
#include "storage/fd.h" #include "storage/fd.h"
#include "utils/guc.h" #include "utils/guc.h"
#include "utils/memutils.h" #include "utils/memutils.h"
#include "postmaster/postmaster.h"
#ifdef USE_DSM_POSIX #ifdef USE_DSM_POSIX
static bool dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size, static bool dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
...@@ -113,6 +114,8 @@ int dynamic_shared_memory_type; ...@@ -113,6 +114,8 @@ int dynamic_shared_memory_type;
/* Size of buffer to be used for zero-filling. */ /* Size of buffer to be used for zero-filling. */
#define ZBUFFER_SIZE 8192 #define ZBUFFER_SIZE 8192
#define SEGMENT_NAME_PREFIX "Global/PostgreSQL"
/*------ /*------
* Perform a low-level shared memory operation in a platform-specific way, * Perform a low-level shared memory operation in a platform-specific way,
* as dictated by the selected implementation. Each implementation is * as dictated by the selected implementation. Each implementation is
...@@ -635,7 +638,7 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size, ...@@ -635,7 +638,7 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
* convention similar to main shared memory. We can change here once * convention similar to main shared memory. We can change here once
* issue mentioned in GetSharedMemName is resolved. * issue mentioned in GetSharedMemName is resolved.
*/ */
snprintf(name, 64, "Global/PostgreSQL.%u", handle); snprintf(name, 64, "%s.%u", SEGMENT_NAME_PREFIX, handle);
/* /*
* Handle teardown cases. Since Windows automatically destroys the object * Handle teardown cases. Since Windows automatically destroys the object
...@@ -982,6 +985,46 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size, ...@@ -982,6 +985,46 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
} }
#endif #endif
/*
* Implementation-specific actions that must be performed when a segment
* is to be preserved until postmaster shutdown.
*
* Except on Windows, we don't need to do anything at all. But since Windows
* cleans up segments automatically when no references remain, we duplicate
* the segment handle into the postmaster process. The postmaster needn't
* do anything to receive the handle; Windows transfers it automatically.
*/
void
dsm_impl_keep_segment(dsm_handle handle, void *impl_private)
{
switch (dynamic_shared_memory_type)
{
#ifdef USE_DSM_WINDOWS
case DSM_IMPL_WINDOWS:
{
HANDLE hmap;
if (!DuplicateHandle(GetCurrentProcess(), impl_private,
PostmasterHandle, &hmap, 0, FALSE,
DUPLICATE_SAME_ACCESS))
{
char name[64];
snprintf(name, 64, "%s.%u", SEGMENT_NAME_PREFIX, handle);
_dosmaperr(GetLastError());
ereport(ERROR,
(errcode_for_dynamic_shared_memory(),
errmsg("could not duplicate handle for \"%s\": %m",
name)));
}
break;
}
#endif
default:
break;
}
}
static int static int
errcode_for_dynamic_shared_memory() errcode_for_dynamic_shared_memory()
{ {
......
...@@ -30,6 +30,7 @@ extern void dsm_detach(dsm_segment *seg); ...@@ -30,6 +30,7 @@ extern void dsm_detach(dsm_segment *seg);
/* Resource management functions. */ /* Resource management functions. */
extern void dsm_keep_mapping(dsm_segment *seg); extern void dsm_keep_mapping(dsm_segment *seg);
extern void dsm_keep_segment(dsm_segment *seg);
extern dsm_segment *dsm_find_mapping(dsm_handle h); extern dsm_segment *dsm_find_mapping(dsm_handle h);
/* Informational functions. */ /* Informational functions. */
......
...@@ -72,4 +72,7 @@ extern bool dsm_impl_op(dsm_op op, dsm_handle handle, Size request_size, ...@@ -72,4 +72,7 @@ extern bool dsm_impl_op(dsm_op op, dsm_handle handle, Size request_size,
/* Some implementations cannot resize segments. Can this one? */ /* Some implementations cannot resize segments. Can this one? */
extern bool dsm_impl_can_resize(void); extern bool dsm_impl_can_resize(void);
/* Implementation-dependent actions required to keep segment until shudown. */
extern void dsm_impl_keep_segment(dsm_handle handle, void *impl_private);
#endif /* DSM_IMPL_H */ #endif /* DSM_IMPL_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment