/////////////////////////////////////////////////////////////////////////////// // // 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 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(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(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(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; } } }