git.delta.rocks / unique-network / refs/commits / ccd56ff0f661

difftreelog

feat track free places inside the agenda

Daniel Shiposha2022-10-26parent: #1768418.patch.diff
in: master

1 file changed

modifiedpallets/scheduler-v2/src/lib.rsdiffbeforeafterboth
246 <T as frame_system::Config>::AccountId,246 <T as frame_system::Config>::AccountId,
247>;247>;
248248
249#[derive(Encode, Decode, MaxEncodedLen, TypeInfo)]
250#[scale_info(skip_type_params(T))]
251pub struct BlockAgenda<T: Config> {
252 agenda: BoundedVec<Option<ScheduledOf<T>>, T::MaxScheduledPerBlock>,
253 free_places: u32,
254}
255
256impl<T: Config> BlockAgenda<T> {
257 fn try_push(&mut self, scheduled: ScheduledOf<T>) -> Option<u32> {
258 if self.free_places == 0 {
259 return None;
260 }
261
262 self.free_places = self.free_places.saturating_sub(1);
263
264 if (self.agenda.len() as u32) < T::MaxScheduledPerBlock::get() {
265 // will always succeed due to the above check.
266 let _ = self.agenda.try_push(Some(scheduled));
267 Some((self.agenda.len() - 1) as u32)
268 } else {
269 match self.agenda.iter().position(|i| i.is_none()) {
270 Some(hole_index) => {
271 self.agenda[hole_index] = Some(scheduled);
272 Some(hole_index as u32)
273 }
274 None => unreachable!("free_places > 0; qed"),
275 }
276 }
277 }
278
279 fn set_slot(&mut self, index: u32, slot: Option<ScheduledOf<T>>) {
280 self.agenda[index as usize] = slot;
281 }
282
283 fn iter(&self) -> impl Iterator<Item = &'_ Option<ScheduledOf<T>>> + '_ {
284 self.agenda.iter()
285 }
286
287 fn get(&self, index: u32) -> Option<&ScheduledOf<T>> {
288 match self.agenda.get(index as usize) {
289 Some(Some(scheduled)) => Some(scheduled),
290 _ => None,
291 }
292 }
293
294 fn get_mut(&mut self, index: u32) -> Option<&mut ScheduledOf<T>> {
295 match self.agenda.get_mut(index as usize) {
296 Some(Some(scheduled)) => Some(scheduled),
297 _ => None,
298 }
299 }
300
301 fn take(&mut self, index: u32) -> Option<ScheduledOf<T>> {
302 let removed = self.agenda.get_mut(index as usize)?.take();
303
304 if removed.is_some() {
305 self.free_places = self.free_places.saturating_add(1);
306 }
307
308 removed
309 }
310}
311
312impl<T: Config> Default for BlockAgenda<T> {
313 fn default() -> Self {
314 let agenda = Default::default();
315 let free_places = T::MaxScheduledPerBlock::get();
316
317 Self {
318 agenda,
319 free_places,
320 }
321 }
322}
323
249struct WeightCounter {324struct WeightCounter {
250 used: Weight,325 used: Weight,
251 limit: Weight,326 limit: Weight,
368443
369 /// Items to be executed, indexed by the block number that they should be executed on.444 /// Items to be executed, indexed by the block number that they should be executed on.
370 #[pallet::storage]445 #[pallet::storage]
371 pub type Agenda<T: Config> = StorageMap<446 pub type Agenda<T: Config> =
372 _,447 StorageMap<_, Twox64Concat, T::BlockNumber, BlockAgenda<T>, ValueQuery>;
373 Twox64Concat,
374 T::BlockNumber,
375 BoundedVec<Option<ScheduledOf<T>>, T::MaxScheduledPerBlock>,
376 ValueQuery,
377 >;
378448
379 /// Lookup from a name to the block number and index of the task.449 /// Lookup from a name to the block number and index of the task.
380 #[pallet::storage]450 #[pallet::storage]
640 what: ScheduledOf<T>,710 what: ScheduledOf<T>,
641 ) -> Result<u32, (DispatchError, ScheduledOf<T>)> {711 ) -> Result<u32, (DispatchError, ScheduledOf<T>)> {
642 let mut agenda = Agenda::<T>::get(when);712 let mut agenda = Agenda::<T>::get(when);
643 let index = if (agenda.len() as u32) < T::MaxScheduledPerBlock::get() {713 let index = agenda
644 // will always succeed due to the above check.714 .try_push(what.clone())
645 let _ = agenda.try_push(Some(what));
646 agenda.len() as u32 - 1
647 } else {715 .ok_or((<Error<T>>::AgendaIsExhausted.into(), what))?;
648 if let Some(hole_index) = agenda.iter().position(|i| i.is_none()) {716
649 agenda[hole_index] = Some(what);
650 hole_index as u32
651 } else {
652 return Err((<Error<T>>::AgendaIsExhausted.into(), what));
653 }
654 };
655 Agenda::<T>::insert(when, agenda);717 Agenda::<T>::insert(when, agenda);
656 Ok(index)718 Ok(index)
657 }719 }
685 origin: Option<T::PalletsOrigin>,747 origin: Option<T::PalletsOrigin>,
686 (when, index): TaskAddress<T::BlockNumber>,748 (when, index): TaskAddress<T::BlockNumber>,
687 ) -> Result<(), DispatchError> {749 ) -> Result<(), DispatchError> {
688 let scheduled = Agenda::<T>::try_mutate(when, |agenda| {750 let scheduled = Agenda::<T>::try_mutate(
689 agenda.get_mut(index as usize).map_or(751 when,
690 Ok(None),
691 |s| -> Result<Option<Scheduled<_, _, _, _, _>>, DispatchError> {752 |agenda| -> Result<Option<Scheduled<_, _, _, _, _>>, DispatchError> {
692 if let (Some(ref o), Some(ref s)) = (origin, s.borrow()) {753 let scheduled = match agenda.get(index) {
754 Some(scheduled) => scheduled,
755 None => return Ok(None),
756 };
757
758 if let Some(ref o) = origin {
693 if matches!(759 if matches!(
694 T::OriginPrivilegeCmp::cmp_privilege(o, &s.origin),760 T::OriginPrivilegeCmp::cmp_privilege(o, &scheduled.origin),
695 Some(Ordering::Less) | None761 Some(Ordering::Less) | None
696 ) {762 ) {
697 return Err(BadOrigin.into());763 return Err(BadOrigin.into());
698 }764 }
699 };765 }
766
700 Ok(s.take())767 Ok(agenda.take(index))
701 },768 },
702 )769 )?;
703 })?;
704 if let Some(s) = scheduled {770 if let Some(s) = scheduled {
705 T::Preimages::drop(&s.call);771 T::Preimages::drop(&s.call);
706772
749 fn do_cancel_named(origin: Option<T::PalletsOrigin>, id: TaskName) -> DispatchResult {815 fn do_cancel_named(origin: Option<T::PalletsOrigin>, id: TaskName) -> DispatchResult {
750 Lookup::<T>::try_mutate_exists(id, |lookup| -> DispatchResult {816 Lookup::<T>::try_mutate_exists(id, |lookup| -> DispatchResult {
751 if let Some((when, index)) = lookup.take() {817 if let Some((when, index)) = lookup.take() {
752 let i = index as usize;
753 Agenda::<T>::try_mutate(when, |agenda| -> DispatchResult {818 Agenda::<T>::try_mutate(when, |agenda| -> DispatchResult {
754 if let Some(s) = agenda.get_mut(i) {819 let scheduled = match agenda.get(index) {
755 if let (Some(ref o), Some(ref s)) = (origin, s.borrow()) {820 Some(scheduled) => scheduled,
821 None => return Ok(()),
822 };
823
824 if let Some(ref o) = origin {
756 if matches!(825 if matches!(
757 T::OriginPrivilegeCmp::cmp_privilege(o, &s.origin),826 T::OriginPrivilegeCmp::cmp_privilege(o, &scheduled.origin),
758 Some(Ordering::Less) | None827 Some(Ordering::Less) | None
759 ) {828 ) {
760 return Err(BadOrigin.into());829 return Err(BadOrigin.into());
761 }
762 T::Preimages::drop(&s.call);
763 }830 }
764 *s = None;831 T::Preimages::drop(&scheduled.call);
765 }832 }
833
834 agenda.take(index);
835
766 Ok(())836 Ok(())
767 })?;837 })?;
768 Self::deposit_event(Event::Canceled { when, index });838 Self::deposit_event(Event::Canceled { when, index });
779 priority: schedule::Priority,849 priority: schedule::Priority,
780 ) -> DispatchResult {850 ) -> DispatchResult {
781 match Lookup::<T>::get(id) {851 match Lookup::<T>::get(id) {
782 Some((when, index)) => {852 Some((when, index)) => Agenda::<T>::try_mutate(when, |agenda| {
783 let i = index as usize;
784 Agenda::<T>::try_mutate(when, |agenda| {
785 if let Some(Some(s)) = agenda.get_mut(i) {853 let scheduled = match agenda.get_mut(index) {
786 if matches!(854 Some(scheduled) => scheduled,
787 T::OriginPrivilegeCmp::cmp_privilege(&origin, &s.origin),
788 Some(Ordering::Less) | None
789 ) {855 None => return Ok(()),
790 return Err(BadOrigin.into());
791 }856 };
792857
793 s.priority = priority;858 if matches!(
859 T::OriginPrivilegeCmp::cmp_privilege(&origin, &scheduled.origin),
860 Some(Ordering::Less) | None
861 ) {
862 return Err(BadOrigin.into());
863 }
864
865 scheduled.priority = priority;
794 Self::deposit_event(Event::PriorityChanged {866 Self::deposit_event(Event::PriorityChanged {
795 when,867 when,
796 index,868 index,
797 priority,869 priority,
798 });870 });
799 }871
800 Ok(())872 Ok(())
801 })873 }),
802 }
803 None => Err(Error::<T>::NotFound.into()),874 None => Err(Error::<T>::NotFound.into()),
804 }875 }
805 }876 }
885 let mut dropped = 0;956 let mut dropped = 0;
886957
887 for (agenda_index, _) in ordered.into_iter().take(max as usize) {958 for (agenda_index, _) in ordered.into_iter().take(max as usize) {
888 let task = match agenda[agenda_index as usize].take() {959 let task = match agenda.take(agenda_index).take() {
889 None => continue,960 None => continue,
890 Some(t) => t,961 Some(t) => t,
891 };962 };
899 break;970 break;
900 }971 }
901 let result = Self::service_task(weight, now, when, agenda_index, *executed == 0, task);972 let result = Self::service_task(weight, now, when, agenda_index, *executed == 0, task);
902 agenda[agenda_index as usize] = match result {973 match result {
903 Err((Unavailable, slot)) => {974 Err((Unavailable, slot)) => {
904 dropped += 1;975 dropped += 1;
905 slot976 agenda.set_slot(agenda_index, slot);
906 }977 }
907 Err((Overweight, slot)) => {978 Err((Overweight, slot)) => {
908 postponed += 1;979 postponed += 1;
909 slot980 agenda.set_slot(agenda_index, slot);
910 }981 }
911 Ok(()) => {982 Ok(()) => {
912 *executed += 1;983 *executed += 1;
913 None
914 }984 }
915 };985 };
916 }986 }
1062 return Err(Overweight);1132 return Err(Overweight);
1063 }1133 }
10641134
1065 // let scheduled_origin =
1066 // <<T as Config>::Origin as From<T::PalletsOrigin>>::from(origin.clone());
1067 let ensured_origin = T::ScheduleOrigin::ensure_origin(dispatch_origin.into());1135 let ensured_origin = T::ScheduleOrigin::ensure_origin(dispatch_origin.into());
10681136
1069 let r = match ensured_origin {1137 let r = match ensured_origin {