|
|
|
Documentation
Installation
The simplest way to install DCCL on your system is as follows:
- tar xzf libdccl-version.tar.gz (untar the source package)
- cd libdccl-version
- ./configure
- make
- make install (as root)
This will compile the sources and will install the libraries and header files
into the standard directories. You can also use the --prefix=dir option
to specify another installation directory (e.g. --prefix=/tmp/dccl will install
the header files into /tmp/dccl/include and the libraries into /tmp/dcl/lib).
Compiling your programs
If your programs are using DCCL and you did set a non standard directory during
the configure process you have to tell the compiler where to look for
the header files and the library. For gcc the directory for the header files is set
with the option "-Idirectory". If you want to link your programs against the
shared version of DCCL you have add "-Ldirectory -ldccl" to the compiler flags.
If you want to use the static version just add "directory/libdccl.a" when
linking your program.
For example, if you have installed DCCL into /tmp/dccl than you can compile your sources as
follows:
g++ -I/tmp/dccl/include -L/tmp/dccl/lib -ldccl main.cc -o main (shared)
or
g++ -I/tmp/dccl/include /tmp/dccl/libdccl.a main.cc -o main (static)
Writing a master
Writing a master is quiet easy and the basic steps will be demonstrated by the following example.
1 #include "master.hh"
2 #include "client.hh"
3 #include <iostream>
4 #include <vector>
5 #define CMD_PORT 17200
6 #define HTTP_PORT 17280
7 bool _quit = false;
8 class mymaster : public master
9 {
10 public:
11 mymaster() : master( CMD_PORT, HTTP_PORT ) {
12 }
13 virtual void result( int jobid, int status, void* buf, int len ) {
14 std::cout << "got result for " << jobid << " " << status << " " << len << std::endl;
15 // do something with the result
16 // when being in this method further incoming results are accepted and will be scheduled
17 // until the method is left
18 free( buf );
19 _quit = true;
20 }
21 };
22 int main( int argc, char** argv )
23 {
24 mymaster* m = new mymaster();
25 std::vector< client* > v;
26 while( v.empty() ) { // wait for at least one slave to become available
27 sleep( 1 );
28 m->get_clients( v );
29 }
30 char* s = "hello slave\n";
31 // use the first slave to add the job with jobid 23
32 if( m->add_job( v[ 0 ], s, strlen( s ) + 1, 23 ) ) {
33 std::cout << "waiting for result..." << std::endl;
34 while( ! _quit ) sleep( 1 );
35 } else {
36 std::cerr << "could not add job" << std::endl;
37 }
38 }
As shown in this example to write a master process first you have write a class that is
derived from the class master and which implements the abstract method
result. This is done in line 8 to 21. The method result is called
whenever a result for a job has been received or
when an error has been occurred for some job. The status can either be OK or
ERR. The result is stored in buf and the length of the result is given
by len. On error buf is set to NULL. The constructor of
master is given the ports where to listen for pings and results and for http
connections. The default is 17200 for pings and results and 17280 for http connections.
To get a list of slaves the master provides the method get_clients which returns
a vector of pointers to slaves. This vector can be used to find a slave that fits to a
jobs. The class client provides the following methods.
| Return type | Method | Description |
| u_int64_t | ram() | Returns the size of the RAM in bytes. |
| double | bogo() | Returns the number of bogomips of one CPU. |
| double | load() | Returns the last reported load. |
| time_t | lastping() | Returns the timestamp of the last received ping. |
If an appropriate slave has been found a job can be added to that client by using the
master's method add_job which is given the client pointer as first argument,
the data of the job as second argument, the size of the data as third argument and an
jobid as fourth argument. If the job has been successfully sent to the slave true
is returned, otherwise false.
Writing a slave
Writing a slave is as easy as writing a master and the basic steps will be demonstrated by the
following example.
1 #include "slave.hh"
2 #include "slaveworkerthread.hh"
3 #include <iostream>
4 class myworker : public slaveworkerthread
5 {
6 public:
7 myworker() {
8 }
9 virtual char* exec( int& len ) {
10 std::cout << "got job" << std::endl;
11 std::cout << siz() << std::endl << buf() << std::endl;
12 len = 13;
13 return strdup( "hello master" );
14 }
15 };
16 class myslave : public slave
17 {
18 public:
19 myslave() : slave( "localhost" ) {
20 }
21 virtual slaveworkerthread* data() {
22 return (slaveworkerthread*) new myworker();
23 }
24 };
25 int main( int argc, char** argv )
26 {
27 myslave* s = new myslave();
28 while( true ) {
29 sleep( 1 );
30 }
31 }
To write a slave at least two classes have to be written which are derived from
the abstract classes slaveworkerthread which is responsible for executing
a job and slave which receives a job, creates a worker thread, executes
this thread and sends the result to the master.
The constructor of slave is given the address of the master as first
argument and optionally the port of the master as second argument. The default value
for the port is set to 17200. The slave's port can be given as third argument
(default: 17201) and the ping interval in seconds as fourth argument (default: 5s).
The abstract method data of slave is called whenever a new job
has been received. It must resturn an instance of slaveworkerthread which
implements the abstract method exec and executes the jobs. Each derived class
of slaveworkerthread inherits the method buf() which returns a
character pointer to the data of the received job and the method siz() which
returns the size of the data. The result must be returned as a character pointer and
the size of the data must be written to len.
|