Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit ad0787b

Browse files
committed
I've written on like that a while ago:
http://webmail.postgresql.org/~petere/dbsize.html The tarball can be rolled into contrib -- now that I think of it I don't know why I never did that. Never imagined this would have anything to do with that TODO item, though. I figured oid2name accomplished that. Peter Eisentraut peter_e@gmx.net
1 parent 40bda4c commit ad0787b

File tree

6 files changed

+203
-2
lines changed

6 files changed

+203
-2
lines changed

contrib/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# $Header: /cvsroot/pgsql/contrib/Makefile,v 1.30 2001/10/12 23:19:09 tgl Exp $
1+
# $Header: /cvsroot/pgsql/contrib/Makefile,v 1.31 2002/02/22 23:05:34 momjian Exp $
22

33
subdir = contrib
44
top_builddir = ..
@@ -11,6 +11,7 @@ WANTED_DIRS = \
1111
cube \
1212
dbase \
1313
dblink \
14+
dbsize \
1415
earthdistance \
1516
findoidjoins \
1617
fulltextindex \

contrib/README

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,11 @@ dbase -
4848

4949
dblink -
5050
Allows remote query execution
51-
by Joe Conway, joe.conway@mail.com
51+
by Joe Conway <joe.conway@mail.com>
52+
53+
dbsize -
54+
Reports database and table disk space
55+
by Peter Eisentraut <peter_e@gmx.net>
5256

5357
earthdistance -
5458
Operator for computing earth distance for two points

contrib/dbsize/Makefile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
subdir = contrib/dbsize
2+
top_builddir = ../..
3+
include $(top_builddir)/src/Makefile.global
4+
5+
MODULES = dbsize
6+
DATA_built = dbsize.sql
7+
DOCS = README.dbsize
8+
9+
include $(top_srcdir)/contrib/contrib-global.mk

contrib/dbsize/README.dbsize

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
This module contains two functions that report the size of a given
2+
database or relation. E.g.,
3+
4+
SELECT database_size('template1');
5+
SELECT relation_size('pg_class');
6+
7+
These functions report the actual file system space. Thus, users can
8+
avoid digging through the details of the database directories.
9+
10+
Copy this directory to contrib/dbsize in your PostgreSQL source tree.
11+
Then just run make; make install.

