Skip to content

Commit 6ebad75

Browse files
zhangh43HaozhouWang
authored andcommitted
Refactor active table logic.
Put all the active table code into one file activetable.c Replace relfilenode convert to Oid code by built-in function Add answer files. Co-authored-by: Haozhou Wang <hawang@pivotal.io> Co-authored-by: Hubert Zhang <hzhang@pivotal.io>
1 parent 4dc58e8 commit 6ebad75

24 files changed

Lines changed: 611 additions & 155 deletions

gpcontrib/diskquota/activetable.c

Lines changed: 82 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
*
77
* Copyright (C) 2013, PostgreSQL Global Development Group
88
*
9-
* IDENTIFICATION
10-
* contrib/diskquota/activetable.c
119
*
1210
* -------------------------------------------------------------------------
1311
*/
@@ -24,20 +22,21 @@
2422
#include "storage/smgr.h"
2523
#include "utils/builtins.h"
2624
#include "utils/fmgroids.h"
25+
#include "utils/relfilenodemap.h"
2726

2827
#include "activetable.h"
29-
#include "diskquota.h"
3028

3129
HTAB *active_tables_map = NULL;
3230
static SmgrStat_hook_type prev_SmgrStat_hook = NULL;
33-
static ScanKeyData relfilenode_skey[2];
3431

3532
static void report_active_table_SmgrStat(SMgrRelation reln);
36-
HTAB* get_active_tables(void);
33+
static HTAB* get_active_tables_stats(void);
34+
static HTAB* get_all_tables_stats(void);
35+
3736
void init_active_table_hook(void);
3837
void init_shm_worker_active_tables(void);
3938
void init_lock_active_tables(void);
40-
void init_relfilenode_key(void);
39+
HTAB* pg_fetch_active_tables(bool);
4140

4241
/*
4342
* Register smgr hook to detect active table.
@@ -86,39 +85,84 @@ void init_lock_active_tables(void)
8685
}
8786

8887
/*
89-
* Init relfilenode key to index search table oid
90-
* given relfilenode and tablespace.
88+
* Fetch active table file size statistics.
89+
* If force is true, then fetch all the tables.
9190
*/
92-
void
93-
init_relfilenode_key(void)
91+
HTAB* pg_fetch_active_tables(bool force)
92+
{
93+
if (force)
94+
{
95+
return get_all_tables_stats();
96+
}
97+
else
98+
{
99+
return get_active_tables_stats();
100+
}
101+
}
102+
103+
/*
104+
* Get the table size statistics for all the tables
105+
*/
106+
static HTAB*
107+
get_all_tables_stats()
94108
{
95-
int i;
109+
HTAB *local_table_stats_map = NULL;
110+
HASHCTL ctl;
111+
HeapTuple tuple;
112+
Relation classRel;
113+
HeapScanDesc relScan;
114+
115+
memset(&ctl, 0, sizeof(ctl));
116+
ctl.keysize = sizeof(Oid);
117+
ctl.entrysize = sizeof(DiskQuotaActiveTableEntry);
118+
ctl.hcxt = CurrentMemoryContext;
119+
ctl.hash = oid_hash;
96120

97-
/* build skey */
98-
MemSet(&relfilenode_skey, 0, sizeof(relfilenode_skey));
121+
local_table_stats_map = hash_create("local table map with table size info",
122+
1024,
123+
&ctl,
124+
HASH_ELEM | HASH_CONTEXT | HASH_FUNCTION);
125+
126+
classRel = heap_open(RelationRelationId, AccessShareLock);
127+
relScan = heap_beginscan_catalog(classRel, 0, NULL);
99128

100-
for (i = 0; i < 2; i++)
129+
while ((tuple = heap_getnext(relScan, ForwardScanDirection)) != NULL)
101130
{
102-
fmgr_info_cxt(F_OIDEQ,
103-
&relfilenode_skey[i].sk_func,
104-
CacheMemoryContext);
105-
relfilenode_skey[i].sk_strategy = BTEqualStrategyNumber;
106-
relfilenode_skey[i].sk_subtype = InvalidOid;
107-
relfilenode_skey[i].sk_collation = InvalidOid;
131+
Oid relOid;
132+
DiskQuotaActiveTableEntry *entry;
133+
134+
Form_pg_class classForm = (Form_pg_class) GETSTRUCT(tuple);
135+
if (classForm->relkind != RELKIND_RELATION &&
136+
classForm->relkind != RELKIND_MATVIEW)
137+
continue;
138+
relOid = HeapTupleGetOid(tuple);
139+
140+
/* ignore system table*/
141+
if (relOid < FirstNormalObjectId)
142+
continue;
143+
144+
entry = (DiskQuotaActiveTableEntry *) hash_search(local_table_stats_map, &relOid, HASH_ENTER, NULL);
145+
146+
entry->tableoid = relOid;
147+
entry->tablesize = (Size) DatumGetInt64(DirectFunctionCall1(pg_total_relation_size,
148+
ObjectIdGetDatum(relOid)));
149+
108150
}
109151

110-
relfilenode_skey[0].sk_attno = Anum_pg_class_reltablespace;
111-
relfilenode_skey[1].sk_attno = Anum_pg_class_relfilenode;
112-
}
152+
heap_endscan(relScan);
153+
heap_close(classRel, AccessShareLock);
113154

