Zookeeper C API 官方示例程序

该博客介绍了Zookeeper的C API编程,虽然示例不可执行,但提供了理解API使用的宝贵线索。

这个程序不可执行,但是可以从中学到利用C API编程时的一些启示。

#include "zookeeper.h"
#include "proto.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#ifndef WIN32
#include <sys/time.h>
#include <unistd.h>
#include <sys/select.h>
#else
#include "winport.h"
//#include <io.h> <-- can't include, conflicting definitions of close()
int read(int _FileHandle, void* _DstBuf, unsigned int _MaxCharCount);
int write(int _Filehandle, const void* _Buf, unsigned int _MaxCharCount);
#define ctime_r(tctime, buffer) ctime_s (buffer, 40, tctime)
#endif

#include <time.h>
#include <errno.h>
#include <assert.h>

#ifdef YCA
#include <yca/yca.h>
#endif

#define _LL_CAST_ (long long)

static zhandle_t* zh;
static clientid_t myid;
static const char* clientIdFile = 0;
struct timeval startTime;
static char cmd[1024];
static int batchMode = 0;

static int to_send = 0;
static int sent = 0;
static int recvd = 0;

static int shutdownThisThing = 0;

//当运行时间超过某一阈值时,就打印执行时间
static __attribute__((unused)) void
printProfileInfo(struct timeval start, struct timeval end, int thres,
	const char* msg)
{
	int delay = (end.tv_sec * 1000 + end.tv_usec / 1000) -
		(start.tv_sec * 1000 + start.tv_usec / 1000);
	if (delay > thres)
		fprintf(stderr, "%s: execution time=%dms\n", msg, delay);
}

//把连接状态(state)转换为相应的常量字符串
static const char* state2String(int state) {
	if (state == 0)
		return "CLOSED_STATE";
	if (state == ZOO_CONNECTING_STATE)
		return "CONNECTING_STATE";
	if (state == ZOO_ASSOCIATING_STATE)
		return "ASSOCIATING_STATE";
	if (state == ZOO_CONNECTED_STATE)
		return "CONNECTED_STATE";
	/*if (state == ZOO_READONLY_STATE)
		return "READONLY_STATE";*/
	if (state == ZOO_EXPIRED_SESSION_STATE)
		return "EXPIRED_SESSION_STATE";
	if (state == ZOO_AUTH_FAILED_STATE)
		return "AUTH_FAILED_STATE";

	return "INVALID_STATE";
}

//把事件状态(type)转换为相应的常量字符串
static const char* type2String(int state) {
	if (state == ZOO_CREATED_EVENT)
		return "CREATED_EVENT";
	if (state == ZOO_DELETED_EVENT)
		return "DELETED_EVENT";
	if (state == ZOO_CHANGED_EVENT)
		return "CHANGED_EVENT";
	if (state == ZOO_CHILD_EVENT)
		return "CHILD_EVENT";
	if (state == ZOO_SESSION_EVENT)
		return "SESSION_EVENT";
	if (state == ZOO_NOTWATCHING_EVENT)
		return "NOTWATCHING_EVENT";

	return "UNKNOWN_EVENT_TYPE";
}

//监视回调函数。
//如果处于连接状态,获取并更新session_id,同时写入文件(如果有路径)。
//如果权限不允许或者会话过期,关闭zzh,shutdown
void watcher(zhandle_t* zzh, int type, int state, const char* path,
	void* context)
{
	/* Be careful using zh here rather than zzh - as this may be mt code
	 * the client lib may call the watcher before zookeeper_init returns */

	fprintf(stderr, "Watcher %s state = %s", type2String(type), state2String(state));
	if (path && strlen(path) > 0) {
		fprintf(stderr, " for path %s", path);
	}
	fprintf(stderr, "\n");

	if (type == ZOO_SESSION_EVENT) {
		if (state == ZOO_CONNECTED_STATE) {
			//获取客户端的session id,只有在客户端的连接状态有效时才可以
			const clientid_t* id = zoo_client_id(zzh);
			//更新myid,如果有文件路径的话,把myid写入文件
			if (myid.client_id == 0 || myid.client_id != id->client_id) {
				myid = *id;
				fprintf(stderr, "Got a new session id: 0x%llx\n",
					_LL_CAST_ myid.client_id);
				if (clientIdFile) {
					FILE* fh = fopen(clientIdFile, "w");
					if (!fh) {
						perror(clientIdFile);
					}
					else {
						int rc = fwrite(&myid, sizeof(myid), 1, fh);
						if (rc != sizeof(myid)) {
							perror("writing client id");
						}
						fclose(fh);
					}
				}
			}
		}
		else if (state == ZOO_AUTH_FAILED_STATE) {
			fprintf(stderr, "Authentication failure. Shutting down...\n");
			//注意zzh与zh的不同之处
			zookeeper_close(zzh);
			shutdownThisThing = 1;
			zh = 0;
		}
		else if (state == ZOO_EXPIRED_SESSION_STATE) {
			fprintf(stderr, "Session expired. Shutting down...\n");
			zookeeper_close(zzh);
			shutdownThisThing = 1;
			zh = 0;
		}
	}
}

//输出stat结构体内容
void dumpStat(const struct Stat* stat) {
	char tctimes[40];
	char tmtimes[40];
	time_t tctime;
	time_t tmtime;

	if (!stat) {
		fprintf(stderr, "null\n");
		return;
	}
	tctime = stat->ctime / 1000;
	tmtime = stat->mtime / 1000;

	ctime_r(&tmtime, tmtimes);
	ctime_r(&tctime, tctimes);

	fprintf(stderr, "\tctime = %s\tczxid=%llx\n"
		"\tmtime=%s\tmzxid=%llx\n"
		"\tversion=%x\taversion=%x\n"
		"\tephemeralOwner = %llx\n",
		tctimes, _LL_CAST_ stat->czxid, tmtimes,
		_LL_CAST_ stat->mzxid,
		(unsigned int)stat->version, (unsigned int)stat->aversion,
		_LL_CAST_ stat->ephemeralOwner);
}

//处理返回字符串的回调函数
//同时判断batchmode,若非0,设置shutdown=1
void my_string_completion(int rc, const char* name, const void* data) {
	fprintf(stderr, "[%s]: rc = %d\n", (char*)(data == 0 ? "null" : data), rc);
	if (!rc) {
		fprintf(stderr, "\tname = %s\n", name);
	}
	if (batchMode)
		shutdownThisThing = 1;
}

//处理返回字符串的回调函数完整版(包括指针所指内存的释放)
void my_string_completion_free_data(int rc, const char* name, const void* data) {
	my_string_completion(rc, name, data);
	free((void*)data);
}

//处理返回字符串和stat结构体的回调函数
//引用上边的返回字符串的回调函数和处理stat结构的函数
void my_string_stat_completion(int rc, const char* name, const struct Stat* stat,
	const void* data) {
	my_string_compl
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值