mirror of
https://github.com/postgres/postgres.git
synced 2025-07-31 22:04:40 +03:00
Allow dynamic shared memory segments to be kept until shutdown.
Amit Kapila, reviewed by Kyotaro Horiguchi, with some further changes by me.
This commit is contained in:
@ -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 @@
|
|||||||
#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;
|
|||||||
/* 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,
|
|||||||
* 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,
|
|||||||
}
|
}
|
||||||
#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);
|
|||||||
|
|
||||||
/* 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,
|
|||||||
/* 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 */
|
||||||
|
Reference in New Issue
Block a user