/******************************************************************************
*                                                                             *
*  TakTuk, a middleware for adaptive large scale parallel remote executions   *
*  deployment. Perl implementation, copyright(C) 2006 Guillaume Huard.        *
*                                                                             *
*  This program is free software; you can redistribute it and/or modify       *
*  it under the terms of the GNU General Public License as published by       *
*  the Free Software Foundation; either version 2 of the License, or          *
*  (at your option) any later version.                                        *
*                                                                             *
*  This program is distributed in the hope that it will be useful,            *
*  but WITHOUT ANY WARRANTY; without even the implied warranty of             *
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
*  GNU General Public License for more details.                               *
*                                                                             *
*  You should have received a copy of the GNU General Public License          *
*  along with this program; if not, write to the Free Software                *
*  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA *
*                                                                             *
*  Contact: Guillaume.Huard@imag.fr                                           *
*           ENSIMAG - Laboratoire ID                                          *
*           51 avenue Jean Kuntzmann                                          *
*           38330 Montbonnot Saint Martin                                     *
*                                                                             *
******************************************************************************/

#ifndef __TAKTUK__
#define __TAKTUK__
#include <sys/types.h>
#include <sys/uio.h>

#define TAKTUK_ESWRIT 1
#define TAKTUK_EFCLSD 2
#define TAKTUK_ESREAD 3
#define TAKTUK_EARGTO 4
#define TAKTUK_EARGBD 5
#define TAKTUK_ETMOUT 6
#define TAKTUK_EINVST 7
#define TAKTUK_EINVAL 8
#define TAKTUK_ENOERR 9
#define TAKTUK_EALLOC 10
#define TAKTUK_EIBUFF 11
#define TAKTUK_ENOCON 12
#define TAKTUK_EMTXNM 13
#define TAKTUK_EMTXAG 14

#define TAKTUK_EINTMX 15
#define TAKTUK_EINTGD 16
#define TAKTUK_EINTFV 17
#define TAKTUK_EINTRM 18
#define TAKTUK_EINTIV 19
#define TAKTUK_EINTGM 20

#define TAKTUK_EMAXCD 21

#define TAKTUK_READ_SIZE 8192
#define TAKTUK_WRITE_SIZE 8192

#define TAKTUK_TIMEOUT 'O'
#define TAKTUK_WAIT_MESSAGE 'W'
#define TAKTUK_MESSAGE 'm'
#define TAKTUK_SEND_TO 't'
#define TAKTUK_GET_INFO 'g'
#define TAKTUK_INVALID 'H'
#define TAKTUK_INFO 'I'

/** Taktuk error message
    taktuk_error_msg() function looks up the error message string corresponding
    to an error number as described in taktukcomm man page (see taktukcomm(3)).
    If the error number is not recognized, this function returns the string
    "Unknown error".
    \param msg_code the error number
    \return the error message string
    \see taktukcomm(3)
*/
const char *taktuk_error_msg(int msg_code);

/* All the following routines return 0 on success and a TakTuk error code on
 * failure. Their detailed description can be found in the man of
 * taktukcomm(3) */

/** Initialize the TakTuk C-interface if threads are used 
    taktuk_init_threads() attemps to initialize the C-interface of TakTuk to
    make its use thread-safe.
    0 is returned upon successful completion, a taktuk error code otherwise.
    \return 0 upon success, an error code otherwise
    \see taktuk_error_msg
    \see taktukcomm(3)
*/
int taktuk_init_threads();

/** Finalize the TakTuk C-interface if threads are used 
    taktuk_leave_threads() attemps to release resources used by the C-interface
    of TakTuk after a call to taktuk_init_threads().
    0 is returned upon successful completion, a taktuk error code otherwise.
    \return 0 upon success, an error code otherwise
    \see taktuk_error_msg
    \see taktuk_init_threads
    \see taktukcomm(3)
*/
int taktuk_leave_threads();

/** Gets TakTuk information
    taktuk_get() attemps to get from the TakTuk engine some global information.
    The name of the global information required is given as 'field' parameter
    (supported fields are "rank" and "count") and the result is returned in
    'result' parameter.
    0 is returned upon successful completion, a taktuk error code otherwise.
    \param field the name of the required information
    \param result the address at which the result should be stored
    \return 0 upon success, an error code otherwise
    \see taktuk_error_msg
    \see taktukcomm(3)
*/
int taktuk_get(char *field, long *result);

/** Send message
    taktuk_multi_send(), taktuk_multi_sendv(), taktuk_send(), and
    taktuk_sendv() are used to transmit a message to other distant
    process(es) spawed by TakTuk.
    'dest' contains either a set of destination peers (multi_send functions
    which perform multicast sends, see taktuk(1)) or a single destination peer
    (send functions). Destination are designated by their TakTuk logical rank.
    
    taktuk_multi_send() taktuk_send() attempts to write 'length' bytes 
    of data to the destination(s) from the buffer pointed to by 'buffer'.
    taktuk_multi_sendv(), taktuk_sendv() performs the same action, but gathers
    the output data from the iovcnt buffers specified by the members of the iov
    array: iov[0], iov[1], ..., iov[iovcnt-1].

    0 is returned upon successful completion, a taktuk error code otherwise.
    \param dest the TakTuk rank(s) of the peer process(es)
    \param buffer the message to be sent
    \param length the length in bytes of the message
    \param iov the array of iovector entries of the message
    \param iovcnt the size of the array iov
    \return 0 upon success, an error code otherwise
    \see taktuk(1)
    \see taktuk_error_msg
    \see taktukcomm(3)
*/
int taktuk_multi_send(const char *dest, const void *buffer, size_t length);
int taktuk_multi_sendv(const char *dest, const struct iovec *iov, int iovcnt);
int taktuk_send(long dest, const void *buffer, size_t length);
int taktuk_sendv(long dest, const struct iovec *iov, int iovcnt);

/** Receive message
    taktuk_recv(), taktuk_recvv(), taktuk_wait_message(), taktuk_read () and
    taktuk_readv() are used to receive a message sent by a distant process
    spawned by TakTuk.

    taktuk_recv() and taktuk_recvv() perform a blocking attempt to receive a
    message. Upon success, the TakTuk rank of the sending process is placed at
    the address pointed to by 'from' and the content of the message is either
    placed at the address pointed to by 'buffer' (and 'length' must exactly
    match the message size) or placed into the 'iovcnt' buffers specified by
    the members of the iov array: iov[0], iov[1], ..., iov[iovcnt-1] (and in
    this case the total length of these buffer must exactly match the message
    length).

    If the given timeout is not nul and expires or in any other case of error,
    a positive number is returned and the content of buffer is undefined.

    taktuk_wait_message(), taktuk_read () and taktuk_readv() are lower level
    functions performing the same task. taktuk_recv() and taktuk_recvv() are
    respectively equivalent to a call to taktuk_wait_message(), some error
    checking tests and a call to either taktuk_read() or taktuk_readv().

    \param from the address where to place the TakTuk rank of the sender
    \param buffer the address at which the message should be placed
    \param length the length in bytes of the message
    \param iov the array of iovector entries for the reception
    \param iovcnt the size of the array iov
    \return 0 upon success, an error code otherwise
    \see taktuk_error_msg
    \see taktukcomm(3)
*/
int taktuk_recv(long *from, void *buffer, size_t *length, int timeout);
int taktuk_recvv(long *from, const struct iovec *iov, int iovcnt, int timeout);
int taktuk_wait_message(long *from, size_t *size, int timeout);
int taktuk_read ( void *buffer, size_t length );
int taktuk_readv( const struct iovec *iov, int iovcnt );
#endif
