2005-08-02 16:07:27 +02:00
|
|
|
/*
|
|
|
|
* dbsize.c
|
2005-08-02 17:17:24 +02:00
|
|
|
* object size functions
|
2005-08-02 16:07:27 +02:00
|
|
|
*
|
2008-01-01 20:46:01 +01:00
|
|
|
* Copyright (c) 2002-2008, PostgreSQL Global Development Group
|
2005-08-02 16:07:27 +02:00
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2008-10-06 16:13:17 +02:00
|
|
|
* $PostgreSQL: pgsql/src/backend/utils/adt/dbsize.c,v 1.22 2008/10/06 14:13:17 heikki Exp $
|
2005-08-02 16:07:27 +02:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "postgres.h"
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
|
|
|
#include "access/heapam.h"
|
2006-11-06 04:06:41 +01:00
|
|
|
#include "catalog/catalog.h"
|
2005-08-02 16:07:27 +02:00
|
|
|
#include "catalog/namespace.h"
|
|
|
|
#include "catalog/pg_tablespace.h"
|
|
|
|
#include "commands/dbcommands.h"
|
|
|
|
#include "commands/tablespace.h"
|
|
|
|
#include "miscadmin.h"
|
|
|
|
#include "storage/fd.h"
|
2007-08-27 03:19:14 +02:00
|
|
|
#include "utils/acl.h"
|
2005-08-02 16:07:27 +02:00
|
|
|
#include "utils/builtins.h"
|
2008-06-19 02:46:06 +02:00
|
|
|
#include "utils/rel.h"
|
2005-08-02 16:07:27 +02:00
|
|
|
#include "utils/syscache.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;
|
2005-10-15 04:49:52 +02:00
|
|
|
struct dirent *direntry;
|
|
|
|
DIR *dirdesc;
|
|
|
|
char filename[MAXPGPATH];
|
2005-08-02 16:07:27 +02:00
|
|
|
|
|
|
|
dirdesc = AllocateDir(path);
|
|
|
|
|
|
|
|
if (!dirdesc)
|
2005-10-15 04:49:52 +02:00
|
|
|
return 0;
|
2005-08-02 16:07:27 +02:00
|
|
|
|
2005-08-02 17:17:24 +02:00
|
|
|
while ((direntry = ReadDir(dirdesc, path)) != NULL)
|
2005-08-02 16:07:27 +02:00
|
|
|
{
|
2005-10-15 04:49:52 +02:00
|
|
|
struct stat fst;
|
2005-08-02 16:07:27 +02:00
|
|
|
|
2005-10-15 04:49:52 +02:00
|
|
|
if (strcmp(direntry->d_name, ".") == 0 ||
|
2005-08-02 16:07:27 +02:00
|
|
|
strcmp(direntry->d_name, "..") == 0)
|
2005-10-15 04:49:52 +02:00
|
|
|
continue;
|
2005-08-02 16:07:27 +02:00
|
|
|
|
|
|
|
snprintf(filename, MAXPGPATH, "%s/%s", path, direntry->d_name);
|
|
|
|
|
|
|
|
if (stat(filename, &fst) < 0)
|
2007-03-11 06:22:00 +01:00
|
|
|
{
|
|
|
|
if (errno == ENOENT)
|
|
|
|
continue;
|
|
|
|
else
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode_for_file_access(),
|
|
|
|
errmsg("could not stat file \"%s\": %m", filename)));
|
|
|
|
}
|
2005-10-15 04:49:52 +02:00
|
|
|
dirsize += fst.st_size;
|
2005-08-02 16:07:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
FreeDir(dirdesc);
|
|
|
|
return dirsize;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* calculate size of database in all tablespaces
|
|
|
|
*/
|
|
|
|
static int64
|
|
|
|
calculate_database_size(Oid dbOid)
|
|
|
|
{
|
2005-09-16 07:35:41 +02:00
|
|
|
int64 totalsize;
|
2005-10-15 04:49:52 +02:00
|
|
|
DIR *dirdesc;
|
|
|
|
struct dirent *direntry;
|
|
|
|
char dirpath[MAXPGPATH];
|
|
|
|
char pathname[MAXPGPATH];
|
2007-08-29 19:24:29 +02:00
|
|
|
AclResult aclresult;
|
|
|
|
|
|
|
|
/* User must have connect privilege for target database */
|
|
|
|
aclresult = pg_database_aclcheck(dbOid, GetUserId(), ACL_CONNECT);
|
|
|
|
if (aclresult != ACLCHECK_OK)
|
|
|
|
aclcheck_error(aclresult, ACL_KIND_DATABASE,
|
|
|
|
get_database_name(dbOid));
|
2005-08-02 16:07:27 +02:00
|
|
|
|
|
|
|
/* Shared storage in pg_global is not counted */
|
|
|
|
|
|
|
|
/* Include pg_default storage */
|
2006-11-06 04:06:41 +01:00
|
|
|
snprintf(pathname, MAXPGPATH, "base/%u", dbOid);
|
2005-09-16 07:35:41 +02:00
|
|
|
totalsize = db_dir_size(pathname);
|
2005-08-02 16:07:27 +02:00
|
|
|
|
|
|
|
/* Scan the non-default tablespaces */
|
2006-11-06 04:06:41 +01:00
|
|
|
snprintf(dirpath, MAXPGPATH, "pg_tblspc");
|
2005-08-02 17:17:24 +02:00
|
|
|
dirdesc = AllocateDir(dirpath);
|
2005-08-02 16:07:27 +02:00
|
|
|
if (!dirdesc)
|
2005-10-15 04:49:52 +02:00
|
|
|
ereport(ERROR,
|
2005-08-02 16:07:27 +02:00
|
|
|
(errcode_for_file_access(),
|
|
|
|
errmsg("could not open tablespace directory \"%s\": %m",
|
2005-08-02 17:17:24 +02:00
|
|
|
dirpath)));
|
2005-08-02 16:07:27 +02:00
|
|
|
|
2005-08-02 17:17:24 +02:00
|
|
|
while ((direntry = ReadDir(dirdesc, dirpath)) != NULL)
|
2005-08-02 16:07:27 +02:00
|
|
|
{
|
2005-10-15 04:49:52 +02:00
|
|
|
if (strcmp(direntry->d_name, ".") == 0 ||
|
2005-08-02 16:07:27 +02:00
|
|
|
strcmp(direntry->d_name, "..") == 0)
|
2005-10-15 04:49:52 +02:00
|
|
|
continue;
|
2005-08-02 16:07:27 +02:00
|
|
|
|
2006-11-06 04:06:41 +01:00
|
|
|
snprintf(pathname, MAXPGPATH, "pg_tblspc/%s/%u",
|
|
|
|
direntry->d_name, dbOid);
|
2005-08-02 16:07:27 +02:00
|
|
|
totalsize += db_dir_size(pathname);
|
|
|
|
}
|
|
|
|
|
|
|
|
FreeDir(dirdesc);
|
|
|
|
|
|
|
|
/* Complain if we found no trace of the DB at all */
|
|
|
|
if (!totalsize)
|
2005-10-15 04:49:52 +02:00
|
|
|
ereport(ERROR,
|
2005-08-02 16:07:27 +02:00
|
|
|
(ERRCODE_UNDEFINED_DATABASE,
|
|
|
|
errmsg("database with OID %u does not exist", dbOid)));
|
|
|
|
|
|
|
|
return totalsize;
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
pg_database_size_oid(PG_FUNCTION_ARGS)
|
|
|
|
{
|
2005-10-15 04:49:52 +02:00
|
|
|
Oid dbOid = PG_GETARG_OID(0);
|
2005-08-02 16:07:27 +02:00
|
|
|
|
|
|
|
PG_RETURN_INT64(calculate_database_size(dbOid));
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
pg_database_size_name(PG_FUNCTION_ARGS)
|
|
|
|
{
|
2005-10-15 04:49:52 +02:00
|
|
|
Name dbName = PG_GETARG_NAME(0);
|
|
|
|
Oid dbOid = get_database_oid(NameStr(*dbName));
|
2005-08-02 16:07:27 +02:00
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2005-10-15 04:49:52 +02:00
|
|
|
char tblspcPath[MAXPGPATH];
|
|
|
|
char pathname[MAXPGPATH];
|
|
|
|
int64 totalsize = 0;
|
|
|
|
DIR *dirdesc;
|
|
|
|
struct dirent *direntry;
|
2007-08-29 19:24:29 +02:00
|
|
|
AclResult aclresult;
|
|
|
|
|
|
|
|
/*
|
2007-11-15 22:14:46 +01:00
|
|
|
* User must have CREATE privilege for target tablespace, either
|
|
|
|
* explicitly granted or implicitly because it is default for current
|
|
|
|
* database.
|
2007-08-29 19:24:29 +02:00
|
|
|
*/
|
|
|
|
if (tblspcOid != MyDatabaseTableSpace)
|
|
|
|
{
|
|
|
|
aclresult = pg_tablespace_aclcheck(tblspcOid, GetUserId(), ACL_CREATE);
|
|
|
|
if (aclresult != ACLCHECK_OK)
|
|
|
|
aclcheck_error(aclresult, ACL_KIND_TABLESPACE,
|
|
|
|
get_tablespace_name(tblspcOid));
|
|
|
|
}
|
2005-08-02 16:07:27 +02:00
|
|
|
|
|
|
|
if (tblspcOid == DEFAULTTABLESPACE_OID)
|
2006-11-06 04:06:41 +01:00
|
|
|
snprintf(tblspcPath, MAXPGPATH, "base");
|
2005-08-02 16:07:27 +02:00
|
|
|
else if (tblspcOid == GLOBALTABLESPACE_OID)
|
2006-11-06 04:06:41 +01:00
|
|
|
snprintf(tblspcPath, MAXPGPATH, "global");
|
2005-08-02 16:07:27 +02:00
|
|
|
else
|
2006-11-06 04:06:41 +01:00
|
|
|
snprintf(tblspcPath, MAXPGPATH, "pg_tblspc/%u", tblspcOid);
|
2005-08-02 16:07:27 +02:00
|
|
|
|
|
|
|
dirdesc = AllocateDir(tblspcPath);
|
|
|
|
|
|
|
|
if (!dirdesc)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode_for_file_access(),
|
|
|
|
errmsg("could not open tablespace directory \"%s\": %m",
|
|
|
|
tblspcPath)));
|
|
|
|
|
2005-08-02 17:17:24 +02:00
|
|
|
while ((direntry = ReadDir(dirdesc, tblspcPath)) != NULL)
|
2005-08-02 16:07:27 +02:00
|
|
|
{
|
2005-10-15 04:49:52 +02:00
|
|
|
struct stat fst;
|
2005-08-02 16:07:27 +02:00
|
|
|
|
2005-10-15 04:49:52 +02:00
|
|
|
if (strcmp(direntry->d_name, ".") == 0 ||
|
2005-08-02 16:07:27 +02:00
|
|
|
strcmp(direntry->d_name, "..") == 0)
|
2005-10-15 04:49:52 +02:00
|
|
|
continue;
|
2005-08-02 16:07:27 +02:00
|
|
|
|
|
|
|
snprintf(pathname, MAXPGPATH, "%s/%s", tblspcPath, direntry->d_name);
|
|
|
|
|
|
|
|
if (stat(pathname, &fst) < 0)
|
2007-03-11 06:22:00 +01:00
|
|
|
{
|
|
|
|
if (errno == ENOENT)
|
|
|
|
continue;
|
|
|
|
else
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode_for_file_access(),
|
|
|
|
errmsg("could not stat file \"%s\": %m", pathname)));
|
|
|
|
}
|
2005-08-02 16:07:27 +02:00
|
|
|
|
Fix a number of places that were making file-type tests infelicitously.
The places that did, eg,
(statbuf.st_mode & S_IFMT) == S_IFDIR
were correct, but there is no good reason not to use S_ISDIR() instead,
especially when that's what the other 90% of our code does. The places
that did, eg,
(statbuf.st_mode & S_IFDIR)
were flat out *wrong* and would fail in various platform-specific ways,
eg a symlink could be mistaken for a regular file on most Unixen.
The actual impact of this is probably small, since the problem cases
seem to always involve symlinks or sockets, which are unlikely to be
found in the directories that PG code might be scanning. But it's
clearly trouble waiting to happen, so patch all the way back anyway.
(There seem to be no occurrences of the mistake in 7.4.)
2008-03-31 03:31:43 +02:00
|
|
|
if (S_ISDIR(fst.st_mode))
|
2005-10-15 04:49:52 +02:00
|
|
|
totalsize += db_dir_size(pathname);
|
|
|
|
|
|
|
|
totalsize += fst.st_size;
|
2005-08-02 16:07:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
FreeDir(dirdesc);
|
2005-10-15 04:49:52 +02:00
|
|
|
|
2005-08-02 16:07:27 +02:00
|
|
|
return totalsize;
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
pg_tablespace_size_oid(PG_FUNCTION_ARGS)
|
|
|
|
{
|
2005-10-15 04:49:52 +02:00
|
|
|
Oid tblspcOid = PG_GETARG_OID(0);
|
|
|
|
|
2005-08-02 16:07:27 +02:00
|
|
|
PG_RETURN_INT64(calculate_tablespace_size(tblspcOid));
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
pg_tablespace_size_name(PG_FUNCTION_ARGS)
|
|
|
|
{
|
2005-10-15 04:49:52 +02:00
|
|
|
Name tblspcName = PG_GETARG_NAME(0);
|
|
|
|
Oid tblspcOid = get_tablespace_oid(NameStr(*tblspcName));
|
2005-08-02 16:07:27 +02:00
|
|
|
|
|
|
|
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
|
2008-10-03 09:33:10 +02:00
|
|
|
calculate_relation_size(RelFileNode *rfn, ForkNumber forknum)
|
2005-08-02 16:07:27 +02:00
|
|
|
{
|
2005-09-30 00:04:36 +02:00
|
|
|
int64 totalsize = 0;
|
2006-11-06 04:06:41 +01:00
|
|
|
char *relationpath;
|
2005-09-30 00:04:36 +02:00
|
|
|
char pathname[MAXPGPATH];
|
|
|
|
unsigned int segcount = 0;
|
2005-08-02 16:07:27 +02:00
|
|
|
|
2008-10-03 09:33:10 +02:00
|
|
|
relationpath = relpath(*rfn, forknum);
|
2005-08-02 16:07:27 +02:00
|
|
|
|
2005-10-15 04:49:52 +02:00
|
|
|
for (segcount = 0;; segcount++)
|
2005-08-02 16:07:27 +02:00
|
|
|
{
|
|
|
|
struct stat fst;
|
|
|
|
|
|
|
|
if (segcount == 0)
|
2006-11-06 04:06:41 +01:00
|
|
|
snprintf(pathname, MAXPGPATH, "%s",
|
|
|
|
relationpath);
|
2005-08-02 16:07:27 +02:00
|
|
|
else
|
2006-11-06 04:06:41 +01:00
|
|
|
snprintf(pathname, MAXPGPATH, "%s.%u",
|
|
|
|
relationpath, segcount);
|
2005-08-02 16:07:27 +02:00
|
|
|
|
|
|
|
if (stat(pathname, &fst) < 0)
|
|
|
|
{
|
|
|
|
if (errno == ENOENT)
|
|
|
|
break;
|
|
|
|
else
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode_for_file_access(),
|
2005-10-29 02:31:52 +02:00
|
|
|
errmsg("could not stat file \"%s\": %m", pathname)));
|
2005-08-02 16:07:27 +02:00
|
|
|
}
|
|
|
|
totalsize += fst.st_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
return totalsize;
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
2008-10-03 09:33:10 +02:00
|
|
|
pg_relation_size(PG_FUNCTION_ARGS)
|
2005-08-02 16:07:27 +02:00
|
|
|
{
|
2008-10-03 09:33:10 +02:00
|
|
|
Oid relOid = PG_GETARG_OID(0);
|
|
|
|
text *forkName = PG_GETARG_TEXT_P(1);
|
2005-09-30 00:04:36 +02:00
|
|
|
Relation rel;
|
|
|
|
int64 size;
|
2005-10-15 04:49:52 +02:00
|
|
|
|
2008-10-03 09:33:10 +02:00
|
|
|
rel = relation_open(relOid, AccessShareLock);
|
2005-10-15 04:49:52 +02:00
|
|
|
|
2008-10-03 09:33:10 +02:00
|
|
|
size = calculate_relation_size(&(rel->rd_node),
|
|
|
|
forkname_to_number(text_to_cstring(forkName)));
|
2005-10-15 04:49:52 +02:00
|
|
|
|
2005-09-30 00:04:36 +02:00
|
|
|
relation_close(rel, AccessShareLock);
|
2005-08-02 16:07:27 +02:00
|
|
|
|
2005-09-30 00:04:36 +02:00
|
|
|
PG_RETURN_INT64(size);
|
2005-08-02 16:07:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Compute the on-disk size of files for the relation according to the
|
2006-11-06 04:06:41 +01:00
|
|
|
* stat function, including heap data, index data, and toast data.
|
2005-08-02 16:07:27 +02:00
|
|
|
*/
|
|
|
|
static int64
|
2005-09-30 00:04:36 +02:00
|
|
|
calculate_total_relation_size(Oid Relid)
|
2005-08-02 16:07:27 +02:00
|
|
|
{
|
2005-09-30 00:04:36 +02:00
|
|
|
Relation heapRel;
|
|
|
|
Oid toastOid;
|
|
|
|
int64 size;
|
|
|
|
ListCell *cell;
|
2008-10-03 09:33:10 +02:00
|
|
|
ForkNumber forkNum;
|
2005-09-30 00:04:36 +02:00
|
|
|
|
|
|
|
heapRel = relation_open(Relid, AccessShareLock);
|
|
|
|
toastOid = heapRel->rd_rel->reltoastrelid;
|
|
|
|
|
|
|
|
/* Get the heap size */
|
2008-10-03 09:33:10 +02:00
|
|
|
size = 0;
|
|
|
|
for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
|
|
|
|
size += calculate_relation_size(&(heapRel->rd_node), forkNum);
|
2005-09-30 00:04:36 +02:00
|
|
|
|
2006-11-06 04:06:41 +01:00
|
|
|
/* Include any dependent indexes */
|
2005-09-30 00:04:36 +02:00
|
|
|
if (heapRel->rd_rel->relhasindex)
|
2005-09-16 07:35:41 +02:00
|
|
|
{
|
2005-10-15 04:49:52 +02:00
|
|
|
List *index_oids = RelationGetIndexList(heapRel);
|
2005-09-16 07:35:41 +02:00
|
|
|
|
2005-09-30 00:04:36 +02:00
|
|
|
foreach(cell, index_oids)
|
2005-09-16 07:35:41 +02:00
|
|
|
{
|
2005-09-30 00:04:36 +02:00
|
|
|
Oid idxOid = lfirst_oid(cell);
|
|
|
|
Relation iRel;
|
|
|
|
|
|
|
|
iRel = relation_open(idxOid, AccessShareLock);
|
|
|
|
|
2008-10-03 09:33:10 +02:00
|
|
|
for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
|
|
|
|
size += calculate_relation_size(&(iRel->rd_node), forkNum);
|
2005-09-30 00:04:36 +02:00
|
|
|
|
|
|
|
relation_close(iRel, AccessShareLock);
|
2005-08-02 16:07:27 +02:00
|
|
|
}
|
2005-09-30 00:04:36 +02:00
|
|
|
|
|
|
|
list_free(index_oids);
|
2005-08-02 16:07:27 +02:00
|
|
|
}
|
2005-09-16 07:35:41 +02:00
|
|
|
|
2006-11-06 04:06:41 +01:00
|
|
|
/* Recursively include toast table (and index) size */
|
2005-09-30 00:04:36 +02:00
|
|
|
if (OidIsValid(toastOid))
|
|
|
|
size += calculate_total_relation_size(toastOid);
|
2005-08-02 16:07:27 +02:00
|
|
|
|
2005-09-30 00:04:36 +02:00
|
|
|
relation_close(heapRel, AccessShareLock);
|
2005-08-02 16:07:27 +02:00
|
|
|
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
2008-10-03 09:33:10 +02:00
|
|
|
pg_total_relation_size(PG_FUNCTION_ARGS)
|
2005-08-02 16:07:27 +02:00
|
|
|
{
|
2005-10-15 04:49:52 +02:00
|
|
|
Oid relid = PG_GETARG_OID(0);
|
2005-08-02 16:07:27 +02:00
|
|
|
|
2005-09-30 00:04:36 +02:00
|
|
|
PG_RETURN_INT64(calculate_total_relation_size(relid));
|
2005-08-02 16:07:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* formatting with size units
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
pg_size_pretty(PG_FUNCTION_ARGS)
|
|
|
|
{
|
2005-10-15 04:49:52 +02:00
|
|
|
int64 size = PG_GETARG_INT64(0);
|
2008-03-25 23:42:46 +01:00
|
|
|
char buf[64];
|
2005-10-15 04:49:52 +02:00
|
|
|
int64 limit = 10 * 1024;
|
|
|
|
int64 mult = 1;
|
2005-09-30 00:04:36 +02:00
|
|
|
|
|
|
|
if (size < limit * mult)
|
2008-03-25 23:42:46 +01:00
|
|
|
snprintf(buf, sizeof(buf), INT64_FORMAT " bytes", size);
|
2005-08-02 16:07:27 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
mult *= 1024;
|
2005-09-30 00:04:36 +02:00
|
|
|
if (size < limit * mult)
|
2008-03-25 23:42:46 +01:00
|
|
|
snprintf(buf, sizeof(buf), INT64_FORMAT " kB",
|
2005-10-15 04:49:52 +02:00
|
|
|
(size + mult / 2) / mult);
|
2005-08-02 16:07:27 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
mult *= 1024;
|
2005-09-30 00:04:36 +02:00
|
|
|
if (size < limit * mult)
|
2008-03-25 23:42:46 +01:00
|
|
|
snprintf(buf, sizeof(buf), INT64_FORMAT " MB",
|
2005-09-30 00:04:36 +02:00
|
|
|
(size + mult / 2) / mult);
|
2005-08-02 16:07:27 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
mult *= 1024;
|
2005-09-30 00:04:36 +02:00
|
|
|
if (size < limit * mult)
|
2008-03-25 23:42:46 +01:00
|
|
|
snprintf(buf, sizeof(buf), INT64_FORMAT " GB",
|
2005-09-30 00:04:36 +02:00
|
|
|
(size + mult / 2) / mult);
|
2005-08-02 16:07:27 +02:00
|
|
|
else
|
|
|
|
{
|
2005-10-15 04:49:52 +02:00
|
|
|
mult *= 1024;
|
2008-03-25 23:42:46 +01:00
|
|
|
snprintf(buf, sizeof(buf), INT64_FORMAT " TB",
|
2005-09-30 00:04:36 +02:00
|
|
|
(size + mult / 2) / mult);
|
2005-08-02 16:07:27 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-03-25 23:42:46 +01:00
|
|
|
PG_RETURN_TEXT_P(cstring_to_text(buf));
|
2005-08-02 16:07:27 +02:00
|
|
|
}
|