singrdk/base/Services/Fat/ClientManager/FatClientManager.sg

421 lines
14 KiB
Plaintext
Raw Permalink Normal View History

2008-03-05 09:52:00 -05:00
///////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: Fat/ClientManager/FatClientManager.sg
//
// Note:
//
using Microsoft.SingSharp;
using Microsoft.Singularity.Channels;
using Microsoft.Singularity.Directory;
using Microsoft.Singularity.Services.Fat.Contracts;
2008-11-17 18:29:00 -05:00
using Microsoft.Singularity.Configuration;
using Microsoft.Singularity.ServiceManager;
2008-03-05 09:52:00 -05:00
using System;
using System.Collections;
using System.IO;
using System.Text;
2008-11-17 18:29:00 -05:00
using FileSystem.Utils;
2008-03-05 09:52:00 -05:00
namespace Microsoft.Singularity.Services.Fat.ClientManager
{
2008-11-17 18:29:00 -05:00
[Category("Service")]
internal class ServiceParameters
{
[CustomEndpoint]
public readonly TRef<ServiceProcessContract.Exp:Starting> ControlEndpointRef;
[CustomEndpoint]
public readonly TRef<ServiceEventContract.Imp:Ready> EventEndpointRef;
reflective private ServiceParameters();
}
2008-03-05 09:52:00 -05:00
public class ClientManager
{
internal static readonly char PathSeparator = Path.DirectorySeparatorChar;
private static ArrayList! mounts = new ArrayList();
internal class Client
{
TRef<FatClientContract.Imp:Running>! tref;
string! diskPath;
string! mountPath;
bool readOnly;
uint cacheMB;
internal Client(
[Claims] FatClientContract.Imp! imp,
string! diskPath,
string! mountPath,
bool readOnly,
uint cacheMB
)
{
this.tref = new TRef<FatClientContract.Imp:Running>(imp);
this.diskPath = diskPath;
this.mountPath = mountPath;
this.readOnly = readOnly;
this.cacheMB = cacheMB;
}
internal FatClientContract.Imp! Acquire()
{
return tref.Acquire();
}
internal void Release([Claims] FatClientContract.Imp! imp)
{
tref.Release(imp);
}
internal string! DiskPath { get { return this.diskPath; } }
internal string! MountPath { get { return this.mountPath; } }
}
internal static void
AddClient(Client newClient)
{
mounts.Add(newClient);
}
internal static Client GetClientByMountPath(string! path)
requires (path.Length > 0 &&
path[path.Length - 1] != Path.DirectorySeparatorChar);
{
for (int i = 0; i < mounts.Count; i++) {
Client! cs = (Client!)mounts[i];
if (String.Compare(cs.MountPath, path, true) == 0) {
return cs;
}
}
return null;
}
internal static Client GetClientByDiskPath(string! path)
requires (path.Length > 0 &&
path[path.Length - 1] != Path.DirectorySeparatorChar);
{
for (int i = 0; i < mounts.Count; i++) {
Client! cs = (Client!)mounts[i];
if (String.Compare(cs.DiskPath, path, true) == 0) {
return cs;
}
}
return null;
}
internal static void DeleteClient(Client! closedClient)
{
mounts.Remove(closedClient);
}
internal static bool ClientIsClosed(Client! client)
{
FatClientContract.Imp:Running! clientImp = client.Acquire();
bool closed = false;
switch receive {
case clientImp.ChannelClosed():
closed = true;
break;
case timeout:
break;
}
client.Release(clientImp);
return closed;
}
private static void
DoMount(FatControlContract.Exp:Ready! controller,
[Claims]
FatMountSettings*! in ExHeap fms)
{
2008-11-17 18:29:00 -05:00
string! diskPath = PathUtils.ToPath(fms->DiskPath);
string! mountPath = PathUtils.ToPath(fms->MountPath);
2008-03-05 09:52:00 -05:00
bool readOnly = fms->ReadOnly;
uint cacheMB = fms->CacheMB;
Client client = GetClientByDiskPath(diskPath);
if (client != null) {
if (!ClientIsClosed(client)) {
// Already using disk path
controller.SendFail(FatContractErrorCode.DiskUnavailable);
delete fms;
return;
}
else {
DeleteClient(client);
client = null;
}
}
client = GetClientByMountPath(mountPath);
if (client != null) {
if (!ClientIsClosed(client)) {
// Already using mount path
controller.SendFail(FatContractErrorCode.PathUnavailable);
delete fms;
return;
}
else {
DeleteClient(client);
client = null;
}
}
FatClientContract.Imp! clientImp;
FatClientContract.Exp! clientExp;
FatClientContract.NewChannel(out clientImp, out clientExp);
string [] args = { "fatfs" };
Process process = new Process(args);
process.SetStartupEndpoint(0, clientExp);
process.Start();
clientImp.SendMount(fms);
2008-11-17 18:29:00 -05:00
switch receive {
2008-03-05 09:52:00 -05:00
case clientImp.Success():
AddClient(
new Client(clientImp, diskPath, mountPath,
readOnly, cacheMB)
);
controller.SendSuccess();
break;
case clientImp.ChannelClosed():
controller.SendSuccess();
delete clientImp;
break;
case clientImp.Fail(reason):
controller.SendFail(reason);
delete clientImp;
break;
}
}
private static void
DoUnmount(
FatControlContract.Exp:Ready! controller,
[Claims] char[]! in ExHeap mountPath,
bool force
)
{
2008-11-17 18:29:00 -05:00
string path = PathUtils.ToPath(Bitter.ToString2(mountPath));
2008-03-05 09:52:00 -05:00
delete mountPath;
Client client = GetClientByMountPath(path);
if (client == null) {
controller.SendFail(FatContractErrorCode.NotMounted);
return;
}
else if (ClientIsClosed(client)) {
controller.SendSuccess();
return;
}
FatClientContract.Imp! clientImp = client.Acquire();
clientImp.SendUnmount(force);
switch receive {
case clientImp.Success():
controller.SendSuccess();
client.Release(clientImp);
DeleteClient(client);
break;
case clientImp.Fail(reason):
controller.SendFail(reason);
client.Release(clientImp);
break;
case clientImp.ChannelClosed():
controller.SendFail(FatContractErrorCode.InternalError);
client.Release(clientImp);
DeleteClient(client);
break;
}
}
private static void
DoGetPreferredFormatSettings(
FatControlContract.Exp:Ready! controller,
[Claims] char[]! in ExHeap diskPath
)
{
2008-11-17 18:29:00 -05:00
string! cleanPath = PathUtils.ToPath(Bitter.ToString2(diskPath));
2008-03-05 09:52:00 -05:00
delete diskPath;
FatClientContract.Imp! clientImp;
FatClientContract.Exp! clientExp;
FatClientContract.NewChannel(out clientImp, out clientExp);
string [] args = { "fatfs" };
Process process = new Process(args);
process.SetStartupEndpoint(0, clientExp);
process.Start();
clientImp.SendGetPreferredFormatSettings(
Bitter.FromString2(cleanPath)
);
try {
2008-11-17 18:29:00 -05:00
switch receive {
2008-03-05 09:52:00 -05:00
case clientImp.PreferredFormatSettings(settings):
controller.SendPreferredFormatSettings(settings);
break;
case clientImp.Fail(error):
controller.SendFail(error);
break;
case clientImp.ChannelClosed():
DebugStub.Break();
break;
}
}
finally {
delete clientImp;
}
}
private static void
DoFormat(
FatControlContract.Exp:Ready! controller,
[Claims] char[]! in ExHeap diskPath,
[Claims] char[]! in ExHeap volumeLabel,
[Claims] FatFormatSettings*! in ExHeap settings
)
{
2008-11-17 18:29:00 -05:00
string! cleanPath = PathUtils.ToPath(Bitter.ToString2(diskPath));
2008-03-05 09:52:00 -05:00
delete diskPath;
FatClientContract.Imp! clientImp;
FatClientContract.Exp! clientExp;
FatClientContract.NewChannel(out clientImp, out clientExp);
string [] args = { "fatfs" };
Process process = new Process(args);
process.SetStartupEndpoint(0, clientExp);
process.Start();
clientImp.SendFormat(Bitter.FromString2(cleanPath),
volumeLabel,
settings);
try {
2008-11-17 18:29:00 -05:00
switch receive {
2008-03-05 09:52:00 -05:00
case clientImp.Success():
controller.SendSuccess();
break;
case clientImp.Fail(error):
controller.SendFail(error);
break;
case clientImp.ChannelClosed():
DebugStub.Break();
break;
}
}
finally {
delete clientImp;
}
}
private static void Shutdown()
{
}
2008-11-17 18:29:00 -05:00
private static void ServiceClients(ServiceProcessContract.Exp! svcontrol)
2008-03-05 09:52:00 -05:00
{
ESet<FatControlContract.Exp:Ready> controllers =
new ESet<FatControlContract.Exp:Ready>();
2008-11-17 18:29:00 -05:00
svcontrol.SendStartSucceeded();
2008-03-05 09:52:00 -05:00
bool run = true;
while (run) {
switch receive {
2008-11-17 18:29:00 -05:00
case svcontrol.Connect(expath, candidate):
if (expath != null) {
// This service does not use subpaths. Reject request.
delete expath;
delete candidate;
svcontrol.SendNakConnect(ErrorCode.NotFound, null);
break;
}
2008-03-05 09:52:00 -05:00
FatControlContract.Exp controller =
candidate as FatControlContract.Exp;
if (controller != null) {
controller.SendSuccess();
controllers.Add(controller);
2008-11-17 18:29:00 -05:00
svcontrol.SendAckConnect();
2008-03-05 09:52:00 -05:00
}
else {
2008-11-17 18:29:00 -05:00
delete candidate;
svcontrol.SendNakConnect(ErrorCode.ContractNotSupported, null);
2008-03-05 09:52:00 -05:00
}
break;
2008-11-17 18:29:00 -05:00
case svcontrol.Stop():
DebugStub.WriteLine("FAT: Received 'Stop' request from Service Manager.");
run = false;
svcontrol.SendAckStop();
break;
case svcontrol.Knock():
DebugStub.WriteLine("FAT: Received 'Knock' request from Service Manager.");
svcontrol.SendAlive();
break;
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
case svcontrol.ChannelClosed():
2008-03-05 09:52:00 -05:00
run = false;
break;
case controller.Mount(settings) in controllers:
DoMount(controller, settings);
controllers.Add(controller);
break;
case controller.Unmount(mountPath, force) in controllers:
DoUnmount(controller, mountPath, force);
controllers.Add(controller);
break;
case controller.GetPreferredFormatSettings(diskPath) in controllers:
DoGetPreferredFormatSettings(controller, diskPath);
controllers.Add(controller);
break;
case controller.Format(diskPath, volumeLabel, fms) in controllers:
DoFormat(controller, diskPath, volumeLabel, fms);
controllers.Add(controller);
break;
case controller.ChannelClosed() in controllers:
delete controller;
break;
}
}
Shutdown();
controllers.Dispose();
}
2008-11-17 18:29:00 -05:00
internal static int AppMain(ServiceParameters! parameters)
2008-03-05 09:52:00 -05:00
{
2008-11-17 18:29:00 -05:00
if (parameters.ControlEndpointRef == null)
throw new Exception("The parent process did not provide a ServiceProcessContract channel.");
ServiceProcessContract.Exp! svcontrol = parameters.ControlEndpointRef.Acquire();
2008-03-05 09:52:00 -05:00
try {
2008-11-17 18:29:00 -05:00
ServiceClients(svcontrol);
return 0;
2008-03-05 09:52:00 -05:00
}
finally {
2008-11-17 18:29:00 -05:00
delete svcontrol;
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
}
2008-03-05 09:52:00 -05:00
}
}