/* * Read a block-sized buffer from the specified block of the underlying file. * * No need for an error return convention; we ereport() on any error. This * module should never attempt to read a block it doesn't know is there. */ static void ltsReadBlock(LogicalTapeSet *lts, long blocknum, void *buffer) { if (BufFileSeekBlock(lts->pfile, blocknum) != 0 || BufFileRead(lts->pfile, buffer, BLCKSZ) != BLCKSZ) ereport(ERROR, (errcode_for_file_access(), errmsg("could not read block %ld of temporary file: %m", blocknum))); }
/* * Write a block-sized buffer to the specified block of the underlying file. * * NB: should not attempt to write beyond current end of file (ie, create * "holes" in file), since BufFile doesn't allow that. The first write pass * must write blocks sequentially. * * No need for an error return convention; we ereport() on any error. */ static void ltsWriteBlock(LogicalTapeSet *lts, long blocknum, void *buffer) { if (BufFileSeekBlock(lts->pfile, blocknum) != 0 || BufFileWrite(lts->pfile, buffer, BLCKSZ) != BLCKSZ) ereport(ERROR, /* XXX is it okay to assume errno is correct? */ (errcode_for_file_access(), errmsg("could not write block %ld of temporary file: %m", blocknum), errhint("Perhaps out of disk space?"))); }
/* * Write a block-sized buffer to the specified block of the underlying file. * * No need for an error return convention; we ereport() on any error. */ static void ltsWriteBlock(LogicalTapeSet *lts, long blocknum, void *buffer) { /* * BufFile does not support "holes", so if we're about to write a block * that's past the current end of file, fill the space between the current * end of file and the target block with zeros. * * This should happen rarely, otherwise you are not writing very * sequentially. In current use, this only happens when the sort ends * writing a run, and switches to another tape. The last block of the * previous tape isn't flushed to disk until the end of the sort, so you * get one-block hole, where the last block of the previous tape will * later go. * * Note that BufFile concatenation can leave "holes" in BufFile between * worker-owned block ranges. These are tracked for reporting purposes * only. We never read from nor write to these hole blocks, and so they * are not considered here. */ while (blocknum > lts->nBlocksWritten) { PGAlignedBlock zerobuf; MemSet(zerobuf.data, 0, sizeof(zerobuf)); ltsWriteBlock(lts, lts->nBlocksWritten, zerobuf.data); } /* Write the requested block */ if (BufFileSeekBlock(lts->pfile, blocknum) != 0 || BufFileWrite(lts->pfile, buffer, BLCKSZ) != BLCKSZ) ereport(ERROR, (errcode_for_file_access(), errmsg("could not write block %ld of temporary file: %m", blocknum))); /* Update nBlocksWritten, if we extended the file */ if (blocknum == lts->nBlocksWritten) lts->nBlocksWritten++; }