* 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. */
| 242 | * No need for an error return convention; we ereport() on any error. |
| 243 | */ |
| 244 | static void |
| 245 | ltsWriteBlock(LogicalTapeSet *lts, long blocknum, void *buffer) |
| 246 | { |
| 247 | /* |
| 248 | * BufFile does not support "holes", so if we're about to write a block |
| 249 | * that's past the current end of file, fill the space between the current |
| 250 | * end of file and the target block with zeros. |
| 251 | * |
| 252 | * This can happen either when tapes preallocate blocks; or for the last |
| 253 | * block of a tape which might not have been flushed. |
| 254 | * |
| 255 | * Note that BufFile concatenation can leave "holes" in BufFile between |
| 256 | * worker-owned block ranges. These are tracked for reporting purposes |
| 257 | * only. We never read from nor write to these hole blocks, and so they |
| 258 | * are not considered here. |
| 259 | */ |
| 260 | while (blocknum > lts->nBlocksWritten) |
| 261 | { |
| 262 | PGAlignedBlock zerobuf; |
| 263 | |
| 264 | MemSet(zerobuf.data, 0, sizeof(zerobuf)); |
| 265 | |
| 266 | ltsWriteBlock(lts, lts->nBlocksWritten, zerobuf.data); |
| 267 | } |
| 268 | |
| 269 | /* Write the requested block */ |
| 270 | if (BufFileSeekBlock(lts->pfile, blocknum) != 0) |
| 271 | ereport(ERROR, |
| 272 | (errcode_for_file_access(), |
| 273 | errmsg("could not seek to block %ld of temporary file", |
| 274 | blocknum))); |
| 275 | BufFileWrite(lts->pfile, buffer, BLCKSZ); |
| 276 | |
| 277 | /* Update nBlocksWritten, if we extended the file */ |
| 278 | if (blocknum == lts->nBlocksWritten) |
| 279 | lts->nBlocksWritten++; |
| 280 | } |
| 281 | |
| 282 | /* |
| 283 | * Read a block-sized buffer from the specified block of the underlying file. |
no test coverage detected