public void Add(ItemOutQueue item, bool first) { // contador Interlocked.Increment(ref countAdded); lock (sync) { try { list.Enqueue(item); // aumentamos el contador de items countItems++; } catch (Exception err) { Node.LogAppendLine("#@ Error al añadir el paquete a la cola de salida {0}", err.Message); item.packetSent.Set(); throw err; } finally { // wake-up anyone waiting on an empty queue Monitor.Pulse(sync); } } }
/// <summary> /// llamado desde la hebra q va a enviar los mensajes de la cola /// </summary> public void ProcSendPacket() { while (sending) { // contador Interlocked.Increment(ref numSenderThreadLaps); ItemOutQueue item = null; try { item = outQueue.NextItem(); IWorkItemResult result = m_STP.QueueWorkItem( new WorkItemCallback(SendItem), item); } catch (Exception err) { Node.LogAppendLine("#@ Error Enviar el paquete", err.Message); if (item != null) { item.exception = new DodoException(err, "Error al enviar el paquete"); } /* * if (item != null) * item.Dispose(); */ } } }
/// <summary> /// obtener el siguiente paquete o esperar hasta q haya uno /// </summary> /// <returns></returns> public ItemOutQueue NextItem() { // contador Interlocked.Increment(ref countRemoved); lock (sync) { ItemOutQueue ret = null; try { while (working) { if (list.Count > 0) { for (int x = 0; x < list.Count; x++) { ret = list.Peek() as ItemOutQueue; if (!ret.route.InUse) { list.Dequeue(); // marcamos la ruta ret.route.InUse = true; // disminuimos el contador countItems--; break; } else { ret = null; } } } if (ret == null) { // if we don't find anything to send, just wait for a signal Monitor.Wait(sync); } else { break; } } return(ret); } catch (Exception err) { Node.LogAppendLine("#@ Error Enviar el paquete sin dirección", err.Message); return(ret); } } }
/// <summary> /// Añade un paquete a la cola de salida de paquetes. Si se completa la cola de salida, espera hasta /// estar de nuevo disponible /// </summary> /// <param name="__sp"></param> /// <returns></returns> public bool AddPacketQueueOut(Route route, Packet packet, bool ctrl) { ItemOutQueue item = null; try { bool ret = false; if (route != null) { // contador Interlocked.Increment(ref numPacketToSend); // creamos el item de la cola de salida item = new ItemOutQueue(route, packet, outQueue); // contador de items preparados numPreparedItems++; // enviar item SendItem(item); // comprobamos que no haya habido error al enviar el paquete // - como hemos tenido que esperar para enviar el paquete // si hubo error al enviarlo lo lanzamos aqui if (item.exception != null) { throw item.exception; } } else { Exception err = new Exception("Paquete sin dirección"); Node.LogAppendLine("#@ Error Enviar el paquete sin dirección {0}", err.Message); throw err; } return(ret); } catch (Exception err) { throw err; } finally { if (item != null) { item.Dispose(); } } }
/// <summary> /// enviar paquetes de salida /// </summary> /// <param name="__packet"></param> /// <param name="__dest"></param> private object SendItem(object param) { // contador Interlocked.Increment(ref numSendPacketCalls); ItemOutQueue item = null; try { item = (ItemOutQueue)param; // calculamos cuanto tenemos que esperar para mantener el ancho de banda DateTime wait = AcpTransmissionInterval(); TimeSpan tsWaiting = (TimeSpan)wait.Subtract(DateTime.Now); if (tsWaiting.Ticks > 0) { Thread.Sleep(tsWaiting); } item.route.Send(item.packet.GetBytes(), item.idx, item.packet.GetNumBytes()); // marcamos la fecha/hora de la ultima keepalive item.route.UpdateActivity(); // actualizar contadores UpdatePerformanceBytes(item.packet.GetNumBytes()); // actualizamos los contadores numSentItems++; numPreparedItems--; } catch (ObjectDisposedException err) { item.exception = new DodoException(err, "Error al enviar un paquete a {0} Error: {1} Nombre objeto: {2}", item.dest, err.Message, err.ObjectName); item.sendFailed = false; } catch (SocketException err) { item.exception = new DodoException(err, "Error al enviar un paquete a {0} socketError: {1}", item.dest.IPEndPoint, err.ErrorCode); item.sendFailed = false; } catch (Exception err) { item.exception = new DodoException(err, "Error al enviar un paquete a {0} Error: {1}", item.dest, err.Message); item.sendFailed = false; } finally { if (item != null) { try { if (item.sendFailed) { localNode.RouteTable.RemoveRoute(item.route); Node.LogAppendLine("No se pudo enviar mensaje por la ruta {0}", item.route.remoteNodeAddress); } // terminamos de usar la ruta item.route.InUse = false; // fin de la espera item.waitingEnd = DateTime.Now.TimeOfDay.ToString(); // debloqueamos hebra item.packetSent.Set(); // if some thread is waiting for this route item.outQueue.WakeUp(); // destruimos el objeto //-- item.Dispose(); } catch (Exception err) { Node.LogAppendLine(err); } } } return(item); }