---
 configure                            |  38 ++++++
 configure.ac                         |  10 ++
 meson.build                          |   1 +
 meson_options.txt                    |   3 +
 src/Makefile.global.in               |   1 +
 src/backend/storage/smgr/Makefile    |   8 ++
 src/backend/storage/smgr/meson.build |   6 +
 src/backend/storage/smgr/smgr.c      |  52 ++++++++-
 src/backend/storage/smgr/umbra.c     | 167 +++++++++++++++++++++++++++
 src/include/pg_config.h.in           |   3 +
 src/include/storage/smgr.h           |  11 +-
 src/include/storage/umbra.h          |  54 +++++++++
 12 files changed, 345 insertions(+), 9 deletions(-)
 create mode 100644 src/backend/storage/smgr/umbra.c
 create mode 100644 src/include/storage/umbra.h

diff --git a/configure b/configure
index f66c1054a7..a63ecb3745 100755
--- a/configure
+++ b/configure
@@ -723,6 +723,7 @@ LIBURING_LIBS
 LIBURING_CFLAGS
 with_liburing
 with_readline
+with_umbra
 with_systemd
 with_selinux
 with_ldap
@@ -872,6 +873,7 @@ with_ldap
 with_bonjour
 with_selinux
 with_systemd
+with_umbra
 with_readline
 with_libedit_preferred
 with_liburing
@@ -1590,6 +1592,7 @@ Optional Packages:
   --with-bonjour          build with Bonjour support
   --with-selinux          build with SELinux support
   --with-systemd          build with systemd support
+  --with-umbra            build with Umbra storage manager (experimental)
   --without-readline      do not use GNU Readline nor BSD Libedit for editing
   --with-libedit-preferred
                           prefer BSD Libedit over GNU Readline
@@ -8635,6 +8638,41 @@ fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_systemd" >&5
 $as_echo "$with_systemd" >&6; }
 
+#
+# Umbra storage manager (experimental)
+#
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build with Umbra 
storage manager" >&5
+$as_echo_n "checking whether to build with Umbra storage manager... " >&6; }
+
+
+
+# Check whether --with-umbra was given.
+if test "${with_umbra+set}" = set; then :
+  withval=$with_umbra;
+  case $withval in
+    yes)
+
+$as_echo "#define USE_UMBRA 1" >>confdefs.h
+
+      ;;
+    no)
+      :
+      ;;
+    *)
+      as_fn_error $? "no argument expected for --with-umbra option" "$LINENO" 5
+      ;;
+  esac
+
+else
+  with_umbra=no
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_umbra" >&5
+$as_echo "$with_umbra" >&6; }
+
+
 #
 # Readline
 #
