// --------------------------------------------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation.
//
//
// Callback for JET_param JET_paramDurableCommitCallback.
//
// --------------------------------------------------------------------------------------------------------------------
namespace Microsoft.Isam.Esent.Interop.Windows8
{
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Reflection;
#if !MANAGEDESENT_ON_CORECLR
using System.Runtime.CompilerServices;
#endif
using Microsoft.Isam.Esent.Interop.Implementation;
///
/// A class which wraps the callback dealing with durable commits.
///
public class DurableCommitCallback : EsentResource
{
///
/// API call tracing.
///
private static readonly TraceSwitch TraceSwitch = new TraceSwitch("ESENT DurableCommitCallback", "Wrapper around unmanaged ESENT durable commit callback");
///
/// Instance associated with this callback.
///
private JET_INSTANCE instance;
///
/// Hold a reference to the delegate so that it doesn't get garbage-collected.
///
private JET_PFNDURABLECOMMITCALLBACK wrappedCallback;
///
/// Hold a reference to the delegate so that it doesn't get garbage-collected.
///
[SuppressMessage("Exchange.Performance", "EX0023:DeadVariableDetector", Justification = "Need to hold on to a reference to the callback, so that it does not get garbage collected.")]
private NATIVE_JET_PFNDURABLECOMMITCALLBACK wrapperCallback;
///
/// Initializes a new instance of the class.
/// The constructor.
///
///
/// The instance with which to associate the callback.
///
///
/// The managed code callback to call.
///
public DurableCommitCallback(
JET_INSTANCE instance,
JET_PFNDURABLECOMMITCALLBACK wrappedCallback)
{
this.instance = instance;
this.wrappedCallback = wrappedCallback;
this.wrapperCallback = this.NativeDurableCommitCallback;
#if !MANAGEDESENT_ON_WSA // RuntimeHelpers works differently in Windows Store Apps.
if (this.wrappedCallback != null)
{
RuntimeHelpers.PrepareMethod(this.wrappedCallback.Method.MethodHandle);
}
RuntimeHelpers.PrepareMethod(typeof(DurableCommitCallback).GetMethod("NativeDurableCommitCallback", BindingFlags.NonPublic | BindingFlags.Instance).MethodHandle);
#endif
InstanceParameters instanceParameters = new InstanceParameters(this.instance);
// This might be null.
instanceParameters.SetDurableCommitCallback(this.wrapperCallback);
this.ResourceWasAllocated();
}
///
/// Generate a string representation of the structure.
///
/// The structure as a string.
public override string ToString()
{
return string.Format(
CultureInfo.InvariantCulture,
"DurableCommitCallback({0})",
this.instance.ToString());
}
///
/// Terminate the durable commit session.
///
public void End()
{
this.CheckObjectIsNotDisposed();
this.ReleaseResource();
}
///
/// Free the durable commit session.
/// We do not try to set the instance parameter to null, since the callback is disposed after JetTerm and
/// the callback cannot be set after JetTerm.
///
protected override void ReleaseResource()
{
this.instance = JET_INSTANCE.Nil;
this.wrappedCallback = null;
this.wrapperCallback = null;
this.ResourceWasReleased();
}
///
/// The proxy callback function to call the user-defined managed delegate.
///
///
/// The instance.
///
///
/// The commit-id flushed.
///
///
/// Reserved currently.
///
///
/// An error code.
///
private JET_err NativeDurableCommitCallback(
IntPtr instance,
ref NATIVE_COMMIT_ID commitIdSeen,
uint grbit)
{
RuntimeHelpers.PrepareConstrainedRegions();
try
{
JET_INSTANCE jetInstance = new JET_INSTANCE()
{
Value = instance
};
if (this.instance != jetInstance)
{
// We assume it's only called on one instance at a time. The only thing
// we really care about is serialization of the byte array.
//
// It would be nice to throw an error, but we're going back to real
// code, which doesn't deal with managed exceptions well.
return JET_err.CallbackFailed;
}
JET_COMMIT_ID commitId = new JET_COMMIT_ID(commitIdSeen);
return this.wrappedCallback(jetInstance, commitId, (DurableCommitCallbackGrbit)grbit);
}
catch (Exception ex)
{
Trace.WriteLineIf(
TraceSwitch.TraceWarning, string.Format(CultureInfo.InvariantCulture, "Caught Exception {0}", ex));
JetApi.ReportUnhandledException(ex, "Unhandled exception during NativeDurableCommitCallback");
// This should never be executed, but the compiler doesn't know it.
return JET_err.CallbackFailed;
}
}
}
}