Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
de004e44
Commit
de004e44
authored
Mar 12, 2005
by
Neil Conway
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add pg_buffercache contrib module, from Mark Kirkwood.
parent
919594f3
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
409 additions
and
1 deletion
+409
-1
contrib/Makefile
contrib/Makefile
+2
-1
contrib/README
contrib/README
+4
-0
contrib/pg_buffercache/Makefile
contrib/pg_buffercache/Makefile
+17
-0
contrib/pg_buffercache/README.pg_buffercache
contrib/pg_buffercache/README.pg_buffercache
+112
-0
contrib/pg_buffercache/pg_buffercache.sql.in
contrib/pg_buffercache/pg_buffercache.sql.in
+18
-0
contrib/pg_buffercache/pg_buffercache_pages.c
contrib/pg_buffercache/pg_buffercache_pages.c
+238
-0
contrib/pg_buffercache/pg_buffercache_pages.h
contrib/pg_buffercache/pg_buffercache_pages.h
+18
-0
No files found.
contrib/Makefile
View file @
de004e44
# $PostgreSQL: pgsql/contrib/Makefile,v 1.5
3 2004/12/14 22:50:23 tgl
Exp $
# $PostgreSQL: pgsql/contrib/Makefile,v 1.5
4 2005/03/12 15:36:24 neilc
Exp $
subdir
=
contrib
top_builddir
=
..
...
...
@@ -26,6 +26,7 @@ WANTED_DIRS = \
noupdate
\
oid2name
\
pg_autovacuum
\
pg_buffercache
\
pg_dumplo
\
pg_trgm
\
pgbench
\
...
...
contrib/README
View file @
de004e44
...
...
@@ -136,6 +136,10 @@ pg_autovacuum -
Automatically performs vacuum
by Matthew T. O'Connor <matthew@zeut.net>
pg_buffercache -
Real time queries on the shared buffer cache
by Mark Kirkwood <markir@paradise.net.nz>
pg_dumplo -
Dump large objects
by Karel Zak <zakkr@zf.jcu.cz>
...
...
contrib/pg_buffercache/Makefile
0 → 100644
View file @
de004e44
# $PostgreSQL: pgsql/contrib/pg_buffercache/Makefile,v 1.1 2005/03/12 15:36:24 neilc Exp $
MODULE_big
=
pg_buffercache
OBJS
=
pg_buffercache_pages.o
DATA_built
=
pg_buffercache.sql
DOCS
=
README.pg_buffercache
ifdef
USE_PGXS
PGXS
=
$(
shell
pg_config
--pgxs
)
include
$(PGXS)
else
subdir
=
contrib/pg_buffercache
top_builddir
=
../..
include
$(top_builddir)/src/Makefile.global
include
$(top_srcdir)/contrib/contrib-global.mk
endif
contrib/pg_buffercache/README.pg_buffercache
0 → 100644
View file @
de004e44
Pg_buffercache - Real time queries on the shared buffer cache.
--------------
This module consists of a C function 'pg_buffercache_pages()' that returns
a set of records, plus a view 'pg_buffercache' to wrapper the function.
The intent is to do for the buffercache what pg_locks does for locks, i.e -
ability to examine what is happening at any given time without having to
restart or rebuild the server with debugging code added.
By default public access is REVOKED from both of these, just in case there
are security issues lurking.
Installation
------------
Build and install the main Postgresql source, then this contrib module:
$ cd contrib/pg_buffercache
$ gmake
$ gmake install
To register the functions:
$ psql -d <database> -f pg_buffercache.sql
Notes
-----
The definition of the columns exposed in the view is:
Column | references | Description
----------------+----------------------+------------------------------------
bufferid | | Id, 1->shared_buffers.
relfilenode | pg_class.relfilenode | Refilenode of the relation.
reltablespace | pg_tablespace.oid | Tablespace oid of the relation.
reldatabase | pg_database.oid | Database for the relation.
relblocknumber | | Offset of the page in the relation.
isdirty | | Is the page dirty?
There is one row for each buffer in the shared cache. Unused buffers are
shown with all fields null except bufferid.
Because the cache is shared by all the databases, there are pages from
relations not belonging to the current database.
When the pg_buffercache view is accessed, internal buffer manager locks are
taken, and a copy of the buffer cache data is made for the view to display.
This ensures that the view produces a consistent set of results, while not
blocking normal buffer activity longer than necessary. Nonetheless there
could be some impact on database performance if this view is read often.
Sample output
-------------
regression=# \d pg_buffercache;
View "public.pg_buffercache"
Column | Type | Modifiers
----------------+---------+-----------
bufferid | integer |
relfilenode | oid |
reltablespace | oid |
reldatabase | oid |
relblocknumber | numeric |
isdirty | boolean |
View definition:
SELECT p.bufferid, p.relfilenode, p.reltablespace, p.reldatabase,
p.relblocknumber, p.isdirty
FROM pg_buffercache_pages() p(bufferid integer, relfilenode oid,
reltablespace oid, reldatabase oid, relblocknumber numeric(10,0),
isdirty boolean);
regression=# SELECT c.relname, count(*) AS buffers
FROM pg_class c, pg_buffercache b
WHERE b.relfilenode = c.relfilenode
GROUP BY c.relname
ORDER BY 2 DESC LIMIT 10;
relname | buffers
---------------------------------+---------
tenk2 | 345
tenk1 | 141
pg_proc | 46
pg_class | 45
pg_attribute | 43
pg_class_relname_nsp_index | 30
pg_proc_proname_args_nsp_index | 28
pg_attribute_relid_attnam_index | 26
pg_depend | 22
pg_depend_reference_index | 20
(10 rows)
regression=#
Author
------
* Mark Kirkwood <markir@paradise.net.nz>
Help
----
* Design suggestions : Neil Conway <neilc@samurai.com>
* Debugging advice : Tom Lane <tgl@sss.pgh.pa.us>
Thanks guys!
contrib/pg_buffercache/pg_buffercache.sql.in
0 → 100644
View file @
de004e44
-- Adjust this setting to control where the objects get created.
SET search_path = public;
-- Register the function.
CREATE OR REPLACE FUNCTION pg_buffercache_pages()
RETURNS SETOF RECORD
AS 'MODULE_PATHNAME', 'pg_buffercache_pages'
LANGUAGE 'C';
-- Create a view for convenient access.
CREATE VIEW pg_buffercache AS
SELECT P.* FROM pg_buffercache_pages() AS P
(bufferid integer, relfilenode oid, reltablespace oid, reldatabase oid,
relblocknumber numeric(10), isdirty bool);
-- Don't want these to be available at public.
REVOKE ALL ON FUNCTION pg_buffercache_pages() FROM PUBLIC;
REVOKE ALL ON pg_buffercache FROM PUBLIC;
contrib/pg_buffercache/pg_buffercache_pages.c
0 → 100644
View file @
de004e44
/*-------------------------------------------------------------------------
*
* pg_buffercache_pages.c
* display some contents of the buffer cache
*
* $PostgreSQL: pgsql/contrib/pg_buffercache/pg_buffercache_pages.c,v 1.1 2005/03/12 15:36:24 neilc Exp $
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "funcapi.h"
#include "catalog/pg_type.h"
#include "storage/buf_internals.h"
#include "storage/bufmgr.h"
#include "utils/relcache.h"
#include "pg_buffercache_pages.h"
#define NUM_BUFFERCACHE_PAGES_ELEM 6
/*
* Record structure holding the to be exposed cache data.
*/
typedef
struct
{
uint32
bufferid
;
Oid
relfilenode
;
Oid
reltablespace
;
Oid
reldatabase
;
BlockNumber
blocknum
;
bool
isvalid
;
bool
isdirty
;
}
BufferCachePagesRec
;
/*
* Function context for data persisting over repeated calls.
*/
typedef
struct
{
AttInMetadata
*
attinmeta
;
BufferCachePagesRec
*
record
;
char
*
values
[
NUM_BUFFERCACHE_PAGES_ELEM
];
}
BufferCachePagesContext
;
/*
* Function returning data from the shared buffer cache - buffer number,
* relation node/tablespace/database/blocknum and dirty indicator.
*/
PG_FUNCTION_INFO_V1
(
pg_buffercache_pages
);
Datum
pg_buffercache_pages
(
PG_FUNCTION_ARGS
)
{
FuncCallContext
*
funcctx
;
Datum
result
;
MemoryContext
oldcontext
;
BufferCachePagesContext
*
fctx
;
/* User function context. */
TupleDesc
tupledesc
;
HeapTuple
tuple
;
if
(
SRF_IS_FIRSTCALL
())
{
RelFileNode
rnode
;
uint32
i
;
BufferDesc
*
bufHdr
;
funcctx
=
SRF_FIRSTCALL_INIT
();
/* Switch context when allocating stuff to be used in later calls */
oldcontext
=
MemoryContextSwitchTo
(
funcctx
->
multi_call_memory_ctx
);
/* Construct a tuple to return. */
tupledesc
=
CreateTemplateTupleDesc
(
NUM_BUFFERCACHE_PAGES_ELEM
,
false
);
TupleDescInitEntry
(
tupledesc
,
(
AttrNumber
)
1
,
"bufferid"
,
INT4OID
,
-
1
,
0
);
TupleDescInitEntry
(
tupledesc
,
(
AttrNumber
)
2
,
"relfilenode"
,
OIDOID
,
-
1
,
0
);
TupleDescInitEntry
(
tupledesc
,
(
AttrNumber
)
3
,
"reltablespace"
,
OIDOID
,
-
1
,
0
);
TupleDescInitEntry
(
tupledesc
,
(
AttrNumber
)
4
,
"reldatabase"
,
OIDOID
,
-
1
,
0
);
TupleDescInitEntry
(
tupledesc
,
(
AttrNumber
)
5
,
"relblockbumber"
,
NUMERICOID
,
-
1
,
0
);
TupleDescInitEntry
(
tupledesc
,
(
AttrNumber
)
6
,
"isdirty"
,
BOOLOID
,
-
1
,
0
);
/* Generate attribute metadata needed later to produce tuples */
funcctx
->
attinmeta
=
TupleDescGetAttInMetadata
(
tupledesc
);
/*
* Create a function context for cross-call persistence
* and initialize the buffer counters.
*/
fctx
=
(
BufferCachePagesContext
*
)
palloc
(
sizeof
(
BufferCachePagesContext
));
funcctx
->
max_calls
=
NBuffers
;
funcctx
->
user_fctx
=
fctx
;
/* Allocate NBuffers worth of BufferCachePagesRec records. */
fctx
->
record
=
(
BufferCachePagesRec
*
)
palloc
(
sizeof
(
BufferCachePagesRec
)
*
NBuffers
);
/* allocate the strings for tuple formation */
fctx
->
values
[
0
]
=
(
char
*
)
palloc
(
3
*
sizeof
(
uint32
)
+
1
);
fctx
->
values
[
1
]
=
(
char
*
)
palloc
(
3
*
sizeof
(
uint32
)
+
1
);
fctx
->
values
[
2
]
=
(
char
*
)
palloc
(
3
*
sizeof
(
uint32
)
+
1
);
fctx
->
values
[
3
]
=
(
char
*
)
palloc
(
3
*
sizeof
(
uint32
)
+
1
);
fctx
->
values
[
4
]
=
(
char
*
)
palloc
(
3
*
sizeof
(
uint32
)
+
1
);
fctx
->
values
[
5
]
=
(
char
*
)
palloc
(
2
);
/* Return to original context when allocating transient memory */
MemoryContextSwitchTo
(
oldcontext
);
/*
* Lock Buffer map and scan though all the buffers, saving the
* relevant fields in the fctx->record structure.
*/
LWLockAcquire
(
BufMappingLock
,
LW_SHARED
);
for
(
i
=
0
,
bufHdr
=
BufferDescriptors
;
i
<
NBuffers
;
i
++
,
bufHdr
++
)
{
/* Lock each buffer header before inspecting. */
LockBufHdr
(
bufHdr
);
rnode
=
bufHdr
->
tag
.
rnode
;
fctx
->
record
[
i
].
bufferid
=
BufferDescriptorGetBuffer
(
bufHdr
);
fctx
->
record
[
i
].
relfilenode
=
rnode
.
relNode
;
fctx
->
record
[
i
].
reltablespace
=
rnode
.
spcNode
;
fctx
->
record
[
i
].
reldatabase
=
rnode
.
dbNode
;
fctx
->
record
[
i
].
blocknum
=
bufHdr
->
tag
.
blockNum
;
if
(
bufHdr
->
flags
&
BM_DIRTY
)
{
fctx
->
record
[
i
].
isdirty
=
true
;
}
else
{
fctx
->
record
[
i
].
isdirty
=
false
;
}
/* Note if the buffer is valid, and has storage created */
if
(
(
bufHdr
->
flags
&
BM_VALID
)
&&
(
bufHdr
->
flags
&
BM_TAG_VALID
))
{
fctx
->
record
[
i
].
isvalid
=
true
;
}
else
{
fctx
->
record
[
i
].
isvalid
=
false
;
}
UnlockBufHdr
(
bufHdr
);
}
/* Release Buffer map. */
LWLockRelease
(
BufMappingLock
);
}
funcctx
=
SRF_PERCALL_SETUP
();
/* Get the saved state */
fctx
=
funcctx
->
user_fctx
;
if
(
funcctx
->
call_cntr
<
funcctx
->
max_calls
)
{
uint32
i
=
funcctx
->
call_cntr
;
char
*
values
[
NUM_BUFFERCACHE_PAGES_ELEM
];
int
j
;
/*
* Use a temporary values array, initially pointing to
* fctx->values, so it can be reassigned w/o losing the storage
* for subsequent calls.
*/
for
(
j
=
0
;
j
<
NUM_BUFFERCACHE_PAGES_ELEM
;
j
++
)
{
values
[
j
]
=
fctx
->
values
[
j
];
}
/*
* Set all fields except the bufferid to null if the buffer is
* unused or not valid.
*/
if
(
fctx
->
record
[
i
].
blocknum
==
InvalidBlockNumber
||
fctx
->
record
[
i
].
isvalid
==
false
)
{
sprintf
(
values
[
0
],
"%u"
,
fctx
->
record
[
i
].
bufferid
);
values
[
1
]
=
NULL
;
values
[
2
]
=
NULL
;
values
[
3
]
=
NULL
;
values
[
4
]
=
NULL
;
values
[
5
]
=
NULL
;
}
else
{
sprintf
(
values
[
0
],
"%u"
,
fctx
->
record
[
i
].
bufferid
);
sprintf
(
values
[
1
],
"%u"
,
fctx
->
record
[
i
].
relfilenode
);
sprintf
(
values
[
2
],
"%u"
,
fctx
->
record
[
i
].
reltablespace
);
sprintf
(
values
[
3
],
"%u"
,
fctx
->
record
[
i
].
reldatabase
);
sprintf
(
values
[
4
],
"%u"
,
fctx
->
record
[
i
].
blocknum
);
if
(
fctx
->
record
[
i
].
isdirty
)
{
strcpy
(
values
[
5
],
"t"
);
}
else
{
strcpy
(
values
[
5
],
"f"
);
}
}
/* Build and return the tuple. */
tuple
=
BuildTupleFromCStrings
(
funcctx
->
attinmeta
,
values
);
result
=
HeapTupleGetDatum
(
tuple
);
SRF_RETURN_NEXT
(
funcctx
,
result
);
}
else
SRF_RETURN_DONE
(
funcctx
);
}
contrib/pg_buffercache/pg_buffercache_pages.h
0 → 100644
View file @
de004e44
/*-------------------------------------------------------------------------
*
* pg_buffercache_pages.h
* Prototypes for pg_buffercache_pages
*
*
* $PostgreSQL: pgsql/contrib/pg_buffercache/pg_buffercache_pages.h,v 1.1 2005/03/12 15:36:24 neilc Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef PG_BUFFERCACHE_PAGES_H
#define PG_BUFFERCACHE_PAGES_H
extern
Datum
pg_buffercache_pages
(
PG_FUNCTION_ARGS
);
#endif
/* PG_BUFFERCACHE_PAGES_H */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment