Main Page | Class Hierarchy | Class List | File List | Class Members

SmartDeviceGUIClient/NACKManager.cs

00001 using System;
00002 using System.Collections;
00003 using System.Threading;
00004 
00005 namespace SmartDeviceGUIClient
00006 {
00011         public class NACKManager {}
00012 
00013 //      public class NACKManager2
00014 //      {
00015 //              /** Fields **/
00016 //              private NackQueue nackQueue; // queue of NACKs waiting to be sent out
00017 //              private TransmissionQueue txQueue; // the transmission queue in which to output things
00018 //              private RemoteHostComms thisRemoteHost;
00019 //
00020 //              /** Constructors **/
00021 //              /// <summary>
00022 //              /// Creates a new NACK Manager, outputting NACKs and retransmissions into a given TransmissionQueue
00023 //              /// </summary>
00024 //              public NACKManager2(RemoteHostComms thisRemoteHost) {
00025 //                      this.thisRemoteHost = thisRemoteHost;
00026 //                      nackQueue = new NackQueue();
00027 //                      this.txQueue = thisRemoteHost.TxQueue;
00028 //              }
00029 //
00030 //              public void ResetConnections() {
00031 //                      Console.WriteLine("NACK Manager Reset Starting ...");
00032 //                      nackQueue.Clear();
00033 //                      Console.WriteLine("... NACK Manager Reset Complete");
00034 //              }
00035 //
00036 //              /// <summary>
00037 //              /// returns null if no nacks waiting otherwise returns the next nack to be issued.
00038 //              /// </summary>
00039 //              /// <returns>Next NACK to be issued, or null if there are none</returns>
00040 //              public NackInfo GetNextNack() {
00041 //                      /* only one thread should be calling this at any given time, so no need to lock */
00042 //                      if (nackQueue.IsEmpty) { return null; }
00043 //                      else return nackQueue.Dequeue();
00044 //              }
00045 //
00046 //              public void ProcessReceivedSegmentHeaders(ref SegmentHeaders newHeaders) {
00047 //                      /* examines headers to see which segments need to be retransmitted */
00048 //                      /* calculate end point of nack range 
00049 //                       * use it in a for loop to add a nack retransmision message to the relevant queue */
00050 //                      uint lastNACK;
00051 //                      uint firstNACK;
00052 //                      ushort destination;
00053 //                      //Console.WriteLine("NACK Manager: Process Received Segment Headers");
00054 //                      if (newHeaders.IsNACK) { // Retransmit
00055 //                              firstNACK = newHeaders.NackInfo.SequenceNumber;
00056 //                              if (newHeaders.NackInfo.IsRanged) { lastNACK = firstNACK + newHeaders.NackInfo.Range; }
00057 //                              else { lastNACK = firstNACK; }
00058 //                              destination = newHeaders.SourceDeviceID; // this should always be the same.
00059 //
00060 //                              // TODO: Fix so that range can wrap round.
00061 //                              for (uint i = firstNACK; i <= lastNACK; i++) {
00062 //                                      // grab segment from retransmission buffer
00063 //                                      Segment tempSegment = thisRemoteHost.RetransmissionBuffer.GetSegment(i);
00064 //                                      // encapsulate segment in retransmission message
00065 //                                      RetransmissionMessage retransMessage = new RetransmissionMessage(tempSegment);
00066 //                                      // set the destination of the retransmission
00067 //                                      retransMessage.Destination = destination;
00068 //                                      // plonk message into the correct transmission queue
00069 //                                      TransmissionQueueEntry[] entries = TransmissionQueueEntry.FromMessage(retransMessage);
00070 //                                      txQueue.Enqueue(entries, false);
00071 //                                      Console.WriteLine("NACK Manager: Issued Reransmision of #" + i);
00072 //                              }
00073 //                      }
00074 //              }
00075 //
00076 //              /// <summary>
00077 //              /// Initiates the issuing of a single-segment NACK
00078 //              /// </summary>
00079 //              /// <param name="segmentNumber">Sequence number of the missing segment</param>
00080 //              public void IssueNACK(uint segmentNumber) {
00081 //                      SendNACK(new NackInfo(segmentNumber));
00082 //              }
00083 //
00084 //              /// <summary>
00085 //              /// Initiates the issuing of a contigious multi-segment NACK
00086 //              /// </summary>
00087 //              /// <param name="segmentNumber">Sequence number of the first missing segment in the sequence</param>
00088 //              /// <param name="Range">The number of subsequent missing segments</param>
00089 //              public void IssueNACK(uint segmentNumber, long range) {
00090 //                      for (long offset = 0; offset < range; offset++) {
00091 //                              IssueNACK((uint)(segmentNumber + offset));
00092 //                      }
00093 //                      //SendNACK(new NackInfo(segmentNumber, (uint)range));
00094 //              }
00095 //
00096 //              private void SendNACK(NackInfo nackInfo) {
00097 //                      lock (txQueue.SyncRoot) {
00098 //                              if (txQueue.IsEmpty) {
00099 //                                      /* create no-op message */
00100 //                                      Message noopMsg = new EmptyMessage();
00101 //                                      noopMsg.Destination = thisRemoteHost.RemoteDeviceID;
00102 //                                      /* segmentise */
00103 //                                      TransmissionQueueEntry[] buffer = TransmissionQueueEntry.FromMessage(noopMsg);
00104 //                                      /* place results in segment queue */
00105 //                                      // make sure this all happens in a monitor, so we get them all together
00106 //                                      txQueue.EnqueueUnprotected(buffer, false);
00107 //                              }
00108 //                              nackQueue.Enqueue(nackInfo);
00109 //                              Console.WriteLine("NACK Manager: NACK Sent for #" + nackInfo.SequenceNumber + " Range: " + (nackInfo.IsRanged ? nackInfo.Range.ToString() : "N/A"));
00110 //                              Monitor.PulseAll(txQueue.SyncRoot);
00111 //                      }
00112 //              }
00113 //      }
00114 
00115         /*****************************************************************************/
00116         public class NackInfo {
00118                 bool isRanged;
00119                 uint sequenceNumber;
00120                 uint range;
00121 
00123                 public NackInfo(uint sequenceNumber) {
00124                         this.isRanged = false;
00125                         this.sequenceNumber = sequenceNumber;
00126                 }
00127 
00128                 public NackInfo(uint sequenceNumber, uint range) {
00129                         this.isRanged = true;
00130                         this.sequenceNumber = sequenceNumber;
00131                         this.range = range;
00132                 }
00133 
00135                 public bool IsRanged { get { return isRanged; }}
00136                 public uint SequenceNumber { get { return sequenceNumber; } }
00137                 public uint Range { get { return range; } }
00138 
00139 
00140         }
00141 
00142 
00143         /*****************************************************************************/
00147 //      class NackQueue : Queue {
00148 //              public NackQueue() : base() {}
00149 //
00150 //              /// <summary>
00151 //              /// Adds an item to the Nack Queue. 
00152 //              /// Thread Safe
00153 //              /// </summary>
00154 //              /// <param name="nackInfo">The Nack Information structure to add</param>
00155 //              public void Enqueue(NackInfo nackInfo) {
00156 //                      lock (this.SyncRoot) {
00157 //                              base.Enqueue(nackInfo);                 
00158 //                      } 
00159 //              }
00160 //
00161 //              public new NackInfo Dequeue() { // this must not block and wait, because of where it's tested.
00162 //                      NackInfo result;
00163 //                      lock (this.SyncRoot) {
00164 //                              result = (NackInfo)base.Dequeue();
00165 //                      }
00166 //                      return result;
00167 //              }
00168 //
00169 //              public bool IsEmpty {
00170 //                      get {
00171 //                              bool result;
00172 //                              lock (this.SyncRoot) {
00173 //                                      result = (this.Count == 0);
00174 //                              }
00175 //                              return result;
00176 //                      }
00177 //              }
00178 //      }
00179 //
00180 //      /*****************************************************************************/
00181 //      public class RetransmissionBuffer {
00182 //              /* Contains a copy of every segment that may be requested by a 
00183 //               * negative acknowledgement.
00184 //               * 
00185 //               * Data is indexed by segment number. Segment number and timestamp
00186 //               * would have been better, but without adding another field to a
00187 //               * segment we can not be sure of selecting the correct segment for
00188 //               * retransmission.
00189 //               * 
00190 //               * If a segment is retransmitted, it will not need to be re-transmitted again
00191 //               * (the segment encapsulating the retransmission will be retransmitted). So we 
00192 //               * can erase the segment from the buffer when it is sent for retransmission.
00193 //               * 
00194 //               * If segment m is such that all segments < m have been received, and m is a NACK 
00195 //               * requesting segment n, then we can retransmit 'n' and erase from the buffer
00196 //               * all segments <= n. 
00197 //               * 
00198 //               * Let's just weaken this condition to 'if there are no missing segments'. 
00199 //               * This is the case where m is the segment just received. And to be honest, 
00200 //               * this is likely to be the case.
00201 //               * 
00202 //               * Failure case: some segment > m is carrying a NACK for segment < n. 
00203 //               * This would occur if... there is no way this would occur.
00204 //               * 
00205 //               * Note that all segments < m must have been received, not NACKd.
00206 //               * 
00207 //               * As a failsafe we should have a 'Segment not in Buffer' message for problems.
00208 //               * */
00209 //              /** fields **/
00210 //              Hashtable buffer;
00211 //              private SequenceManager seqManager;
00212 //              
00213 //              /** properties */
00214 //              private uint earliestSegmentNumber {
00215 //                      get { 
00216 //                              // TODO: Correct Min for wrapround error
00217 //                              lock (buffer.SyncRoot) {
00218 //                                      ICollection keys = buffer.Keys;
00219 //                                      uint[] keyArray = new uint[keys.Count];
00220 //                                      keys.CopyTo(keyArray, 0);
00221 //                                      Array.Sort(keyArray);
00222 //                                      return keyArray[0];
00223 //                              }
00224 //                      }
00225 //              }
00226 //
00227 //              /** constructors **/
00228 //              public RetransmissionBuffer(SequenceManager seqManager) {
00229 //                      this.seqManager = seqManager;
00230 //                      buffer = new Hashtable();
00231 //              }
00232 //
00233 //              /** methods**/
00234 //              /// <summary>
00235 //              /// Called on Connection Reset to return retransmission buffer to initial state
00236 //              /// </summary>
00237 //              public void ResetConnection() {
00238 //                      lock (buffer.SyncRoot) {
00239 //                              buffer.Clear();
00240 //                      }
00241 //              }
00242 //
00243 //
00244 //              /// <summary>
00245 //              /// Adds segment
00246 //              /// </summary>
00247 //              private void Add(Segment target) {
00248 //                      lock (buffer.SyncRoot) {
00249 //                              buffer.Add(target.Headers.SequenceNumber, target);
00250 //                      }
00251 //
00252 //              }
00253 //
00254 //              /// <summary>
00255 //              /// Removes a single segment based on segment number 
00256 //              /// </summary>
00257 //              private void Remove(uint segmentNumber) {
00258 //                      lock (buffer.SyncRoot) {
00259 //                              buffer.Remove(segmentNumber);
00260 //                      }
00261 //              }
00262 //
00263 //              /// <summary>
00264 //              /// Reads a segment from the Retransmission Buffer
00265 //              /// </summary>
00266 //              /// <returns>The segment requested</returns>
00267 //              private Segment Read(uint segmentNumber) {
00268 //                      lock (buffer.SyncRoot) {
00269 //                              return (Segment)buffer[segmentNumber];
00270 //                      }
00271 //              }
00272 //
00273 //              /// <summary>
00274 //              /// Retrieves a segment from the buffer for retransmission, 
00275 //              /// and removes segments no longer needed
00276 //              /// </summary>
00277 //              /// <param name="nackSegmentHeaders">sequence number to retransmitt</param>
00278 //              /// <returns>Segment to be retransmitted</returns>
00279 //              public Segment GetSegment(uint sequenceNumber) {
00280 //                      lock (buffer.SyncRoot) {
00281 //                              Segment result = null;
00282 //
00283 //                              result = Read(sequenceNumber);
00284 //                              /* when we erase all segments 'less' than n, how do we identify them? They could wrap round,
00285 //                               * and thus some could be > n. Perhaps we should have a linked list type index structure? */
00286 //                              /* or perhaps we should have some kind of 'earliest segment' indicator. */
00287 //                              if (!seqManager.IsSegmentsMissing) {
00288 //                                      // erase all segments less than nackSegmentHeaders.SequenceNumber
00289 //                                      // i.e. all the ones that were put in before it.
00290 //                                      if (earliestSegmentNumber > sequenceNumber) {
00291 //                                              for (long i = sequenceNumber; i >= 0; i--) {
00292 //                                                      this.Remove((uint)i); }
00293 //                                              for (long i = UInt32.MaxValue; i >= earliestSegmentNumber; i--) {
00294 //                                                      this.Remove((uint)i); }
00295 //                                      } else { // earliestSegmentNumber <= nackSegmentHeaders.SequenceNumber
00296 //                                              for (long i = sequenceNumber; i >= earliestSegmentNumber; i--) {
00297 //                                                      this.Remove((uint)i); }
00298 //                                      }
00299 //                              } // else  there are segments missing, so we can't erase anything for certain, so noop.
00300 //                              return result;
00301 //                      }
00302 //              }
00303 //
00304 //              /// <summary>
00305 //              /// Inserts a segment into the retransmission buffer
00306 //              /// </summary>
00307 //              /// <param name="target">The segment object to insert</param>
00308 //              public void PutSegment(Segment target) {
00309 //                      // todo: handle exceptions, etc.
00310 //                      lock (buffer.SyncRoot) {
00311 //                              this.Add(target);
00312 //                      }
00313 //              }
00314 //      
00315 //
00316 //      }
00317 }

Generated on Mon May 8 22:07:27 2006 by  doxygen 1.3.9.1