diff options
author | Robert Haas <rhaas@postgresql.org> | 2016-08-23 14:32:23 -0400 |
---|---|---|
committer | Robert Haas <rhaas@postgresql.org> | 2016-08-23 14:32:23 -0400 |
commit | 0fda682e542c9acd368588e50a1993fecd3b73e2 (patch) | |
tree | c00d8001e56c46c36e432ad1b226fd8e610e2409 /src/backend/storage/ipc/dsm_impl.c | |
parent | 19998730aea97137e2516af0516c683a1261ba1f (diff) | |
download | postgresql-0fda682e542c9acd368588e50a1993fecd3b73e2.tar.gz postgresql-0fda682e542c9acd368588e50a1993fecd3b73e2.zip |
Extend dsm API with a new function dsm_unpin_segment.
If you have previously pinned a segment and decide that you don't
actually want to keep it around until shutdown, this new API lets you
remove the pin. This is pretty trivial except on Windows, where it
requires closing the duplicate handle that was used to implement the
pin.
Thomas Munro and Amit Kapila, reviewed by Amit Kapila and by me.
Diffstat (limited to 'src/backend/storage/ipc/dsm_impl.c')
-rw-r--r-- | src/backend/storage/ipc/dsm_impl.c | 57 |
1 files changed, 54 insertions, 3 deletions
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c index 173b9822191..c07a5c6b151 100644 --- a/src/backend/storage/ipc/dsm_impl.c +++ b/src/backend/storage/ipc/dsm_impl.c @@ -987,8 +987,8 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size, #endif /* - * Implementation-specific actions that must be performed when a segment - * is to be preserved until postmaster shutdown. + * Implementation-specific actions that must be performed when a segment is to + * be preserved even when no backend has it attached. * * 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 @@ -996,7 +996,8 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size, * do anything to receive the handle; Windows transfers it automatically. */ void -dsm_impl_pin_segment(dsm_handle handle, void *impl_private) +dsm_impl_pin_segment(dsm_handle handle, void *impl_private, + void **impl_private_pm_handle) { switch (dynamic_shared_memory_type) { @@ -1018,6 +1019,56 @@ dsm_impl_pin_segment(dsm_handle handle, void *impl_private) errmsg("could not duplicate handle for \"%s\": %m", name))); } + + /* + * Here, we remember the handle that we created in the + * postmaster process. This handle isn't actually usable in + * any process other than the postmaster, but that doesn't + * matter. We're just holding onto it so that, if the segment + * is unpinned, dsm_impl_unpin_segment can close it. + */ + *impl_private_pm_handle = hmap; + break; + } +#endif + default: + break; + } +} + +/* + * Implementation-specific actions that must be performed when a segment is no + * longer to be preserved, so that it will be cleaned up when all backends + * have detached from it. + * + * Except on Windows, we don't need to do anything at all. For Windows, we + * close the extra handle that dsm_impl_pin_segment created in the + * postmaster's process space. + */ +void +dsm_impl_unpin_segment(dsm_handle handle, void **impl_private) +{ + switch (dynamic_shared_memory_type) + { +#ifdef USE_DSM_WINDOWS + case DSM_IMPL_WINDOWS: + { + if (*impl_private && + !DuplicateHandle(PostmasterHandle, *impl_private, + NULL, NULL, 0, FALSE, + DUPLICATE_CLOSE_SOURCE)) + { + 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))); + } + + *impl_private = NULL; break; } #endif |