⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tablespace.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 2 页
字号:
		/* This check is just to deliver a friendlier error message */		if (!directory_is_empty(subfile))		{			FreeDir(dirdesc);			return false;		}		/* Do the real deed */		if (rmdir(subfile) < 0)			ereport(ERROR,					(errcode_for_file_access(),					 errmsg("could not delete directory \"%s\": %m",							subfile)));		pfree(subfile);	}	FreeDir(dirdesc);	/*	 * Okay, try to unlink PG_VERSION (we allow it to not be there, even in	 * non-REDO case, for robustness).	 */	subfile = palloc(strlen(location) + 11 + 1);	sprintf(subfile, "%s/PG_VERSION", location);	if (unlink(subfile) < 0)	{		if (errno != ENOENT)			ereport(ERROR,					(errcode_for_file_access(),					 errmsg("could not remove file \"%s\": %m",							subfile)));	}	pfree(subfile);	/*	 * Okay, try to remove the symlink.  We must however deal with the	 * possibility that it's a directory instead of a symlink --- this could	 * happen during WAL replay (see TablespaceCreateDbspace), and it is also	 * the normal case on Windows.	 */	if (lstat(location, &st) == 0 && S_ISDIR(st.st_mode))	{		if (rmdir(location) < 0)			ereport(ERROR,					(errcode_for_file_access(),					 errmsg("could not remove directory \"%s\": %m",							location)));	}	else	{		if (unlink(location) < 0)			ereport(ERROR,					(errcode_for_file_access(),					 errmsg("could not remove symbolic link \"%s\": %m",							location)));	}	pfree(location);	return true;}/* * write out the PG_VERSION file in the specified directory */static voidset_short_version(const char *path){	char	   *short_version;	bool		gotdot = false;	int			end;	char	   *fullname;	FILE	   *version_file;	/* Construct short version string (should match initdb.c) */	short_version = pstrdup(PG_VERSION);	for (end = 0; short_version[end] != '\0'; end++)	{		if (short_version[end] == '.')		{			Assert(end != 0);			if (gotdot)				break;			else				gotdot = true;		}		else if (short_version[end] < '0' || short_version[end] > '9')		{			/* gone past digits and dots */			break;		}	}	Assert(end > 0 && short_version[end - 1] != '.' && gotdot);	short_version[end] = '\0';	/* Now write the file */	fullname = palloc(strlen(path) + 11 + 1);	sprintf(fullname, "%s/PG_VERSION", path);	version_file = AllocateFile(fullname, PG_BINARY_W);	if (version_file == NULL)		ereport(ERROR,				(errcode_for_file_access(),				 errmsg("could not write to file \"%s\": %m",						fullname)));	fprintf(version_file, "%s\n", short_version);	if (FreeFile(version_file))		ereport(ERROR,				(errcode_for_file_access(),				 errmsg("could not write to file \"%s\": %m",						fullname)));	pfree(fullname);	pfree(short_version);}/* * Check if a directory is empty. * * This probably belongs somewhere else, but not sure where... */booldirectory_is_empty(const char *path){	DIR		   *dirdesc;	struct dirent *de;	dirdesc = AllocateDir(path);	while ((de = ReadDir(dirdesc, path)) != NULL)	{		if (strcmp(de->d_name, ".") == 0 ||			strcmp(de->d_name, "..") == 0)			continue;		FreeDir(dirdesc);		return false;	}	FreeDir(dirdesc);	return true;}/* * Rename a tablespace */voidRenameTableSpace(const char *oldname, const char *newname){	Relation	rel;	ScanKeyData entry[1];	HeapScanDesc scan;	HeapTuple	tup;	HeapTuple	newtuple;	Form_pg_tablespace newform;	/* Search pg_tablespace */	rel = heap_open(TableSpaceRelationId, RowExclusiveLock);	ScanKeyInit(&entry[0],				Anum_pg_tablespace_spcname,				BTEqualStrategyNumber, F_NAMEEQ,				CStringGetDatum(oldname));	scan = heap_beginscan(rel, SnapshotNow, 1, entry);	tup = heap_getnext(scan, ForwardScanDirection);	if (!HeapTupleIsValid(tup))		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_OBJECT),				 errmsg("tablespace \"%s\" does not exist",						oldname)));	newtuple = heap_copytuple(tup);	newform = (Form_pg_tablespace) GETSTRUCT(newtuple);	heap_endscan(scan);	/* Must be owner */	if (!pg_tablespace_ownercheck(HeapTupleGetOid(newtuple), GetUserId()))		aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_TABLESPACE, oldname);	/* Validate new name */	if (!allowSystemTableMods && IsReservedName(newname))		ereport(ERROR,				(errcode(ERRCODE_RESERVED_NAME),				 errmsg("unacceptable tablespace name \"%s\"", newname),		errdetail("The prefix \"pg_\" is reserved for system tablespaces.")));	/* Make sure the new name doesn't exist */	ScanKeyInit(&entry[0],				Anum_pg_tablespace_spcname,				BTEqualStrategyNumber, F_NAMEEQ,				CStringGetDatum(newname));	scan = heap_beginscan(rel, SnapshotNow, 1, entry);	tup = heap_getnext(scan, ForwardScanDirection);	if (HeapTupleIsValid(tup))		ereport(ERROR,				(errcode(ERRCODE_DUPLICATE_OBJECT),				 errmsg("tablespace \"%s\" already exists",						newname)));	heap_endscan(scan);	/* OK, update the entry */	namestrcpy(&(newform->spcname), newname);	simple_heap_update(rel, &newtuple->t_self, newtuple);	CatalogUpdateIndexes(rel, newtuple);	heap_close(rel, NoLock);}/* * Change tablespace owner */voidAlterTableSpaceOwner(const char *name, Oid newOwnerId){	Relation	rel;	ScanKeyData entry[1];	HeapScanDesc scandesc;	Form_pg_tablespace spcForm;	HeapTuple	tup;	/* Search pg_tablespace */	rel = heap_open(TableSpaceRelationId, RowExclusiveLock);	ScanKeyInit(&entry[0],				Anum_pg_tablespace_spcname,				BTEqualStrategyNumber, F_NAMEEQ,				CStringGetDatum(name));	scandesc = heap_beginscan(rel, SnapshotNow, 1, entry);	tup = heap_getnext(scandesc, ForwardScanDirection);	if (!HeapTupleIsValid(tup))		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_OBJECT),				 errmsg("tablespace \"%s\" does not exist", name)));	spcForm = (Form_pg_tablespace) GETSTRUCT(tup);	/*	 * If the new owner is the same as the existing owner, consider the	 * command to have succeeded.  This is for dump restoration purposes.	 */	if (spcForm->spcowner != newOwnerId)	{		Datum		repl_val[Natts_pg_tablespace];		char		repl_null[Natts_pg_tablespace];		char		repl_repl[Natts_pg_tablespace];		Acl		   *newAcl;		Datum		aclDatum;		bool		isNull;		HeapTuple	newtuple;		/* Otherwise, must be owner of the existing object */		if (!pg_tablespace_ownercheck(HeapTupleGetOid(tup), GetUserId()))			aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TABLESPACE,						   name);		/* Must be able to become new owner */		check_is_member_of_role(GetUserId(), newOwnerId);		/*		 * Normally we would also check for create permissions here, but there		 * are none for tablespaces so we follow what rename tablespace does		 * and omit the create permissions check.		 *		 * NOTE: Only superusers may create tablespaces to begin with and so		 * initially only a superuser would be able to change its ownership		 * anyway.		 */		memset(repl_null, ' ', sizeof(repl_null));		memset(repl_repl, ' ', sizeof(repl_repl));		repl_repl[Anum_pg_tablespace_spcowner - 1] = 'r';		repl_val[Anum_pg_tablespace_spcowner - 1] = ObjectIdGetDatum(newOwnerId);		/*		 * Determine the modified ACL for the new owner.  This is only		 * necessary when the ACL is non-null.		 */		aclDatum = heap_getattr(tup,								Anum_pg_tablespace_spcacl,								RelationGetDescr(rel),								&isNull);		if (!isNull)		{			newAcl = aclnewowner(DatumGetAclP(aclDatum),								 spcForm->spcowner, newOwnerId);			repl_repl[Anum_pg_tablespace_spcacl - 1] = 'r';			repl_val[Anum_pg_tablespace_spcacl - 1] = PointerGetDatum(newAcl);		}		newtuple = heap_modifytuple(tup, RelationGetDescr(rel), repl_val, repl_null, repl_repl);		simple_heap_update(rel, &newtuple->t_self, newtuple);		CatalogUpdateIndexes(rel, newtuple);		heap_freetuple(newtuple);		/* Update owner dependency reference */		changeDependencyOnOwner(TableSpaceRelationId, HeapTupleGetOid(tup),								newOwnerId);	}	heap_endscan(scandesc);	heap_close(rel, NoLock);}/* * Routines for handling the GUC variable 'default_tablespace'. *//* assign_hook: validate new default_tablespace, do extra actions as needed */const char *assign_default_tablespace(const char *newval, bool doit, GucSource source){	/*	 * If we aren't inside a transaction, we cannot do database access so	 * cannot verify the name.	Must accept the value on faith.	 */	if (IsTransactionState())	{		if (newval[0] != '\0' &&			!OidIsValid(get_tablespace_oid(newval)))		{			if (source >= PGC_S_INTERACTIVE)				ereport(ERROR,						(errcode(ERRCODE_UNDEFINED_OBJECT),						 errmsg("tablespace \"%s\" does not exist",								newval)));			return NULL;		}	}	return newval;}/* * GetDefaultTablespace -- get the OID of the current default tablespace * * May return InvalidOid to indicate "use the database's default tablespace" * * This exists to hide (and possibly optimize the use of) the * default_tablespace GUC variable. */OidGetDefaultTablespace(void){	Oid			result;	/* Fast path for default_tablespace == "" */	if (default_tablespace == NULL || default_tablespace[0] == '\0')		return InvalidOid;	/*	 * It is tempting to cache this lookup for more speed, but then we would	 * fail to detect the case where the tablespace was dropped since the GUC	 * variable was set.  Note also that we don't complain if the value fails	 * to refer to an existing tablespace; we just silently return InvalidOid,	 * causing the new object to be created in the database's tablespace.	 */	result = get_tablespace_oid(default_tablespace);	/*	 * Allow explicit specification of database's default tablespace in	 * default_tablespace without triggering permissions checks.	 */	if (result == MyDatabaseTableSpace)		result = InvalidOid;	return result;}/* * get_tablespace_oid - given a tablespace name, look up the OID * * Returns InvalidOid if tablespace name not found. */Oidget_tablespace_oid(const char *tablespacename){	Oid			result;	Relation	rel;	HeapScanDesc scandesc;	HeapTuple	tuple;	ScanKeyData entry[1];	/* Search pg_tablespace */	rel = heap_open(TableSpaceRelationId, AccessShareLock);	ScanKeyInit(&entry[0],				Anum_pg_tablespace_spcname,				BTEqualStrategyNumber, F_NAMEEQ,				CStringGetDatum(tablespacename));	scandesc = heap_beginscan(rel, SnapshotNow, 1, entry);	tuple = heap_getnext(scandesc, ForwardScanDirection);	if (HeapTupleIsValid(tuple))		result = HeapTupleGetOid(tuple);	else		result = InvalidOid;	heap_endscan(scandesc);	heap_close(rel, AccessShareLock);	return result;}/* * get_tablespace_name - given a tablespace OID, look up the name * * Returns a palloc'd string, or NULL if no such tablespace. */char *get_tablespace_name(Oid spc_oid){	char	   *result;	Relation	rel;	HeapScanDesc scandesc;	HeapTuple	tuple;	ScanKeyData entry[1];	/* Search pg_tablespace */	rel = heap_open(TableSpaceRelationId, AccessShareLock);	ScanKeyInit(&entry[0],				ObjectIdAttributeNumber,				BTEqualStrategyNumber, F_OIDEQ,				ObjectIdGetDatum(spc_oid));	scandesc = heap_beginscan(rel, SnapshotNow, 1, entry);	tuple = heap_getnext(scandesc, ForwardScanDirection);	/* We assume that there can be at most one matching tuple */	if (HeapTupleIsValid(tuple))		result = pstrdup(NameStr(((Form_pg_tablespace) GETSTRUCT(tuple))->spcname));	else		result = NULL;	heap_endscan(scandesc);	heap_close(rel, AccessShareLock);	return result;}/* * TABLESPACE resource manager's routines */voidtblspc_redo(XLogRecPtr lsn, XLogRecord *record){	uint8		info = record->xl_info & ~XLR_INFO_MASK;	if (info == XLOG_TBLSPC_CREATE)	{		xl_tblspc_create_rec *xlrec = (xl_tblspc_create_rec *) XLogRecGetData(record);		char	   *location = xlrec->ts_path;		char	   *linkloc;		/*		 * Attempt to coerce target directory to safe permissions.	If this		 * fails, it doesn't exist or has the wrong owner.		 */		if (chmod(location, 0700) != 0)			ereport(ERROR,					(errcode_for_file_access(),				  errmsg("could not set permissions on directory \"%s\": %m",						 location)));		/* Create or re-create the PG_VERSION file in the target directory */		set_short_version(location);		/* Create the symlink if not already present */		linkloc = (char *) palloc(10 + 10 + 1);		sprintf(linkloc, "pg_tblspc/%u", xlrec->ts_id);		if (symlink(location, linkloc) < 0)		{			if (errno != EEXIST)				ereport(ERROR,						(errcode_for_file_access(),						 errmsg("could not create symbolic link \"%s\": %m",								linkloc)));		}		pfree(linkloc);	}	else if (info == XLOG_TBLSPC_DROP)	{		xl_tblspc_drop_rec *xlrec = (xl_tblspc_drop_rec *) XLogRecGetData(record);		if (!remove_tablespace_directories(xlrec->ts_id, true))			ereport(ERROR,					(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),					 errmsg("tablespace %u is not empty",							xlrec->ts_id)));	}	else		elog(PANIC, "tblspc_redo: unknown op code %u", info);}voidtblspc_desc(char *buf, uint8 xl_info, char *rec){	uint8		info = xl_info & ~XLR_INFO_MASK;	if (info == XLOG_TBLSPC_CREATE)	{		xl_tblspc_create_rec *xlrec = (xl_tblspc_create_rec *) rec;		sprintf(buf + strlen(buf), "create ts: %u \"%s\"",				xlrec->ts_id, xlrec->ts_path);	}	else if (info == XLOG_TBLSPC_DROP)	{		xl_tblspc_drop_rec *xlrec = (xl_tblspc_drop_rec *) rec;		sprintf(buf + strlen(buf), "drop ts: %u",				xlrec->ts_id);	}	else		strcat(buf, "UNKNOWN");}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -