Commit 1173344e authored by Tom Lane's avatar Tom Lane

Adjust WAL code so that checkpoints truncate the xlog at the previous

checkpoint's redo pointer, not its undo pointer, per discussion in
pghackers a few days ago.  No point in hanging onto undo information
until we have the ability to do something with it --- and this solves
a rather large problem with log space for long-running transactions.
Also, change all calls of write() to detect the case where write
returned a count less than requested, but failed to set errno.
Presume that this situation indicates ENOSPC, and give the appropriate
error message, rather than a random message associated with the previous
value of errno.
parent ce370eec
......@@ -155,9 +155,8 @@ int dbf_write_head(dbhead *dbh) {
put_short(head.dbh_hlen, dbh->db_hlen);
put_short(head.dbh_rlen, dbh->db_rlen);
if (write(dbh->db_fd, &head, sizeof(dbf_header)) == -1 ) {
if (write(dbh->db_fd, &head, sizeof(dbf_header)) != sizeof(dbf_header))
return DBF_ERROR;
}
return 0;
}
......@@ -180,14 +179,12 @@ int dbf_put_fields(dbhead *dbh) {
field.dbf_flen = dbh->db_fields[t].db_flen;
field.dbf_dec = dbh->db_fields[t].db_dec;
if (write(dbh->db_fd, &field, sizeof(dbf_field)) == -1) {
if (write(dbh->db_fd, &field, sizeof(dbf_field)) != sizeof(dbf_field))
return DBF_ERROR;
}
}
if (write(dbh->db_fd, &end, 1) == -1) {
if (write(dbh->db_fd, &end, 1) != 1)
return DBF_ERROR;
}
return 0;
}
......@@ -457,16 +454,14 @@ int dbf_put_record(dbhead *dbh, field *rec, u_long where) {
idx += rec[t].db_flen;
}
if (write(dbh->db_fd, data, dbh->db_rlen) == -1) {
if (write(dbh->db_fd, data, dbh->db_rlen) != dbh->db_rlen)
return DBF_ERROR;
}
/* There's a 0x1A at the end of a dbf-file */
if (where == dbh->db_records) {
if (write(dbh->db_fd, &end, 1) == -1) {
if (write(dbh->db_fd, &end, 1) != 1)
return DBF_ERROR;
}
}
dbh->db_offset += dbh->db_rlen;
......
......@@ -23,7 +23,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Header: /cvsroot/pgsql/contrib/pg_resetxlog/Attic/pg_resetxlog.c,v 1.4 2001/05/30 14:18:18 momjian Exp $
* $Header: /cvsroot/pgsql/contrib/pg_resetxlog/Attic/pg_resetxlog.c,v 1.5 2001/06/06 17:07:38 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -772,8 +772,12 @@ RewriteControlFile(void)
exit(1);
}
errno = 0;
if (write(fd, buffer, BLCKSZ) != BLCKSZ)
{
/* if write didn't set errno, assume problem is no disk space */
if (errno == 0)
errno = ENOSPC;
perror("RewriteControlFile failed to write pg_control file");
exit(1);
}
......@@ -884,8 +888,12 @@ WriteEmptyXLOG(void)
exit(1);
}
errno = 0;
if (write(fd, buffer, BLCKSZ) != BLCKSZ)
{
/* if write didn't set errno, assume problem is no disk space */
if (errno == 0)
errno = ENOSPC;
perror("WriteEmptyXLOG: failed to write xlog file");
exit(1);
}
......@@ -894,8 +902,11 @@ WriteEmptyXLOG(void)
memset(buffer, 0, BLCKSZ);
for (nbytes = BLCKSZ; nbytes < XLogSegSize; nbytes += BLCKSZ)
{
errno = 0;
if (write(fd, buffer, BLCKSZ) != BLCKSZ)
{
if (errno == 0)
errno = ENOSPC;
perror("WriteEmptyXLOG: failed to write xlog file");
exit(1);
}
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.68 2001/06/03 14:53:56 petere Exp $
* $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.69 2001/06/06 17:07:38 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -1068,9 +1068,15 @@ XLogWrite(XLogwrtRqst WriteRqst)
/* OK to write the page */
from = XLogCtl->pages + Write->curridx * BLCKSZ;
errno = 0;
if (write(openLogFile, from, BLCKSZ) != BLCKSZ)
{
/* if write didn't set errno, assume problem is no disk space */
if (errno == 0)
errno = ENOSPC;
elog(STOP, "write of log file %u, segment %u, offset %u failed: %m",
openLogId, openLogSeg, openLogOff);
}
openLogOff += BLCKSZ;
/*
......@@ -1323,6 +1329,7 @@ XLogFileInit(uint32 log, uint32 seg,
MemSet(zbuffer, 0, sizeof(zbuffer));
for (nbytes = 0; nbytes < XLogSegSize; nbytes += sizeof(zbuffer))
{
errno = 0;
if ((int) write(fd, zbuffer, sizeof(zbuffer)) != (int) sizeof(zbuffer))
{
int save_errno = errno;
......@@ -1332,7 +1339,8 @@ XLogFileInit(uint32 log, uint32 seg,
* space
*/
unlink(tmppath);
errno = save_errno;
/* if write didn't set errno, assume problem is no disk space */
errno = save_errno ? save_errno : ENOSPC;
elog(STOP, "ZeroFill failed to create or write %s: %m", tmppath);
}
......@@ -1990,8 +1998,14 @@ WriteControlFile(void)
elog(STOP, "WriteControlFile: could not create control file (%s): %m",
ControlFilePath);
errno = 0;
if (write(fd, buffer, BLCKSZ) != BLCKSZ)
{
/* if write didn't set errno, assume problem is no disk space */
if (errno == 0)
errno = ENOSPC;
elog(STOP, "WriteControlFile: write to control file failed: %m");
}
if (pg_fsync(fd) != 0)
elog(STOP, "WriteControlFile: fsync of control file failed: %m");
......@@ -2109,8 +2123,14 @@ UpdateControlFile(void)
if (fd < 0)
elog(STOP, "could not open control file (%s): %m", ControlFilePath);
errno = 0;
if (write(fd, ControlFile, sizeof(ControlFileData)) != sizeof(ControlFileData))
{
/* if write didn't set errno, assume problem is no disk space */
if (errno == 0)
errno = ENOSPC;
elog(STOP, "write to control file failed: %m");
}
if (pg_fsync(fd) != 0)
elog(STOP, "fsync of control file failed: %m");
......@@ -2248,8 +2268,14 @@ BootStrapXLOG(void)
use_existent = false;
openLogFile = XLogFileInit(0, 0, &use_existent, false);
errno = 0;
if (write(openLogFile, buffer, BLCKSZ) != BLCKSZ)
{
/* if write didn't set errno, assume problem is no disk space */
if (errno == 0)
errno = ENOSPC;
elog(STOP, "BootStrapXLOG failed to write log file: %m");
}
if (pg_fsync(openLogFile) != 0)
elog(STOP, "BootStrapXLOG failed to fsync log file: %m");
......@@ -2852,15 +2878,22 @@ CreateCheckPoint(bool shutdown)
elog(STOP, "concurrent transaction log activity while database system is shutting down");
/*
* Remember location of prior checkpoint's earliest info. Oldest item
* is redo or undo, whichever is older; but watch out for case that
* undo = 0.
* Select point at which we can truncate the log, which we base on the
* prior checkpoint's earliest info.
*
* With UNDO support: oldest item is redo or undo, whichever is older;
* but watch out for case that undo = 0.
*
* Without UNDO support: just use the redo pointer. This allows xlog
* space to be freed much faster when there are long-running transactions.
*/
#ifdef NOT_USED
if (ControlFile->checkPointCopy.undo.xrecoff != 0 &&
XLByteLT(ControlFile->checkPointCopy.undo,
ControlFile->checkPointCopy.redo))
XLByteToSeg(ControlFile->checkPointCopy.undo, _logId, _logSeg);
else
#endif
XLByteToSeg(ControlFile->checkPointCopy.redo, _logId, _logSeg);
/*
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/file/fd.c,v 1.79 2001/05/30 14:15:26 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/storage/file/fd.c,v 1.80 2001/06/06 17:07:46 tgl Exp $
*
* NOTES:
*
......@@ -865,7 +865,14 @@ FileWrite(File file, char *buffer, int amount)
VfdCache[file].seekPos, amount, buffer));
FileAccess(file);
errno = 0;
returnCode = write(VfdCache[file].fd, buffer, amount);
/* if write didn't set errno, assume problem is no disk space */
if (returnCode != amount && errno == 0)
errno = ENOSPC;
if (returnCode > 0)
VfdCache[file].seekPos += returnCode;
else
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/smgr/md.c,v 1.84 2001/05/10 20:38:49 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/storage/smgr/md.c,v 1.85 2001/06/06 17:07:46 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -582,8 +582,12 @@ mdblindwrt(RelFileNode rnode,
status = SM_SUCCESS;
/* write and optionally sync the block */
errno = 0;
if (write(fd, buffer, BLCKSZ) != BLCKSZ)
{
/* if write didn't set errno, assume problem is no disk space */
if (errno == 0)
errno = ENOSPC;
elog(DEBUG, "mdblindwrt: write() failed: %m");
status = SM_FAIL;
}
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.68 2001/06/01 20:27:41 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.69 2001/06/06 17:07:46 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -659,13 +659,15 @@ CreateLockFile(const char *filename, bool amPostmaster,
snprintf(buffer, sizeof(buffer), "%d\n%s\n",
amPostmaster ? (int) my_pid : -((int) my_pid),
DataDir);
errno = 0;
if (write(fd, buffer, strlen(buffer)) != strlen(buffer))
{
int save_errno = errno;
close(fd);
unlink(filename);
errno = save_errno;
/* if write didn't set errno, assume problem is no disk space */
errno = save_errno ? save_errno : ENOSPC;
elog(FATAL, "Can't write lock file %s: %m", filename);
}
close(fd);
......@@ -794,9 +796,13 @@ RecordSharedMemoryInLockFile(IpcMemoryKey shmKey, IpcMemoryId shmId)
* update should appear atomic to onlookers.
*/
len = strlen(buffer);
errno = 0;
if (lseek(fd, (off_t) 0, SEEK_SET) != 0 ||
(int) write(fd, buffer, len) != len)
{
/* if write didn't set errno, assume problem is no disk space */
if (errno == 0)
errno = ENOSPC;
elog(DEBUG, "Failed to write %s: %m", directoryLockFile);
close(fd);
return;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment