Cook Computing

« December 2002 »

.NET and 64-bit Windows

Someone pointed me to the following page today: Features unavailable on 64-bit versions of the Windows .NET Server 2003 family. I was surprised to discover that .NET is not supported on the 64-bit version. Some research uncovered this reply from Microsoftie Larry Sullivan here:

The 64bit .Net Framework is under development for release in a future version. The IL is not changed to support 64bit and your managed applications in most instances will run as native 64bit processes. There are some constructs to watch for that can cause some cross platform bugs. These include explicit layout of structures, PInvoke and COM Interop to dll's or COM components where no 64bit equivilent exists. When doing PInvoke use IntPtr instead of int for HANDLES and pointers. Thats the set of issues where you can get into trouble otherwise managed code runs unchanged.

A surprising omission from something called .NET Server.

Posted by Charles Cook at 05:15 PM. Permalink. View Comments.

Encoding in XML-RPC.NET

I'm adding the following to question 6.1 of the XML-RPC.NET FAQ:

When sending a request it is possible to specify the encoding by setting the XmlEncoding property of the proxy class. For example:

SumAndDiffProxy proxy = new SumAndDiffProxy();
proxy.XmlEncoding = new System.Text.ASCIIEncoding();
SumAndDiffValue ret = proxy.SumAndDifference(2, 3); 

Refer to the .NET Framework documentation for the encodings that are supported.

Posted by Charles Cook at 03:26 PM. Permalink. View Comments.

More Mono

Having failed to port XML-RPC.NET to run on Mono, I attempted the same with my IndexedBtree class. I built and ran some performance test code which compares IndexedBtree with the .NET classes Hashtable and SortedList. IndexedBtree ran successfully but enumerating SortedList failed with an InvalidCastException being thrown when the object returned from IEnumerator.Current is unboxed to an instance of DictionaryEntry. The same problem occurred on both Linux and Windows which is at least what you would expect for self-contained code.

I made a quick search for a debugger to do some more testing on Linux but all I could find was mention on the Mono homepage of a debugger under development (screenshot).

And I also did some XML-RPC.NET work today, fixing a couple of bugs reported by Drew Marsh and Dmitry Jemerov.

Posted by Charles Cook at 07:18 PM. Permalink. View Comments.

Mono and XML-RPC.NET (2)

I spent a little more time today trying to build and run XML-RPC.NET using Mono. It was frustrating. There seem to be some major shortcomings in the implementation of HttpWebRequest, at least on the Windows 0.17 build. In particular, setting the Proxy property is ignored (as is it setting it globally using GlobalProxySelection), closing the request stream before calling GetResponse causes Mono to crash, and Content-Length handling appears to be broken when handling the HTTP response.

Once I get the imminent XML-RPC.NET release out I may look into this, the first step being to install Mono on Linux and check whether the same problems occur.

UPDATE: In fact I already had RedHat 7.2 running in a VMWARE image and it only took a couple of minutes to install the necessary RPMs for Mono. I coded a test program with the XML-RPC request hard-coded in a string and cofirmed that the same problems occur (although with different behavior when Close is called on the request stream).

Posted by Charles Cook at 05:42 PM. Permalink. View Comments.

Mono and XML-RPC.NET (1)

I should be working on a new release of XML-RPC.NET - Drew Marsh recently reported a couple of bugs - but there are some new features which need documenting and with the pre-Christmas torpor I've descended into, brought on by too much eating and relaxing, I find I'm prevaricating. I got sidetracked today into installing Mono on Windows XP and and trying to build XML-RPC.NET. I managed to build the assembly with just one change but got the following error at runtime when running a simple client:

C:\Temp\XmlRpc>mono testc.exe

** (testc.exe:1016): WARNING **: Could not load class from token 0x01000001 in testc.exe

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

So I have some work to do to find out what is causing this and possibly a chance to contribute something to the Mono project. The problem is probably in the System.Web.Services.Protocols namespace because I assume the networking and XML classes are fully implemented by now.

Posted by Charles Cook at 06:06 PM. Permalink. View Comments.

Outlook Web Access and WebDAV

