Dryad/LinqToDryad/DryadLinqObjectStore.cs

169 lines
5.9 KiB
C#

/*
Copyright (c) Microsoft Corporation
All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
compliance with the License. You may obtain a copy of the License
at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER
EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF
TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions and
limitations under the License.
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Diagnostics;
using Microsoft.Research.DryadLinq;
namespace Microsoft.Research.DryadLinq.Internal
{
// This class implements an object store that is used to store objects
// needed for remote execution of managed vertex code. All objects put
// in the store must have the .NET Serializable attribute.
// Note: this class is not thread safe
public sealed class DryadLinqObjectStore
{
private const string ObjectStoreFileName = "DryadLinqObjectStore.bin";
internal static string GetClientSideObjectStorePath()
{
return DryadLinqCodeGen.GetPathForGeneratedFile(ObjectStoreFileName, null);
}
private static ArrayList s_objectList = null;
public static bool IsEmpty
{
get {
return (s_objectList == null || s_objectList.Count == 0);
}
}
public static void Clear()
{
s_objectList = null;
}
// this method is only used by the generated vertex code, and always
// assumes "DryadLinqObjectStore.bin" to be in the current directory
public static object Get(int idx)
{
if (s_objectList == null)
{
// Try to open the object store. First look in the parent directory
// (job directory when running normally), then try opening it from the path.
FileStream fs;
try
{
fs = new FileStream(Path.Combine(Directory.GetParent(Directory.GetCurrentDirectory()).FullName, ObjectStoreFileName), FileMode.Open, FileAccess.Read, FileShare.Read);
}
catch (FileNotFoundException)
{
fs = new FileStream(ObjectStoreFileName, FileMode.Open, FileAccess.Read, FileShare.Read);
}
BinaryFormatter bfm = new BinaryFormatter();
try
{
s_objectList = (ArrayList)bfm.Deserialize(fs);
}
catch (SerializationException e)
{
throw new DryadLinqException(DryadLinqErrorCode.FailedToDeserialize,
SR.FailedToDeserialize, e);
}
finally
{
if (fs != null) fs.Close();
}
}
if (idx >= s_objectList.Count)
{
throw new DryadLinqException(DryadLinqErrorCode.IndexOutOfRange,
SR.IndexOutOfRange);
}
return s_objectList[idx];
}
public static int Put(object obj)
{
if (s_objectList != null)
{
for (int idx = 0; idx < s_objectList.Count; idx++)
{
if (Object.ReferenceEquals(obj, s_objectList[idx]))
{
return idx;
}
}
}
if (s_objectList == null)
{
s_objectList = new ArrayList(4);
}
s_objectList.Add(obj);
return (s_objectList.Count - 1);
}
// This method is only used by the client process to save the object store before submitting a job
// Like other generated files we need to save this file in the temp directory
public static void Save()
{
if (IsEmpty) return;
string objectStorePath = GetClientSideObjectStorePath();
FileStream fs = new FileStream(objectStorePath, FileMode.Create);
try
{
BinaryFormatter bfm = new BinaryFormatter();
bfm.Serialize(fs, s_objectList);
}
catch (SerializationException e)
{
foreach (object obj in s_objectList)
{
Type badType = TypeSystem.GetNonserializable(obj);
if (badType != null)
{
if (badType.IsGenericType &&
badType.GetGenericTypeDefinition() == typeof(DryadLinqQuery<>))
{
throw new DryadLinqException(DryadLinqErrorCode.CannotSerializeDryadLinqQuery,
SR.CannotSerializeDryadLinqQuery);
}
else
{
throw new DryadLinqException(DryadLinqErrorCode.CannotSerializeObject,
string.Format(SR.CannotSerializeObject, obj));
}
}
}
throw new DryadLinqException(DryadLinqErrorCode.GeneralSerializeFailure,
SR.GeneralSerializeFailure, e);
}
finally
{
if (fs != null) fs.Close();
}
}
}
}