PostgreSQL Source Code: src/backend/utils/resowner/resowner.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
47
57
58
59
60
61
62
63
65{
69
70
71
72
73#define RESOWNER_ARRAY_SIZE 32
74
75
76
77
78
79#define RESOWNER_HASH_INIT_SIZE 64
80
81
82
83
84
85
86
87
88
89
90
91#define RESOWNER_HASH_MAX_ITEMS(capacity) \
92 Min(capacity - RESOWNER_ARRAY_SIZE, (capacity)/4 * 3)
93
95 "initial hash size too small compared to array size");
96
97
98
99
100
101
102
103
104
105
106
107#define MAX_RESOWNER_LOCKS 15
108
109
110
111
113{
118
119
120
121
122
123
124
125
128
129
130
131
132
136
137
138
139
140
141
143
144
145
146
147
148
149
150
151
152
153
157
158
160
161
162
163
164
166};
167
168
169
170
171
172
177
178
179
180#ifdef RESOWNER_STATS
181static int narray_lookups = 0;
182static int nhash_lookups = 0;
183#endif
184
185
186
187
189{
194
196
197
198
206 bool printLeakWarnings);
209 bool isCommit,
210 bool isTopLevel);
212
213
214
215
216
217
218
219
220
223{
224
225
226
227
228
229
230
231
232
233
234#if SIZEOF_DATUM == 8
236#else
238#endif
239}
240
241
242
243
244static void
246{
249
250 Assert(kind != NULL);
251
252
254 for (;;)
255 {
257 break;
259 }
263}
264
265
266
267
268static int
270{
273
274
278 return -1;
279 else
280 return 1;
281}
282
283
284
285
286
287
288
289
290
291static void
293{
296
297 if (owner->nhash == 0)
298 {
301 }
302 else
303 {
304
305
306
307
309
311 {
313 {
314 if (dst != idx)
316 dst++;
317 }
318 }
319
320
321
322
323
324
325
326
329 {
331 dst++;
332 }
334 owner->narr = 0;
335 owner->nhash = dst;
336
339 }
340
342}
343
344
345
346
347static void
349 bool printLeakWarnings)
350{
353
354
355
356
357
360 if (owner->nhash == 0)
361 {
364 }
365 else
366 {
370 }
371
372
373
374
375
376
377
379 {
383
385 break;
387
388 if (printLeakWarnings)
389 {
390 char *res_str;
391
395 elog(WARNING, "resource was not closed: %s", res_str);
397 }
400 }
401 if (owner->nhash == 0)
403 else
405}
406
407
408
409
410
411
412
413
414
415
416
417
418
419
422{
424
428
429 if (parent)
430 {
431 owner->parent = parent;
434 }
435
437
438 return owner;
439}
440
441
442
443
444
445
446
447
448
449
450
451void
453{
454
455
456
457
459 elog(ERROR, "ResourceOwnerEnlarge called after release started");
460
462 return;
463
464
465
466
468 {
470 oldcap,
471 newcap;
474
475 oldhash = owner->hash;
477
478
482
483
484
485
486
487 owner->hash = newhash;
490 owner->nhash = 0;
491
492 if (oldhash != NULL)
493 {
494
495
496
497
498
499 for (i = 0; i < oldcap; i++)
500 {
501 if (oldhash[i].kind != NULL)
503 }
504
505
507 }
508 }
509
510
511 for (int i = 0; i < owner->narr; i++)
513 owner->narr = 0;
514
516}
517
518
519
520
521
522
523void
525{
527
528
531
532
533
534
535
538
540 {
541
542 elog(ERROR, "ResourceOwnerRemember called but array was full");
543 }
544
545
549 owner->narr++;
550}
551
552
553
554
555
556
557
558
559
560
561
562
563void
565{
566
567
568
569
570
572 elog(ERROR, "ResourceOwnerForget called for %s after release started", kind->name);
574
575
576 for (int i = owner->narr - 1; i >= 0; i--)
577 {
580 {
581 owner->arr[i] = owner->arr[owner->narr - 1];
582 owner->narr--;
583
584#ifdef RESOWNER_STATS
585 narray_lookups++;
586#endif
587 return;
588 }
589 }
590
591
592 if (owner->nhash > 0)
593 {
596
599 {
602 {
606
607#ifdef RESOWNER_STATS
608 nhash_lookups++;
609#endif
610 return;
611 }
613 }
614 }
615
616
617
618
619
620
621 elog(ERROR, "%s %p is not owned by resource owner %s",
623}
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657void
660 bool isCommit,
661 bool isTopLevel)
662{
663
665
666#ifdef RESOWNER_STATS
667 if (isTopLevel)
668 {
669 elog(LOG, "RESOWNER STATS: lookups: array %d, hash %d",
670 narray_lookups, nhash_lookups);
671 narray_lookups = 0;
672 nhash_lookups = 0;
673 }
674#endif
675}
676
677static void
680 bool isCommit,
681 bool isTopLevel)
682{
687
688
691
692
693
694
695
696
697
698
699
701 {
705 }
706 else
707 {
708
709
710
711
712
713
714 }
716 {
718 owner->sorted = true;
719 }
720
721
722
723
724
727
729 {
730
731
732
733
734
735
736
738
740 {
742
744 }
745 }
747 {
748 if (isTopLevel)
749 {
750
751
752
753
754
756 {
759 }
760 }
761 else
762 {
763
764
765
766
767
769 int nlocks;
770
772
773
774
775
776
778 {
779 locks = NULL;
780 nlocks = 0;
781 }
782 else
783 {
784 locks = owner->locks;
785 nlocks = owner->nlocks;
786 }
787
788 if (isCommit)
790 else
792 }
793 }
795 {
796
797
798
800 }
801
802
804 {
805
807 item->callback(phase, isCommit, isTopLevel, item->arg);
808 }
809
811}
812
813
814
815
816
817void
819{
820
822 elog(ERROR, "ResourceOwnerForget called for %s after release started", kind->name);
824
825
826
827
828
829
831
832
833 for (int i = 0; i < owner->narr; i++)
834 {
835 if (owner->arr[i].kind == kind)
836 {
838
839 owner->arr[i] = owner->arr[owner->narr - 1];
840 owner->narr--;
841 i--;
842
844 }
845 }
846
847
848 for (int i = 0; i < owner->capacity; i++)
849 {
851 {
853
857
859 }
860 }
862}
863
864
865
866
867
868
869
870void
872{
873
875
876
880
881
882
883
884
887
888
889
890
891
892
894
895
896 if (owner->hash)
899}
900
901
902
903
906{
907 return owner->parent;
908}
909
910
911
912
913void
916{
918
919 if (oldparent)
920 {
923 else
924 {
926
928 {
930 {
932 break;
933 }
934 }
935 }
936 }
937
938 if (newparent)
939 {
940 Assert(owner != newparent);
941 owner->parent = newparent;
944 }
945 else
946 {
947 owner->parent = NULL;
949 }
950}
951
952
953
954
955
956
957
958
959
960void
962{
964
972}
973
974void
976{
979
980 prev = NULL;
982 {
984 {
985 if (prev)
987 else
990 break;
991 }
992 }
993}
994
995
996
997
998void
1000{
1005
1006
1007
1008
1009
1011}
1012
1013
1014
1015
1016
1017
1018void
1020{
1021
1022
1023
1024
1027 isCommit, true);
1030 isCommit, true);
1033 isCommit, true);
1034
1037}
1038
1039
1040
1041
1042
1043static void
1045{
1046 bool isCommit = (code == 0);
1047
1049}
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061void
1063{
1064 Assert(locallock != NULL);
1065
1067 return;
1068
1070 owner->locks[owner->nlocks] = locallock;
1071 else
1072 {
1073
1074 }
1076}
1077
1078
1079
1080
1081void
1083{
1084 int i;
1085
1087 return;
1088
1090 for (i = owner->nlocks - 1; i >= 0; i--)
1091 {
1092 if (locallock == owner->locks[i])
1093 {
1096 return;
1097 }
1098 }
1099 elog(ERROR, "lock reference %p is not owned by resource owner %s",
1100 locallock, owner->name);
1101}
1102
1103void
1105{
1107}
1108
1109void
1111{
1113}
Datum idx(PG_FUNCTION_ARGS)
void pgaio_io_release_resowner(dlist_node *ioh_node, bool on_error)
static uint64 hash_combine64(uint64 a, uint64 b)
static uint64 murmurhash64(uint64 data)
static uint32 hash_combine(uint32 a, uint32 b)
static uint32 murmurhash32(uint32 data)
Assert(PointerIsAligned(start, uint64))
static void dlist_init(dlist_head *head)
static void dlist_delete_from(dlist_head *head, dlist_node *node)
static dlist_node * dlist_head_node(dlist_head *head)
static bool dlist_is_empty(const dlist_head *head)
static void dlist_push_tail(dlist_head *head, dlist_node *node)
static int pg_cmp_u32(uint32 a, uint32 b)
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
void LockReassignCurrentOwner(LOCALLOCK **locallocks, int nlocks)
void LockReleaseCurrentOwner(LOCALLOCK **locallocks, int nlocks)
void * MemoryContextAlloc(MemoryContext context, Size size)
void * MemoryContextAllocZero(MemoryContext context, Size size)
void pfree(void *pointer)
MemoryContext TopMemoryContext
#define qsort(a, b, c, d)
static Pointer DatumGetPointer(Datum X)
void ReleasePredicateLocks(bool isCommit, bool isReadOnlySafe)
char * psprintf(const char *fmt,...)
void ResourceOwnerNewParent(ResourceOwner owner, ResourceOwner newparent)
#define MAX_RESOWNER_LOCKS
void ResourceOwnerRememberLock(ResourceOwner owner, LOCALLOCK *locallock)
static void ReleaseAuxProcessResourcesCallback(int code, Datum arg)
ResourceOwner TopTransactionResourceOwner
#define RESOWNER_HASH_INIT_SIZE
static void ResourceOwnerReleaseAll(ResourceOwner owner, ResourceReleasePhase phase, bool printLeakWarnings)
void UnregisterResourceReleaseCallback(ResourceReleaseCallback callback, void *arg)
ResourceOwner ResourceOwnerCreate(ResourceOwner parent, const char *name)
#define RESOWNER_HASH_MAX_ITEMS(capacity)
void ReleaseAuxProcessResources(bool isCommit)
ResourceOwner ResourceOwnerGetParent(ResourceOwner owner)
ResourceOwner CurrentResourceOwner
void ResourceOwnerRememberAioHandle(ResourceOwner owner, struct dlist_node *ioh_node)
static uint32 hash_resource_elem(Datum value, const ResourceOwnerDesc *kind)
struct ResourceElem ResourceElem
static ResourceReleaseCallbackItem * ResourceRelease_callbacks
static void ResourceOwnerAddToHash(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
void CreateAuxProcessResourceOwner(void)
void ResourceOwnerRelease(ResourceOwner owner, ResourceReleasePhase phase, bool isCommit, bool isTopLevel)
static int resource_priority_cmp(const void *a, const void *b)
void RegisterResourceReleaseCallback(ResourceReleaseCallback callback, void *arg)
static void ResourceOwnerReleaseInternal(ResourceOwner owner, ResourceReleasePhase phase, bool isCommit, bool isTopLevel)
void ResourceOwnerForget(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
void ResourceOwnerReleaseAllOfKind(ResourceOwner owner, const ResourceOwnerDesc *kind)
ResourceOwner AuxProcessResourceOwner
struct ResourceReleaseCallbackItem ResourceReleaseCallbackItem
void ResourceOwnerDelete(ResourceOwner owner)
ResourceOwner CurTransactionResourceOwner
void ResourceOwnerRemember(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
#define RESOWNER_ARRAY_SIZE
static void ResourceOwnerSort(ResourceOwner owner)
StaticAssertDecl(RESOWNER_HASH_MAX_ITEMS(RESOWNER_HASH_INIT_SIZE) >=RESOWNER_ARRAY_SIZE, "initial hash size too small compared to array size")
void ResourceOwnerForgetLock(ResourceOwner owner, LOCALLOCK *locallock)
void ResourceOwnerForgetAioHandle(ResourceOwner owner, struct dlist_node *ioh_node)
void ResourceOwnerEnlarge(ResourceOwner owner)
@ RESOURCE_RELEASE_BEFORE_LOCKS
@ RESOURCE_RELEASE_AFTER_LOCKS
struct ResourceOwnerData * ResourceOwner
void(* ResourceReleaseCallback)(ResourceReleasePhase phase, bool isCommit, bool isTopLevel, void *arg)
void ProcReleaseLocks(bool isCommit)
const ResourceOwnerDesc * kind
LOCALLOCK * locks[MAX_RESOWNER_LOCKS]
ResourceElem arr[RESOWNER_ARRAY_SIZE]
char *(* DebugPrint)(Datum res)
ResourceReleasePhase release_phase
void(* ReleaseResource)(Datum res)
ResourceReleasePriority release_priority
struct ResourceReleaseCallbackItem * next
ResourceReleaseCallback callback
static void callback(struct sockaddr *addr, struct sockaddr *mask, void *unused)