Wednesday, December 29, 2010

Using the FIM WMI Provider While Syncs Are Running

It’s always been a worst-practice to make external calls from rules extensions in the sync engine, but a bad idea of mine illustrated the reason why today.

In my scenario, I really want my MV code to fire on objects ONLY when they have already been exported and confirmed by the outbound MA.  The right way to do this is to use a constant Import Attribute Flow (IAF) rule on that MA, in which case the scenario looks like this:

  1. MV code creates a new CSEntry in the outbound MA
  2. Outbound MA runs Export
  3. Outbound MA runs Import
  4. Outbound MA runs Sync – this is where our IAF rule flows a value to the MVEntry

If the attribute on the MVEntry has a value, then we know the outbound MA has completed the Export and Import successfully.

The rub in my scenario is that I cannot modify the MV schema, so I can’t use this approach.  Grasping at straws I thought I could just look at the CSEntry using the MIIS_CSObject class in WMI.  This is where the wheels came off.

When I put the code in place and ran Preview, the sync service hung.  In my sync cycle, WMI was being called from my MV code which seems harmless enough since WMI is only reading objects, but I knew I was being less than smart, this was just prototyping, really, I’m normally a lot smarter, at least the second or third time.

Anyhow, this exact scenario created what is most likely a deadlock in SQL but the usual MIIS deadlock error didn’t happen.  Unfortunately the service just hung and had to be killed (killed several times in fact, as I was troubleshooting the issue).  Hard to call this a fault of the product since I should know better, but I would have liked the sync cycle to fail with a deadlock error, or the WMI call to fail with something similar.

The moral of the story is simple; follow the best practices as much as possible; don’t make external calls from rules extension code, and don’t query the sync database (even with WMI I guess) while the sync engine is running.

3 comments:

Chris Clayton said...

Well, this gives me a little pause today. I currently schedule my ILM/FIM MA runs by vbscript and making WMI calls. Before any MA run profile is executed the script cycles through all MAs and determines whether any of them have a run in progress already. If so, it sends me an email and waits a predetermined amount of time before trying again. This is a holdover from when I had more than one script scheduled (I combined them), but is also a good safety in case the script is accidentally run twice or I hop on and run something manually.

I had been considering doing WMI calls periodically to ensure that a run profile had been started recently to make sure something didn't hang. I have to wonder if the MIIS_ManagementAgent source isn't less intrusive than using MIIS_CSObject.

Craig Martin said...

Don't forget to check out the FIM PowerShell Module, it makes very easy work of dealing with the Sync Engine's WMI classes.
http://fimpowershellmodule.codeplex.com/wikipage?title=Get-ManagementAgent&referringTitle=Documentation

David Lundell said...

I believe the Deadlock occurred because the sync process created an exclusive lock on the record in the mms_connectorspace table and then your code launched an outside process (the WMI query) that tried to obtain a shared lock on the very same record, and your code running within the context of the sync process was waiting on your outside process (the WMI query) to complete before it would release its exclusive lock.