Runtime Configuration
Centralized configuration management for HDDS with lock-free performance.
Overview
The configuration module provides:
- Static constants - RTPS spec values (ports, IPs, timing)
- RuntimeConfig - Dynamic key-value store (QoS, custom settings)
- Lock-free operations - DashMap + ArcSwap for high concurrency
- Port formula helpers - Calculate RTPS ports for any domain/participant
Architecture
┌─────────────────────────────────────────────────────────────────────┐
│ RuntimeConfig │
│ │
│ ┌────────────────────────────────────────────────────────────────┐ │
│ │ QoS Store (DashMap) │ │
│ │ "qos.reliability.kind" → "RELIABLE" │ │
│ │ "qos.durability.kind" → "TRANSIENT_LOCAL" │ │
│ │ "qos.history.depth" → "10" │ │
│ │ "user.cache_size" → "1000" │ │
│ │ "app.debug_mode" → "true" │ │
│ └────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌────────────────────────────────────────────────────────────────┐ │
│ │ Port Mapping (ArcSwap) │ │
│ │ metatraffic_multicast: 7400 │ │
│ │ sedp_unicast: 7410 │ │
│ │ user_unicast: 7411 │ │
│ └────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
Static Constants
RTPS Port Mapping (Sec. 9.6.1.1)
use hdds::config::*;
// Base port (IANA registered: 7400-7469)
const PORT_BASE: u16 = 7400;
// Port calculation gains
const DOMAIN_ID_GAIN: u16 = 250;
const PARTICIPANT_ID_GAIN: u16 = 2;
// Offsets
const SEDP_UNICAST_OFFSET: u16 = 10;
const USER_UNICAST_OFFSET: u16 = 11;
const DATA_MULTICAST_OFFSET: u16 = 1;
Pre-calculated Ports (Domain 0, Participant 0)
| Constant | Value | Description |
|---|---|---|
SPDP_MULTICAST_PORT_DOMAIN0 | 7400 | SPDP discovery multicast |
DATA_MULTICAST_PORT_DOMAIN0 | 7401 | User data multicast |
SEDP_UNICAST_PORT_DOMAIN0_P0 | 7410 | SEDP unicast |
USER_UNICAST_PORT_DOMAIN0_P0 | 7411 | User data unicast |
Port Calculation Functions
use hdds::config::{spdp_multicast_port, sedp_unicast_port, user_unicast_port};
// SPDP multicast port for any domain
let port = spdp_multicast_port(0); // 7400
let port = spdp_multicast_port(1); // 7650
let port = spdp_multicast_port(2); // 7900
// SEDP unicast port for domain and participant
let port = sedp_unicast_port(0, 0); // 7410
let port = sedp_unicast_port(0, 1); // 7412
let port = sedp_unicast_port(1, 0); // 7660
// User data unicast port
let port = user_unicast_port(0, 0); // 7411
let port = user_unicast_port(0, 1); // 7413
Multicast Addresses
use hdds::config::{MULTICAST_IP, MULTICAST_GROUP};
// Standard RTPS multicast (239.255.0.1)
let ip: [u8; 4] = MULTICAST_IP; // [239, 255, 0, 1]
let group: &str = MULTICAST_GROUP; // "239.255.0.1"
// Alternative (RTI legacy)
let alt_ip = MULTICAST_IP_ALT; // [239, 255, 0, 2]
Timing Constants
| Constant | Value | Description |
|---|---|---|
SPDP_ANNOUNCEMENT_PERIOD_MS | 3000 | SPDP announce interval |
PARTICIPANT_LEASE_DURATION_MS | 30000 | Participant timeout |
LEASE_CHECK_INTERVAL_MS | 1000 | Lease check frequency |
Buffer Sizes
| Constant | Value | Description |
|---|---|---|
RX_RING_SIZE | 256 | Discovery RX ring buffer |
RX_POOL_SIZE | 255 | Zero-copy buffer pool |
MTU_SIZE | 1500 | Ethernet MTU |
FRAGMENT_BUFFER_SIZE | 256 | Max fragments in flight |
FRAGMENT_TIMEOUT_MS | 500 | Fragment reassembly timeout |
READER_HISTORY_RING_SIZE | 1024 | DataReader history |
RuntimeConfig
Creating Configuration
use hdds::config::RuntimeConfig;
use std::sync::Arc;
// Create new config
let config = Arc::new(RuntimeConfig::new());
// Pass to components (cheap clone - just Arc increment)
let config_clone = config.clone();
Custom Port Mapping
Override RTPS formula with custom ports:
use hdds::transport::{PortMapping, CustomPortMapping};
let custom = CustomPortMapping {
spdp_multicast: 9400,
sedp_unicast: 9410,
user_unicast: 9411,
};
let mapping = PortMapping::from_custom(custom);
config.set_port_mapping(mapping);
// Read back
if let Some(ports) = config.get_port_mapping() {
println!("SPDP multicast: {}", ports.metatraffic_multicast);
}
// Clear (revert to RTPS formula)
config.clear_port_mapping();
User Configuration
For application-specific settings, use user.* or app.* prefixes:
// Set user-land config
config.set_user("user.cache_size", "1000");
config.set_user("app.debug_mode", "true");
// Get config
let cache_size = config.get_user_string("user.cache_size"); // Some("1000")
let debug = config.get_user("app.debug_mode"); // Some(Arc<"true">)
// Check existence
if config.contains_user("user.cache_size") {
// ...
}
// Remove
config.remove_user("user.cache_size");
Namespace Restriction
set_user() only accepts keys starting with user. or app.. Other prefixes are ignored with a log warning.
QoS Configuration
Set QoS parameters programmatically:
use hdds::config::{RuntimeConfig, qos};
let config = RuntimeConfig::new();
// Bulk set (efficient for XML loading)
config.set_qos_bulk(vec![
(qos::RELIABILITY_KIND, qos::RELIABLE),
(qos::DURABILITY_KIND, qos::TRANSIENT_LOCAL),
(qos::HISTORY_DEPTH, "10"),
]);
// Or with owned strings (dynamic)
config.set_qos_bulk_owned(vec![
("qos.reliability.kind".to_string(), "RELIABLE".to_string()),
("qos.history.depth".to_string(), "100".to_string()),
]);
QoS Keys and Values
The qos module provides type-safe constants:
use hdds::config::qos;
// Keys
qos::RELIABILITY_KIND // "qos.reliability.kind"
qos::DURABILITY_KIND // "qos.durability.kind"
qos::HISTORY_KIND // "qos.history.kind"
qos::HISTORY_DEPTH // "qos.history.depth"
qos::LIVELINESS_KIND // "qos.liveliness.kind"
qos::DEADLINE_PERIOD // "qos.deadline.period"
qos::OWNERSHIP_KIND // "qos.ownership.kind"
qos::PARTITION_NAME // "qos.partition.name"
// Values
qos::RELIABLE // "RELIABLE"
qos::BEST_EFFORT // "BEST_EFFORT"
qos::TRANSIENT_LOCAL // "TRANSIENT_LOCAL"
qos::VOLATILE // "VOLATILE"
qos::KEEP_LAST // "KEEP_LAST"
qos::KEEP_ALL // "KEEP_ALL"
qos::AUTOMATIC // "AUTOMATIC"
qos::MANUAL_BY_PARTICIPANT // "MANUAL_BY_PARTICIPANT"
Search Operations
// Search by prefix
let reliability_params = config.search_qos_prefix("qos.reliability.");
// → [("qos.reliability.kind", "RELIABLE"), ("qos.reliability.max_blocking_time", "100")]
// Search by pattern (contains)
let timeouts = config.search_qos_pattern("duration");
// → [("qos.liveliness.lease_duration", "30000"), ...]
// Get all entries
let all = config.get_all_qos();
println!("Config has {} entries", config.len());
Performance
RuntimeConfig is optimized for high-concurrency access:
| Operation | Time | Notes |
|---|---|---|
get_port_mapping() | ~20 ns | Atomic load |
set_port_mapping() | ~50 ns | Atomic swap |
get_user() | ~80 ns | DashMap lookup |
set_user() | ~100 ns | DashMap insert |
search_qos_prefix() | O(n) | Full scan |
Key characteristics:
- Lock-free: DashMap uses sharding, not global locks
- Zero-copy:
Arc<str>keys/values avoid cloning - Thread-safe: Safe concurrent access from any thread
Integration Example
use hdds::config::{RuntimeConfig, qos};
use std::sync::Arc;
fn setup_participant() {
// Create shared config
let config = Arc::new(RuntimeConfig::new());
// Set default QoS
config.set_qos_bulk(vec![
(qos::RELIABILITY_KIND, qos::RELIABLE),
(qos::DURABILITY_KIND, qos::VOLATILE),
(qos::HISTORY_KIND, qos::KEEP_LAST),
(qos::HISTORY_DEPTH, "10"),
]);
// Application-specific settings
config.set_user("app.telemetry_enabled", "true");
config.set_user("user.max_samples", "1000");
// Pass to DDS components
// (each clone is just an Arc increment)
let participant = ParticipantBuilder::new()
.with_config(config.clone())
.build();
}
Environment Variables
Configuration can also be set via environment:
| Variable | Description |
|---|---|
HDDS_CONFIG_FILE | Path to XML config file |
HDDS_DISCOVERY_PORT | Override SPDP port |
HDDS_MULTICAST_DISABLE | Disable multicast (1/0) |
HDDS_SHM_DISABLE | Disable shared memory (1/0) |
See Environment Variables for the complete list.
Related
- QoS Policies - QoS configuration
- Environment Variables - Full reference
- Concepts: Architecture - System overview