00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "postgres.h"
00022
00023 #include "access/hash.h"
00024 #include "storage/predicate.h"
00025 #include "storage/proc.h"
00026 #include "utils/memutils.h"
00027 #include "utils/rel.h"
00028 #include "utils/resowner_private.h"
00029 #include "utils/snapmgr.h"
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 #define MAX_RESOWNER_LOCKS 15
00048
00049
00050
00051
00052 typedef struct ResourceOwnerData
00053 {
00054 ResourceOwner parent;
00055 ResourceOwner firstchild;
00056 ResourceOwner nextchild;
00057 const char *name;
00058
00059
00060 int nbuffers;
00061 Buffer *buffers;
00062 int maxbuffers;
00063
00064
00065 int nlocks;
00066 LOCALLOCK *locks[MAX_RESOWNER_LOCKS];
00067
00068
00069 int ncatrefs;
00070 HeapTuple *catrefs;
00071 int maxcatrefs;
00072
00073 int ncatlistrefs;
00074 CatCList **catlistrefs;
00075 int maxcatlistrefs;
00076
00077
00078 int nrelrefs;
00079 Relation *relrefs;
00080 int maxrelrefs;
00081
00082
00083 int nplanrefs;
00084 CachedPlan **planrefs;
00085 int maxplanrefs;
00086
00087
00088 int ntupdescs;
00089 TupleDesc *tupdescs;
00090 int maxtupdescs;
00091
00092
00093 int nsnapshots;
00094 Snapshot *snapshots;
00095 int maxsnapshots;
00096
00097
00098 int nfiles;
00099 File *files;
00100 int maxfiles;
00101 } ResourceOwnerData;
00102
00103
00104
00105
00106
00107
00108 ResourceOwner CurrentResourceOwner = NULL;
00109 ResourceOwner CurTransactionResourceOwner = NULL;
00110 ResourceOwner TopTransactionResourceOwner = NULL;
00111
00112
00113
00114
00115 typedef struct ResourceReleaseCallbackItem
00116 {
00117 struct ResourceReleaseCallbackItem *next;
00118 ResourceReleaseCallback callback;
00119 void *arg;
00120 } ResourceReleaseCallbackItem;
00121
00122 static ResourceReleaseCallbackItem *ResourceRelease_callbacks = NULL;
00123
00124
00125
00126 static void ResourceOwnerReleaseInternal(ResourceOwner owner,
00127 ResourceReleasePhase phase,
00128 bool isCommit,
00129 bool isTopLevel);
00130 static void PrintRelCacheLeakWarning(Relation rel);
00131 static void PrintPlanCacheLeakWarning(CachedPlan *plan);
00132 static void PrintTupleDescLeakWarning(TupleDesc tupdesc);
00133 static void PrintSnapshotLeakWarning(Snapshot snapshot);
00134 static void PrintFileLeakWarning(File file);
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 ResourceOwner
00150 ResourceOwnerCreate(ResourceOwner parent, const char *name)
00151 {
00152 ResourceOwner owner;
00153
00154 owner = (ResourceOwner) MemoryContextAllocZero(TopMemoryContext,
00155 sizeof(ResourceOwnerData));
00156 owner->name = name;
00157
00158 if (parent)
00159 {
00160 owner->parent = parent;
00161 owner->nextchild = parent->firstchild;
00162 parent->firstchild = owner;
00163 }
00164
00165 return owner;
00166 }
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194 void
00195 ResourceOwnerRelease(ResourceOwner owner,
00196 ResourceReleasePhase phase,
00197 bool isCommit,
00198 bool isTopLevel)
00199 {
00200
00201 ResourceOwner save;
00202
00203 save = CurrentResourceOwner;
00204 PG_TRY();
00205 {
00206 ResourceOwnerReleaseInternal(owner, phase, isCommit, isTopLevel);
00207 }
00208 PG_CATCH();
00209 {
00210 CurrentResourceOwner = save;
00211 PG_RE_THROW();
00212 }
00213 PG_END_TRY();
00214 CurrentResourceOwner = save;
00215 }
00216
00217 static void
00218 ResourceOwnerReleaseInternal(ResourceOwner owner,
00219 ResourceReleasePhase phase,
00220 bool isCommit,
00221 bool isTopLevel)
00222 {
00223 ResourceOwner child;
00224 ResourceOwner save;
00225 ResourceReleaseCallbackItem *item;
00226
00227
00228 for (child = owner->firstchild; child != NULL; child = child->nextchild)
00229 ResourceOwnerReleaseInternal(child, phase, isCommit, isTopLevel);
00230
00231
00232
00233
00234
00235
00236 save = CurrentResourceOwner;
00237 CurrentResourceOwner = owner;
00238
00239 if (phase == RESOURCE_RELEASE_BEFORE_LOCKS)
00240 {
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253 while (owner->nbuffers > 0)
00254 {
00255 if (isCommit)
00256 PrintBufferLeakWarning(owner->buffers[owner->nbuffers - 1]);
00257 ReleaseBuffer(owner->buffers[owner->nbuffers - 1]);
00258 }
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268 while (owner->nrelrefs > 0)
00269 {
00270 if (isCommit)
00271 PrintRelCacheLeakWarning(owner->relrefs[owner->nrelrefs - 1]);
00272 RelationClose(owner->relrefs[owner->nrelrefs - 1]);
00273 }
00274 }
00275 else if (phase == RESOURCE_RELEASE_LOCKS)
00276 {
00277 if (isTopLevel)
00278 {
00279
00280
00281
00282
00283
00284 if (owner == TopTransactionResourceOwner)
00285 {
00286 ProcReleaseLocks(isCommit);
00287 ReleasePredicateLocks(isCommit);
00288 }
00289 }
00290 else
00291 {
00292
00293
00294
00295
00296
00297 LOCALLOCK **locks;
00298 int nlocks;
00299
00300 Assert(owner->parent != NULL);
00301
00302
00303
00304
00305
00306 if (owner->nlocks > MAX_RESOWNER_LOCKS)
00307 {
00308 locks = NULL;
00309 nlocks = 0;
00310 }
00311 else
00312 {
00313 locks = owner->locks;
00314 nlocks = owner->nlocks;
00315 }
00316
00317 if (isCommit)
00318 LockReassignCurrentOwner(locks, nlocks);
00319 else
00320 LockReleaseCurrentOwner(locks, nlocks);
00321 }
00322 }
00323 else if (phase == RESOURCE_RELEASE_AFTER_LOCKS)
00324 {
00325
00326
00327
00328
00329
00330
00331
00332
00333 while (owner->ncatrefs > 0)
00334 {
00335 if (isCommit)
00336 PrintCatCacheLeakWarning(owner->catrefs[owner->ncatrefs - 1]);
00337 ReleaseCatCache(owner->catrefs[owner->ncatrefs - 1]);
00338 }
00339
00340 while (owner->ncatlistrefs > 0)
00341 {
00342 if (isCommit)
00343 PrintCatCacheListLeakWarning(owner->catlistrefs[owner->ncatlistrefs - 1]);
00344 ReleaseCatCacheList(owner->catlistrefs[owner->ncatlistrefs - 1]);
00345 }
00346
00347 while (owner->nplanrefs > 0)
00348 {
00349 if (isCommit)
00350 PrintPlanCacheLeakWarning(owner->planrefs[owner->nplanrefs - 1]);
00351 ReleaseCachedPlan(owner->planrefs[owner->nplanrefs - 1], true);
00352 }
00353
00354 while (owner->ntupdescs > 0)
00355 {
00356 if (isCommit)
00357 PrintTupleDescLeakWarning(owner->tupdescs[owner->ntupdescs - 1]);
00358 DecrTupleDescRefCount(owner->tupdescs[owner->ntupdescs - 1]);
00359 }
00360
00361 while (owner->nsnapshots > 0)
00362 {
00363 if (isCommit)
00364 PrintSnapshotLeakWarning(owner->snapshots[owner->nsnapshots - 1]);
00365 UnregisterSnapshot(owner->snapshots[owner->nsnapshots - 1]);
00366 }
00367
00368
00369 while (owner->nfiles > 0)
00370 {
00371 if (isCommit)
00372 PrintFileLeakWarning(owner->files[owner->nfiles - 1]);
00373 FileClose(owner->files[owner->nfiles - 1]);
00374 }
00375
00376
00377 ReleaseResources_hash();
00378 }
00379
00380
00381 for (item = ResourceRelease_callbacks; item; item = item->next)
00382 (*item->callback) (phase, isCommit, isTopLevel, item->arg);
00383
00384 CurrentResourceOwner = save;
00385 }
00386
00387
00388
00389
00390
00391
00392
00393 void
00394 ResourceOwnerDelete(ResourceOwner owner)
00395 {
00396
00397 Assert(owner != CurrentResourceOwner);
00398
00399
00400 Assert(owner->nbuffers == 0);
00401 Assert(owner->nlocks == 0 || owner->nlocks == MAX_RESOWNER_LOCKS + 1);
00402 Assert(owner->ncatrefs == 0);
00403 Assert(owner->ncatlistrefs == 0);
00404 Assert(owner->nrelrefs == 0);
00405 Assert(owner->nplanrefs == 0);
00406 Assert(owner->ntupdescs == 0);
00407 Assert(owner->nsnapshots == 0);
00408 Assert(owner->nfiles == 0);
00409
00410
00411
00412
00413
00414 while (owner->firstchild != NULL)
00415 ResourceOwnerDelete(owner->firstchild);
00416
00417
00418
00419
00420
00421
00422 ResourceOwnerNewParent(owner, NULL);
00423
00424
00425 if (owner->buffers)
00426 pfree(owner->buffers);
00427 if (owner->catrefs)
00428 pfree(owner->catrefs);
00429 if (owner->catlistrefs)
00430 pfree(owner->catlistrefs);
00431 if (owner->relrefs)
00432 pfree(owner->relrefs);
00433 if (owner->planrefs)
00434 pfree(owner->planrefs);
00435 if (owner->tupdescs)
00436 pfree(owner->tupdescs);
00437 if (owner->snapshots)
00438 pfree(owner->snapshots);
00439 if (owner->files)
00440 pfree(owner->files);
00441
00442 pfree(owner);
00443 }
00444
00445
00446
00447
00448 ResourceOwner
00449 ResourceOwnerGetParent(ResourceOwner owner)
00450 {
00451 return owner->parent;
00452 }
00453
00454
00455
00456
00457 void
00458 ResourceOwnerNewParent(ResourceOwner owner,
00459 ResourceOwner newparent)
00460 {
00461 ResourceOwner oldparent = owner->parent;
00462
00463 if (oldparent)
00464 {
00465 if (owner == oldparent->firstchild)
00466 oldparent->firstchild = owner->nextchild;
00467 else
00468 {
00469 ResourceOwner child;
00470
00471 for (child = oldparent->firstchild; child; child = child->nextchild)
00472 {
00473 if (owner == child->nextchild)
00474 {
00475 child->nextchild = owner->nextchild;
00476 break;
00477 }
00478 }
00479 }
00480 }
00481
00482 if (newparent)
00483 {
00484 Assert(owner != newparent);
00485 owner->parent = newparent;
00486 owner->nextchild = newparent->firstchild;
00487 newparent->firstchild = owner;
00488 }
00489 else
00490 {
00491 owner->parent = NULL;
00492 owner->nextchild = NULL;
00493 }
00494 }
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505 void
00506 RegisterResourceReleaseCallback(ResourceReleaseCallback callback, void *arg)
00507 {
00508 ResourceReleaseCallbackItem *item;
00509
00510 item = (ResourceReleaseCallbackItem *)
00511 MemoryContextAlloc(TopMemoryContext,
00512 sizeof(ResourceReleaseCallbackItem));
00513 item->callback = callback;
00514 item->arg = arg;
00515 item->next = ResourceRelease_callbacks;
00516 ResourceRelease_callbacks = item;
00517 }
00518
00519 void
00520 UnregisterResourceReleaseCallback(ResourceReleaseCallback callback, void *arg)
00521 {
00522 ResourceReleaseCallbackItem *item;
00523 ResourceReleaseCallbackItem *prev;
00524
00525 prev = NULL;
00526 for (item = ResourceRelease_callbacks; item; prev = item, item = item->next)
00527 {
00528 if (item->callback == callback && item->arg == arg)
00529 {
00530 if (prev)
00531 prev->next = item->next;
00532 else
00533 ResourceRelease_callbacks = item->next;
00534 pfree(item);
00535 break;
00536 }
00537 }
00538 }
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551 void
00552 ResourceOwnerEnlargeBuffers(ResourceOwner owner)
00553 {
00554 int newmax;
00555
00556 if (owner == NULL ||
00557 owner->nbuffers < owner->maxbuffers)
00558 return;
00559
00560 if (owner->buffers == NULL)
00561 {
00562 newmax = 16;
00563 owner->buffers = (Buffer *)
00564 MemoryContextAlloc(TopMemoryContext, newmax * sizeof(Buffer));
00565 owner->maxbuffers = newmax;
00566 }
00567 else
00568 {
00569 newmax = owner->maxbuffers * 2;
00570 owner->buffers = (Buffer *)
00571 repalloc(owner->buffers, newmax * sizeof(Buffer));
00572 owner->maxbuffers = newmax;
00573 }
00574 }
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584 void
00585 ResourceOwnerRememberBuffer(ResourceOwner owner, Buffer buffer)
00586 {
00587 if (owner != NULL)
00588 {
00589 Assert(owner->nbuffers < owner->maxbuffers);
00590 owner->buffers[owner->nbuffers] = buffer;
00591 owner->nbuffers++;
00592 }
00593 }
00594
00595
00596
00597
00598
00599
00600
00601 void
00602 ResourceOwnerForgetBuffer(ResourceOwner owner, Buffer buffer)
00603 {
00604 if (owner != NULL)
00605 {
00606 Buffer *buffers = owner->buffers;
00607 int nb1 = owner->nbuffers - 1;
00608 int i;
00609
00610
00611
00612
00613
00614
00615 for (i = nb1; i >= 0; i--)
00616 {
00617 if (buffers[i] == buffer)
00618 {
00619 while (i < nb1)
00620 {
00621 buffers[i] = buffers[i + 1];
00622 i++;
00623 }
00624 owner->nbuffers = nb1;
00625 return;
00626 }
00627 }
00628 elog(ERROR, "buffer %d is not owned by resource owner %s",
00629 buffer, owner->name);
00630 }
00631 }
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643 void
00644 ResourceOwnerRememberLock(ResourceOwner owner, LOCALLOCK * locallock)
00645 {
00646 if (owner->nlocks > MAX_RESOWNER_LOCKS)
00647 return;
00648
00649 if (owner->nlocks < MAX_RESOWNER_LOCKS)
00650 owner->locks[owner->nlocks] = locallock;
00651 else
00652 {
00653
00654 }
00655 owner->nlocks++;
00656 }
00657
00658
00659
00660
00661 void
00662 ResourceOwnerForgetLock(ResourceOwner owner, LOCALLOCK *locallock)
00663 {
00664 int i;
00665
00666 if (owner->nlocks > MAX_RESOWNER_LOCKS)
00667 return;
00668
00669 Assert(owner->nlocks > 0);
00670 for (i = owner->nlocks - 1; i >= 0; i--)
00671 {
00672 if (locallock == owner->locks[i])
00673 {
00674 owner->locks[i] = owner->locks[owner->nlocks - 1];
00675 owner->nlocks--;
00676 return;
00677 }
00678 }
00679 elog(ERROR, "lock reference %p is not owned by resource owner %s",
00680 locallock, owner->name);
00681 }
00682
00683
00684
00685
00686
00687
00688
00689
00690 void
00691 ResourceOwnerEnlargeCatCacheRefs(ResourceOwner owner)
00692 {
00693 int newmax;
00694
00695 if (owner->ncatrefs < owner->maxcatrefs)
00696 return;
00697
00698 if (owner->catrefs == NULL)
00699 {
00700 newmax = 16;
00701 owner->catrefs = (HeapTuple *)
00702 MemoryContextAlloc(TopMemoryContext, newmax * sizeof(HeapTuple));
00703 owner->maxcatrefs = newmax;
00704 }
00705 else
00706 {
00707 newmax = owner->maxcatrefs * 2;
00708 owner->catrefs = (HeapTuple *)
00709 repalloc(owner->catrefs, newmax * sizeof(HeapTuple));
00710 owner->maxcatrefs = newmax;
00711 }
00712 }
00713
00714
00715
00716
00717
00718
00719 void
00720 ResourceOwnerRememberCatCacheRef(ResourceOwner owner, HeapTuple tuple)
00721 {
00722 Assert(owner->ncatrefs < owner->maxcatrefs);
00723 owner->catrefs[owner->ncatrefs] = tuple;
00724 owner->ncatrefs++;
00725 }
00726
00727
00728
00729
00730 void
00731 ResourceOwnerForgetCatCacheRef(ResourceOwner owner, HeapTuple tuple)
00732 {
00733 HeapTuple *catrefs = owner->catrefs;
00734 int nc1 = owner->ncatrefs - 1;
00735 int i;
00736
00737 for (i = nc1; i >= 0; i--)
00738 {
00739 if (catrefs[i] == tuple)
00740 {
00741 while (i < nc1)
00742 {
00743 catrefs[i] = catrefs[i + 1];
00744 i++;
00745 }
00746 owner->ncatrefs = nc1;
00747 return;
00748 }
00749 }
00750 elog(ERROR, "catcache reference %p is not owned by resource owner %s",
00751 tuple, owner->name);
00752 }
00753
00754
00755
00756
00757
00758
00759
00760
00761 void
00762 ResourceOwnerEnlargeCatCacheListRefs(ResourceOwner owner)
00763 {
00764 int newmax;
00765
00766 if (owner->ncatlistrefs < owner->maxcatlistrefs)
00767 return;
00768
00769 if (owner->catlistrefs == NULL)
00770 {
00771 newmax = 16;
00772 owner->catlistrefs = (CatCList **)
00773 MemoryContextAlloc(TopMemoryContext, newmax * sizeof(CatCList *));
00774 owner->maxcatlistrefs = newmax;
00775 }
00776 else
00777 {
00778 newmax = owner->maxcatlistrefs * 2;
00779 owner->catlistrefs = (CatCList **)
00780 repalloc(owner->catlistrefs, newmax * sizeof(CatCList *));
00781 owner->maxcatlistrefs = newmax;
00782 }
00783 }
00784
00785
00786
00787
00788
00789
00790 void
00791 ResourceOwnerRememberCatCacheListRef(ResourceOwner owner, CatCList *list)
00792 {
00793 Assert(owner->ncatlistrefs < owner->maxcatlistrefs);
00794 owner->catlistrefs[owner->ncatlistrefs] = list;
00795 owner->ncatlistrefs++;
00796 }
00797
00798
00799
00800
00801 void
00802 ResourceOwnerForgetCatCacheListRef(ResourceOwner owner, CatCList *list)
00803 {
00804 CatCList **catlistrefs = owner->catlistrefs;
00805 int nc1 = owner->ncatlistrefs - 1;
00806 int i;
00807
00808 for (i = nc1; i >= 0; i--)
00809 {
00810 if (catlistrefs[i] == list)
00811 {
00812 while (i < nc1)
00813 {
00814 catlistrefs[i] = catlistrefs[i + 1];
00815 i++;
00816 }
00817 owner->ncatlistrefs = nc1;
00818 return;
00819 }
00820 }
00821 elog(ERROR, "catcache list reference %p is not owned by resource owner %s",
00822 list, owner->name);
00823 }
00824
00825
00826
00827
00828
00829
00830
00831
00832 void
00833 ResourceOwnerEnlargeRelationRefs(ResourceOwner owner)
00834 {
00835 int newmax;
00836
00837 if (owner->nrelrefs < owner->maxrelrefs)
00838 return;
00839
00840 if (owner->relrefs == NULL)
00841 {
00842 newmax = 16;
00843 owner->relrefs = (Relation *)
00844 MemoryContextAlloc(TopMemoryContext, newmax * sizeof(Relation));
00845 owner->maxrelrefs = newmax;
00846 }
00847 else
00848 {
00849 newmax = owner->maxrelrefs * 2;
00850 owner->relrefs = (Relation *)
00851 repalloc(owner->relrefs, newmax * sizeof(Relation));
00852 owner->maxrelrefs = newmax;
00853 }
00854 }
00855
00856
00857
00858
00859
00860
00861 void
00862 ResourceOwnerRememberRelationRef(ResourceOwner owner, Relation rel)
00863 {
00864 Assert(owner->nrelrefs < owner->maxrelrefs);
00865 owner->relrefs[owner->nrelrefs] = rel;
00866 owner->nrelrefs++;
00867 }
00868
00869
00870
00871
00872 void
00873 ResourceOwnerForgetRelationRef(ResourceOwner owner, Relation rel)
00874 {
00875 Relation *relrefs = owner->relrefs;
00876 int nr1 = owner->nrelrefs - 1;
00877 int i;
00878
00879 for (i = nr1; i >= 0; i--)
00880 {
00881 if (relrefs[i] == rel)
00882 {
00883 while (i < nr1)
00884 {
00885 relrefs[i] = relrefs[i + 1];
00886 i++;
00887 }
00888 owner->nrelrefs = nr1;
00889 return;
00890 }
00891 }
00892 elog(ERROR, "relcache reference %s is not owned by resource owner %s",
00893 RelationGetRelationName(rel), owner->name);
00894 }
00895
00896
00897
00898
00899 static void
00900 PrintRelCacheLeakWarning(Relation rel)
00901 {
00902 elog(WARNING, "relcache reference leak: relation \"%s\" not closed",
00903 RelationGetRelationName(rel));
00904 }
00905
00906
00907
00908
00909
00910
00911
00912
00913 void
00914 ResourceOwnerEnlargePlanCacheRefs(ResourceOwner owner)
00915 {
00916 int newmax;
00917
00918 if (owner->nplanrefs < owner->maxplanrefs)
00919 return;
00920
00921 if (owner->planrefs == NULL)
00922 {
00923 newmax = 16;
00924 owner->planrefs = (CachedPlan **)
00925 MemoryContextAlloc(TopMemoryContext, newmax * sizeof(CachedPlan *));
00926 owner->maxplanrefs = newmax;
00927 }
00928 else
00929 {
00930 newmax = owner->maxplanrefs * 2;
00931 owner->planrefs = (CachedPlan **)
00932 repalloc(owner->planrefs, newmax * sizeof(CachedPlan *));
00933 owner->maxplanrefs = newmax;
00934 }
00935 }
00936
00937
00938
00939
00940
00941
00942 void
00943 ResourceOwnerRememberPlanCacheRef(ResourceOwner owner, CachedPlan *plan)
00944 {
00945 Assert(owner->nplanrefs < owner->maxplanrefs);
00946 owner->planrefs[owner->nplanrefs] = plan;
00947 owner->nplanrefs++;
00948 }
00949
00950
00951
00952
00953 void
00954 ResourceOwnerForgetPlanCacheRef(ResourceOwner owner, CachedPlan *plan)
00955 {
00956 CachedPlan **planrefs = owner->planrefs;
00957 int np1 = owner->nplanrefs - 1;
00958 int i;
00959
00960 for (i = np1; i >= 0; i--)
00961 {
00962 if (planrefs[i] == plan)
00963 {
00964 while (i < np1)
00965 {
00966 planrefs[i] = planrefs[i + 1];
00967 i++;
00968 }
00969 owner->nplanrefs = np1;
00970 return;
00971 }
00972 }
00973 elog(ERROR, "plancache reference %p is not owned by resource owner %s",
00974 plan, owner->name);
00975 }
00976
00977
00978
00979
00980 static void
00981 PrintPlanCacheLeakWarning(CachedPlan *plan)
00982 {
00983 elog(WARNING, "plancache reference leak: plan %p not closed", plan);
00984 }
00985
00986
00987
00988
00989
00990
00991
00992
00993 void
00994 ResourceOwnerEnlargeTupleDescs(ResourceOwner owner)
00995 {
00996 int newmax;
00997
00998 if (owner->ntupdescs < owner->maxtupdescs)
00999 return;
01000
01001 if (owner->tupdescs == NULL)
01002 {
01003 newmax = 16;
01004 owner->tupdescs = (TupleDesc *)
01005 MemoryContextAlloc(TopMemoryContext, newmax * sizeof(TupleDesc));
01006 owner->maxtupdescs = newmax;
01007 }
01008 else
01009 {
01010 newmax = owner->maxtupdescs * 2;
01011 owner->tupdescs = (TupleDesc *)
01012 repalloc(owner->tupdescs, newmax * sizeof(TupleDesc));
01013 owner->maxtupdescs = newmax;
01014 }
01015 }
01016
01017
01018
01019
01020
01021
01022 void
01023 ResourceOwnerRememberTupleDesc(ResourceOwner owner, TupleDesc tupdesc)
01024 {
01025 Assert(owner->ntupdescs < owner->maxtupdescs);
01026 owner->tupdescs[owner->ntupdescs] = tupdesc;
01027 owner->ntupdescs++;
01028 }
01029
01030
01031
01032
01033 void
01034 ResourceOwnerForgetTupleDesc(ResourceOwner owner, TupleDesc tupdesc)
01035 {
01036 TupleDesc *tupdescs = owner->tupdescs;
01037 int nt1 = owner->ntupdescs - 1;
01038 int i;
01039
01040 for (i = nt1; i >= 0; i--)
01041 {
01042 if (tupdescs[i] == tupdesc)
01043 {
01044 while (i < nt1)
01045 {
01046 tupdescs[i] = tupdescs[i + 1];
01047 i++;
01048 }
01049 owner->ntupdescs = nt1;
01050 return;
01051 }
01052 }
01053 elog(ERROR, "tupdesc reference %p is not owned by resource owner %s",
01054 tupdesc, owner->name);
01055 }
01056
01057
01058
01059
01060 static void
01061 PrintTupleDescLeakWarning(TupleDesc tupdesc)
01062 {
01063 elog(WARNING,
01064 "TupleDesc reference leak: TupleDesc %p (%u,%d) still referenced",
01065 tupdesc, tupdesc->tdtypeid, tupdesc->tdtypmod);
01066 }
01067
01068
01069
01070
01071
01072
01073
01074
01075 void
01076 ResourceOwnerEnlargeSnapshots(ResourceOwner owner)
01077 {
01078 int newmax;
01079
01080 if (owner->nsnapshots < owner->maxsnapshots)
01081 return;
01082
01083 if (owner->snapshots == NULL)
01084 {
01085 newmax = 16;
01086 owner->snapshots = (Snapshot *)
01087 MemoryContextAlloc(TopMemoryContext, newmax * sizeof(Snapshot));
01088 owner->maxsnapshots = newmax;
01089 }
01090 else
01091 {
01092 newmax = owner->maxsnapshots * 2;
01093 owner->snapshots = (Snapshot *)
01094 repalloc(owner->snapshots, newmax * sizeof(Snapshot));
01095 owner->maxsnapshots = newmax;
01096 }
01097 }
01098
01099
01100
01101
01102
01103
01104 void
01105 ResourceOwnerRememberSnapshot(ResourceOwner owner, Snapshot snapshot)
01106 {
01107 Assert(owner->nsnapshots < owner->maxsnapshots);
01108 owner->snapshots[owner->nsnapshots] = snapshot;
01109 owner->nsnapshots++;
01110 }
01111
01112
01113
01114
01115 void
01116 ResourceOwnerForgetSnapshot(ResourceOwner owner, Snapshot snapshot)
01117 {
01118 Snapshot *snapshots = owner->snapshots;
01119 int ns1 = owner->nsnapshots - 1;
01120 int i;
01121
01122 for (i = ns1; i >= 0; i--)
01123 {
01124 if (snapshots[i] == snapshot)
01125 {
01126 while (i < ns1)
01127 {
01128 snapshots[i] = snapshots[i + 1];
01129 i++;
01130 }
01131 owner->nsnapshots = ns1;
01132 return;
01133 }
01134 }
01135 elog(ERROR, "snapshot reference %p is not owned by resource owner %s",
01136 snapshot, owner->name);
01137 }
01138
01139
01140
01141
01142 static void
01143 PrintSnapshotLeakWarning(Snapshot snapshot)
01144 {
01145 elog(WARNING,
01146 "Snapshot reference leak: Snapshot %p still referenced",
01147 snapshot);
01148 }
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158 void
01159 ResourceOwnerEnlargeFiles(ResourceOwner owner)
01160 {
01161 int newmax;
01162
01163 if (owner->nfiles < owner->maxfiles)
01164 return;
01165
01166 if (owner->files == NULL)
01167 {
01168 newmax = 16;
01169 owner->files = (File *)
01170 MemoryContextAlloc(TopMemoryContext, newmax * sizeof(File));
01171 owner->maxfiles = newmax;
01172 }
01173 else
01174 {
01175 newmax = owner->maxfiles * 2;
01176 owner->files = (File *)
01177 repalloc(owner->files, newmax * sizeof(File));
01178 owner->maxfiles = newmax;
01179 }
01180 }
01181
01182
01183
01184
01185
01186
01187 void
01188 ResourceOwnerRememberFile(ResourceOwner owner, File file)
01189 {
01190 Assert(owner->nfiles < owner->maxfiles);
01191 owner->files[owner->nfiles] = file;
01192 owner->nfiles++;
01193 }
01194
01195
01196
01197
01198 void
01199 ResourceOwnerForgetFile(ResourceOwner owner, File file)
01200 {
01201 File *files = owner->files;
01202 int ns1 = owner->nfiles - 1;
01203 int i;
01204
01205 for (i = ns1; i >= 0; i--)
01206 {
01207 if (files[i] == file)
01208 {
01209 while (i < ns1)
01210 {
01211 files[i] = files[i + 1];
01212 i++;
01213 }
01214 owner->nfiles = ns1;
01215 return;
01216 }
01217 }
01218 elog(ERROR, "temporery file %d is not owned by resource owner %s",
01219 file, owner->name);
01220 }
01221
01222
01223
01224
01225
01226 static void
01227 PrintFileLeakWarning(File file)
01228 {
01229 elog(WARNING,
01230 "temporary file leak: File %d still referenced",
01231 file);
01232 }