singrdk/base/Applications/ServiceManager/SMSClient/SMSClient.cs

314 lines
10 KiB
C#

///////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: Applications\ServiceManager\SMSClient\SMSClient.sg
//
// Note: Service Manager client program
//
using System;
using Microsoft.SingSharp;
using Microsoft.SingSharp.Reflection;
using Microsoft.Singularity;
using Microsoft.Singularity.Applications;
using Microsoft.Singularity.Channels;
using Microsoft.Singularity.Configuration;
using Microsoft.Singularity.Contracts;
using Microsoft.Singularity.Directory;
using Microsoft.Singularity.Io;
using Microsoft.Singularity.ServiceManager;
[assembly: Transform(typeof(ApplicationResourceTransform))]
namespace Microsoft.Singularity.Applications.ServiceManager
{
[ConsoleCategory(HelpMessage="Service management client", DefaultAction=true)]
internal class DefaultConfig
{
[InputEndpoint("data")]
public readonly TRef<UnicodePipeContract.Exp:READY> Stdin;
[OutputEndpoint("data")]
public readonly TRef<UnicodePipeContract.Imp:READY> Stdout;
reflective internal DefaultConfig();
internal int AppMain()
{
return SMSClient.DefaultMain(this);
}
}
[ConsoleCategory(Action="start", HelpMessage="Start a service")]
internal class StartConfig
{
[InputEndpoint("data")]
public readonly TRef<UnicodePipeContract.Exp:READY> Stdin;
[OutputEndpoint("data")]
public readonly TRef<UnicodePipeContract.Imp:READY> Stdout;
[StringParameter("service", Mandatory=true, Position=0)]
internal string service;
[StringParameter("type", Mandatory=false, Position=1)]
internal string type;
reflective internal StartConfig();
internal int AppMain()
{
return SMSClient.StartService(this);
}
}
[ConsoleCategory(Action="stop", HelpMessage="Stop a service")]
internal class StopConfig
{
[InputEndpoint("data")]
public readonly TRef<UnicodePipeContract.Exp:READY> Stdin;
[OutputEndpoint("data")]
public readonly TRef<UnicodePipeContract.Imp:READY> Stdout;
//[StringParameter("service", Mandatory=true, Position=0)]
//internal string service;
[LongParameter("id", Mandatory=true, Position=0)]
internal long id;
reflective internal StopConfig();
internal int AppMain()
{
return SMSClient.StopService(this);
}
}
[ConsoleCategory(Action="restart", HelpMessage="Restart a service")]
internal class RestartConfig
{
[InputEndpoint("data")]
public readonly TRef<UnicodePipeContract.Exp:READY> Stdin;
[OutputEndpoint("data")]
public readonly TRef<UnicodePipeContract.Imp:READY> Stdout;
[StringParameter("service", Mandatory=true, Position=0)]
internal string service;
reflective internal RestartConfig();
internal int AppMain()
{
return SMSClient.RestartService(this);
}
}
[ConsoleCategory(Action="list", HelpMessage="Show a list of services")]
internal class ListConfig
{
[InputEndpoint("data")]
public readonly TRef<UnicodePipeContract.Exp:READY> Stdin;
[OutputEndpoint("data")]
public readonly TRef<UnicodePipeContract.Imp:READY> Stdout;
reflective internal ListConfig();
internal int AppMain()
{
return SMSClient.ListServices(this);
}
}
public class SMSClient
{
private static void GetEndpoint(out ServiceManagementContract.Imp! ep)
{
ErrorCode error;
DirectoryServiceContract.Imp ds;
ServiceManagementContract.Exp! scServer;
ServiceManagementContract.NewChannel(out ep, out scServer);
ds = DirectoryService.NewClientEndpoint();
SdsUtils.Bind(ServiceManagementContract.ModuleName, ds,
scServer, out error);
delete ds;
}
internal static int StartService(StartConfig! config)
{
int res = 1;
ServiceType type = ServiceType.Unknown;
ServiceInfo* in ExHeap info;
ServiceManagementContract.Imp! ep;
ServiceControlContract.Imp! client;
ServiceControlContract.Exp! server;
switch (config.type)
{
case "Resilient":
type = ServiceType.Resilient;
break;
case "Default":
type = ServiceType.Default;
break;
default:
type = ServiceType.Default;
break;
}
Console.Write("Starting service: " + config.service + " ... ");
GetEndpoint(out ep);
ep.RecvSuccess();
ServiceControlContract.NewChannel(out client, out server);
info = new[ExHeap] ServiceInfo(0, config.service, config.service,
type);
ep.SendBind(info, server);
switch receive {
case ep.AckBind():
break;
case ep.NotFound(rejected):
delete rejected;
Console.WriteLine("Doesn't exist.");
goto exit;
break;
case ep.PermissionDenied(rejected):
delete rejected;
Console.WriteLine("Permission denied");
goto exit;
break;
}
client.RecvSuccess();
client.SendStartService();
switch receive {
case client.RecvAckStartService():
Console.WriteLine("done.");
res = 0;
break;
case client.NakStartService(error):
Console.WriteLine("Error code: " + error);
break;
case client.ChannelClosed():
Console.WriteLine("Channel is closed.");
break;
}
exit:
delete client;
delete ep;
return res;
}
internal static int StopService(StopConfig! config)
{
int res = 1;
ServiceManagementContract.Imp! ep;
ServiceControlContract.Imp! client;
ServiceControlContract.Exp! server;
Console.Write("Stopping service: " + config.id + " ... ");
GetEndpoint(out ep);
ep.RecvSuccess();
ServiceControlContract.NewChannel(out client, out server);
ep.SendGetControl((int)config.id, server);
switch receive {
case ep.RecvAckGetControl():
break;
case ep.NotFound(rejected):
delete rejected;
Console.WriteLine("Doesn't exist.");
goto exit;
break;
case ep.PermissionDenied(rejected):
delete rejected;
Console.WriteLine("Permission denied");
goto exit;
break;
case ep.TryAgain(rejected):
delete rejected;
Console.WriteLine("Busy!");
goto exit;
break;
}
client.RecvSuccess();
client.SendStopService();
switch receive {
case client.AckStopService():
Console.WriteLine("done.");
res = 0;
break;
case client.NakStopService(error):
Console.WriteLine("Error code: " + error);
break;
}
exit:
delete client;
delete ep;
return res;
}
internal static int RestartService(RestartConfig! config)
{
Console.WriteLine("-- Sorry, not implemented yet.");
return 1;
}
internal static int ListServices(ListConfig! config)
{
bool next = false;
int count = 0;
ServiceManagementContract.Imp! ep;
GetEndpoint(out ep);
ep.RecvSuccess();
ep.SendBeginEnumeration();
Console.WriteLine();
Console.WriteLine("PID Task Name");
Console.WriteLine("=== ===================");
do {
switch receive {
case ep.RecvCurrent(info):
++count;
Console.WriteLine("{0,3} {1,-19}",
info->Id, info->Name);
delete info;
ep.SendMoveNext();
next = true;
break;
case ep.RecvEnumerationTerminated():
next = false;
break;
case ep.ChannelClosed():
next = false;
break;
}
} while (next);
Console.WriteLine();
Console.WriteLine(count + " services are found.");
delete ep;
return 0;
}
internal static int DefaultMain(DefaultConfig! config)
{
Console.WriteLine("Usage: svconf <command> [name] [type]");
Console.WriteLine(" @start Start the service");
Console.WriteLine(" @stop Stop the service");
//Console.WriteLine(" @restart Restart the service");
Console.WriteLine(" @list Show a list of running services");
Console.WriteLine(" type: Default or Resilient");
return 0;
}
}
}