/// <summary> /// Constructs a new message queue. /// </summary> public MessageQueue() { this.CurrentFrame = MessageFrame.Acquire(); this.SecondaryHash = Filter <uint> .HashInt32( (uint)(Interlocked.Increment(ref NextId)) ); }
/// <summary> /// Publishes a message to a remote server. /// </summary> /// <param name="contract">The contract</param> /// <param name="channel">The channel to publish to.</param> /// <param name="reply">The reply handler.</param> public void Enqueue(int contract, string channel, ArraySegment <byte> message) { lock (this.PublishLock) { // Try to append the message directly, and exit once we're done //this.MsgSend.Increment(); while (!this.CurrentFrame.TryAppendMessage(contract, channel, message)) { // The frame is full, enqueue it to the pending queue and acquire a new one this.FrameQueue.Enqueue(this.CurrentFrame); this.CurrentFrame = MessageFrame.Acquire(); } } }
/// <summary> /// Handles frames of the mesh layer. /// </summary> /// <param name="server">The server sending the frame.</param> /// <param name="frame">The data frame to process.</param> /// <returns>The processing state of the event.</returns> public ProcessingState ProcessFrame(IServer server, ArraySegment <byte> frame) { MessageFrame.TryParse(frame); return(ProcessingState.Success); }
/// <summary> /// This sends all the frames though the message bus. /// </summary> private static void Flush() { // This task should run while the service is running Console.WriteLine("Messaging: Starting publisher on thread #" + Thread.CurrentThread.ManagedThreadId); while (Service.IsRunning) { try { // Measure one send using (Profiler.Default.Measure("MessageQueue.Flush")) { // Go through all the connections foreach (var server in Service.Mesh.Members) { // Get the message queue var mq = server.Session as MessageQueue; if (mq == null || server.State != ServerState.Online) { continue; } // Acquire a lock on the current frame so we can push it to the pending queue lock (mq.PublishLock) { // If frame is empty, ignore if (mq.CurrentFrame.Length > 0) { // The frame is not full, but push it anyway mq.FrameQueue.Enqueue(mq.CurrentFrame); mq.CurrentFrame = MessageFrame.Acquire(); } } MessageFrame frame; while (mq.FrameQueue.TryDequeue(out frame)) { try { // Send the buffer server.Send( MeshFrame.Acquire(frame.AsSegment()) ); } catch (Exception ex) { // Catch all exceptions here and print it out Service.Logger.Log(ex); } finally { // Once the frame is sent, release it frame.TryRelease(); } } } } // Wait for the messages to queue up Thread.Sleep(2); } catch (Exception ex) { // Log the exception Service.Logger.Log(ex); } } }