/* $Id: apphb.c,v 1.16.2.2 2004/09/14 16:29:12 alan Exp $ */
/*
* apphb.c: application heartbeat library code.
*
* Copyright (C) 2002 Alan Robertson <alanr@unix.sh>
*
*
*
* 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 <portability.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <apphb.h>
#define time footime
#define index fooindex
#include <glib.h>
#undef time
#undef index
#include <clplumbing/ipc.h>
#include <clplumbing/apphb_cs.h>
#include <stdio.h>
static struct IPC_CHANNEL* hbcomm = NULL;
static GHashTable * hbattrs;
static int hbstatus = -1;
static int apphb_getrc(void);
/* Get return code from last operation */
static int
apphb_getrc(void)
{
struct apphb_rc * rcs;
int rc;
struct IPC_MESSAGE * msg;
hbcomm->ops->waitin(hbcomm);
if (hbcomm->ops->recv(hbcomm, &msg) != IPC_OK) {
perror("Receive failure:");
return errno;
}
rcs = msg->msg_body;
rc = rcs->rc;
msg->msg_done(msg);
return rc;
}
/* Register for application heartbeat services */
int
apphb_register(const char * appname, const char * appinstance)
{
int err;
struct IPC_MESSAGE Msg;
struct apphb_signupmsg msg;
static char path [] = IPC_PATH_ATTR;
static char sockpath [] = APPHBSOCKPATH;
if (hbcomm != NULL) {
errno = EEXIST;
return -1;
}
if (appname == NULL || appinstance == NULL) {
errno = EINVAL;
return -1;
}
if (strlen(appname) >= APPHB_OLEN
|| strlen(appinstance) >= APPHB_OLEN) {
errno = ENAMETOOLONG;
return -1;
}
/* Create communication channel with server... */
hbattrs = g_hash_table_new(g_str_hash,g_str_equal);
g_hash_table_insert(hbattrs, path, sockpath);
hbcomm = ipc_channel_constructor(IPC_ANYTYPE, hbattrs);
if (hbcomm == NULL
|| (hbstatus = hbcomm->ops->initiate_connection(hbcomm)
!= IPC_OK)) {
apphb_unregister();
errno = EBADF;
return -1;
}
/* Send registration message ... */
strncpy(msg.msgtype, REGISTER, sizeof(msg.msgtype));
strncpy(msg.appname, appname, sizeof(msg.appname));
strncpy(msg.appinstance, appinstance, sizeof(msg.appinstance));
msg.pid = getpid();
msg.uid = getuid();
msg.gid = getgid();
Msg.msg_body = &msg;
Msg.msg_len = sizeof(msg);
Msg.msg_done = NULL;
Msg.msg_private = NULL;
Msg.msg_ch = hbcomm;
if (hbcomm->ops->send(hbcomm, &Msg) != IPC_OK) {
apphb_unregister();
errno = EBADF;
return -1;
}
if ((err = apphb_getrc()) != 0) {
hbstatus = -1;
errno = err;
return -1;
}
return 0;
}
/* Unregister from application heartbeat services */
int
apphb_unregister(void)
{
int rc = 0;
int err;
struct apphb_msg msg;
struct IPC_MESSAGE Msg;
if (hbcomm == NULL || hbstatus != IPC_OK) {
errno = ESRCH;
rc = -1;
}
/* Send an unregister message to the server... */
if (hbcomm != NULL && hbstatus == IPC_OK) {
strncpy(msg.msgtype, UNREGISTER, sizeof(msg.msgtype));
Msg.msg_body = &msg;
Msg.msg_len = sizeof(msg);
Msg.msg_done = NULL;
Msg.msg_private = NULL;
Msg.msg_ch = hbcomm;
if (hbcomm->ops->send(hbcomm, &Msg) != IPC_OK) {
rc = -1;
rc = EBADF;
}else if ((err = apphb_getrc()) != 0) {
errno = err;
rc = -1;
}
}
/* Destroy and NULL out hbcomm */
if (hbcomm) {
hbcomm->ops->destroy(hbcomm);
hbcomm = NULL;
}else{
errno = ESRCH;
rc = -1;
}
/* Destroy and NULL out hbattrs */
if (hbattrs) {
g_hash_table_destroy(hbattrs);
hbattrs = NULL;
}
return rc;
}
/* Set application heartbeat interval (in milliseconds) */
int
apphb_setinterval(unsigned long hbms)
{
struct apphb_msmsg msg;
struct IPC_MESSAGE Msg;
int err;
if (hbcomm == NULL || hbstatus != IPC_OK) {
errno = ESRCH;
return -1;
}
strncpy(msg.msgtype, SETINTERVAL, sizeof(msg.msgtype));
msg.ms = hbms;
Msg.msg_body = &msg;
Msg.msg_len = sizeof(msg);
Msg.msg_done = NULL;
Msg.msg_private = NULL;
Msg.msg_ch = hbcomm;
if (hbcomm->ops->send(hbcomm, &Msg) != IPC_OK) {
errno = EBADF;
return -1;
}
if ((err = apphb_getrc()) != 0) {
errno = err;
return -1;
}
return 0;
}
/* Set application heartbeat warning time (in milliseconds) */
int
apphb_setwarn(unsigned long hbms)
{
struct apphb_msmsg msg;
struct IPC_MESSAGE Msg;
int err;
if (hbcomm == NULL || hbstatus != IPC_OK) {
errno = ESRCH;
return -1;
}
if (hbms <= 0) {
errno = EINVAL;
return -1;
}
strncpy(msg.msgtype, SETWARNTIME, sizeof(msg.msgtype));
msg.ms = hbms;
Msg.msg_body = &msg;
Msg.msg_len = sizeof(msg);
Msg.msg_done = NULL;
Msg.msg_private = NULL;
Msg.msg_ch = hbcomm;
if (hbcomm->ops->send(hbcomm, &Msg) != IPC_OK) {
errno = EBADF;
return -1;
}
if ((err = apphb_getrc()) != 0) {
errno = err;
return -1;
}
return 0;
}
/* Perform application heartbeat */
int
apphb_hb(void)
{
struct apphb_msg msg;
struct IPC_MESSAGE Msg;
if (hbcomm == NULL || hbstatus != IPC_OK) {
errno = ESRCH;
return -1;
}
strncpy(msg.msgtype, HEARTBEAT, sizeof(msg.msgtype));
Msg.msg_body = &msg;
Msg.msg_len = sizeof(msg);
Msg.msg_done = NULL;
Msg.msg_private = NULL;
Msg.msg_ch = hbcomm;
if (hbcomm->ops->send(hbcomm, &Msg) != IPC_OK) {
errno = EBADF;
return -1;
}
/* NOTE: we do not expect a return code from server */
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1