3
3
* pg_buffercache_pages.c
4
4
* display some contents of the buffer cache
5
5
*
6
- * $PostgreSQL: pgsql/contrib/pg_buffercache/pg_buffercache_pages.c,v 1.10 2006/10/19 18:32:46 tgl Exp $
6
+ * $PostgreSQL: pgsql/contrib/pg_buffercache/pg_buffercache_pages.c,v 1.11 2006/10/22 17:49:21 tgl Exp $
7
7
*-------------------------------------------------------------------------
8
8
*/
9
9
#include "postgres.h"
10
- #include "funcapi.h"
10
+
11
+ #include "access/heapam.h"
11
12
#include "catalog/pg_type.h"
13
+ #include "funcapi.h"
12
14
#include "storage/buf_internals.h"
13
15
#include "storage/bufmgr.h"
14
16
#include "utils/relcache.h"
@@ -26,15 +28,13 @@ Datum pg_buffercache_pages(PG_FUNCTION_ARGS);
26
28
*/
27
29
typedef struct
28
30
{
29
-
30
31
uint32 bufferid ;
31
32
Oid relfilenode ;
32
33
Oid reltablespace ;
33
34
Oid reldatabase ;
34
35
BlockNumber blocknum ;
35
36
bool isvalid ;
36
37
bool isdirty ;
37
-
38
38
} BufferCachePagesRec ;
39
39
40
40
@@ -43,11 +43,8 @@ typedef struct
43
43
*/
44
44
typedef struct
45
45
{
46
-
47
- AttInMetadata * attinmeta ;
46
+ TupleDesc tupdesc ;
48
47
BufferCachePagesRec * record ;
49
- char * values [NUM_BUFFERCACHE_PAGES_ELEM ];
50
-
51
48
} BufferCachePagesContext ;
52
49
53
50
@@ -56,10 +53,10 @@ typedef struct
56
53
* relation node/tablespace/database/blocknum and dirty indicator.
57
54
*/
58
55
PG_FUNCTION_INFO_V1 (pg_buffercache_pages );
56
+
59
57
Datum
60
58
pg_buffercache_pages (PG_FUNCTION_ARGS )
61
59
{
62
-
63
60
FuncCallContext * funcctx ;
64
61
Datum result ;
65
62
MemoryContext oldcontext ;
@@ -77,7 +74,10 @@ pg_buffercache_pages(PG_FUNCTION_ARGS)
77
74
/* Switch context when allocating stuff to be used in later calls */
78
75
oldcontext = MemoryContextSwitchTo (funcctx -> multi_call_memory_ctx );
79
76
80
- /* Construct a tuple to return. */
77
+ /* Create a user function context for cross-call persistence */
78
+ fctx = (BufferCachePagesContext * ) palloc (sizeof (BufferCachePagesContext ));
79
+
80
+ /* Construct a tuple descriptor for the result rows. */
81
81
tupledesc = CreateTemplateTupleDesc (NUM_BUFFERCACHE_PAGES_ELEM , false);
82
82
TupleDescInitEntry (tupledesc , (AttrNumber ) 1 , "bufferid" ,
83
83
INT4OID , -1 , 0 );
@@ -92,27 +92,14 @@ pg_buffercache_pages(PG_FUNCTION_ARGS)
92
92
TupleDescInitEntry (tupledesc , (AttrNumber ) 6 , "isdirty" ,
93
93
BOOLOID , -1 , 0 );
94
94
95
- /* Generate attribute metadata needed later to produce tuples */
96
- funcctx -> attinmeta = TupleDescGetAttInMetadata (tupledesc );
97
-
98
- /*
99
- * Create a function context for cross-call persistence and initialize
100
- * the buffer counters.
101
- */
102
- fctx = (BufferCachePagesContext * ) palloc (sizeof (BufferCachePagesContext ));
103
- funcctx -> max_calls = NBuffers ;
104
- funcctx -> user_fctx = fctx ;
95
+ fctx -> tupdesc = BlessTupleDesc (tupledesc );
105
96
106
97
/* Allocate NBuffers worth of BufferCachePagesRec records. */
107
98
fctx -> record = (BufferCachePagesRec * ) palloc (sizeof (BufferCachePagesRec ) * NBuffers );
108
99
109
- /* allocate the strings for tuple formation */
110
- fctx -> values [0 ] = (char * ) palloc (3 * sizeof (uint32 ) + 1 );
111
- fctx -> values [1 ] = (char * ) palloc (3 * sizeof (uint32 ) + 1 );
112
- fctx -> values [2 ] = (char * ) palloc (3 * sizeof (uint32 ) + 1 );
113
- fctx -> values [3 ] = (char * ) palloc (3 * sizeof (uint32 ) + 1 );
114
- fctx -> values [4 ] = (char * ) palloc (3 * sizeof (uint32 ) + 1 );
115
- fctx -> values [5 ] = (char * ) palloc (2 );
100
+ /* Set max calls and remember the user function context. */
101
+ funcctx -> max_calls = NBuffers ;
102
+ funcctx -> user_fctx = fctx ;
116
103
117
104
/* Return to original context when allocating transient memory */
118
105
MemoryContextSwitchTo (oldcontext );
@@ -167,19 +154,11 @@ pg_buffercache_pages(PG_FUNCTION_ARGS)
167
154
if (funcctx -> call_cntr < funcctx -> max_calls )
168
155
{
169
156
uint32 i = funcctx -> call_cntr ;
170
- char * values [NUM_BUFFERCACHE_PAGES_ELEM ];
171
- int j ;
172
-
173
- /*
174
- * Use a temporary values array, initially pointing to fctx->values,
175
- * so it can be reassigned w/o losing the storage for subsequent
176
- * calls.
177
- */
178
- for (j = 0 ; j < NUM_BUFFERCACHE_PAGES_ELEM ; j ++ )
179
- {
180
- values [j ] = fctx -> values [j ];
181
- }
157
+ Datum values [NUM_BUFFERCACHE_PAGES_ELEM ];
158
+ bool nulls [NUM_BUFFERCACHE_PAGES_ELEM ];
182
159
160
+ values [0 ] = Int32GetDatum (fctx -> record [i ].bufferid );
161
+ nulls [0 ] = false;
183
162
184
163
/*
185
164
* Set all fields except the bufferid to null if the buffer is unused
@@ -188,43 +167,32 @@ pg_buffercache_pages(PG_FUNCTION_ARGS)
188
167
if (fctx -> record [i ].blocknum == InvalidBlockNumber ||
189
168
fctx -> record [i ].isvalid == false)
190
169
{
191
-
192
- sprintf (values [0 ], "%u" , fctx -> record [i ].bufferid );
193
- values [1 ] = NULL ;
194
- values [2 ] = NULL ;
195
- values [3 ] = NULL ;
196
- values [4 ] = NULL ;
197
- values [5 ] = NULL ;
198
-
170
+ nulls [1 ] = true;
171
+ nulls [2 ] = true;
172
+ nulls [3 ] = true;
173
+ nulls [4 ] = true;
174
+ nulls [5 ] = true;
199
175
}
200
176
else
201
177
{
202
-
203
- sprintf (values [0 ], "%u" , fctx -> record [i ].bufferid );
204
- sprintf (values [1 ], "%u" , fctx -> record [i ].relfilenode );
205
- sprintf (values [2 ], "%u" , fctx -> record [i ].reltablespace );
206
- sprintf (values [3 ], "%u" , fctx -> record [i ].reldatabase );
207
- sprintf (values [4 ], "%u" , fctx -> record [i ].blocknum );
208
- if (fctx -> record [i ].isdirty )
209
- {
210
- strcpy (values [5 ], "t" );
211
- }
212
- else
213
- {
214
- strcpy (values [5 ], "f" );
215
- }
216
-
178
+ values [1 ] = ObjectIdGetDatum (fctx -> record [i ].relfilenode );
179
+ nulls [1 ] = false;
180
+ values [2 ] = ObjectIdGetDatum (fctx -> record [i ].reltablespace );
181
+ nulls [2 ] = false;
182
+ values [3 ] = ObjectIdGetDatum (fctx -> record [i ].reldatabase );
183
+ nulls [3 ] = false;
184
+ values [4 ] = Int64GetDatum ((int64 ) fctx -> record [i ].blocknum );
185
+ nulls [4 ] = false;
186
+ values [5 ] = BoolGetDatum (fctx -> record [i ].isdirty );
187
+ nulls [5 ] = false;
217
188
}
218
189
219
-
220
190
/* Build and return the tuple. */
221
- tuple = BuildTupleFromCStrings ( funcctx -> attinmeta , values );
191
+ tuple = heap_form_tuple ( fctx -> tupdesc , values , nulls );
222
192
result = HeapTupleGetDatum (tuple );
223
193
224
-
225
194
SRF_RETURN_NEXT (funcctx , result );
226
195
}
227
196
else
228
197
SRF_RETURN_DONE (funcctx );
229
-
230
198
}
0 commit comments