提交 b95059a8 编写于 作者: H Hubert Zhang 提交者: Hubert Zhang

Add hook functions for diskquota extension.

Diskquota extension needs two kinds of hooks:
1. hooks to detect active tables when tables are being modified.
2. hooks to cancel a query whose quota limit is reached.

These two kinds of hooks are described in detail in Wiki:
https://github.com/greenplum-db/gpdb/wiki/Greenplum-Diskquota-Design#design-of-diskquota
They are corresponding to two components: Quota Enforcement Operator
and Quota Change Detector.
Co-authored-by: NHaozhou Wang <hawang@pivotal.io>
Co-authored-by: NHao Wu <gfphoenix78@gmail.com>
上级 17068f86
...@@ -23,6 +23,11 @@ ...@@ -23,6 +23,11 @@
#include "cdb/cdbbufferedappend.h" #include "cdb/cdbbufferedappend.h"
#include "utils/guc.h" #include "utils/guc.h"
/*
* Hook function in BufferedAppendWrite, used by plugins to call
* when the size of AO table is increased.
*/
BufferedAppendWrite_hook_type BufferedAppendWrite_hook = NULL;
static void BufferedAppendWrite( static void BufferedAppendWrite(
BufferedAppend *bufferedAppend, BufferedAppend *bufferedAppend,
bool needsWAL); bool needsWAL);
...@@ -196,6 +201,8 @@ BufferedAppendWrite(BufferedAppend *bufferedAppend, bool needsWAL) ...@@ -196,6 +201,8 @@ BufferedAppendWrite(BufferedAppend *bufferedAppend, bool needsWAL)
bufferedAppend->filePathName, bufferedAppend->filePathName,
bufferedAppend->largeWritePosition, bufferedAppend->largeWritePosition,
bytestotal); bytestotal);
if (BufferedAppendWrite_hook)
(*BufferedAppendWrite_hook)(bufferedAppend);
/* /*
* Log each varblock to the XLog. Write to the file first, before * Log each varblock to the XLog. Write to the file first, before
......
...@@ -48,6 +48,8 @@ ...@@ -48,6 +48,8 @@
*/ */
#define DISPATCH_WAIT_CANCEL_TIMEOUT_MSEC 100 #define DISPATCH_WAIT_CANCEL_TIMEOUT_MSEC 100
DispatcherCheckPerms_hook_type DispatcherCheckPerms_hook = NULL;
typedef struct CdbDispatchCmdAsync typedef struct CdbDispatchCmdAsync
{ {
...@@ -539,6 +541,12 @@ checkDispatchResult(CdbDispatcherState *ds, ...@@ -539,6 +541,12 @@ checkDispatchResult(CdbDispatcherState *ds,
checkSegmentAlive(pParms); checkSegmentAlive(pParms);
} }
/* Hook to check permissions when dispatcher timeout */
if (DispatcherCheckPerms_hook && pParms->waitMode == DISPATCH_WAIT_NONE)
{
(*DispatcherCheckPerms_hook)();
}
if (!wait) if (!wait)
break; break;
} }
......
...@@ -32,6 +32,16 @@ ...@@ -32,6 +32,16 @@
#include "utils/hsearch.h" #include "utils/hsearch.h"
#include "utils/inval.h" #include "utils/inval.h"
/*
* Hook for plugins to extend smgr functions.
* for example, collect statistics from smgr functions
* via recording the active relfilenode information.
*/
smgrcreate_hook_type smgrcreate_hook = NULL;
smgrextend_hook_type smgrextend_hook = NULL;
smgrtruncate_hook_type smgrtruncate_hook = NULL;
smgrdounlinkall_hook_type smgrdounlinkall_hook = NULL;
/* /*
* Each backend has a hashtable that stores all extant SMgrRelation objects. * Each backend has a hashtable that stores all extant SMgrRelation objects.
* In addition, "unowned" SMgrRelation objects are chained together in a list. * In addition, "unowned" SMgrRelation objects are chained together in a list.
...@@ -329,6 +339,11 @@ smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo) ...@@ -329,6 +339,11 @@ smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
if (isRedo && reln->md_fd[forknum] != NULL) if (isRedo && reln->md_fd[forknum] != NULL)
return; return;
if (smgrcreate_hook)
{
(*smgrcreate_hook)(reln, forknum, isRedo);
}
/* /*
* We may be using the target table space for the first time in this * We may be using the target table space for the first time in this
* database, so create a per-database subdirectory if needed. * database, so create a per-database subdirectory if needed.
...@@ -445,6 +460,11 @@ smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo, char *relstorages) ...@@ -445,6 +460,11 @@ smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo, char *relstorages)
if (nrels == 0) if (nrels == 0)
return; return;
if (smgrdounlinkall_hook)
{
(*smgrdounlinkall_hook)(rels, nrels, isRedo, relstorages);
}
/* /*
* create an array which contains all relations to be dropped, and close * create an array which contains all relations to be dropped, and close
* each relation's forks at the smgr level while at it * each relation's forks at the smgr level while at it
...@@ -519,6 +539,11 @@ void ...@@ -519,6 +539,11 @@ void
smgrextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, smgrextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
char *buffer, bool skipFsync) char *buffer, bool skipFsync)
{ {
if (smgrextend_hook)
{
(*smgrextend_hook)(reln, forknum, blocknum, buffer, skipFsync);
}
mdextend(reln, forknum, blocknum, buffer, skipFsync); mdextend(reln, forknum, blocknum, buffer, skipFsync);
} }
...@@ -587,6 +612,11 @@ smgrnblocks(SMgrRelation reln, ForkNumber forknum) ...@@ -587,6 +612,11 @@ smgrnblocks(SMgrRelation reln, ForkNumber forknum)
void void
smgrtruncate(SMgrRelation reln, ForkNumber forknum, BlockNumber nblocks) smgrtruncate(SMgrRelation reln, ForkNumber forknum, BlockNumber nblocks)
{ {
if (smgrtruncate_hook)
{
(*smgrtruncate_hook)(reln, forknum, nblocks);
}
/* /*
* Get rid of any buffers for the about-to-be-deleted blocks. bufmgr will * Get rid of any buffers for the about-to-be-deleted blocks. bufmgr will
* just drop them without bothering to write the contents. * just drop them without bothering to write the contents.
......
...@@ -182,4 +182,8 @@ extern void BufferedAppendCompleteFile( ...@@ -182,4 +182,8 @@ extern void BufferedAppendCompleteFile(
extern void BufferedAppendFinish( extern void BufferedAppendFinish(
BufferedAppend *bufferedAppend); BufferedAppend *bufferedAppend);
/* Hook type and declaration in BufferedAppendWrite */
typedef void (*BufferedAppendWrite_hook_type)(BufferedAppend *bufferedAppend);
extern PGDLLIMPORT BufferedAppendWrite_hook_type BufferedAppendWrite_hook;
#endif /* CDBBUFFEREDAPPEND_H */ #endif /* CDBBUFFEREDAPPEND_H */
...@@ -18,4 +18,12 @@ ...@@ -18,4 +18,12 @@
extern DispatcherInternalFuncs DispatcherAsyncFuncs; extern DispatcherInternalFuncs DispatcherAsyncFuncs;
/*
* Hook for plugins to check permissions in dispatcher
* One example is to check whether disk quota limit is
* exceeded for the table which is loading data.
*/
typedef bool (*DispatcherCheckPerms_hook_type) (void);
extern PGDLLIMPORT DispatcherCheckPerms_hook_type DispatcherCheckPerms_hook;
#endif #endif
...@@ -146,4 +146,32 @@ extern Datum smgrin(PG_FUNCTION_ARGS); ...@@ -146,4 +146,32 @@ extern Datum smgrin(PG_FUNCTION_ARGS);
extern Datum smgreq(PG_FUNCTION_ARGS); extern Datum smgreq(PG_FUNCTION_ARGS);
extern Datum smgrne(PG_FUNCTION_ARGS); extern Datum smgrne(PG_FUNCTION_ARGS);
/*
* Hook for plugins to extend smgr functions.
* for example, collect statistics from smgr functions
* via recording the active relfilenode information.
*/
typedef void (*smgrcreate_hook_type)(SMgrRelation reln,
ForkNumber forknum,
bool isRedo);
extern PGDLLIMPORT smgrcreate_hook_type smgrcreate_hook;
typedef void (*smgrextend_hook_type)(SMgrRelation reln,
ForkNumber forknum,
BlockNumber blocknum,
char *buffer,
bool skipFsync);
extern PGDLLIMPORT smgrextend_hook_type smgrextend_hook;
typedef void (*smgrtruncate_hook_type)(SMgrRelation reln,
ForkNumber forknum,
BlockNumber nblocks);
extern PGDLLIMPORT smgrtruncate_hook_type smgrtruncate_hook;
typedef void (*smgrdounlinkall_hook_type)(SMgrRelation *rels,
int nrels,
bool isRedo,
char *relstorages);
extern PGDLLIMPORT smgrdounlinkall_hook_type smgrdounlinkall_hook;
#endif /* SMGR_H */ #endif /* SMGR_H */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册