A Generic API for controlling software components
Joe Armstrong
erlang@REDACTED
Wed Nov 25 10:56:37 CET 2009
I would like to start a discussion about the generic control
of software components. Let me start by describing the problem
and a possible solution. I'd welcome feedback on this.
What's the problem?
To start with I'll use the term "component" rather than the word
"application" since the word application has specific meaning in the OTP
context.
To me a component is a black-box offering some functionality that I want
to use in my project.
Examples of components are couchDB, mochiweb, rabbitMQ, ejabberd, yaws
etc.
All these different components have chosen Ad Hock ways of controlling
them. The way that I control couchDB and yaws is completely different.
The way I upgrade the code is completely different.
What I would like to do is manage all the components in a uniform manner.
Much of this design is inspired by how Mac OS-X manages applications.
By manage I mean start and stop the component, upgrade the code,
change the behavior of the component at run time and so on.
Here's a suggestion for a set of rules for managed components:
Draft 1 - 25 Nov 2009
Rule1: All components are unpacked into the same top-level
directory (default $HOME/eComponent) and have the extension
.ec (Erlang component)
Example: Imagine I have installed mochiweb ejabberd and couchDB
then after installation I should see the following:
$pwd
/home/joe/eComponents
$ls
mochiweb.ec ejabberd.ec couchDB.ec
Rule2: A normal user should *never* have to examine any of the
files *inside* the component. To do so causes
"abstraction leakage" - I want to consider each of these
components as black boxes. Once installed the component
should be installed in a read-only disk area.
Rule3: The component should not break if relocated to a different
top-level directory. A simple "mv" command should suffice
So no hard-wired paths or links please.
Rule4: All components C must have a file called
$HOME/eComponents/C.ec/Preferences.pl
The extension .pl means the file contains a property
list. Here is an example:
{codePath, "/bin"}.
{expiryDate, {2009,12,24}}.
{icon, "/images/myIcon.png"}
{version,1}
{myKey1, ...}
The keys codePath, version, and expiryDate are obligatory
Why do we need code path? - so that Erlang can find
a module called C.erl
Expiry date has a "time to live for the component"
Version is used for local configuration data (see later)
Version numbers should start at one and be increased by one
for each new release.
Rule5: Local configuration data
Local configuration data must not be stored under the
eComponents directory - (you can't remember we said the
component is in a read-only disk area - see rule2)
Local data for the component C must be stored
in the directory
$HOME/eLibrary/ComponentName/Vsn
Thus local preferences for ejabberd version 1
would be stored in the file
$HOME/eLibrary/ejabberd/1/Preferences.pl
Rule6: Code upgrade
We should upgrade an component C when it's expiry date has
been reached. To update an component we delete the entire
component under $HOME/eComponents/C.ec we install the
new component and run the command: C:install().
Data that is to be carried over between different versions
of the component is stored in $HOME/eLibrary/C/V/...
Rule7: management
All components C must provide a module in the file
C_control.erl - so ejabberd provides ejabberd_control.erl
The management API is as follows:
C:start_link() -> Pid
create a controller process for the component.
Pid has the following protocol [see note 1 for notation]
PL is a property list (list of {Key::atom(), Value::any()}
Pid !! {start, PL} => ok | {error, Why}
Cold start the component. PL is a property
list describing how the component should behave
Pid !! {stop, PL} => ok
Stop the component
Pid !! {modify, PL} => ok | {error, Why}
Change the behavior of the component
Pid !! info => PL
Pid !! {info, [Keys]} => [Values]
Pid !! suspendLocal => ok
Pid !! resumeLocal => ok
Suspend the component data can be written to
$HOME/eLibrary/ComponentName/Vsn/...
Pid !! suspendRemote => <<BinaryClosure>>
Pid !! {resumeRemote, <<BinaryClosure>>} => ok
This ton suspend an component on one machine
and resume it on another
Notes:
[1] Notation
Pid !! M => A | B | C ...
Is my notation for for a remote procedure call
This means if you send Pid the message Pid ! {self(), M}
you will eventually be send one of the messages {Pid,A} or {Pid,B}, ...
/Joe
More information about the erlang-questions
mailing list