PostgreSQL Source Code  git master
test_resowner_many.c File Reference
#include "postgres.h"
#include "fmgr.h"
#include "lib/ilist.h"
#include "utils/resowner.h"
Include dependency graph for test_resowner_many.c:

Go to the source code of this file.

Data Structures

struct  ManyTestResourceKind
 
struct  ManyTestResource
 

Functions

static void ReleaseManyTestResource (Datum res)
 
static char * PrintManyTest (Datum res)
 
static void InitManyTestResourceKind (ManyTestResourceKind *kind, char *name, ResourceReleasePhase phase, uint32 priority)
 
static void RememberManyTestResources (ResourceOwner owner, ManyTestResourceKind *kinds, int nkinds, int nresources)
 
static void ForgetManyTestResources (ResourceOwner owner, ManyTestResourceKind *kinds, int nkinds, int nresources)
 
static int GetTotalResourceCount (ManyTestResourceKind *kinds, int nkinds)
 
 PG_FUNCTION_INFO_V1 (test_resowner_many)
 
Datum test_resowner_many (PG_FUNCTION_ARGS)
 

Variables

static ResourceReleasePhase current_release_phase
 
static uint32 last_release_priority = 0
 

Function Documentation

◆ ForgetManyTestResources()

static void ForgetManyTestResources ( ResourceOwner  owner,
ManyTestResourceKind kinds,
int  nkinds,
int  nresources 
)
static

Definition at line 144 of file test_resowner_many.c.

