Monday, April 21, 2008

Enumerating XML nodes

I just submitted an update to OmniXmlUtils.pas - a helper library for the Delphi implementation of the XML DOM model, the OmniXML. It allows you to walk over child nodes with a simple enumerator (but you already saw that coming, huh?).

In OmniXML (and in MS XML on which the OmniXML interface is based), you access child nodes via IXMLNodeList interface. Actually, when you access any subset of nodes (for example, when you call SelectNodes and pass it an XPath expression), you are using IXMLNodeList. More and more I was using it, more I hated its stupid interface.

  IXMLCustomList = interface
function GetLength: Integer;
function GetItem(const Index: Integer): IXMLNode;
property Item[const Index: Integer]: IXMLNode read GetItem;
property Length: Integer read GetLength;

IXMLNodeList = interface(IXMLCustomList)
procedure Reset;
function NextNode: IXMLNode;
[I removed declarations of all functions that are not used when walking over the list.]

Basically, I have two options with the current design. I can use a standard for loop using Length and Item[] or I can use NextNode and while loop.

Or, of course, I can write an enumerator - and that's what I did. XMLEnumNodes takes an IXMLNodeList and wraps it in an enumerator. Even better - it takes an xml node or document and an XPath expression and runs SelectNodes automatically for me so I can write code like this:

for nodePassword in XMLEnumNodes(xmlConfig, '//*/PasswordHash') do
SetTextChild(nodePassword, '(removed)');

Now that's what I call a nice code!

If you can't wait for tomorrow update to the OmniXML daily snapshot, you can download OmniXMLUtils 1.25 here.

Tuesday, April 01, 2008

TDM Rerun #7: File Sharing on Linux

In the Windows world we are used to file locking. It is something natural, something that permeates the operating system, something that we had to learn when we stopped using DOS. But for all practical purposes, Linux is Unix, and Unix was designed with different things in mind, one of which was openness and sharing. From the very old days, Unix has supported different kinds of file systems, including those that span a network. Remember, that was well before Windows, and file locking was something that was simply too expensive (in terms of time and network traffic) to be implemented. And that is why there is no locking on Linux.

- File Sharing on Linux, The Delphi Magazine 84, August 2002

The year was 2002, Kylix was still alive and I was planning to write some software for the new platform. Sadly, that never happened - other (Windows) projects were more important and before I came back to Kylix, it was more or less dead.

GpLinuxFileSync testerStill, this short excursion was responsible for my only Linux article. I took my  GpFileSync unit from TDB 68: Let's Cooperate and tried to adapt it to Linux. As it turned out, this was nearly an impossible mission. The ideas behind Unix file systems almost totally prevent its abuse in such direction. To make myself clear - it is certainly possible to use file system for locking, but there are big problems where you want to a) make the lock disappear if the program terminates abnormally, b) put the lock file on a networked location (NFS) or c) all of the above.

I ended with three less than perfect solutions. First used a simple lock file, second was an adaptation of the first that worked with the NFS 2 volums (both were not able to auto-delete the file-mutex on program termination) and third used fcntl() call (auto-delete worked well, but NFS was not fully supported). As far as I know, none of them was ever tested in a real-world application.

Links: article (PDF, 125 KB), source code (ZIP, 16 KB), current GpFileSync unit