Fence installation transaction durability (T-613)
This commit is contained in:
@@ -66,6 +66,14 @@ func (record transactionRecord) validate() error {
|
||||
}
|
||||
|
||||
func writeTransaction(layout appLayout, record transactionRecord) error {
|
||||
return writeTransactionWithFence(layout, record, defaultDurability())
|
||||
}
|
||||
|
||||
func writeTransactionWithFence(
|
||||
layout appLayout,
|
||||
record transactionRecord,
|
||||
fence durabilityFence,
|
||||
) error {
|
||||
if err := record.validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -79,6 +87,7 @@ func writeTransaction(layout appLayout, record transactionRecord) error {
|
||||
layout.transaction,
|
||||
layout.transactionBackup,
|
||||
data,
|
||||
fence,
|
||||
); err != nil {
|
||||
return fmt.Errorf("write install transaction: %w", err)
|
||||
}
|
||||
@@ -135,11 +144,23 @@ func ensureJSONEOF(decoder *json.Decoder) error {
|
||||
}
|
||||
|
||||
func removeTransaction(layout appLayout) error {
|
||||
return removeTransactionWithFence(layout, defaultDurability())
|
||||
}
|
||||
|
||||
func removeTransactionWithFence(layout appLayout, fence durabilityFence) error {
|
||||
removed := false
|
||||
if err := os.Remove(layout.transaction); err != nil && !os.IsNotExist(err) {
|
||||
return fmt.Errorf("remove install transaction: %w", err)
|
||||
} else if err == nil {
|
||||
removed = true
|
||||
}
|
||||
if err := os.Remove(layout.transactionBackup); err != nil && !os.IsNotExist(err) {
|
||||
return fmt.Errorf("remove install transaction backup: %w", err)
|
||||
} else if err == nil {
|
||||
removed = true
|
||||
}
|
||||
if removed {
|
||||
return syncDirectoryWithFence(fence, layout.root, "app root after transaction removal")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -149,6 +170,7 @@ func replaceFileWithBackup(
|
||||
target string,
|
||||
backup string,
|
||||
data []byte,
|
||||
fence durabilityFence,
|
||||
) error {
|
||||
temporary, err := os.CreateTemp(directory, ".install-transaction-*.tmp")
|
||||
if err != nil {
|
||||
@@ -165,7 +187,7 @@ func replaceFileWithBackup(
|
||||
temporary.Close()
|
||||
return err
|
||||
}
|
||||
if err := temporary.Sync(); err != nil {
|
||||
if err := syncFileWithFence(fence, temporary, "temporary install transaction"); err != nil {
|
||||
temporary.Close()
|
||||
return err
|
||||
}
|
||||
@@ -178,12 +200,19 @@ func replaceFileWithBackup(
|
||||
if info.Mode()&os.ModeSymlink != 0 || !info.Mode().IsRegular() {
|
||||
return fmt.Errorf("%w: transaction target is not a regular file", ErrUnsafeInstallLayout)
|
||||
}
|
||||
if err := os.Remove(backup); err != nil && !os.IsNotExist(err) {
|
||||
if err := os.Remove(backup); err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
} else if err := syncDirectoryWithFence(fence, directory, "app root after stale transaction backup removal"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.Rename(target, backup); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := syncDirectoryWithFence(fence, directory, "app root after transaction backup rename"); err != nil {
|
||||
return err
|
||||
}
|
||||
movedTarget = true
|
||||
} else if !os.IsNotExist(err) {
|
||||
return err
|
||||
@@ -191,14 +220,22 @@ func replaceFileWithBackup(
|
||||
|
||||
if err := os.Rename(temporaryPath, target); err != nil {
|
||||
if movedTarget {
|
||||
_ = os.Rename(backup, target)
|
||||
if restoreErr := os.Rename(backup, target); restoreErr == nil {
|
||||
_ = syncDirectoryWithFence(fence, directory, "app root after transaction restore")
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
if err := syncDirectoryWithFence(fence, directory, "app root after transaction replace"); err != nil {
|
||||
return err
|
||||
}
|
||||
if movedTarget {
|
||||
if err := os.Remove(backup); err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
if err := syncDirectoryWithFence(fence, directory, "app root after transaction backup removal"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user