Skip to main content

ProcessVariable

Struct ProcessVariable 

Source
pub struct ProcessVariable {
    pub name: String,
    pub value: RwLock<EpicsValue>,
    pub subscribers: Mutex<Vec<Subscriber>>,
    /* private fields */
}
Expand description

A process variable hosted by the server.

Fields§

§name: String§value: RwLock<EpicsValue>§subscribers: Mutex<Vec<Subscriber>>

Implementations§

Source§

impl ProcessVariable

Source

pub fn new(name: String, initial: EpicsValue) -> Self

Source

pub fn set_metadata(&self, metadata: PvMetadata)

Install (or replace) the shadow DBR_GR_/DBR_CTRL_/enum metadata served on this PV’s snapshots. Used by the CA / PVA gateway after fetching the upstream IOC’s control metadata. See PvMetadata. To publish the change to downstream property monitors, follow with Self::post_property.

Source

pub fn metadata(&self) -> PvMetadata

Snapshot (clone) of the installed shadow metadata; empty (Default) for a plain local PV.

Source

pub fn set_access_hook(&self, hook: AccessHook)

Install an access hook. Replaces any previously installed hook.

Source

pub fn access_hook(&self) -> Option<AccessHook>

Snapshot of the installed access hook (clone of the Arc), or None. Consulted by the CA server’s compute_access; cheap and non-async, like Self::write_hook.

Source

pub fn set_read_hook(&self, hook: ReadHook)

Install a read hook. Replaces any previously-installed hook. Used by the CA gateway’s no-cache mode so each downstream GET is served by a fresh upstream fetch. See ReadHook.

Source

pub fn read_hook(&self) -> Option<ReadHook>

Snapshot of the installed read hook (clone of the Arc), or None. Cheap and non-async, like Self::write_hook: the read lock is released before the cloned Arc returns, so the caller’s subsequent await on the hook holds no lock.

Source

pub fn set_write_hook(&self, hook: WriteHook)

Install a write hook. Replaces any previously-installed hook.

Source

pub fn clear_write_hook(&self)

Remove any installed write hook.

Source

pub fn write_hook(&self) -> Option<WriteHook>

Snapshot of the installed write hook (clone of the Arc), or None if none. Used by the CA TCP write path; cheap and non-async — the read lock is released before the cloned Arc returns, so the caller’s subsequent await on the hook does not hold any lock.

Source

pub async fn get(&self) -> EpicsValue

Get the current value.

Source

pub async fn snapshot(&self) -> Snapshot

Build a Snapshot for this bare PV.

A ProcessVariable is a non-record-backed channel: it has no alarm engine, no DESC/EGU/PREC metadata and no timestamp user tag of its own. The snapshot is therefore value + NO_ALARM + wall-clock now, with user_tag = 0. Display / control / enum metadata is None unless a proxy installed it via Self::set_metadata (the CA / PVA gateway shadowing an upstream IOC) — see Self::apply_metadata. Record-backed channels build their snapshot via RecordInstance::snapshot_for_field, which carries the record’s own alarm/metadata. The only path that injects a non-zero alarm onto a bare PV is Self::post_alarm (used by the gateway adapter to surface upstream disconnect).

Source

pub async fn read_snapshot(&self) -> Result<Snapshot, CaError>

Build the snapshot served on a one-shot client GET (CA_PROTO_READ / CA_PROTO_READ_NOTIFY).

When a ReadHook is installed (the CA gateway’s no-cache mode), the snapshot is fetched fresh through the hook — value and its upstream alarm status/severity and IOC timestamp together — and the shadow’s last-known property metadata (display/control/enum) is overlaid for the fields a DBR_TIME_* event does not carry; on hook error the failure propagates so the server can answer ECA_GETFAIL, matching C ca-gateway forwarding each read to the IOC under -no_cache (gateVc.cc:1361-1369, gatePv.cc:976/:1789-1794). Without a hook this is exactly Self::snapshot wrapped in Ok, so the GET path is unchanged for every record-backed and cached PV.

Only the GET path calls this; monitor fan-out, the initial monitor event, and access-rights re-posts keep using Self::snapshot (the stored value), so a no-cache PV still backs a downstream monitor with its upstream subscription’s events rather than a per-event upstream get.

