这个程序不可执行,但是可以从中学到利用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

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

被折叠的 条评论
为什么被折叠?



