/// <summary> /// Increases all queue counters according to the provided message and /// puts a message into the queue. /// </summary> /// <param name="message">The message being put into the queue.</param> /// <param name="onlyCheckIn">Check the message in without adding it to any queues.</param> public void AddMessage(Message message, bool onlyCheckIn) { BinaryLogWriter binaryLogWriter = GenuineLoggingServices.BinaryLogWriter; using (new ReaderAutoLocker(this._disposeLock)) { if (this._disposed) { throw OperationException.WrapException(this._disposeException); } int maxContentSize = 0; if (message.SecuritySessionParameters != null) { maxContentSize = message.SecuritySessionParameters.MaxContentSize; } if (maxContentSize == 0) { maxContentSize = this._maxContentSize; } if (maxContentSize > 0 && !this._noSizeChecking) { // calculate message effective size try { if (message.SerializedContent != null && message.SerializedContent.CanSeek) { message.EffectiveMessageSize = (int)message.SerializedContent.Length; } // else if (message.Stream != null && message.Stream.CanSeek) // message.EffectiveMessageSize = (int) message.Stream.Length; } catch (Exception ex) { // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.ImplementationWarning] > 0) { binaryLogWriter.WriteEvent(LogCategory.ImplementationWarning, "MessageContainer.AddMessage", LogMessageType.Warning, ex, message, message.Recipient, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, -1, 0, 0, 0, null, null, null, null, "Message stream doesn't support the Length property. Set the NoSizeChecking parameter to true to increase performance"); } } try { if (message.SerializedContent != null && message.EffectiveMessageSize == 0 && message.SerializedContent.CanSeek) { message.EffectiveMessageSize = Math.Min(message.EffectiveMessageSize, (int)message.SerializedContent.Length); } } catch (Exception ex) { // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.ImplementationWarning] > 0) { binaryLogWriter.WriteEvent(LogCategory.ImplementationWarning, "MessageContainer.AddMessage", LogMessageType.Warning, ex, message, message.Recipient, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, -1, 0, 0, 0, null, null, null, null, "Message stream doesn't support the Length property. Set the NoSizeChecking parameter to true to increase performance"); } } // check the message size if (message.EffectiveMessageSize > maxContentSize) { throw GenuineExceptions.Get_Send_TooLargePacketSize((int)message.EffectiveMessageSize, maxContentSize); } } bool overloaded = false; lock (this._queue) { // check on total size if (this._currentTotalMessages + 1 > this._maxQueuedItems || message.EffectiveMessageSize + this._currentTotalSize > this._maxTotalSize) { // to prevent a deadlock overloaded = true; } else { this._currentTotalMessages++; this._currentTotalSize += message.EffectiveMessageSize; // put it into the queue or awaiting list if (!onlyCheckIn) { this._queue.Enqueue(message); // reflect the change in the queue state if (message.Recipient != null) { message.Recipient.QueueLength = this._queue.Count; } // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.MessageProcessing] > 0) { binaryLogWriter.WriteEvent(LogCategory.MessageProcessing, "MessageContainer.AddMessage", LogMessageType.MessageIsEnqueued, null, message, message.Recipient, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, -1, 0, 0, 0, null, null, null, null, "The message has been enqueued because no connections are available. Messages in the queue: {0}. Queue size: {1}.", this._currentTotalMessages, this._currentTotalSize); } } } } // lock (this._queue) if (overloaded) { Exception exception = GenuineExceptions.Get_Send_QueueIsOverloaded(this._maxQueuedItems, this._currentTotalMessages + 1, this._maxTotalSize, message.EffectiveMessageSize + this._currentTotalSize); // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.MessageProcessing] > 0) { binaryLogWriter.WriteEvent(LogCategory.MessageProcessing, "MessageContainer.AddMessage", LogMessageType.MessageIsEnqueued, exception, message, message.Recipient, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, -1, 0, 0, 0, null, null, null, null, "Queue is overrun."); } this.Dispose(exception); throw exception; } } }