singrdk/base/Applications/ServiceManager/Replace/ReplaceGame.sg

400 lines
13 KiB
Plaintext

///////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: Applications\ServiceManager\Replace\ReplaceGame.sg
//
// Note:
//
using System;
using System.Threading;
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.Directory;
using Microsoft.Singularity.Io;
using Microsoft.Singularity.ServiceManager;
using Microsoft.Singularity.Services;
[assembly: Transform(typeof(ApplicationResourceTransform))]
namespace Microsoft.Singularity.Applications
{
[ConsoleCategory(HelpMessage="Replace Game Client", DefaultAction=true)]
internal class DefaultConfig
{
[InputEndpoint("data")]
public readonly TRef<UnicodePipeContract.Exp:READY> Stdin;
[OutputEndpoint("data")]
public readonly TRef<UnicodePipeContract.Imp:READY> Stdout;
[LongParameter("interval", Default=500)]
internal long interval;
[BoolParameter("test", Default=true)]
internal bool test;
reflective internal DefaultConfig();
internal int AppMain()
{
return ReplaceGame.DefaultMain(this);
}
}
internal sealed class ReplaceGame
{
private const int DefaultCount = 50;
private int count;
private String![]! names;
private int self;
private Random! random;
private const int NumberOfActions = 4;
private enum Action : int { Overwrite, Protect, Score, Pose };
private static TRef<ServiceControlContract.Imp:Ready>! controlRef;
private static TRef<ServiceManagementContract.Imp:Ready>! manageRef;
internal ReplaceGame(String![]! competitors, int self)
{
this.count = DefaultCount;
this.names = competitors;
this.self = self;
Thread.Sleep(1); // To get a different seed
this.random = new Random();
}
internal void Run()
{
int action;
GamePlayerContract.Imp! ep;
if (!Connect(out ep)) {
goto exit;
}
switch receive {
case ep.Success():
break;
case unsatisfiable:
goto exit;
break;
}
Score(ep);
Console.WriteLine(names[self] + " start!!");
try {
while (count-- > 0) {
action = random.Next(NumberOfActions);
switch ((Action)action) {
case Action.Overwrite:
Console.WriteLine(names[self] + " overwrite");
Overwrite(ep);
break;
case Action.Protect:
Console.WriteLine(names[self] + " protect");
Protect(ep);
break;
case Action.Score:
Console.WriteLine(names[self] + " score");
Score(ep);
break;
case Action.Pose:
Pose();
break;
}
}
Console.WriteLine(names[self] + " end!!");
Score(ep);
}
catch (Exception e) {
DebugStub.Print(e.ToString());
}
exit:
delete ep;
}
private void Overwrite(GamePlayerContract.Imp:Ready! ep)
{
int pos = -1;
DebugStub.Print("Enter overwrite\n");
ep.SendSearch(Bitter.FromString2(GetSomeone()));
switch receive {
case ep.AckSearch(position):
pos = position;
break;
case ep.ChannelClosed():
//throw new ChannelClosedException();
break;
}
if (pos >= 0) {
ep.SendOverwrite(Bitter.FromString2(names[self]), pos);
switch receive {
case ep.AckOverwrite():
break;
case ep.ChannelClosed():
//throw new ChannelClosedException();
break;
}
}
DebugStub.Print("Exit overwrite\n");
}
private void Protect(GamePlayerContract.Imp:Ready! ep)
{
int pos = -1;
ep.SendSearch(Bitter.FromString2(names[self]));
switch receive {
case ep.AckSearch(position):
pos = position;
break;
case ep.ChannelClosed():
//throw new ChannelClosedException();
break;
}
if (pos >= 0) {
ep.SendProtect(pos);
switch receive {
case ep.AckProtect():
break;
case ep.ChannelClosed():
//throw new ChannelClosedException();
break;
}
}
}
private void Score(GamePlayerContract.Imp:Ready! ep)
{
ep.SendScore(Bitter.FromString2(names[self]));
switch receive {
case ep.AckScore(score):
Console.Write("{0, -10} : {1}\n", names[self], score);
break;
case ep.ChannelClosed():
//throw new ChannelClosedException();
break;
}
}
private void Pose()
{
Thread.Sleep(100);
}
private String! GetSomeone()
{
int index;
do {
index = random.Next(names.Length);
} while (index == self);
return names[index];
}
internal bool Connect(out GamePlayerContract.Imp! ep)
{
DirectoryServiceContract.Imp! ds;
GamePlayerContract.Imp! imp;
GamePlayerContract.Exp! exp;
ErrorCode error;
ds = DirectoryService.NewClientEndpoint();
GamePlayerContract.NewChannel(out imp, out exp);
SdsUtils.Bind(GamePlayerContract.ModuleName, ds, exp, out error);
ep = imp;
delete ds;
return (error == ErrorCode.NoError);
}
//--------------------------------------------------------------------
// Test Code
//--------------------------------------------------------------------
private static bool StartService()
{
bool success = false;
ServiceInfo* in ExHeap serviceInfo;
ServiceManagementContract.Imp! ep;
ServiceControlContract.Imp! imp;
ServiceControlContract.Exp! exp;
Console.Write("Starting service: " +
GamePlayerContract.ModuleName + " ...");
GetEndpoint(out ep);
ep.RecvSuccess();
ServiceControlContract.NewChannel(out imp, out exp);
serviceInfo = new [ExHeap] ServiceInfo(0,
GamePlayerContract.ModuleName,
GamePlayerContract.ModuleName,
ServiceType.Resilient);
ep.SendBind(serviceInfo, exp);
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;
}
}
imp.RecvSuccess();
imp.SendStartService();
switch receive {
case imp.RecvAckStartService():
{
Console.WriteLine(" done.");
success = true;
break;
}
case imp.NakStartService(error):
{
Console.WriteLine(" error: " + error);
break;
}
case imp.ChannelClosed():
{
Console.WriteLine(" Channel is closed.");
break;
}
}
exit:
if (success) {
controlRef =
new TRef<ServiceControlContract.Imp:Ready>(imp);
manageRef =
new TRef<ServiceManagementContract.Imp:Ready>(ep);
}
else {
delete imp;
delete ep;
}
return success;
}
private static bool RestartService()
{
bool success = false;
ServiceControlContract.Imp:Ready! ep;
ep = controlRef.Acquire();
ep.SendRestartService();
switch receive {
case ep.AckRestartService():
{
success = true;
break;
}
case ep.ChannelClosed():
{
success = false;
break;
}
}
controlRef.Release(ep);
return success;
}
private static bool StopService()
{
bool success = false;
ServiceControlContract.Imp:Ready! ep;
Console.Write("Stopping service ...");
ep = controlRef.Acquire();
ep.SendStopService();
switch receive {
case ep.AckStopService():
{
Console.WriteLine(" done.");
success = true;
break;
}
case ep.NakStopService(error):
{
Console.WriteLine(" error: " + error);
break;
}
}
delete ep;
delete manageRef.Acquire();
return success;
}
private static void GetEndpoint(out ServiceManagementContract.Imp! ep)
{
ErrorCode error;
DirectoryServiceContract.Imp ds;
ServiceManagementContract.Exp! scServer;
ServiceManagementContract.NewChannel(out ep, out scServer);
DebugStub.Print("GetEndpoint\n");
ds = DirectoryService.NewClientEndpoint();
SdsUtils.Bind(ServiceManagementContract.ModuleName, ds, scServer,
out error);
DebugStub.Print("GetEndpoint: {0}\n", __arglist((int)error));
delete ds;
}
internal static int DefaultMain(DefaultConfig! config)
{
// bang! bang! bang!
String![]! names = new String![4] {"Microsoft", "Google", "Yahoo", "Apple"};
ReplaceGame![]! game = new ReplaceGame![4];
Thread![]! players = new Thread![4];
if (config.test) {
StartService();
Thread.Sleep(2000);
}
for (int i = 0; i < 4; i++) {
game[i] = new ReplaceGame(names, i);
players[i] = new Thread(new ThreadStart(game[i].Run));
}
foreach (Thread! player in players) {
player.Start();
}
if (config.test) {
Thread.Sleep(8000);
RestartService();
}
foreach (Thread! player in players) {
player.Join();
}
if (config.test) {
StopService();
}
return 0;
}
}
}