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

📄 relcache.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 4 页
字号:
	/*	 * If this isn't initdb time, then we want to initialize some index	 * relation descriptors, as well.  The descriptors are for	 * pg_attnumind (to make building relation descriptors fast) and	 * possibly others, as they're added.	 */	if (!IsBootstrapProcessingMode())		init_irels();	MemoryContextSwitchTo(oldcxt);}static voidAttrDefaultFetch(Relation relation){	AttrDefault *attrdef = relation->rd_att->constr->defval;	int			ndef = relation->rd_att->constr->num_defval;	Relation	adrel;	Relation	irel;	ScanKeyData skey;	HeapTupleData tuple;	Form_pg_attrdef adform;	IndexScanDesc sd;	RetrieveIndexResult indexRes;	struct varlena *val;	bool		isnull;	int			found;	int			i;	ScanKeyEntryInitialize(&skey,						   (bits16) 0x0,						   (AttrNumber) 1,						   (RegProcedure) F_OIDEQ,						   ObjectIdGetDatum(RelationGetRelid(relation)));	adrel = heap_openr(AttrDefaultRelationName);	irel = index_openr(AttrDefaultIndex);	sd = index_beginscan(irel, false, 1, &skey);	tuple.t_data = NULL;	for (found = 0;;)	{		Buffer		buffer;		indexRes = index_getnext(sd, ForwardScanDirection);		if (!indexRes)			break;		tuple.t_self = indexRes->heap_iptr;		heap_fetch(adrel, SnapshotNow, &tuple, &buffer);		pfree(indexRes);		if (tuple.t_data == NULL)			continue;		found++;		adform = (Form_pg_attrdef) GETSTRUCT(&tuple);		for (i = 0; i < ndef; i++)		{			if (adform->adnum != attrdef[i].adnum)				continue;			if (attrdef[i].adsrc != NULL)				elog(ERROR, "AttrDefaultFetch: second record found for attr %s in rel %s",				relation->rd_att->attrs[adform->adnum - 1]->attname.data,					 relation->rd_rel->relname.data);			val = (struct varlena *) fastgetattr(&tuple,												 Anum_pg_attrdef_adbin,												 adrel->rd_att, &isnull);			if (isnull)				elog(ERROR, "AttrDefaultFetch: adbin IS NULL for attr %s in rel %s",				relation->rd_att->attrs[adform->adnum - 1]->attname.data,					 relation->rd_rel->relname.data);			attrdef[i].adbin = textout(val);			val = (struct varlena *) fastgetattr(&tuple,												 Anum_pg_attrdef_adsrc,												 adrel->rd_att, &isnull);			if (isnull)				elog(ERROR, "AttrDefaultFetch: adsrc IS NULL for attr %s in rel %s",				relation->rd_att->attrs[adform->adnum - 1]->attname.data,					 relation->rd_rel->relname.data);			attrdef[i].adsrc = textout(val);			break;		}		ReleaseBuffer(buffer);		if (i >= ndef)			elog(ERROR, "AttrDefaultFetch: unexpected record found for attr %d in rel %s",				 adform->adnum,				 relation->rd_rel->relname.data);	}	if (found < ndef)		elog(ERROR, "AttrDefaultFetch: %d record not found for rel %s",			 ndef - found, relation->rd_rel->relname.data);	index_endscan(sd);	pfree(sd);	index_close(irel);	heap_close(adrel);}static voidRelCheckFetch(Relation relation){	ConstrCheck *check = relation->rd_att->constr->check;	int			ncheck = relation->rd_att->constr->num_check;	Relation	rcrel;	Relation	irel;	ScanKeyData skey;	HeapTupleData tuple;	IndexScanDesc sd;	RetrieveIndexResult indexRes;	Name		rcname;	struct varlena *val;	bool		isnull;	int			found;	ScanKeyEntryInitialize(&skey,						   (bits16) 0x0,						   (AttrNumber) 1,						   (RegProcedure) F_OIDEQ,						   ObjectIdGetDatum(RelationGetRelid(relation)));	rcrel = heap_openr(RelCheckRelationName);	irel = index_openr(RelCheckIndex);	sd = index_beginscan(irel, false, 1, &skey);	tuple.t_data = NULL;	for (found = 0;;)	{		Buffer		buffer;		indexRes = index_getnext(sd, ForwardScanDirection);		if (!indexRes)			break;		tuple.t_self = indexRes->heap_iptr;		heap_fetch(rcrel, SnapshotNow, &tuple, &buffer);		pfree(indexRes);		if (tuple.t_data == NULL)			continue;		if (found == ncheck)			elog(ERROR, "RelCheckFetch: unexpected record found for rel %s",				 relation->rd_rel->relname.data);		rcname = (Name) fastgetattr(&tuple,									Anum_pg_relcheck_rcname,									rcrel->rd_att, &isnull);		if (isnull)			elog(ERROR, "RelCheckFetch: rcname IS NULL for rel %s",				 relation->rd_rel->relname.data);		check[found].ccname = nameout(rcname);		val = (struct varlena *) fastgetattr(&tuple,											 Anum_pg_relcheck_rcbin,											 rcrel->rd_att, &isnull);		if (isnull)			elog(ERROR, "RelCheckFetch: rcbin IS NULL for rel %s",				 relation->rd_rel->relname.data);		check[found].ccbin = textout(val);		val = (struct varlena *) fastgetattr(&tuple,											 Anum_pg_relcheck_rcsrc,											 rcrel->rd_att, &isnull);		if (isnull)			elog(ERROR, "RelCheckFetch: rcsrc IS NULL for rel %s",				 relation->rd_rel->relname.data);		check[found].ccsrc = textout(val);		found++;		ReleaseBuffer(buffer);	}	if (found < ncheck)		elog(ERROR, "RelCheckFetch: %d record not found for rel %s",			 ncheck - found,			 relation->rd_rel->relname.data);	index_endscan(sd);	pfree(sd);	index_close(irel);	heap_close(rcrel);}/* *	init_irels(), write_irels() -- handle special-case initialization of *								   index relation descriptors. * *		In late 1992, we started regularly having databases with more than *		a thousand classes in them.  With this number of classes, it became *		critical to do indexed lookups on the system catalogs. * *		Bootstrapping these lookups is very hard.  We want to be able to *		use an index on pg_attribute, for example, but in order to do so, *		we must have read pg_attribute for the attributes in the index, *		which implies that we need to use the index. * *		In order to get around the problem, we do the following: * *		   +  When the database system is initialized (at initdb time), we *			  don't use indices on pg_attribute.  We do sequential scans. * *		   +  When the backend is started up in normal mode, we load an image *			  of the appropriate relation descriptors, in internal format, *			  from an initialization file in the data/base/... directory. * *		   +  If the initialization file isn't there, then we create the *			  relation descriptors using sequential scans and write 'em to *			  the initialization file for use by subsequent backends. * *		We could dispense with the initialization file and just build the *		critical reldescs the hard way on every backend startup, but that *		slows down backend startup noticeably if pg_class is large. * *		As of v6.5, vacuum.c deletes the initialization file at completion *		of a VACUUM, so that it will be rebuilt at the next backend startup. *		This ensures that vacuum-collected stats for the system indexes *		will eventually get used by the optimizer --- otherwise the relcache *		entries for these indexes will show zero sizes forever, since the *		relcache entries are pinned in memory and will never be reloaded *		from pg_class. *//* pg_attnumind, pg_classnameind, pg_classoidind */#define Num_indices_bootstrap	3static voidinit_irels(void){	Size		len;	int			nread;	File		fd;	Relation	irel[Num_indices_bootstrap];	Relation	ird;	Form_pg_am	am;	Form_pg_class relform;	IndexStrategy strat;	RegProcedure *support;	int			i;	int			relno;#ifndef __CYGWIN32__	if ((fd = FileNameOpenFile(RELCACHE_INIT_FILENAME, O_RDONLY, 0600)) < 0)#else	if ((fd = FileNameOpenFile(RELCACHE_INIT_FILENAME, O_RDONLY | O_BINARY, 0600)) < 0)#endif	{		write_irels();		return;	}	FileSeek(fd, 0L, SEEK_SET);	for (relno = 0; relno < Num_indices_bootstrap; relno++)	{		/* first read the relation descriptor length */		if ((nread = FileRead(fd, (char *) &len, sizeof(len))) != sizeof(len))		{			write_irels();			return;		}		ird = irel[relno] = (Relation) palloc(len);		MemSet(ird, 0, len);		/* then, read the Relation structure */		if ((nread = FileRead(fd, (char *) ird, len)) != len)		{			write_irels();			return;		}		/* the file descriptor is not yet opened */		ird->rd_fd = -1;		/* lock info is not initialized */		ird->lockInfo = (char *) NULL;		/* next, read the access method tuple form */		if ((nread = FileRead(fd, (char *) &len, sizeof(len))) != sizeof(len))		{			write_irels();			return;		}		am = (Form_pg_am) palloc(len);		if ((nread = FileRead(fd, (char *) am, len)) != len)		{			write_irels();			return;		}		ird->rd_am = am;		/* next read the relation tuple form */		if ((nread = FileRead(fd, (char *) &len, sizeof(len))) != sizeof(len))		{			write_irels();			return;		}		relform = (Form_pg_class) palloc(len);		if ((nread = FileRead(fd, (char *) relform, len)) != len)		{			write_irels();			return;		}		ird->rd_rel = relform;		/* initialize attribute tuple forms */		ird->rd_att = CreateTemplateTupleDesc(relform->relnatts);		/* next read all the attribute tuple form data entries */		len = ATTRIBUTE_TUPLE_SIZE;		for (i = 0; i < relform->relnatts; i++)		{			if ((nread = FileRead(fd, (char *) &len, sizeof(len))) != sizeof(len))			{				write_irels();				return;			}			ird->rd_att->attrs[i] = (Form_pg_attribute) palloc(len);			if ((nread = FileRead(fd, (char *) ird->rd_att->attrs[i], len)) != len)			{				write_irels();				return;			}		}		/* next, read the index strategy map */		if ((nread = FileRead(fd, (char *) &len, sizeof(len))) != sizeof(len))		{			write_irels();			return;		}		strat = (IndexStrategy) palloc(len);		if ((nread = FileRead(fd, (char *) strat, len)) != len)		{			write_irels();			return;		}		/* oh, for god's sake... */#define SMD(i)	strat[0].strategyMapData[i].entry[0]		/* have to reinit the function pointers in the strategy maps */		for (i = 0; i < am->amstrategies * relform->relnatts; i++)		{			fmgr_info(SMD(i).sk_procedure,					  &(SMD(i).sk_func));			SMD(i).sk_nargs = SMD(i).sk_func.fn_nargs;		}		/*		 * use a real field called rd_istrat instead of the bogosity of		 * hanging invisible fields off the end of a structure - jolly		 */		ird->rd_istrat = strat;		/* finally, read the vector of support procedures */		if ((nread = FileRead(fd, (char *) &len, sizeof(len))) != sizeof(len))		{			write_irels();			return;		}		support = (RegProcedure *) palloc(len);		if ((nread = FileRead(fd, (char *) support, len)) != len)		{			write_irels();			return;		}		/*		 * p += sizeof(IndexStrategy); ((RegProcedure **) p) = support;		 */		ird->rd_support = support;		RelationCacheInsert(ird);		RelationInitLockInfo(ird);	}}static voidwrite_irels(void){	Size		len;	int			nwritten;	File		fd;	Relation	irel[Num_indices_bootstrap];	Relation	ird;	Form_pg_am	am;	Form_pg_class relform;	IndexStrategy strat;	RegProcedure *support;	ProcessingMode oldmode;	int			i;	int			relno;	RelationBuildDescInfo bi;#ifndef __CYGWIN32__	fd = FileNameOpenFile(RELCACHE_INIT_FILENAME, O_WRONLY | O_CREAT | O_TRUNC, 0600);#else	fd = FileNameOpenFile(RELCACHE_INIT_FILENAME, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0600);#endif	if (fd < 0)		elog(FATAL, "cannot create init file %s", RELCACHE_INIT_FILENAME);	FileSeek(fd, 0L, SEEK_SET);	/*	 * Build a relation descriptor for pg_attnumind without resort to the	 * descriptor cache.  In order to do this, we set ProcessingMode to	 * Bootstrap.  The effect of this is to disable indexed relation	 * searches -- a necessary step, since we're trying to instantiate the	 * index relation descriptors here.	 */	oldmode = GetProcessingMode();	SetProcessingMode(BootstrapProcessing);	bi.infotype = INFO_RELNAME;	bi.i.info_name = AttributeNumIndex;	irel[0] = RelationBuildDesc(bi);	irel[0]->rd_isnailed = true;	bi.i.info_name = ClassNameIndex;	irel[1] = RelationBuildDesc(bi);	irel[1]->rd_isnailed = true;	bi.i.info_name = ClassOidIndex;	irel[2] = RelationBuildDesc(bi);	irel[2]->rd_isnailed = true;	SetProcessingMode(oldmode);	/* nail the descriptor in the cache */	for (relno = 0; relno < Num_indices_bootstrap; relno++)	{		ird = irel[relno];		/* save the volatile fields in the relation descriptor */		am = ird->rd_am;		ird->rd_am = (Form_pg_am) NULL;		relform = ird->rd_rel;		ird->rd_rel = (Form_pg_class) NULL;		strat = ird->rd_istrat;		support = ird->rd_support;		/*		 * first write the relation descriptor , excluding strategy and		 * support		 */		len = sizeof(RelationData);		/* first, write the relation descriptor length */		if ((nwritten = FileWrite(fd, (char *) &len, sizeof(len)))			!= sizeof(len))			elog(FATAL, "cannot write init file -- descriptor length");		/* next, write out the Relation structure */		if ((nwritten = FileWrite(fd, (char *) ird, len)) != len)			elog(FATAL, "cannot write init file -- reldesc");		/* next, write the access method tuple form */		len = sizeof(FormData_pg_am);		if ((nwritten = FileWrite(fd, (char *) &len, sizeof(len)))			!= sizeof(len))			elog(FATAL, "cannot write init file -- am tuple form length");		if ((nwritten = FileWrite(fd, (char *) am, len)) != len)			elog(FATAL, "cannot write init file -- am tuple form");		/* next write the relation tuple form */		len = sizeof(FormData_pg_class);		if ((nwritten = FileWrite(fd, (char *) &len, sizeof(len)))			!= sizeof(len))			elog(FATAL, "cannot write init file -- relation tuple form length");		if ((nwritten = FileWrite(fd, (char *) relform, len)) != len)			elog(FATAL, "cannot write init file -- relation tuple form");		/* next, do all the attribute tuple form data entries */		len = ATTRIBUTE_TUPLE_SIZE;		for (i = 0; i < relform->relnatts; i++)		{			if ((nwritten = FileWrite(fd, (char *) &len, sizeof(len)))				!= sizeof(len))				elog(FATAL, "cannot write init file -- length of attdesc %d", i);			if ((nwritten = FileWrite(fd, (char *) ird->rd_att->attrs[i], len))				!= len)				elog(FATAL, "cannot write init file -- attdesc %d", i);		}		/* next, write the index strategy map */		len = AttributeNumberGetIndexStrategySize(relform->relnatts,												  am->amstrategies);		if ((nwritten = FileWrite(fd, (char *) &len, sizeof(len)))			!= sizeof(len))			elog(FATAL, "cannot write init file -- strategy map length");		if ((nwritten = FileWrite(fd, (char *) strat, len)) != len)			elog(FATAL, "cannot write init file -- strategy map");		/* finally, write the vector of support procedures */		len = relform->relnatts * (am->amsupport * sizeof(RegProcedure));		if ((nwritten = FileWrite(fd, (char *) &len, sizeof(len)))			!= sizeof(len))			elog(FATAL, "cannot write init file -- support vector length");		if ((nwritten = FileWrite(fd, (char *) support, len)) != len)			elog(FATAL, "cannot write init file -- support vector");		/* restore volatile fields */		ird->rd_am = am;		ird->rd_rel = relform;	}	FileClose(fd);}

⌨️ 快捷键说明

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