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 + -
显示快捷键?