public static async Task<TransactionalState> GetTransactionalStateAsync(Link link) { Transaction txn = Transaction.Current; if (txn != null) { byte[] txnId = await instance.EnlistAsync(link, txn); return new TransactionalState() { TxnId = txnId }; } return null; }
Controller GetOrCreateController(Link link) { Controller controller; lock (this.SyncRoot) { if (!this.controllers.TryGetValue(link.Session.Connection, out controller)) { Session session = new Session(link.Session.Connection); controller = new Controller(session); controller.Closed += this.OnControllerClosed; this.controllers.Add(link.Session.Connection, controller); } } return controller; }
async Task<byte[]> EnlistAsync(Link link, Transaction txn) { string id = txn.TransactionInformation.LocalIdentifier; Enlistment enlistment; lock (this.SyncRoot) { if (!this.enlistments.TryGetValue(id, out enlistment)) { enlistment = new Enlistment(this, txn); this.enlistments.Add(id, enlistment); txn.TransactionCompleted += this.OnTransactionCompleted; if (!txn.EnlistPromotableSinglePhase(enlistment)) { this.enlistments.Remove(id); txn.TransactionCompleted -= this.OnTransactionCompleted; throw new InvalidOperationException("DTC not supported"); } } } return await enlistment.EnlistAsync(link); }
internal virtual void OnAttach(Attach attach) { lock (this.ThisLock) { if (attach.Handle > this.handleMax) { throw new AmqpException(ErrorCode.NotAllowed, Fx.Format(SRAmqp.AmqpHandleExceeded, this.handleMax + 1)); } for (int i = 0; i < this.localLinks.Length; ++i) { Link link = this.localLinks[i]; if (link != null && string.Compare(link.Name, attach.LinkName) == 0) { link.OnAttach(attach.Handle, attach); int count = this.remoteLinks.Length; if (count - 1 < attach.Handle) { int size = Math.Min(count * 2, (int)this.handleMax + 1); Link[] expanded = new Link[size]; Array.Copy(this.remoteLinks, expanded, count); this.remoteLinks = expanded; } var remoteLink = this.remoteLinks[attach.Handle]; if (remoteLink != null) { throw new AmqpException(ErrorCode.HandleInUse, Fx.Format(SRAmqp.AmqpHandleInUse, attach.Handle, remoteLink.Name)); } this.remoteLinks[attach.Handle] = link; return; } } } throw new AmqpException(ErrorCode.NotFound, Fx.Format(SRAmqp.LinkNotFound, attach.LinkName)); }
internal uint AddLink(Link link) { this.ThrowIfEnded("AddLink"); lock (this.ThisLock) { int count = this.localLinks.Length; for (int i = 0; i < count; ++i) { if (this.localLinks[i] == null) { this.localLinks[i] = link; return (uint)i; } } if (count - 1 < this.handleMax) { int size = Math.Min(count * 2, (int)this.handleMax + 1); Link[] expanded = new Link[size]; Array.Copy(this.localLinks, expanded, count); this.localLinks = expanded; this.localLinks[count] = link; return (ushort)count; } throw new AmqpException(ErrorCode.NotAllowed, Fx.Format(SRAmqp.AmqpHandleExceeded, this.handleMax + 1)); } }
public async Task<byte[]> EnlistAsync(Link link) { if (this.txnid != null) { return this.txnid; } lock (this.syncRoot) { if (this.declareTask == null) { this.controller = this.owner.GetOrCreateController(link); this.declareTask = this.controller.DeclareAsync(); } } return this.txnid = await this.declareTask; }
internal Delivery RemoveDeliveries(Link link) { LinkedList list = null; lock (this.ThisLock) { Delivery temp = (Delivery)this.outgoingList.First; while (temp != null) { Delivery curr = temp; temp = (Delivery)temp.Next; if (curr.Link == link) { this.outgoingList.Remove(curr); if (list == null) { list = new LinkedList(); } list.Add(curr); } } } return list == null ? null : (Delivery)list.First; }
internal void RemoveLink(Link link, uint remoteHandle) { lock (this.ThisLock) { this.localLinks[link.Handle] = null; this.remoteLinks[remoteHandle] = null; } }
internal uint AddLink(Link link) { this.ThrowIfEnded("AddLink"); lock (this.ThisLock) { int index = -1; int count = this.localLinks.Length; for (int i = 0; i < count; ++i) { if (this.localLinks[i] == null) { if (index < 0) { index = i; } } else if (string.Compare(this.localLinks[i].Name, link.Name) == 0) { throw new AmqpException(ErrorCode.NotAllowed, link.Name + " has been attached."); } } if (index >= 0) { this.localLinks[index] = link; return (uint)index; } if (count - 1 < this.handleMax) { int size = (int)Math.Min(count * 2 - 1, this.handleMax) + 1; Link[] expanded = new Link[size]; Array.Copy(this.localLinks, expanded, count); this.localLinks = expanded; this.localLinks[count] = link; return (ushort)count; } throw new AmqpException(ErrorCode.NotAllowed, Fx.Format(SRAmqp.AmqpHandleExceeded, this.handleMax + 1)); } }
internal void AddRemoteLink(uint remoteHandle, Link link) { lock (this.ThisLock) { int count = this.remoteLinks.Length; if (count - 1 < remoteHandle) { int size = (int)Math.Min(count * 2 - 1, this.handleMax) + 1; Link[] expanded = new Link[size]; Array.Copy(this.remoteLinks, expanded, count); this.remoteLinks = expanded; } var remoteLink = this.remoteLinks[remoteHandle]; if (remoteLink != null) { throw new AmqpException(ErrorCode.HandleInUse, Fx.Format(SRAmqp.AmqpHandleInUse, remoteHandle, remoteLink.Name)); } this.remoteLinks[remoteHandle] = link; } }
void AddLink(Link link, bool role, string source, string target) { int index; link.Handle = this.GetLinkHandle(out index); link.RemoteHandle = (uint)~index; this.links[index] = link; link.State = AttachSent; List attach = new List() { link.Name, link.Handle, link.Role, null, null, new DescribedValue(0x28ul, new List() { source }), new DescribedValue(0x29ul, new List() { target }) }; this.WriteFrame(0, 0, 0x12, attach); Fx.DebugPrint(true, 0, "attach", attach, "name", "handle", "role", "snd-mode", "rcv-mode", "source", "target"); }
void RaiseErrorEvent(Link link, Symbol error) { var onError = this.OnError; if (onError != null) { onError.Invoke(this, link, error); } }
internal void CloseLink(Link link) { link.State |= DetachSent; List detach = new List { link.Handle, true }; this.WriteFrame(0, 0, 0x16, detach); Fx.DebugPrint(true, 0, "detach", detach, "handle"); try { this.Wait(o => (((Link)o).State & DetachReceived) == 0, link, 60000); } finally { link.State = 0xff; int index = (int)link.RemoteHandle; lock (this) { if (index >= 0) { this.links[index] = null; } else { this.links[~index] = null; } } } }
static void client_OnError(Client client, Link link, Symbol error) { Microsoft.SPOT.Debug.Print((link != null ? "Link" : "Client") + " was closed due to error " + (error ?? "[unknown]")); }
void OnFrame(ushort channel, ulong code, List fields, ByteBuffer payload) { switch (code) { case 0x10ul: // open Fx.DebugPrint(false, channel, "open", fields, "container-id", "host-name", "max-frame-size", "channel-max", "idle-time-out"); this.state |= OpenReceived; // process open.idle-time-out if exists: final value is determined by the min of the local and the remote values uint remoteValue = uint.MaxValue; if (fields.Count >= 5 && fields[4] != null) { remoteValue = (uint)fields[4]; } uint timeout = this.idleTimeout < remoteValue ? this.idleTimeout : remoteValue; if (timeout < uint.MaxValue) { timeout -= 5000; timeout = timeout > MaxIdleTimeout ? MaxIdleTimeout : timeout; this.heartBeatTimer = new Timer(onHeartBeatTimer, this, (int)timeout, (int)timeout); } break; case 0x11ul: // begin Fx.DebugPrint(false, channel, "begin", fields, "remote-channel", "next-outgoing-id", "incoming-window", "outgoing-window", "handle-max"); this.nextIncomingId = (uint)fields[1]; this.outWindow = (uint)fields[2]; this.state |= BeginReceived; break; case 0x12ul: // attach { Fx.DebugPrint(false, channel, "attach", fields, "name", "handle", "role", "snd-mode", "rcv-mode", "source", "target"); Link link = null; uint remoteHandle = (uint)fields[1]; Fx.AssertAndThrow(ErrorCode.ClientInvalidHandle, remoteHandle < this.links.Length); lock (this) { for (int i = 0; i < this.links.Length; i++) { if (this.links[i] != null && this.links[i].Name.Equals(fields[0])) { link = this.links[i]; int index = (int)~link.RemoteHandle; Fx.AssertAndThrow(ErrorCode.ClientInvalidHandle, index == i); if (index != (int)remoteHandle) { Fx.AssertAndThrow(ErrorCode.ClientHandlInUse, this.links[(int)remoteHandle] == null); this.links[(int)remoteHandle] = link; this.links[i] = null; } break; } } } Fx.AssertAndThrow(ErrorCode.ClientLinkNotFound, link != null); link.RemoteHandle = remoteHandle; link.State |= AttachReceived; link.OnAttach(fields); break; } case 0x13ul: // flow { Fx.DebugPrint(false, channel, "flow", fields, "next-in-id", "in-window", "next-out", "out-window", "handle", "dc", "credit"); uint nextIncomingId = (uint)fields[0]; uint incomingWindow = (uint)fields[1]; lock (this) { this.outWindow = incomingWindow < uint.MaxValue ? nextIncomingId + incomingWindow - this.nextOutgoingId : uint.MaxValue; } if (fields[4] != null) { Link link = this.links[(uint)fields[4]]; Fx.AssertAndThrow(ErrorCode.ClientLinkNotFound, link != null); link.OnFlow(fields); } break; } case 0x14ul: // transfer { lock (this) { this.nextOutgoingId++; if (--this.inWindow == 0) { this.inWindow = DefaultWindowSize; List flow = new List() { this.nextIncomingId, this.inWindow, this.nextOutgoingId, this.outWindow }; this.WriteFrame(0, 0, 0x13, flow); Fx.DebugPrint(true, 0, "flow", flow, "next-in-id", "in-window", "next-out", "out-window", "handle", "dc", "credit"); } } Link link = this.links[(uint)fields[0]]; Fx.AssertAndThrow(ErrorCode.ClientLinkNotFound, link != null); ((Receiver)link).OnTransfer(fields, payload); break; } case 0x15ul: // disposition { Fx.DebugPrint(false, channel, "disposition", fields, "role", "first", "last"); bool role = (bool)fields[0]; uint first = (uint)fields[1]; uint last = fields[2] == null ? first : (uint)fields[2]; for (int i = 0; i < this.links.Length; i++) { Link link = this.links[i]; if (link != null && role != link.Role) { link.OnDisposition(first, last, fields[4] as DescribedValue); } } break; } case 0x16ul: // detach { Fx.DebugPrint(false, channel, "detach", fields, "handle"); Link link = this.links[(uint)fields[0]]; Fx.AssertAndThrow(ErrorCode.ClientLinkNotFound, link != null); link.State |= DetachReceived; if ((link.State & DetachSent) == 0) { this.CloseLink(link); this.RaiseErrorEvent(link, GetError(fields, 2)); } break; } case 0x17ul: // end Fx.DebugPrint(false, channel, "end", null); this.state |= EndReceived; if ((this.state & EndSent) == 0) { this.WriteFrame(0, 0, 0x17ul, new List()); Fx.DebugPrint(true, channel, "end", null); this.ClearLinks(); } break; case 0x18ul: // close Fx.DebugPrint(false, channel, "close", null); this.state |= CloseReceived; if ((this.state & CloseSent) == 0) { this.Close(); this.RaiseErrorEvent(null, GetError(fields, 0)); } break; default: Fx.AssertAndThrow(ErrorCode.ClientInvalidCodeOnFrame, false); break; } }