Skip to content

Commit

Permalink
Merge pull request #1047 from dVakulen/json-net-fallback-serializer
Browse files Browse the repository at this point in the history
 Implemented Json.Net fallback serializer
  • Loading branch information
Gabriel Kliot committed Nov 26, 2015
2 parents 0f6d7ee + 06b86c1 commit ae97c47
Show file tree
Hide file tree
Showing 19 changed files with 591 additions and 91 deletions.
10 changes: 10 additions & 0 deletions src/Orleans/Configuration/MessagingConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ public class MessagingConfiguration : IMessagingConfiguration
public int GatewaySenderQueues { get; set; }
public int ClientSenderBuckets { get; set; }
public bool UseStandardSerializer { get; set; }
public bool UseJsonFallbackSerializer { get; set; }

public int BufferPoolBufferSize { get; set; }
public int BufferPoolMaxSize { get; set; }
Expand Down Expand Up @@ -226,6 +227,8 @@ public override string ToString()
}
sb.AppendFormat(" Use standard (.NET) serializer: {0}", UseStandardSerializer)
.AppendLine(isSiloConfig ? "" : " [NOTE: This *MUST* match the setting on the server or nothing will work!]");
sb.AppendFormat(" Use fallback json serializer: {0}", UseJsonFallbackSerializer)
.AppendLine(isSiloConfig ? "" : " [NOTE: This *MUST* match the setting on the server or nothing will work!]");
sb.AppendFormat(" Buffer Pool Buffer Size: {0}", BufferPoolBufferSize).AppendLine();
sb.AppendFormat(" Buffer Pool Max Size: {0}", BufferPoolMaxSize).AppendLine();
sb.AppendFormat(" Buffer Pool Preallocation Size: {0}", BufferPoolPreallocationSize).AppendLine();
Expand Down Expand Up @@ -298,6 +301,13 @@ internal virtual void Load(XmlElement child)
"invalid boolean value for the UseStandardSerializer attribute on the Messaging element");
}

if (child.HasAttribute("UseJsonFallbackSerializer"))
{
UseJsonFallbackSerializer =
ConfigUtilities.ParseBool(child.GetAttribute("UseJsonFallbackSerializer"),
"invalid boolean value for the UseJsonFallbackSerializer attribute on the Messaging element");
}

