Improve the treatment of partial(incomplete) blocks of relation files.
authorHiroshi Inoue
Wed, 6 Oct 1999 06:38:04 +0000 (06:38 +0000)
committerHiroshi Inoue
Wed, 6 Oct 1999 06:38:04 +0000 (06:38 +0000)
This may solve a TODO item
* Recover or force failure when disk space is exhausted

src/backend/storage/smgr/md.c

index a2c102145b88c23a4c2c5e35c61679a1bc6093ee..6d8425c4bd6f2d29951beec832cd935f66cf5e6c 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/storage/smgr/md.c,v 1.55 1999/09/28 11:41:07 vadim Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/storage/smgr/md.c,v 1.56 1999/10/06 06:38:04 inoue Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -233,7 +233,7 @@ mdunlink(Relation reln)
 int
 mdextend(Relation reln, char *buffer)
 {
-   long        pos;
+   long        pos, nbytes;
    int         nblocks;
    MdfdVec    *v;
 
@@ -243,8 +243,22 @@ mdextend(Relation reln, char *buffer)
    if ((pos = FileSeek(v->mdfd_vfd, 0L, SEEK_END)) < 0)
        return SM_FAIL;
 
-   if (FileWrite(v->mdfd_vfd, buffer, BLCKSZ) != BLCKSZ)
+   if (pos % BLCKSZ != 0) /* the last block is incomplete */
+   {
+       pos -= pos % BLCKSZ;
+       if (FileSeek(v->mdfd_vfd, pos, SEEK_SET) < 0)
+           return SM_FAIL;
+   }
+
+   if ((nbytes = FileWrite(v->mdfd_vfd, buffer, BLCKSZ)) != BLCKSZ)
+   {
+       if (nbytes > 0)
+       {
+           FileTruncate(v->mdfd_vfd, pos);
+           FileSeek(v->mdfd_vfd, pos, SEEK_SET);
+       }
        return SM_FAIL;
+   }
 
    /* remember that we did a write, so we can sync at xact commit */
    v->mdfd_flags |= MDFD_DIRTY;
@@ -432,6 +446,8 @@ mdread(Relation reln, BlockNumber blocknum, char *buffer)
    {
        if (nbytes == 0)
            MemSet(buffer, 0, BLCKSZ);
+       else if (blocknum == 0 && nbytes > 0 && mdnblocks(reln) == 0)
+           MemSet(buffer, 0, BLCKSZ);
        else
            status = SM_FAIL;
    }
@@ -1067,6 +1083,7 @@ _mdnblocks(File file, Size blcksz)
 {
    long        len;
 
-   len = FileSeek(file, 0L, SEEK_END) - 1;
-   return (BlockNumber) ((len < 0) ? 0 : 1 + len / blcksz);
+   len = FileSeek(file, 0L, SEEK_END);
+   if (len < 0) return 0;  /* on failure, assume file is empty */
+   return (BlockNumber) (len / blcksz);
 }