A Generic API for controlling software components

Joe Armstrong <>
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