From 8094682bf16e25873376b29ffd0f8edae9a6d735 Mon Sep 17 00:00:00 2001 From: Hari Date: Thu, 1 Jun 2017 15:22:04 +1000 Subject: [PATCH 03/10] Storage access method API functions --- src/backend/access/heap/Makefile | 3 +- src/backend/access/heap/storageamapi.c | 103 +++++++++++++++ src/include/access/storageamapi.h | 228 +++++++++++++++++++++++++++++++++ 3 files changed, 333 insertions(+), 1 deletion(-) create mode 100644 src/backend/access/heap/storageamapi.c create mode 100644 src/include/access/storageamapi.h diff --git a/src/backend/access/heap/Makefile b/src/backend/access/heap/Makefile index b83d496..35e7b92 100644 --- a/src/backend/access/heap/Makefile +++ b/src/backend/access/heap/Makefile @@ -12,6 +12,7 @@ subdir = src/backend/access/heap top_builddir = ../../../.. include $(top_builddir)/src/Makefile.global -OBJS = heapam.o hio.o pruneheap.o rewriteheap.o syncscan.o tuptoaster.o visibilitymap.o +OBJS = heapam.o hio.o pruneheap.o rewriteheap.o storageamapi.o \ + syncscan.o tuptoaster.o visibilitymap.o include $(top_srcdir)/src/backend/common.mk diff --git a/src/backend/access/heap/storageamapi.c b/src/backend/access/heap/storageamapi.c new file mode 100644 index 0000000..def2029 --- /dev/null +++ b/src/backend/access/heap/storageamapi.c @@ -0,0 +1,103 @@ +/*---------------------------------------------------------------------- + * + * storageamapi.c + * Support routines for API for Postgres storage access methods + * + * FIXME: looks like this should be in amapi.c. + * + * Copyright (c) 2016, PostgreSQL Global Development Group + * + * src/backend/access/heap/storageamapi.c + *---------------------------------------------------------------------- + */ +#include "postgres.h" + +#include "access/htup_details.h" +#include "access/storageamapi.h" +#include "catalog/pg_am.h" +#include "catalog/pg_proc.h" +#include "utils/syscache.h" +#include "utils/memutils.h" + + +/* + * GetStorageAmRoutine + * Call the specified access method handler routine to get its + * StorageAmRoutine struct, which will be palloc'd in the caller's + * memory context. + */ +StorageAmRoutine * +GetStorageAmRoutine(Oid amhandler) +{ + Datum datum; + StorageAmRoutine *routine; + + datum = OidFunctionCall0(amhandler); + routine = (StorageAmRoutine *) DatumGetPointer(datum); + + if (routine == NULL || !IsA(routine, StorageAmRoutine)) + elog(ERROR, "storage access method handler %u did not return a StorageAmRoutine struct", + amhandler); + + return routine; +} + +/* A crock */ +StorageAmRoutine * +GetHeapamStorageAmRoutine(void) +{ + Datum datum; + static StorageAmRoutine *HeapamStorageAmRoutine = NULL; + + if (HeapamStorageAmRoutine == NULL) + { + MemoryContext oldcxt; + + oldcxt = MemoryContextSwitchTo(TopMemoryContext); + datum = OidFunctionCall0(HEAPAM_STORAGE_AM_HANDLER_OID); + HeapamStorageAmRoutine = (StorageAmRoutine *) DatumGetPointer(datum); + MemoryContextSwitchTo(oldcxt); + } + + return HeapamStorageAmRoutine; +} + +/* + * GetStorageAmRoutineByAmId - look up the handler of the storage access + * method with the given OID, and get its StorageAmRoutine struct. + */ +StorageAmRoutine * +GetStorageAmRoutineByAmId(Oid amoid) +{ + regproc amhandler; + HeapTuple tuple; + Form_pg_am amform; + + /* Get handler function OID for the access method */ + tuple = SearchSysCache1(AMOID, ObjectIdGetDatum(amoid)); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "cache lookup failed for access method %u", + amoid); + amform = (Form_pg_am) GETSTRUCT(tuple); + + /* Check that it is a storage access method */ + if (amform->amtype != AMTYPE_STORAGE) + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("access method \"%s\" is not of type %s", + NameStr(amform->amname), "STORAGE"))); + + amhandler = amform->amhandler; + + /* Complain if handler OID is invalid */ + if (!RegProcedureIsValid(amhandler)) + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("storage access method \"%s\" does not have a handler", + NameStr(amform->amname)))); + + ReleaseSysCache(tuple); + + /* And finally, call the handler function to get the API struct. */ + return GetStorageAmRoutine(amhandler); +} diff --git a/src/include/access/storageamapi.h b/src/include/access/storageamapi.h new file mode 100644 index 0000000..87130c9 --- /dev/null +++ b/src/include/access/storageamapi.h @@ -0,0 +1,228 @@ +/*--------------------------------------------------------------------- + * + * storageamapi.h + * API for Postgres storage access methods + * + * Copyright (c) 2016, PostgreSQL Global Development Group + * + * src/include/access/storageamapi.h + *--------------------------------------------------------------------- + */ +#ifndef STORAGEAMAPI_H +#define STORAGEAMAPI_H + +#include "access/heapam.h" +#include "access/sdir.h" +#include "access/skey.h" +#include "executor/tuptable.h" +#include "utils/relcache.h" +#include "utils/snapshot.h" + +/* A physical tuple coming from a storage AM scan */ +typedef void *StorageTuple; + +typedef HeapScanDesc (*scan_begin_function) (Relation relation, + Snapshot snapshot, + int nkeys, + ScanKey key); +typedef HeapScanDesc (*scan_begin_catalog_function) (Relation relation, + int nkeys, + ScanKey key); +typedef HeapScanDesc (*scan_begin_strat_function) (Relation relation, + Snapshot snapshot, + int nkeys, + ScanKey key, + bool allow_strat, + bool allow_sync); +typedef HeapScanDesc (*scan_begin_bm_function) (Relation relation, + Snapshot snapshot, + int nkeys, + ScanKey key); +typedef HeapScanDesc (*scan_begin_sampling_function) (Relation relation, + Snapshot snapshot, + int nkeys, + ScanKey key, + bool allow_strat, + bool allow_sync, + bool allow_pagemode); +typedef void (*scan_setlimits_function) (HeapScanDesc sscan, BlockNumber startBlk, BlockNumber numBlks); + +/* must return a TupleTableSlot? */ +typedef StorageTuple (*scan_getnext_function) (HeapScanDesc scan, + ScanDirection direction); + +typedef void (*scan_end_function) (HeapScanDesc scan); + + +typedef void (*scan_getpage_function) (HeapScanDesc scan, BlockNumber page); +typedef void (*scan_rescan_function) (HeapScanDesc scan, ScanKey key); +typedef void (*scan_rescan_set_params_function) (HeapScanDesc scan, ScanKey key, + bool allow_strat, bool allow_sync, bool allow_pagemode); +typedef void (*scan_update_snapshot_function) (HeapScanDesc scan, Snapshot snapshot); + +typedef Oid (*tuple_insert_function) (Relation relation, + TupleTableSlot *tupslot, + CommandId cid, + int options, + BulkInsertState bistate, + ItemPointer iptr); + +typedef HTSU_Result (*tuple_delete_function) (Relation relation, + ItemPointer tid, + CommandId cid, + Snapshot crosscheck, + bool wait, + HeapUpdateFailureData *hufd); + +typedef HTSU_Result (*tuple_update_function) (Relation relation, + ItemPointer otid, + TupleTableSlot *slot, + CommandId cid, + Snapshot crosscheck, + bool wait, + HeapUpdateFailureData *hufd, + LockTupleMode *lockmode, + ItemPointer iptr); +typedef bool (*tuple_fetch_function) (Relation relation, + ItemPointer tid, + Snapshot snapshot, + StorageTuple *tuple, + Buffer *userbuf, + bool keep_buf, + Relation stats_relation); + +typedef HTSU_Result (*tuple_lock_function) (Relation relation, + ItemPointer tid, + StorageTuple tuple, + CommandId cid, + LockTupleMode mode, + LockWaitPolicy wait_policy, + bool follow_update, + Buffer *buffer, + HeapUpdateFailureData *hufd); + +typedef TransactionId (*tuple_get_xmin_function) (StorageTuple tuple); + +typedef TransactionId (*tuple_get_updated_xid_function) (StorageTuple tuple); + +typedef CommandId (*tuple_get_cmin_function) (StorageTuple tuple); + +typedef ItemPointer (*tuple_get_itempointer_function) (StorageTuple tuple); + +typedef ItemPointerData (*tuple_get_ctid_function) (StorageTuple tuple); + +typedef void (*slot_set_tuple_oid_function) (TupleTableSlot *slot, Oid tupleoid); + +typedef StorageTuple (*tuple_from_datum_function) (Datum data, Oid tableoid); + +typedef bool (* tuple_is_heaponly_function) (StorageTuple tuple); + +typedef void (*slot_store_tuple_function) (TupleTableSlot *slot, + StorageTuple tuple, + bool shouldFree); +typedef void (*slot_clear_tuple_function) (TupleTableSlot *slot); +typedef void (*slot_materialize_tuple_function) (TupleTableSlot *slot); +typedef Datum (*slot_getattr_function) (TupleTableSlot *slot, + int attnum, bool *isnull); +typedef void (*slot_getallattrs_function) (TupleTableSlot *slot); +typedef void (*slot_getsomeattrs_function) (TupleTableSlot *slot, int attnum); +typedef bool (*slot_attisnull_function) (TupleTableSlot *slot, int attnum); + +typedef HeapTuple (*slot_copy_tuple_function) (TupleTableSlot *slot); +typedef MinimalTuple (*slot_copy_min_tuple_function) (TupleTableSlot *slot); +typedef HeapTuple (*slot_get_tuple_function) (TupleTableSlot *slot); +typedef bool (*slot_is_physical_tuple_function) (TupleTableSlot *slot); + +typedef void (*slot_update_tableoid_function) (TupleTableSlot *slot, Oid tableoid); + +typedef void (*tuple_set_speculative_token_function) (TupleTableSlot *slot, + uint32 specToken); +typedef void (*speculative_finish_function) (Relation rel, + TupleTableSlot *slot); +typedef void (*speculative_abort_function) (Relation rel, + TupleTableSlot *slot); + + +/* + * API struct for a storage AM. Note this must be stored in a single palloc'd + * chunk of memory. + * + * XXX currently all functions are together in a single struct. Would it be + * worthwhile to split the slot-accessor functions to a different struct? + * That way, MinimalTuple could be handled without a complete StorageAmRoutine + * for them -- it'd only have a few functions in TupleTableSlotAmRoutine or so. + */ +typedef struct StorageAmRoutine +{ + NodeTag type; + + /* Operations on relation scans */ + scan_begin_function scan_begin; + scan_begin_catalog_function scan_begin_catalog; + scan_begin_strat_function scan_begin_strat; + scan_begin_bm_function scan_begin_bm; + scan_begin_sampling_function scan_begin_sampling; + scan_setlimits_function scansetlimits; + scan_getnext_function scan_getnext; + scan_end_function scan_end; + scan_getpage_function scan_getpage; + scan_rescan_function scan_rescan; + scan_rescan_set_params_function scan_rescan_set_params; + scan_update_snapshot_function scan_update_snapshot; + + // heap_sync_function heap_sync; /* heap_sync */ + /* not implemented */ + // parallelscan_estimate_function parallelscan_estimate; /* heap_parallelscan_estimate */ + // parallelscan_initialize_function parallelscan_initialize; /* heap_parallelscan_initialize */ + // parallelscan_begin_function parallelscan_begin; /* heap_beginscan_parallel */ + + /* Operations on physical tuples */ + tuple_insert_function tuple_insert; /* heap_insert */ + tuple_update_function tuple_update; /* heap_update */ + tuple_delete_function tuple_delete; /* heap_delete */ + tuple_fetch_function tuple_fetch; /* heap_fetch */ + tuple_lock_function tuple_lock; /* heap_lock_tuple */ + + tuple_get_xmin_function tuple_get_xmin; /* HeapTupleHeaderGetXmin */ + tuple_get_updated_xid_function tuple_get_updated_xid; + tuple_get_cmin_function tuple_get_cmin; /* HeapTupleHeaderGetCmin */ + tuple_get_itempointer_function tuple_get_itempointer; + tuple_get_ctid_function tuple_get_ctid; + tuple_is_heaponly_function tuple_is_heaponly; + tuple_from_datum_function tuple_from_datum; + + /* Operations on TupleTableSlot */ + slot_store_tuple_function slot_store_tuple; + slot_getattr_function slot_getattr; + slot_getallattrs_function slot_getallattrs; + slot_getsomeattrs_function slot_getsomeattrs; + slot_attisnull_function slot_attisnull; + slot_clear_tuple_function slot_clear_tuple; + slot_materialize_tuple_function slot_materialize_tuple; + slot_copy_tuple_function slot_copy_tuple; + slot_get_tuple_function slot_get_tuple; + slot_copy_min_tuple_function slot_copy_min_tuple; + slot_is_physical_tuple_function slot_is_physical_tuple; + slot_update_tableoid_function slot_update_tableoid; + slot_set_tuple_oid_function slot_set_tuple_oid; + + /* + * Speculative insertion support operations + * + * Setting a tuple's speculative token is a slot-only operation, so no need + * for a storage AM method, but after inserting a tuple containing a + * speculative token, the insertion must be completed by these routines: + */ + tuple_set_speculative_token_function tuple_set_speculative_token; /* HeapTupleHeaderSetSpeculativeToken */ + speculative_finish_function speculative_finish; + speculative_abort_function speculative_abort; +} StorageAmRoutine; + +extern StorageAmRoutine *GetStorageAmRoutine(Oid amhandler); +extern StorageAmRoutine *GetStorageAmRoutineByAmId(Oid amoid); + +extern StorageAmRoutine *GetHeapamStorageAmRoutine(void); + +extern void heap_abort_speculative(Relation relation, HeapTuple tuple); + +#endif /* STORAGEAMAPI_H */ -- 2.7.4.windows.1