217 lines
8.8 KiB
Plaintext
217 lines
8.8 KiB
Plaintext
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Microsoft Research Singularity
|
||
|
//
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//
|
||
|
// File: Services\ServiceManager\ServiceController.sg
|
||
|
//
|
||
|
// Note: Client counterpart
|
||
|
//
|
||
|
using System;
|
||
|
using System.Collections;
|
||
|
using System.Threading;
|
||
|
using Microsoft.SingSharp;
|
||
|
using Microsoft.Singularity;
|
||
|
using Microsoft.Singularity.Channels;
|
||
|
using Microsoft.Singularity.ServiceManager;
|
||
|
|
||
|
namespace Microsoft.Singularity.Services.ServiceManager
|
||
|
{
|
||
|
// ServiceController is created per client and provides generic services,
|
||
|
// such as starting a service and enumerating current running services.
|
||
|
// ServiceController is created by ServiceManager when ServiceManager
|
||
|
// accepts a client connection.
|
||
|
internal class ServiceController
|
||
|
{
|
||
|
protected Acceptor acceptor;
|
||
|
|
||
|
protected TRef<ServiceManagementContract.Exp:Ready> endpoint;
|
||
|
protected TRef<ThreadTerminationContract.Imp:Start> sender;
|
||
|
protected TRef<ThreadTerminationContract.Exp:Start> signal;
|
||
|
|
||
|
internal ServiceController(Acceptor acceptor,
|
||
|
[Claims]ServiceManagementContract.Exp:Start! ep)
|
||
|
{
|
||
|
this.acceptor = acceptor;
|
||
|
ep.SendSuccess();
|
||
|
this.endpoint = new TRef<ServiceManagementContract.Exp:Ready>(ep);
|
||
|
|
||
|
ThreadTerminationContract.Imp! imp;
|
||
|
ThreadTerminationContract.Exp! exp;
|
||
|
ThreadTerminationContract.NewChannel(out imp, out exp);
|
||
|
this.sender = new TRef<ThreadTerminationContract.Imp:Start>(imp);
|
||
|
this.signal = new TRef<ThreadTerminationContract.Exp:Start>(exp);
|
||
|
}
|
||
|
|
||
|
internal void Stop()
|
||
|
{
|
||
|
ThreadTerminationContract.Imp! imp;
|
||
|
imp = sender.Acquire();
|
||
|
imp.SendStop();
|
||
|
delete imp;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Service main loop.
|
||
|
/// </summary>
|
||
|
internal void Run()
|
||
|
{
|
||
|
ServiceManagementContract.Exp:Ready! ep;
|
||
|
ThreadTerminationContract.Exp:Start! sig;
|
||
|
|
||
|
ep = endpoint.Acquire();
|
||
|
sig = signal.Acquire();
|
||
|
for (;;) {
|
||
|
switch receive {
|
||
|
case ep.Bind(info, control):
|
||
|
{
|
||
|
try {
|
||
|
string name = info->Name;
|
||
|
string binary = info->Binary;
|
||
|
Service service;
|
||
|
|
||
|
DebugStub.Print("Binding '{0}({1})' ... ",
|
||
|
__arglist(name, binary));
|
||
|
|
||
|
// Create a new process
|
||
|
service = ServiceManager.NewService(name,
|
||
|
binary,
|
||
|
info->Type);
|
||
|
if (service != null) {
|
||
|
// Bind the given control to the service
|
||
|
// counterpart. This doesn't start the
|
||
|
// service itself.
|
||
|
service.Start(control);
|
||
|
ep.SendAckBind();
|
||
|
DebugStub.Print(" done.\n");
|
||
|
}
|
||
|
else {
|
||
|
ep.SendNotFound(control);
|
||
|
}
|
||
|
}
|
||
|
catch (ProcessCreateException) {
|
||
|
ep.SendNotFound(control);
|
||
|
}
|
||
|
catch (AccessControlException) {
|
||
|
ep.SendPermissionDenied(control);
|
||
|
}
|
||
|
delete info;
|
||
|
break;
|
||
|
}
|
||
|
case ep.GetControl(id, control):
|
||
|
{
|
||
|
Service service = ServiceManager.GetService(id);
|
||
|
if (service != null) {
|
||
|
if (!service.IsBound()) {
|
||
|
service.Start(control);
|
||
|
ep.SendAckGetControl();
|
||
|
}
|
||
|
else {
|
||
|
ep.SendTryAgain(control);
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
ep.SendNotFound(control);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case ep.Unbind(id):
|
||
|
{
|
||
|
try {
|
||
|
Service service = ServiceManager.GetService(id);
|
||
|
if (service != null) {
|
||
|
if (service.IsBound()) {
|
||
|
ServiceControlContract.Exp:Ready! control;
|
||
|
service.Stop(out control);
|
||
|
// HI: It doesn't check the ownership of
|
||
|
// the control.
|
||
|
ep.SendAckUnbind(control);
|
||
|
}
|
||
|
else {
|
||
|
ep.SendControlNotFound();
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
ep.SendServiceNotFound();
|
||
|
}
|
||
|
}
|
||
|
catch (AccessControlException) {
|
||
|
ep.SendControlPermissionDenied();
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case ep.BeginEnumeration():
|
||
|
{
|
||
|
IDictionaryEnumerator controls;
|
||
|
|
||
|
controls = ServiceManager.GetEnumerator();
|
||
|
if (controls == null) {
|
||
|
ep.SendEnumerationTerminated();
|
||
|
}
|
||
|
else {
|
||
|
Service entry = null;
|
||
|
bool next = false;
|
||
|
do {
|
||
|
if (controls.MoveNext() == false) {
|
||
|
ep.SendEnumerationTerminated();
|
||
|
break;
|
||
|
}
|
||
|
entry = (Service)controls.Value;
|
||
|
if (entry == null) {
|
||
|
ep.SendEnumerationTerminated();
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
ServiceInfo* in ExHeap info;
|
||
|
|
||
|
info = new[ExHeap] ServiceInfo(entry.Id,
|
||
|
entry.Name,
|
||
|
entry.Binary,
|
||
|
entry.Type);
|
||
|
ep.SendCurrent(info);
|
||
|
|
||
|
switch receive {
|
||
|
case ep.RecvMoveNext():
|
||
|
next = true;
|
||
|
break;
|
||
|
case ep.RecvEndEnumeration():
|
||
|
next = false;
|
||
|
break;
|
||
|
case ep.ChannelClosed():
|
||
|
next = false;
|
||
|
break;
|
||
|
}
|
||
|
} while (next);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case ep.ChannelClosed():
|
||
|
{
|
||
|
DebugStub.Print("Controller: Client Channel closed\n");
|
||
|
goto exit;
|
||
|
break;
|
||
|
}
|
||
|
case sig.Stop():
|
||
|
{
|
||
|
sig.SendAckStop();
|
||
|
goto exit;
|
||
|
break;
|
||
|
}
|
||
|
case sig.ChannelClosed():
|
||
|
{
|
||
|
DebugStub.Print("Controller: Signal ch closed\n");
|
||
|
goto exit;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
exit:
|
||
|
delete ep;
|
||
|
delete sig;
|
||
|
acceptor.ReleaseController(this);
|
||
|
//DebugStub.Print("Exit Service Controller\n");
|
||
|
}
|
||
|
}
|
||
|
}
|