A load balancer written in DALIS

I mentioned to a friend of mine that I wanted to slap together a quick load balancer to demonstrate that DALIS programs can bounce between different servers without the need for any shared state. Being able to do that was my original aim for writing a cloud based language, and a demo showing DALIS in action would be nice to have. Of course, I had intended to simply extend my C# webserver example and make a simple load-balancer out of that. But my friend happened to say “why don’t you write the load balancer in DALIS?”. Damn him, putting ideas in my head like that. Still I got my own back when I showed him the Esoteric Programming Languages site and he spent way too much time reading it :-) So ... here is my (very simple) load balancer written in DALIS:

TRANSPARENT
IF ISASSIGNED("arg0")
   IF (RANDOM >= 0.5)
      newUrl = REPLACE arg0, "DALIS", "DALIS1"
   OTHERWISE
      newUrl = REPLACE arg0, "DALIS", "DALIS2"
   END
   IF ISASSIGNED("arg1")
      newUrl = REPLACE newUrl, "balance", arg1
   END
   IF RAWCONTENT = ""
      WRITE WEBGET newUrl
   OTHERWISE
      WRITE WEBPOST newUrl, RAWCONTENT
   END
END

I had to add a few new things to the language to make this work (it is great when you’re the boss of the programming language and you can add whatever you like):

  • RANDOM – generate a pseudo random number between 0.0 and 1.0
  • RAWCONTENT – allows your program to access the data in the raw http request
  • TRANSPARENT – tells DALIS that you don’t want it to add anything to the output
  • WEBPOST – does an http POST with the data you specify
  • REPLACE – replace a value in some text with some new value

Anyway, this seems to work a treat, it means that you can run 3 separate DALIS servers (called DALIS, DALIS1 and DALIS2 in this example), one being the load-balancer, along with two others. You can then run a DALIS program via the load-balancer and it will route it randomly to one of the other two DALIS servers. Using the TRANSPARENT keyword in the load-balancer code is critical, since it allows stuff to simply pass through without any interference.

The trouble is, I’m actually starting to enjoy programming in DALIS now. What have I done?

A simple DALIS server

A while back I wrote a simple web server and said that I could turn it into a DALIS server that would run outside of IIS. Well that's exactly what I did, take a look at this YouTube clip I've made:

In this clip I'm showing two instances of the same program running (one in IE the other in Chrome). Each program shows a kindof bouncing ball thingy in ASCII Art. This is not the kind of thing that I designed DALIS to do of course, but who cares. In the background you can see the DALIS server runnng as a console app. I've made it so that each thread servicing a web request shows up like a blinking light. This means you can see it is working - and you can tell that I still like blinking LEDs on things. Ahh, do you remember the days when you used to see blinky LEDs on the front of your modem? Good times, eh?

So anyway... whilst I have not said much about the DALIS progaming language recently, development has continued on background threads :-) I have added a few more features to the language. I have also tried to think of a better name for it, but DALIS has kinda stuck now. One day I might have the guts to tell everyone what DALIS stands for, or maybe not.

Best Station Announcement Ever

Moorgate Underground

My wife and I happened to be passing through Moorgate Underground station (in London) last night.  Just before we walked out of the exit we heard the best station tannoy announcement ever. I have tried to record it as accurately as possible, it went like this (imagine a total deadpan voice):

“Passengers are reminded not to excrete their body fluids at any place within this station, this is because this is … … … erm, disgusting”.

You had to be there I guess, but we laughed all the way home.

Retro CDs

I was looking for some writable CDs, for making up music CDs, since I'd run out. By accident I found these:

Retro style CD

...how awesome are they? Now I know they exist, I might buy some more from Amazon. Sometimes you find something new when you support a small independant retailer. I bought mine from a small store in the village of Linton, near Cambridge. If you ever find youself near Linton, pop into Tournants (in the High Street) and have a look round their interesting collection of computer bits and electrical supplies. It's good to have shops like this.

 

Simple C# Web Server

During my lunchbreak the other day I wondered how hard it would be to write a simple webserver in C#. Surely with all the toys in the .net framework these days it should be pretty easy? So I decided to give it a go and see what happens. The aim was to write a simple class that recieves a delegate to a method which is responsible for the page content, everything else could be taken care of by the class I'm writing. That way the server can serve whatever page(s) you like, but you just need to write a simple method that returns a string with some html in it. Of course, with this approach the HttpListener is our friend and does much of the hard stuff. Here it is in action running on my Iconia tablet:

The webserver running

It took me about 30 minutes to get it working. After taking the code home and tidying it up a bit, this is what now I have:

using System;
using System.Net;
using System.Threading;
using System.Linq;
using System.Text;
 
namespace SimpleWebServer
{
    public class WebServer
    {
        private readonly HttpListener _listener = new HttpListener();
        private readonly Func<HttpListenerRequeststring> _responderMethod;
 
        public WebServer(string[] prefixes, Func<HttpListenerRequeststring> method)
        {
            if (!HttpListener.IsSupported)
                throw new NotSupportedException(
                    "Needs Windows XP SP2, Server 2003 or later.");
 
            // URI prefixes are required, for example 
            // "http://localhost:8080/index/".
            if (prefixes == null || prefixes.Length == 0)
                throw new ArgumentException("prefixes");
 
            // A responder method is required
            if (method == null)
                throw new ArgumentException("method");
 
            foreach (string s in prefixes)
                _listener.Prefixes.Add(s);
 
            _responderMethod = method;
            _listener.Start();
        }
 
        public WebServer(Func<HttpListenerRequeststring> method, params string[] prefixes)
            : this(prefixes, method) { }
 
        public void Run()
        {
            ThreadPool.QueueUserWorkItem((o) =>
            {
                Console.WriteLine("Webserver running...");
                try
                {
                    while (_listener.IsListening)
                    {
                        ThreadPool.QueueUserWorkItem((c) =>
                        {
                            var ctx = c as HttpListenerContext;
                            try
                            {
                                string rstr = _responderMethod(ctx.Request);
                                byte[] buf = Encoding.UTF8.GetBytes(rstr);
                                ctx.Response.ContentLength64 = buf.Length;
                                ctx.Response.OutputStream.Write(buf, 0, buf.Length);
                            }
                            catch { } // suppress any exceptions
                            finally
                            {
                                // always close the stream
                                ctx.Response.OutputStream.Close();
                            }
                        }, _listener.GetContext());
                    }
                }
                catch { } // suppress any exceptions
            });
        }
 
        public void Stop()
        {
            _listener.Stop();
            _listener.Close();
        }
    }
}

All the work is done on background threads, which will be automatically cleaned up when the program quits.  Example use of this code is pretty simple, like this:

class Program
{
    static void Main(string[] args)
    {
        WebServer ws = new WebServer(SendResponse, "http://localhost:8080/test/");
        ws.Run();
        Console.WriteLine("A simple webserver. Press a key to quit.");
        Console.ReadKey();
        ws.Stop();
    }
 
    public static string SendResponse(HttpListenerRequest request)
    {
        return string.Format("<HTML><BODY>My web page.<br>{0}</BODY></HTML>"DateTime.Now);    
    }
}

I'm even considering using this code to build a little DALIS aware test server, so that I can run DALIS programs without hosting anything in IIS... even better I could run a couple of them and bounce DALIS programs between them.


EDIT:This little bit of code has proved quite popular, and recently I have been asked if it has been released under any particular license. Since it was such a small bit of code and just an evolution of the MSDN documentation found here, I didn't really think about a license for it. But I am happy to share this code, so to make the situation clear I'm releasing it under the MIT License.