microsoft / ManagedEsent

MIT License
242 stars 36 forks source link

Question: How to properly use esent session on different threads #8

Open Opiumtm opened 6 years ago

Opiumtm commented 6 years ago

Normally esent sessions are bound to thread on which they're created. Any attempt to use session on different thread results in exception. Although there is an API method to temporarily bind session to different thread, so session could be used from such thread without exception.

But this particular feature is poorly documented.

public static void JetSetSessionContext(
    JET_SESID sesid,
    IntPtr context
)

context Type: System.IntPtr The context to set.

The meaning of "context" argument is unexplained and there is nowhere to find a clear explanation what it really means and what should be used for the "context" value.

machish commented 6 years ago

It is pretty obtuse. Even when I was at MS and had full access to the code it took me a while to figure it out, and now I forget. :) This is from memory. Maybe @michaelthorp can correct me if I'm wrong:

Hope that helps slightly, and sorry that I couldn't be more definitive.

-martin

Opiumtm commented 6 years ago

@machish As far as I have understood from this repository unit tests and from quite unclear documentation at MSDN (no information on managed ESENT page, but some incomplete information on unmanaged ESENT API page), it looks like JetSessionContext can take any valid IntPtr (-1 and null are explicitly stated as invalid values). At least, it's advised to pass a pointer to (arbitrary) valid C++ object on heap as a session context pointer value. But I'm not sure if I completely understand the valid value rules (Pointer should have reference to the allocated virtual memory page? Or not?) and I don't know how it's apply to managed .NET memory (where objects could be freely moved to the new address by GC) as it was advised to pass a pointer to the unmanaged C++ object.

It might be that you have to call JetSetSessionContext prior to starting the first transaction? And that you have to call JetResetSessionContext after committing/rolling back to level 0?

Unmanaged Esent API documentation explicitly states that to successfully invoke JetSetSessionContext, session shouldn't be in any transaction and context should be set before you start any transaction.

Opiumtm commented 6 years ago

@michaelthorp any info on this question?

michaelthorp commented 5 years ago

@Opiumtm - I can't find anywhere that the pointer is dereferenced, so I believe you would be fine even if GC ran (I don't think .NET GC updates pointers). If you wanted to be safe (especially if you are planning on using long-living contexts) you could allocate some context on the managed heap and then GC wouldn't touch it so your pointer would stay.