Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita62d839

Browse files
committed
Repair Large Object bugs demonstrated by Ian Grant's example. inv_write
was inappropriately relying on rel->rd_nblocks to tell if the LO isempty (apparently a hack to get around a long-dead index bug), causingmisbehavior on a written-but-never-vacuumed LO. Also, inv_read failedto cope gracefully with 'holes' (unwritten regions) in the object.
1 parent946e80c commita62d839

File tree

1 file changed

+33
-23
lines changed

1 file changed

+33
-23
lines changed

‎src/backend/storage/large_object/inv_api.c

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.69 2000/06/0507:28:45 tgl Exp $
12+
* $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.70 2000/06/15 06:07:34 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -187,6 +187,7 @@ inv_create(int flags)
187187
retval->idesc=RelationGetDescr(indr);
188188
retval->offset=retval->lowbyte=retval->highbyte=0;
189189
ItemPointerSetInvalid(&(retval->htid));
190+
retval->flags=0;
190191

191192
if (flags&INV_WRITE)
192193
{
@@ -198,7 +199,7 @@ inv_create(int flags)
198199
LockRelation(r,ShareLock);
199200
retval->flags=IFS_RDLOCK;
200201
}
201-
retval->flags |=IFS_ATEOF;
202+
retval->flags |=IFS_ATEOF;/* since we know the object is empty */
202203

203204
returnretval;
204205
}
@@ -235,6 +236,7 @@ inv_open(Oid lobjId, int flags)
235236
retval->idesc=RelationGetDescr(indrel);
236237
retval->offset=retval->lowbyte=retval->highbyte=0;
237238
ItemPointerSetInvalid(&(retval->htid));
239+
retval->flags=0;
238240

239241
if (flags&INV_WRITE)
240242
{
@@ -373,14 +375,8 @@ inv_seek(LargeObjectDesc *obj_desc, int offset, int whence)
373375
if (whence==SEEK_CUR)
374376
{
375377
offset+=obj_desc->offset;/* calculate absolute position */
376-
returninv_seek(obj_desc,offset,SEEK_SET);
377378
}
378-
379-
/*
380-
* if you seek past the end (offset > 0) I have no clue what happens
381-
* :-( B.L. 9/1/93
382-
*/
383-
if (whence==SEEK_END)
379+
elseif (whence==SEEK_END)
384380
{
385381
/* need read lock for getsize */
386382
if (!(obj_desc->flags&IFS_RDLOCK))
@@ -391,8 +387,8 @@ inv_seek(LargeObjectDesc *obj_desc, int offset, int whence)
391387
offset+=_inv_getsize(obj_desc->heap_r,
392388
obj_desc->hdesc,
393389
obj_desc->index_r);
394-
returninv_seek(obj_desc,offset,SEEK_SET);
395390
}
391+
/* now we can assume that the operation is SEEK_SET */
396392

397393
/*
398394
* Whenever we do a seek, we turn off the EOF flag bit to force
@@ -416,17 +412,13 @@ inv_seek(LargeObjectDesc *obj_desc, int offset, int whence)
416412
* stores the offset of the last byte that appears on it, and we have
417413
* an index on this.
418414
*/
419-
420-
421-
/* right now, just assume that the operation is SEEK_SET */
422415
if (obj_desc->iscan!= (IndexScanDesc)NULL)
423416
{
424417
d=Int32GetDatum(offset);
425418
btmovescan(obj_desc->iscan,d);
426419
}
427420
else
428421
{
429-
430422
ScanKeyEntryInitialize(&skey,0x0,1,F_INT4GE,
431423
Int32GetDatum(offset));
432424

@@ -489,9 +481,27 @@ inv_read(LargeObjectDesc *obj_desc, char *buf, int nbytes)
489481

490482
/* copy the data from this block into the buffer */
491483
d=heap_getattr(&tuple,2,obj_desc->hdesc,&isNull);
484+
fsblock= (structvarlena*)DatumGetPointer(d);
492485
ReleaseBuffer(buffer);
493486

494-
fsblock= (structvarlena*)DatumGetPointer(d);
487+
/*
488+
* If block starts beyond current seek point, then we are looking
489+
* at a "hole" (unwritten area) in the object. Return zeroes for
490+
* the "hole".
491+
*/
492+
if (obj_desc->offset<obj_desc->lowbyte)
493+
{
494+
intnzeroes=obj_desc->lowbyte-obj_desc->offset;
495+
496+
if (nzeroes> (nbytes-nread))
497+
nzeroes= (nbytes-nread);
498+
MemSet(buf,0,nzeroes);
499+
buf+=nzeroes;
500+
nread+=nzeroes;
501+
obj_desc->offset+=nzeroes;
502+
if (nread >=nbytes)
503+
break;
504+
}
495505

496506
off=obj_desc->offset-obj_desc->lowbyte;
497507
ncopy=obj_desc->highbyte-obj_desc->offset+1;
@@ -537,14 +547,11 @@ inv_write(LargeObjectDesc *obj_desc, char *buf, int nbytes)
537547
Bufferbuffer;
538548

539549
/*
540-
* Fetch the current inversion file system block. If the class
541-
* storing the inversion file is empty, we don't want to do an
542-
* index lookup, since index lookups choke on empty files (should
543-
* be fixed someday).
550+
* Fetch the current inversion file system block. We can skip
551+
* the work if we already know we are at EOF.
544552
*/
545553

546-
if ((obj_desc->flags&IFS_ATEOF)
547-
||obj_desc->heap_r->rd_nblocks==0)
554+
if (obj_desc->flags&IFS_ATEOF)
548555
tuple.t_data=NULL;
549556
else
550557
inv_fetchtup(obj_desc,&tuple,&buffer);
@@ -659,6 +666,7 @@ inv_fetchtup(LargeObjectDesc *obj_desc, HeapTuple tuple, Buffer *buffer)
659666
}
660667
else
661668
index_rescan(obj_desc->iscan, false,&skey);
669+
662670
do
663671
{
664672
res=index_getnext(obj_desc->iscan,ForwardScanDirection);
@@ -1149,7 +1157,8 @@ inv_indextup(LargeObjectDesc *obj_desc, HeapTuple tuple)
11491157
pfree(res);
11501158
}
11511159

1152-
/*
1160+
#ifdefNOT_USED
1161+
11531162
staticvoid
11541163
DumpPage(Pagepage,intblkno)
11551164
{
@@ -1239,7 +1248,8 @@ ItemPointerFormExternal(ItemPointer pointer)
12391248

12401249
returnitemPointerString;
12411250
}
1242-
*/
1251+
1252+
#endif
12431253

12441254
staticint
12451255
_inv_getsize(Relationhreln,TupleDeschdesc,Relationireln)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp