Skip to content
82 changes: 64 additions & 18 deletions rs/execution_environment/src/canister_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ use ic_replicated_state::{
use ic_types::ingress::{IngressState, IngressStatus};
use ic_types::messages::{
CanisterCall, Payload, RejectContext, Response as CanisterResponse, SignedIngressContent,
StopCanisterCallId, StopCanisterContext,
StopCanisterCallId,
};
use ic_types::{
CanisterId, CanisterTimer, ComputeAllocation, DEFAULT_AGGREGATE_LOG_MEMORY_LIMIT,
Expand Down Expand Up @@ -631,7 +631,7 @@ impl CanisterManager {
subnet_memory_saturation: ResourceSaturation,
subnet_size: usize,
cost_schedule: CanisterCyclesCostSchedule,
) -> Result<(), CanisterManagerError> {
) -> Result<CanisterManagerResponse, CanisterManagerError> {
let sender = origin.origin();

validate_controller(canister, &sender)?;
Expand Down Expand Up @@ -733,7 +733,16 @@ impl CanisterManager {
}
*/

Ok(())
Ok(CanisterManagerResponse {
canister_id: canister.canister_id(),
reply: Some(EmptyBlob.encode()),
// TODO(DSM-123): set `heap_delta_increase` due to canister log buffer resize
heap_delta_increase: NumBytes::new(0),
unflushed_checkpoint_op: None,
deleted_call_context_responses: vec![],
stop_call_id_to_remove: None,
stop_contexts_to_reject: vec![],
})
}

/// Check if the sender is on NNS or on the same subnet.
Expand Down Expand Up @@ -1087,20 +1096,28 @@ impl CanisterManager {
///
/// If the canister is in the process of being stopped (i.e stopping), then
/// the canister is transitioned back into a running state and the
/// `stop_contexts` that were used for stopping the canister are
/// `stop_contexts_to_reject` that were used for stopping the canister are
/// returned.
pub(crate) fn start_canister(
&self,
sender: PrincipalId,
canister: &mut CanisterState,
subnet_admins: Option<BTreeSet<PrincipalId>>,
) -> Result<Vec<StopCanisterContext>, CanisterManagerError> {
) -> Result<CanisterManagerResponse, CanisterManagerError> {
validate_controller_or_subnet_admin(canister, subnet_admins, &sender)?;

let stop_contexts = canister.system_state.start_canister();
let stop_contexts_to_reject = canister.system_state.start_canister();
canister.system_state.bump_canister_version();

Ok(stop_contexts)
Ok(CanisterManagerResponse {
canister_id: canister.canister_id(),
reply: Some(EmptyBlob.encode()),
heap_delta_increase: NumBytes::new(0),
unflushed_checkpoint_op: None,
deleted_call_context_responses: vec![],
stop_call_id_to_remove: None,
stop_contexts_to_reject,
})
}

/// Fetches the current status of the canister.
Expand Down Expand Up @@ -1558,7 +1575,7 @@ impl CanisterManager {
cycles_amount: Option<u128>,
canister: &mut CanisterState,
provisional_whitelist: &ProvisionalWhitelist,
) -> Result<(), CanisterManagerError> {
) -> Result<CanisterManagerResponse, CanisterManagerError> {
if !provisional_whitelist.contains(&sender) {
return Err(CanisterManagerError::SenderNotInWhitelist(sender));
}
Expand All @@ -1570,7 +1587,15 @@ impl CanisterManager {

canister.system_state.add_cycles(cycles_amount);

Ok(())
Ok(CanisterManagerResponse {
canister_id: canister.canister_id(),
reply: Some(EmptyBlob.encode()),
heap_delta_increase: NumBytes::new(0),
unflushed_checkpoint_op: None,
deleted_call_context_responses: vec![],
stop_call_id_to_remove: None,
stop_contexts_to_reject: vec![],
})
}

pub(crate) fn deposit_cycles(
Expand Down Expand Up @@ -1667,7 +1692,7 @@ impl CanisterManager {
subnet_size: usize,
cost_schedule: CanisterCyclesCostSchedule,
resource_saturation: &ResourceSaturation,
) -> Result<UploadChunkResult, CanisterManagerError> {
) -> Result<CanisterManagerResponse, CanisterManagerError> {
// Allow the canister itself to perform this operation.
if sender != canister.canister_id().into() {
validate_controller(canister, &sender)?
Expand Down Expand Up @@ -1696,11 +1721,17 @@ impl CanisterManager {
{
ChunkValidationResult::Insert(validated_chunk) => validated_chunk,
ChunkValidationResult::AlreadyExists(hash) => {
return Ok(UploadChunkResult {
reply: UploadChunkReply {
hash: hash.to_vec(),
},
let reply = UploadChunkReply {
hash: hash.to_vec(),
};
return Ok(CanisterManagerResponse {
canister_id: canister.canister_id(),
reply: Some(reply.encode()),
heap_delta_increase: NumBytes::new(0),
unflushed_checkpoint_op: None,
deleted_call_context_responses: vec![],
stop_call_id_to_remove: None,
stop_contexts_to_reject: vec![],
});
}
ChunkValidationResult::ValidationError(err) => {
Expand Down Expand Up @@ -1751,9 +1782,16 @@ impl CanisterManager {
.system_state
.wasm_chunk_store
.insert_chunk(validated_chunk);
Ok(UploadChunkResult {
reply: UploadChunkReply { hash },

let reply = UploadChunkReply { hash };
Ok(CanisterManagerResponse {
canister_id: canister.canister_id(),
reply: Some(reply.encode()),
heap_delta_increase: chunk_bytes,
unflushed_checkpoint_op: None,
deleted_call_context_responses: vec![],
stop_call_id_to_remove: None,
stop_contexts_to_reject: vec![],
})
}

Expand All @@ -1765,7 +1803,7 @@ impl CanisterManager {
subnet_size: usize,
cost_schedule: CanisterCyclesCostSchedule,
resource_saturation: &ResourceSaturation,
) -> Result<(), CanisterManagerError> {
) -> Result<CanisterManagerResponse, CanisterManagerError> {
// Allow the canister itself to perform this operation.
if sender != canister.canister_id().into() {
validate_controller(canister, &sender)?
Expand Down Expand Up @@ -1797,7 +1835,15 @@ impl CanisterManager {
validated_cycles_and_memory_usage,
);

Ok(())
Ok(CanisterManagerResponse {
canister_id: canister.canister_id(),
reply: Some(EmptyBlob.encode()),
heap_delta_increase: NumBytes::new(0),
unflushed_checkpoint_op: None,
deleted_call_context_responses: vec![],
stop_call_id_to_remove: None,
stop_contexts_to_reject: vec![],
})
}

pub(crate) fn stored_chunks(
Expand Down
18 changes: 10 additions & 8 deletions rs/execution_environment/src/canister_manager/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1340,10 +1340,11 @@ fn start_a_stopping_canister_with_no_stop_contexts() {
state.put_canister_state(canister);

let canister = state.canister_state_make_mut(&canister_id).unwrap();
assert_eq!(
canister_manager.start_canister(sender, canister, subnet_admins),
Ok(Vec::new())
);
let stop_contexts_to_reject = canister_manager
.start_canister(sender, canister, subnet_admins)
.unwrap()
.stop_contexts_to_reject;
assert_eq!(stop_contexts_to_reject, Vec::new());
});
}

Expand All @@ -1363,10 +1364,11 @@ fn start_a_stopping_canister_with_stop_contexts() {
state.put_canister_state(canister);

let canister = state.canister_state_make_mut(&canister_id).unwrap();
assert_eq!(
canister_manager.start_canister(sender, canister, subnet_admins),
Ok(vec![stop_context])
);
let stop_contexts_to_reject = canister_manager
.start_canister(sender, canister, subnet_admins)
.unwrap()
.stop_contexts_to_reject;
assert_eq!(stop_contexts_to_reject, vec![stop_context]);
});
}

Expand Down
7 changes: 1 addition & 6 deletions rs/execution_environment/src/canister_manager/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use ic_interfaces::execution_environment::{CanisterOutOfCyclesError, HypervisorE
use ic_logger::ReplicaLogger;
use ic_management_canister_types_private::{
CanisterChangeOrigin, CanisterInstallModeV2, InstallChunkedCodeArgs, InstallCodeArgsV2,
UploadChunkReply,
};
use ic_registry_subnet_type::SubnetType;
use ic_replicated_state::{
Expand Down Expand Up @@ -301,15 +300,11 @@ impl TryFrom<(CanisterChangeOrigin, InstallCodeArgsV2)> for InstallCodeContext {
}
}

pub(crate) struct UploadChunkResult {
pub(crate) reply: UploadChunkReply,
pub(crate) heap_delta_increase: NumBytes,
}

/// Bundles the reply (success) to a management canister request (referred to as "current request")
/// with changes to `ReplicatedState` that must be applied separately.
/// This is because `CanisterManager` only mutates a single `CanisterState` (but no other parts of `ReplicatedState`)
/// in cases when it returns `CanisterManagerResponse`.
#[derive(Eq, PartialEq, Debug)]
pub(crate) struct CanisterManagerResponse {
/// The target canister of the current request.
/// Only `CanisterState` of that canister could have been mutated
Expand Down
Loading
Loading