summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBlake Rouse <blake.rouse@canonical.com>2014-09-05 11:55:14 -0400
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>2014-12-25 15:06:18 +0100
commite13ec67da393480e7cec408f94f21a8e9d266bc3 (patch)
treed0df10d7ce93d0fce594f6467a283e35934447b8
parent85ba098cd84a983b816d2dbdf7ec741c4f93ec75 (diff)
downloadpsycopg2-e13ec67da393480e7cec408f94f21a8e9d266bc3.tar.gz
Use lseek64 and ltell64 to support large object greater than 2gb in size.
-rw-r--r--psycopg/lobject.h4
-rw-r--r--psycopg/lobject_int.c20
-rw-r--r--psycopg/lobject_type.c14
-rwxr-xr-xtests/test_lobject.py18
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()