// ---------------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // // ---------------------------------------------------------------------------- using System; using Microsoft.SingSharp; using Microsoft.Singularity.Channels; using Microsoft.Singularity.ServiceManager; namespace Microsoft.Singularity.Services.ServiceManager { /// /// References to instances of this class are stored in Service.WatchersList, /// and also as the "data" field of the endpoint map at ServiceManager.clients_readywatch. /// class ServiceWatcher { public ServiceWatcher(Service! service) { this.Service = service; this.MissedChange = true; this._endpointCanSend = false; this.EndpointRef = null; } public readonly Service! Service; /// /// If true, then Client contains an endpoint that we can send to. /// If false, then Client is either null, or has already been acquired. /// public bool EndpointCanSend { get { return _endpointCanSend; } } bool _endpointCanSend; /// /// If true, then the status of the service changed while 'CanSend' was false. /// So, the next time we send a status change message to the client, we pass /// a flag that says "you missed one or more updates". /// public bool MissedChange; /// /// The client endpoint that has subscribed to the status of the service. /// If EndpointCanSend is true, then this field is non-null and contains /// an endpoint (can be acquired). If EndpointCanSend is false, then this /// field is either null, or it is in the "acquired" state. /// TRef EndpointRef; public void TakeEndpoint([Claims]ServiceManagerContract.Exp:WaitingServiceChange! client) { if (_endpointCanSend) throw new InvalidOperationException("This ServiceWatcher instance already has an endpoint; another endpoint cannot be accepted."); if (EndpointRef != null) EndpointRef.Release(client); else EndpointRef = new TRef(client); _endpointCanSend = true; } public ServiceManagerContract.Exp:WaitingServiceChange! AcquireEndpoint() { if (!_endpointCanSend) throw new InvalidOperationException("This ServiceWatcher instance does not contain an endpoint."); assert EndpointRef != null; _endpointCanSend = false; return EndpointRef.Acquire(); } } class ServiceStartWatcher { public ServiceStartWatcher( Service! service, [Claims]ServiceManagerContract.Exp:StartingServiceWait:StartingServiceWait! endpoint) { this.Service = service; this.EndpointRef = new TRef(endpoint); } public Service! Service; public TRef! EndpointRef; public void Dispose() { } } class ServiceStopWatcher : IDisposable { public ServiceStopWatcher( Service! service, [Claims]ServiceManagerContract.Exp:StoppingServiceWait:StoppingServiceWait! endpoint) { this.Service = service; this.EndpointRef = new TRef(endpoint); } public Service! Service; public TRef! EndpointRef; public void Dispose() { } } }