/// <summary> /// Add a subscription for a specific event /// </summary> /// <param name="eventType">EventType being subscribed to</param> /// <param name="localOnly">Specifies if subscription is only for local machine or global</param> /// <param name="methodBody">String containing the method body defining the filter</param> /// <param name="usingLibraries">List of using libraries which the method requires, null if none required</param> /// <param name="referencedAssemblies">List of referenced assemblies which the method requires, null if none required</param> public void AddSubscription(Guid eventType, bool localOnly, string methodBody, List <string> usingLibraries, List <string> referencedAssemblies) { ReturnCode rc; Subscription subscription = new Subscription(); subscription.SubscriptionEventType = eventType; subscription.Subscribe = true; subscription.LocalOnly = localOnly; subscription.MethodBody = methodBody; subscription.UsingLibraries = usingLibraries; subscription.ReferencedAssemblies = referencedAssemblies; WspEvent wspEvent = new WspEvent(Subscription.SubscriptionEvent, null, subscription.Serialize()); publishMgr.Publish(wspEvent.SerializedEvent, out rc); Dictionary <string, Subscription> subscriptionFilter; if (subscriptions.TryGetValue(eventType, out subscriptionFilter) == false) { subscriptions[eventType] = new Dictionary <string, Subscription>(); } subscriptions[eventType][methodBody] = subscription; }
/// <summary> /// Remove a subscription for a specific event /// </summary> /// <param name="eventType">EventType being unsubscribed to</param> /// <param name="localOnly">Specifies if subscription is only for local machine or global</param> /// <param name="methodBody">String containing the method body defining the filter</param> /// <param name="usingLibraries">List of using libraries which the method requires, null if none required</param> /// <param name="referencedAssemblies">List of referenced assemblies which the method requires, null if none required</param> /// <returns>True if successful</returns> public bool RemoveSubscription(Guid eventType, bool localOnly, string methodBody, List <string> usingLibraries, List <string> referencedAssemblies) { ReturnCode rc; Subscription subscription = null; Dictionary <string, Subscription> subscriptionFilter; if (subscriptions.TryGetValue(eventType, out subscriptionFilter) == true) { if (subscriptionFilter.TryGetValue(methodBody, out subscription) == true) { subscription.Subscribe = false; WspEvent wspEvent = new WspEvent(Subscription.SubscriptionEvent, null, subscription.Serialize()); publishMgr.Publish(wspEvent.SerializedEvent, out rc); subscriptionFilter.Remove(methodBody); if (subscriptionFilter.Count == 0) { subscriptions.Remove(eventType); } } } return(true); }
/// <summary> /// Dequeues events from shared memory /// </summary> internal void Listener() { WspEvent wspEvent; DateTime nextPushSubscriptions = DateTime.UtcNow.AddMinutes(subscriptionRefreshIncrement); ReturnCode rc; try { Thread.CurrentThread.Priority = ThreadPriority.Highest; byte[] buffer = null; while (StopListening == false) { try { buffer = eventQueue.Dequeue(Timeout); if (buffer != null) { try { wspEvent = new WspEvent(buffer); } catch (Exception e) { EventLog.WriteEntry("WspEventRouter", "Event has invalid format: " + e.ToString(), EventLogEntryType.Error); continue; } List <WspEventObservable> observables; if (WspEventObservable.eventObservables.TryGetValue(wspEvent.EventType, out observables) == true) { for (int i = 0; i < observables.Count; i++) { observables[i].queue.Enqueue(wspEvent, wspEvent.SerializedEvent.Length); } } } if (DateTime.UtcNow > nextPushSubscriptions) { try { foreach (Guid subId in subscriptions.Keys) { foreach (string expression in subscriptions[subId].Keys) { WspEvent subEvent = new WspEvent(Subscription.SubscriptionEvent, null, subscriptions[subId][expression].Serialize()); publishMgr.Publish(subEvent.SerializedEvent, out rc); } } nextPushSubscriptions = DateTime.UtcNow.AddMinutes(subscriptionRefreshIncrement); } catch { // intentionally left blank // it will retry next time } } } catch (PubSubException e) { EventLog.WriteEntry("WspEventRouter", "Exception occurred processing event from shared queue: " + e.ToString(), EventLogEntryType.Error); continue; } catch (Exception e) { EventLog.WriteEntry("WspEventRouter", "Exception occurred processing event from shared queue: " + e.ToString(), EventLogEntryType.Error); continue; } } } catch (ThreadAbortException) { // Another thread has signalled that this worker // thread must terminate. Typically, this occurs when // the main service thread receives a service stop // command. } catch (AccessViolationException) { // This can occur after the thread has been stopped and the runtime is doing GC. // Just let the thread quit to end listening. } catch (SharedQueueException e) { throw new PubSubException(e.Message, e.InnerException); } }
/// <summary> /// Base contructor to deserialize a byte array into a WspEvent object /// </summary> /// <param name="serializationData">Serialized WspEvent</param> /// <param name="inRouterNameArray">A UTF-8 encoded byte array of the InRouterName </param> /// <param name="inRouterName">Name of the router that the event was passed in from</param> public static WspEvent ChangeInRouterName(byte[] serializationData, byte[] inRouterNameArray, string inRouterName) { WspEvent wspEvent = new WspEvent(); int position = 0; int positionOfInRouterName = 0; Int32 oldTotalLength; Int32 newTotalLength; Int32 oldHeaderLength = 0; Int32 newHeaderLength = 0; Int32 oldInRouterNameLength = 0; Int32 bodyLength; HeaderType headerType; Int32 valueLength; oldTotalLength = Read(serializationData, ref position); oldHeaderLength = Read(serializationData, ref position); Int32 headerLength = oldHeaderLength + sizeof(Int32) + sizeof(Int32); while (position < headerLength) { headerType = (HeaderType)serializationData[position]; position++; valueLength = Read(serializationData, ref position); if (headerType == HeaderType.InRouterName) { oldInRouterNameLength = valueLength; positionOfInRouterName = position; wspEvent.Headers[(byte)headerType] = inRouterName; Read(serializationData, ref position, valueLength); } else { wspEvent.Headers[(byte)headerType] = Read(serializationData, ref position, valueLength); } } bodyLength = Read(serializationData, ref position); wspEvent.Body = new byte[bodyLength]; Buffer.BlockCopy(serializationData, position, wspEvent.Body, 0, bodyLength); wspEvent.EventType = new Guid(wspEvent.Headers[(byte)HeaderType.EventType]); wspEvent.OriginatingRouterName = wspEvent.Headers[(byte)HeaderType.OriginatingRouter]; wspEvent.InRouterName = wspEvent.Headers[(byte)HeaderType.InRouterName]; wspEvent.Version = new Version(wspEvent.Headers[(byte)HeaderType.Version]); wspEvent.TimeStamp = long.Parse(wspEvent.Headers[(byte)HeaderType.UtcTimestamp]); newTotalLength = oldTotalLength + (inRouterNameArray.Length - oldInRouterNameLength); newHeaderLength = oldHeaderLength + (inRouterNameArray.Length - oldInRouterNameLength); wspEvent.SerializedEvent = new byte[newTotalLength]; int location = 0; int copyLength; Buffer.BlockCopy(BitConverter.GetBytes((Int32)newTotalLength), 0, wspEvent.SerializedEvent, location, sizeof(Int32)); location += sizeof(Int32); Buffer.BlockCopy(BitConverter.GetBytes((Int32)newHeaderLength), 0, wspEvent.SerializedEvent, location, sizeof(Int32)); location += sizeof(Int32); copyLength = positionOfInRouterName - sizeof(Int32) - location; Buffer.BlockCopy(serializationData, location, wspEvent.SerializedEvent, location, copyLength); location += copyLength; Buffer.BlockCopy(BitConverter.GetBytes((Int32)inRouterNameArray.Length), 0, wspEvent.SerializedEvent, location, sizeof(Int32)); location += sizeof(Int32); Buffer.BlockCopy(inRouterNameArray, 0, wspEvent.SerializedEvent, location, inRouterNameArray.Length); location += inRouterNameArray.Length; copyLength = newTotalLength - location; Buffer.BlockCopy(serializationData, oldTotalLength - copyLength, wspEvent.SerializedEvent, location, copyLength); location += copyLength; return(wspEvent); }