Hi all,

  I'd like to run heartbeat on a single node.

  Because heartbeat refuses to start as the it requires at least one
usable media for communication, I think it might be good idea to have
a new HBcomm plugin for this purpose.

  The attached file has been tested on openSUSE 10.2 + hg version of hb2.

  Comments are welcome.

  Thanks.
/*
 * null.c: Null communication for heartbeat v2.
 * 
 * Copyright (C) 2007 Xinwei Hu <[EMAIL PROTECTED]>
 *
 * Null Communication is useful when using heartbeat to
 * monitor application on one node ONLY.
 *
 * 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
 *
 */
#include <lha_internal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include <sys/types.h>

#include <semaphore.h>
#include <sys/types.h>
#include <sys/mman.h>

#include <heartbeat.h>
#include <HBcomm.h>

#define PIL_PLUGINTYPE          HB_COMM_TYPE
#define PIL_PLUGINTYPE_S        HB_COMM_TYPE_S
#define PIL_PLUGIN              nullc
#define PIL_PLUGIN_S            "nullc"
#define PIL_PLUGINLICENSE 	LICENSE_LGPL
#define PIL_PLUGINLICENSEURL 	URL_LGPL
#include <pils/plugin.h>

static int		nullc_init(void);
struct hb_media*	nullc_new(const char* interface);
static int		nullc_open(struct hb_media* mp);
static int		nullc_close(struct hb_media* mp);
static void*		nullc_read(struct hb_media* mp, int *lenp);
static int		nullc_write(struct hb_media* mp, void* msg, int len);
static int		nullc_descr(char** buffer);
static int		nullc_mtype(char** buffer);
static int		nullc_isping(void);

static struct hb_media_fns nullcOps ={
	nullc_new,	/* Create single object function */
	NULL,		/* whole-line parse function */
	nullc_open,
	nullc_close,
	nullc_read,
	nullc_write,
	nullc_mtype,
	nullc_descr,
	nullc_isping,
};

PIL_PLUGIN_BOILERPLATE2("1.0", Debug)
static const PILPluginImports*  PluginImports;
static PILPlugin*               OurPlugin;
static PILInterface*		OurInterface;
static struct hb_media_imports*	OurImports;
static void*			interfprivate;

#define LOG	PluginImports->log
#define MALLOC	PluginImports->alloc
#define STRDUP  PluginImports->mstrdup
#define FREE	PluginImports->mfree

PIL_rc
PIL_PLUGIN_INIT(PILPlugin*us, const PILPluginImports* imports);

PIL_rc
PIL_PLUGIN_INIT(PILPlugin*us, const PILPluginImports* imports)
{
	/* Force the compiler to do a little type checking */
	(void)(PILPluginInitFun)PIL_PLUGIN_INIT;

	PluginImports = imports;
	OurPlugin = us;

	/* Register ourself as a plugin */
	imports->register_plugin(us, &OurPIExports);  

	/*  Register our interface implementation */
 	return imports->register_interface(us, PIL_PLUGINTYPE_S
	,	PIL_PLUGIN_S
	,	&nullcOps
	,	NULL		/*close */
	,	&OurInterface
	,	(void*)&OurImports
	,	interfprivate); 
}

#define		ISNULLCOBJECT(mp) ((mp) && ((mp)->vf == (void*)&nullcOps))
#define		NULLCASSERT(mp)	g_assert(ISNULLCOBJECT(mp))

static int 
nullc_mtype(char** buffer) { 
	*buffer = STRDUP(PIL_PLUGIN_S);
	if (!*buffer) {
		return 0;
	}

	return STRLEN_CONST(PIL_PLUGIN_S);
}

static int
nullc_descr(char **buffer) { 
	const char constret[] = "Null communication";
	*buffer = STRDUP(constret);
	if (!*buffer) {
		return 0;
	}
	return STRLEN_CONST(constret);
}

static int
nullc_isping(void) {
    return 0;
}

