Skip to content

Commit d90fd21

Browse files
author
Maxim Orlov
committed
Issue #27: Add fix for VALGRING failed test.
1 parent 1f5e597 commit d90fd21

File tree

1 file changed

+130
-18
lines changed

1 file changed

+130
-18
lines changed

pg_variables.c

+130-18
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,8 @@ static dlist_head *changesStack = NULL;
130130
static MemoryContext changesStackContext = NULL;
131131

132132
/*
133-
* List to store all the running hash_seq_search scan for hash table.
133+
* List to store all the running hash_seq_search, variable and package scan for
134+
* hash table.
134135
*
135136
* NOTE: In function variable_select we use hash_seq_search to find next tuple.
136137
* So, in case user do not get all the data from set at once (use cursors or
@@ -143,10 +144,116 @@ static MemoryContext changesStackContext = NULL;
143144
* TopTransactionContext is handy here, becouse it wount be reset by the time
144145
* pgvTransCallback is called.
145146
*/
146-
static List *variables_stats = NIL;
147+
static List *variables_stats = NIL;
147148
static List *packages_stats = NIL;
148149

149-
static void freeStatsLists(bool deep);
150+
typedef struct tagHtabToStat {
151+
HTAB *hash;
152+
HASH_SEQ_STATUS *status;
153+
Variable *variable;
154+
Package *package;
155+
} HtabToStat;
156+
157+
/*
158+
* A bunch of comp functions for HtabToStat members here.
159+
*/
160+
static bool
161+
HtabToStat_status_eq(HtabToStat *entry, void *value)
162+
{
163+
return entry->status == (HASH_SEQ_STATUS *) value;
164+
}
165+
166+
static bool
167+
HtabToStat_variable_eq(HtabToStat *entry, void *value)
168+
{
169+
return entry->variable == (Variable *) value;
170+
}
171+
172+
static bool
173+
HtabToStat_package_eq(HtabToStat *entry, void *value)
174+
{
175+
return entry->package == (Package *) value;
176+
}
177+
178+
static bool
179+
HtabToStat_eq_all(HtabToStat *entry, void *value)
180+
{
181+
return true;
182+
}
183+
184+
/*
185+
* Generic remove_if algorithm for HtabToStat.
186+
*
187+
* + eq if function pointer used to compare list entry to the value.
188+
* + if match_first is true return on first match.
189+
*/
190+
static void
191+
HtabToStat_remove_if(List **l, void *value,
192+
bool (*eq)(HtabToStat *, void *),
193+
bool match_first)
194+
{
195+
ListCell *cell, *next, *prev = NULL;
196+
HtabToStat *entry = NULL;
197+
198+
for (cell = list_head(*l); cell; cell = next)
199+
{
200+
entry = (HtabToStat *) lfirst(cell);
201+
next = lnext(cell);
202+
203+
if (eq(entry, value))
204+
{
205+
*l = list_delete_cell(*l, cell, prev);
206+
pfree(entry->status);
207+
pfree(entry);
208+
209+
if (match_first)
210+
return;
211+
}
212+
else
213+
{
214+
prev = cell;
215+
}
216+
}
217+
}
218+
219+
/*
220+
* Remove first entry for status.
221+
*/
222+
static void
223+
remove_variables_status(List **l, HASH_SEQ_STATUS *status)
224+
{
225+
HtabToStat_remove_if(l, status, HtabToStat_status_eq, true);
226+
}
227+
228+
/*
229+
* Remove first entry for variable.
230+
*/
231+
static void
232+
remove_variables_variable(List **l, Variable *variable)
233+
{
234+
HtabToStat_remove_if(l, variable, HtabToStat_variable_eq, true);
235+
}
236+
237+
/*
238+
* Remove all the entrys for package.
239+
*/
240+
static void
241+
remove_variables_package(List **l, Package *package)
242+
{
243+
HtabToStat_remove_if(l, package, HtabToStat_package_eq, false);
244+
}
245+
246+
/*
247+
* Remove all.
248+
*/
249+
static void
250+
remove_variables_all(List **l)
251+
{
252+
HtabToStat_remove_if(l, NULL, HtabToStat_eq_all, false);
253+
*l = NIL;
254+
}
255+
256+
static void freeStatsLists(void);
150257
/* Returns a lists of packages and variables changed at current subxact level */
151258
#define get_actual_changes_list() \
152259
( \
@@ -632,6 +739,7 @@ variable_select(PG_FUNCTION_ARGS)
632739
{
633740
MemoryContext oldcontext;
634741
RecordVar *record;
742+
HtabToStat *htab_to_stat;
635743

636744
record = &(GetActualValue(variable).record);
637745
funcctx = SRF_FIRSTCALL_INIT();
@@ -644,7 +752,12 @@ variable_select(PG_FUNCTION_ARGS)
644752
hash_seq_init(rstat, record->rhash);
645753
funcctx->user_fctx = rstat;
646754

647-
variables_stats = lcons((void *)rstat, variables_stats);
755+
htab_to_stat = palloc0(sizeof(HtabToStat));
756+
htab_to_stat->hash = record->rhash;
757+
htab_to_stat->status = rstat;
758+
htab_to_stat->variable = variable;
759+
htab_to_stat->package = package;
760+
variables_stats = lcons((void *)htab_to_stat, variables_stats);
648761

649762
MemoryContextSwitchTo(oldcontext);
650763
PG_FREE_IF_COPY(package_name, 0);
@@ -665,8 +778,7 @@ variable_select(PG_FUNCTION_ARGS)
665778
}
666779
else
667780
{
668-
variables_stats = list_delete(variables_stats, rstat);
669-
pfree(rstat);
781+
remove_variables_status(&variables_stats, rstat);
670782
SRF_RETURN_DONE(funcctx);
671783
}
672784
}
@@ -968,6 +1080,8 @@ remove_package(PG_FUNCTION_ARGS)
9681080

