Skip to main content

Module version

Module version 

Source
Expand description

Version compatibility checking.

Provides version range checking and graceful degradation for reading files created with different format versions. Format version management and compatibility checking.

This module defines the versioning strategy for Hexz snapshot files (.hxz), enabling safe evolution of the on-disk format while maintaining backward and forward compatibility guarantees. Version negotiation ensures that readers can detect incompatible snapshots and provide actionable error messages.

§Versioning Strategy

Hexz uses a monotonic integer versioning scheme where each version number represents a distinct on-disk format:

  • Version 1: Initial format with two-level index, LZ4/Zstd compression, optional encryption, thin provisioning support
  • Future versions: Reserved for incompatible format changes (e.g., new index structures, alternative serialization formats, block metadata extensions)

§Semantic Versioning Alignment

Format versions are independent of Hexz software versions (semver). A software release may support multiple format versions for backward compatibility. The mapping is defined as:

Format VersionHexz Software VersionsKey Changes
10.1.0+Initial release

§Compatibility Model

§Backward Compatibility (Reading Old Snapshots)

Hexz readers maintain compatibility with snapshots created by older software:

  • MIN_SUPPORTED_VERSION: Oldest format version we can read (currently 1)
  • Upgrade Path: Snapshots older than MIN_SUPPORTED_VERSION must be migrated using the hexz-migrate tool (see Migration section below)

§Forward Compatibility (Reading New Snapshots)

Hexz readers handle snapshots created by newer software:

  • MAX_SUPPORTED_VERSION: Newest format version we can read (currently 1)
  • Degraded Mode: Future versions may enable partial reads with warnings if minor features are unrecognized (not yet implemented)
  • Strict Rejection: Snapshots with version > MAX_SUPPORTED_VERSION are rejected with an actionable error message

§Version Negotiation Workflow

When opening a snapshot file:

1. Read header magic bytes (validate "HEXZ" signature)
2. Read header.version field
3. Call check_version(header.version)
4. If VersionCompatibility::Incompatible:
      - Generate human-readable error via compatibility_message()
      - Suggest upgrade/migration path
      - Abort operation
5. If VersionCompatibility::Full:
      - Proceed with normal operations
6. If VersionCompatibility::Degraded (future):
      - Log warning about unsupported features
      - Proceed with limited functionality

§Adding New Format Versions

To introduce a breaking format change:

§Step 1: Increment Version Constant

pub const CURRENT_VERSION: u32 = 2;  // Changed from 1
pub const MAX_SUPPORTED_VERSION: u32 = 2;

§Step 2: Update Serialization Logic

Modify crate::format::header::Header or crate::format::index::MasterIndex to include new fields or change existing structures. Use serde attributes to maintain compatibility:

#[derive(Serialize, Deserialize)]
pub struct Header {
    // Existing fields...
    #[serde(skip_serializing_if = "Option::is_none")]
    pub new_feature: Option<NewFeatureData>,  // Version 2+ only
}

§Step 3: Conditional Deserialization

Add version-aware deserialization in reader code:

match header.version {
    1 => {
        // Legacy path for version 1
        read_index_v1(reader)?
    }
    2 => {
        // New path for version 2
        read_index_v2(reader)?
    }
    _ => unreachable!("check_version already validated"),
}

§Step 4: Update Tests

Add test fixtures for the new format version:

#[test]
fn test_read_v2_snapshot() {
    let snapshot = load_fixture("testdata/v2_snapshot.hxz");
    assert_eq!(snapshot.header.version, 2);
    // Verify new features work correctly
}

§Step 5: Document Migration Path

Update the migration guide with conversion instructions (see Migration section).

§Migration Between Versions

The hexz-migrate tool converts snapshots between format versions:

# Upgrade old snapshot to current format
hexz-migrate upgrade --input old_v1.hxz --output new_v2.hxz

# Downgrade for compatibility (if supported)
hexz-migrate downgrade --input new_v2.hxz --output legacy_v1.hxz \
    --target-version 1

§Migration Algorithm

The migration tool performs a streaming rewrite:

  1. Open source snapshot with reader for version N
  2. Create destination snapshot with writer for version M
  3. Stream all blocks through decompression/re-compression
  4. Rebuild index in target format
  5. Preserve metadata (encryption keys, parent references, etc.)

§Lossy Migrations

Downgrading may lose features unsupported in the target version:

  • Version 2 → 1: Hypothetical new features would be discarded with warnings

§Performance Considerations

Version checking is performed once per snapshot open operation:

  • Overhead: Negligible (~100ns for integer comparison)
  • Caching: Version is cached in crate::api::file::File struct
  • Hot Path: Not in block read/write paths

§Examples

§Basic Version Check

use hexz_core::format::version::{check_version, VersionCompatibility};

let snapshot_version = 1;
let compat = check_version(snapshot_version);

match compat {
    VersionCompatibility::Full => {
        println!("Snapshot is fully compatible");
    }
    VersionCompatibility::Incompatible => {
        eprintln!("Cannot read snapshot (incompatible version)");
    }
    VersionCompatibility::Degraded => {
        println!("Snapshot readable with warnings");
    }
}

§User-Facing Error Messages

use hexz_core::format::version::compatibility_message;

let version = 999;  // Future version
let message = compatibility_message(version);
println!("{}", message);
// Output: "Version 999 is too new (max supported: 1). Please upgrade Hexz."

§Reader Implementation

use hexz_core::format::version::check_version;
use hexz_core::error::Error;

fn open_snapshot(path: &Path) -> Result<Snapshot, Error> {
    let header = read_header(path)?;

    if !check_version(header.version).is_compatible() {
        return Err(Error::IncompatibleVersion {
            found: header.version,
            min_supported: MIN_SUPPORTED_VERSION,
            max_supported: MAX_SUPPORTED_VERSION,
        });
    }

    // Proceed with version-aware deserialization
    Ok(Snapshot { header, /* ... */ })
}

Enums§

VersionCompatibility
Result of snapshot version compatibility analysis.

Constants§

CURRENT_VERSION
Current format version written by this build of Hexz.
MAX_SUPPORTED_VERSION
Maximum format version readable by this build.
MIN_SUPPORTED_VERSION
Minimum format version readable by this build.

Functions§

check_version
Determines compatibility status of a snapshot format version.
compatibility_message
Generates a user-facing message describing version compatibility status.