66
77#include "access/heapam.h"
88#include "catalog/catalog.h"
9+ #include "catalog/catname.h"
910#include "catalog/namespace.h"
11+ #include "catalog/pg_tablespace.h"
1012#include "commands/dbcommands.h"
1113#include "fmgr.h"
1214#include "storage/fd.h"
1315#include "utils/builtins.h"
1416
1517
18+ static int64
19+ get_tablespace_size (Oid dbid ,Oid spcid ,bool baddirOK );
20+
1621static char *
1722psnprintf (size_t len ,const char * fmt ,...)
1823{
@@ -44,25 +49,68 @@ database_size(PG_FUNCTION_ARGS)
4449Name dbname = PG_GETARG_NAME (0 );
4550
4651Oid dbid ;
47- char * dbpath ;
48- DIR * dirdesc ;
49- struct dirent * direntry ;
5052int64 totalsize ;
53+ #ifdef SYMLINK
54+ Relation dbrel ;
55+ HeapScanDesc scan ;
56+ HeapTuple tuple ;
57+ #endif
5158
5259dbid = get_database_oid (NameStr (* dbname ));
5360if (!OidIsValid (dbid ))
5461ereport (ERROR ,
5562(errcode (ERRCODE_UNDEFINED_DATABASE ),
5663errmsg ("database \"%s\" does not exist" ,NameStr (* dbname ))));
5764
58- dbpath = GetDatabasePath (dbid );
65+ #ifdef SYMLINK
66+
67+ dbrel = heap_openr (TableSpaceRelationName ,AccessShareLock );
68+ scan = heap_beginscan (dbrel ,SnapshotNow ,0 , (ScanKey )NULL );
69+
70+ totalsize = 0 ;
71+
72+ while ((tuple = heap_getnext (scan ,ForwardScanDirection )))
73+ {
74+ Oid spcid = HeapTupleGetOid (tuple );
75+ if (spcid != GLOBALTABLESPACE_OID )
76+ totalsize += get_tablespace_size (dbid ,spcid , true);
77+ }
78+ heap_endscan (scan );
79+ heap_close (dbrel ,AccessShareLock );
80+ #else
81+ /* Same as always */
82+ totalsize = get_tablespace_size (dbid ,DEFAULTTABLESPACE_OID , false);
83+ #endif
84+
85+ /*
86+ * We need to keep in mind that we may not be called from the database
87+ * whose size we're reporting so, we need to look in every tablespace
88+ * to see if our database has data in there
89+ */
90+
91+ PG_RETURN_INT64 (totalsize );
92+ }
93+
94+ static int64
95+ get_tablespace_size (Oid dbid ,Oid spcid ,bool baddirOK )
96+ {
97+ char * dbpath ;
98+ DIR * dirdesc ;
99+ struct dirent * direntry ;
100+ int64 totalsize ;
101+
102+ dbpath = GetDatabasePath (dbid ,spcid );
59103
60104dirdesc = AllocateDir (dbpath );
61105if (!dirdesc )
62- ereport (ERROR ,
106+ {
107+ if (baddirOK )
108+ return 0 ;
109+ else
110+ ereport (ERROR ,
63111(errcode_for_file_access (),
64112errmsg ("could not open directory \"%s\": %m" ,dbpath )));
65-
113+ }
66114totalsize = 0 ;
67115for (;;)
68116{
@@ -87,18 +135,14 @@ database_size(PG_FUNCTION_ARGS)
87135ereport (ERROR ,
88136(errcode_for_file_access (),
89137errmsg ("could not stat \"%s\": %m" ,fullname )));
90-
91138totalsize += statbuf .st_size ;
92139pfree (fullname );
93140}
94141
95142FreeDir (dirdesc );
96-
97- PG_RETURN_INT64 (totalsize );
143+ return (totalsize );
98144}
99145
100-
101-
102146/*
103147 * SQL function: relation_size(text) returns bigint
104148 */