Archive for September, 2008

Transactional remote receive in MSMQ

Thursday, September 25th, 2008

Can you implement publish-subscribe load balancing with MSMQ?

Surprisingly, prior to Windows Server 2008 the answer was no! (Well, technically the capability is in Vista too, but who runs Vista in their datacenter?)

It's a common scenario. I have work that I want to share among several load-balanced, redundant servers. Only one server can be working on an item at a time. If a server crashes while working on an item, then another server should pick it up instead.

What's the solution? Publish the work items to a queue and have each of the servers subscribe. The servers receive the work items transactionally, so that if the work fails or the server crashes it is aborted back to the queue. But while one server has the work item locked, other servers will not receive it. They will get work items further down in the queue.

The problem is that MSMQ 3.0 and prior cannot receive messages transactionally from a remote queue. This feature only works with local queues. Instead of a publish-subscribe model, you have to use a push model. Push the message to the machine that you want to process it.

John Breakwell posted your options. You can upgrade to Windows Server 2008, implement a dispatcher (turning your pub-sub into a push), or peek-then-receive. The last is not really an option, because it violates the requirement that only one server is working on an item at a time.

Here's my solution
I propose a fourth option. Don't use MSMQ. Instead, write a journal table in SQL Server. Getting the locking right is a bit tricky, but it's doable. (Hint: you will make use of UPDLOCK.)

Honestly, this is a primary use case for a queuing technology. No, this is the primary use case. How could you even release version 1.0 without support for pub-sub? I've gone my entire career assuming that this feature was there, only to find out in integration testing that it is lacking.

Relative CSS Positioning

Saturday, September 20th, 2008

I learned a couple of CSS positioning rules that are not immediately apparent from reading W3Schools. Web designers are familiar with these rules, but this information needs to trickle down to us brute-force developers.

The position CSS style
Here are some rules I learned from Aucustic Cuckoo.

The position: relative and position: absolute styles don't work the way you might expect as a developer. We expect that absolute means to set the position from the top-left corner of the window, and that relative means to set the position from the container. Both of these assumptions are wrong.

If you don't set a position CSS style on your element, the browser lays it out based on the surrounding elements and reserves space for it. This is called static positioning.

The position: relative setting positions the element based on its static position. The element still takes up space as if it were in its static position. On its own, it's almost useless.

The position: absolute setting positions the element based on its containing block. The containing block is a parent element that is not statically positioned. Most of the time, that means you are placing elements in window coordinates.

To get the most out of these settings, you have to use them together. Set the position of a parent div to relative, but don't touch any of its other positioning properties. This will cause the parent to act as if it were statically positioned, but qualify as a containing block. Then you can set the position of child elements to absolute to position them relative to the parent. Yeah, it blew my mind, too.

The right and bottom CSS styles
Here's one I picked up from watching a video on Chris doesn't explicitly call this out, so I had to pause the video to read his CSS.

I usually move elements by setting their X and Y coordinates. To me, X maps to left and Y maps to top. It never occurred to me that an element has right and bottom properties, too.

If you set the right property and not the left, then the right side of the child element will be positioned relative to the right side of the parent. So if you want to right-align an image inside a div, set the div position to relative, the image position to absolute, and the image right to 0. Same thing for the bottom.

The float and clear styles
And finally, here's one from BarelyFitz.

The float style is usually used to wrap text around an image. But web designers have figured out how to use this property for columns. If you float your main content to the left or right, then your side bar will sit nicely next to it. But be sure that the floating element has greater height, or the other elements will wrap around it at the bottom. That's why the main content is usually floating, and not the sidebar.

To put more content after all of the floating elements, set the clear property to both. This could be used to put a footer on a page, but is not as easy as nesting divs. Put the side bar and the content in one div, and the footer in another.

The real solution to creating objects in a managed WMI provider

Wednesday, September 3rd, 2008

This is a case of RTFM. The real solution to the problem of creating an object via WMI is the ManagementCreate attribute. This attribute decorates a static method that takes key parameters (themselves decorated with ManagementName) and returns a new management entity.

The mental block that I was running into was the proxy. I was equating a .NET object with a WMI object. I assumed that creation of a .NET object via "new" was equivalent to the creation of a WMI entity via "path ... create". Not the case.

The .NET objects are proxies for the WMI entities. The are created and destroyed with each request. A call to the create method should cause the enumerate method to include the new entity, as well as return the new proxy object. However, the .NET object returned from the create method will be different from the one returned from the create method. These are merely proxies to the same entity.

Problem solved. Moving on.

Solution to creating a managed MWI provider

Tuesday, September 2nd, 2008

I am attempting to create a Windows Service in C# that exposes management interfaces through WMI. I'm having trouble creating new objects from the WMI command line. See the problem description.

In working through the referenced article, I learned a bit more about managed MWI providers. At the half-way point, you have a working coupled WMI provider written in C#. You should be able to enumerate service objects with the following command:

C:\>wmic /NAMESPACE:\\root\test PATH win32_servicehost get /value

I tried that, and sure enough I get a list of service hosts and the services that they are running. These objects are created in code by the EnumerateServiceHosts method.

My problem requires that I create a new object. I have to allow operations to specify its properties and issue it commands. So I tried do create an instance of a Win32_ServiceHost with an ID not yet in the list:

wmic:root\cli>PATH win32_servicehost create id=821
Create instance of 'win32_servicehost' class (Y/N)?y
Code = 0x80041024
Description = Provider is not capable of the attempted operation
Facility = WMI

Not surprising that this would fail, since the code returns null if the process ID is not found. But if I try to create an object using a process ID already in the list, this is what happens:

wmic:root\cli>PATH win32_servicehost create ID=820
Create instance of 'win32_servicehost' class (Y/N)?y
Code = 0x80041019
Description = Object or property already exists
Facility = WMI

So I changed the example code to allow me to create process hosts with IDs that are not in use. Now every ID I use gives me "Object or property already exists". But if I query for an ID that does not exist, it tells me "No Instance(s) Available".

wmic:root\cli>PATH win32_servicehost create id=820
Create instance of 'win32_servicehost' class (Y/N)?y
Code = 0x80041019
Description = Object or property already exists
Facility = WMI

wmic:root\cli>PATH win32_servicehost create id=821
Create instance of 'win32_servicehost' class (Y/N)?y
Code = 0x80041019
Description = Object or property already exists
Facility = WMI

wmic:root\cli>PATH win32_servicehost where ID=820
ID   Services
820  {"SCardSvr"}

wmic:root\cli>PATH win32_servicehost where ID=821
No Instance(s) Available.

Here's my solution

I think I'm approaching the problem from the wrong angle. Create doesn't mean what I think it means. WMI is set up to access objects that already exist.

Instead of creating instances of objects from WMI, I'm going to change my service so that I can return objects created in code. The operations team can issue commands to these existing objects to cause new objects to be created -- in code. Based on what works in the example, this should solve the problem. I'll post when it's working.