SHARE
TWEET

Untitled

a guest Mar 20th, 2017 49 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. using System;
  2. using System.Collections.Generic;
  3.  
  4. namespace PortsManager
  5. {
  6.     class PortsManager
  7.     {
  8.         int count = 0;
  9.  
  10.         readonly (int minPort, int maxPort) range;
  11.  
  12.         LinkedList<(int minPort, int maxPort)> ranges = new LinkedList<(int, int)>();
  13.  
  14.         internal PortsManager(int minPort, int maxPort)
  15.         {
  16.             count = maxPort - minPort + 1;
  17.             range = (minPort, maxPort);
  18.             ranges.AddLast(range);
  19.         }
  20.  
  21.         internal int Count { get => count; }
  22.  
  23.         internal bool IsPortAvailable(int port)
  24.         {
  25.             if (port < range.minPort || port > range.maxPort)
  26.             {
  27.                 return false;
  28.             }
  29.  
  30.             for (var node = ranges.First; node != null; node = node.Next)
  31.             {
  32.                 var range = node.Value;
  33.                 if (port >= range.minPort && port <= range.maxPort)
  34.                 {
  35.                     return true;
  36.                 }
  37.             }
  38.             return false;
  39.         }
  40.  
  41.         internal int? GetPort()
  42.         {
  43.             if (ranges.Count > 0)
  44.             {
  45.                 var range = ranges.First.Value;
  46.                 int port = range.minPort++;
  47.                 ranges.RemoveFirst();
  48.                 if (range.minPort <= range.maxPort)
  49.                 {
  50.                     ranges.AddFirst(range);
  51.                 }
  52.                 --count;
  53.                 return port;
  54.             }
  55.             return null;
  56.         }
  57.  
  58.         internal void ReturnPort(int port)
  59.         {
  60.             if (port < range.minPort || port > range.maxPort)
  61.             {
  62.                 return;
  63.             }
  64.  
  65.             ++count;
  66.             for (var node = ranges.First; node != null; node = node.Next)
  67.             {
  68.                 var range = node.Value;
  69.                 if (port < range.minPort)
  70.                 {
  71.                     if (port == range.minPort - 1)
  72.                     {
  73.                         if (node.Previous != null && port == node.Previous.Value.maxPort + 1)
  74.                         {
  75.                             // the port bridges the gap between two adjacent ranges, merge them
  76.                             range.minPort = node.Previous.Value.minPort;
  77.                             ranges.Remove(node.Previous);
  78.                         }
  79.                         else
  80.                         {
  81.                             // just merge the port into the current range
  82.                             --range.minPort;
  83.                         }
  84.                         var next = node.Next;
  85.                         ranges.Remove(node);
  86.                         node = next != null ? ranges.AddBefore(next, range) : ranges.AddLast(range);
  87.                         return;
  88.                     }
  89.                     if (node.Previous != null)
  90.                     {
  91.                         if (port == node.Previous.Value.maxPort + 1)
  92.                         {
  93.                             // merge with the previous node, and done
  94.                             range.minPort = node.Previous.Value.minPort;
  95.                             range.maxPort = node.Previous.Value.maxPort + 1;
  96.                             ranges.Remove(node.Previous);
  97.                             ranges.AddBefore(node, range);
  98.                             return;
  99.                         }
  100.                     }
  101.                     // add a new range
  102.                     ranges.AddBefore(node, (port, port));
  103.                     return;
  104.                 }
  105.                 else if (port <= range.maxPort)
  106.                 {
  107.                     --count; // NB: this is the only scenario where 'count' shouldn't be incremented
  108.                     return;
  109.                 }
  110.                 else if (node.Next == null)
  111.                 {
  112.                     if (port == range.maxPort + 1)
  113.                     {
  114.                         ++range.maxPort;
  115.                         ranges.RemoveLast();
  116.                         ranges.AddLast(range);
  117.                         return;
  118.                     }
  119.                 }
  120.             }
  121.  
  122.             // if control comes here, the port forms the last range
  123.             ranges.AddLast((port, port));
  124.         }
  125.  
  126.         internal void VerifyIntegrity()
  127.         {
  128.             int count = 0;
  129.             for (var node = ranges.First; node != null; node = node.Next)
  130.             {
  131.                 var range = node.Value;
  132.                 System.Diagnostics.Debug.Assert(range.minPort <= range.maxPort);
  133.                 count += range.maxPort - range.minPort + 1;
  134.  
  135.                 if (node.Previous != null)
  136.                 {
  137.                     System.Diagnostics.Debug.Assert(node.Previous.Value.maxPort < range.minPort - 1);
  138.                 }
  139.             }
  140.             System.Diagnostics.Debug.Assert(count == this.count);
  141.         }
  142.     }
  143.  
  144.     class Program
  145.     {
  146.         static void Main(string[] args)
  147.         {
  148.             PortsManager pm = new PortsManager(1, 100);
  149.  
  150.             Random rnd = new Random();
  151.             for (var c = 0; c < 100; ++c)
  152.             {
  153.                 for (var i = 0; i < 50; ++i)
  154.                 {
  155.                     var port = pm.GetPort();
  156.                     Console.WriteLine($"GetPort: {port}");
  157.                 }
  158.                 pm.VerifyIntegrity();
  159.                 Console.WriteLine($"Count: {pm.Count}");
  160.                 for (var i = 0; i < 100; ++i)
  161.                 {
  162.                     var port = rnd.Next(1, 100);
  163.                     Console.WriteLine($"ReturnPort: {port}");
  164.                     pm.ReturnPort(port);
  165.                 }
  166.                 pm.VerifyIntegrity();
  167.                 Console.WriteLine($"Count: {pm.Count}");
  168.             }
  169.         }
  170.     }
  171. }
RAW Paste Data
Top