I was experimenting with Outlook Web Access (OWA) and ProxyTrace yesterday after I read that OWA uses the WebDAV protocol. The first thought that came to mind was that there must be some pretty impressive JavaScript to make this possible and, sure enough, I found eight .js files in the IE cache with a total size of 181KB.

ProxyTrace reveals heavy use of the SEARCH WebDAV method. This is still at the draft stage and is used here to specify a range and ordering for the multistatus response from the server. A standard PROPFIND request would not work very well for displaying items in the Inbox. For example if the Inbox contains 5000 items and you only want to display the first 50 in most recent first order.

The request body for retrieving list of folders and associated properties is as follows (yes, it is invalid XML):

<searchrequest xmlns="DAV:">
 <sql> Select 
  "DAV:displayname",
  "DAV:href",
  "http://schemas.microsoft.com/exchange/content-href",
  "DAV:hassubs",
 "urn:schemas:httpmail:unreadcount",
 "DAV:contentclass",
 "http://schemas.microsoft.com/exchange/smallicon" 
 FROM Scope('HIERARCHICAL TRAVERSAL OF ""') 
 WHERE "DAV:ishidden" = false
 </>
</>

The contents of the inbox are retrieved with a slightly more complex request. Note the use of the range element to restrict the number of entries in the DAV multistatus response:

<searchrequest xmlns="DAV:">
 <sql>SELECT  
  "http://schemas.microsoft.com/exchange/x-priority-long" as prop1,
  "http://schemas.microsoft.com/exchange/smallicon" as prop2,
  "http://schemas.microsoft.com/mapi/proptag/x10900003" as prop3,
  "urn:schemas:httpmail:hasattachment" as prop4,
  "http://schemas.microsoft.com/mapi/sent_representing_name" as prop5, 
  "http://schemas.microsoft.com/mapi/subject" as prop6,
  "urn:schemas:httpmail:datereceived" as prop7,
  "http://schemas.microsoft.com/mapi/proptag/x0e080003" as prop8,
  "urn:schemas:httpmail:read" as read,
  "http://schemas.microsoft.com/exchange/outlookmessageclass" as messageclass,
  "DAV:href" as davhref
  FROM Scope('SHALLOW TRAVERSAL OF ""')
  WHERE "http://schemas.microsoft.com/mapi/proptag/0x67aa000b" = false 
   AND "DAV:isfolder" = false
  ORDER BY 
  "http://schemas.microsoft.com/mapi/proptag/x10900003" ASC,
  "urn:schemas:httpmail:datereceived"  DESC 
 </sql>
 <range type="row">0-24</range>
</searchrequest>

I was interested in determining whether performance using WebDAV is better than MAPI so I implemented a test with my .NET WebDAV library. WebDAV calls turned out to be significantly slower but this was maybe because the connection was being closed after each call and the NTLM authentication process was being repeated each time. I need to look into this further.

This article provides some information on OWA and WebDAV.

Posted by Charles Cook at 09:02 AM. Permalink. View Comments.

Natural Keyboard

David McCusker writes that he has bought a Microsoft Natural Keyboard to alleviate the problems with his hands and wrists. I've been using the type of keyboard at home and work for several months now as a precautionary measure and find them very comfortable to use. Perhaps more relevant to David's problem, my wife used to do a lot of typing at work (the real thing at around 70 wpm) and suffered RSI-type problems. She finds the Natural keyboard much easer on her hands. If she does much typing on a traditional keyboard her hands start playing up again.

Oh, I forgot to mention, you have to learn to touch type. The two or three fingered pecking skills you have developed over many years don't work on this layout.

Posted by Charles Cook at 08:23 AM. Permalink. View Comments.

DCOM String Bindings in Windows 2000

I've been investigating some DCOM problems on a multi-homed server system and it appears that in Windows 2000 the DUALSTRINGARRAY part of an object reference always begins with the domain host name of the server, followed by one or more IP addresses (more than one if the server is multi-homed). For example:

0x7 reeves.shooting.com
0x7 64.124.140.181
0x7 192.168.7.12

where the first address is the name of the server, the second address is that of the public NIC and the third is the address of the private NIC.

