static int setup_master(void) { rstatus_t status; uint32_t j; vr_listen **vlisten; vr_worker *worker; for (j = 0; j < darray_n(&workers); j ++) { worker = darray_get(&workers, j); status = aeCreateFileEvent(master.vel.el, worker->socketpairs[0], AE_READABLE, thread_event_process, worker); if (status == AE_ERR) { log_error("Unrecoverable error creating master ipfd file event."); return VR_ERROR; } } for (j = 0; j < darray_n(&master.listens); j ++) { vlisten = darray_get(&master.listens,j); status = aeCreateFileEvent(master.vel.el, (*vlisten)->sd, AE_READABLE, client_accept, *vlisten); if (status == AE_ERR) { log_error("Unrecoverable error creating master ipfd file event."); return VR_ERROR; } } return VR_OK; }
int main(int argc, char **argv) { int ret; #if _LINUX_ aeEventLoop *loop; #endif SSRC = getpid(); IPCAM_DEV = create_empty_ipcam_link(); #if !_LINUX_ pthread_t deal_msg_pid; pthread_t deal_console_input_pid; pthread_t maintain_ipcam_link_pid; ret = pthread_create(&deal_console_input_pid, 0, deal_console_input, NULL); if (ret) { debug_print("pthread_create failed"); exit(errno); } ret = pthread_create(&deal_msg_pid, 0, recv_msg_from_ipcam, NULL); if (ret) { debug_print("pthread_create failed"); exit(errno); } ret = pthread_create(&maintain_ipcam_link_pid, 0, maintain_ipcam_link, NULL); if (ret) { debug_print("pthread_create failed"); exit(errno); } pthread_join(maintain_ipcam_link_pid, NULL); pthread_join(deal_msg_pid, NULL); pthread_join(deal_console_input_pid, NULL); #else int pc_server_fd; pc_server_fd = init_server_UDP_fd(PC_SERVER_PORT, "0.0.0.0"); assert(pc_server_fd > 0); loop = aeCreateEventLoop(); fprintf(stdout, "\033[01;32mipc_shell> \033[0m"); fflush(stdout); ret = aeCreateFileEvent(loop, STDIN_FILENO, AE_READABLE, dealcmd, NULL); assert(ret != AE_ERR); ret = aeCreateFileEvent(loop, pc_server_fd, AE_READABLE, dealnet, NULL); assert(ret != AE_ERR); aeCreateTimeEvent(loop, CHECK_IPCAM_CYCLE * 1000, watch_ipcam_link_clear, NULL, NULL); aeMain(loop); #endif return 0; }
void init_server_config() { g_server.port = DEFAULT_PORT; g_server.bindaddr = NULL; g_server.commands = NULL; g_server.clients = listCreate(); g_server.el = aeCreateEventLoop(100 + 1024); if (g_server.el == NULL) { printf ("el error\n"); } // create tcp server g_server.socket_fd = anetTcpServer(g_server.neterr, g_server.port, g_server.bindaddr); if (g_server.socket_fd == ANET_ERR) { printf ("socket error\n"); exit(1); } // binding acceptTcpHandler to client connected. if (g_server.socket_fd > 0) { if (aeCreateFileEvent(g_server.el, g_server.socket_fd, AE_READABLE, acceptTcpHandler, NULL) == AE_ERR){ printf ("Unrecoverable error creating server.ipfd file event"); exit(1); } } }
void initServer(){ server.mainthread = pthread_self(); server.clients = listCreate(); server.el = aeCreateEventLoop(); if (server.port != 0) { server.ipfd = anetTcpServer(server.neterr,server.port,server.bindaddr); if (server.ipfd == ANET_ERR) { redisLog(REDIS_WARNING, "Opening port %d: %s", server.port, server.neterr); exit(1); } } // if (server.unixsocket != NULL) { // unlink(server.unixsocket); /* don't care if this fails */ // server.sofd = anetUnixServer(server.neterr,server.unixsocket,server.unixsocketperm); // if (server.sofd == ANET_ERR) { // redisLog(REDIS_WARNING, "Opening socket: %s", server.neterr); // exit(1); // } // } if (server.ipfd < 0 && server.sofd < 0) { redisLog(REDIS_WARNING, "Configured to not listen anywhere, exiting."); exit(1); } aeCreateTimeEvent(server.el, 1, serverCron, NULL, NULL); if (server.ipfd > 0 && aeCreateFileEvent(server.el,server.ipfd,AE_READABLE, acceptTcpHandler,NULL) == AE_ERR) oom("creating file event"); // if (server.sofd > 0 && aeCreateFileEvent(server.el,server.sofd,AE_READABLE, // acceptUnixHandler,NULL) == AE_ERR) oom("creating file event"); }
client *createClient(int fd) { client *c = malloc(sizeof(client)); anetNonBlock(NULL,fd); anetEnableTcpNoDelay(NULL,fd); if (server.tcpkeepalive) anetKeepAlive(NULL,fd,server.tcpkeepalive); if (aeCreateFileEvent(server.el,fd,AE_READABLE, readQueryFromClient, c) == AE_ERR) { close(fd); free(c); return NULL; } c->id = server.next_client_id++; c->fd = fd; c->name = NULL; c->bufpos = 0; c->querybuf = sdsempty(); c->querybuf_peak = 0; c->reqtype = 0; c->argc = 0; c->argv = NULL; c->lastcmd = NULL; c->multibulklen = 0; c->bulklen = -1; c->sentlen = 0; c->flags = 0; c->ctime = c->lastinteraction = server.unixtime; if (fd != -1) listAddNodeTail(server.clients,c); return c; }
void one_work_start(struct aeEventLoop *eventLoop, int fd, void *clientData, int mask) { int incomesock; if(read(fd,&incomesock,sizeof(incomesock)) != sizeof(incomesock)) { logError( "file :"__FILE__",line :%d"\ "one_work_start get incomesock failed.",\ __LINE__); return ; } if(setnonblocking(incomesock) < 0) return ; storage_client_t *pClient; pClient = init_storage_client(clientData); pClient->sockfd = incomesock; pClient->data.buff = &pClient->cmd; pClient->data.need_size = sizeof(pClient->cmd); pClient->data.proc = accept_command; if(aeCreateFileEvent(eventLoop, incomesock, AE_READABLE,nb_sock_recv_data,pClient) != AE_OK) { logError( "file :"__FILE__",line :%d"\ "one_work_start CreateFileEvent failed.",\ __LINE__); clean_storage_client(pClient); return ; } return ; }
static void smrConnect () { redisLog (REDIS_NOTICE, "initialize SMR Connection, Local Dumpfile Seq Num:%lld", server.smr_seqnum); server.smr_conn = smr_connect_tcp (server.smr_lport, server.smr_seqnum, &smrCb, NULL); if (server.smr_conn == NULL) { redisLog (REDIS_WARNING, "Failed to connect to smr, errno(%d)", errno); exit (1); } server.smr_fd = smr_get_poll_fd (server.smr_conn); if (server.smr_fd == -1) { redisLog (REDIS_WARNING, "Failed to get poll fd from smr"); exit (1); } if (server.smr_fd > 0 && aeCreateFileEvent (server.el, server.smr_fd, AE_READABLE, processSmrCallback, NULL) == AE_ERR) { redisLog (REDIS_WARNING, "Unrecoverable error creating smr.fd file event."); smr_disconnect (server.smr_conn); exit (1); } }
struct gwseriport *gwseriport_create(const char *ttypath,int uart_speed) { struct gwseriport *s = malloc(sizeof(*s)); if(s == NULL) return NULL; memset(s,0,sizeof(*s)); int fd = open_seriport(ttypath,uart_speed); if(fd < 0){ free(s); return NULL; } s->recvbuf = buffer_create(1024); s->fd = fd; s->ttypath = strdup(ttypath); if(aeCreateFileEvent(server.el,fd,AE_READABLE,seriportHandler,s) == AE_ERR){ close(fd); buffer_release(s->recvbuf); free(s); return NULL; } listAddNodeTail(server.seriports,s); return s; }
static void resetClient(client c) { aeDeleteFileEvent(config.el,c->context->fd,AE_WRITABLE); aeDeleteFileEvent(config.el,c->context->fd,AE_READABLE); aeCreateFileEvent(config.el,c->context->fd,AE_WRITABLE,writeHandler,c); c->written = 0; c->pending = config.pipeline; }
void new_nb_sock_send_file(struct aeEventLoop *eventLoop, int sockfd, void *clientData, int mask) { storage_client_t *pClient; pClient = clientData; logDebug("new_nb_sock_send_file %s,%d",pClient->file.file_name,pClient->file.start_offlen); if(pClient->file.fd == 0) { if((pClient->file.fd = open(pClient->file.file_name,O_RDONLY)) == -1) { logError( "file: "__FILE__",line: %d,"\ "new_nb_sock_send_file call open file failed,"\ "errno: %d,error info: %s",\ __LINE__,errno,strerror(errno)); return ; } } if(aeCreateFileEvent(eventLoop,sockfd, AE_WRITABLE,do_new_nb_sock_send_file,pClient) != AE_OK) { logError( "file :"__FILE__",line :%d\ new_nb_sock_send_file CreateFileEvent failed.",\ __LINE__); return ; } return ; }
void readBodyFromPipe( aeEventLoop *el, int fd , aePipeData data ) { int pos = PIPE_DATA_HEADER_LENG; int nread = 0; int needlen = data.len; int bodylen = 0; if( data.len <= 0 ) { return; } nread = read( fd , data.data , needlen ); //if (nread == -1 && errno == EAGAIN) return; if( nread < 0 ) { if (nread == -1 && errno == EAGAIN) return; printf( "readBodyFromPipe error\n"); } //set writable event to connfd if ( sdslen( servG->connlist[data.connfd].send_buffer ) == 0 ) { aeCreateFileEvent( el, data.connfd, AE_WRITABLE, onClientWritable, NULL ); } servG->connlist[data.connfd].send_buffer = sdscatlen( servG->connlist[data.connfd].send_buffer ,data.data, nread ); }
int main() { printf("Start\n"); signal(SIGINT, StopServer); //初始化网络事件循环 g_event_loop = aeCreateEventLoop(1024*10); //设置监听事件 int fd = anetTcpServer(g_err_string, PORT, NULL); if( ANET_ERR == fd ) fprintf(stderr, "Open port %d error: %s\n", PORT, g_err_string); if( aeCreateFileEvent(g_event_loop, fd, AE_READABLE, AcceptTcpHandler, NULL) == AE_ERR ) fprintf(stderr, "Unrecoverable error creating server.ipfd file event."); //设置定时事件 aeCreateTimeEvent(g_event_loop, 1, PrintTimer, NULL, NULL); //开启事件循环 aeMain(g_event_loop); //删除事件循环 aeDeleteEventLoop(g_event_loop); printf("End\n"); return 0; }
void *reactorThreadRun(void *arg) { reactorThreadParam* param = (reactorThreadParam*)arg; aeServer* serv = param->serv; int thid = param->thid; aeEventLoop* el = aeCreateEventLoop( 1024 ); serv->reactorThreads[thid].reactor.eventLoop = el; int ret,i; //每个线程都有workerNum个worker pipe for( i = 0; i < serv->workerNum; i++ ) { if ( aeCreateFileEvent( el,serv->workers[i].pipefd[0], AE_READABLE,onMasterPipeReadable, thid ) == -1 ) { printf( "CreateFileEvent error fd " ); close(serv->workers[i].pipefd[0]); } } aeSetBeforeSleepProc( el ,initThreadOnLoopStart ); aeMain( el ); aeDeleteEventLoop( el ); el = NULL; }
int create_storage_service() { if((g_storage_service.sockfd = sock_server(g_storage_service.heart_beat.port)) < 0) return -1; if (tcpsetserveropt(g_storage_service.sockfd, g_storage_service.network_timeout) != 0) { return -2; } if((g_storage_service.eventLoop = (aeEventLoop*)aeCreateEventLoop()) == NULL) { logError( "file :"__FILE__",line :%d"\ "create_storage_service CreateEventLoop failed."); exit(1); } aeCreateTimeEvent(g_storage_service.eventLoop,g_storage_service.heart_beat_millisec,heart_beat_init,g_storage_service.nio_pool.nio_node,NULL); if(aeCreateFileEvent(g_storage_service.eventLoop, g_storage_service.sockfd, AE_READABLE,accept_tcp,NULL) != AE_OK) { logError( "file :"__FILE__",line :%d"\ "create_storage_service CreateFileEvent failed."); exit(1); } return 0; }
int create_tracker_service() { if((g_tracker_service.sockfd = sock_server(g_tracker_service.server_port)) < 0) return -1; if (tcpsetserveropt(g_tracker_service.sockfd, g_tracker_service.network_timeout) != 0) { return -2; } if((g_tracker_service.eventLoop = (aeEventLoop*)aeCreateEventLoop()) == NULL) { logError( "file :"__FILE__",line :%d"\ "create_tracker_service CreateEventLoop failed."); return -3; } aeCreateTimeEvent(g_tracker_service.eventLoop,g_tracker_service.check_storage_pool_millisec,check_storage_pool,NULL,NULL); if(aeCreateFileEvent(g_tracker_service.eventLoop, g_tracker_service.sockfd, AE_READABLE,accept_tcp,NULL) != AE_OK) { logError( "file :"__FILE__",line :%d"\ "create_tracker_service CreateFileEvent failed."); return -4; } return 0; }
static int connect_socket(thread *thread, connection *c) { struct addrinfo addr = cfg.addr; struct aeEventLoop *loop = thread->loop; int fd, flags; fd = socket(addr.ai_family, addr.ai_socktype, addr.ai_protocol); flags = fcntl(fd, F_GETFL, 0); fcntl(fd, F_SETFL, flags | O_NONBLOCK); if (connect(fd, addr.ai_addr, addr.ai_addrlen) == -1) { if (errno != EINPROGRESS) goto error; } flags = 1; setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &flags, sizeof(flags)); if (aeCreateFileEvent(loop, fd, AE_READABLE, socket_handshake, c) != AE_OK) { goto error; } c->fd = fd; return fd; error: thread->errors.connect++; close(fd); return -1; }
void *reactorThreadRun( void *arg ) { reactorThreadParam *param = (reactorThreadParam *) arg; appnetServer *serv = param->serv; int thid = param->thid; aeEventLoop *el = aeCreateEventLoop( MAX_EVENT ); serv->reactor_threads[thid].reactor.event_loop = el; serv->reactor_threads[thid].hh = (httpHeader *) malloc( sizeof(httpHeader) ); serv->reactor_threads[thid].hs = (handshake *) malloc( sizeof(handshake) ); int ret,i,index; for (i = 0; i < serv->worker_num + serv->task_worker_num; i++) { index = i * serv->reactor_num + thid; if (aeCreateFileEvent( el , serv->worker_pipes[index].pipefd[0] , AE_READABLE , onMasterPipeReadable , thid ) == -1) { printf( "CreateFileEvent error fd " ); close( serv->worker_pipes[index].pipefd[0] ); } } aeSetBeforeSleepProc( el , initThreadOnLoopStart ); aeMain( el ); aeDeleteEventLoop( el ); free( serv->reactor_threads[thid].hh ); free( serv->reactor_threads[thid].hs ); el = NULL; }
int main(int argc, char** argv) { signal(SIGABRT, &sighandler); signal(SIGTERM, &sighandler); signal(SIGINT, &sighandler); initServer(); aeEventLoop* eventLoop = aeCreateEventLoop(server.max_process_client + SHTTPSVR_EVENTLOOP_FDSET_INCR); server.el = eventLoop; int listen_socket = anetTcpServer(NULL, 80, NULL, server.tcp_backlog); anetNonBlock(NULL, listen_socket); if (listen_socket > 0 && AE_ERR == aeCreateFileEvent(eventLoop, listen_socket, AE_READABLE, tAcceptProc, NULL)) { ERRLOG("aeCreateFileEvent error!"); exit(1); } aeSetBeforeSleepProc(eventLoop, tBeforeSleepProc); initTimeEvent(eventLoop); aeMain(eventLoop); aeDeleteEventLoop(eventLoop); return 0; }
void aeFileReadWrite(struct aeEventLoop *eventLoop, int fd, void *clientData, int mask) { int ret; printf("aeFileReadWrite mask = %d, fd = %d\n", mask, fd); if(server_fd == fd){ struct sockaddr_in client_addr; socklen_t sin_size; printf("A New client connect\n"); int new_fd = accept(fd, (struct sockaddr *)&client_addr, &sin_size); printf("New connection client%s:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); ret = aeCreateFileEvent(eventLoop, new_fd, AE_READABLE, aeFileReadWrite, NULL); if(ret == AE_ERR) printf("aeCreateFileEvent failed\n"); }else{ char buf[1024]; ret = recv(fd, buf, sizeof(buf), 0); if (ret <= 0) { printf("A Client disconnet\n"); aeDeleteFileEvent(eventLoop, fd, AE_READABLE | AE_WRITABLE); aeClose(fd); }else{ buf[ret] = '\0'; printf("Recv data: %s\n", buf); } } }
int acceptor_start(acceptor_t *acceptor) { if(0!=aeCreateFileEvent(g_libnet.evLoop,acceptor->fd, AE_READABLE,_accept_handler,(void*)acceptor)){ return (-1); } return 0; }
void addReplay(vuiClient *c, const char *body) { if (body) c->res.body = sdscpy(c->res.body, body); else sdsclear(c->res.body); c->procing = PROC_HALF; aeCreateFileEvent(server.el, c->fd, AE_WRITABLE, sendReplay, c); }
redisClient *createClient(int fd) { redisClient *c = zmalloc(sizeof(redisClient)); /* passing -1 as fd it is possible to create a non connected client. * This is useful since all the Redis commands needs to be executed * in the context of a client. When commands are executed in other * contexts (for instance a Lua script) we need a non connected client. */ if (fd != -1) { anetNonBlock(NULL,fd); anetEnableTcpNoDelay(NULL,fd); if (server.tcpkeepalive) anetKeepAlive(NULL,fd,server.tcpkeepalive); if (aeCreateFileEvent(server.el,fd,AE_READABLE, readQueryFromClient, c) == AE_ERR) { close(fd); zfree(c); return NULL; } } selectDb(c,0); c->fd = fd; c->name = NULL; c->bufpos = 0; c->querybuf = sdsempty(); c->querybuf_peak = 0; c->reqtype = 0; c->argc = 0; c->argv = NULL; c->cmd = c->lastcmd = NULL; c->multibulklen = 0; c->bulklen = -1; c->sentlen = 0; c->flags = 0; c->ctime = c->lastinteraction = server.unixtime; c->authenticated = 0; c->replstate = REDIS_REPL_NONE; c->slave_listening_port = 0; c->reply = listCreate(); c->reply_bytes = 0; c->obuf_soft_limit_reached_time = 0; listSetFreeMethod(c->reply,decrRefCount); listSetDupMethod(c->reply,dupClientReplyValue); c->bpop.keys = dictCreate(&setDictType,NULL); c->bpop.timeout = 0; c->bpop.target = NULL; c->io_keys = listCreate(); c->watched_keys = listCreate(); listSetFreeMethod(c->io_keys,decrRefCount); c->pubsub_channels = dictCreate(&setDictType,NULL); c->pubsub_patterns = listCreate(); listSetFreeMethod(c->pubsub_patterns,decrRefCount); listSetMatchMethod(c->pubsub_patterns,listMatchObjects); if (fd != -1) listAddNodeTail(server.clients,c); initClientMultiState(c); return c; }
int SetWriteEvent(proxy_client*c) { if(aeCreateFileEvent(el,c->fd,AE_WRITABLE,SendOutcome,c)==AE_ERR){ LogError("Set write event failed"); return -1; } return 0; }
/* Set the event loop to listen for write events on the client's socket. * Typically gets called every time a reply is built. */ int _installWriteEvent(redisClient *c) { if (c->fd <= 0) return REDIS_ERR; if (c->bufpos == 0 && listLength(c->reply) == 0 && (c->replstate == REDIS_REPL_NONE || c->replstate == REDIS_REPL_ONLINE) && aeCreateFileEvent(server.el, c->fd, AE_WRITABLE, sendReplyToClient, c) == AE_ERR) return REDIS_ERR; return REDIS_OK; }
//此函数必须在写入send_buffer前执行 void setPipeWritable( aeEventLoop *el , void *privdata , int worker_id ) { if (sdslen( servG->workers[worker_id].send_buffer ) == 0 ) { aeCreateFileEvent( el, servG->workers[worker_id].pipefd[0], AE_WRITABLE, onMasterPipeWritable, worker_id ); } }
/* This function is called every time we are going to transmit new data * to the client. The behavior is the following: * * If the client should receive new data (normal clients will) the function * returns REDIS_OK, and make sure to install the write handler in our event * loop so that when the socket is writable new data gets written. * * If the client should not receive new data, because it is a fake client * or a slave, or because the setup of the write handler failed, the function * returns REDIS_ERR. * * Typically gets called every time a reply is built, before adding more * data to the clients output buffers. If the function returns REDIS_ERR no * data should be appended to the output buffers. */ int prepareClientToWrite(redisClient *c) { if (c->flags & REDIS_LUA_CLIENT) return REDIS_OK; if (c->fd <= 0) return REDIS_ERR; /* Fake client */ if (c->bufpos == 0 && listLength(c->reply) == 0 && (c->replstate == REDIS_REPL_NONE || c->replstate == REDIS_REPL_ONLINE) && aeCreateFileEvent(server.el, c->fd, AE_WRITABLE, sendReplyToClient, c) == AE_ERR) return REDIS_ERR; return REDIS_OK; }
/* This function is called at the end of every background saving. * The argument bgsaveerr is REDIS_OK if the background saving succeeded * otherwise REDIS_ERR is passed to the function. * * The goal of this function is to handle slaves waiting for a successful * background saving in order to perform non-blocking synchronization. */ void updateSlavesWaitingBgsave(int bgsaveerr) { //backgroundSaveDoneHandler在BGSAVE操作完成后,调用这里来处理可能的从库事件。 listNode *ln; int startbgsave = 0; listIter li; listRewind(server.slaves,&li); while((ln = listNext(&li))) {//循环遍历每一个从库,查看其状态进行相应的处理。 redisClient *slave = ln->value; if (slave->replstate == REDIS_REPL_WAIT_BGSAVE_START) { startbgsave = 1;//刚才在做bgsave的时候,有客户端来请求sync同步,但是我没有理他,现在得给他准备了。 slave->replstate = REDIS_REPL_WAIT_BGSAVE_END;//修改这个状态后,新的写入操作会记录到这个连接的缓存里 } else if (slave->replstate == REDIS_REPL_WAIT_BGSAVE_END) { //后台保存完成,下面需要发送rdb文件了,丫的够大的 struct redis_stat buf; if (bgsaveerr != REDIS_OK) { freeClient(slave); redisLog(REDIS_WARNING,"SYNC failed. BGSAVE child returned an error"); continue; } //打开这个rdb_filename,要准备给这个slave发送数据了。 if ((slave->repldbfd = open(server.rdb_filename,O_RDONLY)) == -1 || redis_fstat(slave->repldbfd,&buf) == -1) { freeClient(slave); redisLog(REDIS_WARNING,"SYNC failed. Can't open/stat DB after BGSAVE: %s", strerror(errno)); continue; } slave->repldboff = 0; slave->repldbsize = buf.st_size; //记住此时slave->repldbfd没有关闭,可写事件的时候就不需要打开了。 slave->replstate = REDIS_REPL_SEND_BULK; aeDeleteFileEvent(server.el,slave->fd,AE_WRITABLE);//删掉之前的可写回调,注册为sendBulkToSlave if (aeCreateFileEvent(server.el, slave->fd, AE_WRITABLE, sendBulkToSlave, slave) == AE_ERR) { freeClient(slave); continue; } } } if (startbgsave) {//悲剧,又有要sync的,还得保存一次。 if (rdbSaveBackground(server.rdb_filename) != REDIS_OK) { listIter li; listRewind(server.slaves,&li); redisLog(REDIS_WARNING,"SYNC failed. BGSAVE failed"); while((ln = listNext(&li))) { redisClient *slave = ln->value; //这下面似乎有问题,replstate已经在上面被设置为了_END。https://github.com/antirez/redis/issues/1308 if (slave->replstate == REDIS_REPL_WAIT_BGSAVE_START) freeClient(slave); } } } }
static void acceptCommonHandler(int fd, int flags, char *ip) { client *c = (client *)zmalloc(sizeof(client)); c->fd = fd; if (aeCreateFileEvent(server.el, fd, AE_READABLE, readClient, (void *) c) == AE_ERR) { close(fd); zfree(c); return; } anetNonBlock(NULL, fd); return; }
void sendBulkToSlave(aeEventLoop *el, int fd, void *privdata, int mask) { redisClient *slave = privdata; REDIS_NOTUSED(el); REDIS_NOTUSED(mask); char buf[REDIS_IOBUF_LEN]; ssize_t nwritten, buflen; if (slave->repldboff == 0) { /* Write the bulk write count before to transfer the DB. In theory here * we don't know how much room there is in the output buffer of the * socket, but in pratice SO_SNDLOWAT (the minimum count for output * operations) will never be smaller than the few bytes we need. */ sds bulkcount; bulkcount = sdscatprintf(sdsempty(),"$%lld\r\n",(unsigned long long) slave->repldbsize); if (write(fd,bulkcount,sdslen(bulkcount)) != (signed)sdslen(bulkcount)) { sdsfree(bulkcount); freeClient(slave); return; } sdsfree(bulkcount); } lseek(slave->repldbfd,slave->repldboff,SEEK_SET); buflen = read(slave->repldbfd,buf,REDIS_IOBUF_LEN); if (buflen <= 0) { redisLog(REDIS_WARNING,"Read error sending DB to slave: %s", (buflen == 0) ? "premature EOF" : strerror(errno)); freeClient(slave); return; } if ((nwritten = write(fd,buf,buflen)) == -1) { redisLog(REDIS_VERBOSE,"Write error sending DB to slave: %s", strerror(errno)); freeClient(slave); return; } slave->repldboff += nwritten; if (slave->repldboff == slave->repldbsize) { close(slave->repldbfd); slave->repldbfd = -1; aeDeleteFileEvent(server.el,slave->fd,AE_WRITABLE); slave->replstate = REDIS_REPL_ONLINE; if (aeCreateFileEvent(server.el, slave->fd, AE_WRITABLE, sendReplyToClient, slave) == AE_ERR) { freeClient(slave); return; } addReplySds(slave,sdsempty()); redisLog(REDIS_NOTICE,"Synchronization with slave succeeded"); } }
/* Set the event loop to listen for write events on the client's socket. * Typically gets called every time a reply is built. */ int _installWriteEvent(redisClient *c) { /* When CLOSE_AFTER_REPLY is set, no more replies may be added! */ redisAssert(!(c->flags & REDIS_CLOSE_AFTER_REPLY)); if (c->fd <= 0) return REDIS_ERR; if (c->bufpos == 0 && listLength(c->reply) == 0 && (c->replstate == REDIS_REPL_NONE || c->replstate == REDIS_REPL_ONLINE) && aeCreateFileEvent(server.el, c->fd, AE_WRITABLE, sendReplyToClient, c) == AE_ERR) return REDIS_ERR; return REDIS_OK; }