Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 26 additions & 4 deletions wicketd/src/http_entrypoints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -395,10 +395,32 @@ impl WicketdApi for WicketdApiImpl {
// Fetch the transceiver information from the SP.
let maybe_transceiver_inventory =
match rqctx.context().transceiver_handle.get_transceivers() {
GetTransceiversResponse::Response {
transceivers,
transceivers_last_seen,
} => Some((transceivers, transceivers_last_seen)),
GetTransceiversResponse::Response { transceivers } => {
// transceivers tracks the last_seen for each switch
// independently. But the (currently frozen) wicketd API
// wire shape only has a single last_seen field. So we must
// pick: min or max? We choose max here, so that if one of
// the fetch tasks is wedged, the timestamp indicates that.
//
// TODO: clean this up (report per-switch last_seen) once
// rkdeploy is on the stable commissioning API.
let last_seen = transceivers
.iter()
.map(|switch| switch.updated_at.elapsed())
.max();
last_seen.map(|last_seen| {
// The (currently frozen) wicketd API is a HashMap, so
// collect into that.
//
// TODO: switch to IdOrdMap once rkdeploy is on the
// stable commissioning API.
let inventory = transceivers
.into_iter()
.map(|switch| (switch.switch, switch.transceivers))
.collect();
(inventory, last_seen)
})
}
GetTransceiversResponse::Unavailable => None,
};

Expand Down
46 changes: 34 additions & 12 deletions wicketd/src/transceivers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
//! Fetching transceiver state from the SP.

use gateway_types::component::SpIdentifier;
use iddqd::{IdOrdItem, IdOrdMap, id_ord_map, id_upcast};
use sled_agent_types::early_networking::SwitchSlot;
use slog::{Logger, debug, error};
use slog_error_chain::InlineErrorChain;
use std::{
collections::HashMap,
sync::{Arc, Mutex},
time::Duration,
};
Expand All @@ -24,7 +24,30 @@ use transceiver_controller::{SpRequest, message::ExtendedStatus};
use wicket_common::inventory::{SpType, Transceiver};

/// Type alias for a map of all transceivers on each switch.
pub type TransceiverMap = HashMap<SwitchSlot, Vec<Transceiver>>;
pub type TransceiverMap = IdOrdMap<SwitchTransceivers>;

/// Item in a [`TransceiverMap`].
///
/// This tracks the state of all transceivers on a single switch.
#[derive(Clone, Debug)]
pub struct SwitchTransceivers {
/// The switch slot.
pub switch: SwitchSlot,
/// The list of transceivers on this switch.
pub transceivers: Vec<Transceiver>,
/// The last time we fetched transceivers from this switch.
pub updated_at: Instant,
}

impl IdOrdItem for SwitchTransceivers {
type Key<'a> = SwitchSlot;

fn key(&self) -> Self::Key<'_> {
self.switch
}

id_upcast!();
}

// Queue size for passing messages between transceiver fetch task.
const CHANNEL_CAPACITY: usize = 4;
Expand All @@ -50,7 +73,7 @@ const OTHER_SWITCH_SP_INTERFACE: &str = "sidecar1";

#[derive(Clone, Debug)]
pub enum GetTransceiversResponse {
Response { transceivers: TransceiverMap, transceivers_last_seen: Duration },
Response { transceivers: TransceiverMap },
Unavailable,
}

Expand Down Expand Up @@ -171,22 +194,21 @@ impl Manager {
error!(self.log, "all transceiver fetch tasks have exited");
return;
};
let update = SwitchTransceivers {
switch: switch_slot,
transceivers: these_transceivers,
updated_at,
};
let mut transceivers_by_switch = self.transceivers.lock().unwrap();
match &mut *transceivers_by_switch {
GetTransceiversResponse::Response {
transceivers,
transceivers_last_seen,
} => {
transceivers.insert(switch_slot, these_transceivers);
*transceivers_last_seen = updated_at.elapsed();
GetTransceiversResponse::Response { transceivers } => {
transceivers.insert_overwrite(update);
}
GetTransceiversResponse::Unavailable => {
let mut all_transceivers = TransceiverMap::new();
all_transceivers.insert(switch_slot, these_transceivers);
let all_transceivers = id_ord_map! { update };
*transceivers_by_switch =
GetTransceiversResponse::Response {
transceivers: all_transceivers,
transceivers_last_seen: updated_at.elapsed(),
};
}
}
Expand Down
Loading
You are viewing a condensed version of this merge commit. You can view the full changes here.