protected BaseWoopsaSubscriptionServiceSubscription( WoopsaSubscriptionChannel channel, WoopsaContainer root, int subscriptionId, string propertyPath, TimeSpan monitorInterval, TimeSpan publishInterval) { Channel = channel; Root = root; SubscriptionId = subscriptionId; MonitorInterval = monitorInterval; PublishInterval = publishInterval; PropertyPath = propertyPath; _lock = new object(); _notifications = new List <IWoopsaNotification>(); if (monitorInterval == WoopsaSubscriptionServiceConst.MonitorIntervalLastPublishedValueOnly && publishInterval == WoopsaSubscriptionServiceConst.PublishIntervalOnce) { DoPublish(); } else if (publishInterval > TimeSpan.FromMilliseconds(0)) { _publishTimer = channel.ServiceImplementation.TimerScheduler.AllocateTimer(publishInterval); _publishTimer.Elapsed += _publishTimer_Elapsed; _publishTimer.IsEnabled = true; } else { throw new WoopsaException("A publish interval of 0 with a non-zero monitor interval is not allowed"); } }
public WoopsaSubscriptionServiceSubscriptionServerSubClient( WoopsaSubscriptionChannel channel, WoopsaContainer root, int subscriptionId, string propertyPath, TimeSpan monitorInterval, TimeSpan publishInterval, WoopsaBaseClientObject subClient, string relativePropertyPath) : base(channel, root, subscriptionId, propertyPath, monitorInterval, publishInterval) { bool isSingleNotification = monitorInterval == WoopsaSubscriptionServiceConst.MonitorIntervalLastPublishedValueOnly && publishInterval == WoopsaSubscriptionServiceConst.PublishIntervalOnce; EventHandler <WoopsaNotificationEventArgs> handler; if (isSingleNotification) { handler = (sender, e) => { EnqueueNewMonitoredValue(e.Notification.Value); DoPublish(); // there is not publish timer, force publishing the unique notification } } ; else { handler = (sender, e) => { EnqueueNewMonitoredValue(e.Notification.Value); } }; _clientSubscription = subClient.Subscribe(relativePropertyPath, handler, monitorInterval, publishInterval); }
public int RegisterSubscription(WoopsaContainer root, bool isServerSide, string woopsaPropertyPath, TimeSpan monitorInterval, TimeSpan publishInterval) { BaseWoopsaSubscriptionServiceSubscription newSubscription; int subscriptionId; _watchClientActivity.Restart(); lock (_idLock) { _lastSubscriptionId++; subscriptionId = _lastSubscriptionId; } if (isServerSide) { if (FindWoopsaClientAlongPath(root, woopsaPropertyPath, out WoopsaBaseClientObject subclient, out string relativePath)) { // subscribe directly instead of polling newSubscription = new WoopsaSubscriptionServiceSubscriptionServerSubClient( this, root, subscriptionId, woopsaPropertyPath, monitorInterval, publishInterval, subclient, relativePath); } else { newSubscription = new WoopsaSubscriptionServiceSubscriptionMonitorServer( this, root, subscriptionId, woopsaPropertyPath, monitorInterval, publishInterval); } }
public static IWoopsaElement ByNameOrNull(this IWoopsaContainer woopsaContainer, string name) { IWoopsaElement result; // For performance optimization, use directly the methods of classes WoopsaObject and WoopsaContainer // Complexity : O(1) if (woopsaContainer is WoopsaObject) { WoopsaObject woopsaObject = (WoopsaObject)woopsaContainer; result = woopsaObject.ByNameOrNull(name); } else if (woopsaContainer is WoopsaContainer) { WoopsaContainer container = (WoopsaContainer)woopsaContainer; result = container.ByNameOrNull(name); } else { // The code below can manage all the cases, but is used only for elements not // of type WoopsaContainer or WoopsaObject // Complexity : O(n) result = woopsaContainer.Items.ByNameOrNull(name); if (result == null && woopsaContainer is IWoopsaObject) { IWoopsaObject woopsaObject = (IWoopsaObject)woopsaContainer; result = woopsaObject.Properties.ByNameOrNull(name); if (result == null) { woopsaObject.Methods.ByNameOrNull(name); } } } return(result); }
public WoopsaSubscriptionServiceSubscriptionMonitorServer( WoopsaSubscriptionChannel channel, WoopsaContainer root, int subscriptionId, string propertyPath, TimeSpan monitorInterval, TimeSpan publishInterval) : base(channel, root, subscriptionId, propertyPath, monitorInterval, publishInterval) { }
public WoopsaContainer(WoopsaContainer container, string name) : base(container, name) { Lock = new object(); _items = new WoopsaElementList <WoopsaContainer>(); if (Owner != null) { Owner.Add(this); } }
/// <summary> /// Create a WoopsaObjectAdapter for a fixed object reference /// </summary> /// <param name="container">Can be null if it's the root object.</param> /// <param name="name"></param> /// <param name="targetObjectGetter"></param> /// <param name="declaredExposedType"> /// Type to expose for the targetObject. /// Specify null to use targetObject.GetType(). /// The specified type can be different than the targetObject.GetType() /// when an interface is published instead of the public methods of the type. /// Specifying null implies that the type is determined dynamically, as targetObjectGetter /// does not necesarily return always the same object. /// </param> /// <param name="options"></param> /// <param name="defaultVisibility"></param> public WoopsaObjectAdapter(WoopsaContainer container, string name, object targetObject, Type declaredExposedType = null, WoopsaConverters customValueTypeConverters = null, WoopsaObjectAdapterOptions options = WoopsaObjectAdapterOptions.None, WoopsaVisibility defaultVisibility = DefaultDefaultVisibility) : this(container, name, () => targetObject, declaredExposedType, new TypeDescriptions(customValueTypeConverters), options, defaultVisibility) { }
internal void Add(WoopsaContainer item) { lock (Lock) { if (_items.ByNameOrNull(item.Name) != null) { throw new WoopsaException("Tried to add an item with duplicate name '" + item.Name + "' to WoopsaContainer '" + Name + "'"); } _items.Add(item); } }
/// <summary> /// Create a WoopsaObjectAdapter for a dynamic object reference, returned by a delegate /// </summary> /// <param name="container"></param> /// <param name="name"></param> /// <param name="targetObjectGetter"></param> /// <param name="declaredExposedType"> /// Type to expose for the targetObject. /// Specify null to use targetObject.GetType(). /// The specified type can be different than the targetObject.GetType() /// when an interface is published instead of the public methods of the type. /// Specifying null implies that the type is determined dynamically, as targetObjectGetter /// does not necesarily return always the same object. /// </param> /// <param name="options"></param> /// <param name="defaultVisibility"></param> protected WoopsaObjectAdapter(WoopsaContainer container, string name, Func <object> targetObjectGetter, Type declaredExposedType, TypeDescriptions typeDescriptions, WoopsaObjectAdapterOptions options = WoopsaObjectAdapterOptions.None, WoopsaVisibility defaultVisibility = DefaultDefaultVisibility) : base(container, name) { TargetObjectGetter = targetObjectGetter; DeclaredExposedType = declaredExposedType; DefaultVisibility = defaultVisibility; Options = options; TypeDescriptions = typeDescriptions; _lock = new object(); }
public WoopsaSubscriptionServiceImplementation(WoopsaContainer root, bool isServerSide) { _root = root; _isServerSide = isServerSide; _channels = new Dictionary <int, WoopsaSubscriptionChannel>(); TimerScheduler = new LightWeightTimerScheduler(); TimerScheduler.Started += (sender, e) => { _currentService = this; }; TimerScheduler.Start(); _timerCheckChannelTimedOut = TimerScheduler.AllocateTimer( WoopsaSubscriptionServiceConst.SubscriptionChannelLifeTimeCheckInterval); _timerCheckChannelTimedOut.Elapsed += _timerCheckChannelTimedOut_Elapsed; _timerCheckChannelTimedOut.IsEnabled = true; }
public WoopsaSubscriptionServiceSubscriptionMonitor( WoopsaSubscriptionChannel channel, WoopsaContainer root, int subscriptionId, string propertyPath, TimeSpan monitorInterval, TimeSpan publishInterval) : base(channel, root, subscriptionId, propertyPath, monitorInterval, publishInterval) { if (monitorInterval != WoopsaSubscriptionServiceConst.MonitorIntervalLastPublishedValueOnly) { // create monitor timer _monitorTimer = channel.ServiceImplementation.TimerScheduler.AllocateTimer(monitorInterval); _monitorTimer.Elapsed += _monitorTimer_Elapsed; _monitorTimer.IsEnabled = true; } // Force immediate publishing of the current value DoMonitor(); DoPublish(); }
public WoopsaClient(string url, WoopsaContainer container, int notificationQueueSize = DefaultNotificationQueueSize) { Uri uri = new Uri(url); AuthorityUrl = uri.GetLeftPart(UriPartial.Authority); ClientProtocol = new WoopsaClientProtocol(url); _container = container; WoopsaUnboundClientObject unboundRoot = CreateUnboundRoot(""); SubscriptionChannel = new WoopsaClientSubscriptionChannel(this, unboundRoot, notificationQueueSize); _remoteMethodMultiRequest = unboundRoot.GetMethod( WoopsaMultiRequestConst.WoopsaMultiRequestMethodName, WoopsaValueType.JsonData, new WoopsaMethodArgumentInfo[] { new WoopsaMethodArgumentInfo(WoopsaMultiRequestConst.WoopsaMultiRequestArgumentName, WoopsaValueType.JsonData) }); }
private bool FindWoopsaClientAlongPath(WoopsaContainer root, string path, out WoopsaBaseClientObject client, out string relativePath) { OnBeforeWoopsaModelAccess(); try { string[] pathParts = path.Split(WoopsaConst.WoopsaPathSeparator); WoopsaContainer container = root; bool found = false; client = null; relativePath = string.Empty; for (int i = 0; i < pathParts.Length; i++) { if (container is WoopsaBaseClientObject) { client = (WoopsaBaseClientObject)container; for (int j = i; j < pathParts.Length; j++) { relativePath += WoopsaConst.WoopsaPathSeparator + pathParts[j]; } found = true; break; } else if (container == null) { break; } else if (!string.IsNullOrEmpty(pathParts[i])) { container = container.ByNameOrNull(pathParts[i]) as WoopsaContainer; } } return(found); } finally { OnAfterWoopsaModelAccess(); } }
internal WoopsaBaseClientObject(WoopsaClient client, WoopsaContainer container, string name, IWoopsaContainer root) : base(container, name) { Client = client; Root = root ?? this; }
public WoopsaObject(WoopsaContainer container, string name) : base(container, name) { _properties = new WoopsaElementList <WoopsaProperty>(); _methods = new WoopsaElementList <WoopsaMethod>(); }
public WoopsaSubscriptionService(WoopsaServer server, WoopsaContainer container) : base(container, WoopsaSubscriptionServiceConst.WoopsaServiceSubscriptionName) { _server = server; _subscriptionServiceImplementation = new WoopsaSubscriptionServiceImplementation(container, true); _subscriptionServiceImplementation.BeforeWoopsaModelAccess += (sender, e) => { server.ExecuteBeforeWoopsaModelAccess(); }; _subscriptionServiceImplementation.AfterWoopsaModelAccess += (sender, e) => { server.ExecuteAfterWoopsaModelAccess(); }; _subscriptionServiceImplementation.CanWatch += OnCanReconnectSubscriptionToNewObject; MethodCreateSubscriptionChannel = new WoopsaMethod( this, WoopsaSubscriptionServiceConst.WoopsaCreateSubscriptionChannel, WoopsaValueType.Integer, new WoopsaMethodArgumentInfo[] { new WoopsaMethodArgumentInfo(WoopsaSubscriptionServiceConst.WoopsaNotificationQueueSize, WoopsaValueType.Integer) }, arguments => _subscriptionServiceImplementation.CreateSubscriptionChannel(arguments[0].ToInt32()) ); MethodRegisterSubscription = new WoopsaMethod( this, WoopsaSubscriptionServiceConst.WoopsaRegisterSubscription, WoopsaValueType.Integer, new WoopsaMethodArgumentInfo[] { new WoopsaMethodArgumentInfo(WoopsaSubscriptionServiceConst.WoopsaSubscriptionChannel, WoopsaValueType.Integer), new WoopsaMethodArgumentInfo(WoopsaSubscriptionServiceConst.WoopsaPropertyLink, WoopsaValueType.WoopsaLink), new WoopsaMethodArgumentInfo(WoopsaSubscriptionServiceConst.WoopsaMonitorInterval, WoopsaValueType.TimeSpan), new WoopsaMethodArgumentInfo(WoopsaSubscriptionServiceConst.WoopsaPublishInterval, WoopsaValueType.TimeSpan) }, arguments => { return(_subscriptionServiceImplementation.RegisterSubscription( arguments[0].ToInt32(), arguments[1].DecodeWoopsaLocalLink(), arguments[2].ToTimeSpan(), arguments[3].ToTimeSpan())); }); MethodUnregisterSubscription = new WoopsaMethod( this, WoopsaSubscriptionServiceConst.WoopsaUnregisterSubscription, WoopsaValueType.Logical, new WoopsaMethodArgumentInfo[] { new WoopsaMethodArgumentInfo(WoopsaSubscriptionServiceConst.WoopsaSubscriptionChannel, WoopsaValueType.Integer), new WoopsaMethodArgumentInfo(WoopsaSubscriptionServiceConst.WoopsaSubscriptionId, WoopsaValueType.Integer) }, arguments => { return(_subscriptionServiceImplementation.UnregisterSubscription( arguments[0].ToInt32(), arguments[1].ToInt32())); }); MethodWaitNotification = new WoopsaMethod( this, WoopsaSubscriptionServiceConst.WoopsaWaitNotification, WoopsaValueType.JsonData, new WoopsaMethodArgumentInfo[] { new WoopsaMethodArgumentInfo(WoopsaSubscriptionServiceConst.WoopsaSubscriptionChannel, WoopsaValueType.Integer), new WoopsaMethodArgumentInfo(WoopsaSubscriptionServiceConst.WoopsaLastNotificationId, WoopsaValueType.Integer) }, arguments => { using (var accessFreeSection = _server.EnterModelAccessFreeSection()) return(new WoopsaValue(_subscriptionServiceImplementation.WaitNotification( arguments[0].ToInt32(), arguments[1].ToInt32()))); }); }
internal void Remove(WoopsaContainer item) { lock (Lock) _items.Remove(item); }
protected WoopsaElement(WoopsaContainer owner, string name) { Owner = owner; Name = name; }
internal WoopsaUnboundClientObject(WoopsaClient client, WoopsaContainer container, string name, IWoopsaContainer root) : base(client, container, name, root) { }