Skip to main content

EditSession

Struct EditSession 

Source
pub struct EditSession { /* private fields */ }
Expand description

An open HDF5 file being edited in place.

Mirror the file in memory and keep a writable handle; every mutation is applied to both so the on-disk file stays consistent. Stage additions with create_dataset / create_group, value overwrites with write_dataset, and group attribute edits with set_group_attr / remove_group_attr, then apply them with commit.

§Example

use hdf5_pure::{AttrValue, EditSession};

let mut session = EditSession::open("existing.h5")?;
session.create_group("run2");
session.set_group_attr("run2", "kind", AttrValue::AsciiString("trial".into()));
session
    .create_dataset("run2/signal")
    .with_f64_data(&[1.0, 2.0, 3.0]);
session.commit()?;

Implementations§

Source§

impl EditSession

Source

pub fn open<P: AsRef<Path>>(path: P) -> Result<Self, Error>

Open an existing HDF5 file for in-place editing.

Reads the file into memory and retains a read/write handle. Takes an exclusive OS advisory lock so the file cannot be opened concurrently by another writer or reader; the lock is released automatically when the session is dropped or the process exits (including on a crash). Fails with Error::FileLocked if the file is already locked, or Error::EditUnsupported if the file is not a supported target (see the module docs for the exact requirements). To control or disable locking, use open_with_locking or set HDF5_USE_FILE_LOCKING=FALSE.

Source

pub fn open_with_locking<P: AsRef<Path>>( path: P, locking: FileLocking, ) -> Result<Self, Error>

Open an existing HDF5 file for in-place editing, choosing the file-locking policy explicitly. See open and FileLocking.

Source

pub fn create_dataset(&mut self, path: &str) -> &mut DatasetBuilder

Stage a new dataset, added on the next commit. The argument is the full path of the dataset; everything before the last component names the parent group, which must exist (or be created in this session). Returns the DatasetBuilder — the same builder used by FileBuilder — to configure data, shape, and attributes.

The dataset may be contiguous or chunked, and chunked datasets may be filtered (with_deflate, with_shuffle, with_fletcher32, with_scale_offset, with_zfp) and/or extensible (with_maxshape). An empty (zero-element) contiguous dataset is supported (chunking one is not), a provenance dataset (with_provenance) is supported, and a contiguous dataset may carry variable-length attributes, a variable-length-string payload (with_vlen_strings), or path-resolved object-reference elements (with_path_references; chunking any of these is not supported — see the module docs for the path-resolution rule and what still stays unsupported (dense attributes)).

Source

pub fn write_dataset(&mut self, path: &str) -> &mut DatasetBuilder

Stage an in-place overwrite of an existing dataset’s values (the HDF5 H5Dwrite whole-dataset write), applied on the next commit. path is the full path of a dataset that must already exist; the returned DatasetBuilder — the same builder used by create_dataset — supplies the replacement data.

This is a value overwrite, not a reshape or retype: the new data’s datatype and shape must match the on-disk dataset’s exactly (byte-for-byte after serialization, so endianness and compound layout must agree), or commit reports Error::EditUnsupported. Contiguous, compact, and chunked (including filtered) datasets are all supported; the dataset’s existing chunk geometry, filter pipeline, and chunk index are taken from the on-disk header (a builder that itself requests chunking/filtering is refused as “not a value overwrite”). A chunk index this engine cannot enumerate (a version-2 B-tree) is refused. Partial / sub-region writes are out of scope — the whole dataset is replaced.

When the new data is the same length as the existing contiguous data block (the common case), the bytes are written straight into that block: no object header is rewritten and the superblock root is not flipped, so the commit’s linearization point is the synced data write itself. A chunked dataset is handled the same way when every (re-encoded) chunk is the same byte length as the slot it replaces — an unfiltered overwrite (chunk sizes are fixed by the unchanged shape) or a filtered one whose re-encoded chunks match — so it too writes straight into the existing chunk slots. When the length differs (a resized contiguous block, or a filtered chunk that no longer fits), the dataset’s storage is rebuilt at end-of-file (or in reusable freed space), the old extent is freed, the data-layout message is repointed, the object header is rewritten, and the parent group’s link is patched — exactly like an addition relocates the path up to the root. A relocating overwrite moves the object header, so it is refused unless the dataset has a single hard link.

Source

pub fn create_group(&mut self, path: &str)

Stage a new (empty) group at path, created on the next commit. The parent must already exist or be created in the same session; populate the group with datasets via create_dataset using a path under it.

Source

pub fn set_group_attr( &mut self, path: &str, name: &str, value: AttrValue, ) -> &mut Self

Stage an attribute add or replacement on a group, applied on the next commit.

path names the group to edit; "" or "/" names the root group. The group may already exist or may be created earlier in the same session with create_group. Attributes — fixed-size or variable-length (AttrValue::VarLenAsciiArray) — are stored compactly in the rebuilt group header; an edit that would exceed the compact-attribute limit, or a group using dense (fractal-heap) attribute storage, is refused before any file bytes are changed.