diff --git a/configure.ac b/configure.ac
index 8d176bd346..43006a5284 100644
--- a/configure.ac
+++ b/configure.ac
@@ -992,6 +992,16 @@ PGAC_ARG_BOOL(with, systemd, no, [build with systemd 
support],
 AC_SUBST(with_systemd)
 AC_MSG_RESULT([$with_systemd])
 
+#
+# Umbra storage manager (experimental)
+#
+AC_MSG_CHECKING([whether to build with Umbra storage manager])
+PGAC_ARG_BOOL(with, umbra, no,
+              [build with Umbra storage manager (experimental)],
+              [AC_DEFINE([USE_UMBRA], 1, [Define to build with Umbra storage 
manager. (--with-umbra)])])
+AC_MSG_RESULT([$with_umbra])
+AC_SUBST(with_umbra)
+
 #
 # Readline
 #
diff --git a/meson.build b/meson.build
index be97e986e5..016ba9fc0c 100644
--- a/meson.build
+++ b/meson.build
@@ -505,6 +505,7 @@ meson_bin = find_program(meson_binpath, native: true)
 
 cdata.set('USE_ASSERT_CHECKING', get_option('cassert') ? 1 : false)
 cdata.set('USE_INJECTION_POINTS', get_option('injection_points') ? 1 : false)
+cdata.set('USE_UMBRA', get_option('umbra').enabled() ? 1 : false)
 
 blocksize = get_option('blocksize').to_int() * 1024
 
diff --git a/meson_options.txt b/meson_options.txt
index 6a793f3e47..469239543c 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -46,6 +46,9 @@ option('tap_tests', type: 'feature', value: 'auto',
 option('injection_points', type: 'boolean', value: false,
   description: 'Enable injection points')
 
+option('umbra', type: 'feature', value: 'disabled',
+  description: 'Enable experimental Umbra storage manager')
+
 option('PG_TEST_EXTRA', type: 'string', value: '',
   description: 'Enable selected extra tests. Overridden by PG_TEST_EXTRA 
environment variable.')
 
diff --git a/src/Makefile.global.in b/src/Makefile.global.in
index a7699b026b..4e2815218a 100644
--- a/src/Makefile.global.in
+++ b/src/Makefile.global.in
@@ -201,6 +201,7 @@ with_liburing       = @with_liburing@
 with_libxml    = @with_libxml@
 with_libxslt   = @with_libxslt@
 with_llvm      = @with_llvm@
+with_umbra     = @with_umbra@
 with_system_tzdata = @with_system_tzdata@
 with_uuid      = @with_uuid@
 with_zlib      = @with_zlib@
diff --git a/src/backend/storage/smgr/Makefile 
b/src/backend/storage/smgr/Makefile
index 1d0b98764f..537e7b65f4 100644
--- a/src/backend/storage/smgr/Makefile
+++ b/src/backend/storage/smgr/Makefile
@@ -17,4 +17,12 @@ OBJS = \
        md.o \
        smgr.o
 
+ifeq ($(with_umbra), yes)
+OBJS += \
+       umbra.o
+endif
+
+# Reconfiguration can change both OBJS and the default smgr implementation.
+objfiles.txt smgr.o: $(top_builddir)/src/Makefile.global
+
 include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/storage/smgr/meson.build 
b/src/backend/storage/smgr/meson.build
index 3785c40385..ba28e59f2f 100644
--- a/src/backend/storage/smgr/meson.build
+++ b/src/backend/storage/smgr/meson.build
@@ -5,3 +5,9 @@ backend_sources += files(
   'md.c',
   'smgr.c',
 )
+
+if get_option('umbra').enabled()
+  backend_sources += files(
+    'umbra.c',
+  )
+endif
diff --git a/src/backend/storage/smgr/smgr.c b/src/backend/storage/smgr/smgr.c
index 5391640d86..a7b70d856c 100644
--- a/src/backend/storage/smgr/smgr.c
+++ b/src/backend/storage/smgr/smgr.c
@@ -4,8 +4,9 @@
  *       public interface routines to storage manager switch.
  *
  * All file system operations on relations dispatch through these routines.
- * An SMgrRelation represents physical on-disk relation files that are open
- * for reading and writing.
+ * An SMgrRelation represents storage-manager state for a relation.  The
+ * selected storage manager implementation owns any implementation-specific
+ * state needed to service those operations.
  *
  * When a relation is first accessed through the relation cache, the
  * corresponding SMgrRelation entry is opened by calling smgropen(), and the
@@ -71,6 +72,9 @@
 #include "storage/ipc.h"
 #include "storage/md.h"
 #include "storage/smgr.h"
+#ifdef USE_UMBRA
+#include "storage/umbra.h"
+#endif
 #include "utils/hsearch.h"
 #include "utils/inval.h"
 
@@ -91,6 +95,7 @@ typedef struct f_smgr
        void            (*smgr_shutdown) (void);        /* may be NULL */
        void            (*smgr_open) (SMgrRelation reln);
        void            (*smgr_close) (SMgrRelation reln, ForkNumber forknum);
+       void            (*smgr_destroy) (SMgrRelation reln);    /* may be NULL 
*/
        void            (*smgr_create) (SMgrRelation reln, ForkNumber forknum,
                                                                bool isRedo);
        bool            (*smgr_exists) (SMgrRelation reln, ForkNumber forknum);
@@ -125,6 +130,14 @@ typedef struct f_smgr
        int                     (*smgr_fd) (SMgrRelation reln, ForkNumber 
forknum, BlockNumber blocknum, uint32 *off);
 } f_smgr;
 
+#define SMGR_MD                0
+#ifdef USE_UMBRA
+#define SMGR_UMBRA     1
+#define SMGR_DEFAULT   SMGR_UMBRA
+#else
+#define SMGR_DEFAULT   SMGR_MD
+#endif
+
 static const f_smgr smgrsw[] = {
        /* magnetic disk */
        {
@@ -132,6 +145,7 @@ static const f_smgr smgrsw[] = {
                .smgr_shutdown = NULL,
                .smgr_open = mdopen,
                .smgr_close = mdclose,
+               .smgr_destroy = NULL,
                .smgr_create = mdcreate,
                .smgr_exists = mdexists,
                .smgr_unlink = mdunlink,
@@ -148,7 +162,33 @@ static const f_smgr smgrsw[] = {
                .smgr_immedsync = mdimmedsync,
                .smgr_registersync = mdregistersync,
                .smgr_fd = mdfd,
-       }
+       },
+#ifdef USE_UMBRA
+       /* Umbra storage manager */
+       {
+               .smgr_init = uminit,
+               .smgr_shutdown = NULL,
+               .smgr_open = umopen,
+               .smgr_close = umclose,
+               .smgr_destroy = umdestroy,
+               .smgr_create = umcreate,
+               .smgr_exists = umexists,
+               .smgr_unlink = umunlink,
+               .smgr_extend = umextend,
+               .smgr_zeroextend = umzeroextend,
+               .smgr_prefetch = umprefetch,
+               .smgr_maxcombine = ummaxcombine,
+               .smgr_readv = umreadv,
+               .smgr_startreadv = umstartreadv,
+               .smgr_writev = umwritev,
+               .smgr_writeback = umwriteback,
+               .smgr_nblocks = umnblocks,
+               .smgr_truncate = umtruncate,
+               .smgr_immedsync = umimmedsync,
+               .smgr_registersync = umregistersync,
+               .smgr_fd = umfd,
+       },
+#endif
 };
 
 static const int NSmgr = lengthof(smgrsw);
@@ -273,7 +313,8 @@ smgropen(RelFileLocator rlocator, ProcNumber backend)
                reln->smgr_targblock = InvalidBlockNumber;
                for (int i = 0; i <= MAX_FORKNUM; ++i)
                        reln->smgr_cached_nblocks[i] = InvalidBlockNumber;
-               reln->smgr_which = 0;   /* we only have md.c at present */
+               reln->smgr_which = SMGR_DEFAULT;
+               reln->smgr_private = NULL;
 
                /* it is not pinned yet */
                reln->pincount = 0;
@@ -331,6 +372,9 @@ smgrdestroy(SMgrRelation reln)
        for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
                smgrsw[reln->smgr_which].smgr_close(reln, forknum);
 
+       if (smgrsw[reln->smgr_which].smgr_destroy != NULL)
+               smgrsw[reln->smgr_which].smgr_destroy(reln);
+
        dlist_delete(&reln->node);
 
        if (hash_search(SMgrRelationHash,
diff --git a/src/backend/storage/smgr/umbra.c b/src/backend/storage/smgr/umbra.c
new file mode 100644
index 0000000000..4c4fd28dbf
--- /dev/null
+++ b/src/backend/storage/smgr/umbra.c
@@ -0,0 +1,167 @@
+/*-------------------------------------------------------------------------
+ *
+ * umbra.c
+ *       Umbra storage manager skeleton.
+ *
+ * This file establishes Umbra as a separate smgr implementation from md.c.
+ * The initial implementation preserves md semantics by forwarding relation
+ * file operations to md.c.
+ *
+ * src/backend/storage/smgr/umbra.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "storage/md.h"
+#include "storage/smgr.h"
+#include "storage/umbra.h"
+#include "utils/memutils.h"
+
+typedef struct UmbraSmgrRelationState
+{
+       bool            initialized;
+} UmbraSmgrRelationState;
+
+void
+uminit(void)
+{
+}
+
+void
+umopen(SMgrRelation reln)
+{
+       UmbraSmgrRelationState *state;
+
+       Assert(reln->smgr_private == NULL);
+
+       state = MemoryContextAllocZero(TopMemoryContext,
+                                                                  
sizeof(UmbraSmgrRelationState));
+       state->initialized = true;
+       reln->smgr_private = state;
+
+       mdopen(reln);
+}
+
+void
+umclose(SMgrRelation reln, ForkNumber forknum)
+{
+       mdclose(reln, forknum);
+}
+
+void
+umdestroy(SMgrRelation reln)
+{
+       UmbraSmgrRelationState *state = reln->smgr_private;
+
+       if (state != NULL)
+       {
+               Assert(state->initialized);
+               pfree(state);
+               reln->smgr_private = NULL;
+       }
+}
+
+void
+umcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
+{
+       mdcreate(reln, forknum, isRedo);
+}
+
+bool
+umexists(SMgrRelation reln, ForkNumber forknum)
+{
+       return mdexists(reln, forknum);
+}
+
+void
+umunlink(RelFileLocatorBackend rlocator, ForkNumber forknum, bool isRedo)
+{
+       mdunlink(rlocator, forknum, isRedo);
+}
+
+void
+umextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
+                const void *buffer, bool skipFsync)
+{
+       mdextend(reln, forknum, blocknum, buffer, skipFsync);
+}
+
+void
+umzeroextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
+                        int nblocks, bool skipFsync)
+{
+       mdzeroextend(reln, forknum, blocknum, nblocks, skipFsync);
+}
+
+bool
+umprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
+                  int nblocks)
+{
+       return mdprefetch(reln, forknum, blocknum, nblocks);
+}
+
+uint32
+ummaxcombine(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum)
+{
+       return mdmaxcombine(reln, forknum, blocknum);
+}
+
+void
+umreadv(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
+               void **buffers, BlockNumber nblocks)
+{
+       mdreadv(reln, forknum, blocknum, buffers, nblocks);
+}
+
+void
+umstartreadv(PgAioHandle *ioh, SMgrRelation reln, ForkNumber forknum,
+                        BlockNumber blocknum, void **buffers, BlockNumber 
nblocks)
+{
+       mdstartreadv(ioh, reln, forknum, blocknum, buffers, nblocks);
+}
+
+void
+umwritev(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
+                const void **buffers, BlockNumber nblocks, bool skipFsync)
+{
+       mdwritev(reln, forknum, blocknum, buffers, nblocks, skipFsync);
+}
+
+void
+umwriteback(SMgrRelation reln, ForkNumber forknum,
+                       BlockNumber blocknum, BlockNumber nblocks)
+{
+       mdwriteback(reln, forknum, blocknum, nblocks);
+}
+
+BlockNumber
+umnblocks(SMgrRelation reln, ForkNumber forknum)
+{
+       return mdnblocks(reln, forknum);
+}
+
+void
+umtruncate(SMgrRelation reln, ForkNumber forknum,
+                  BlockNumber old_blocks, BlockNumber nblocks)
+{
+       mdtruncate(reln, forknum, old_blocks, nblocks);
+}
+
+void
+umimmedsync(SMgrRelation reln, ForkNumber forknum)
+{
+       mdimmedsync(reln, forknum);
+}
+
+void
+umregistersync(SMgrRelation reln, ForkNumber forknum)
+{
+       mdregistersync(reln, forknum);
+}
+
+int
+umfd(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, uint32 *off)
+{
+       return mdfd(reln, forknum, blocknum, off);
+}
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 4f8113c144..2bd28af842 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -698,6 +698,9 @@
 /* Define to 1 to build with injection points. (--enable-injection-points) */
 #undef USE_INJECTION_POINTS
 
+/* Define to build with Umbra storage manager. (--with-umbra) */
+#undef USE_UMBRA
+
 /* Define to 1 to build with LDAP support. (--with-ldap) */
 #undef USE_LDAP
 
diff --git a/src/include/storage/smgr.h b/src/include/storage/smgr.h
index 09bd42fcf4..1076717b92 100644
--- a/src/include/storage/smgr.h
+++ b/src/include/storage/smgr.h
@@ -21,11 +21,11 @@
 
 /*
  * smgr.c maintains a table of SMgrRelation objects, which are essentially
- * cached file handles.  An SMgrRelation is created (if not already present)
- * by smgropen(), and destroyed by smgrdestroy().  Note that neither of these
- * operations imply I/O, they just create or destroy a hashtable entry.  (But
- * smgrdestroy() may release associated resources, such as OS-level file
- * descriptors.)
+ * cached storage-manager handles for a relation.  An SMgrRelation is created
+ * (if not already present) by smgropen(), and destroyed by smgrdestroy().
+ * Note that neither of these operations imply I/O, they just create or destroy
+ * a hashtable entry.  (But smgrdestroy() may release associated resources,
+ * such as OS-level file descriptors.)
  *
  * An SMgrRelation may be "pinned", to prevent it from being destroyed while
  * it's in use.  We use this to prevent pointers in relcache to smgr from being
@@ -53,6 +53,7 @@ typedef struct SMgrRelationData
         * submodules.  Do not touch them from elsewhere.
         */
        int                     smgr_which;             /* storage manager 
selector */
+       void       *smgr_private;       /* implementation-private state */
 
        /*
         * for md.c; per-fork arrays of the number of open segments
diff --git a/src/include/storage/umbra.h b/src/include/storage/umbra.h
new file mode 100644
index 0000000000..9a2873f96d
--- /dev/null
+++ b/src/include/storage/umbra.h
@@ -0,0 +1,54 @@
+/*-------------------------------------------------------------------------
+ *
+ * umbra.h
+ *       Umbra storage manager public interface declarations.
+ *
+ * This header declares the Umbra smgr callback surface used by smgr.c when
+ * the build is configured with --with-umbra.
+ *
+ * src/include/storage/umbra.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef UMBRA_H
+#define UMBRA_H
+
+#include "storage/aio_types.h"
+#include "storage/block.h"
+#include "storage/relfilelocator.h"
+#include "storage/smgr.h"
+
+extern void uminit(void);
+extern void umopen(SMgrRelation reln);
+extern void umclose(SMgrRelation reln, ForkNumber forknum);
+extern void umdestroy(SMgrRelation reln);
+extern void umcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo);
+extern bool umexists(SMgrRelation reln, ForkNumber forknum);
+extern void umunlink(RelFileLocatorBackend rlocator, ForkNumber forknum, bool 
isRedo);
+extern void umextend(SMgrRelation reln, ForkNumber forknum,
+                                        BlockNumber blocknum, const void 
*buffer, bool skipFsync);
+extern void umzeroextend(SMgrRelation reln, ForkNumber forknum,
+                                                BlockNumber blocknum, int 
nblocks, bool skipFsync);
+extern bool umprefetch(SMgrRelation reln, ForkNumber forknum,
+                                          BlockNumber blocknum, int nblocks);
+extern uint32 ummaxcombine(SMgrRelation reln, ForkNumber forknum,
+                                                  BlockNumber blocknum);
+extern void umreadv(SMgrRelation reln, ForkNumber forknum, BlockNumber 
blocknum,
+                                       void **buffers, BlockNumber nblocks);
+extern void umstartreadv(PgAioHandle *ioh,
+                                                SMgrRelation reln, ForkNumber 
forknum,
+                                                BlockNumber blocknum,
+                                                void **buffers, BlockNumber 
nblocks);
+extern void umwritev(SMgrRelation reln, ForkNumber forknum, BlockNumber 
blocknum,
+                                        const void **buffers, BlockNumber 
nblocks, bool skipFsync);
+extern void umwriteback(SMgrRelation reln, ForkNumber forknum,
+                                               BlockNumber blocknum, 
BlockNumber nblocks);
+extern BlockNumber umnblocks(SMgrRelation reln, ForkNumber forknum);
+extern void umtruncate(SMgrRelation reln, ForkNumber forknum,
+                                          BlockNumber old_blocks, BlockNumber 
nblocks);
+extern void umimmedsync(SMgrRelation reln, ForkNumber forknum);
+extern void umregistersync(SMgrRelation reln, ForkNumber forknum);
+extern int     umfd(SMgrRelation reln, ForkNumber forknum,
+                                BlockNumber blocknum, uint32 *off);
+
+#endif                                                 /* UMBRA_H */
-- 
2.50.1 (Apple Git-155)



Reply via email to