147 {
148  int kind_idx = 0;
149  int ntotal;
150 
151  ntotal = GetTotalResourceCount(kinds, nkinds);
152  if (ntotal < nresources)
153  elog(PANIC, "cannot free %d resources, only %d remembered", nresources, ntotal);
154 
155  for (int i = 0; i < nresources; i++)
156  {
157  bool found = false;
158 
159  for (int j = 0; j < nkinds; j++)
160  {
161  kind_idx = (kind_idx + 1) % nkinds;
162  if (!dlist_is_empty(&kinds[kind_idx].current_resources))
163  {
164  ManyTestResource *mres = dlist_head_element(ManyTestResource, node, &kinds[kind_idx].current_resources);
165 
166  ResourceOwnerForget(owner, PointerGetDatum(mres), &kinds[kind_idx].desc);
167  kinds[kind_idx].nforgotten++;
168  dlist_delete(&mres->node);
169  pfree(mres);
170 
171  found = true;
172  break;
173  }
174  }
175  if (!found)
176  elog(ERROR, "could not find a test resource to forget");
177  }
178 }
#define PANIC
Definition: elog.h:42
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define dlist_head_element(type, membername, lhead)
Definition: ilist.h:603
static void dlist_delete(dlist_node *node)
Definition: ilist.h:405
static bool dlist_is_empty(const dlist_head *head)
Definition: ilist.h:336
int j
Definition: isn.c:73
int i
Definition: isn.c:72
void pfree(void *pointer)
Definition: mcxt.c:1521
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
void ResourceOwnerForget(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition: resowner.c:554
static int GetTotalResourceCount(ManyTestResourceKind *kinds, int nkinds)

References dlist_delete(), dlist_head_element, dlist_is_empty(), elog, ERROR, GetTotalResourceCount(), i, j, ManyTestResourceKind::nforgotten, ManyTestResource::node, PANIC, pfree(), PointerGetDatum(), and ResourceOwnerForget().

Referenced by test_resowner_many().

◆ GetTotalResourceCount()

static int GetTotalResourceCount ( ManyTestResourceKind kinds,
int  nkinds 
)
static

Definition at line 184 of file test_resowner_many.c.

185 {
186  int ntotal = 0;
187 
188  for (int i = 0; i < nkinds; i++)
189  ntotal += kinds[i].nremembered - kinds[i].nforgotten - kinds[i].nreleased;
190 
191  return ntotal;
192 }

References i.

Referenced by ForgetManyTestResources(), and test_resowner_many().

◆ InitManyTestResourceKind()

static void InitManyTestResourceKind ( ManyTestResourceKind kind,
char *  name,
ResourceReleasePhase  phase,
uint32  priority 
)
static

Definition at line 96 of file test_resowner_many.c.

98 {
99  kind->desc.name = name;
100  kind->desc.release_phase = phase;
101  kind->desc.release_priority = priority;
103  kind->desc.DebugPrint = PrintManyTest;
104  kind->nremembered = 0;
105  kind->nforgotten = 0;
106  kind->nreleased = 0;
107  kind->nleaked = 0;
109 }
static void dlist_init(dlist_head *head)
Definition: ilist.h:314
ResourceOwnerDesc desc
char *(* DebugPrint)(Datum res)
Definition: resowner.h:118
ResourceReleasePhase release_phase
Definition: resowner.h:96
void(* ReleaseResource)(Datum res)
Definition: resowner.h:108
ResourceReleasePriority release_priority
Definition: resowner.h:97
const char * name
Definition: resowner.h:93
static void ReleaseManyTestResource(Datum res)
static char * PrintManyTest(Datum res)
const char * name

References ManyTestResourceKind::current_resources, ResourceOwnerDesc::DebugPrint, ManyTestResourceKind::desc, dlist_init(), name, ResourceOwnerDesc::name, ManyTestResourceKind::nforgotten, ManyTestResourceKind::nleaked, ManyTestResourceKind::nreleased, ManyTestResourceKind::nremembered, PrintManyTest(), ResourceOwnerDesc::release_phase, ResourceOwnerDesc::release_priority, ReleaseManyTestResource(), and ResourceOwnerDesc::ReleaseResource.

Referenced by test_resowner_many().

◆ PG_FUNCTION_INFO_V1()

PG_FUNCTION_INFO_V1 ( test_resowner_many  )

◆ PrintManyTest()

static char * PrintManyTest ( Datum  res)
static

Definition at line 82 of file test_resowner_many.c.

83 {
85 
86  /*
87  * XXX: we assume that the DebugPrint function is called once for each
88  * leaked resource, and that there are no other callers.
89  */
90  mres->kind->nleaked++;
91 
92  return psprintf("many-test resource from %s", mres->kind->desc.name);
93 }
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312
char * psprintf(const char *fmt,...)
Definition: psprintf.c:43
ManyTestResourceKind * kind

References DatumGetPointer(), ManyTestResourceKind::desc, ManyTestResource::kind, ResourceOwnerDesc::name, ManyTestResourceKind::nleaked, psprintf(), and res.

Referenced by InitManyTestResourceKind().

◆ ReleaseManyTestResource()

static void ReleaseManyTestResource ( Datum  res)
static

Definition at line 67 of file test_resowner_many.c.

68 {
70 
71  elog(DEBUG1, "releasing resource %p from %s", mres, mres->kind->desc.name);
72  Assert(last_release_priority <= mres->kind->desc.release_priority);
73 
74  dlist_delete(&mres->node);
75  mres->kind->nreleased++;
77  pfree(mres);
78 }
#define Assert(condition)
Definition: c.h:812
#define DEBUG1
Definition: elog.h:30
static uint32 last_release_priority

References Assert, DatumGetPointer(), DEBUG1, ManyTestResourceKind::desc, dlist_delete(), elog, ManyTestResource::kind, last_release_priority, ResourceOwnerDesc::name, ManyTestResource::node, ManyTestResourceKind::nreleased, pfree(), ResourceOwnerDesc::release_priority, and res.

Referenced by InitManyTestResourceKind().

◆ RememberManyTestResources()

static void RememberManyTestResources ( ResourceOwner  owner,
ManyTestResourceKind kinds,
int  nkinds,
int  nresources 
)
static

Definition at line 116 of file test_resowner_many.c.

119 {
120  int kind_idx = 0;
121 
122  for (int i = 0; i < nresources; i++)
123  {
124  ManyTestResource *mres = palloc(sizeof(ManyTestResource));
125 
126  mres->kind = &kinds[kind_idx];
127  dlist_node_init(&mres->node);
128 
129  ResourceOwnerEnlarge(owner);
130  ResourceOwnerRemember(owner, PointerGetDatum(mres), &kinds[kind_idx].desc);
131  kinds[kind_idx].nremembered++;
132  dlist_push_tail(&kinds[kind_idx].current_resources, &mres->node);
133 
134  elog(DEBUG1, "remembered resource %p from %s", mres, mres->kind->desc.name);
135 
136  kind_idx = (kind_idx + 1) % nkinds;
137  }
138 }
static void dlist_push_tail(dlist_head *head, dlist_node *node)
Definition: ilist.h:364
static void dlist_node_init(dlist_node *node)
Definition: ilist.h:325
void * palloc(Size size)
Definition: mcxt.c:1317
void ResourceOwnerRemember(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition: resowner.c:514
void ResourceOwnerEnlarge(ResourceOwner owner)
Definition: resowner.c:442

References DEBUG1, ManyTestResourceKind::desc, dlist_node_init(), dlist_push_tail(), elog, i, ManyTestResource::kind, ResourceOwnerDesc::name, ManyTestResource::node, ManyTestResourceKind::nremembered, palloc(), PointerGetDatum(), ResourceOwnerEnlarge(), and ResourceOwnerRemember().

Referenced by test_resowner_many().

◆ test_resowner_many()

Datum test_resowner_many ( PG_FUNCTION_ARGS  )

Definition at line 203 of file test_resowner_many.c.

204 {
205  int32 nkinds = PG_GETARG_INT32(0);
206  int32 nremember_bl = PG_GETARG_INT32(1);
207  int32 nforget_bl = PG_GETARG_INT32(2);
208  int32 nremember_al = PG_GETARG_INT32(3);
209  int32 nforget_al = PG_GETARG_INT32(4);
210 
211  ResourceOwner resowner;
212 
213  ManyTestResourceKind *before_kinds;
214  ManyTestResourceKind *after_kinds;
215 
216  /* Sanity check the arguments */
217  if (nkinds < 0)
218  elog(ERROR, "nkinds must be >= 0");
219  if (nremember_bl < 0)
220  elog(ERROR, "nremember_bl must be >= 0");
221  if (nforget_bl < 0 || nforget_bl > nremember_bl)
222  elog(ERROR, "nforget_bl must between 0 and 'nremember_bl'");
223  if (nremember_al < 0)
224  elog(ERROR, "nremember_al must be greater than zero");
225  if (nforget_al < 0 || nforget_al > nremember_al)
226  elog(ERROR, "nforget_al must between 0 and 'nremember_al'");
227 
228  /* Initialize all the different resource kinds to use */
229  before_kinds = palloc(nkinds * sizeof(ManyTestResourceKind));
230  for (int i = 0; i < nkinds; i++)
231  {
232  InitManyTestResourceKind(&before_kinds[i],
233  psprintf("resource before locks %d", i),
236  }
237  after_kinds = palloc(nkinds * sizeof(ManyTestResourceKind));
238  for (int i = 0; i < nkinds; i++)
239  {
240  InitManyTestResourceKind(&after_kinds[i],
241  psprintf("resource after locks %d", i),
244  }
245 
246  resowner = ResourceOwnerCreate(CurrentResourceOwner, "TestOwner");
247 
248  /* Remember a bunch of resources */
249  if (nremember_bl > 0)
250  {
251  elog(NOTICE, "remembering %d before-locks resources", nremember_bl);
252  RememberManyTestResources(resowner, before_kinds, nkinds, nremember_bl);
253  }
254  if (nremember_al > 0)
255  {
256  elog(NOTICE, "remembering %d after-locks resources", nremember_al);
257  RememberManyTestResources(resowner, after_kinds, nkinds, nremember_al);
258  }
259 
260  /* Forget what was remembered */
261  if (nforget_bl > 0)
262  {
263  elog(NOTICE, "forgetting %d before-locks resources", nforget_bl);
264  ForgetManyTestResources(resowner, before_kinds, nkinds, nforget_bl);
265  }
266 
267  if (nforget_al > 0)
268  {
269  elog(NOTICE, "forgetting %d after-locks resources", nforget_al);
270  ForgetManyTestResources(resowner, after_kinds, nkinds, nforget_al);
271  }
272 
273  /* Start releasing */
274  elog(NOTICE, "releasing resources before locks");
277  ResourceOwnerRelease(resowner, RESOURCE_RELEASE_BEFORE_LOCKS, false, false);
278  Assert(GetTotalResourceCount(before_kinds, nkinds) == 0);
279 
280  elog(NOTICE, "releasing locks");
283  ResourceOwnerRelease(resowner, RESOURCE_RELEASE_LOCKS, false, false);
284 
285  elog(NOTICE, "releasing resources after locks");
288  ResourceOwnerRelease(resowner, RESOURCE_RELEASE_AFTER_LOCKS, false, false);
289  Assert(GetTotalResourceCount(before_kinds, nkinds) == 0);
290  Assert(GetTotalResourceCount(after_kinds, nkinds) == 0);
291 
292  ResourceOwnerDelete(resowner);
293 
294  PG_RETURN_VOID();
295 }
int32_t int32
Definition: c.h:481
#define NOTICE
Definition: elog.h:35
#define PG_RETURN_VOID()
Definition: fmgr.h:349
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
ResourceOwner ResourceOwnerCreate(ResourceOwner parent, const char *name)
Definition: resowner.c:413
ResourceOwner CurrentResourceOwner
Definition: resowner.c:165
void ResourceOwnerRelease(ResourceOwner owner, ResourceReleasePhase phase, bool isCommit, bool isTopLevel)
Definition: resowner.c:648
void ResourceOwnerDelete(ResourceOwner owner)
Definition: resowner.c:854
@ RESOURCE_RELEASE_LOCKS
Definition: resowner.h:55
@ RESOURCE_RELEASE_BEFORE_LOCKS
Definition: resowner.h:54
@ RESOURCE_RELEASE_AFTER_LOCKS
Definition: resowner.h:56
#define RELEASE_PRIO_FIRST
Definition: resowner.h:80
static void InitManyTestResourceKind(ManyTestResourceKind *kind, char *name, ResourceReleasePhase phase, uint32 priority)
static void ForgetManyTestResources(ResourceOwner owner, ManyTestResourceKind *kinds, int nkinds, int nresources)
static ResourceReleasePhase current_release_phase
static void RememberManyTestResources(ResourceOwner owner, ManyTestResourceKind *kinds, int nkinds, int nresources)

References Assert, current_release_phase, CurrentResourceOwner, elog, ERROR, ForgetManyTestResources(), GetTotalResourceCount(), i, InitManyTestResourceKind(), last_release_priority, NOTICE, palloc(), PG_GETARG_INT32, PG_RETURN_VOID, psprintf(), RELEASE_PRIO_FIRST, RememberManyTestResources(), RESOURCE_RELEASE_AFTER_LOCKS, RESOURCE_RELEASE_BEFORE_LOCKS, RESOURCE_RELEASE_LOCKS, ResourceOwnerCreate(), ResourceOwnerDelete(), and ResourceOwnerRelease().

Variable Documentation

◆ current_release_phase

ResourceReleasePhase current_release_phase
static

Definition at line 49 of file test_resowner_many.c.

Referenced by test_resowner_many().

◆ last_release_priority

uint32 last_release_priority = 0
static

Definition at line 50 of file test_resowner_many.c.

Referenced by ReleaseManyTestResource(), and test_resowner_many().