/*
 * Client-side Local Resource Manager API.
 *
 * Copyright (C) 2004 Huang Zhen <zhenh@cn.ibm.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library 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
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

/*
 * This is a draft. 
 *
 * By Huang Zhen <zhenh@cn.ibm.com> 2004/2/20
 *
 * It is based on the works of Alan Robertson, Lars Marowsky Bree, Andrew Beekhof.
 * 
 * The Local Resource Manager needs to provide the following functionalities:
 * 1. Provide the information of the resources holding by the node to its 
 *    clients, including listing the resources and their status.
 * 2. Its clients can add new resources to lrm or remove from it.
 * 3. Its clients can ask lrm to operate the resources, including start, 
 *    restart, stop and so on.
 * 4. Provide the information of the lrm itself, including what types of 
 *    resource are supporting by lrm.
 * 5. Notify the clients if they want when the status of a certain resource 
 *    changed.
 * 
 * The typical clients of lrm are crm and lrmadmin.
 */

#ifndef __LRM_API_H
#define __LRM_API_H 1

#include <uuid/uuid.h>
#include <glib.h>

#define	LRM_PROTOCOL_VERSION	0.1

#ifndef NULL
#define NULL ((void*)0)
#endif

/*using the uuid as the id of resource */
typedef	uuid_t	rsc_id_t;

/*define the values of resource type*/
#define RSC_TYPE_LSB		"LSB"
#define RSC_TYPE_HEARTBEAT	"HeartBeat"
#define RSC_TYPE_OCF		"OCF"

/*lrm's client uses this structure to access the resource*/
typedef struct lrm_rsc
{
	rsc_id_t	rsc_id;
	const char*	rsc_name;
	const char*	rsc_type;
	const char*	rsc_parameter;
	struct rsc_ops*	rsc_ops;
}lrm_rsc_t;

/*define the values of op_type*/
#define CLOP_START		"start"
#define CLOP_STOP		"stop"
#define CLOP_STATUS		"status"
#define CLOP_RESTART   	"restart"
#define CLOP_RELOAD		"reload"
#define CLOP_METADATA  	"metadata"
#define CLOP_RTYPENAM  	"rtypename"

#define LRM_MONITOR_SET		0
#define LRM_MONITOR_CHANGE	1
#define LRM_MONITOR_CLEAR	2

struct rsc_ops
{
/*
 *	perform_op:	Performs the operation on the resource.
 *			
 *	op_type:	The type of the operation.
 *
 *	parameter:	Some operations may need parameter.
 *	
 *	timeout:	The timeout of the operation.
 *
 *	return:		All operations will be asynchronous.
 *				The call will return the call id or failed code 
 *				immediately.
 *				The call id will be passed to the callback function
 *				when the operation finished later.
 */
	int	(*perform_op) (lrm_rsc_t*, const char* op_type, int timeout);

/*
 *	is_op_supported:
 *				check if the type of the operation is 
 *				supported by the resource.
 *
 *	op_type:	the type of the operation.
 *
 */
	int	(*is_op_supported) (lrm_rsc_t*, const char * op_type); 

/*
 *	get_metadata:
 *				Returns XML metadata as a (malloced) string.
 *				Performing the CLOP_METADATA operation on 
 *				any resource will do the same thing.
 *				But this function will return immediately.
 *
 */
	char* (*get_metadata) (lrm_rsc_t*);
	
/*
 *	set_monitor:
 *				Add a monitor to a resource.
 *
 *	monitor_mode:
 *				If 'monitor_mode' is LRM_MONITOR_SET, the client's monitor
 *				callback will be called when the status of the resource is set.
 *
 *				If 'monitor_mode' is LRM_MONITOR_CHANGE, the client's monitor 
 *				callback will be called when the status of the resource is 
 *				changed.
 *
 *				If 'monitor_mode' is LRM_MONITOR_CLEAR, the monitors set on
 *				this resource before will be all cleared.
 *
 *	time:		The monitor will check the status every 'time' seconds.
 *
 *	status:		If 'monitor_mode' is set to LRM_MONITOR_SET, 'status' is the 
 *				trigger status.
 *
 *	user_data:	This data will be passed to the callback function.
 *
 * 	return: 	the monitor_id used in the callback function.
 */
	int (*set_monitor) (lrm_rsc_t*, int monitor_mode, int time, int status
	, 					void* user_data);

};

