singrdk/base/Libraries/Resiliency/ServiceProxy.sg

188 lines
6.8 KiB
Plaintext

///////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: Libraries\Resiliency\Proxy.sg
//
// Note:
//
using System;
using System.Threading;
using Microsoft.SingSharp;
using Microsoft.Singularity;
using Microsoft.Singularity.Channels;
using Microsoft.Singularity.Directory;
using Microsoft.Singularity.Services;
using Microsoft.Singularity.ServiceManager;
namespace Microsoft.Singularity.Resiliency
{
public sealed class ServiceProxy
{
private Thread serviceThread;
private JournaletFactory! factory;
private TRef<ManagedServiceContract.Exp:Ready> serviceRef;
private TRef<ManagedProxyContract.Imp:Ready> recoveryRef;
private TRef<DirectoryServiceContract.Imp:Ready> rootDsRef;
private TRef<DirectoryServiceContract.Exp:Ready> myDsRef;
private TRef<ServiceProxyContract.Exp:Ready> proxyRef;
public ServiceProxy(JournaletFactory! factory,
[Claims]ManagedServiceContract.Exp:Start! mep,
[Claims]ManagedProxyContract.Imp:Start! pep,
[Claims]DirectoryServiceContract.Imp:Ready! dep,
[Claims]DirectoryServiceContract.Exp:Start! fep,
[Claims]ServiceProxyContract.Exp:Start! xep)
{
this.factory = factory;
this.rootDsRef = new TRef<DirectoryServiceContract.Imp:Ready>(dep);
fep.SendSuccess();
this.myDsRef = new TRef<DirectoryServiceContract.Exp:Ready>(fep);
mep.SendSuccess();
this.serviceRef = new TRef<ManagedServiceContract.Exp:Ready>(mep);
switch receive {
case pep.Success():
break;
case unsatisfiable:
DebugStub.Break();
break;
}
this.recoveryRef = new TRef<ManagedProxyContract.Imp:Ready>(pep);
xep.SendSuccess();
this.proxyRef = new TRef<ServiceProxyContract.Exp:Ready>(xep);
}
public void Start()
{
if (serviceThread == null) {
serviceThread = new Thread(new ThreadStart(Run));
}
serviceThread.Start();
}
public void Run()
{
Thread thread = null;
DirectoryServiceProxy dsProxy;
ManagedServiceContract.Exp:Ready! manager;
ThreadTerminationContract.Imp! imp;
ThreadTerminationContract.Exp! exp;
DebugStub.Print("-- Start proxy\n");
dsProxy = new DirectoryServiceProxy(this,
factory,
rootDsRef.Acquire(),
myDsRef.Acquire(),
proxyRef.Acquire());
ThreadTerminationContract.NewChannel(out imp, out exp);
dsProxy.Signal(exp);
manager = serviceRef.Acquire();
for (;;) {
switch receive {
case manager.StartService():
{
if (thread == null) {
thread = new Thread(new ThreadStart(dsProxy.Run));
}
thread.Start();
manager.SendAckStartService();
break;
}
case manager.StopService():
{
DebugStub.Print("Px: recv stop service\n");
imp.SendStop();
switch receive {
case imp.AckStop():
manager.SendAckStopService();
break;
case unsatisfiable:
manager.SendBusy();
break;
}
thread = null;
break;
}
case manager.RestartService():
{
manager.SendAckRestartService();
break;
}
case manager.Knock():
{
manager.SendAlive();
break;
}
case manager.Stop():
{
imp.SendStop();
switch receive {
case unsatisfiable:
break;
}
manager.SendAckStop();
goto exit;
break;
}
case manager.Restart():
{
DebugStub.Break();
manager.SendAckRestart();
break;
}
}
}
exit:
delete manager;
delete recoveryRef.Acquire();
delete imp;
}
/// <summary>
/// Asks ServiceManager to recover the corresponding service and
/// the initial direct channels to the service.
/// </summary>
internal void RecoverService(out DirectoryServiceContract.Exp:Ready ep,
out ServiceProxyContract.Exp:Ready xep)
{
ManagedProxyContract.Imp:Ready! manager;
DebugStub.Print("Px: Enter RecoverService\n");
manager = recoveryRef.Acquire();
#if COMPATIBLE_V1
manager.SendRequestDSRecovery();
switch receive {
case manager.AckDSRecovery(proxy):
#else
manager.SendRequestRecovery();
switch receive {
case manager.AckRecovery(directory, proxy):
#endif
{
directory.SendSuccess();
proxy.SendSuccess();
ep = directory;
xep = proxy;
break;
}
case unsatisfiable:
{
ep = null;
xep = null;
break;
}
}
recoveryRef.Release(manager);
DebugStub.Print("Px: Exit RecoverService\n");
}
}
}