9691081
resetVariablesCache();
9701082

1083+
remove_variables_package(&variables_stats, package);
1084+
9711085
PG_FREE_IF_COPY(package_name, 0);
9721086
PG_RETURN_VOID();
9731087
}
@@ -1063,6 +1177,7 @@ remove_packages(PG_FUNCTION_ARGS)
10631177
}
10641178

10651179
resetVariablesCache();
1180+
remove_variables_all(&variables_stats);
10661181

10671182
PG_RETURN_VOID();
10681183
}
@@ -1317,7 +1432,7 @@ get_packages_stats(PG_FUNCTION_ARGS)
13171432
else
13181433
{
13191434
packages_stats = list_delete(packages_stats, rstat);
1320-
pfree(rstat);
1435+
// pfree(rstat);
13211436
SRF_RETURN_DONE(funcctx);
13221437
}
13231438
}
@@ -1777,6 +1892,7 @@ removeObject(TransObject *object, TransObjectType type)
17771892

17781893
/* Remove object from hash table */
17791894
hash_search(hash, object->name, HASH_REMOVE, &found);
1895+
remove_variables_variable(&variables_stats, (Variable *) object);
17801896

17811897
/* Remove package if it became empty */
17821898
if (type == TRANS_VARIABLE && isPackageEmpty(package))
@@ -2227,7 +2343,7 @@ pgvTransCallback(XactEvent event, void *arg)
22272343
}
22282344

22292345
if (event == XACT_EVENT_PRE_COMMIT || event == XACT_EVENT_ABORT)
2230-
freeStatsLists(true);
2346+
freeStatsLists();
22312347
}
22322348

22332349
/*
@@ -2241,25 +2357,23 @@ variable_ExecutorEnd(QueryDesc *queryDesc)
22412357
else
22422358
standard_ExecutorEnd(queryDesc);
22432359

2244-
freeStatsLists(false);
2360+
freeStatsLists();
22452361
}
22462362

22472363
/*
22482364
* Free hash_seq_search scans
22492365
*/
2250-
void
2251-
freeStatsLists(bool deep)
2366+
static void
2367+
freeStatsLists(void)
22522368
{
22532369
ListCell *cell;
22542370
HASH_SEQ_STATUS *status;
2371+
HtabToStat *htab_to_stat;
22552372

22562373
foreach(cell, variables_stats)
22572374
{
2258-
status = (HASH_SEQ_STATUS *) lfirst(cell);
2259-
hash_seq_term(status);
2260-
2261-
if (deep)
2262-
pfree(status);
2375+
htab_to_stat = (HtabToStat *) lfirst(cell);
2376+
hash_seq_term(htab_to_stat->status);
22632377
}
22642378

22652379
variables_stats = NIL;
@@ -2268,8 +2382,6 @@ freeStatsLists(bool deep)
22682382
{
22692383
status = (HASH_SEQ_STATUS *) lfirst(cell);
22702384
hash_seq_term(status);
2271-
2272-
pfree(status);
22732385
}
22742386

22752387
packages_stats = NIL;

0 commit comments

Comments
 (0)