singrdk/base/Services/NetStack/Runtime/Reservations.cs

204 lines
7.1 KiB
C#

// ----------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ----------------------------------------------------------------------------
///
// Microsoft Corporation, Redmond, WA.
// author: Glenn Peterson
//
// #define DEBUG_RESERVATIONS
using System;
using System.Collections;
//using System.Diagnostics;
//using System.Net.IP;
//using Microsoft.Singularity;
//using Drivers.Net;
//using NetStack.Common;
//using NetStack.NetDrivers;
//using NetStack.Protocols;
namespace NetStack.Runtime
{
/// <summary>
/// An enumeration describing a Reservation's current state: Under-, Over-,
/// and Limit- Utilized. It's used to control service to the Reservation's
/// sessions.
/// </summary>
public enum ReservationCategory
{
/// <summary>
/// This Reservation's Utilization is less than its "Reservation" level.
/// </summary>
/// <remarks>
/// This reservation's sessions are serviced at high priority.
/// </remarks>
UnderUtilized = 0,
/// <summary>
/// This Reservation's Utilization is more than its "Reservation" level
/// and less that its "Maximum" level.
/// </summary>
/// <remarks>
/// This reservation's sessions are serviced at low priority.
/// </remarks>
OverUtilized = 1,
/// <summary>
/// This Reservation's Utilization is more than its "Maximum" level.
/// </summary>
/// <remarks>
/// This reservation's sessions are not serviced.
/// </remarks>
LimitUtilized = 2,
}
/// <summary>
/// A collection of Reservations of the same Category (Under/Over/Limit).
/// </summary>
internal class ReservationsByCategory
{
private ReservationCategory reservationCategory;
private readonly ArrayList reservations = new ArrayList();
public ReservationsByCategory(ReservationCategory reservationCategory)
{
this.reservationCategory = reservationCategory;
}
public ReservationCategory ReservationCategory
{
get { return this.reservationCategory; }
}
public void AddReservation(Reservation reservation)
{
this.reservations.Add(reservation);
}
public void RemoveReservation(Reservation reservation)
{
this.reservations.Remove(reservation);
}
}
/// <summary>
/// A Network Reservation, containing of a collection of Network Sessions.
/// </summary>
/// <remarks>
/// In addition to the collection of sessions, a Reservation contains
/// housekeeping information: currentUtilization, the time the
/// currentUtilization was computed, Reservation category, and the
/// utilization limits: Reserved and Maximum. It also has the time
/// (measured form the time the current utilization was computed) that
/// it will become elegible to transfer to a more active category -
/// assuming it remains idle if in the "OverUtilized" category.
/// </remarks>
internal class Reservation
{
public const double AveragingSeconds = 1.0;
// public static TimeSpan AveragingTimeSpan =
// TimeSpan.FromSeconds(Reservation.AveragingSeconds);
// Sessions sharing this Reservation
private readonly ArrayList sessions;
// Utilization Limits for this Reservation.
private double reservationUtilization;
private double maximumUtilization;
// Utilization and when Computed
private double currentUtilization;
private DateTime currentUtilizationEvaluationTime;
private ReservationsByCategory reservationsByCategory;
public Reservation(double reservationUtilization,
double maximumUtilization)
{
// Initialize Readonly Fields
this.sessions = new ArrayList();
// Initialize Dynamic Fields
this.reservationUtilization = reservationUtilization;
this.maximumUtilization = maximumUtilization;
this.currentUtilization = reservationUtilization * 0.5; // TODO: Revisit GRP
this.currentUtilizationEvaluationTime = DateTime.Now;
}
public void AddSession(Session session)
{
this.sessions.Add(session);
}
public void RemoveSession(Session session)
{
this.sessions.Remove(session);
}
public void ChangeReservationLimits(double reservationUtilization,
double maximumUtilization)
{
this.reservationUtilization = reservationUtilization;
this.maximumUtilization = maximumUtilization;
this.CheckCategory();
}
public void MergeUtilizationsWithDamping(double utilization,
TimeSpan duration)
{
// Compute the weighted (merged) utilization.
double durationSeconds = duration.TotalSeconds;
double mergedUtilization = this.currentUtilization * Reservation.AveragingSeconds
+ utilization * durationSeconds;
// Rescale the merged Utilization and its Evaluation Time.
this.currentUtilization =
mergedUtilization * Reservation.AveragingSeconds /
(durationSeconds + Reservation.AveragingSeconds);
this.currentUtilizationEvaluationTime += duration;
// See if we're in a new Category (Under/Over/Limit).
this.CheckCategory();
}
private void CheckCategory()
{
ReservationCategory newCategory = ReservationCategory.UnderUtilized;
if (this.currentUtilization > this.reservationUtilization)
{
newCategory = (this.currentUtilization > this.maximumUtilization)
? ReservationCategory.OverUtilized : ReservationCategory.LimitUtilized;
}
if (newCategory != this.reservationsByCategory.ReservationCategory)
{
ChangeCategory(newCategory);
}
}
private void ChangeCategory(ReservationCategory newCategory)
{
ReservationsByCategory newReservationsByCategory = new ReservationsByCategory(ReservationCategory.OverUtilized); // BUGBUG: TODO: Look up in Array (GRP)
this.reservationsByCategory.RemoveReservation(this);
newReservationsByCategory.AddReservation(this);
this.reservationsByCategory = newReservationsByCategory;
if (newCategory == ReservationCategory.OverUtilized)
{
// Stur pot. (Check appropriate queue - we may be able to start transmitting / receiving. // TODO GRP.
}
}
}
}