155+
return local_table_stats_map;
156+
}
114157
/*
115158
* Get local active table with table oid and table size info.
116159
* This function first copies active table map from shared memory
117160
* to local active table map with refilenode info. Then traverses
118161
* the local map and find corresponding table oid and table file
119162
* size. Finnaly stores them into local active table map and return.
120163
*/
121-
HTAB* get_active_tables()
164+
static HTAB*
165+
get_active_tables_stats()
122166
{
123167
HASHCTL ctl;
124168
HTAB *local_active_table_file_map = NULL;
@@ -127,9 +171,6 @@ HTAB* get_active_tables()
127171
DiskQuotaActiveTableFileEntry *active_table_file_entry;
128172
DiskQuotaActiveTableEntry *active_table_entry;
129173

130-
Relation relation;
131-
HeapTuple tuple;
132-
SysScanDesc relScan;
133174
Oid relOid;
134175

135176
memset(&ctl, 0, sizeof(ctl));
@@ -178,56 +219,34 @@ HTAB* get_active_tables()
178219
&ctl,
179220
HASH_ELEM | HASH_CONTEXT | HASH_FUNCTION);
180221

181-
relation = heap_open(RelationRelationId, AccessShareLock);
182222
/* traverse local active table map and calculate their file size. */
183223
hash_seq_init(&iter, local_active_table_file_map);
184224
/* scan whole local map, get the oid of each table and calculate the size of them */
185225
while ((active_table_file_entry = (DiskQuotaActiveTableFileEntry *) hash_seq_search(&iter)) != NULL)
186226
{
187227
Size tablesize;
188228
bool found;
189-
ScanKeyData skey[2];
190-
Oid reltablespace;
191229

192-
reltablespace = active_table_file_entry->tablespaceoid;
193-
194-
/* pg_class will show 0 when the value is actually MyDatabaseTableSpace */
195-
if (reltablespace == MyDatabaseTableSpace)
196-
reltablespace = 0;
197-
198-
/* set scan arguments */
199-
memcpy(skey, relfilenode_skey, sizeof(skey));
200-
skey[0].sk_argument = ObjectIdGetDatum(reltablespace);
201-
skey[1].sk_argument = ObjectIdGetDatum(active_table_file_entry->relfilenode);
202-
relScan = systable_beginscan(relation,
203-
ClassTblspcRelfilenodeIndexId,
204-
true,
205-
NULL,
206-
2,
207-
skey);
208-
209-
tuple = systable_getnext(relScan);
210-
211-
if (!HeapTupleIsValid(tuple))
230+
relOid = RelidByRelfilenode(active_table_file_entry->tablespaceoid, active_table_file_entry->relfilenode);
231+
232+
//TODO replace DirectFunctionCall1 by a new total relation size function, which could handle Invalid relOid
233+
/* avoid to generate ERROR if relOid is not existed (i.e. table has been droped) */
234+
PG_TRY();
212235
{
213-
systable_endscan(relScan);
214-
continue;
236+
tablesize = (Size) DatumGetInt64(DirectFunctionCall1(pg_total_relation_size,
237+
ObjectIdGetDatum(relOid)));
215238
}
216-
relOid = HeapTupleGetOid(tuple);
217-
218-
/* Call function directly to get size of table by oid */
219-
tablesize = (Size) DatumGetInt64(DirectFunctionCall1(pg_total_relation_size, ObjectIdGetDatum(relOid)));
220-
221-
active_table_entry = hash_search(local_active_table_stats_map, &relOid, HASH_ENTER, &found);
222-
if (active_table_entry)
239+
PG_CATCH();
223240
{
224-
active_table_entry->tableoid = relOid;
225-
active_table_entry->tablesize = tablesize;
241+
FlushErrorState();
242+
tablesize = 0;
226243
}
227-
systable_endscan(relScan);
244+
PG_END_TRY();
245+
active_table_entry = hash_search(local_active_table_stats_map, &relOid, HASH_ENTER, &found);
246+
active_table_entry->tableoid = relOid;
247+
active_table_entry->tablesize = tablesize;
228248
}
229249
elog(DEBUG1, "active table number is:%ld", hash_get_num_entries(local_active_table_file_map));
230-
heap_close(relation, AccessShareLock);
231250
hash_destroy(local_active_table_file_map);
232251
return local_active_table_stats_map;
233252
}

