* Shared functionality between saving and creating a replication slot. */
| 1527 | * Shared functionality between saving and creating a replication slot. |
| 1528 | */ |
| 1529 | static void |
| 1530 | SaveSlotToPath(ReplicationSlot *slot, const char *dir, int elevel) |
| 1531 | { |
| 1532 | char tmppath[MAXPGPATH]; |
| 1533 | char path[MAXPGPATH]; |
| 1534 | int fd; |
| 1535 | ReplicationSlotOnDisk cp; |
| 1536 | bool was_dirty; |
| 1537 | |
| 1538 | /* first check whether there's something to write out */ |
| 1539 | SpinLockAcquire(&slot->mutex); |
| 1540 | was_dirty = slot->dirty; |
| 1541 | slot->just_dirtied = false; |
| 1542 | SpinLockRelease(&slot->mutex); |
| 1543 | |
| 1544 | /* and don't do anything if there's nothing to write */ |
| 1545 | if (!was_dirty) |
| 1546 | return; |
| 1547 | |
| 1548 | LWLockAcquire(&slot->io_in_progress_lock, LW_EXCLUSIVE); |
| 1549 | |
| 1550 | /* silence valgrind :( */ |
| 1551 | memset(&cp, 0, sizeof(ReplicationSlotOnDisk)); |
| 1552 | |
| 1553 | snprintf(tmppath, sizeof(tmppath), "%s/state.tmp", dir); |
| 1554 | snprintf(path, sizeof(path), "%s/state", dir); |
| 1555 | |
| 1556 | fd = OpenTransientFile(tmppath, O_CREAT | O_EXCL | O_WRONLY | PG_BINARY); |
| 1557 | if (fd < 0) |
| 1558 | { |
| 1559 | /* |
| 1560 | * If not an ERROR, then release the lock before returning. In case |
| 1561 | * of an ERROR, the error recovery path automatically releases the |
| 1562 | * lock, but no harm in explicitly releasing even in that case. Note |
| 1563 | * that LWLockRelease() could affect errno. |
| 1564 | */ |
| 1565 | int save_errno = errno; |
| 1566 | |
| 1567 | LWLockRelease(&slot->io_in_progress_lock); |
| 1568 | errno = save_errno; |
| 1569 | ereport(elevel, |
| 1570 | (errcode_for_file_access(), |
| 1571 | errmsg("could not create file \"%s\": %m", |
| 1572 | tmppath))); |
| 1573 | return; |
| 1574 | } |
| 1575 | |
| 1576 | cp.magic = SLOT_MAGIC; |
| 1577 | INIT_CRC32C(cp.checksum); |
| 1578 | cp.version = SLOT_VERSION; |
| 1579 | cp.length = ReplicationSlotOnDiskV2Size; |
| 1580 | |
| 1581 | SpinLockAcquire(&slot->mutex); |
| 1582 | |
| 1583 | memcpy(&cp.slotdata, &slot->data, sizeof(ReplicationSlotPersistentData)); |
| 1584 | |
| 1585 | SpinLockRelease(&slot->mutex); |
| 1586 |
no test coverage detected