diff --git a/contrib/Makefile b/contrib/Makefile index 25263c0..9739013 100644 --- a/contrib/Makefile +++ b/contrib/Makefile @@ -17,6 +17,7 @@ SUBDIRS = \ dblink \ dict_int \ dict_xsyn \ + dsm_demo \ earthdistance \ file_fdw \ fuzzystrmatch \ diff --git a/contrib/dsm_demo/Makefile b/contrib/dsm_demo/Makefile new file mode 100644 index 0000000..dd9ea92 --- /dev/null +++ b/contrib/dsm_demo/Makefile @@ -0,0 +1,17 @@ +# contrib/dsm_demo/Makefile + +MODULES = dsm_demo + +EXTENSION = dsm_demo +DATA = dsm_demo--1.0.sql + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/dsm_demo +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/dsm_demo/dsm_demo--1.0.sql b/contrib/dsm_demo/dsm_demo--1.0.sql new file mode 100644 index 0000000..c0f1a99 --- /dev/null +++ b/contrib/dsm_demo/dsm_demo--1.0.sql @@ -0,0 +1,19 @@ +/* contrib/dsm_demo/dsm_demo--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION dsm_demo" to load this file. \quit + +CREATE FUNCTION dsm_demo_create(pg_catalog.text, pg_catalog.int4 default 0) +RETURNS pg_catalog.int8 STRICT +AS 'MODULE_PATHNAME' +LANGUAGE C; + +CREATE FUNCTION dsm_demo_read(pg_catalog.int8) +RETURNS pg_catalog.text STRICT +AS 'MODULE_PATHNAME' +LANGUAGE C; + +CREATE FUNCTION dsm_demo_unpin_segment(pg_catalog.int8) +RETURNS pg_catalog.bool STRICT +AS 'MODULE_PATHNAME' +LANGUAGE C; \ No newline at end of file diff --git a/contrib/dsm_demo/dsm_demo.c b/contrib/dsm_demo/dsm_demo.c new file mode 100644 index 0000000..7b10972 --- /dev/null +++ b/contrib/dsm_demo/dsm_demo.c @@ -0,0 +1,150 @@ +/* ------------------------------------------------------------------------- + * + * dsm_demo.c + * Dynamic shared memory demonstration. + * + * Copyright (C) 2013, PostgreSQL Global Development Group + * + * IDENTIFICATION + * contrib/dsm_demo/dsm_demo.c + * + * ------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "storage/dsm.h" +#include "fmgr.h" + +PG_MODULE_MAGIC; + +void _PG_init(void); +Datum dsm_demo_create(PG_FUNCTION_ARGS); +Datum dsm_demo_read(PG_FUNCTION_ARGS); +Datum dsm_demo_unpin_segment(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1(dsm_demo_create); +PG_FUNCTION_INFO_V1(dsm_demo_read); +PG_FUNCTION_INFO_V1(dsm_demo_unpin_segment); + +#define DSM_DEMO_MAGIC 0x44454D4F + +typedef struct +{ + uint32 magic; + int32 len; + char data[FLEXIBLE_ARRAY_MEMBER]; +} dsm_demo_payload; + +/* + * dsm_demo_create(text, segment_lifetime int4) + * + * The first argument is the text data to be shared by using dsm, the second + * controls the life span of dsm segemnt. 0 indicates session lifetime, 1 + * indicates postmaster lifetime. + */ +Datum +dsm_demo_create(PG_FUNCTION_ARGS) +{ + text *txt = PG_GETARG_TEXT_PP(0); + int len = VARSIZE_ANY(txt); + int segment_life = PG_GETARG_INT32(1); + uint64 seglen; + dsm_segment *seg; + dsm_handle h; + dsm_demo_payload *payload; + + seglen = offsetof(dsm_demo_payload, data) + len; + seg = dsm_create(seglen, DSM_CREATE_NULL_IF_MAXSEGMENTS); + + if (segment_life == 0) + dsm_pin_mapping(seg); + else if (segment_life == 1) + dsm_pin_segment(seg); + else + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + (errmsg("value of segment lifetime can be either 0 or 1")))); + + payload = dsm_segment_address(seg); + payload->magic = DSM_DEMO_MAGIC; + payload->len = len; + memcpy(payload->data, txt, len); + + h = dsm_segment_handle(seg); + + dsm_detach(seg); + + PG_RETURN_INT64(h); +} + +Datum +dsm_demo_read(PG_FUNCTION_ARGS) +{ + dsm_handle h = PG_GETARG_INT64(0); + dsm_segment *seg; + bool needs_detach = false; + text *txt = NULL; + dsm_demo_payload *payload; + + /* + * We could be called from the same sesion that called dsm_demo_create(), + * so search for an existing mapping. If we don't find one, attach the + * segment. + */ + seg = dsm_find_mapping(h); + if (seg == NULL) + { + seg = dsm_attach(h); + if (!seg) + PG_RETURN_NULL(); + needs_detach = true; + } + + /* Extract data, after checking magic number. */ + payload = dsm_segment_address(seg); + if (payload->magic == DSM_DEMO_MAGIC) + { + txt = palloc(payload->len); + memcpy(txt, payload->data, payload->len); + } + + /* Detach, if there was no existing mapping. */ + if (needs_detach) + dsm_detach(seg); + + if (txt == NULL) + PG_RETURN_NULL(); + + PG_RETURN_TEXT_P(txt); +} + +Datum +dsm_demo_unpin_segment(PG_FUNCTION_ARGS) +{ + dsm_handle h = PG_GETARG_INT64(0); + dsm_segment *seg; + bool needs_detach = false; + + /* + * We could be called from the same sesion that called dsm_demo_create(), + * so search for an existing mapping. If we don't find one, attach the + * segment. + */ + seg = dsm_find_mapping(h); + if (seg == NULL) + { + seg = dsm_attach(h); + if (!seg) + PG_RETURN_BOOL(false); + needs_detach = true; + } + + dsm_unpin_segment(h); + + /* Detach, if there was no existing mapping. */ + if (needs_detach) + dsm_detach(seg); + + PG_RETURN_BOOL(true); +} diff --git a/contrib/dsm_demo/dsm_demo.control b/contrib/dsm_demo/dsm_demo.control new file mode 100644 index 0000000..4060791 --- /dev/null +++ b/contrib/dsm_demo/dsm_demo.control @@ -0,0 +1,5 @@ +# dsm_demo extension +comment = 'Dynamic shared memory demonstration' +default_version = '1.0' +module_pathname = 'dsm_demo' +relocatable = true