Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit f7acfa1

Browse files
author
Alexander Korotkov
committed
Fix release of memory of dropped in-memory tables
Use object access hook instead of event trigger. That makes it possible to handle DROP SCHEMA and DROP DATABASE.
1 parent a52c47b commit f7acfa1

File tree

7 files changed

+122
-50
lines changed

7 files changed

+122
-50
lines changed

contrib/in_memory/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,5 +60,5 @@ isolationcheck: | submake-isolation submake-in_memory temp-install
6060

6161
temp-install: EXTRA_INSTALL=contrib/in_memory
6262

63-
standby-check: submake-in_memory temp-install
63+
prove-check: submake-in_memory temp-install
6464
$(prove_check)

contrib/in_memory/fdw.c

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ is_valid_option(const char *option, Oid context)
8888
}
8989

9090
static void in_memory_fdw_validate_index(List* index_params, bool pk);
91+
static void drop_fdw_by_descr(SharedDescr *descr);
9192

9293
Datum
9394
in_memory_fdw_validator(PG_FUNCTION_ARGS)
@@ -1659,20 +1660,32 @@ void
16591660
drop_fdw(Oid reloid)
16601661
{
16611662
SharedDescr *descr;
1662-
int i;
1663-
DropFDWUndoStackItem *item;
16641663

16651664
descr = find_shared_descr(MyDatabaseId, reloid);
16661665
if (descr)
1667-
{
1668-
for (i = 0; i < descr->ntrees; i++)
1669-
drop_btree(descr->tree[i].root, descr->tree[i].meta);
1670-
item = MemoryContextAlloc(CurTransactionContext, sizeof(*item));
1671-
item->header.cb = drop_fdw_undo_callback;
1672-
item->datoid = descr->key.datoid;
1673-
item->reloid = descr->key.reloid;
1674-
add_undo_item(&item->header);
1675-
}
1666+
drop_fdw_by_descr(descr);
1667+
}
1668+
1669+
void
1670+
drop_database_fdw(Oid datoid)
1671+
{
1672+
iterate_database_fdws(datoid, drop_fdw_by_descr);
1673+
}
1674+
1675+
static void
1676+
drop_fdw_by_descr(SharedDescr *descr)
1677+
{
1678+
int i;
1679+
DropFDWUndoStackItem *item;
1680+
1681+
for (i = 0; i < descr->ntrees; i++)
1682+
drop_btree(descr->tree[i].root, descr->tree[i].meta);
1683+
1684+
item = MemoryContextAlloc(CurTransactionContext, sizeof(*item));
1685+
item->header.cb = drop_fdw_undo_callback;
1686+
item->datoid = descr->key.datoid;
1687+
item->reloid = descr->key.reloid;
1688+
add_undo_item(&item->header);
16761689
}
16771690

16781691
bool

contrib/in_memory/fdw.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ extern void im_fdw_init_root(void *buf, bool found);
2525
extern bool check_fdw_is_in_memory_relid(Oid relid);
2626
extern void truncate_fdw(Oid relid);
2727
extern void drop_fdw(Oid relid);
28+
extern void drop_database_fdw(Oid datoid);
2829
extern void drop_fdw_descr(Oid datoid, Oid reloid);
2930
extern void free_fdw(Oid datoid, Oid reloid);
3031
extern void invalidate_private_fdw_descr(Oid reloid);

contrib/in_memory/fdw_descr.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,34 @@ find_shared_descr(Oid datoid, Oid reloid)
296296
COMMITSEQNO_INPROGRESS);
297297
}
298298

