WIP: pluggable init fork creation, relation size estimation, file creation.
authorAndres Freund <[email protected]>
Thu, 6 Dec 2018 04:09:05 +0000 (20:09 -0800)
committerAndres Freund <[email protected]>
Tue, 11 Dec 2018 01:36:51 +0000 (17:36 -0800)
This doesn't yet really work.

src/backend/access/heap/heapam_handler.c
src/backend/catalog/heap.c
src/backend/commands/tablecmds.c
src/backend/optimizer/util/plancat.c
src/backend/utils/cache/relcache.c
src/include/access/tableam.h
src/include/catalog/heap.h

index 49f8d833f616e2929a93e1e105137aa3a6066eaa..95513dfec8ddf09e0c47983109feb1fd1da8d378 100644 (file)
@@ -30,6 +30,7 @@
 #include "catalog/catalog.h"
 #include "catalog/index.h"
 #include "catalog/pg_am_d.h"
+#include "catalog/storage_xlog.h"
 #include "executor/executor.h"
 #include "pgstat.h"
 #include "storage/lmgr.h"
@@ -2062,6 +2063,28 @@ heap_copy_for_cluster(Relation OldHeap, Relation NewHeap, Relation OldIndex,
    pfree(isnull);
 }
 
+/*
+ * Set up an init fork for an unlogged table so that it can be correctly
+ * reinitialized on restart.  An immediate sync is required even if the
+ * page has been logged, because the write did not go through
+ * shared_buffers and therefore a concurrent checkpoint may have moved
+ * the redo pointer past our xlog record.  Recovery may as well remove it
+ * while replaying, for example, XLOG_DBASE_CREATE or XLOG_TBLSPC_CREATE
+ * record. Therefore, logging is necessary even if wal_level=minimal.
+ */
+static void
+heap_create_init_fork(Relation rel)
+{
+   Assert(rel->rd_rel->relkind == RELKIND_RELATION ||
+          rel->rd_rel->relkind == RELKIND_MATVIEW ||
+          rel->rd_rel->relkind == RELKIND_TOASTVALUE);
+   RelationOpenSmgr(rel);
+   smgrcreate(rel->rd_smgr, INIT_FORKNUM, false);
+   log_smgrcreate(&rel->rd_smgr->smgr_rnode.node, INIT_FORKNUM);
+   smgrimmedsync(rel->rd_smgr, INIT_FORKNUM);
+}
+
+
 static const TableAmRoutine heapam_methods = {
    .type = T_TableAmRoutine,
 
@@ -2098,6 +2121,7 @@ static const TableAmRoutine heapam_methods = {
    .scan_analyze_next_block = heapam_scan_analyze_next_block,
    .scan_analyze_next_tuple = heapam_scan_analyze_next_tuple,
    .relation_copy_for_cluster = heap_copy_for_cluster,
+   .relation_create_init_fork = heap_create_init_fork,
    .relation_sync = heap_sync,
 
    .begin_index_fetch = heapam_begin_index_fetch,
index f85eab1714c2a15210bcc3f07b7ec85631d11d33..a3015333f37cb3e13960785be040f7b07afaf586 100644 (file)
@@ -32,6 +32,7 @@
 #include "access/htup_details.h"
 #include "access/multixact.h"
 #include "access/sysattr.h"
+#include "access/tableam.h"
 #include "access/transam.h"
 #include "access/xact.h"
 #include "access/xlog.h"
@@ -1396,7 +1397,7 @@ heap_create_with_catalog(const char *relname,
     */
    if (relpersistence == RELPERSISTENCE_UNLOGGED &&
        relkind != RELKIND_PARTITIONED_TABLE)
-       heap_create_init_fork(new_rel_desc);
+       table_create_init_fork(new_rel_desc);
 
    /*
     * ok, the relation has been cataloged, so close our relations and return
@@ -1408,27 +1409,6 @@ heap_create_with_catalog(const char *relname,
    return relid;
 }
 
-/*
- * Set up an init fork for an unlogged table so that it can be correctly
- * reinitialized on restart.  An immediate sync is required even if the
- * page has been logged, because the write did not go through
- * shared_buffers and therefore a concurrent checkpoint may have moved
- * the redo pointer past our xlog record.  Recovery may as well remove it
- * while replaying, for example, XLOG_DBASE_CREATE or XLOG_TBLSPC_CREATE
- * record. Therefore, logging is necessary even if wal_level=minimal.
- */
-void
-heap_create_init_fork(Relation rel)
-{
-   Assert(rel->rd_rel->relkind == RELKIND_RELATION ||
-          rel->rd_rel->relkind == RELKIND_MATVIEW ||
-          rel->rd_rel->relkind == RELKIND_TOASTVALUE);
-   RelationOpenSmgr(rel);
-   smgrcreate(rel->rd_smgr, INIT_FORKNUM, false);
-   log_smgrcreate(&rel->rd_smgr->smgr_rnode.node, INIT_FORKNUM);
-   smgrimmedsync(rel->rd_smgr, INIT_FORKNUM);
-}
-
 /*
  *     RelationRemoveInheritance
  *
index 20f1e5f2c618640a449dc5a166be562ad0488a66..959b824e8815d5aeaede81eb2ae9614049080562 100644 (file)
@@ -1624,7 +1624,7 @@ ExecuteTruncateGuts(List *explicit_rels, List *relids, List *relids_logged,
            RelationSetNewRelfilenode(rel, rel->rd_rel->relpersistence,
                                      RecentXmin, minmulti);
            if (rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED)
-               heap_create_init_fork(rel);
+               table_create_init_fork(rel);
 
            heap_relid = RelationGetRelid(rel);
 
@@ -1641,7 +1641,7 @@ ExecuteTruncateGuts(List *explicit_rels, List *relids, List *relids_logged,
                                          toastrel->rd_rel->relpersistence,
                                          RecentXmin, minmulti);
                if (toastrel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED)
-                   heap_create_init_fork(toastrel);
+                   table_create_init_fork(toastrel);
                heap_close(toastrel, NoLock);
            }
 
index 58e8c7cc5f3d8f3e043801fa033d0adcdab66239..5e1b27be757e0c5bff8629b2b57b7f18c53a6f9f 100644 (file)
@@ -946,6 +946,20 @@ estimate_rel_size(Relation rel, int32 *attr_widths,
    BlockNumber relallvisible;
    double      density;
 
+#if 0
+   /*
+    * If the relation contains any specific EstimateRelSize
+    * function, use that instead of the regular default heap method.
+    */
+   if (rel->rd_tableamroutine &&
+           rel->rd_tableamroutine->EstimateRelSize)
+   {
+       rel->rd_tableamroutine->EstimateRelSize(rel, attr_widths, pages,
+                                               tuples, allvisfrac);
+       return;
+   }
+#endif
+
    switch (rel->rd_rel->relkind)
    {
        case RELKIND_RELATION:
index 8b79e5907731ad2a7bcf623386312293b008c926..120550f5268538d6ae30b8be17fe75ea099fd032 100644 (file)
@@ -3417,6 +3417,21 @@ RelationSetNewRelfilenode(Relation relation, char persistence,
    HeapTuple   tuple;
    Form_pg_class classform;
 
+
+#if 0
+   /*
+    * If the relation contains any specific SetNewFilenode
+    * function, use that instead of the regular default heap method.
+    */
+   if (relation->rd_tableamroutine &&
+           relation->rd_tableamroutine->SetNewFileNode)
+   {
+       relation->rd_tableamroutine->SetNewFileNode(relation, persistence,
+                                                   freezeXid, minmulti);
+       return;
+   }
+#endif
+
    /* Indexes, sequences must have Invalid frozenxid; other rels must not */
    Assert((relation->rd_rel->relkind == RELKIND_INDEX ||
            relation->rd_rel->relkind == RELKIND_SEQUENCE) ?
index 7364afa340c3f2af38e1651cea00b544df7c1c4c..966c0e00d888f6d8e7b7da628834cfbe12b50c11 100644 (file)
@@ -114,7 +114,13 @@ typedef void (*RelationCopyForCluster_function)(Relation NewHeap, Relation OldHe
                                       TransactionId OldestXmin, TransactionId FreezeXid, MultiXactId MultiXactCutoff,
                                       double *num_tuples, double *tups_vacuumed, double *tups_recently_dead);
 
+typedef void (*RelationCreateInitFork_function)(Relation rel);
+typedef void (*RelationSetNewFileNode_function)(Relation relation, char persistence,
+                                       TransactionId freezeXid, MultiXactId minmulti);
 typedef void (*RelationSync_function) (Relation relation);
+typedef void (*RelationEstimateSize_function)(Relation rel, int32 *attr_widths,
+                 BlockNumber *pages, double *tuples, double *allvisfrac);
+
 
 typedef const TupleTableSlotOps* (*SlotCallbacks_function) (Relation relation);
 
@@ -206,7 +212,11 @@ typedef struct TableAmRoutine
    RelationScanAnalyzeNextBlock_function scan_analyze_next_block;
    RelationScanAnalyzeNextTuple_function scan_analyze_next_tuple;
    RelationCopyForCluster_function relation_copy_for_cluster;
+
+   RelationCreateInitFork_function relation_create_init_fork;
+   RelationSetNewFileNode_function relation_set_new_filenode;
    RelationSync_function relation_sync;
+   RelationEstimateSize_function relation_estimate_size;
 
    /* Operations on relation scans */
    ScanBegin_function scan_begin;
@@ -646,6 +656,20 @@ table_copy_for_cluster(Relation OldHeap, Relation NewHeap, Relation OldIndex,
                                                      num_tuples, tups_vacuumed, tups_recently_dead);
 }
 
+static inline void
+table_create_init_fork(Relation rel)
+{
+   rel->rd_tableamroutine->relation_create_init_fork(rel);
+}
+
+static inline void
+table_set_new_filenode(Relation rel, char persistence,
+                      TransactionId freezeXid, MultiXactId minmulti)
+{
+   rel->rd_tableamroutine->relation_set_new_filenode(rel, persistence,
+                                                     freezeXid, minmulti);
+}
+
 /*
  * table_sync      - sync a heap, for use when no WAL has been written
  */
@@ -655,6 +679,14 @@ table_sync(Relation rel)
    rel->rd_tableamroutine->relation_sync(rel);
 }
 
+static inline void
+table_estimate_size(Relation rel, int32 *attr_widths,
+                   BlockNumber *pages, double *tuples, double *allvisfrac)
+{
+   rel->rd_tableamroutine->relation_estimate_size(rel, attr_widths,
+                                                  pages, tuples, allvisfrac);
+}
+
 static inline double
 table_index_build_scan(Relation heapRelation,
                       Relation indexRelation,
index cedc19fbcf5a8e0f46030ae07fb567065d70682d..9fbca37269e0c31626b4bcfecef28e1b577037d2 100644 (file)
@@ -75,8 +75,6 @@ extern Oid heap_create_with_catalog(const char *relname,
                         Oid relrewrite,
                         ObjectAddress *typaddress);
 
-extern void heap_create_init_fork(Relation rel);
-
 extern void heap_drop_with_catalog(Oid relid);
 
 extern void heap_truncate(List *relids);