Source

pub async fn set(&self, new_value: EpicsValue)

Set a new value and notify all subscribers.

Source

pub async fn set_snapshot(&self, snapshot: Snapshot)

Set value from a full snapshot (value + alarm + timestamp) and notify all subscribers. Used by the CA gateway forwarding task to propagate the upstream alarm status/severity and IOC timestamp to downstream monitors. Mirrors gateVcData::setEventData + vcPostEvent in the C ca-gateway: the incoming dbr_time_xxx GDD carries all three fields.

Source

pub async fn post_alarm(&self, severity: u16, status: u16)

Push a fresh monitor event holding the current value but with the supplied alarm severity/status. Used by the PVA / CA gateway adapter to surface upstream-disconnect to downstream monitor subscribers without dropping the simple PV (which would force every downstream client into ECA_DISCONN + reconnect storms when the upstream is just briefly unreachable). Mirrors gatePvData::death’s “alarm-post” alternative discussed in the C++ ca-gateway audit.

Source

pub async fn post_property(&self, snapshot: Snapshot)

Post a DBE_PROPERTY monitor event carrying the decoded upstream CTRL event snapshot — its value plus the upstream status / severity and timestamp — overlaid with the installed shadow metadata, so downstream property-change monitors re-read the units / precision / limits / enum labels with the upstream alarm state.

Used by the CA / PVA gateway when an upstream DBE_PROPERTY event fires (metadata changed) after it has refreshed the shadow PV via Self::set_metadata. The caller supplies the snapshot rather than this method synthesising one: C ca-gateway decodes the upstream DBR_CTRL_* callback and re-posts the value with setStatSevr() status/severity preserved (gatePv.cc:2413-2438, runValueDataCB), leaving the timestamp as the control DBR carries none — it must NOT be replaced with a fresh NO_ALARM / wall-clock-now snapshot just because metadata changed. Pass the timestamp the upstream value carried (the control event has none of its own); pass status/severity from the upstream CTRL payload. Property events are a distinct class from value/alarm: only DBE_PROPERTY subscribers receive them.

Source

pub async fn add_subscriber( &self, sid: u32, data_type: DbFieldType, mask: u16, ) -> Option<Receiver<MonitorEvent>>

Add a subscriber. Returns the receiver for monitor events, or None when the per-PV subscriber cap has been reached (defends against a misbehaving client opening many MONITOR ops against one shared PV; per-channel cap limits channels but not subscriber rows on a single PV). Operators override the cap via EPICS_CAS_MAX_SUBSCRIBERS_PER_PV (default 1024 — large enough for any realistic dashboard fan-out, small enough to bound memory under abuse).

Channel depth defaults to 64 events; the operator can lift the cap via EPICS_CAS_MAX_EVENTS_PER_CHAN for sites that need deeper coalescing buffers. C rsrv does not advertise this knob (its queue is internally fixed) — exposing it lets us tune memory vs latency for slow-viewer workloads.

Source

pub async fn attach_filters_to_subscriber(&self, sid: u32, filters: FilterChain)

attach a channel-filter chain to an already-added subscriber (looked up by sid). The CA server first add_subscribers, then attaches the chain parsed from the channel’s .{...} suffix — symmetric with the record-field RecordInstance::attach_filter_to_last_subscriber path, so a SimplePv monitor runs the SAME filter chain as a record-field monitor instead of the empty default FilterChain that add_subscriber installs. Update delivery (Self::notify_subscribers / Self::post_alarm) already applies sub.filters; this is the missing wiring that populates it.

The caller passes a FRESH chain per subscriber so stateful filters (dbnd last-value, dec counter, sync state) stay isolated across subscribers. An empty chain is a no-op (keeps the default). No-op when no subscriber matches sid (e.g. it was reaped between add and attach).

Source

pub async fn remove_subscriber(&self, sid: u32)

Remove a subscriber by subscription ID.

Source

pub async fn pop_coalesced(&self, sid: u32) -> Option<MonitorEvent>

Take any pending coalesced overflow value for the given subscriber. Called by the per-subscription forwarder task after each rx.recv() and folded in via coalesce_consume, which drains the now-stale queue tail so a slow consumer converges on the latest known value without ever delivering it before older queued values.

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> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
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.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more