This causes problems on the system in question because the server is in a different Windows domain to the clients and the clients have no way of resolving the private host name of the server (the DNS servers could be configured to fix this but we have to assume a worst case scenario where the customer doesn't want to do this).

On Windows 98, NT4 and pre-SP3 Windows 2000 clients this results in a long delay connecting because the OXID resolver on the client processes the bindings sequentially: typically 15 to 20 seconds as the client unsuccessfully tries to use the first binding before connecting without any further delay using the second binding.

I must be missing something here because I don't understand why the host name binding is supplied. The IP address is also supplied so what extra benefit does the name provide? Without the name binding the client would connect without delay to the server and we wouldn't have a problem. Possibly because the IP address of the server might change during the lifetime of an object?

From SP3 onwards of Windows 2000 the problem does not exist anymore because the client's OXID resolver attempts concurrent calls on all the bindings. But unfortunately there are still a lot of people out there with Windows 98 and NT client machines.

Posted by Charles Cook at 05:30 PM. Permalink. View Comments.

IndexedBtree Tests

I coded some very unscientific performance tests for the IndexedBtree class last night. Of course Hashtable wins - unless you need access by numerical index. SortedList provides the numeric indexed access but is much slower on random adds and deletes. The new class IndexedBtree is somewhere in-between, but does give you numerical indexing which could be important in some applications.

I've thought about implementing a skip-list class but I think a blob btree as described by David McCusker has more scope for being used in interesting ways, particularly if the implementation can be used for both in-memory and on-disk blobs.

The test adds 100,000 pseudo-random entries, performs the various operations for each entry, and then removes them pseudo-randomly. All times in msecs.

test: Hashtable  Add:        220  Enumerate:  121  Item:       60  GetByIndex: n/a  Remove:     130
test: SortedList  Add:        92142  Enumerate:  511  Item:       40  GetByIndex: 30  Remove:     96699
test: IndexedBtree  Add:        1502  Enumerate:  651  Item:       70  GetByIndex: 441  Remove:     1472
Posted by Charles Cook at 08:18 AM. Permalink. View Comments.

Early Optimization

David McCusker writes about his preference for early optimization on the OSAF dev list. As I wrote here a while ago, this is also my preference. The pitfall in delaying optimization is that once you have implemented some software there is not necessarily a direct path to an optimized version. Typically a re-design or at least a significant amount of backtracking is required.

Sometimes it is obvious how optimization can be applied later on, in which case an unoptimized implementation can be traded off in the short term against delivering something more quickly, but it is always risky to assume that once something has been developed optimization will only require localised changes to the code. As for the point of view that significant bottlenecks can only be determined after implementation, I'd say the ability to foresee issues like this is why experienced developers are paid more (or should be paid more).

In the same posting he goes on to discuss performance of btrees. My IndexedBtree class both stores keys in inner nodes and rebalances on deletion when required. The performance advantage of the former is obvious, that of the latter not so clear one way or the other.

Posted by Charles Cook at 12:47 PM. Permalink. View Comments.

COM Was Love

Inside OLE 2

Clemens Vasters gets nostalgic about COM. I too remember the excitement. Unlike the launch of .NET where we have all been submerged by countless books and articles, Kraig Brocksmidt's Inside OLE was about all we had to work with. Unfortunately the underlying simplicity of COM was hidden by the emphasis on OLE and people would say things like "Its takes 6 months before you understand OLE and can do anything useful with it". I recall being particularly enthusiastic about monikers, which seemed an all-powerful concept, although in the end I never did much with them.

My first misgivings about COM arose when I discovered that it was not possible to configure timeouts in DCOM. This was particularly harmful to a design I worked on which used a client-side broker to locate COM objects from one of multiple servers: we couldn't expect end-users to wait a couple of minutes while a request to a non-running server timed out. I spent a lot of time devising a proprietary solution which did not involve spinning off multiple threads. This problem was made even more frustrating because Microsoft did not seem willing to understand the importance of timeouts in client software, not just in DCOM, for example Outlook until recent versions used to hang for a very long time and often fail to recover if the network connection went down.

The final blow to my relationship with COM was Windows 2000. DCOM had become quite usable under NT and then it all fell to pieces. I guess all the good engineers were already working on .NET and Microsoft used some interns to port DCOM to Windows 2000. Several service packs later the damage is just about repaired but it caused us a lot of extra work and hassle with customers.

Posted by Charles Cook at 08:13 AM. Permalink. View Comments.