Skip to content

Commit d18ff3e

Browse files
committed
fix PackDatumToByteArray() & UnpackDatumFromByteArray(), install pathman_relcache_hook() only once, introduce fini_local_cache()
1 parent 7d45123 commit d18ff3e

File tree

4 files changed

+100
-54
lines changed

4 files changed

+100
-54
lines changed

src/init.c

Lines changed: 47 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,17 @@
4444

4545

4646
/* Storage for PartRelationInfos */
47-
HTAB *partitioned_rels = NULL;
47+
HTAB *partitioned_rels = NULL;
4848

4949
/* Storage for PartParentInfos */
50-
HTAB *parent_cache = NULL;
50+
HTAB *parent_cache = NULL;
5151

52-
bool initialization_needed = true;
52+
bool initialization_needed = true;
53+
static bool relcache_callback_needed = true;
5354

5455

56+
static void init_local_cache(void);
57+
static void fini_local_cache(void);
5558
static void read_pathman_config(void);
5659

5760
static Expr *get_partition_constraint_expr(Oid partition, AttrNumber part_attno);
@@ -80,12 +83,20 @@ static int oid_cmp(const void *p1, const void *p2);
8083
void
8184
load_config(void)
8285
{
83-
/* cache PATHMAN_CONFIG relation Oid */
86+
/* Cache PATHMAN_CONFIG relation Oid */
8487
pathman_config_relid = get_relname_relid(PATHMAN_CONFIG, get_pathman_schema());
8588

86-
init_local_config(); /* create 'relations' hash table */
89+
init_local_cache(); /* create 'partitioned_rels' hash table */
8790
read_pathman_config(); /* read PATHMAN_CONFIG table & fill cache */
8891

92+
/* Register pathman_relcache_hook(), currently we can't unregister it */
93+
if (relcache_callback_needed)
94+
{
95+
CacheRegisterRelcacheCallback(pathman_relcache_hook, PointerGetDatum(NULL));
96+
relcache_callback_needed = false;
97+
}
98+
99+
/* Mark pg_pathman as initialized */
89100
initialization_needed = false;
90101

91102
elog(DEBUG2, "pg_pathman's config has been loaded successfully");
@@ -97,26 +108,12 @@ load_config(void)
97108
void
98109
unload_config(void)
99110
{
100-
HASH_SEQ_STATUS status;
101-
PartRelationInfo *prel;
102-
103-
hash_seq_init(&status, partitioned_rels);
104-
while((prel = (PartRelationInfo *) hash_seq_search(&status)) != NULL)
105-
{
106-
if (PrelIsValid(prel))
107-
{
108-
FreeChildrenArray(prel);
109-
FreeRangesArray(prel);
110-
}
111-
}
112-
113-
/* Now we can safely destroy hash tables */
114-
hash_destroy(partitioned_rels);
115-
hash_destroy(parent_cache);
116-
partitioned_rels = NULL;
117-
parent_cache = NULL;
111+
fini_local_cache(); /* destroy 'partitioned_rels' hash table */
118112

113+
/* Mark pg_pathman as uninitialized */
119114
initialization_needed = true;
115+
116+
elog(DEBUG2, "pg_pathman's config has been unloaded successfully");
120117
}
121118

122119
/*
@@ -131,8 +128,8 @@ estimate_pathman_shmem_size(void)
131128
/*
132129
* Initialize per-process resources.
133130
*/
134-
void
135-
init_local_config(void)
131+
static void
132+
init_local_cache(void)
136133
{
137134
HASHCTL ctl;
138135

@@ -152,8 +149,32 @@ init_local_config(void)
152149
parent_cache = hash_create("pg_pathman's partition parents cache",
153150
PART_RELS_SIZE * CHILD_FACTOR,
154151
&ctl, HASH_ELEM | HASH_BLOBS);
152+
}
153+
154+
/*
155+
* Safely free per-process resources.
156+
*/
157+
static void
158+
fini_local_cache(void)
159+
{
160+
HASH_SEQ_STATUS status;
161+
PartRelationInfo *prel;
155162

156-
CacheRegisterRelcacheCallback(pathman_relcache_hook, PointerGetDatum(NULL));
163+
hash_seq_init(&status, partitioned_rels);
164+
while((prel = (PartRelationInfo *) hash_seq_search(&status)) != NULL)
165+
{
166+
if (PrelIsValid(prel))
167+
{
168+
FreeChildrenArray(prel);
169+
FreeRangesArray(prel);
170+
}
171+
}
172+
173+
/* Now we can safely destroy hash tables */
174+
hash_destroy(partitioned_rels);
175+
hash_destroy(parent_cache);
176+
partitioned_rels = NULL;
177+
parent_cache = NULL;
157178
}
158179

159180
/*

src/init.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ extern bool initialization_needed;
2525

2626

2727
Size estimate_pathman_shmem_size(void);
28-
void init_local_config(void);
2928
void init_shmem_config(void);
3029
void load_config(void);
3130
void unload_config(void);

src/pg_pathman.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -860,7 +860,8 @@ create_partitions_internal(Oid relid, Datum value, Oid value_type)
860860
prel->atttype);
861861

862862
/* Convert interval from CSTRING to 'prel->atttype' */
863-
interval_binary = OidFunctionCall1(typein_proc, value);
863+
interval_binary = OidFunctionCall1(typein_proc,
864+
CStringGetDatum(interval_cstring));
864865
interval_type = prel->atttype;
865866
}
866867

