/////////////////////////////////////////////////////////////////////////////// // // 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 endpoint; protected TRef sender; protected TRef signal; internal ServiceController(Acceptor acceptor, [Claims]ServiceManagementContract.Exp:Start! ep) { this.acceptor = acceptor; ep.SendSuccess(); this.endpoint = new TRef(ep); ThreadTerminationContract.Imp! imp; ThreadTerminationContract.Exp! exp; ThreadTerminationContract.NewChannel(out imp, out exp); this.sender = new TRef(imp); this.signal = new TRef(exp); } internal void Stop() { ThreadTerminationContract.Imp! imp; imp = sender.Acquire(); imp.SendStop(); delete imp; } /// /// Service main loop. /// 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"); } } }