Class CrashSafeYamlFiles
@ConfigEntity files, framework state or credentials.
Why it cannot overwrite operator content. Existing-file writes own only the named complete key paths and reuse the configuration gate's plain-data, fingerprint, parse/render/reparse and unowned-byte checks. Every other byte (comments, unknown keys, BOM and line endings included) must stay unchanged or the edit is refused. Creation owns the whole file only while no directory entry exists. Neither method updates the caller's live objects.
Supported filesystems and metadata. These File-based methods (snapshots also originate from a
File) use the default filesystem. Publication requires ordinary files on a local default POSIX filesystem
with native atomic rename/link semantics, working POSIX attributes and an existing parent directory. An existing
final symlink is refused, not followed; parent links are resolved with filesystem semantics. Paths must be trusted
module paths, not unsanitized user input; this is not a path sandbox.
Existing files keep the nine POSIX permission bits, owner and group, applied and verified before commit; failure
aborts publication. Read-only targets are refused. New files use the process-created owner/group and mode 0600.
Staging is created exclusively at 0600 before any content and narrowed to 0000 before a required identity change.
Non-POSIX or a Java-exposed ACL view on parent/target/stage is refused. No ACLs are copied. Absence of an ACL view
does not establish absence of hidden ACLs/default ACLs, labels or xattrs. Do not adopt this API where preserving
those, special mode bits, alternate streams, inode identity, hard-link relationships, creation times or arbitrary
flags is required. Replacement uses a new inode; hard-link aliases retain old content. Unknown metadata has
replacement/new-file semantics; not every incompatible layout can be detected.
Commit and limits. Complete UTF-8 contents and promised metadata are forced with force(true) and
closed before atomic replacement, or exclusive native POSIX hard-link creation. Unsupported rename/link operations
fail without copy, ordinary-move, truncate or journal fallback. The POSIX link contract, not a blanket guarantee for
every NIO provider, underlies exclusive creation. With a functioning OS/filesystem a process crash leaves old/absent
or complete-new final content. Directory forcing after commit is best effort and warns on failure; WRITTEN is not
absolute power-loss durability. OS crashes, remote storage, filesystem recovery and device failure are outside this
guarantee. This is single-file publication, not a multi-file transaction.
Same-JVM gate writes serialize and recheck bytes/kind/promised metadata before commit. There is no cross-process
lock or guarantee against an external edit/rename/chmod in the final check-to-publication interval; do not share the
file with concurrent uncoordinated writers. No startup scan, journal, replay, promotion or rollback is performed.
Only the exact current invocation's known-file-key regular temp may be cleaned. A crash can leave a partial/complete
<name>.ultitools-stage-<32 lower-case hex>.tmp, or a second hard link after creation. Later calls leave it
alone. Stop competing writers/server, inspect the target and named temp, and never assume a temp is authoritative
or promote it automatically. Delete only one recognized as no longer needed; otherwise keep it and use an independently
trusted backup or explicit recreate action. Retained temps may contain new data under the declared final mode: protect
them like the YAML file. Legacy OperatorFiles.write(com.ultikits.ultitools.config.OperatorFiles.Snapshot, java.util.Map<java.util.List<java.lang.String>, java.lang.Object>) and internal writer defaults are unchanged.
- Since:
- 6.4.0
-
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionstatic OperatorFiles.WriteResultPublishes a complete validated root map only for an explicit operator create action, never replacing any existing entry.private static OperatorFiles.WriteResultoutcome(OperatorFileWriter.Result result) static OperatorFiles.WriteResultWrites only explicitly edited keys while the existing file still holds the snapshot's bytes.
-
Constructor Details
-
CrashSafeYamlFiles
private CrashSafeYamlFiles()
-
-
Method Details
-
write
public static OperatorFiles.WriteResult write(OperatorFiles.Snapshot readAt, Map<List<String>, Object> values) throws IOExceptionWrites only explicitly edited keys while the existing file still holds the snapshot's bytes. No unowned byte is authorized to change (see the class contract). Empty edits and semantic no-ops do not stage or change metadata.- Parameters:
readAt- snapshot fromOperatorFiles.read(File)on which the edit was decidedvalues- complete key paths to plain-data values; dots within a key are literal, null values are valid- Returns:
- WRITTEN, UNCHANGED, FILE_CHANGED (including a missing target), or REFUSED with a value-free warning
- Throws:
IllegalArgumentException- for null arguments, null/empty key paths, null keys or non-plain values, before I/OIOException- if staging, promised metadata or publication fails before commit; no new bytes are published
-
create
public static OperatorFiles.WriteResult create(File file, Map<String, Object> values) throws IOExceptionPublishes a complete validated root map only for an explicit operator create action, never replacing any existing entry. This is why whole-file ownership cannot overwrite operator content. The parent must already exist.- Parameters:
file- trusted destination on the default local POSIX filesystemvalues- complete plain-data root map; whole literal keys, nullable values, empty map allowed- Returns:
- WRITTEN, FILE_CHANGED if an entry already exists/appears, or REFUSED; never UNCHANGED
- Throws:
IllegalArgumentException- for null arguments/keys or non-plain data, before I/OIOException- if staging, metadata, parent resolution or native link publication fails before commit
-
outcome
-