|
9 | 9 | #include "postgres.h"
|
10 | 10 |
|
11 | 11 | #include "access/htup_details.h"
|
| 12 | +#include "access/relation.h" |
12 | 13 | #include "catalog/pg_type.h"
|
13 | 14 | #include "funcapi.h"
|
14 | 15 | #include "port/pg_numa.h"
|
15 | 16 | #include "storage/buf_internals.h"
|
16 | 17 | #include "storage/bufmgr.h"
|
| 18 | +#include "utils/rel.h" |
17 | 19 |
|
18 | 20 |
|
19 | 21 | #define NUM_BUFFERCACHE_PAGES_MIN_ELEM 8
|
20 | 22 | #define NUM_BUFFERCACHE_PAGES_ELEM 9
|
21 | 23 | #define NUM_BUFFERCACHE_SUMMARY_ELEM 5
|
22 | 24 | #define NUM_BUFFERCACHE_USAGE_COUNTS_ELEM 4
|
| 25 | +#define NUM_BUFFERCACHE_EVICT_ELEM 2 |
| 26 | +#define NUM_BUFFERCACHE_EVICT_RELATION_ELEM 3 |
| 27 | +#define NUM_BUFFERCACHE_EVICT_ALL_ELEM 3 |
23 | 28 |
|
24 | 29 | #define NUM_BUFFERCACHE_NUMA_ELEM 3
|
25 | 30 |
|
@@ -93,6 +98,8 @@ PG_FUNCTION_INFO_V1(pg_buffercache_numa_pages);
|
93 | 98 | PG_FUNCTION_INFO_V1(pg_buffercache_summary);
|
94 | 99 | PG_FUNCTION_INFO_V1(pg_buffercache_usage_counts);
|
95 | 100 | PG_FUNCTION_INFO_V1(pg_buffercache_evict);
|
| 101 | +PG_FUNCTION_INFO_V1(pg_buffercache_evict_relation); |
| 102 | +PG_FUNCTION_INFO_V1(pg_buffercache_evict_all); |
96 | 103 |
|
97 | 104 |
|
98 | 105 | /* Only need to touch memory once per backend process lifetime */
|
@@ -637,21 +644,131 @@ pg_buffercache_usage_counts(PG_FUNCTION_ARGS)
|
637 | 644 | return (Datum) 0;
|
638 | 645 | }
|
639 | 646 |
|
| 647 | +/* |
| 648 | + * Helper function to check if the user has superuser privileges. |
| 649 | + */ |
| 650 | +static void |
| 651 | +pg_buffercache_superuser_check(char *func_name) |
| 652 | +{ |
| 653 | + if (!superuser()) |
| 654 | + ereport(ERROR, |
| 655 | + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), |
| 656 | + errmsg("must be superuser to use %s()", |
| 657 | + func_name))); |
| 658 | +} |
| 659 | + |
640 | 660 | /*
|
641 | 661 | * Try to evict a shared buffer.
|
642 | 662 | */
|
643 | 663 | Datum
|
644 | 664 | pg_buffercache_evict(PG_FUNCTION_ARGS)
|
645 | 665 | {
|
| 666 | + Datum result; |
| 667 | + TupleDesc tupledesc; |
| 668 | + HeapTuple tuple; |
| 669 | + Datum values[NUM_BUFFERCACHE_EVICT_ELEM]; |
| 670 | + bool nulls[NUM_BUFFERCACHE_EVICT_ELEM] = {0}; |
| 671 | + |
646 | 672 | Buffer buf = PG_GETARG_INT32(0);
|
| 673 | + bool buffer_flushed; |
647 | 674 |
|
648 |
| - if (!superuser()) |
649 |
| - ereport(ERROR, |
650 |
| - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), |
651 |
| - errmsg("must be superuser to use pg_buffercache_evict function"))); |
| 675 | + if (get_call_result_type(fcinfo, NULL, &tupledesc) != TYPEFUNC_COMPOSITE) |
| 676 | + elog(ERROR, "return type must be a row type"); |
| 677 | + |
| 678 | + pg_buffercache_superuser_check("pg_buffercache_evict"); |
652 | 679 |
|
653 | 680 | if (buf < 1 || buf > NBuffers)
|
654 | 681 | elog(ERROR, "bad buffer ID: %d", buf);
|
655 | 682 |
|
656 |
| - PG_RETURN_BOOL(EvictUnpinnedBuffer(buf)); |
| 683 | + values[0] = BoolGetDatum(EvictUnpinnedBuffer(buf, &buffer_flushed)); |
| 684 | + values[1] = BoolGetDatum(buffer_flushed); |
| 685 | + |
| 686 | + tuple = heap_form_tuple(tupledesc, values, nulls); |
| 687 | + result = HeapTupleGetDatum(tuple); |
| 688 | + |
| 689 | + PG_RETURN_DATUM(result); |
| 690 | +} |
| 691 | + |
| 692 | +/* |
| 693 | + * Try to evict specified relation. |
| 694 | + */ |
| 695 | +Datum |
| 696 | +pg_buffercache_evict_relation(PG_FUNCTION_ARGS) |
| 697 | +{ |
| 698 | + Datum result; |
| 699 | + TupleDesc tupledesc; |
| 700 | + HeapTuple tuple; |
| 701 | + Datum values[NUM_BUFFERCACHE_EVICT_RELATION_ELEM]; |
| 702 | + bool nulls[NUM_BUFFERCACHE_EVICT_RELATION_ELEM] = {0}; |
| 703 | + |
| 704 | + Oid relOid; |
| 705 | + Relation rel; |
| 706 | + |
| 707 | + int32 buffers_evicted = 0; |
| 708 | + int32 buffers_flushed = 0; |
| 709 | + int32 buffers_skipped = 0; |
| 710 | + |
| 711 | + if (get_call_result_type(fcinfo, NULL, &tupledesc) != TYPEFUNC_COMPOSITE) |
| 712 | + elog(ERROR, "return type must be a row type"); |
| 713 | + |
| 714 | + pg_buffercache_superuser_check("pg_buffercache_evict_relation"); |
| 715 | + |
| 716 | + relOid = PG_GETARG_OID(0); |
| 717 | + |
| 718 | + rel = relation_open(relOid, AccessShareLock); |
| 719 | + |
| 720 | + if (RelationUsesLocalBuffers(rel)) |
| 721 | + ereport(ERROR, |
| 722 | + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), |
| 723 | + errmsg("relation uses local buffers, %s() is intended to be used for shared buffers only", |
| 724 | + "pg_buffercache_evict_relation"))); |
| 725 | + |
| 726 | + EvictRelUnpinnedBuffers(rel, &buffers_evicted, &buffers_flushed, |
| 727 | + &buffers_skipped); |
| 728 | + |
| 729 | + relation_close(rel, AccessShareLock); |
| 730 | + |
| 731 | + values[0] = Int32GetDatum(buffers_evicted); |
| 732 | + values[1] = Int32GetDatum(buffers_flushed); |
| 733 | + values[2] = Int32GetDatum(buffers_skipped); |
| 734 | + |
| 735 | + tuple = heap_form_tuple(tupledesc, values, nulls); |
| 736 | + result = HeapTupleGetDatum(tuple); |
| 737 | + |
| 738 | + PG_RETURN_DATUM(result); |
| 739 | +} |
| 740 | + |
| 741 | + |
| 742 | +/* |
| 743 | + * Try to evict all shared buffers. |
| 744 | + */ |
| 745 | +Datum |
| 746 | +pg_buffercache_evict_all(PG_FUNCTION_ARGS) |
| 747 | +{ |
| 748 | + Datum result; |
| 749 | + TupleDesc tupledesc; |
| 750 | + HeapTuple tuple; |
| 751 | + Datum values[NUM_BUFFERCACHE_EVICT_ALL_ELEM]; |
| 752 | + bool nulls[NUM_BUFFERCACHE_EVICT_ALL_ELEM] = {0}; |
| 753 | + |
| 754 | + int32 buffers_evicted = 0; |
| 755 | + int32 buffers_flushed = 0; |
| 756 | + int32 buffers_skipped = 0; |
| 757 | + |
| 758 | + if (get_call_result_type(fcinfo, NULL, &tupledesc) != TYPEFUNC_COMPOSITE) |
| 759 | + elog(ERROR, "return type must be a row type"); |
| 760 | + |
| 761 | + pg_buffercache_superuser_check("pg_buffercache_evict_all"); |
| 762 | + |
| 763 | + EvictAllUnpinnedBuffers(&buffers_evicted, &buffers_flushed, |
| 764 | + &buffers_skipped); |
| 765 | + |
| 766 | + values[0] = Int32GetDatum(buffers_evicted); |
| 767 | + values[1] = Int32GetDatum(buffers_flushed); |
| 768 | + values[2] = Int32GetDatum(buffers_skipped); |
| 769 | + |
| 770 | + tuple = heap_form_tuple(tupledesc, values, nulls); |
| 771 | + result = HeapTupleGetDatum(tuple); |
| 772 | + |
| 773 | + PG_RETURN_DATUM(result); |
657 | 774 | }
|
0 commit comments