299+
/*
300+
* Iterate over all present FDWs in given database.
301+
*/
302+
void
303+
iterate_database_fdws(Oid datoid, DescrCallback callback)
304+
{
305+
BTreeIterator *iter;
306+
DescrKey key;
307+
SharedDescr *descr;
308+
309+
key.datoid = datoid;
310+
key.reloid = (Oid) 0;
311+
312+
iter = make_btree_iterator(&im_fdw_meta_cache_tree, (Pointer) &key,
313+
BTreeKey, COMMITSEQNO_INPROGRESS);
314+
315+
while ((descr = (SharedDescr *) btree_iterate(iter)) != NULL)
316+
{
317+
if (descr->key.datoid != datoid)
318+
break;
319+
320+
callback(descr);
321+
322+
pfree(descr);
323+
}
324+
free_btree_iterator(iter);
325+
}
326+
299327
void
300328
drop_fdw_descr(Oid datoid, Oid reloid)
301329
{

contrib/in_memory/fdw_internal.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,4 +191,8 @@ typedef struct IMFdwPlanState
191191
List *local_conds;
192192
} IMFdwPlanState;
193193

194+
typedef void (*DescrCallback) (SharedDescr *descr);
195+
196+
extern void iterate_database_fdws(Oid datoid, DescrCallback callback);
197+
194198
#endif /* __IN_MEMORY_FDW_INTERNAL_H__ */

contrib/in_memory/in_memory.c

Lines changed: 26 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#include "access/heapam.h"
1818
#include "access/htup_details.h"
1919
#include "catalog/namespace.h"
20+
#include "catalog/objectaccess.h"
21+
#include "catalog/pg_database.h"
2022
#include "commands/event_trigger.h"
2123
#include "commands/tablecmds.h"
2224
#include "executor/spi.h"
@@ -50,6 +52,7 @@ void _PG_init(void);
5052
static shmem_startup_hook_type prev_shmem_startup_hook = NULL;
5153
static ProcessUtility_hook_type next_ProcessUtility_hook = NULL;
5254
static logical_message_redo_hook_type prev_logical_message_redo_hook = NULL;
55+
static object_access_hook_type prev_object_access_hook = NULL;
5356

5457
static Pointer shared_segment = NULL;
5558
static bool shared_segment_initialized = false;
@@ -81,6 +84,8 @@ static void in_memory_utility_command(PlannedStmt *pstmt,
8184
char *completionTag);
8285
static void in_memory_logical_message_hook(xl_logical_message *xlrec);
8386
static void in_memory_relcache_hook(Datum arg, Oid relid);
87+
static void in_memory_object_access_hook(ObjectAccessType access, Oid classId,
88+
Oid objectId, int subId, void *arg);
8489

8590
PG_FUNCTION_INFO_V1(in_memory_fsm_test);
8691
PG_FUNCTION_INFO_V1(in_memory_page_stats);
@@ -176,6 +181,8 @@ _PG_init(void)
176181
ProcessUtility_hook = in_memory_utility_command;
177182
prev_logical_message_redo_hook = logical_message_redo_hook;
178183
logical_message_redo_hook = in_memory_logical_message_hook;
184+
prev_object_access_hook = object_access_hook;
185+
object_access_hook = in_memory_object_access_hook;
179186
RegisterXactCallback(undo_xact_callback, NULL);
180187
RegisterSubXactCallback(undo_subxact_callback, NULL);
181188
CacheRegisterRelcacheCallback(in_memory_relcache_hook, PointerGetDatum(NULL));
@@ -515,48 +522,29 @@ in_memory_relcache_hook(Datum arg, Oid relid)
515522
invalidate_private_fdw_descr(relid);
516523
}
517524