#define CALLBACK_TYPE_OP_DONE		1
#define CALLBACK_TYPE_OP_FAILED		2
#define CALLBACK_TYPE_OP_TIMEOUT	3

/*
 * 	lrm_op_done_callback_t:	
 *				This type of callback functions are called when some
 *				 asynchronous operation is done.
 *
 *	call_id:	call_id is the id returned by the perform_op() before.
 *
 *	rsc_id:		the id of the resource
 *	
 *	rc:			return code of the operation
 *
 *	user_data:	the data set by client in the perform_op call
 *	
 */
typedef void (*lrm_op_done_callback_t)	(int call_id, rsc_id_t rsc_id
,		int rc, void* user_data);


/*
 * 	lrm_monitor_callback_t:	
 *				This type of callback functions are called when the status
 *				of resource changed in a monitored mode.
 *
 *	rsc_id:		the id of the resource
 *	
 *	monitor_id:	return by the set_monitor function.
 *	
 *	user_data:	the data set by client in the set_monitor call			
 */

typedef void (*lrm_monitor_callback_t)	(int call_id, rsc_id_t rsc_id
, 		int callback_type, const char * callback_data, void* user_data);

typedef struct ll_lrm 
{
	void *		lrm_private;
	struct lrm_ops*	lrm_ops;
}ll_lrm_t;

struct lrm_ops 
{
	int		(*signon)  	(ll_lrm_t*, const char * service);

	int		(*signoff) 	(ll_lrm_t*);

	int		(*delete)  	(ll_lrm_t*);

	int		(*set_lrm_callback) (ll_lrm_t*
	,		lrm_op_done_callback_t op_done_callback_func
	, 		lrm_monitor_callback_t montior_callback_func);


/*
 *	get_rsc_types_supported:
 *				Returns the resource types supported.
 *
 *	return:		a list of pointers of char*
 *
 */
	GList * 	(*get_rsc_types_supported)(ll_lrm_t*);


/*
 *	get_all_rscs:
 *				Returns all resources.
 *
 *	return:		a list of pointers of lrm_rsc_t
 *
 */
	GList*		(*get_all_rscs)(ll_lrm_t*);


/*
 *	get_rsc:	Gets one resource pointer by the id
 *
 */
	lrm_rsc_t*	(*get_rsc)(ll_lrm_t*, rsc_id_t rsc_id);


/*
 *	add_rsc:	Adds a new resource to lrm.
 *				lrmd holds nothing when it starts.
 *				crm or lrmadmin should add resources to lrm using 
 *				this function.
 */
	int		(*add_rsc)(ll_lrm_t*, rsc_id_t rsc_id, const char* rsc_type
	, 		const char* rsc_name, const char* parameter);

	int		(*delete_rsc)(ll_lrm_t*, rsc_id_t rsc_id);

/*
 *	inputfd:	Return fd which can be given to select(2) or poll(2)
 *				for determining when messages are ready to be read.
 */

	int		(*inputfd)(ll_lrm_t*);

/*
 *	msgready:	Returns TRUE (1) when a message is ready to be read.
 */
	int		(*msgready)(ll_lrm_t*);

/*
 *	rcvmsg:	Cause the next message to be read - activating callbacks for
 *		processing the message.  If no callback processes the message
 *		it will be ignored.  The message is automatically disposed of.
 *		It returns 1 if a message was received.
 */
	int		(*rcvmsg)(ll_lrm_t*, int blocking);

};

/*
 *	ll_lrm_new:
 *			initializes the lrm client library.
 *
 *	llctype:	"lrm"
 *
 */
ll_lrm_t* ll_lrm_new(const char * llctype);

#endif /* __LRM_API_H */
