// ----------------------------------------------------------------------------
//
// 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()
{
}
}
}