1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-06 07:49:08 +03:00

Add API for 64-bit large object access. Now users can access up to

4TB large objects (standard 8KB BLCKSZ case).  For this purpose new
libpq API lo_lseek64, lo_tell64 and lo_truncate64 are added.  Also
corresponding new backend functions lo_lseek64, lo_tell64 and
lo_truncate64 are added. inv_api.c is changed to handle 64-bit
offsets.

Patch contributed by Nozomi Anzai (backend side) and Yugo Nagata
(frontend side, docs, regression tests and example program). Reviewed
by Kohei Kaigai. Committed by Tatsuo Ishii with minor editings.
This commit is contained in:
Tatsuo Ishii
2012-10-07 08:36:48 +09:00
parent ae835c7d6e
commit 461ef73f09
16 changed files with 856 additions and 32 deletions

View File

@@ -324,10 +324,10 @@ inv_drop(Oid lobjId)
* NOTE: LOs can contain gaps, just like Unix files. We actually return
* the offset of the last byte + 1.
*/
static uint32
static uint64
inv_getsize(LargeObjectDesc *obj_desc)
{
uint32 lastbyte = 0;
uint64 lastbyte = 0;
ScanKeyData skey[1];
SysScanDesc sd;
HeapTuple tuple;
@@ -368,7 +368,7 @@ inv_getsize(LargeObjectDesc *obj_desc)
heap_tuple_untoast_attr((struct varlena *) datafield);
pfreeit = true;
}
lastbyte = data->pageno * LOBLKSIZE + getbytealen(datafield);
lastbyte = (uint64) data->pageno * LOBLKSIZE + getbytealen(datafield);
if (pfreeit)
pfree(datafield);
}
@@ -378,30 +378,31 @@ inv_getsize(LargeObjectDesc *obj_desc)
return lastbyte;
}
int
inv_seek(LargeObjectDesc *obj_desc, int offset, int whence)
int64
inv_seek(LargeObjectDesc *obj_desc, int64 offset, int whence)
{
Assert(PointerIsValid(obj_desc));
switch (whence)
{
case SEEK_SET:
if (offset < 0)
elog(ERROR, "invalid seek offset: %d", offset);
if (offset < 0 || offset >= MAX_LARGE_OBJECT_SIZE)
elog(ERROR, "invalid seek offset: " INT64_FORMAT, offset);
obj_desc->offset = offset;
break;
case SEEK_CUR:
if (offset < 0 && obj_desc->offset < ((uint32) (-offset)))
elog(ERROR, "invalid seek offset: %d", offset);
if ((offset + obj_desc->offset) < 0 ||
(offset + obj_desc->offset) >= MAX_LARGE_OBJECT_SIZE)
elog(ERROR, "invalid seek offset: " INT64_FORMAT, offset);
obj_desc->offset += offset;
break;
case SEEK_END:
{
uint32 size = inv_getsize(obj_desc);
int64 pos = inv_getsize(obj_desc) + offset;
if (offset < 0 && size < ((uint32) (-offset)))
elog(ERROR, "invalid seek offset: %d", offset);
obj_desc->offset = size + offset;
if (pos < 0 || pos >= MAX_LARGE_OBJECT_SIZE)
elog(ERROR, "invalid seek offset: " INT64_FORMAT, offset);
obj_desc->offset = pos;
}
break;
default:
@@ -410,7 +411,7 @@ inv_seek(LargeObjectDesc *obj_desc, int offset, int whence)
return obj_desc->offset;
}
int
int64
inv_tell(LargeObjectDesc *obj_desc)
{
Assert(PointerIsValid(obj_desc));
@@ -422,11 +423,11 @@ int
inv_read(LargeObjectDesc *obj_desc, char *buf, int nbytes)
{
int nread = 0;
int n;
int off;
int64 n;
int64 off;
int len;
int32 pageno = (int32) (obj_desc->offset / LOBLKSIZE);
uint32 pageoff;
uint64 pageoff;
ScanKeyData skey[2];
SysScanDesc sd;
HeapTuple tuple;
@@ -437,6 +438,9 @@ inv_read(LargeObjectDesc *obj_desc, char *buf, int nbytes)
if (nbytes <= 0)
return 0;
if ((nbytes + obj_desc->offset) > MAX_LARGE_OBJECT_SIZE)
elog(ERROR, "invalid read request size: %d", nbytes);
open_lo_relation();
ScanKeyInit(&skey[0],
@@ -467,7 +471,7 @@ inv_read(LargeObjectDesc *obj_desc, char *buf, int nbytes)
* 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;
pageoff = ((uint64) data->pageno) * LOBLKSIZE;
if (pageoff > obj_desc->offset)
{
n = pageoff - obj_desc->offset;
@@ -560,6 +564,9 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes)
if (nbytes <= 0)
return 0;
if ((nbytes + obj_desc->offset) > MAX_LARGE_OBJECT_SIZE)
elog(ERROR, "invalid write request size: %d", nbytes);
open_lo_relation();
indstate = CatalogOpenIndexes(lo_heap_r);
@@ -718,10 +725,10 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes)
}
void
inv_truncate(LargeObjectDesc *obj_desc, int len)
inv_truncate(LargeObjectDesc *obj_desc, int64 len)
{
int32 pageno = (int32) (len / LOBLKSIZE);
int off;
int32 off;
ScanKeyData skey[2];
SysScanDesc sd;
HeapTuple oldtuple;