376 lines
12 KiB
Plaintext
376 lines
12 KiB
Plaintext
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Microsoft Research Singularity
|
||
|
//
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//
|
||
|
// File: FileUtils.sg
|
||
|
//
|
||
|
// Note:
|
||
|
//
|
||
|
|
||
|
using System;
|
||
|
using System.Text;
|
||
|
using System.Threading;
|
||
|
using Microsoft.SingSharp;
|
||
|
using Microsoft.Singularity;
|
||
|
using Microsoft.Singularity.Directory;
|
||
|
using Microsoft.Singularity.Channels;
|
||
|
using Microsoft.Singularity.FileSystem;
|
||
|
using Microsoft.Singularity.V1.Services;
|
||
|
|
||
|
namespace FileSystem.Utils
|
||
|
{
|
||
|
public class FileUtils
|
||
|
{
|
||
|
public static object lockTarget = new object();
|
||
|
public static bool recording = false;
|
||
|
public static TimeSpan bindTime = new TimeSpan(0);
|
||
|
public static long bindCount = 0;
|
||
|
|
||
|
private static TRef<DirectoryServiceContract.Imp:Ready>! m_epNS =
|
||
|
new TRef<DirectoryServiceContract.Imp:Ready>(DirectoryService.NewClientEndpoint());
|
||
|
|
||
|
private static DirectoryServiceContract.Imp:Ready! GetDirectoryServiceContract()
|
||
|
{
|
||
|
return m_epNS.Acquire();
|
||
|
}
|
||
|
|
||
|
private static void ReleaseDirectoryServiceContract([Claims] DirectoryServiceContract.Imp:Ready! imp)
|
||
|
{
|
||
|
m_epNS.Release(imp);
|
||
|
}
|
||
|
|
||
|
|
||
|
public static FileContract.Imp:Ready OpenFile(string! filePath)
|
||
|
{
|
||
|
DirectoryServiceContract.Imp! rootNS = GetDirectoryServiceContract();
|
||
|
try {
|
||
|
return OpenFile(filePath, rootNS);
|
||
|
}
|
||
|
finally {
|
||
|
ReleaseDirectoryServiceContract(rootNS);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static FileContract.Imp:Ready OpenFile(string! filePath, out ErrorCode error)
|
||
|
{
|
||
|
DirectoryServiceContract.Imp! rootNS = GetDirectoryServiceContract();
|
||
|
try {
|
||
|
return OpenFile(filePath, rootNS, out error);
|
||
|
}
|
||
|
finally {
|
||
|
ReleaseDirectoryServiceContract(rootNS);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static FileContract.Imp:Ready OpenFile(string! filePath, DirectoryServiceContract.Imp! rootNS)
|
||
|
{
|
||
|
ErrorCode error;
|
||
|
return OpenFile(filePath, rootNS, out error);
|
||
|
}
|
||
|
|
||
|
public static FileContract.Imp:Ready OpenFile(string! filePath,
|
||
|
DirectoryServiceContract.Imp! rootNS,
|
||
|
out ErrorCode errorOut)
|
||
|
{
|
||
|
FileContract.Imp! fileClient;
|
||
|
FileContract.Exp! fileServer;
|
||
|
FileContract.NewChannel(out fileClient, out fileServer);
|
||
|
|
||
|
TimeSpan start = ProcessService.GetUpTime();
|
||
|
bool ok = SdsUtils.Bind(filePath, rootNS, fileServer, out errorOut);
|
||
|
if (recording) {
|
||
|
TimeSpan duration = ProcessService.GetUpTime() - start;
|
||
|
lock (lockTarget) {
|
||
|
bindTime += duration;
|
||
|
++bindCount;
|
||
|
}
|
||
|
}
|
||
|
if (!ok) {
|
||
|
delete fileClient;
|
||
|
return null;
|
||
|
}
|
||
|
else {
|
||
|
}
|
||
|
fileClient.RecvSuccess();
|
||
|
|
||
|
return fileClient;
|
||
|
}
|
||
|
|
||
|
public static bool FileExists(DirectoryServiceContract.Imp:Ready! dsRoot,string! filePath)
|
||
|
{
|
||
|
ErrorCode error;
|
||
|
long size;
|
||
|
NodeType nodeType;
|
||
|
|
||
|
return GetAttributes(filePath, dsRoot, out size, out nodeType, out error);
|
||
|
}
|
||
|
|
||
|
#if !REMOVE
|
||
|
// REMOVE
|
||
|
public static int CreateFile(string! filePath)
|
||
|
{
|
||
|
DirectoryServiceContract.Imp! rootNS = DirectoryService.NewClientEndpoint();
|
||
|
|
||
|
try {
|
||
|
return CreateFile(filePath, rootNS);
|
||
|
}
|
||
|
finally {
|
||
|
delete rootNS;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
public static int CreateFile(string! filePath, DirectoryServiceContract.Imp! ds)
|
||
|
{
|
||
|
ErrorCode errorCode;
|
||
|
if (!CreateFile(filePath, ds, out errorCode)) {
|
||
|
return -1;
|
||
|
}
|
||
|
else return 0;
|
||
|
}
|
||
|
|
||
|
public static bool CreateFile(string! filePath, DirectoryServiceContract.Imp! ds, out ErrorCode errorCode)
|
||
|
{
|
||
|
errorCode = ErrorCode.Unknown;
|
||
|
|
||
|
string fileName = PathUtils.FileFromPath(filePath);
|
||
|
|
||
|
if (fileName == null) {
|
||
|
// No trailing file part
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
DirectoryServiceContract.Imp dirClient = DirectoryUtils.FindDir(filePath, ds);
|
||
|
|
||
|
if (dirClient == null)
|
||
|
{
|
||
|
// Couldn't open enclosing directory
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
dirClient.SendCreateFile(Bitter.FromString2(fileName));
|
||
|
|
||
|
switch receive {
|
||
|
case dirClient.NakCreateFile(error):
|
||
|
// Failure
|
||
|
errorCode = error;
|
||
|
delete dirClient;
|
||
|
return false;
|
||
|
|
||
|
case dirClient.AckCreateFile():
|
||
|
// Success
|
||
|
break;
|
||
|
|
||
|
case dirClient.ChannelClosed():
|
||
|
// Channel closed unexpectedly
|
||
|
errorCode = ErrorCode.ChannelClosed;
|
||
|
delete dirClient;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
delete dirClient;
|
||
|
return true;
|
||
|
} //createFile
|
||
|
|
||
|
// 0 is success
|
||
|
public static bool GetAttributes(string! filePath,
|
||
|
DirectoryServiceContract.Imp! ds,
|
||
|
out long size,
|
||
|
out NodeType nodeType,
|
||
|
out ErrorCode errorOut)
|
||
|
{
|
||
|
bool ok = SdsUtils.GetAttributes(filePath, ds, out size, out nodeType, out errorOut);
|
||
|
return ok;
|
||
|
}
|
||
|
|
||
|
// 0 is success
|
||
|
public static bool GetAttributes(string! filePath,
|
||
|
out long size,
|
||
|
out NodeType nodeType,
|
||
|
out ErrorCode errorOut)
|
||
|
{
|
||
|
bool ok = false;
|
||
|
nodeType = NodeType.BadNode;
|
||
|
errorOut = ErrorCode.Unknown;
|
||
|
size = 0;
|
||
|
DirectoryServiceContract.Imp! rootNS = GetDirectoryServiceContract();
|
||
|
try {
|
||
|
ok = GetAttributes(filePath, rootNS, out size, out nodeType, out errorOut);
|
||
|
}
|
||
|
catch (Exception e) {
|
||
|
Console.WriteLine("FileUtils.GetAttributes exception: {0}", e.Message);
|
||
|
}
|
||
|
finally {
|
||
|
ReleaseDirectoryServiceContract(rootNS);
|
||
|
}
|
||
|
return ok;
|
||
|
}
|
||
|
|
||
|
#if !REMOVE
|
||
|
// REMOVE version that does not have ep
|
||
|
public static int DeleteFile(string! filePath)
|
||
|
{
|
||
|
DirectoryServiceContract.Imp! ds = GetDirectoryServiceContract();
|
||
|
ErrorCode errorOut = ErrorCode.Unknown;
|
||
|
try {
|
||
|
DeleteFile(filePath, ds, out errorOut);
|
||
|
}
|
||
|
catch (Exception e) {
|
||
|
Console.WriteLine("FileUtils.DeleteFile exception: {0}", e.Message);
|
||
|
}
|
||
|
finally {
|
||
|
ReleaseDirectoryServiceContract(ds);
|
||
|
}
|
||
|
return (int) errorOut;
|
||
|
}
|
||
|
#endif
|
||
|
public static int DeleteFile(string! filePath, DirectoryServiceContract.Imp! ds, out ErrorCode errorOut )
|
||
|
{
|
||
|
string fileName = PathUtils.FileFromPath(filePath);
|
||
|
errorOut = ErrorCode.Unknown;
|
||
|
|
||
|
if (fileName == null) {
|
||
|
// No trailing filename
|
||
|
errorOut = ErrorCode.NotFound;
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
DirectoryServiceContract.Imp dirClient = DirectoryUtils.FindDir(filePath, ds);
|
||
|
|
||
|
if (dirClient == null)
|
||
|
{
|
||
|
// Couldn't open enclosing directory
|
||
|
errorOut = ErrorCode.NotFound;
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
dirClient.SendDeleteFile(Bitter.FromString2(fileName));
|
||
|
|
||
|
switch receive {
|
||
|
case dirClient.NakDeleteFile(error):
|
||
|
errorOut = error;
|
||
|
// Failed; no such file?
|
||
|
delete dirClient;
|
||
|
return (int) errorOut;
|
||
|
|
||
|
case dirClient.AckDeleteFile():
|
||
|
errorOut = ErrorCode.NoError;
|
||
|
// Success
|
||
|
break;
|
||
|
|
||
|
case dirClient.ChannelClosed():
|
||
|
// Channel closed unexpectedly
|
||
|
errorOut = ErrorCode.ChannelClosed;
|
||
|
delete dirClient;
|
||
|
return (int) errorOut;
|
||
|
}
|
||
|
|
||
|
delete dirClient;
|
||
|
return 0;
|
||
|
} //DeleteFile
|
||
|
|
||
|
public static byte[] ReadEntireFile(
|
||
|
string! filePath,
|
||
|
DirectoryServiceContract.Imp! ds)
|
||
|
{
|
||
|
FileContract.Imp:Ready fileEP = OpenFile(filePath, ds);
|
||
|
|
||
|
if (fileEP == null) {
|
||
|
delete fileEP;
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
long size;
|
||
|
NodeType ignored;
|
||
|
ErrorCode err;
|
||
|
|
||
|
if (!GetAttributes(filePath, out size, out ignored, out err)) {
|
||
|
delete fileEP;
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
byte[] data = new byte[size];
|
||
|
|
||
|
if (Read(fileEP, 0, (int)size, 0, data) != size) {
|
||
|
delete fileEP;
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
delete fileEP;
|
||
|
return data;
|
||
|
}
|
||
|
|
||
|
public static long Read(
|
||
|
FileContract.Imp:Ready! fileClient,
|
||
|
int bufOffset,
|
||
|
int readSize,
|
||
|
long fileOffset,
|
||
|
byte[]! buf)
|
||
|
{
|
||
|
long readCount = 0;
|
||
|
int error;
|
||
|
byte[]! in ExHeap readBytes = new[ExHeap] byte[readSize];
|
||
|
fileClient.SendRead(readBytes, 0, fileOffset, readBytes.Length);
|
||
|
fileClient.RecvAckRead(out readBytes, out readCount, out error);
|
||
|
|
||
|
if (error == 0) {
|
||
|
Bitter.ToByteArray(readBytes, 0, (int)readCount, buf, (int)bufOffset);
|
||
|
} else {
|
||
|
readCount = 0;
|
||
|
}
|
||
|
|
||
|
delete readBytes;
|
||
|
return readCount;
|
||
|
}
|
||
|
|
||
|
public static long Write(
|
||
|
FileContract.Imp:Ready! fileClient,
|
||
|
int bufOffset,
|
||
|
int writeSize,
|
||
|
long fileOffset,
|
||
|
byte[]! buf)
|
||
|
{
|
||
|
long writeCount = 0;
|
||
|
int error;
|
||
|
byte[]! in ExHeap writeBytes = new[ExHeap] byte[writeSize];
|
||
|
|
||
|
Bitter.FromByteArray(writeBytes, 0, writeSize, buf, bufOffset);
|
||
|
fileClient.SendWrite(writeBytes, 0, fileOffset, writeSize);
|
||
|
fileClient.RecvAckWrite(out writeBytes, out writeCount, out error);
|
||
|
|
||
|
if (error != 0) {
|
||
|
writeCount = 0;
|
||
|
}
|
||
|
|
||
|
delete writeBytes;
|
||
|
return writeCount;
|
||
|
}
|
||
|
|
||
|
public static long Write(
|
||
|
FileContract.Imp:Ready! fileClient,
|
||
|
long offset,
|
||
|
byte[]! data)
|
||
|
{
|
||
|
return Write(fileClient, 0, data.Length, offset, data);
|
||
|
}
|
||
|
|
||
|
// we'll do something more intelligent than this later
|
||
|
public static long Write(
|
||
|
FileContract.Imp:Ready! fileClient,
|
||
|
long offset,
|
||
|
string! line) {
|
||
|
|
||
|
return Write(fileClient, offset, Encoding.UTF8.GetBytes(line));
|
||
|
}
|
||
|
|
||
|
public static long WriteLine(
|
||
|
FileContract.Imp:Ready! fileClient,
|
||
|
long offset,
|
||
|
string line) {
|
||
|
|
||
|
return Write(fileClient, offset, line+"\r\n");
|
||
|
}
|
||
|
}
|
||
|
}
|