Source

pub fn remove_group_attr(&mut self, path: &str, name: &str) -> &mut Self

Stage removal of a compact attribute from a group, applied on the next commit.

path names the group to edit; "" or "/" names the root group. The named attribute must exist in the committed group state after any earlier staged attribute operations for the same group have been applied.

Source

pub fn delete(&mut self, path: &str)

Stage removal of the link at path (the HDF5 H5Ldelete), applied on the next commit. The link’s object — and, for a group, its whole subtree — becomes unreachable. The bytes it occupied are returned to this session’s free list (issue #21): a later commit reuses them for new objects instead of growing the file, and if a freed run reaches end-of-file the file is truncated. Contiguous and chunked datasets (their chunk index and chunk data blocks) and whole group subtrees are all reclaimed. Reclaim is best-effort — an object whose blocks this engine cannot enumerate exhaustively (variable-length global-heap storage, dense attribute/link heaps, a version 2 B-tree chunk index) is left as dead bytes rather than risk freeing a region that is still in use. Freed space is reused within the open session; for a file created with H5Pset_file_space_strategy(persist = true) it is also recorded on disk so it survives reopen (see the module docs), otherwise it is forgotten on close. After reuse, an object reference to a deleted object may resolve to an unrelated object (deleting a referenced object is undefined in HDF5).

The path must exist. A deletion may not overlap another staged change in the same commit (e.g. delete /a while adding /a/b); split such edits into separate commits. The link’s parent group must itself be editable in place (compact links, single-chunk header); the target being removed has no such restriction.

Source

pub fn copy(&mut self, src: &str, dst: &str)

Stage a deep copy of the object at src to a new link at dst (the HDF5 H5Ocopy), applied on the next commit. The source — a dataset or a whole group subtree — is duplicated: fresh copies of every object’s data and header are written, internal links and the contiguous data address are repointed to the copies, and a link named by dst’s last component is added to dst’s parent group. The original is untouched.

The copy reflects the file’s on-disk state at commit time. src must exist and dst must not (and may not lie inside src). A chunked (and filtered) dataset is copied with its chunk payloads and filter pipeline preserved byte-for-byte (the index is rebuilt at the new location, so a source using a B-tree-v1 or implicit index is reproduced with an equivalent v4 index). The source subtree must otherwise be copyable in place: compact links and attributes, single-chunk headers, and a chunk index this engine can enumerate (a version-2 B-tree, or a sparse/unallocated chunk grid, is refused) — otherwise commit reports Error::EditUnsupported.

Source

pub fn copy_from( &mut self, source: &File, src: &str, dst: &str, ) -> Result<(), Error>

Stage a deep copy of the object at src in another open file source to a new link at dst in this file — a cross-file HDF5 H5Ocopy — applied on the next commit. Like copy but the source lives in a separate, independently-opened File reader rather than the file being edited.

The source — a dataset or a whole group subtree — is duplicated faithfully: fresh, byte-identical copies of every object’s header and data are appended to this file, internal links repointed, and a link named by dst’s last component added to dst’s parent group (which must already exist or be created earlier in this session). Both files are left otherwise untouched; the destination only changes on commit.

Unlike the same-file copy, the source is read eagerly here (the source borrow need not outlive the call), so this returns Result: the source subtree is resolved, validated, and read out before returning, and only an already-validated copy is queued for commit.

§Errors

Returns Error::EditUnsupported if the copy cannot be reproduced exactly in another file. Because the copy is byte-for-byte verbatim, anything that embeds a source-file absolute address is refused (it would dangle here): variable-length or reference datasets and attributes (including a chunked dataset whose elements are variable-length or references, whose chunk payloads embed such addresses), and any shared header message (a committed datatype, or an SOHM-shared dataspace, fill value, or filter pipeline). As with copy a chunked/filtered source is copied with its chunk payloads and pipeline preserved (index rebuilt at the new location); the source must use compact links and attributes, single-chunk version-2 headers, and a chunk index this engine can enumerate (a version-2 B-tree, or a sparse chunk grid, is refused). The source must be a buffered file (File::open or File::from_bytes, not open_streaming) using 8-byte offsets and no userblock, and src must exist in it and not be the root group.

Source

pub fn commit(&mut self) -> Result<(), Error>

Apply all staged additions and deletions to the file in place and flush.

Appends each new dataset (its data — a contiguous blob, or the chunk data and index for a chunked/filtered dataset — plus its object header) and each new group, then appends rewritten object headers for every touched group and its ancestors up to the root (omitting any deleted links), then repoints the superblock at the new root. On success the staged set is cleared and the session can be reused. On any Error::EditUnsupported the file on disk is left untouched: the checks that raise it — including each dataset’s filter-pipeline and chunk-geometry validation — all run before the first byte is written. Should a later step fail mid-apply (an I/O error, or a residual build error), the superblock — repointed last — still names the prior root, so the file stays valid and the appended bytes are unreferenced slack.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.