518-
Datum
519-
in_memory_event_trigger(PG_FUNCTION_ARGS)
525+
static void
526+
in_memory_object_access_hook(ObjectAccessType access, Oid classId,
527+
Oid objectId, int subId, void *arg)
520528
{
521-
EventTriggerData *trigdata;
522-
int ret;
523-
uint64 proc;
524-
525-
if (!CALLED_AS_EVENT_TRIGGER(fcinfo)) /* internal error */
526-
elog(ERROR, "in_memory_event_trigger: not fired by event trigger manager");
527-
528-
trigdata = (EventTriggerData *) fcinfo->context;
529-
530-
if (strcmp(trigdata->event, "sql_drop"))
531-
PG_RETURN_NULL();
532-
533-
SPI_connect();
534-
ret = SPI_execute(
535-
"SELECT "
536-
"objid "
537-
"FROM "
538-
"pg_event_trigger_dropped_objects() "
539-
"WHERE classid = 'pg_catalog.pg_class'::regclass;", true, 0);
540-
proc = SPI_processed;
541-
elog(LOG, "%u", (uint32) proc);
542-
543-
if (ret > 0 && SPI_tuptable != NULL)
529+
if (access == OAT_DROP && classId == RelationRelationId)
544530
{
545-
TupleDesc tupdesc = SPI_tuptable->tupdesc;
546-
SPITupleTable *tuptable = SPI_tuptable;
547-
uint64 i;
548-
bool isnull;
549-
550-
for (i = 0; i < proc; i++)
551-
{
552-
HeapTuple tuple = tuptable->vals[i];
553-
Oid reloid;
531+
drop_fdw(objectId);
532+
}
554533

555-
reloid = DatumGetObjectId(SPI_getbinval(tuple, tupdesc, 1, &isnull));
556-
drop_fdw(reloid);
557-
}
534+
if (access == OAT_DROP && classId == DatabaseRelationId)
535+
{
536+
drop_database_fdw(objectId);
558537
}
559-
SPI_finish();
560538

539+
if (prev_object_access_hook)
540+
prev_object_access_hook(access, classId, objectId, subId, arg);
541+
}
542+
543+
/*
544+
* No longer used, but reserved for future usage.
545+
*/
546+
Datum
547+
in_memory_event_trigger(PG_FUNCTION_ARGS)
548+
{
561549
PG_RETURN_NULL();
562550
}

contrib/in_memory/t/002_drop.pl

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Test in_memory tables memory releazed on drop.
2+
use strict;
3+
use warnings;
4+
use PostgresNode;
5+
use TestLib;
6+
use Test::More tests => 2;
7+
8+
my $node;
9+
10+
# Initialize node
11+
$node = get_new_node('master');
12+
$node->init(allows_streaming => 1);
13+
$node->append_conf('postgresql.conf', "shared_preload_libraries = 'in_memory'");
14+
$node->start;
15+
16+
# Create in_memory table master and fill it with some data
17+
$node->safe_psql("postgres", "CREATE EXTENSION in_memory;");
18+
$node->safe_psql("postgres", "CREATE DATABASE test;");
19+
20+
# Make table, and then drop extension
21+
$node->safe_psql("test", "CREATE EXTENSION in_memory;");
22+
$node->safe_psql("test", "CREATE FOREIGN TABLE im_test (id int8 not null, value text) SERVER in_memory;");
23+
$node->safe_psql("test", "INSERT INTO im_test SELECT id, 'val' || id FROM generate_series(1, 10000) id;");
24+
$node->safe_psql("test", "DROP EXTENSION in_memory CASCADE;");
25+
26+
# Check that memory is releazed
27+
my $result = $node->safe_psql("postgres", "SELECT busy_pages FROM in_memory_page_stats();");
28+
is($result, "2", "in_memory table memory releazed after extension drop");
29+
30+
# Make table again, and then drop database
31+
$node->safe_psql("test", "CREATE EXTENSION in_memory;");
32+
$node->safe_psql("test", "CREATE FOREIGN TABLE im_test (id int8 not null, value text) SERVER in_memory;");
33+
$node->safe_psql("test", "INSERT INTO im_test SELECT id, 'val' || id FROM generate_series(1, 10000) id;");
34+
$node->safe_psql("postgres", "DROP DATABASE test;");
35+
36+
# Check that memory is releazed
37+
$result = $node->safe_psql("postgres", "SELECT busy_pages FROM in_memory_page_stats();");
38+
is($result, "2", "in_memory table memory releazed after database drop");

0 commit comments

Comments
 (0)