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

📄 inv_api.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 2 页
字号:
		if (pfreeit)			pfree(datafield);		break;	}	index_endscan(sd);	if (!found)		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_OBJECT),				 errmsg("large object %u does not exist", obj_desc->id)));	return lastbyte;}intinv_seek(LargeObjectDesc *obj_desc, int offset, int whence){	Assert(PointerIsValid(obj_desc));	switch (whence)	{		case SEEK_SET:			if (offset < 0)				elog(ERROR, "invalid seek offset: %d", offset);			obj_desc->offset = offset;			break;		case SEEK_CUR:			if (offset < 0 && obj_desc->offset < ((uint32) (-offset)))				elog(ERROR, "invalid seek offset: %d", offset);			obj_desc->offset += offset;			break;		case SEEK_END:			{				uint32		size = inv_getsize(obj_desc);				if (offset < 0 && size < ((uint32) (-offset)))					elog(ERROR, "invalid seek offset: %d", offset);				obj_desc->offset = size + offset;			}			break;		default:			elog(ERROR, "invalid whence: %d", whence);	}	return obj_desc->offset;}intinv_tell(LargeObjectDesc *obj_desc){	Assert(PointerIsValid(obj_desc));	return obj_desc->offset;}intinv_read(LargeObjectDesc *obj_desc, char *buf, int nbytes){	int			nread = 0;	int			n;	int			off;	int			len;	int32		pageno = (int32) (obj_desc->offset / LOBLKSIZE);	uint32		pageoff;	ScanKeyData skey[2];	IndexScanDesc sd;	HeapTuple	tuple;	Assert(PointerIsValid(obj_desc));	Assert(buf != NULL);	if (nbytes <= 0)		return 0;	open_lo_relation();	ScanKeyInit(&skey[0],				Anum_pg_largeobject_loid,				BTEqualStrategyNumber, F_OIDEQ,				ObjectIdGetDatum(obj_desc->id));	ScanKeyInit(&skey[1],				Anum_pg_largeobject_pageno,				BTGreaterEqualStrategyNumber, F_INT4GE,				Int32GetDatum(pageno));	sd = index_beginscan(lo_heap_r, lo_index_r,						 obj_desc->snapshot, 2, skey);	while ((tuple = index_getnext(sd, ForwardScanDirection)) != NULL)	{		Form_pg_largeobject data;		bytea	   *datafield;		bool		pfreeit;		data = (Form_pg_largeobject) GETSTRUCT(tuple);		/*		 * We assume the indexscan will deliver pages in order.  However,		 * there may be missing pages if the LO contains unwritten "holes". We		 * want missing sections to read out as zeroes.		 */		pageoff = ((uint32) data->pageno) * LOBLKSIZE;		if (pageoff > obj_desc->offset)		{			n = pageoff - obj_desc->offset;			n = (n <= (nbytes - nread)) ? n : (nbytes - nread);			MemSet(buf + nread, 0, n);			nread += n;			obj_desc->offset += n;		}		if (nread < nbytes)		{			Assert(obj_desc->offset >= pageoff);			off = (int) (obj_desc->offset - pageoff);			Assert(off >= 0 && off < LOBLKSIZE);			datafield = &(data->data);			pfreeit = false;			if (VARATT_IS_EXTENDED(datafield))			{				datafield = (bytea *)					heap_tuple_untoast_attr((varattrib *) datafield);				pfreeit = true;			}			len = getbytealen(datafield);			if (len > off)			{				n = len - off;				n = (n <= (nbytes - nread)) ? n : (nbytes - nread);				memcpy(buf + nread, VARDATA(datafield) + off, n);				nread += n;				obj_desc->offset += n;			}			if (pfreeit)				pfree(datafield);		}		if (nread >= nbytes)			break;	}	index_endscan(sd);	return nread;}intinv_write(LargeObjectDesc *obj_desc, char *buf, int nbytes){	int			nwritten = 0;	int			n;	int			off;	int			len;	int32		pageno = (int32) (obj_desc->offset / LOBLKSIZE);	ScanKeyData skey[2];	IndexScanDesc sd;	HeapTuple	oldtuple;	Form_pg_largeobject olddata;	bool		neednextpage;	bytea	   *datafield;	bool		pfreeit;	struct	{		bytea		hdr;		char		data[LOBLKSIZE];	}			workbuf;	char	   *workb = VARATT_DATA(&workbuf.hdr);	HeapTuple	newtup;	Datum		values[Natts_pg_largeobject];	char		nulls[Natts_pg_largeobject];	char		replace[Natts_pg_largeobject];	CatalogIndexState indstate;	Assert(PointerIsValid(obj_desc));	Assert(buf != NULL);	/* enforce writability because snapshot is probably wrong otherwise */	if ((obj_desc->flags & IFS_WRLOCK) == 0)		ereport(ERROR,				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),				 errmsg("large object %u was not opened for writing",						obj_desc->id)));	if (nbytes <= 0)		return 0;	open_lo_relation();	indstate = CatalogOpenIndexes(lo_heap_r);	ScanKeyInit(&skey[0],				Anum_pg_largeobject_loid,				BTEqualStrategyNumber, F_OIDEQ,				ObjectIdGetDatum(obj_desc->id));	ScanKeyInit(&skey[1],				Anum_pg_largeobject_pageno,				BTGreaterEqualStrategyNumber, F_INT4GE,				Int32GetDatum(pageno));	sd = index_beginscan(lo_heap_r, lo_index_r,						 obj_desc->snapshot, 2, skey);	oldtuple = NULL;	olddata = NULL;	neednextpage = true;	while (nwritten < nbytes)	{		/*		 * If possible, get next pre-existing page of the LO.  We assume the		 * indexscan will deliver these in order --- but there may be holes.		 */		if (neednextpage)		{			if ((oldtuple = index_getnext(sd, ForwardScanDirection)) != NULL)			{				olddata = (Form_pg_largeobject) GETSTRUCT(oldtuple);				Assert(olddata->pageno >= pageno);			}			neednextpage = false;		}		/*		 * If we have a pre-existing page, see if it is the page we want to		 * write, or a later one.		 */		if (olddata != NULL && olddata->pageno == pageno)		{			/*			 * Update an existing page with fresh data.			 *			 * First, load old data into workbuf			 */			datafield = &(olddata->data);			pfreeit = false;			if (VARATT_IS_EXTENDED(datafield))			{				datafield = (bytea *)					heap_tuple_untoast_attr((varattrib *) datafield);				pfreeit = true;			}			len = getbytealen(datafield);			Assert(len <= LOBLKSIZE);			memcpy(workb, VARDATA(datafield), len);			if (pfreeit)				pfree(datafield);			/*			 * Fill any hole			 */			off = (int) (obj_desc->offset % LOBLKSIZE);			if (off > len)				MemSet(workb + len, 0, off - len);			/*			 * Insert appropriate portion of new data			 */			n = LOBLKSIZE - off;			n = (n <= (nbytes - nwritten)) ? n : (nbytes - nwritten);			memcpy(workb + off, buf + nwritten, n);			nwritten += n;			obj_desc->offset += n;			off += n;			/* compute valid length of new page */			len = (len >= off) ? len : off;			VARATT_SIZEP(&workbuf.hdr) = len + VARHDRSZ;			/*			 * Form and insert updated tuple			 */			memset(values, 0, sizeof(values));			memset(nulls, ' ', sizeof(nulls));			memset(replace, ' ', sizeof(replace));			values[Anum_pg_largeobject_data - 1] = PointerGetDatum(&workbuf);			replace[Anum_pg_largeobject_data - 1] = 'r';			newtup = heap_modifytuple(oldtuple, RelationGetDescr(lo_heap_r),									  values, nulls, replace);			simple_heap_update(lo_heap_r, &newtup->t_self, newtup);			CatalogIndexInsert(indstate, newtup);			heap_freetuple(newtup);			/*			 * We're done with this old page.			 */			oldtuple = NULL;			olddata = NULL;			neednextpage = true;		}		else		{			/*			 * Write a brand new page.			 *			 * First, fill any hole			 */			off = (int) (obj_desc->offset % LOBLKSIZE);			if (off > 0)				MemSet(workb, 0, off);			/*			 * Insert appropriate portion of new data			 */			n = LOBLKSIZE - off;			n = (n <= (nbytes - nwritten)) ? n : (nbytes - nwritten);			memcpy(workb + off, buf + nwritten, n);			nwritten += n;			obj_desc->offset += n;			/* compute valid length of new page */			len = off + n;			VARATT_SIZEP(&workbuf.hdr) = len + VARHDRSZ;			/*			 * Form and insert updated tuple			 */			memset(values, 0, sizeof(values));			memset(nulls, ' ', sizeof(nulls));			values[Anum_pg_largeobject_loid - 1] = ObjectIdGetDatum(obj_desc->id);			values[Anum_pg_largeobject_pageno - 1] = Int32GetDatum(pageno);			values[Anum_pg_largeobject_data - 1] = PointerGetDatum(&workbuf);			newtup = heap_formtuple(lo_heap_r->rd_att, values, nulls);			simple_heap_insert(lo_heap_r, newtup);			CatalogIndexInsert(indstate, newtup);			heap_freetuple(newtup);		}		pageno++;	}	index_endscan(sd);	CatalogCloseIndexes(indstate);	/*	 * Advance command counter so that my tuple updates will be seen by later	 * large-object operations in this transaction.	 */	CommandCounterIncrement();	return nwritten;}

⌨️ 快捷键说明

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