Un-Windows-ify newlines.
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 2 Aug 2005 14:07:27 +0000 (14:07 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 2 Aug 2005 14:07:27 +0000 (14:07 +0000)
src/backend/utils/adt/dbsize.c

index 158d2cf402658a7dfe9dc53bce0106c1a0ad6a0d..57b72fe15cc3be3d23f79d666926c8f6eb4419ca 100644 (file)
-/*\r
- * dbsize.c\r
- * object size functions\r
- *\r
- * Copyright (c) 2002-2005, PostgreSQL Global Development Group\r
- *\r
- * IDENTIFICATION\r
- *       $PostgreSQL: pgsql/src/backend/utils/adt/dbsize.c,v 1.1 2005/07/29 14:46:57 momjian Exp $\r
- *\r
- */\r
-\r
-#include "postgres.h"\r
-\r
-#include <sys/types.h>\r
-#include <sys/stat.h>\r
-\r
-#include "access/heapam.h"\r
-#include "catalog/namespace.h"\r
-#include "catalog/pg_tablespace.h"\r
-#include "commands/dbcommands.h"\r
-#include "commands/tablespace.h"\r
-#include "miscadmin.h"\r
-#include "storage/fd.h"\r
-#include "utils/builtins.h"\r
-#include "utils/syscache.h"\r
-#include "utils/relcache.h"\r
-\r
-\r
-/* Return physical size of directory contents, or 0 if dir doesn't exist */\r
-static int64\r
-db_dir_size(const char *path)\r
-{\r
-       int64           dirsize = 0;\r
-    struct dirent *direntry;\r
-       DIR         *dirdesc;\r
-       char filename[MAXPGPATH];\r
-\r
-       dirdesc = AllocateDir(path);\r
-\r
-       if (!dirdesc)\r
-           return 0;\r
-\r
-       while ((direntry = readdir(dirdesc)) != NULL)\r
-       {\r
-           struct stat fst;\r
-\r
-           if (strcmp(direntry->d_name, ".") == 0 ||\r
-                       strcmp(direntry->d_name, "..") == 0)\r
-                   continue;\r
-\r
-               snprintf(filename, MAXPGPATH, "%s/%s", path, direntry->d_name);\r
-\r
-               if (stat(filename, &fst) < 0)\r
-                       ereport(ERROR,\r
-                                       (errcode_for_file_access(),\r
-                                        errmsg("could not stat \"%s\": %m", filename)));\r
-        \r
-        dirsize += fst.st_size;\r
-       }\r
-\r
-       FreeDir(dirdesc);\r
-       return dirsize;\r
-}\r
-\r
-/*\r
- * calculate size of database in all tablespaces\r
- */\r
-static int64\r
-calculate_database_size(Oid dbOid)\r
-{\r
-       int64           totalsize = 0;\r
-       DIR         *dirdesc;\r
-    struct dirent *direntry;\r
-       char pathname[MAXPGPATH];\r
-\r
-       /* Shared storage in pg_global is not counted */\r
-\r
-       /* Include pg_default storage */\r
-       snprintf(pathname, MAXPGPATH, "%s/base/%u", DataDir, dbOid);\r
-       totalsize += db_dir_size(pathname);\r
-\r
-       /* Scan the non-default tablespaces */\r
-       snprintf(pathname, MAXPGPATH, "%s/pg_tblspc", DataDir);\r
-       dirdesc = AllocateDir(pathname);\r
-       if (!dirdesc)\r
-           ereport(ERROR,\r
-                               (errcode_for_file_access(),\r
-                                errmsg("could not open tablespace directory \"%s\": %m",\r
-                                               pathname)));\r
-\r
-       while ((direntry = readdir(dirdesc)) != NULL)\r
-       {\r
-           if (strcmp(direntry->d_name, ".") == 0 ||\r
-                       strcmp(direntry->d_name, "..") == 0)\r
-                   continue;\r
-\r
-               snprintf(pathname, MAXPGPATH, "%s/pg_tblspc/%s/%u",\r
-                                DataDir, direntry->d_name, dbOid);\r
-               totalsize += db_dir_size(pathname);\r
-       }\r
-\r
-       FreeDir(dirdesc);\r
-\r
-       /* Complain if we found no trace of the DB at all */\r
-       if (!totalsize)\r
-           ereport(ERROR,\r
-                               (ERRCODE_UNDEFINED_DATABASE,\r
-                                errmsg("database with OID %u does not exist", dbOid)));\r
-\r
-       return totalsize;\r
-}\r
-\r
-Datum\r
-pg_database_size_oid(PG_FUNCTION_ARGS)\r
-{\r
-    Oid dbOid = PG_GETARG_OID(0);\r
-\r
-       PG_RETURN_INT64(calculate_database_size(dbOid));\r
-}\r
-\r
-Datum\r
-pg_database_size_name(PG_FUNCTION_ARGS)\r
-{\r
-       Name dbName = PG_GETARG_NAME(0);\r
-       Oid dbOid = get_database_oid(NameStr(*dbName));\r
-\r
-       if (!OidIsValid(dbOid))\r
-               ereport(ERROR,\r
-                               (errcode(ERRCODE_UNDEFINED_DATABASE),\r
-                                errmsg("database \"%s\" does not exist",\r
-                                               NameStr(*dbName))));\r
-\r
-       PG_RETURN_INT64(calculate_database_size(dbOid));\r
-}\r
-\r
-\r
-/*\r
- * calculate total size of tablespace\r
- */\r
-static int64\r
-calculate_tablespace_size(Oid tblspcOid)\r
-{\r
-       char tblspcPath[MAXPGPATH];\r
-       char pathname[MAXPGPATH];\r
-       int64           totalsize=0;\r
-       DIR         *dirdesc;\r
-    struct dirent *direntry;\r
-\r
-       if (tblspcOid == DEFAULTTABLESPACE_OID)\r
-           snprintf(tblspcPath, MAXPGPATH, "%s/base", DataDir);\r
-       else if (tblspcOid == GLOBALTABLESPACE_OID)\r
-           snprintf(tblspcPath, MAXPGPATH, "%s/global", DataDir);\r
-       else\r
-               snprintf(tblspcPath, MAXPGPATH, "%s/pg_tblspc/%u", DataDir, tblspcOid);\r
-\r
-       dirdesc = AllocateDir(tblspcPath);\r
-\r
-       if (!dirdesc)\r
-               ereport(ERROR,\r
-                               (errcode_for_file_access(),\r
-                                errmsg("could not open tablespace directory \"%s\": %m",\r
-                                               tblspcPath)));\r
-\r
-       while ((direntry = readdir(dirdesc)) != NULL)\r
-       {\r
-           struct stat fst;\r
-\r
-           if (strcmp(direntry->d_name, ".") == 0 ||\r
-                       strcmp(direntry->d_name, "..") == 0)\r
-                   continue;\r
-\r
-               snprintf(pathname, MAXPGPATH, "%s/%s", tblspcPath, direntry->d_name);\r
-\r
-               if (stat(pathname, &fst) < 0)\r
-                       ereport(ERROR,\r
-                                       (errcode_for_file_access(),\r
-                                        errmsg("could not stat \"%s\": %m", pathname)));\r
-\r
-               if (fst.st_mode & S_IFDIR)\r
-                   totalsize += db_dir_size(pathname);\r
-        \r
-        totalsize += fst.st_size;\r
-       }\r
-\r
-       FreeDir(dirdesc);\r
-    \r
-       return totalsize;\r
-}\r
-\r
-Datum\r
-pg_tablespace_size_oid(PG_FUNCTION_ARGS)\r
-{\r
-    Oid tblspcOid = PG_GETARG_OID(0);\r
-    \r
-       PG_RETURN_INT64(calculate_tablespace_size(tblspcOid));\r
-}\r
-\r
-Datum\r
-pg_tablespace_size_name(PG_FUNCTION_ARGS)\r
-{\r
-       Name tblspcName = PG_GETARG_NAME(0);\r
-       Oid tblspcOid = get_tablespace_oid(NameStr(*tblspcName));\r
-\r
-       if (!OidIsValid(tblspcOid))\r
-               ereport(ERROR,\r
-                               (errcode(ERRCODE_UNDEFINED_OBJECT),\r
-                                errmsg("tablespace \"%s\" does not exist",\r
-                                               NameStr(*tblspcName))));\r
-\r
-       PG_RETURN_INT64(calculate_tablespace_size(tblspcOid));\r
-}\r
-\r
-\r
-/*\r
- * calculate size of a relation\r
- */\r
-static int64\r
-calculate_relation_size(Oid tblspcOid, Oid relnodeOid)\r
-{\r
-       int64           totalsize=0;\r
-       unsigned int segcount=0;\r
-       char dirpath[MAXPGPATH];\r
-       char pathname[MAXPGPATH];\r
-\r
-       if (!tblspcOid)\r
-               tblspcOid = MyDatabaseTableSpace;\r
-\r
-       if (tblspcOid == DEFAULTTABLESPACE_OID)\r
-           snprintf(dirpath, MAXPGPATH, "%s/base/%u", DataDir, MyDatabaseId);\r
-       else if (tblspcOid == GLOBALTABLESPACE_OID)\r
-           snprintf(dirpath, MAXPGPATH, "%s/global", DataDir);\r
-       else\r
-           snprintf(dirpath, MAXPGPATH, "%s/pg_tblspc/%u/%u",\r
-                                DataDir, tblspcOid, MyDatabaseId);\r
-\r
-       for (segcount = 0 ;; segcount++)\r
-       {\r
-               struct stat fst;\r
-\r
-               if (segcount == 0)\r
-                   snprintf(pathname, MAXPGPATH, "%s/%u",\r
-                                        dirpath, relnodeOid);\r
-               else\r
-                   snprintf(pathname, MAXPGPATH, "%s/%u.%u",\r
-                                        dirpath, relnodeOid, segcount);\r
-\r
-               if (stat(pathname, &fst) < 0)\r
-               {\r
-                       if (errno == ENOENT)\r
-                               break;\r
-                       else\r
-                               ereport(ERROR,\r
-                                               (errcode_for_file_access(),\r
-                                                errmsg("could not stat \"%s\": %m", pathname)));\r
-               }\r
-               totalsize += fst.st_size;\r
-       }\r
-\r
-       return totalsize;\r
-}\r
-\r
-Datum\r
-pg_relation_size_oid(PG_FUNCTION_ARGS)\r
-{\r
-       Oid         relOid=PG_GETARG_OID(0);\r
-       HeapTuple   tuple;\r
-       Form_pg_class pg_class;\r
-       Oid                     relnodeOid;\r
-       Oid         tblspcOid;\r
-\r
-       tuple = SearchSysCache(RELOID,\r
-                                                  ObjectIdGetDatum(relOid),\r
-                                                  0, 0, 0);\r
-       if (!HeapTupleIsValid(tuple))\r
-           ereport(ERROR,\r
-                               (ERRCODE_UNDEFINED_TABLE,\r
-                                errmsg("relation with OID %u does not exist", relOid)));\r
-\r
-       pg_class = (Form_pg_class) GETSTRUCT(tuple);\r
-       relnodeOid = pg_class->relfilenode;\r
-       tblspcOid = pg_class->reltablespace;\r
-\r
-       ReleaseSysCache(tuple);\r
-\r
-       PG_RETURN_INT64(calculate_relation_size(tblspcOid, relnodeOid));\r
-}\r
-\r
-Datum\r
-pg_relation_size_name(PG_FUNCTION_ARGS)\r
-{\r
-       text       *relname = PG_GETARG_TEXT_P(0);\r
-       RangeVar   *relrv;\r
-       Relation        relation;\r
-       Oid                     relnodeOid;\r
-       Oid         tblspcOid;\r
-    \r
-       relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));    \r
-       relation = relation_openrv(relrv, AccessShareLock);\r
-    \r
-       tblspcOid  = relation->rd_rel->reltablespace;             \r
-       relnodeOid = relation->rd_rel->relfilenode;\r
-             \r
-       relation_close(relation, AccessShareLock);\r
-\r
-       PG_RETURN_INT64(calculate_relation_size(tblspcOid, relnodeOid));\r
-}\r
-\r
-\r
-/*\r
- *  Compute on-disk size of files for 'relation' according to the stat function, \r
- *  optionally including heap data, index data, and/or toast data.\r
- */\r
-static int64\r
-calculate_complete_relation_size(Oid tblspcOid, Oid relnodeOid)\r
-{\r
-    Relation        heapRelation;\r
-       Relation        idxRelation;\r
-       Relation        toastRelation;\r
-    Oid             idxOid;\r
-    Oid             idxTblspcOid;\r
-       Oid             toastOid;\r
-       Oid             toastTblspcOid;\r
-       bool            hasIndices;\r
-       int64           size = 0;\r
-       List            *indexoidlist;\r
-       ListCell        *idx;\r
-\r
-    heapRelation = relation_open(relnodeOid, AccessShareLock);\r
-       toastOid = heapRelation->rd_rel->reltoastrelid;\r
-       hasIndices = heapRelation->rd_rel->relhasindex;\r
-\r
-    /* Get the heap size */\r
-    size += calculate_relation_size(tblspcOid, relnodeOid);\r
-\r
-    /* Get Index size */\r
-       if ( hasIndices ) {\r
-               /* recursively include any dependent indexes ... */\r
-               indexoidlist = RelationGetIndexList(heapRelation);\r
-             \r
-               foreach(idx, indexoidlist) {\r
-            idxOid = lfirst_oid(idx);\r
-                       idxRelation = relation_open(idxOid, AccessShareLock);\r
-            idxTblspcOid = idxRelation->rd_rel->reltablespace;\r
-                       size += calculate_relation_size(idxTblspcOid, idxOid);\r
-                       relation_close(idxRelation, AccessShareLock);\r
-               }\r
-               list_free(indexoidlist);\r
-       }\r
-    \r
-    /* Close heapReleation now we no longer need it */\r
-    relation_close(heapRelation, AccessShareLock);\r
-\r
-    /* Get toast table size */\r
-       if ( toastOid != 0 ) {\r
-\r
-               /* recursively include any toast relations ... */\r
-               toastRelation = relation_open(toastOid, AccessShareLock);\r
-               toastTblspcOid = toastRelation->rd_rel->reltablespace;\r
-               size += calculate_relation_size(toastTblspcOid, toastOid);\r
-               relation_close(toastRelation, AccessShareLock);\r
-       }\r
-\r
-       return size;\r
-}\r
-\r
-/*\r
- *  Compute on-disk size of files for 'relation' including \r
- *  heap data, index data, and toasted data.\r
- */\r
-Datum\r
-pg_complete_relation_size_oid(PG_FUNCTION_ARGS)\r
-{\r
-       Oid             relOid=PG_GETARG_OID(0);\r
-       HeapTuple       tuple;\r
-       Form_pg_class   pg_class;\r
-       Oid             relnodeOid;\r
-       Oid             tblspcOid;\r
-\r
-       tuple = SearchSysCache(RELOID,\r
-                                  ObjectIdGetDatum(relOid),\r
-                                  0, 0, 0);\r
-       if (!HeapTupleIsValid(tuple))\r
-           ereport(ERROR,\r
-                               (ERRCODE_UNDEFINED_TABLE,\r
-                                errmsg("relation with OID %u does not exist", relOid)));\r
-\r
-       pg_class = (Form_pg_class) GETSTRUCT(tuple);\r
-       relnodeOid = pg_class->relfilenode;\r
-       tblspcOid = pg_class->reltablespace;\r
-\r
-       ReleaseSysCache(tuple);\r
-\r
-       PG_RETURN_INT64(calculate_complete_relation_size(tblspcOid, relnodeOid));\r
-}\r
-\r
-Datum\r
-pg_complete_relation_size_name(PG_FUNCTION_ARGS)\r
-{\r
-       text            *relname = PG_GETARG_TEXT_P(0);\r
-       RangeVar        *relrv;\r
-       Relation        relation;\r
-       Oid             relnodeOid;\r
-       Oid             tblspcOid;\r
-    \r
-       relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));    \r
-       relation = relation_openrv(relrv, AccessShareLock);\r
-    \r
-       tblspcOid  = relation->rd_rel->reltablespace;             \r
-       relnodeOid = relation->rd_rel->relfilenode;\r
-             \r
-       relation_close(relation, AccessShareLock);\r
-\r
-       PG_RETURN_INT64(calculate_complete_relation_size(tblspcOid, relnodeOid));\r
-}\r
-\r
-/*\r
- * formatting with size units\r
- */\r
-Datum\r
-pg_size_pretty(PG_FUNCTION_ARGS)\r
-{\r
-       int64 size=PG_GETARG_INT64(0);\r
-       char *result=palloc(50+VARHDRSZ);\r
-       int64 limit = 10*1024;\r
-       int64 mult=1;\r
-\r
-       if (size < limit*mult)\r
-           snprintf(VARDATA(result), 50, INT64_FORMAT" bytes",\r
-                                size);\r
-       else\r
-       {\r
-               mult *= 1024;\r
-               if (size < limit*mult)\r
-                    snprintf(VARDATA(result), 50, INT64_FORMAT " kB",\r
-                                         (size+mult/2) / mult);\r
-               else\r
-               {\r
-                       mult *= 1024;\r
-                       if (size < limit*mult)\r
-                           snprintf(VARDATA(result), 50, INT64_FORMAT " MB",\r
-                                                (size+mult/2) / mult);\r
-                       else\r
-                       {\r
-                               mult *= 1024;\r
-                               if (size < limit*mult)\r
-                                   snprintf(VARDATA(result), 50, INT64_FORMAT " GB",\r
-                                                        (size+mult/2) / mult);\r
-                               else\r
-                               {\r
-                                   mult *= 1024;\r
-                                   snprintf(VARDATA(result), 50, INT64_FORMAT " TB",\r
-                                                        (size+mult/2) / mult);\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-\r
-       VARATT_SIZEP(result) = strlen(VARDATA(result)) + VARHDRSZ;\r
-\r
-       PG_RETURN_TEXT_P(result);\r
-}\r
+/*
+ * dbsize.c
+ * object size functions
+ *
+ * Copyright (c) 2002-2005, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/dbsize.c,v 1.2 2005/08/02 14:07:27 tgl Exp $
+ *
+ */
+
+#include "postgres.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "access/heapam.h"
+#include "catalog/namespace.h"
+#include "catalog/pg_tablespace.h"
+#include "commands/dbcommands.h"
+#include "commands/tablespace.h"
+#include "miscadmin.h"
+#include "storage/fd.h"
+#include "utils/builtins.h"
+#include "utils/syscache.h"
+#include "utils/relcache.h"
+
+
+/* Return physical size of directory contents, or 0 if dir doesn't exist */
+static int64
+db_dir_size(const char *path)
+{
+       int64           dirsize = 0;
+    struct dirent *direntry;
+       DIR         *dirdesc;
+       char filename[MAXPGPATH];
+
+       dirdesc = AllocateDir(path);
+
+       if (!dirdesc)
+           return 0;
+
+       while ((direntry = readdir(dirdesc)) != NULL)
+       {
+           struct stat fst;
+
+           if (strcmp(direntry->d_name, ".") == 0 ||
+                       strcmp(direntry->d_name, "..") == 0)
+                   continue;
+
+               snprintf(filename, MAXPGPATH, "%s/%s", path, direntry->d_name);
+
+               if (stat(filename, &fst) < 0)
+                       ereport(ERROR,
+                                       (errcode_for_file_access(),
+                                        errmsg("could not stat \"%s\": %m", filename)));
+        
+        dirsize += fst.st_size;
+       }
+
+       FreeDir(dirdesc);
+       return dirsize;
+}
+
+/*
+ * calculate size of database in all tablespaces
+ */
+static int64
+calculate_database_size(Oid dbOid)
+{
+       int64           totalsize = 0;
+       DIR         *dirdesc;
+    struct dirent *direntry;
+       char pathname[MAXPGPATH];
+
+       /* Shared storage in pg_global is not counted */
+
+       /* Include pg_default storage */
+       snprintf(pathname, MAXPGPATH, "%s/base/%u", DataDir, dbOid);
+       totalsize += db_dir_size(pathname);
+
+       /* Scan the non-default tablespaces */
+       snprintf(pathname, MAXPGPATH, "%s/pg_tblspc", DataDir);
+       dirdesc = AllocateDir(pathname);
+       if (!dirdesc)
+           ereport(ERROR,
+                               (errcode_for_file_access(),
+                                errmsg("could not open tablespace directory \"%s\": %m",
+                                               pathname)));
+
+       while ((direntry = readdir(dirdesc)) != NULL)
+       {
+           if (strcmp(direntry->d_name, ".") == 0 ||
+                       strcmp(direntry->d_name, "..") == 0)
+                   continue;
+
+               snprintf(pathname, MAXPGPATH, "%s/pg_tblspc/%s/%u",
+                                DataDir, direntry->d_name, dbOid);
+               totalsize += db_dir_size(pathname);
+       }
+
+       FreeDir(dirdesc);
+
+       /* Complain if we found no trace of the DB at all */
+       if (!totalsize)
+           ereport(ERROR,
+                               (ERRCODE_UNDEFINED_DATABASE,
+                                errmsg("database with OID %u does not exist", dbOid)));
+
+       return totalsize;
+}
+
+Datum
+pg_database_size_oid(PG_FUNCTION_ARGS)
+{
+    Oid dbOid = PG_GETARG_OID(0);
+
+       PG_RETURN_INT64(calculate_database_size(dbOid));
+}
+
+Datum
+pg_database_size_name(PG_FUNCTION_ARGS)
+{
+       Name dbName = PG_GETARG_NAME(0);
+       Oid dbOid = get_database_oid(NameStr(*dbName));
+
+       if (!OidIsValid(dbOid))
+               ereport(ERROR,
+                               (errcode(ERRCODE_UNDEFINED_DATABASE),
+                                errmsg("database \"%s\" does not exist",
+                                               NameStr(*dbName))));
+
+       PG_RETURN_INT64(calculate_database_size(dbOid));
+}
+
+
+/*
+ * calculate total size of tablespace
+ */
+static int64
+calculate_tablespace_size(Oid tblspcOid)
+{
+       char tblspcPath[MAXPGPATH];
+       char pathname[MAXPGPATH];
+       int64           totalsize=0;
+       DIR         *dirdesc;
+    struct dirent *direntry;
+
+       if (tblspcOid == DEFAULTTABLESPACE_OID)
+           snprintf(tblspcPath, MAXPGPATH, "%s/base", DataDir);
+       else if (tblspcOid == GLOBALTABLESPACE_OID)
+           snprintf(tblspcPath, MAXPGPATH, "%s/global", DataDir);
+       else
+               snprintf(tblspcPath, MAXPGPATH, "%s/pg_tblspc/%u", DataDir, tblspcOid);
+
+       dirdesc = AllocateDir(tblspcPath);
+
+       if (!dirdesc)
+               ereport(ERROR,
+                               (errcode_for_file_access(),
+                                errmsg("could not open tablespace directory \"%s\": %m",
+                                               tblspcPath)));
+
+       while ((direntry = readdir(dirdesc)) != NULL)
+       {
+           struct stat fst;
+
+           if (strcmp(direntry->d_name, ".") == 0 ||
+                       strcmp(direntry->d_name, "..") == 0)
+                   continue;
+
+               snprintf(pathname, MAXPGPATH, "%s/%s", tblspcPath, direntry->d_name);
+
+               if (stat(pathname, &fst) < 0)
+                       ereport(ERROR,
+                                       (errcode_for_file_access(),
+                                        errmsg("could not stat \"%s\": %m", pathname)));
+
+               if (fst.st_mode & S_IFDIR)
+                   totalsize += db_dir_size(pathname);
+        
+        totalsize += fst.st_size;
+       }
+
+       FreeDir(dirdesc);
+    
+       return totalsize;
+}
+
+Datum
+pg_tablespace_size_oid(PG_FUNCTION_ARGS)
+{
+    Oid tblspcOid = PG_GETARG_OID(0);
+    
+       PG_RETURN_INT64(calculate_tablespace_size(tblspcOid));
+}
+
+Datum
+pg_tablespace_size_name(PG_FUNCTION_ARGS)
+{
+       Name tblspcName = PG_GETARG_NAME(0);
+       Oid tblspcOid = get_tablespace_oid(NameStr(*tblspcName));
+
+       if (!OidIsValid(tblspcOid))
+               ereport(ERROR,
+                               (errcode(ERRCODE_UNDEFINED_OBJECT),
+                                errmsg("tablespace \"%s\" does not exist",
+                                               NameStr(*tblspcName))));
+
+       PG_RETURN_INT64(calculate_tablespace_size(tblspcOid));
+}
+
+
+/*
+ * calculate size of a relation
+ */
+static int64
+calculate_relation_size(Oid tblspcOid, Oid relnodeOid)
+{
+       int64           totalsize=0;
+       unsigned int segcount=0;
+       char dirpath[MAXPGPATH];
+       char pathname[MAXPGPATH];
+
+       if (!tblspcOid)
+               tblspcOid = MyDatabaseTableSpace;
+
+       if (tblspcOid == DEFAULTTABLESPACE_OID)
+           snprintf(dirpath, MAXPGPATH, "%s/base/%u", DataDir, MyDatabaseId);
+       else if (tblspcOid == GLOBALTABLESPACE_OID)
+           snprintf(dirpath, MAXPGPATH, "%s/global", DataDir);
+       else
+           snprintf(dirpath, MAXPGPATH, "%s/pg_tblspc/%u/%u",
+                                DataDir, tblspcOid, MyDatabaseId);
+
+       for (segcount = 0 ;; segcount++)
+       {
+               struct stat fst;
+
+               if (segcount == 0)
+                   snprintf(pathname, MAXPGPATH, "%s/%u",
+                                        dirpath, relnodeOid);
+               else
+                   snprintf(pathname, MAXPGPATH, "%s/%u.%u",
+                                        dirpath, relnodeOid, segcount);
+
+               if (stat(pathname, &fst) < 0)
+               {
+                       if (errno == ENOENT)
+                               break;
+                       else
+                               ereport(ERROR,
+                                               (errcode_for_file_access(),
+                                                errmsg("could not stat \"%s\": %m", pathname)));
+               }
+               totalsize += fst.st_size;
+       }
+
+       return totalsize;
+}
+
+Datum
+pg_relation_size_oid(PG_FUNCTION_ARGS)
+{
+       Oid         relOid=PG_GETARG_OID(0);
+       HeapTuple   tuple;
+       Form_pg_class pg_class;
+       Oid                     relnodeOid;
+       Oid         tblspcOid;
+
+       tuple = SearchSysCache(RELOID,
+                                                  ObjectIdGetDatum(relOid),
+                                                  0, 0, 0);
+       if (!HeapTupleIsValid(tuple))
+           ereport(ERROR,
+                               (ERRCODE_UNDEFINED_TABLE,
+                                errmsg("relation with OID %u does not exist", relOid)));
+
+       pg_class = (Form_pg_class) GETSTRUCT(tuple);
+       relnodeOid = pg_class->relfilenode;
+       tblspcOid = pg_class->reltablespace;
+
+       ReleaseSysCache(tuple);
+
+       PG_RETURN_INT64(calculate_relation_size(tblspcOid, relnodeOid));
+}
+
+Datum
+pg_relation_size_name(PG_FUNCTION_ARGS)
+{
+       text       *relname = PG_GETARG_TEXT_P(0);
+       RangeVar   *relrv;
+       Relation        relation;
+       Oid                     relnodeOid;
+       Oid         tblspcOid;
+    
+       relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));    
+       relation = relation_openrv(relrv, AccessShareLock);
+    
+       tblspcOid  = relation->rd_rel->reltablespace;             
+       relnodeOid = relation->rd_rel->relfilenode;
+             
+       relation_close(relation, AccessShareLock);
+
+       PG_RETURN_INT64(calculate_relation_size(tblspcOid, relnodeOid));
+}
+
+
+/*
+ *  Compute on-disk size of files for 'relation' according to the stat function, 
+ *  optionally including heap data, index data, and/or toast data.
+ */
+static int64
+calculate_complete_relation_size(Oid tblspcOid, Oid relnodeOid)
+{
+    Relation        heapRelation;
+       Relation        idxRelation;
+       Relation        toastRelation;
+    Oid             idxOid;
+    Oid             idxTblspcOid;
+       Oid             toastOid;
+       Oid             toastTblspcOid;
+       bool            hasIndices;
+       int64           size = 0;
+       List            *indexoidlist;
+       ListCell        *idx;
+
+    heapRelation = relation_open(relnodeOid, AccessShareLock);
+       toastOid = heapRelation->rd_rel->reltoastrelid;
+       hasIndices = heapRelation->rd_rel->relhasindex;
+
+    /* Get the heap size */
+    size += calculate_relation_size(tblspcOid, relnodeOid);
+
+    /* Get Index size */
+       if ( hasIndices ) {
+               /* recursively include any dependent indexes ... */
+               indexoidlist = RelationGetIndexList(heapRelation);
+             
+               foreach(idx, indexoidlist) {
+            idxOid = lfirst_oid(idx);
+                       idxRelation = relation_open(idxOid, AccessShareLock);
+            idxTblspcOid = idxRelation->rd_rel->reltablespace;
+                       size += calculate_relation_size(idxTblspcOid, idxOid);
+                       relation_close(idxRelation, AccessShareLock);
+               }
+               list_free(indexoidlist);
+       }
+    
+    /* Close heapReleation now we no longer need it */
+    relation_close(heapRelation, AccessShareLock);
+
+    /* Get toast table size */
+       if ( toastOid != 0 ) {
+
+               /* recursively include any toast relations ... */
+               toastRelation = relation_open(toastOid, AccessShareLock);
+               toastTblspcOid = toastRelation->rd_rel->reltablespace;
+               size += calculate_relation_size(toastTblspcOid, toastOid);
+               relation_close(toastRelation, AccessShareLock);
+       }
+
+       return size;
+}
+
+/*
+ *  Compute on-disk size of files for 'relation' including 
+ *  heap data, index data, and toasted data.
+ */
+Datum
+pg_complete_relation_size_oid(PG_FUNCTION_ARGS)
+{
+       Oid             relOid=PG_GETARG_OID(0);
+       HeapTuple       tuple;
+       Form_pg_class   pg_class;
+       Oid             relnodeOid;
+       Oid             tblspcOid;
+
+       tuple = SearchSysCache(RELOID,
+                                  ObjectIdGetDatum(relOid),
+                                  0, 0, 0);
+       if (!HeapTupleIsValid(tuple))
+           ereport(ERROR,
+                               (ERRCODE_UNDEFINED_TABLE,
+                                errmsg("relation with OID %u does not exist", relOid)));
+
+       pg_class = (Form_pg_class) GETSTRUCT(tuple);
+       relnodeOid = pg_class->relfilenode;
+       tblspcOid = pg_class->reltablespace;
+
+       ReleaseSysCache(tuple);
+
+       PG_RETURN_INT64(calculate_complete_relation_size(tblspcOid, relnodeOid));
+}
+
+Datum
+pg_complete_relation_size_name(PG_FUNCTION_ARGS)
+{
+       text            *relname = PG_GETARG_TEXT_P(0);
+       RangeVar        *relrv;
+       Relation        relation;
+       Oid             relnodeOid;
+       Oid             tblspcOid;
+    
+       relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));    
+       relation = relation_openrv(relrv, AccessShareLock);
+    
+       tblspcOid  = relation->rd_rel->reltablespace;             
+       relnodeOid = relation->rd_rel->relfilenode;
+             
+       relation_close(relation, AccessShareLock);
+
+       PG_RETURN_INT64(calculate_complete_relation_size(tblspcOid, relnodeOid));
+}
+
+/*
+ * formatting with size units
+ */
+Datum
+pg_size_pretty(PG_FUNCTION_ARGS)
+{
+       int64 size=PG_GETARG_INT64(0);
+       char *result=palloc(50+VARHDRSZ);
+       int64 limit = 10*1024;
+       int64 mult=1;
+
+       if (size < limit*mult)
+           snprintf(VARDATA(result), 50, INT64_FORMAT" bytes",
+                                size);
+       else
+       {
+               mult *= 1024;
+               if (size < limit*mult)
+                    snprintf(VARDATA(result), 50, INT64_FORMAT " kB",
+                                         (size+mult/2) / mult);
+               else
+               {
+                       mult *= 1024;
+                       if (size < limit*mult)
+                           snprintf(VARDATA(result), 50, INT64_FORMAT " MB",
+                                                (size+mult/2) / mult);
+                       else
+                       {
+                               mult *= 1024;
+                               if (size < limit*mult)
+                                   snprintf(VARDATA(result), 50, INT64_FORMAT " GB",
+                                                        (size+mult/2) / mult);
+                               else
+                               {
+                                   mult *= 1024;
+                                   snprintf(VARDATA(result), 50, INT64_FORMAT " TB",
+                                                        (size+mult/2) / mult);
+                               }
+                       }
+               }
+       }
+
+       VARATT_SIZEP(result) = strlen(VARDATA(result)) + VARHDRSZ;
+
+       PG_RETURN_TEXT_P(result);
+}