src/worker.c

Lines changed: 51 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -51,32 +51,51 @@ typedef struct
5151
} PartitionArgs;
5252

5353

54-
#define PackDatumToByteArray(array, datum, datum_size, typbyval) \
55-
do { \
56-
memcpy((void *) (array), \
57-
(const void *) ((typbyval) ? \
58-
(Pointer) (&datum) : \
59-
DatumGetPointer(datum)), \
60-
datum_size); \
61-
} while (0)
6254

6355
/*
64-
* 'typid' is not necessary, but it is used by PrintUnpackedDatum().
56+
* Useful datum packing\unpacking functions for BGW.
6557
*/
66-
#define UnpackDatumFromByteArray(array, datum, datum_size, typbyval, typid) \
67-
do { \
68-
if (typbyval) \
69-
memcpy((void *) &datum, (const void *) array, datum_size); \
70-
else \
71-
{ \
72-
datum = PointerGetDatum(palloc(datum_size)); \
73-
memcpy((void *) DatumGetPointer(datum), \
74-
(const void *) array, \
75-
datum_size); \
76-
} \
77-
elog(LOG, "BGW: arg->value is '%s' [%u]", \
78-
DebugPrintDatum(datum, typid), MyProcPid); \
79-
} while (0)
58+
59+
static void
60+
PackDatumToByteArray(void *byte_array, Datum datum, Size datum_size, bool typbyval)
61+
{
62+
if (typbyval)
63+
/* We have to copy all Datum's bytes */
64+
datum_size = Max(sizeof(Datum), datum_size);
65+
66+
memcpy((void *) byte_array,
67+
(const void *) (typbyval ?
68+
(Pointer) &datum : /* treat Datum as byte array */
69+
DatumGetPointer(datum)), /* extract pointer to data */
70+
datum_size);
71+
}
72+
73+
static void
74+
UnpackDatumFromByteArray(Datum *datum, Size datum_size, bool typbyval,
75+
const void *byte_array)
76+
{
77+
void *dst;
78+
79+
if (typbyval)
80+
{
81+
/* Write Data to Datum directly */
82+
dst = datum;
83+
84+
/* We have to copy all Datum's bytes */
85+
datum_size = Max(sizeof(Datum), datum_size);
86+
}
87+
else
88+
{
89+
/* Allocate space for Datum's internals */
90+
dst = palloc(datum_size);
91+
92+
/* Save pointer to Datum */
93+
*datum = PointerGetDatum(dst);
94+
}
95+
96+
memcpy(dst, byte_array, datum_size);
97+
}
98+
8099

81100

82101
/*
@@ -121,7 +140,7 @@ create_partitions_bg_worker_segment(Oid relid, Datum value, Oid value_type)
121140
args->value_size = datum_size;
122141
args->value_byval = typcache->typbyval;
123142

124-
PackDatumToByteArray(&args->value, value,
143+
PackDatumToByteArray((void *) args->value, value,
125144
datum_size, args->value_byval);
126145

127146
return segment;
@@ -255,10 +274,16 @@ bg_worker_main(Datum main_arg)
255274
bg_worker_load_config(create_partitions_bgw);
256275

257276
/* Upack Datum from segment to 'value' */
258-
UnpackDatumFromByteArray(&args->value, value,
277+
UnpackDatumFromByteArray(&value,
259278
args->value_size,
260279
args->value_byval,
261-
args->value_type);
280+
(const void *) args->value);
281+
282+
#ifdef USE_ASSERT_CHECKING
283+
elog(LOG, "%s: arg->value is '%s' [%u]",
284+
create_partitions_bgw,
285+
DebugPrintDatum(value, args->value_type), MyProcPid);
286+
#endif
262287

263288
/* Create partitions */
264289
args->result = create_partitions_internal(args->partitioned_table,

0 commit comments

Comments
 (0)