diff options
author | Blake Rouse <blake.rouse@canonical.com> | 2014-09-05 11:55:14 -0400 |
---|---|---|
committer | Daniele Varrazzo <daniele.varrazzo@gmail.com> | 2014-12-25 15:06:18 +0100 |
commit | e13ec67da393480e7cec408f94f21a8e9d266bc3 (patch) | |
tree | d0df10d7ce93d0fce594f6467a283e35934447b8 | |
parent | 85ba098cd84a983b816d2dbdf7ec741c4f93ec75 (diff) | |
download | psycopg2-e13ec67da393480e7cec408f94f21a8e9d266bc3.tar.gz |
Use lseek64 and ltell64 to support large object greater than 2gb in size.
-rw-r--r-- | psycopg/lobject.h | 4 | ||||
-rw-r--r-- | psycopg/lobject_int.c | 20 | ||||
-rw-r--r-- | psycopg/lobject_type.c | 14 | ||||
-rwxr-xr-x | tests/test_lobject.py | 18 |
4 files changed, 37 insertions, 19 deletions
diff --git a/psycopg/lobject.h b/psycopg/lobject.h index 56f9ead..b9c8c3d 100644 --- a/psycopg/lobject.h +++ b/psycopg/lobject.h @@ -60,8 +60,8 @@ RAISES_NEG HIDDEN int lobject_export(lobjectObject *self, const char *filename); RAISES_NEG HIDDEN Py_ssize_t lobject_read(lobjectObject *self, char *buf, size_t len); RAISES_NEG HIDDEN Py_ssize_t lobject_write(lobjectObject *self, const char *buf, size_t len); -RAISES_NEG HIDDEN int lobject_seek(lobjectObject *self, int pos, int whence); -RAISES_NEG HIDDEN int lobject_tell(lobjectObject *self); +RAISES_NEG HIDDEN long lobject_seek(lobjectObject *self, long pos, int whence); +RAISES_NEG HIDDEN long lobject_tell(lobjectObject *self); RAISES_NEG HIDDEN int lobject_truncate(lobjectObject *self, size_t len); RAISES_NEG HIDDEN int lobject_close(lobjectObject *self); diff --git a/psycopg/lobject_int.c b/psycopg/lobject_int.c index 21b1e18..731d3da 100644 --- a/psycopg/lobject_int.c +++ b/psycopg/lobject_int.c @@ -376,21 +376,21 @@ lobject_read(lobjectObject *self, char *buf, size_t len) /* lobject_seek - move the current position in the lo */ -RAISES_NEG int -lobject_seek(lobjectObject *self, int pos, int whence) +RAISES_NEG long +lobject_seek(lobjectObject *self, long pos, int whence) { PGresult *pgres = NULL; char *error = NULL; - int where; + long where; - Dprintf("lobject_seek: fd = %d, pos = %d, whence = %d", + Dprintf("lobject_seek: fd = %d, pos = %Ld, whence = %d", self->fd, pos, whence); Py_BEGIN_ALLOW_THREADS; pthread_mutex_lock(&(self->conn->lock)); - where = lo_lseek(self->conn->pgconn, self->fd, pos, whence); - Dprintf("lobject_seek: where = %d", where); + where = lo_lseek64(self->conn->pgconn, self->fd, pos, whence); + Dprintf("lobject_seek: where = %Ld", where); if (where < 0) collect_error(self->conn, &error); @@ -404,20 +404,20 @@ lobject_seek(lobjectObject *self, int pos, int whence) /* lobject_tell - tell the current position in the lo */ -RAISES_NEG int +RAISES_NEG long lobject_tell(lobjectObject *self) { PGresult *pgres = NULL; char *error = NULL; - int where; + long where; Dprintf("lobject_tell: fd = %d", self->fd); Py_BEGIN_ALLOW_THREADS; pthread_mutex_lock(&(self->conn->lock)); - where = lo_tell(self->conn->pgconn, self->fd); - Dprintf("lobject_tell: where = %d", where); + where = lo_tell64(self->conn->pgconn, self->fd); + Dprintf("lobject_tell: where = %Ld", where); if (where < 0) collect_error(self->conn, &error); diff --git a/psycopg/lobject_type.c b/psycopg/lobject_type.c index ef442f9..ba27e4f 100644 --- a/psycopg/lobject_type.c +++ b/psycopg/lobject_type.c @@ -121,7 +121,7 @@ static PyObject * psyco_lobj_read(lobjectObject *self, PyObject *args) { PyObject *res; - int where, end; + long where, end; Py_ssize_t size = -1; char *buffer; @@ -165,10 +165,10 @@ psyco_lobj_read(lobjectObject *self, PyObject *args) static PyObject * psyco_lobj_seek(lobjectObject *self, PyObject *args) { - int offset, whence=0; - int pos=0; + long offset, pos=0; + int whence=0; - if (!PyArg_ParseTuple(args, "i|i", &offset, &whence)) + if (!PyArg_ParseTuple(args, "l|i", &offset, &whence)) return NULL; EXC_IF_LOBJ_CLOSED(self); @@ -178,7 +178,7 @@ psyco_lobj_seek(lobjectObject *self, PyObject *args) if ((pos = lobject_seek(self, offset, whence)) < 0) return NULL; - return PyInt_FromLong((long)pos); + return PyLong_FromLong(pos); } /* tell method - tell current position in the lobject */ @@ -189,7 +189,7 @@ psyco_lobj_seek(lobjectObject *self, PyObject *args) static PyObject * psyco_lobj_tell(lobjectObject *self, PyObject *args) { - int pos; + long pos; EXC_IF_LOBJ_CLOSED(self); EXC_IF_LOBJ_LEVEL0(self); @@ -198,7 +198,7 @@ psyco_lobj_tell(lobjectObject *self, PyObject *args) if ((pos = lobject_tell(self)) < 0) return NULL; - return PyInt_FromLong((long)pos); + return PyLong_FromLong(pos); } /* unlink method - unlink (destroy) the lobject */ diff --git a/tests/test_lobject.py b/tests/test_lobject.py index 66a3d8a..36b2427 100755 --- a/tests/test_lobject.py +++ b/tests/test_lobject.py @@ -225,6 +225,24 @@ class LargeObjectTests(LargeObjectTestCase): self.assertEqual(lo.seek(-2, 2), length - 2) self.assertEqual(lo.read(), "ta") + def test_seek_tell_greater_than_2gb(self): + lo = self.conn.lobject() + + # write chunks until its 3gb + length = 0 + for _ in range(24): + # each chunk is written with 128mb + length += lo.write("data" * (1 << 25)) + self.assertEqual(lo.tell(), length) + lo.close() + lo = self.conn.lobject(lo.oid) + + # seek to 3gb - 4, last written text should be data + offset = (1 << 31) + (1 << 30) - 4 # 2gb + 1gb - 4 + self.assertEqual(lo.seek(offset, 0), offset) + self.assertEqual(lo.tell(), offset) + self.assertEqual(lo.read(), "data") + def test_unlink(self): lo = self.conn.lobject() lo.unlink() |