static int
nullc_init(void)
{
	g_assert(OurImports != NULL);
	return(HA_OK);
}

static void* msgbuf = NULL;
static sem_t* readable_lock = NULL;
static sem_t* writable_lock = NULL;

struct hb_media *
nullc_new(const char * intf)
{
	struct hb_media *	ret;
    int shmid;
	static char readlock_name[256] = "/nullc.";
	static char writelock_name[256] = "/nullc.";
	static char sharem_name[256] = "/nullc.";
    
	nullc_init();
	ret = (struct hb_media*) MALLOC(sizeof(struct hb_media));
	if (ret != NULL) {
		char * name;
		memset(ret, 0, sizeof(*ret));
		name = STRDUP("intf");
		if (name != NULL) {
			ret->name = name;
		} else {
			FREE(ret);
			ret = NULL;
		}
	}

	strncat(readlock_name, ret->name, 248);
	strncat(writelock_name, ret->name, 248);
	strncat(sharem_name, ret->name, 248);
	readable_lock = sem_open(readlock_name, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR, 0);
	if (readable_lock == SEM_FAILED) {
		PILCallLog(LOG, PIL_CRIT, "readable_lock init failed due to %s", strerror(errno));
		FREE(ret);
		return NULL;
	}
	writable_lock = sem_open(writelock_name, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR, 1);
	if (writable_lock == SEM_FAILED) {
		PILCallLog(LOG, PIL_CRIT, "writeable_lock init failed due to %s", strerror(errno));
		FREE(ret);
		return NULL;
	}
	/*
    shmid = shmget(ftok("/tmp/nullc.ASDF", 1), sizeof(char)*MAXMSG+sizeof(int), IPC_CREAT|SHM_R|SHM_W);
    if (shmid == -1) {
      FREE(ret);
      return NULL;
    }
    msgbuf = shmat(shmid, NULL, 0);
	*/
	shmid= shm_open(sharem_name, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
	if (shmid == -1) {
		PILCallLog(LOG, PIL_CRIT, "shm_open failed due to %s", strerror(errno));
		FREE(ret);
		return NULL;
	}
	ftruncate(shmid, sizeof(char)*MAXMSG+sizeof(int));
	msgbuf = mmap(NULL, sizeof(char)*MAXMSG+sizeof(int), PROT_READ|PROT_WRITE, MAP_SHARED, shmid, 0);
	if (msgbuf == NULL) {
		PILCallLog(LOG, PIL_CRIT, "mmap failed due to %s", strerror(errno));
		FREE(ret);
		return NULL;
	}
    
	return(ret);
}

static int
nullc_open(struct hb_media* mp) {
  return(HA_OK);
}

static int
nullc_close(struct hb_media* mp) {
  PILCallLog(LOG, PIL_CRIT, "nullc_close");
  return (HA_OK);
}

static void *
nullc_read(struct hb_media* mp, int * lenp) {
	static char buf[MAXMSG];
  int* pi = msgbuf;
  int len = *pi + 1;
  sem_wait(readable_lock);
  memcpy(buf, (char*)msgbuf+sizeof(int),  sizeof(char)*len);
  *lenp = len;
  *pi = 0;
  sem_post(writable_lock);
//  PILCallLog(LOG, PIL_CRIT, "read: %s", (char*)buf);  
  return buf;

}

static int
nullc_write(struct hb_media* mp, void *pkt, int len) {
  int* pi = msgbuf;
  char* buf = (char*)msgbuf+sizeof(int);
  
  *pi = len;
  sem_wait(writable_lock);
  memcpy(buf, pkt, *pi);
  sem_post(readable_lock);
//  PILCallLog(LOG, PIL_CRIT, "write: %s", (char*)buf);
  return(HA_OK);
}

_______________________________________________________
Linux-HA-Dev: [email protected]
http://lists.linux-ha.org/mailman/listinfo/linux-ha-dev
Home Page: http://linux-ha.org/

Reply via email to