Small code cleanups.

Moved some server initialisation code into separate methods to
allow connections to be established with other machines part of
the server group.
Added tracking of machine_id, machine_ip and machine_port used
to uniquely identify machines that are part of the distributed
system.
Added main_init method to core server API.
Added basic concurrency primitives.

Mutex - a C++ wrapper around pthread mutexes.
Lock - a scope-level lock.
    Uses C++ stack unwinding to ensure that locks do not
    remain acquired upon exiting the scope.
    Usage example:
    ... lockless method code ...
    {
         Lock lock(mutex);
         ... do stuff ...
         if (premature_exit) {
             return FAILURE;
             (lock is released by destructor)
         }
         ...
         return SUCCESS;
         (lock is released by destructor
     }
     ... lockless method code ...
Abstractions for managing key spaces within a server layer.

Only initial implementation.

Each server layer has a space of keys used to uniquely identify singular
entities. For example, the directory layer identifies directories via
SHA1 hashes, while the file and data layers identify file metadata and
data chunks via 64-bit unique IDs. Within a layer, regions of the hash
space are distributed across multiple machines such that certain regions
are stored (replicated) on a set of machines and are served by a single
primary machine.

AssocKeySpace offers a compact data structure allowing one to update values
uniformly across one segment of the key space (for example, in order to
say that machine i stores keys within the interval l and r,
AssocKeySpace would associate the interval l, r with the value i).
The implementation is generic allowing keys to be any subclass of Hash
(currently only SHA1Hash and UInt64Hash) and values to be anything.

ServerHost maintains information about machines that are part of the
distributed system, such as their unique ID and (IP, port) tuple, their
server layer (directory / file / data), the regions of the key space
which they store and which they serve as well as active connections if
needed.

On top of both of these, ServerGroup maintains information about an
entire group of machines (either the directory layer group, the file
layer group or the data layer group).

Correctness of implementation tested in main program upon server
initialisation (should move into separate test program).
Serialisation support for server system state.

- Can read and write instances of Hash subclasses, AssocKeySpace,
  ServerHost and ServerGroup to file descriptors.
- Reworked server initialisation. The server layer, the directory
  in which persistent data is to be store and the binding ip and
  port are now passed in as arguments. The server persists its
  state and that of the system under that directory and rereads
  the state upon booting.
- Reorganised some internal data structures to allow previous
  reworking.
- Made all layers use UInt64Hash key spaces for consistency and
  simplicity. For the directory layer, while directories will
  still be addressed by the full 160-bits of the SHA1 hash,
  partitioning of data will only be done by the first 64-bits.
  This will allow for better performance while simplifying
  implementation effort when having to rebalance data across
  machines.
- ServerGroups are now parameterised by the ServerHost type
  instead of the key type.