public void VerifyWrapperPassesArguments() { JET_SESID expectedSesid = new JET_SESID { Value = (IntPtr)1 }; JET_DBID expectedDbid = new JET_DBID { Value = 2 }; JET_TABLEID expectedTableid = new JET_TABLEID { Value = (IntPtr)3 }; JET_cbtyp expectedCbtyp = JET_cbtyp.AfterReplace; object expectedArg1 = null; object expectedArg2 = null; IntPtr expectedContext = (IntPtr)4; JET_SESID actualSesid = new JET_SESID(); JET_DBID actualDbid = new JET_DBID(); JET_TABLEID actualTableid = new JET_TABLEID(); JET_cbtyp actualCbtyp = JET_cbtyp.Null; object actualArg1 = null; object actualArg2 = null; IntPtr actualContext = new IntPtr(); var wrapper = new JetCallbackWrapper( (sesid, dbid, tableid, cbtyp, arg1, arg2, context, unused) => { actualSesid = sesid; actualDbid = dbid; actualTableid = tableid; actualCbtyp = cbtyp; actualArg1 = arg1; actualArg2 = arg2; actualContext = context; return(JET_err.Success); }); wrapper.NativeCallback( expectedSesid.Value, expectedDbid.Value, expectedTableid.Value, (uint)expectedCbtyp, IntPtr.Zero, IntPtr.Zero, expectedContext, IntPtr.Zero); Assert.AreEqual(expectedSesid, actualSesid); Assert.AreEqual(expectedDbid, actualDbid); Assert.AreEqual(expectedTableid, actualTableid); Assert.AreEqual(expectedCbtyp, actualCbtyp); Assert.AreEqual(expectedArg1, actualArg1); Assert.AreEqual(expectedArg2, actualArg2); Assert.AreEqual(expectedContext, actualContext); }
/// <summary> /// A JET_CALLBACK delegate used as the runtime callback. /// </summary> /// <param name="callbackSesid">The session.</param> /// <param name="callbackDbid">The database.</param> /// <param name="callbackTableid">The table.</param> /// <param name="cbtyp">The callback type.</param> /// <param name="arg1">Argument 1.</param> /// <param name="arg2">Argument 2.</param> /// <param name="context">Unused context.</param> /// <param name="unused">This parameter is ignored.</param> /// <returns>Always returns JET_err.Success.</returns> private JET_err RuntimeCallback( JET_SESID callbackSesid, JET_DBID callbackDbid, JET_TABLEID callbackTableid, JET_cbtyp cbtyp, object arg1, object arg2, IntPtr context, IntPtr unused) { this.runtimeCallbackWasCalled = true; return(JET_err.Success); }
/// <summary> /// Callback function for native code. We don't want to throw an exception through /// unmanaged ESENT because that will corrupt ESENT's internal state. Instead we /// catch all exceptions and return an error instead. We use a CER to make catching /// the exceptions as reliable as possible. /// </summary> /// <param name="nativeSesid">The session for which the callback is being made.</param> /// <param name="nativeDbid">The database for which the callback is being made.</param> /// <param name="nativeTableid">The cursor for which the callback is being made.</param> /// <param name="nativeCbtyp">The operation for which the callback is being made.</param> /// <param name="arg1">First callback-specific argument.</param> /// <param name="arg2">Second callback-specific argument.</param> /// <param name="nativeContext">Callback context.</param> /// <param name="unused">This parameter is not used.</param> /// <returns>An ESENT error code.</returns> private JET_err CallbackImpl( IntPtr nativeSesid, uint nativeDbid, IntPtr nativeTableid, uint nativeCbtyp, IntPtr arg1, IntPtr arg2, IntPtr nativeContext, IntPtr unused) { RuntimeHelpers.PrepareConstrainedRegions(); try { var sesid = new JET_SESID { Value = nativeSesid }; var dbid = new JET_DBID { Value = nativeDbid }; var tableid = new JET_TABLEID { Value = nativeTableid }; JET_cbtyp cbtyp = (JET_cbtyp)nativeCbtyp; Debug.Assert(this.wrappedCallback.IsAlive, "Wrapped callback has been garbage collected"); // This will throw an exception if the wrapped callback has been collected. The exception // will be handled below. JET_CALLBACK callback = (JET_CALLBACK)this.wrappedCallback.Target; return(callback(sesid, dbid, tableid, cbtyp, null, null, nativeContext, IntPtr.Zero)); } catch (Exception ex) { // Thread aborts aren't handled here. ESENT callbacks can execute on client threads or // internal ESENT threads so it isn't clear what should be done on an abort. Trace.WriteLineIf( traceSwitch.TraceWarning, String.Format(CultureInfo.InvariantCulture, "Caught Exception {0}", ex)); return(JET_err.CallbackFailed); } }
private JET_err DefragmentationStatusCallback(JET_SESID sesid, JET_DBID dbId, JET_TABLEID tableId, JET_cbtyp cbtyp, object data1, object data2, IntPtr ptr1, IntPtr ptr2) { defragmentationCompleted = cbtyp == JET_cbtyp.OnlineDefragCompleted; return JET_err.Success; }
/// <summary> /// A JET_CALLBACK delegate used as the runtime callback. /// </summary> /// <param name="callbackSesid">The session.</param> /// <param name="callbackDbid">The database.</param> /// <param name="callbackTableid">The table.</param> /// <param name="cbtyp">The callback type.</param> /// <param name="arg1">Argument 1.</param> /// <param name="arg2">Argument 2.</param> /// <param name="context">Unused context.</param> /// <param name="unused">This parameter is ignored.</param> /// <returns>JET_err.Success.</returns> private JET_err RuntimeCallback( JET_SESID callbackSesid, JET_DBID callbackDbid, JET_TABLEID callbackTableid, JET_cbtyp cbtyp, object arg1, object arg2, IntPtr context, IntPtr unused) { this.runtimeCallbackWasCalled = true; return JET_err.Success; }
/// <summary> /// Configures the database engine to stop issuing notifications to the /// application as previously requested through /// <see cref="JetRegisterCallback"/>. /// </summary> /// <param name="sesid">The session to use.</param> /// <param name="tableid"> /// A cursor opened on the table that the callback should be /// registered on. /// </param> /// <param name="cbtyp"> /// The callback reasons for which the application no longer wishes to receive notifications. /// </param> /// <param name="callbackId"> /// The handle of the registered callback that was returned by <see cref="JetRegisterCallback"/>. /// </param> public static void JetUnregisterCallback(JET_SESID sesid, JET_TABLEID tableid, JET_cbtyp cbtyp, JET_HANDLE callbackId) { Api.Check(Impl.JetUnregisterCallback(sesid, tableid, cbtyp, callbackId)); }
/// <summary> /// Allows the application to configure the database engine to issue /// notifications to the application for specific events. These /// notifications are associated with a specific table and remain in /// effect only until the instance containing the table is shut down /// using <see cref="JetTerm"/>. /// </summary> /// <param name="sesid">The session to use.</param> /// <param name="tableid"> /// A cursor opened on the table that the callback should be /// registered on. /// </param> /// <param name="cbtyp"> /// The callback reasons for which the application wishes to receive notifications. /// </param> /// <param name="callback">The callback function.</param> /// <param name="context">A context that will be given to the callback.</param> /// <param name="callbackId"> /// A handle that can later be used to cancel the registration of the given /// callback function using <see cref="JetUnregisterCallback"/>. /// </param> public static void JetRegisterCallback( JET_SESID sesid, JET_TABLEID tableid, JET_cbtyp cbtyp, JET_CALLBACK callback, IntPtr context, out JET_HANDLE callbackId) { Api.Check(Impl.JetRegisterCallback(sesid, tableid, cbtyp, callback, context, out callbackId)); }
private JET_err DefragmentationStatusCallback(JET_SESID sesid, JET_DBID dbId, JET_TABLEID tableId, JET_cbtyp cbtyp, object data1, object data2, IntPtr ptr1, IntPtr ptr2) { defragmentationCompleted = cbtyp == JET_cbtyp.OnlineDefragCompleted; return(JET_err.Success); }