dbsize.c
来自「postgresql8.3.4源码,开源数据库」· C语言 代码 · 共 434 行
C
434 行
/* * dbsize.c * object size functions * * Copyright (c) 2002-2008, PostgreSQL Global Development Group * * IDENTIFICATION * $PostgreSQL: pgsql/src/backend/utils/adt/dbsize.c,v 1.16.2.1 2008/03/31 01:32:01 tgl Exp $ * */#include "postgres.h"#include <sys/types.h>#include <sys/stat.h>#include "access/heapam.h"#include "catalog/catalog.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/acl.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 int64db_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, path)) != 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) { if (errno == ENOENT) continue; else ereport(ERROR, (errcode_for_file_access(), errmsg("could not stat file \"%s\": %m", filename))); } dirsize += fst.st_size; } FreeDir(dirdesc); return dirsize;}/* * calculate size of database in all tablespaces */static int64calculate_database_size(Oid dbOid){ int64 totalsize; DIR *dirdesc; struct dirent *direntry; char dirpath[MAXPGPATH]; char pathname[MAXPGPATH]; 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)); /* Shared storage in pg_global is not counted */ /* Include pg_default storage */ snprintf(pathname, MAXPGPATH, "base/%u", dbOid); totalsize = db_dir_size(pathname); /* Scan the non-default tablespaces */ snprintf(dirpath, MAXPGPATH, "pg_tblspc"); dirdesc = AllocateDir(dirpath); if (!dirdesc) ereport(ERROR, (errcode_for_file_access(), errmsg("could not open tablespace directory \"%s\": %m", dirpath))); while ((direntry = ReadDir(dirdesc, dirpath)) != NULL) { if (strcmp(direntry->d_name, ".") == 0 || strcmp(direntry->d_name, "..") == 0) continue; snprintf(pathname, MAXPGPATH, "pg_tblspc/%s/%u", 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;}Datumpg_database_size_oid(PG_FUNCTION_ARGS){ Oid dbOid = PG_GETARG_OID(0); PG_RETURN_INT64(calculate_database_size(dbOid));}Datumpg_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 int64calculate_tablespace_size(Oid tblspcOid){ char tblspcPath[MAXPGPATH]; char pathname[MAXPGPATH]; int64 totalsize = 0; DIR *dirdesc; struct dirent *direntry; AclResult aclresult; /* * User must have CREATE privilege for target tablespace, either * explicitly granted or implicitly because it is default for current * database. */ 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)); } if (tblspcOid == DEFAULTTABLESPACE_OID) snprintf(tblspcPath, MAXPGPATH, "base"); else if (tblspcOid == GLOBALTABLESPACE_OID) snprintf(tblspcPath, MAXPGPATH, "global"); else snprintf(tblspcPath, MAXPGPATH, "pg_tblspc/%u", 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, tblspcPath)) != 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) { if (errno == ENOENT) continue; else ereport(ERROR, (errcode_for_file_access(), errmsg("could not stat file \"%s\": %m", pathname))); } if (S_ISDIR(fst.st_mode)) totalsize += db_dir_size(pathname); totalsize += fst.st_size; } FreeDir(dirdesc); return totalsize;}Datumpg_tablespace_size_oid(PG_FUNCTION_ARGS){ Oid tblspcOid = PG_GETARG_OID(0); PG_RETURN_INT64(calculate_tablespace_size(tblspcOid));}Datumpg_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 int64calculate_relation_size(RelFileNode *rfn){ int64 totalsize = 0; char *relationpath; char pathname[MAXPGPATH]; unsigned int segcount = 0; relationpath = relpath(*rfn); for (segcount = 0;; segcount++) { struct stat fst; if (segcount == 0) snprintf(pathname, MAXPGPATH, "%s", relationpath); else snprintf(pathname, MAXPGPATH, "%s.%u", relationpath, segcount); if (stat(pathname, &fst) < 0) { if (errno == ENOENT) break; else ereport(ERROR, (errcode_for_file_access(), errmsg("could not stat file \"%s\": %m", pathname))); } totalsize += fst.st_size; } return totalsize;}Datumpg_relation_size_oid(PG_FUNCTION_ARGS){ Oid relOid = PG_GETARG_OID(0); Relation rel; int64 size; rel = relation_open(relOid, AccessShareLock); size = calculate_relation_size(&(rel->rd_node)); relation_close(rel, AccessShareLock); PG_RETURN_INT64(size);}Datumpg_relation_size_name(PG_FUNCTION_ARGS){ text *relname = PG_GETARG_TEXT_P(0); RangeVar *relrv; Relation rel; int64 size; relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname)); rel = relation_openrv(relrv, AccessShareLock); size = calculate_relation_size(&(rel->rd_node)); relation_close(rel, AccessShareLock); PG_RETURN_INT64(size);}/* * Compute the on-disk size of files for the relation according to the * stat function, including heap data, index data, and toast data. */static int64calculate_total_relation_size(Oid Relid){ Relation heapRel; Oid toastOid; int64 size; ListCell *cell; heapRel = relation_open(Relid, AccessShareLock); toastOid = heapRel->rd_rel->reltoastrelid; /* Get the heap size */ size = calculate_relation_size(&(heapRel->rd_node)); /* Include any dependent indexes */ if (heapRel->rd_rel->relhasindex) { List *index_oids = RelationGetIndexList(heapRel); foreach(cell, index_oids) { Oid idxOid = lfirst_oid(cell); Relation iRel; iRel = relation_open(idxOid, AccessShareLock); size += calculate_relation_size(&(iRel->rd_node)); relation_close(iRel, AccessShareLock); } list_free(index_oids); } /* Recursively include toast table (and index) size */ if (OidIsValid(toastOid)) size += calculate_total_relation_size(toastOid); relation_close(heapRel, AccessShareLock); return size;}Datumpg_total_relation_size_oid(PG_FUNCTION_ARGS){ Oid relid = PG_GETARG_OID(0); PG_RETURN_INT64(calculate_total_relation_size(relid));}Datumpg_total_relation_size_name(PG_FUNCTION_ARGS){ text *relname = PG_GETARG_TEXT_P(0); RangeVar *relrv; Oid relid; relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname)); relid = RangeVarGetRelid(relrv, false); PG_RETURN_INT64(calculate_total_relation_size(relid));}/* * formatting with size units */Datumpg_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); } } } } SET_VARSIZE(result, strlen(VARDATA(result)) + VARHDRSZ); PG_RETURN_TEXT_P(result);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?