contrib/dbsize/dbsize.c

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
#include "postgres.h"
2+
#include "fmgr.h"
3+
4+
#include "access/heapam.h"
5+
#include "catalog/catalog.h"
6+
#include "catalog/catname.h"
7+
#include "catalog/pg_database.h"
8+
#include "utils/fmgroids.h"
9+
10+
#include <stdlib.h>
11+
#include <sys/types.h>
12+
#include <dirent.h>
13+
#include <sys/stat.h>
14+
#include <unistd.h>
15+
#include <errno.h>
16+
17+
18+
static char *
19+
psnprintf(size_t len, const char *fmt,...)
20+
{
21+
va_list ap;
22+
char *buf;
23+
24+
buf = palloc(len);
25+
26+
va_start(ap, fmt);
27+
vsnprintf(buf, len, fmt, ap);
28+
va_end(ap);
29+
30+
return buf;
31+
}
32+
33+
34+
35+
/*
36+
* SQL function: database_size(name) returns bigint
37+
*/
38+
39+
PG_FUNCTION_INFO_V1(database_size);
40+
41+
Datum
42+
database_size(PG_FUNCTION_ARGS)
43+
{
44+
Name dbname = PG_GETARG_NAME(0);
45+
46+
HeapTuple tuple;
47+
Relation relation;
48+
ScanKeyData scanKey;
49+
HeapScanDesc scan;
50+
Oid dbid;
51+
char *dbpath;
52+
DIR *dirdesc;
53+
struct dirent *direntry;
54+
int64 totalsize;
55+
56+
relation = heap_openr(DatabaseRelationName, AccessShareLock);
57+
ScanKeyEntryInitialize(&scanKey, 0, Anum_pg_database_datname,
58+
F_NAMEEQ, NameGetDatum(dbname));
59+
scan = heap_beginscan(relation, 0, SnapshotNow, 1, &scanKey);
60+
tuple = heap_getnext(scan, 0);
61+
62+
if (!HeapTupleIsValid(tuple))
63+
elog(ERROR, "database %s does not exist", NameStr(*dbname));
64+
65+
dbid = tuple->t_data->t_oid;
66+
if (dbid == InvalidOid)
67+
elog(ERROR, "invalid database id");
68+
69+
heap_endscan(scan);
70+
heap_close(relation, NoLock);
71+
72+
dbpath = GetDatabasePath(dbid);
73+
74+
dirdesc = opendir(dbpath);
75+
if (!dirdesc)
76+
elog(ERROR, "could not open directory %s: %s", dbpath, strerror(errno));
77+
78+
totalsize = 0;
79+
for (;;)
80+
{
81+
char *fullname;
82+
struct stat statbuf;
83+
84+
errno = 0;
85+
direntry = readdir(dirdesc);
86+
if (!direntry)
87+
{
88+
if (errno)
89+
elog(ERROR, "error reading directory: %s", strerror(errno));
90+
else
91+
break;
92+
}
93+
94+
fullname = psnprintf(strlen(dbpath) + 1 + strlen(direntry->d_name) + 1,
95+
"%s/%s", dbpath, direntry->d_name);
96+
if (stat(fullname, &statbuf) == -1)
97+
elog(ERROR, "could not stat %s: %s", fullname, strerror(errno));
98+
totalsize += statbuf.st_size;
99+
pfree(fullname);
100+
}
101+
102+
closedir(dirdesc);
103+
104+
PG_RETURN_INT64(totalsize);
105+
}
106+
107+
108+
109+
/*
110+
* SQL function: relation_size(name) returns bigint
111+
*/
112+
113+
PG_FUNCTION_INFO_V1(relation_size);
114+
115+
Datum
116+
relation_size(PG_FUNCTION_ARGS)
117+
{
118+
Name relname = PG_GETARG_NAME(0);
119+
120+
HeapTuple tuple;
121+
Relation relation;
122+
ScanKeyData scanKey;
123+
HeapScanDesc scan;
124+
Oid relnode;
125+
int64 totalsize;
126+
unsigned int segcount;
127+
128+
relation = heap_openr(RelationRelationName, AccessShareLock);
129+
ScanKeyEntryInitialize(&scanKey, 0, Anum_pg_class_relname,
130+
F_NAMEEQ, NameGetDatum(relname));
131+
scan = heap_beginscan(relation, 0, SnapshotNow, 1, &scanKey);
132+
tuple = heap_getnext(scan, 0);
133+
134+
if (!HeapTupleIsValid(tuple))
135+
elog(ERROR, "relation %s does not exist", NameStr(*relname));
136+
137+
relnode = ((Form_pg_class) GETSTRUCT(tuple))->relfilenode;
138+
if (relnode == InvalidOid)
139+
elog(ERROR, "invalid relation node id");
140+
141+
heap_endscan(scan);
142+
heap_close(relation, NoLock);
143+
144+
totalsize = 0;
145+
segcount = 0;
146+
for (;;)
147+
{
148+
char *fullname;
149+
struct stat statbuf;
150+
151+
if (segcount == 0)
152+
fullname = psnprintf(25, "%u", (unsigned) relnode);
153+
else
154+
fullname = psnprintf(50, "%u.%u", (unsigned) relnode, segcount);
155+
156+
if (stat(fullname, &statbuf) == -1)
157+
{
158+
if (errno == ENOENT)
159+
break;
160+
else
161+
elog(ERROR, "could not stat %s: %s", fullname, strerror(errno));
162+
}
163+
totalsize += statbuf.st_size;
164+
pfree(fullname);
165+
segcount++;
166+
}
167+
168+
PG_RETURN_INT64(totalsize);
169+
}

contrib/dbsize/dbsize.sql.in

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CREATE FUNCTION database_size (name) RETURNS bigint
2+
AS '@MODULE_FILENAME@', 'database_size'
3+
LANGUAGE C WITH (isstrict);
4+
5+
CREATE FUNCTION relation_size (name) RETURNS bigint
6+
AS '@MODULE_FILENAME@', 'relation_size'
7+
LANGUAGE C WITH (isstrict);

0 commit comments

Comments
 (0)