Thursday, October 27, 2011

Management Tool For Windows Service

Background
I've created a Windows service that exposes a TCP socket to wireless clients that access it over (right now) WiFi, Edge, and 3G connections. The basic purpose of the service is to collect a user identifier from the client, process certain validations against it, and return the result back to the wireless client. The requirement is that appear to be instantaneous to the end user. That goal has been accomplished. On average, the round trip is under half a second. That appears immediate enough to the end user. There are occasional lags and timeouts, but there's nothing that can be done about that due to the fact that the wireless networks have their own stability issues. If the connection drops, too bad. Some devices hold a backup database which allows a fail over in the event of a server timeout, and this helps to hide the occasional server issue. A client side backup is not an option on all devices.
Problem
The data that the server uses to validate client requests is stored in a cache that lives in the memory space of the Windows service, so there's no easy way to see if the cache is being updated, completely built, missing items, or to look at the state of specific items. There is logging on the server, but there has to be the balance of logging issues and providing diagnostic information that can give details of the current state of the server.
Solution
We could go log file crazy, writing a bunch of various logs that serve different purposes, but that would very quickly get messy. The code would be more complex than necessary, provide additional overhead to the service, and create more potential points of failure in the service. A better option is to create a simple UI client application that the customer can use to ask the service for its current state, so that's what I'm doing.
I've created a WCF service endpoint using named pipes in the Windows service. This service end point exposes a handful of useful methods for gathering information, and running simple tasks against, the cache and processing stored in the Windows service. The UI client can then call methods exposed on the WCF service, and provide data that the customer would like to review. Extending the functionality of the WCF service is simple enough, although it does require a redeployment of the Windows service, and that is not always convenient in a production server.

Friday, October 7, 2011

Forcing Blackberry socket timeout

Maybe if I talk it through I can come up with a better solution because I don't like what I'm doing, but right now, I have nothing better.

Here's the situation.
I've written an application for a Blackberry. This application requires a socket connection to communicate with a remote resource. It works fine, but once in a while I'm told that the application fails to contact the remote server. It throws a connection timeout error, and I'm told that it takes 15 seconds for this to occur. This is not acceptable to the client, and they are requiring that I drive the timeout down to 3 seconds. My research has shown that there is a connection object that will allow me to set a connection timeout, but in order to use this object I have to utilize the BES server. This is not an option, so as far as I can tell, I'm stuck not being able to set a timeout on the connection.

Here's my solution.
I've created a thread object that wraps the process of connecting, sets any exceptions, and sets a boolean variable indicating that the connection attempt is complete. If there's no exception I can assume that a complete connection attempt was successful, and go about my business.
I start the thread.
I then go in to a loop that will loop for 3 seconds or until my boolean variable indicates that my connection is complete. In the loop I sleep for a little bit, and then check again.
I'm not happy with this solution. It feels like there's too much going on with this solution, but I'm just not really sure what else I can do to force the socket to not try to connect for more than 3 seconds.

// something like this.
private static void openConnection(final String url) throws Exception
{
    boolean connecting = true;
    Exception exception = null;

    new Thread()
    {
        public void run()
        {
            try
            {
                _connection = (StreamConnection)Connector.open(url);
            }
            catch(Exception e)
            {
                 _exception = e;
            }
            finally
            {
                 connecting = false;
            }
        }
    }.run();
    long timeout = getTime() + _threadTimeout; // 3000 ms added to the current time
    while(connecting || getTime() < timeout)
    {
        Thread.sleep(50);
    }
    if(null != exception)
    {
        throw exception;
    }
}