Skip to content

Commit 6f04a5a

Browse files
authored
feat(node): extend lease transport surface for M9-T09 (#93)
1 parent efaf307 commit 6f04a5a

File tree

10 files changed

+562
-339
lines changed

10 files changed

+562
-339
lines changed

crates/allocdb-core/src/state_machine_members.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,27 @@ impl AllocDb {
4343
.copied()
4444
}
4545

46+
#[must_use]
47+
///
48+
/// # Panics
49+
///
50+
/// Panics if `reservation.member_count` cannot fit `usize` on the current platform or if the
51+
/// trusted core has lost one of the live member records required by `reservation`.
52+
pub fn reservation_member_resource_ids(
53+
&self,
54+
reservation: ReservationRecord,
55+
) -> Vec<ResourceId> {
56+
let mut resource_ids =
57+
Vec::with_capacity(usize::try_from(reservation.member_count).expect("u32 fits usize"));
58+
for member_index in 0..reservation.member_count {
59+
let member = self
60+
.reservation_member(reservation.reservation_id, member_index)
61+
.expect("live reservation must retain all member records");
62+
resource_ids.push(member.resource_id);
63+
}
64+
resource_ids
65+
}
66+
4667
pub(crate) fn reservation_contains_resource(
4768
&self,
4869
reservation: ReservationRecord,

crates/allocdb-node/src/api.rs

Lines changed: 89 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ use allocdb_core::command_codec::{
33
CommandCodecError, decode_client_request, encode_client_request,
44
};
55
use allocdb_core::ids::{HolderId, Lsn, ReservationId, ResourceId, Slot};
6-
use allocdb_core::result::CommandOutcome;
6+
use allocdb_core::result::ResultCode;
77
use allocdb_core::{
8-
ReservationLookupError, ReservationRecord, ReservationState, ResourceRecord, ResourceState,
9-
SlotOverflowKind,
8+
AllocDb, ReservationLookupError, ReservationRecord, ReservationState, ResourceRecord,
9+
ResourceState, SlotOverflowKind,
1010
};
1111

1212
use crate::engine::{
@@ -26,7 +26,7 @@ pub use codec::{ApiCodecError, decode_request, decode_response, encode_request,
2626
pub enum ApiRequest {
2727
Submit(SubmitRequest),
2828
GetResource(ResourceRequest),
29-
GetReservation(ReservationRequest),
29+
GetLease(LeaseRequest),
3030
GetMetrics(MetricsRequest),
3131
TickExpirations(TickExpirationsRequest),
3232
}
@@ -63,8 +63,8 @@ pub struct ResourceRequest {
6363
}
6464

6565
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
66-
pub struct ReservationRequest {
67-
pub reservation_id: ReservationId,
66+
pub struct LeaseRequest {
67+
pub lease_id: ReservationId,
6868
pub current_slot: Slot,
6969
pub required_lsn: Option<Lsn>,
7070
}
@@ -83,12 +83,12 @@ pub struct TickExpirationsRequest {
8383
pub enum ApiResponse {
8484
Submit(SubmitResponse),
8585
GetResource(ResourceResponse),
86-
GetReservation(ReservationResponse),
86+
GetLease(LeaseResponse),
8787
GetMetrics(MetricsResponse),
8888
TickExpirations(TickExpirationsResponse),
8989
}
9090

91-
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
91+
#[derive(Clone, Debug, Eq, PartialEq)]
9292
pub enum SubmitResponse {
9393
Committed(SubmissionCommitted),
9494
Rejected(SubmissionFailure),
@@ -97,21 +97,27 @@ pub enum SubmitResponse {
9797
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
9898
pub struct SubmissionCommitted {
9999
pub applied_lsn: Lsn,
100-
pub outcome: CommandOutcome,
100+
pub result_code: ResultCode,
101+
pub lease_id: Option<ReservationId>,
102+
pub lease_epoch: Option<u64>,
103+
pub deadline_slot: Option<Slot>,
101104
pub from_retry_cache: bool,
102105
}
103106

104107
impl From<SubmissionResult> for SubmissionCommitted {
105108
fn from(value: SubmissionResult) -> Self {
106109
Self {
107110
applied_lsn: value.applied_lsn,
108-
outcome: value.outcome,
111+
result_code: value.outcome.result_code,
112+
lease_id: value.outcome.reservation_id,
113+
lease_epoch: value.outcome.lease_epoch,
114+
deadline_slot: value.outcome.deadline_slot,
109115
from_retry_cache: value.from_retry_cache,
110116
}
111117
}
112118
}
113119

114-
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
120+
#[derive(Clone, Debug, Eq, PartialEq)]
115121
pub struct SubmissionFailure {
116122
pub category: SubmissionErrorCategory,
117123
pub code: SubmissionFailureCode,
@@ -206,7 +212,7 @@ impl InvalidRequestReason {
206212
}
207213
}
208214

209-
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
215+
#[derive(Clone, Debug, Eq, PartialEq)]
210216
pub enum ResourceResponse {
211217
Found(ResourceView),
212218
NotFound,
@@ -217,28 +223,70 @@ pub enum ResourceResponse {
217223
},
218224
}
219225

226+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
227+
pub enum ResourceViewState {
228+
Available,
229+
Reserved,
230+
Active,
231+
Revoking,
232+
}
233+
234+
impl From<ResourceState> for ResourceViewState {
235+
fn from(value: ResourceState) -> Self {
236+
match value {
237+
ResourceState::Available => Self::Available,
238+
ResourceState::Reserved => Self::Reserved,
239+
ResourceState::Confirmed => Self::Active,
240+
ResourceState::Revoking => Self::Revoking,
241+
}
242+
}
243+
}
244+
220245
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
221246
pub struct ResourceView {
222247
pub resource_id: ResourceId,
223-
pub state: ResourceState,
224-
pub current_reservation_id: Option<ReservationId>,
248+
pub state: ResourceViewState,
249+
pub current_lease_id: Option<ReservationId>,
225250
pub version: u64,
226251
}
227252

228253
impl From<ResourceRecord> for ResourceView {
229254
fn from(value: ResourceRecord) -> Self {
230255
Self {
231256
resource_id: value.resource_id,
232-
state: value.current_state,
233-
current_reservation_id: value.current_reservation_id,
257+
state: value.current_state.into(),
258+
current_lease_id: value.current_reservation_id,
234259
version: value.version,
235260
}
236261
}
237262
}
238263

239264
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
240-
pub enum ReservationResponse {
241-
Found(ReservationView),
265+
pub enum LeaseViewState {
266+
Reserved,
267+
Active,
268+
Revoking,
269+
Released,
270+
Expired,
271+
Revoked,
272+
}
273+
274+
impl From<ReservationState> for LeaseViewState {
275+
fn from(value: ReservationState) -> Self {
276+
match value {
277+
ReservationState::Reserved => Self::Reserved,
278+
ReservationState::Confirmed => Self::Active,
279+
ReservationState::Revoking => Self::Revoking,
280+
ReservationState::Released => Self::Released,
281+
ReservationState::Expired => Self::Expired,
282+
ReservationState::Revoked => Self::Revoked,
283+
}
284+
}
285+
}
286+
287+
#[derive(Clone, Debug, Eq, PartialEq)]
288+
pub enum LeaseResponse {
289+
Found(LeaseView),
242290
NotFound,
243291
Retired,
244292
EngineHalted,
@@ -248,31 +296,32 @@ pub enum ReservationResponse {
248296
},
249297
}
250298

251-
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
252-
pub struct ReservationView {
253-
pub reservation_id: ReservationId,
254-
pub resource_id: ResourceId,
299+
#[derive(Clone, Debug, Eq, PartialEq)]
300+
pub struct LeaseView {
301+
pub lease_id: ReservationId,
255302
pub holder_id: HolderId,
303+
pub state: LeaseViewState,
256304
pub lease_epoch: u64,
257-
pub state: ReservationState,
258305
pub created_lsn: Lsn,
259-
pub deadline_slot: Slot,
306+
pub deadline_slot: Option<Slot>,
260307
pub released_lsn: Option<Lsn>,
261308
pub retire_after_slot: Option<Slot>,
309+
pub member_resource_ids: Vec<ResourceId>,
262310
}
263311

264-
impl From<ReservationRecord> for ReservationView {
265-
fn from(value: ReservationRecord) -> Self {
312+
impl LeaseView {
313+
#[must_use]
314+
pub fn from_db(db: &AllocDb, value: ReservationRecord) -> Self {
266315
Self {
267-
reservation_id: value.reservation_id,
268-
resource_id: value.resource_id,
316+
lease_id: value.reservation_id,
269317
holder_id: value.holder_id,
318+
state: value.state.into(),
270319
lease_epoch: value.lease_epoch,
271-
state: value.state,
272320
created_lsn: value.created_lsn,
273-
deadline_slot: value.deadline_slot,
321+
deadline_slot: Some(value.deadline_slot),
274322
released_lsn: value.released_lsn,
275323
retire_after_slot: value.retire_after_slot,
324+
member_resource_ids: db.reservation_member_resource_ids(value),
276325
}
277326
}
278327
}
@@ -282,7 +331,7 @@ pub struct MetricsResponse {
282331
pub metrics: EngineMetrics,
283332
}
284333

285-
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
334+
#[derive(Clone, Debug, Eq, PartialEq)]
286335
pub enum TickExpirationsResponse {
287336
Applied(TickExpirationsApplied),
288337
Rejected(SubmissionFailure),
@@ -314,8 +363,8 @@ impl SingleNodeEngine {
314363
ApiRequest::GetResource(request) => {
315364
ApiResponse::GetResource(self.handle_resource_request(request))
316365
}
317-
ApiRequest::GetReservation(request) => {
318-
ApiResponse::GetReservation(self.handle_reservation_request(request))
366+
ApiRequest::GetLease(request) => {
367+
ApiResponse::GetLease(self.handle_lease_request(request))
319368
}
320369
ApiRequest::GetMetrics(request) => ApiResponse::GetMetrics(MetricsResponse {
321370
metrics: self.metrics(request.current_wall_clock_slot),
@@ -367,14 +416,14 @@ impl SingleNodeEngine {
367416
})
368417
}
369418

370-
fn handle_reservation_request(&self, request: ReservationRequest) -> ReservationResponse {
419+
fn handle_lease_request(&self, request: LeaseRequest) -> LeaseResponse {
371420
if let Some(error) = self.read_error(request.required_lsn) {
372421
return match error {
373-
ReadError::EngineHalted => ReservationResponse::EngineHalted,
422+
ReadError::EngineHalted => LeaseResponse::EngineHalted,
374423
ReadError::RequiredLsnNotApplied {
375424
required_lsn,
376425
last_applied_lsn,
377-
} => ReservationResponse::FenceNotApplied {
426+
} => LeaseResponse::FenceNotApplied {
378427
required_lsn,
379428
last_applied_lsn,
380429
},
@@ -383,11 +432,11 @@ impl SingleNodeEngine {
383432

384433
match self
385434
.db()
386-
.reservation(request.reservation_id, request.current_slot)
435+
.reservation(request.lease_id, request.current_slot)
387436
{
388-
Ok(record) => ReservationResponse::Found(record.into()),
389-
Err(ReservationLookupError::NotFound) => ReservationResponse::NotFound,
390-
Err(ReservationLookupError::Retired) => ReservationResponse::Retired,
437+
Ok(record) => LeaseResponse::Found(LeaseView::from_db(self.db(), record)),
438+
Err(ReservationLookupError::NotFound) => LeaseResponse::NotFound,
439+
Err(ReservationLookupError::Retired) => LeaseResponse::Retired,
391440
}
392441
}
393442

0 commit comments

Comments
 (0)