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{

117 const char *name;

118

119

120

121

122

123

124

125

127 bool sorted;

128

129

130

131

132

134 uint8 narr;

135 uint32 nhash;

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;

258 idx = (idx + 1) & mask;

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 }

612 idx = (idx + 1) & mask;

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)