gpcontrib/diskquota/activetable.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#ifndef ACTIVE_TABLE_H
22
#define ACTIVE_TABLE_H
33

4-
#include "storage/lwlock.h"
54
#include "diskquota.h"
65

76
/* Cache to detect the active table list */
@@ -19,9 +18,8 @@ typedef struct DiskQuotaActiveTableEntry
1918
} DiskQuotaActiveTableEntry;
2019

2120

22-
extern HTAB* get_active_tables(void);
21+
extern HTAB* pg_fetch_active_tables(bool);
2322
extern void init_active_table_hook(void);
24-
extern void init_relfilenode_key(void);
2523
extern void init_shm_worker_active_tables(void);
2624
extern void init_lock_active_tables(void);
2725

gpcontrib/diskquota/data/generate_insert.py

Lines changed: 0 additions & 6 deletions
This file was deleted.

gpcontrib/diskquota/data/generate_table.py

Lines changed: 0 additions & 8 deletions
This file was deleted.

gpcontrib/diskquota/diskquota.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99
*
1010
* Copyright (C) 2013, PostgreSQL Global Development Group
1111
*
12-
* IDENTIFICATION
13-
* contrib/diskquota/diskquota.c
1412
*
1513
* -------------------------------------------------------------------------
1614
*/
@@ -266,9 +264,6 @@ disk_quota_launcher_main(Datum main_arg)
266264
/* We're now ready to receive signals */
267265
BackgroundWorkerUnblockSignals();
268266

269-
/* Connect to our database */
270-
//BackgroundWorkerInitializeConnection("postgres", NULL, 0);
271-
272267
memset(&hash_ctl, 0, sizeof(hash_ctl));
273268
hash_ctl.keysize = NAMEDATALEN;
274269
hash_ctl.entrysize = sizeof(DiskQuotaWorkerEntry);
@@ -279,7 +274,7 @@ disk_quota_launcher_main(Datum main_arg)
279274
HASH_ELEM);
280275

281276
dblist = get_database_list();
282-
277+
elog(LOG,"diskquota launcher started");
283278
foreach(cell, dblist)
284279
{
285280
char *db_name;
@@ -468,6 +463,7 @@ start_worker(char* dbname)
468463
bool found;
469464
DiskQuotaWorkerEntry* workerentry;
470465

466+
memset(&worker, 0, sizeof(BackgroundWorker));
471467
worker.bgw_flags = BGWORKER_SHMEM_ACCESS |
472468
BGWORKER_BACKEND_DATABASE_CONNECTION;
473469
worker.bgw_start_time = BgWorkerStart_RecoveryFinished;
@@ -477,6 +473,7 @@ start_worker(char* dbname)
477473
snprintf(worker.bgw_name, BGW_MAXLEN, "%s", dbname);
478474
/* set bgw_notify_pid so that we can use WaitForBackgroundWorkerStartup */
479475
worker.bgw_notify_pid = MyProcPid;
476+
worker.bgw_main_arg = (Datum) 0;
480477

481478
if (!RegisterDynamicBackgroundWorker(&worker, &handle))
482479
return -1;

gpcontrib/diskquota/enforcement.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
*
88
* Copyright (C) 2013, PostgreSQL Global Development Group
99
*
10-
* IDENTIFICATION
11-
* contrib/diskquota/enforcement.c
1210
*
1311
* -------------------------------------------------------------------------
1412
*/
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
drop table badquota.t1;
2+
drop role testbody;
3+
drop schema badquota;
4+
drop extension diskquota;

gpcontrib/diskquota/expected/dummy.out

Whitespace-only changes.

gpcontrib/diskquota/expected/empty.out

Whitespace-only changes.
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
create extension diskquota;
2+
select pg_sleep(1);
3+
pg_sleep
4+
----------
5+
6+
(1 row)
7+
8+
\! pg_ctl -D /tmp/pg_diskquota_test/data reload
9+
server signaled
10+
\! cp data/csmall.txt /tmp/csmall.txt
11+
select pg_sleep(5);
12+
pg_sleep
13+
----------
14+
15+
(1 row)
16+
17+
-- prepare a schema that has reached quota limit
18+
create schema badquota;
19+
select diskquota.set_schema_quota('badquota', '1 MB');
20+
set_schema_quota
21+
------------------
22+
23+
(1 row)
24+
25+
create role testbody;
26+
create table badquota.t1(i int);
27+
alter table badquota.t1 owner to testbody;
28+
insert into badquota.t1 select generate_series(0, 50000);
29+
select pg_sleep(5);
30+
pg_sleep
31+
----------
32+
33+
(1 row)
34+
35+
insert into badquota.t1 select generate_series(0, 10);
36+
ERROR: schema's disk space quota exceeded with name:badquota

0 commit comments

Comments
 (0)