This section is probably interesting only to those to wants to understand the internals of the program. If you just want to use bongoyo, you can skip this section.
Bongoyo's objective is high availability. And it accomplishes this by running on multiple fail-over servers that can take over the server/service that is to be made highly available. Immediately it follows that bongoyo needs to have a way to know if the HA server/service is down, and needs to have a way to provide the same service if so. Of course, when it comes to implementing the solution, a lot more details comes up that needs to be taken care of that were not first obvious from 10,000 feet. The rest of the section an attempt will be made to try to describe the internals of bongoyo, with the hope that the reader can understand that the program does, and perhaps contribute to it.
Bongoyo is written in perl? Some of the reasons why perl is used are:
Like many programs, bongoyo is designed to be very flexible. Bongoyo's flexibility comes mainly from two main "ingredients":
The task-approach has the advantage of running arbitrary subroutines without having to resort to a huge and ugly loop of while's and if's. For example, the subroutine that checks if the boss is alive is run as one task, the subroutine that checks for the service is run as another tasks, and if there is another service that needs to be checked, it can run as another tasks, when an incoming connection is received, a task is started to collect the message, when an external task needs to be executed, a task is created to run it, etc. It makes the program very, very flexible, however, the trade off is that weird interactions like deadlock and race conditions are more likely.
Once bongoyo has initialized (a few small subroutines), the first thing it runs is the task switcher main_loop. main_loop is pretty much the equivalent of the kernel scheduler, all it does is to run one subroutine (task) after another. Each of the task will either run until it is completed, or it will return control to main_loop and schedule itself to be executed again. Since this is not a full blown kernel with protected memory space between each task and pre-emptive multitasking, things have to be simulated.
Most task will complete in a single run. Some tasks cannot or might not be completed in a single run, i.e., input might block. In situations like this, the task will have to set its task specific data, $s_task, (so that it knows which state it was at when it gets run again) and return control to main_loop. The return value is an integer: if it is less than 0, the task is deleted, otherwise the task is scheduled to run again after as many seconds (1 = 1 s, 2 = 2s, etc., 0 = ASAP), or longer (if there are lots of tasks--there is no guarantee).
To provide for task-specific memory, the $s_task data structure is maintained for each task. It contains stuffs like task subroutine pointer, wake-up time, and pointer to more task specific data.
Aside from the core bits, most of the functionalities of bongoyo are implemented as modules. This allows for easy expansion of the program. There are three main classes of modules:
Basically everything that cannot be modularized are considered to be core bits of bongoyo. There are two classes of core bits:
In a distributed system, there is always the problem of semaphore/locking. There are two obvious approaches: (1) semaphore is contested by all servers for each action and (2) semaphore is contested once and held on forever. Since the second approach seems like a simpler solution, that used in bongoyo. The fail-over server that won the contest is called the boss.
Each fail-over server will run the boss_monitor task at all time. The purpose of this task is to make sure that there is one and only one boss at any time. This includes:
The way the boss selection works is this:
duty_monitor is basically the slave to the boss, and it contains all the stuffs needed to process command from the boss. It gets run by all fail-over servers (including the server that is currently the boss). The functions of this task include:
This task gets run only by the boss. It's function is to make sure that the virtual server is available. It does it by:
In an attempt to be robust (i.e., the design decision was sort of forgotten), the service_monitor keeps track of three states for each of the virtual server:
The combo states consist of three characters, representing the summary of the three states for each virtual server:
Ideally the combo state for a virtual server should be UU1. However, we are dealing with computers after all, so all kinds of weird stuffs can happen. The only time a request for volunteer is sent is when the combo state is DD0.
Page mangling by Edwin Lim.
Wed Sep 6 01:39:53 EDT 2000