/** <summary>This is called if the cache's don't have an Address mapping. It prepares an asynchronous Dht query if one doesn't already exist, that is only one query at a time per IP regardless of how many misses occur. The ansychonorous call back is call MissCallback.</summary> <param name="ip">The IP Address to look up in the Dht.</param> */ protected bool Miss(MemBlock ip) { Channel queue = null; lock(_sync) { if (_queued.Contains(ip)) { return false; } _queued[ip] = true; queue = new Channel(); queue.CloseEvent += MissCallback; _mapping[queue] = ip; } String ips = Utils.MemBlockToString(ip, '.'); ProtocolLog.WriteIf(IpopLog.ResolverLog, String.Format( "Adding {0} to queue.", ips)); /* * If we were already looking up this string, there * would be a table entry, since there is not, start a * new lookup */ byte[] key = Encoding.UTF8.GetBytes("dhcp:" + _ipop_namespace + ":" + ips); try { _dht.AsyncGet(key, queue); } catch { queue.CloseEvent -= MissCallback; lock(_sync) { _queued.Remove(ip); _mapping.Remove(queue); } queue.Close(); } return true; }
public void ChannelTests() { Channel c0 = new Channel(); bool e_event_fired = false; c0.EnqueueEvent += delegate(object o, EventArgs arg) { e_event_fired = true; }; c0.Enqueue(0); bool c_event_fired = false; c0.CloseEvent += delegate(object o, EventArgs arg) { c_event_fired = true; }; c0.Close(); Assert.IsTrue(c_event_fired, "CloseEvent"); c0 = new Channel(); c0.CloseAfterEnqueue(); c_event_fired = false; c0.CloseEvent += delegate(object o, EventArgs arg) { c_event_fired = true; }; c0.Enqueue(1); //This should close the channel: Assert.IsTrue(c_event_fired, "CloseEvent on Enqueue"); Assert.IsTrue(c0.Closed, "Closed"); c0 = new Channel(1); c_event_fired = false; c0.CloseEvent += delegate(object o, EventArgs arg) { c_event_fired = true; }; c0.Enqueue(1); //This should close the channel: Assert.IsTrue(c_event_fired, "CloseEvent on Enqueue"); Assert.IsTrue(c0.Closed, "Closed"); //Try with different starting values: Random r = new Random(); int en_count; for(int i = 0; i < 100; i++) { int max_enqueues = r.Next(1, 1000); c0 = new Channel(max_enqueues); c_event_fired = false; en_count = 0; c0.CloseEvent += delegate(object o, EventArgs arg) { c_event_fired = true; }; c0.EnqueueEvent += delegate(object o, EventArgs arg) { en_count++; }; for(int j = 0; j < max_enqueues; j++) { c0.Enqueue(j); } Assert.IsTrue(c_event_fired, "CloseEvent on Enqueue"); Assert.AreEqual(en_count, max_enqueues, "EnqueueEvent count"); Assert.IsTrue(c0.Closed, "Closed"); try { c0.Enqueue(null); Assert.IsTrue(false, "Enqueue after close didn't fail"); } catch { Assert.IsTrue(true, "Enqueue after close Got exception"); } } }