//--
if (child.HasAttribute("BufferPoolBufferSize"))
{
Expand Down
2 changes: 2 additions & 0 deletions src/Orleans/IDs/ActivationAddress.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ MIT License
*/

using System;
using Newtonsoft.Json;

namespace Orleans.Runtime
{
Expand All @@ -37,6 +38,7 @@ public bool IsComplete
get { return Grain != null && Activation != null && Silo != null; }
}

[JsonConstructor]
private ActivationAddress(SiloAddress silo, GrainId grain, ActivationId activation)
{
Silo = silo;
Expand Down
2 changes: 2 additions & 0 deletions src/Orleans/IDs/UniqueIdentifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@ MIT License
*/

using System;
using Newtonsoft.Json;

namespace Orleans.Runtime
{
[Serializable]
internal abstract class UniqueIdentifier : IEquatable<UniqueIdentifier>, IComparable<UniqueIdentifier>
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
[JsonProperty]
protected readonly internal UniqueKey Key;

protected UniqueIdentifier()
Expand Down
1 change: 1 addition & 0 deletions src/Orleans/Logging/ErrorCodes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -903,6 +903,7 @@ internal enum ErrorCode
SerMgr_IgnoreAssembly = SerializationManagerBase + 8,
SerMgr_TypeRegistrationFailureIgnore = SerializationManagerBase + 9,
SerMgr_ArtifactReport = SerializationManagerBase + 10,
SerMgr_UnavailableSerializer = SerializationManagerBase + 11,

WatchdogBase = Runtime + 2600,
Watchdog_ParticipantThrownException = WatchdogBase + 1,
Expand Down
7 changes: 6 additions & 1 deletion src/Orleans/Orleans.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Newtonsoft.Json">
<HintPath>$(SolutionDir)packages\Newtonsoft.Json.6.0.8\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Management" />
<Reference Include="System.Xml" />
Expand Down Expand Up @@ -124,6 +127,8 @@
<Compile Include="IDs\UniqueKey.cs" />
<Compile Include="Core\IGrainFactory.cs" />
<Compile Include="Runtime\IGrainRuntime.cs" />
<Compile Include="Serialization\OrleansJsonSerializer.cs" />
<Compile Include="Serialization\BinaryFormatterSerializer.cs" />
<Compile Include="Streams\Internal\StreamHandshakeToken.cs" />
<Compile Include="Serialization\NonSerializableAttribute.cs" />
<Compile Include="Streams\PersistentStreams\IDeploymentConfiguration.cs" />
Expand Down Expand Up @@ -429,4 +434,4 @@
<Message Text="[OrleansDllBootstrapUsingCodeGen] - Invoking Code Generator" />
<Exec Command="&quot;$(BootstrapOutputPath)ClientGenerator.exe&quot; &quot;@$(ArgsFile)&quot;" />
</Target>
</Project>
</Project>
2 changes: 1 addition & 1 deletion src/Orleans/Runtime/OutsideRuntimeClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ public OutsideRuntimeClient(ClientConfiguration cfg, GrainFactory grainFactory,

if (!TraceLogger.IsInitialized) TraceLogger.Initialize(config);
StatisticsCollector.Initialize(config);
SerializationManager.Initialize(config.UseStandardSerializer, cfg.SerializationProviders);
SerializationManager.Initialize(config.UseStandardSerializer, cfg.SerializationProviders, config.UseJsonFallbackSerializer);
logger = TraceLogger.GetLogger("OutsideRuntimeClient", TraceLogger.LoggerType.Runtime);
appLogger = TraceLogger.GetLogger("Application", TraceLogger.LoggerType.Application);

Expand Down
130 changes: 130 additions & 0 deletions src/Orleans/Serialization/BinaryFormatterSerializer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading.Tasks;
using Orleans.Runtime;

#if !DNXCORE50
namespace Orleans.Serialization
{
public class BinaryFormatterSerializer : IExternalSerializer
{
private TraceLogger logger;
public void Initialize(TraceLogger logger)
{
this.logger = logger;
}

public bool IsSupportedType(Type itemType)
{
return itemType.GetTypeInfo().IsSerializable;
}

public object DeepCopy(object source)
{
if (source == null)
{
return null;
}

var formatter = new BinaryFormatter();
object ret = null;
using (var memoryStream = new MemoryStream())
{
formatter.Serialize(memoryStream, source);
memoryStream.Flush();
memoryStream.Seek(0, SeekOrigin.Begin);
formatter.Binder = DynamicBinder.Instance;
ret = formatter.Deserialize(memoryStream);
}

return ret;
}

public void Serialize(object item, BinaryTokenStreamWriter writer, Type expectedType)
{
if (writer == null)
{
throw new ArgumentNullException("writer");
}

if (item == null)
{
writer.WriteNull();
return;
}

var formatter = new BinaryFormatter();
byte[] bytes;
using (var memoryStream = new MemoryStream())
{
formatter.Serialize(memoryStream, item);
memoryStream.Flush();
bytes = memoryStream.ToArray();
}

writer.Write(bytes.Length);
writer.Write(bytes);
}

public object Deserialize(Type expectedType, BinaryTokenStreamReader reader)
{
if (reader == null)
{
throw new ArgumentNullException("reader");
}

var n = reader.ReadInt();
var bytes = reader.ReadBytes(n);
var formatter = new BinaryFormatter();
object retVal = null;
using (var memoryStream = new MemoryStream(bytes))
{
retVal = formatter.Deserialize(memoryStream);
}

return retVal;
}


/// <summary>
/// This appears necessary because the BinaryFormatter by default will not see types
/// that are defined by the InvokerGenerator.
/// Needs to be public since it used by generated client code.
/// </summary>
class DynamicBinder : SerializationBinder
{
public static readonly SerializationBinder Instance = new DynamicBinder();

private readonly Dictionary<string, Assembly> assemblies = new Dictionary<string, Assembly>();

public override Type BindToType(string assemblyName, string typeName)
{
lock (this.assemblies)
{
Assembly result;
if (!this.assemblies.TryGetValue(assemblyName, out result))
{
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
this.assemblies[assembly.GetName().FullName] = assembly;

// in some cases we have to explicitly load the assembly even though it seems to be already loaded but for some reason it's not listed in AppDomain.CurrentDomain.GetAssemblies()
if (!this.assemblies.TryGetValue(assemblyName, out result))
this.assemblies[assemblyName] = Assembly.Load(new AssemblyName(assemblyName));

result = this.assemblies[assemblyName];
}

return result.GetType(typeName);
}
}
}
}
}
#endif

0 comments on commit ae97c47

Please sign in to comment.