204 lines
7.7 KiB
Plaintext
204 lines
7.7 KiB
Plaintext
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Microsoft Research Singularity
|
||
|
//
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//
|
||
|
// File: Services\ServiceManager\ResilientService.sg
|
||
|
//
|
||
|
// Note:
|
||
|
//
|
||
|
using System;
|
||
|
using System.Threading;
|
||
|
using Microsoft.SingSharp;
|
||
|
using Microsoft.Singularity;
|
||
|
using Microsoft.Singularity.Channels;
|
||
|
using Microsoft.Singularity.Directory;
|
||
|
using Microsoft.Singularity.ServiceManager;
|
||
|
|
||
|
namespace Microsoft.Singularity.Services.ServiceManager
|
||
|
{
|
||
|
internal class ResilientService : Service
|
||
|
{
|
||
|
protected JournalService journalService;
|
||
|
protected Object! recoveryLock;
|
||
|
protected TRef<ServiceProxyContract.Imp:Start> proxyRef;
|
||
|
|
||
|
internal ResilientService(string! serviceName,
|
||
|
string! binaryName,
|
||
|
[Claims]DirectoryServiceContract.Imp:Ready! ds,
|
||
|
[Claims]ServiceProxyContract.Imp:Start! sp,
|
||
|
JournalService journal)
|
||
|
{
|
||
|
base(serviceName, binaryName, ServiceType.Resilient, ds);
|
||
|
this.journalService = journal;
|
||
|
this.recoveryLock = new Object();
|
||
|
this.proxyRef = new TRef<ServiceProxyContract.Imp:Start>(sp);
|
||
|
}
|
||
|
|
||
|
internal override ServiceError StartServiceProcess()
|
||
|
{
|
||
|
ServiceError report;
|
||
|
ManagedServiceContract.Imp! msImp;
|
||
|
ManagedServiceContract.Exp! msExp;
|
||
|
|
||
|
DebugStub.Print("RS: Create process '{0}'\n",
|
||
|
__arglist(binaryName));
|
||
|
|
||
|
process = new Process(new String[1]{binaryName}, null, 3);
|
||
|
|
||
|
// Create a channel to the service
|
||
|
ManagedServiceContract.NewChannel(out msImp, out msExp);
|
||
|
if (!process.SetStartupEndpoint(0, (Endpoint * in ExHeap)msExp)) {
|
||
|
DebugStub.Print("Endpoint cannot be set. (ManagedService)\n");
|
||
|
delete msImp;
|
||
|
return ServiceError.TryAgain;
|
||
|
}
|
||
|
|
||
|
if (!process.SetStartupEndpoint(1, (Endpoint * in ExHeap)directory.Acquire())) {
|
||
|
DebugStub.Print("Endpoint cannot be set. " +
|
||
|
"(DirectoryService)\n");
|
||
|
delete msImp;
|
||
|
return ServiceError.TryAgain;
|
||
|
}
|
||
|
|
||
|
if (!process.SetStartupEndpoint(2, (Endpoint * in ExHeap)proxyRef.Acquire())) {
|
||
|
DebugStub.Print("Endpoint cannot be set. (ServiceProxy)\n");
|
||
|
delete msImp;
|
||
|
return ServiceError.TryAgain;
|
||
|
}
|
||
|
|
||
|
DebugStub.Print("RS: start process\n");
|
||
|
process.Start();
|
||
|
|
||
|
// Make sure the process has been started
|
||
|
switch receive {
|
||
|
case msImp.RecvSuccess():
|
||
|
managementEndpoint = new TRef<ManagedServiceContract.Imp:Ready>(msImp);
|
||
|
report = ServiceError.None;
|
||
|
break;
|
||
|
case msImp.ChannelClosed():
|
||
|
DebugStub.Print("Service process's channel is closed.\n");
|
||
|
delete msImp;
|
||
|
report = ServiceError.ChannelClosed;
|
||
|
break;
|
||
|
}
|
||
|
return report;
|
||
|
}
|
||
|
|
||
|
internal override ServiceError RestartServiceProcess()
|
||
|
{
|
||
|
ServiceError report = ServiceError.Unknown;
|
||
|
ManagedServiceContract.Imp! msImp;
|
||
|
ManagedServiceContract.Exp! msExp;
|
||
|
DirectoryServiceContract.Imp! substituteImp;
|
||
|
DirectoryServiceContract.Exp! substituteExp;
|
||
|
ServiceProxyContract.Imp! proxyImp;
|
||
|
ServiceProxyContract.Exp! proxyExp;
|
||
|
|
||
|
DebugStub.Print("ResilientService: ENTER RestartServiceProcess\n");
|
||
|
if (!Monitor.TryEnter(recoveryLock)) {
|
||
|
return ServiceError.TryAgain;
|
||
|
}
|
||
|
|
||
|
DebugStub.Print("RS: Stopping the process ...\n");
|
||
|
process.Stop();
|
||
|
|
||
|
|
||
|
DirectoryServiceContract.NewChannel(out substituteImp,
|
||
|
out substituteExp);
|
||
|
ServiceProxyContract.NewChannel(out proxyImp, out proxyExp);
|
||
|
// Set substituteExp to JournalProducer and check the connection
|
||
|
journalService.TransferDirectoryService(substituteExp, proxyExp);
|
||
|
|
||
|
switch receive {
|
||
|
case substituteImp.RecvSuccess():
|
||
|
report = ServiceError.None;
|
||
|
break;
|
||
|
case substituteImp.ChannelClosed():
|
||
|
report = ServiceError.ChannelClosed;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (report != ServiceError.None) {
|
||
|
delete substituteImp;
|
||
|
delete proxyImp;
|
||
|
goto exit;
|
||
|
}
|
||
|
DebugStub.Print("sub received\n");
|
||
|
|
||
|
DebugStub.Print("RS: creating a new process ... ");
|
||
|
process = new Process(new String[1]{binaryName}, null, 3);
|
||
|
DebugStub.Print("done.\n");
|
||
|
|
||
|
//
|
||
|
// Create a channel to the service
|
||
|
//
|
||
|
ManagedServiceContract.NewChannel(out msImp, out msExp);
|
||
|
if (!process.SetStartupEndpoint(0, (Endpoint * in ExHeap)msExp)) {
|
||
|
DebugStub.Print("Endpoint cannot be set. (ManagedService)\n");
|
||
|
delete msImp;
|
||
|
delete substituteImp;
|
||
|
delete proxyImp;
|
||
|
report = ServiceError.TryAgain;
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
if (!process.SetStartupEndpoint(1, (Endpoint * in ExHeap)substituteImp)) {
|
||
|
DebugStub.Print("Endpoint cannot be set. " +
|
||
|
"(DirectoryService)\n");
|
||
|
delete msImp;
|
||
|
delete proxyImp;
|
||
|
report = ServiceError.TryAgain;
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
if (!process.SetStartupEndpoint(2, (Endpoint * in ExHeap)proxyImp)) {
|
||
|
DebugStub.Print("Endpoint cannot be set. " +
|
||
|
"(ServiceProxy)\n");
|
||
|
delete msImp;
|
||
|
report = ServiceError.TryAgain;
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
DebugStub.Print("RS: Restarting service process ... ");
|
||
|
process.Start();
|
||
|
DebugStub.Print("done.\n");
|
||
|
|
||
|
// Make sure the process has been started
|
||
|
switch receive {
|
||
|
case msImp.RecvSuccess():
|
||
|
// Replace the existing endpoint
|
||
|
managementEndpoint = new TRef<ManagedServiceContract.Imp:Ready>(msImp);
|
||
|
report = ServiceError.None;
|
||
|
break;
|
||
|
case msImp.ChannelClosed():
|
||
|
DebugStub.Print("Service process's channel is closed.\n");
|
||
|
delete msImp;
|
||
|
report = ServiceError.ChannelClosed;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
exit:
|
||
|
Monitor.Exit(recoveryLock);
|
||
|
DebugStub.Print("RS: Exit RestartServiceProcess\n");
|
||
|
return report;
|
||
|
}
|
||
|
|
||
|
internal override ServiceError RestartService()
|
||
|
{
|
||
|
ServiceError report;
|
||
|
|
||
|
//this.StopService();
|
||
|
// Currently, we don't know what condition the service
|
||
|
// process is, so just kill the process and restart it.
|
||
|
report = RestartServiceProcess();
|
||
|
if (report == ServiceError.None) {
|
||
|
report = StartService();
|
||
|
}
|
||
|
|
||
|
return report;
|
||
|
}
|
||
|
}
|
||
|
}
|