public char ReadChar() { InitializeReading(); try { long startingPos = this.byteBuffer.Position; try { int type = this.dataIn.ReadByte(); if (type == PrimitiveMap.CHAR_TYPE) { return(this.dataIn.ReadChar()); } else if (type == PrimitiveMap.NULL) { this.byteBuffer.Seek(startingPos, SeekOrigin.Begin); throw new NMSException("Cannot convert Null type to a char"); } else { this.byteBuffer.Seek(startingPos, SeekOrigin.Begin); throw new MessageFormatException("Value is not a Char type."); } } catch (FormatException e) { this.byteBuffer.Seek(startingPos, SeekOrigin.Begin); throw NMSExceptionSupport.CreateMessageFormatException(e); } } catch (EndOfStreamException e) { throw NMSExceptionSupport.CreateMessageEOFException(e); } catch (IOException e) { throw NMSExceptionSupport.CreateMessageFormatException(e); } }
public object ReadObject() { FailIfWriteOnlyMsgBody(); FailIfBytesInBuffer(); object result = null; object value = null; try { value = cloak.Peek(); if (value == null) { result = null; } else if (value is byte[]) { byte[] buffer = value as byte[]; result = new byte[buffer.Length]; Array.Copy(buffer, 0, result as byte[], 0, buffer.Length); } else if (ConversionSupport.IsNMSType(value)) { result = value; } } catch (EndOfStreamException eos) { throw NMSExceptionSupport.CreateMessageEOFException(eos); } catch (IOException ioe) { throw NMSExceptionSupport.CreateMessageFormatException(ioe); } catch (Exception e) { Tracer.InfoFormat("Unexpected exception caught reading Object stream. Exception = {0}", e); throw NMSExceptionSupport.Create("Unexpected exception caught reading Object stream.", e); } cloak.Pop(); return(result); }
public void WriteString(string value) { InitializeWriting(); try { if (value.Length > 8192) { this.dataOut.Write(PrimitiveMap.BIG_STRING_TYPE); this.dataOut.WriteString32(value); } else { this.dataOut.Write(PrimitiveMap.STRING_TYPE); this.dataOut.WriteString16(value); } } catch (IOException e) { NMSExceptionSupport.Create(e); } }
internal void OnAsyncException(Exception error) { if (!this.closed.Value && !this.closing.Value) { if (this.ExceptionListener != null) { if (!(error is NMSException)) { error = NMSExceptionSupport.Create(error); } NMSException e = (NMSException)error; // Called in another thread so that processing can continue // here, ensures no lock contention. executor.QueueUserWorkItem(AsyncCallExceptionListener, e); } else { Tracer.Debug("Async exception with no exception listener: " + error); } } }
/// <summary> /// Used to get an enqueued message from the unconsumedMessages list. The /// amount of time this method blocks is based on the timeout value. if /// timeout == Timeout.Infinite then it blocks until a message is received. /// if timeout == 0 then it it tries to not block at all, it returns a /// message if it is available if timeout > 0 then it blocks up to timeout /// amount of time. Expired messages will consumed by this method. /// </summary> /// <param name="timeout"> /// A <see cref="System.TimeSpan"/> /// </param> /// <returns> /// A <see cref="MessageDispatch"/> /// </returns> private MessageDispatch Dequeue(TimeSpan timeout) { DateTime deadline = DateTime.Now; if (timeout > TimeSpan.Zero) { deadline += timeout; } while (true) { MessageDispatch dispatch = this.unconsumedMessages.Dequeue(timeout); // Grab a single date/time for calculations to avoid timing errors. DateTime dispatchTime = DateTime.Now; if (dispatch == null) { if (timeout > TimeSpan.Zero && !this.unconsumedMessages.Closed) { if (dispatchTime > deadline) { // Out of time. timeout = TimeSpan.Zero; } else { // Adjust the timeout to the remaining time. timeout = deadline - dispatchTime; } } else { // Informs the caller of an error in the event that an async exception // took down the parent connection. if (this.failureError != null) { throw NMSExceptionSupport.Create(this.failureError); } return(null); } } else if (dispatch.Message == null) { return(null); } else if (!IgnoreExpiration && dispatch.Message.IsExpired()) { Tracer.DebugFormat("{0} received expired message: {1}", info.ConsumerId, dispatch.Message.MessageId); BeforeMessageIsConsumed(dispatch); AfterMessageIsConsumed(dispatch, true); // Refresh the dispatch time dispatchTime = DateTime.Now; if (timeout > TimeSpan.Zero && !this.unconsumedMessages.Closed) { if (dispatchTime > deadline) { // Out of time. timeout = TimeSpan.Zero; } else { // Adjust the timeout to the remaining time. timeout = deadline - dispatchTime; } } } else { return(dispatch); } } }
public Object ReadObject() { InitializeReading(); long startingPos = this.byteBuffer.Position; try { int type = this.dataIn.ReadByte(); if (type == PrimitiveMap.BIG_STRING_TYPE) { return(this.dataIn.ReadString32()); } else if (type == PrimitiveMap.STRING_TYPE) { return(this.dataIn.ReadString16()); } else if (type == PrimitiveMap.LONG_TYPE) { return(this.dataIn.ReadInt64()); } else if (type == PrimitiveMap.INTEGER_TYPE) { return(this.dataIn.ReadInt32()); } else if (type == PrimitiveMap.SHORT_TYPE) { return(this.dataIn.ReadInt16()); } else if (type == PrimitiveMap.FLOAT_TYPE) { return(this.dataIn.ReadSingle()); } else if (type == PrimitiveMap.DOUBLE_TYPE) { return(this.dataIn.ReadDouble()); } else if (type == PrimitiveMap.CHAR_TYPE) { return(this.dataIn.ReadChar()); } else if (type == PrimitiveMap.BYTE_TYPE) { return(this.dataIn.ReadByte()); } else if (type == PrimitiveMap.BOOLEAN_TYPE) { return(this.dataIn.ReadBoolean()); } else if (type == PrimitiveMap.BYTE_ARRAY_TYPE) { int length = this.dataIn.ReadInt32(); byte[] data = new byte[length]; this.dataIn.Read(data, 0, length); return(data); } else if (type == PrimitiveMap.NULL) { return(null); } else { this.byteBuffer.Seek(startingPos, SeekOrigin.Begin); throw new MessageFormatException("Value is not a known type."); } } catch (FormatException e) { this.byteBuffer.Seek(startingPos, SeekOrigin.Begin); throw NMSExceptionSupport.CreateMessageFormatException(e); } catch (EndOfStreamException e) { throw NMSExceptionSupport.CreateMessageEOFException(e); } catch (IOException e) { throw NMSExceptionSupport.CreateMessageFormatException(e); } }
public string ReadString() { InitializeReading(); long startingPos = this.byteBuffer.Position; try { int type = this.dataIn.ReadByte(); switch (type) { case PrimitiveMap.BIG_STRING_TYPE: return(this.dataIn.ReadString32()); case PrimitiveMap.STRING_TYPE: return(this.dataIn.ReadString16()); case PrimitiveMap.LONG_TYPE: return(this.dataIn.ReadInt64().ToString()); case PrimitiveMap.INTEGER_TYPE: return(this.dataIn.ReadInt32().ToString()); case PrimitiveMap.SHORT_TYPE: return(this.dataIn.ReadInt16().ToString()); case PrimitiveMap.FLOAT_TYPE: return(this.dataIn.ReadSingle().ToString()); case PrimitiveMap.DOUBLE_TYPE: return(this.dataIn.ReadDouble().ToString()); case PrimitiveMap.CHAR_TYPE: return(this.dataIn.ReadChar().ToString()); case PrimitiveMap.BYTE_TYPE: return(this.dataIn.ReadByte().ToString()); case PrimitiveMap.BOOLEAN_TYPE: return(this.dataIn.ReadBoolean().ToString()); case PrimitiveMap.NULL: return(null); default: this.byteBuffer.Seek(startingPos, SeekOrigin.Begin); throw new MessageFormatException("Value is not a known type."); } } catch (FormatException e) { this.byteBuffer.Seek(startingPos, SeekOrigin.Begin); throw NMSExceptionSupport.CreateMessageFormatException(e); } catch (EndOfStreamException e) { throw NMSExceptionSupport.CreateMessageEOFException(e); } catch (IOException e) { throw NMSExceptionSupport.CreateMessageFormatException(e); } }
/// <summary> /// Sets the public properties of a target object using a string map. /// This method uses .Net reflection to access public properties of /// the target object matching the keys from the passed map. /// </summary> /// <param name="target">The object whose properties will be set.</param> /// <param name="valueMap">Map of key/value pairs.</param> /// <param name="nameMap">Map of key/property name pairs.</param> public static void SetProperties(object target, StringDictionary valueMap, StringDictionary nameMap) { Tracer.DebugFormat("SetProperties called with target: {0}", target.GetType().Name); // Application of specified values is recursive. If a key does not // correspond to a member of the current target object, it is // supposed to refer to a sub-member of such a member. Since member // keys can contain dot characters, an attempt is made to find the // "longest" key corresponding to a member of the current object // (this identifies the "sub-target"), and extract the remaining // key characters as a sub-key to sub-members. // The following dictionary indexes keys to "sub-targets", and // "sub-key"/value pairs to assign to "sub-targets". Dictionary <string, StringDictionary> subTargetMap = null; foreach (string key in valueMap.Keys) { if (nameMap.ContainsKey(key)) { // Key refers to a member of the current target string memberName = nameMap[key]; MemberInfo member = FindMemberInfo(target, memberName); if (member == null) { // Should not happen if the nameMap was indeed created // for the current target object... throw new NMSException(string.Format( "No such property or field: {0} on class: {1}", memberName, target.GetType().Name)); } // Set value try { if (member.MemberType == MemberTypes.Property) { PropertyInfo property = (PropertyInfo)member; object value = ConvertValue(valueMap[key], property.PropertyType); property.SetValue(target, value, null); } else { FieldInfo field = (FieldInfo)member; object value = ConvertValue(valueMap[key], field.FieldType); field.SetValue(target, value); } } catch (Exception ex) { throw NMSExceptionSupport.Create( "Error while attempting to apply option.", ex); } } else { // Key does NOT refers to a member of the current target // Extract maximal member key + subkeys string memberKey = key; int dotPos = memberKey.LastIndexOf('.'); bool memberFound = false; while (!memberFound && dotPos > 0) { memberKey = memberKey.Substring(0, dotPos); if (nameMap.ContainsKey(memberKey)) { memberKey = nameMap[memberKey]; memberFound = true; } else { dotPos = memberKey.LastIndexOf('.'); } } if (!memberFound) { throw new NMSException(string.Format( "Unknown property or field: {0} on class: {1}", key, target.GetType().Name)); } // Register memberKey, subKey and value for further processing string subKey = key.Substring(dotPos + 1); StringDictionary subValueMap; if (subTargetMap == null) { subTargetMap = new Dictionary <string, StringDictionary>(); } if (!subTargetMap.TryGetValue(memberKey, out subValueMap)) { subValueMap = new StringDictionary(); subTargetMap.Add(memberKey, subValueMap); } // In theory, we can't have the same subkey twice, since // they were unique subkeys from another dictionary. // Therefore, no need to check for subValueMap.ContainsKey. subValueMap.Add(subKey, valueMap[key]); } } // Now process any compound assignments. if (subTargetMap != null) { foreach (string subTargetKey in subTargetMap.Keys) { MemberInfo member = FindMemberInfo(target, subTargetKey); object subTarget = GetUnderlyingObject(member, target); SetProperties(subTarget, subTargetMap[subTargetKey]); } } }
private IMessage ReceiveInternal(int timeout) { try { long deadline = 0; if (timeout > 0) { deadline = GetDeadline(timeout); } while (true) { InboundMessageDispatch envelope = messageQueue.Dequeue(timeout); if (failureCause != null) { throw NMSExceptionSupport.Create(failureCause); } if (envelope == null) { return(null); } if (IsMessageExpired(envelope)) { if (Tracer.IsDebugEnabled) { Tracer.Debug($"{Info.Id} filtered expired message: {envelope.Message.NMSMessageId}"); } DoAckExpired(envelope); if (timeout > 0) { timeout = (int)Math.Max(deadline - DateTime.UtcNow.Ticks / 10_000L, 0); } } else if (IsRedeliveryExceeded(envelope)) { if (Tracer.IsDebugEnabled) { Tracer.Debug($"{Info.Id} filtered message with excessive redelivery count: {envelope.RedeliveryCount}"); } // TODO: Apply redelivery policy DoAckExpired(envelope); } else { if (Tracer.IsDebugEnabled) { Tracer.Debug($"{Info.Id} received message {envelope.Message.NMSMessageId}."); } AckFromReceive(envelope); return(envelope.Message.Copy()); } } } catch (NMSException) { throw; } catch (Exception ex) { throw ExceptionSupport.Wrap(ex, "Receive failed"); } }
/// <summary> /// Sets the public properties of a target object using a string map. /// This method uses .Net reflection to identify public properties of /// the target object matching the keys from the passed map. /// </summary> /// <param name="target">The object whose properties will be set.</param> /// <param name="map">Map of key/value pairs.</param> /// <param name="prefix">Key value prefix. This is prepended to the property name /// before searching for a matching key value.</param> public static void SetProperties(object target, StringDictionary map, string prefix) { Tracer.DebugFormat("SetProperties called with target: {0}, and prefix: {1}", target.GetType().Name, prefix); foreach (string key in map.Keys) { if (key.StartsWith(prefix, StringComparison.InvariantCultureIgnoreCase)) { string propertyName = key.Substring(prefix.Length); // Process all member assignments at this level before processing // any deeper member assignments. if (!propertyName.Contains(".")) { MemberInfo member = FindPropertyInfo(target, propertyName); if (member == null) { throw new NMSException(string.Format("No such property or field: {0} on class: {1}", propertyName, target.GetType().Name)); } try { if (member.MemberType == MemberTypes.Property) { PropertyInfo property = member as PropertyInfo; property.SetValue(target, Convert.ChangeType(map[key], property.PropertyType, CultureInfo.InvariantCulture), null); } else { FieldInfo field = member as FieldInfo; field.SetValue(target, Convert.ChangeType(map[key], field.FieldType, CultureInfo.InvariantCulture)); } } catch (Exception ex) { throw NMSExceptionSupport.Create("Error while attempting to apply option.", ex); } } } } IList <string> propertiesSet = new List <string>(); // Now process any compound assignments, ensuring that once we recurse into an // object we don't do it again as there could be multiple compunds element assignments // and they'd have already been processed recursively. foreach (string key in map.Keys) { if (key.StartsWith(prefix, StringComparison.InvariantCultureIgnoreCase)) { string propertyName = key.Substring(prefix.Length); if (propertyName.Contains(".")) { string newTargetName = propertyName.Substring(0, propertyName.IndexOf('.')); string newPrefix = prefix + newTargetName + "."; if (!propertiesSet.Contains(newPrefix)) { MemberInfo member = FindPropertyInfo(target, newTargetName); object newTarget = GetUnderlyingObject(member, target); SetProperties(newTarget, map, newPrefix); propertiesSet.Add(newPrefix); } } } } }
public void Close() { if (!this.closed.Value && !transportFailed.Value) { this.Stop(); } lock (connectedLock) { if (this.closed.Value) { return; } try { Tracer.InfoFormat("Connection[{0}]: Closing Connection Now.", this.ClientId); this.closing.Value = true; Scheduler scheduler = this.scheduler; if (scheduler != null) { try { scheduler.Stop(); } catch (Exception e) { throw NMSExceptionSupport.Create(e); } } lock (sessions.SyncRoot) { foreach (Session session in sessions) { session.Shutdown(); } } sessions.Clear(); // Connected is true only when we've successfully sent our CONNECT // to the broker, so if we haven't announced ourselves there's no need to // inform the broker of a remove, and if the transport is failed, why bother. if (connected.Value && !transportFailed.Value) { DISCONNECT disconnect = new DISCONNECT(); transport.Oneway(disconnect); } executor.Shutdown(); if (!executor.AwaitTermination(TimeSpan.FromMinutes(1))) { Tracer.DebugFormat("Connection[{0}]: Failed to properly shutdown its executor", this.ClientId); } Tracer.DebugFormat("Connection[{0}]: Disposing of the Transport.", this.ClientId); transport.Stop(); transport.Dispose(); } catch (Exception ex) { Tracer.ErrorFormat("Connection[{0}]: Error during connection close: {1}", ClientId, ex); } finally { if (executor != null) { executor.Shutdown(); } this.transport = null; this.closed.Value = true; this.connected.Value = false; this.closing.Value = false; } } }