void NesApuDMChannel::reset() { memset(this, 0, sizeof(NesApuDMChannel)); m_currentFrequencyLut = m_frequencyLut[nesSystemType]; for (int i = 0; i < 4; i++) write(i, 0); for (int i = 0; i < 4; i++) syncWrite(i, 0); }
void AX12::setMultiPosVel (byte targetlength, byte* targets, int* posvalues, int* velvalues) { byte valuess [targetlength][4]; byte * pointers [targetlength]; for (byte f=0; f<targetlength; f++) { valuess [f][0] = lowByte(posvalues[f]); valuess[f][1] = highByte(posvalues[f]); valuess [f][2] = lowByte(velvalues[f]); valuess[f][3] = highByte(velvalues[f]); pointers[f] = &valuess[f][0]; } //nota: la sync write no respeta la propiedad "inverse" syncWrite (GOAL_POSITION, 4, targetlength, targets, pointers); }
/** "intelligent" sync write */ void AX12::syncInfo (byte registr, byte targetlength, byte* targets, int* values) { byte reglength = lengthWrite (registr); if (reglength==0) {return;} byte valuess [targetlength][reglength]; byte * pointers [targetlength]; for (byte f=0; f<targetlength; f++) { valuess [f][0] = lowByte(values[f]); if (reglength > 1) {valuess[f][1] = highByte(values[f]);} pointers[f] = &valuess[f][0]; } //nota: la sync write no respeta la propiedad "inverse" syncWrite (registr, reglength, targetlength, targets, pointers); }
int AioOutputStream::append(const char *pBuf, int len) { if (getfd() == -1) return LS_FAIL; if (!m_async) { #ifdef AIOSTREAM_DEBUG printf("AIOSTREAM: Reg Writing %.*s, %d\n", len, pBuf, len); #endif return syncWrite(pBuf, len); } if (!m_pRecv) m_pRecv = ResourcePool::getInstance().getAutoBuf(); #ifdef AIOSTREAM_DEBUG printf("AIOSTREAM: Aio Writing %.*s, %d\n", len, pBuf, len); #endif return m_pRecv->append(pBuf, len); }
/* Send a synchronous command to the master. Used to send AUTH and * REPLCONF commands before starting the replication with SYNC. * * On success NULL is returned. * On error an sds string describing the error is returned. */ char *sendSynchronousCommand(int fd, ...) { va_list ap; sds cmd = sdsempty(); char *arg, buf[256]; /* Create the command to send to the master, we use simple inline * protocol for simplicity as currently we only send simple strings. */ va_start(ap,fd); while(1) { arg = va_arg(ap, char*); if (arg == NULL) break; if (sdslen(cmd) != 0) cmd = sdscatlen(cmd," ",1); cmd = sdscat(cmd,arg); } cmd = sdscatlen(cmd,"\r\n",2); /* Transfer command to the server. */ if (syncWrite(fd,cmd,sdslen(cmd),server.repl_syncio_timeout*1000) == -1) { sdsfree(cmd); return sdscatprintf(sdsempty(),"Writing to master: %s", strerror(errno)); } sdsfree(cmd); /* Read the reply from the server. */ if (syncReadLine(fd,buf,sizeof(buf),server.repl_syncio_timeout*1000) == -1) { return sdscatprintf(sdsempty(),"Reading from master: %s", strerror(errno)); } /* Check for errors from the server. */ if (buf[0] != '+') { return sdscatprintf(sdsempty(),"Error from master: %s", buf); } return NULL; /* No errors. */ }
void NesApuDMChannel::sl() { emsl.array("regs", m_regs, sizeof(m_regs)); if (!emsl.save) { for (int i = 0; i < 4; i++) { write(i, m_regs[i]); syncWrite(i, m_regs[i]); } } emsl.var("dmaLength", m_dmaLength); emsl.var("address", m_address); emsl.var("irq", m_syncIrq); emsl.var("timer", m_timer); emsl.var("buffer", m_buffer); emsl.var("dac", m_dac); emsl.var("syncCycles", m_syncCycles); if (!emsl.save) m_syncDmaLength = m_dmaLength; }
int syncWithMaster(void) { char buf[1024], tmpfile[256], authcmd[1024]; int fd = anetTcpConnect(NULL,server.masterhost,server.masterport); int dfd, maxtries = 5; if (fd == -1) { redisLog(REDIS_WARNING,"Unable to connect to MASTER: %s", strerror(errno)); return REDIS_ERR; } /* AUTH with the master if required. */ if(server.masterauth) { snprintf(authcmd, 1024, "AUTH %s\r\n", server.masterauth); if (syncWrite(fd, authcmd, strlen(server.masterauth)+7, 5) == -1) { close(fd); redisLog(REDIS_WARNING,"Unable to AUTH to MASTER: %s", strerror(errno)); return REDIS_ERR; } /* Read the AUTH result. */ if (syncReadLine(fd,buf,1024,3600) == -1) { close(fd); redisLog(REDIS_WARNING,"I/O error reading auth result from MASTER: %s", strerror(errno)); return REDIS_ERR; } if (buf[0] != '+') { close(fd); redisLog(REDIS_WARNING,"Cannot AUTH to MASTER, is the masterauth password correct?"); return REDIS_ERR; } } /* Issue the SYNC command */ if (syncWrite(fd,"SYNC \r\n",7,5) == -1) { close(fd); redisLog(REDIS_WARNING,"I/O error writing to MASTER: %s", strerror(errno)); return REDIS_ERR; } /* Prepare a suitable temp file for bulk transfer */ while(maxtries--) { snprintf(tmpfile,256, "temp-%d.%ld.rdb",(int)time(NULL),(long int)getpid()); dfd = open(tmpfile,O_CREAT|O_WRONLY|O_EXCL,0644); if (dfd != -1) break; sleep(1); } if (dfd == -1) { close(fd); redisLog(REDIS_WARNING,"Opening the temp file needed for MASTER <-> SLAVE synchronization: %s",strerror(errno)); return REDIS_ERR; } /* Setup the non blocking download of the bulk file. */ if (aeCreateFileEvent(server.el, fd, AE_READABLE, readSyncBulkPayload, NULL) == AE_ERR) { close(fd); redisLog(REDIS_WARNING,"Can't create readable event for SYNC"); return REDIS_ERR; } server.replstate = REDIS_REPL_TRANSFER; server.repl_transfer_left = -1; server.repl_transfer_s = fd; server.repl_transfer_fd = dfd; server.repl_transfer_lastio = time(NULL); server.repl_transfer_tmpfile = zstrdup(tmpfile); return REDIS_OK; }
void syncWithMaster(aeEventLoop *el, int fd, void *privdata, int mask) { char tmpfile[256], *err; int dfd, maxtries = 5; int sockerr = 0; socklen_t errlen = sizeof(sockerr); REDIS_NOTUSED(el); REDIS_NOTUSED(privdata); REDIS_NOTUSED(mask); /* If this event fired after the user turned the instance into a master * with SLAVEOF NO ONE we must just return ASAP. */ if (server.repl_state == REDIS_REPL_NONE) { close(fd); return; } /* Check for errors in the socket. */ if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &sockerr, &errlen) == -1) sockerr = errno; if (sockerr) { aeDeleteFileEvent(server.el,fd,AE_READABLE|AE_WRITABLE); redisLog(REDIS_WARNING,"Error condition on socket for SYNC: %s", strerror(sockerr)); goto error; } /* If we were connecting, it's time to send a non blocking PING, we want to * make sure the master is able to reply before going into the actual * replication process where we have long timeouts in the order of * seconds (in the meantime the slave would block). */ if (server.repl_state == REDIS_REPL_CONNECTING) { redisLog(REDIS_NOTICE,"Non blocking connect for SYNC fired the event."); /* Delete the writable event so that the readable event remains * registered and we can wait for the PONG reply. */ aeDeleteFileEvent(server.el,fd,AE_WRITABLE); server.repl_state = REDIS_REPL_RECEIVE_PONG; /* Send the PING, don't check for errors at all, we have the timeout * that will take care about this. */ syncWrite(fd,"PING\r\n",6,100); return; } /* Receive the PONG command. */ if (server.repl_state == REDIS_REPL_RECEIVE_PONG) { char buf[1024]; /* Delete the readable event, we no longer need it now that there is * the PING reply to read. */ aeDeleteFileEvent(server.el,fd,AE_READABLE); /* Read the reply with explicit timeout. */ buf[0] = '\0'; if (syncReadLine(fd,buf,sizeof(buf), server.repl_syncio_timeout*1000) == -1) { redisLog(REDIS_WARNING, "I/O error reading PING reply from master: %s", strerror(errno)); goto error; } /* We don't care about the reply, it can be +PONG or an error since * the server requires AUTH. As long as it replies correctly, it's * fine from our point of view. */ if (buf[0] != '-' && buf[0] != '+') { redisLog(REDIS_WARNING,"Unexpected reply to PING from master."); goto error; } else { redisLog(REDIS_NOTICE, "Master replied to PING, replication can continue..."); } } /* AUTH with the master if required. */ if(server.masterauth) { err = sendSynchronousCommand(fd,"AUTH",server.masterauth,NULL); if (err) { redisLog(REDIS_WARNING,"Unable to AUTH to MASTER: %s",err); sdsfree(err); goto error; } } /* Set the slave port, so that Master's INFO command can list the * slave listening port correctly. */ { sds port = sdsfromlonglong(server.port); err = sendSynchronousCommand(fd,"REPLCONF","listening-port",port, NULL); sdsfree(port); /* Ignore the error if any, not all the Redis versions support * REPLCONF listening-port. */ if (err) { redisLog(REDIS_NOTICE,"(non critical): Master does not understand REPLCONF listening-port: %s", err); sdsfree(err); } } /* Issue the SYNC command */ if (syncWrite(fd,"SYNC\r\n",6,server.repl_syncio_timeout*1000) == -1) { redisLog(REDIS_WARNING,"I/O error writing to MASTER: %s", strerror(errno)); goto error; } /* Prepare a suitable temp file for bulk transfer */ while(maxtries--) { snprintf(tmpfile,256, "temp-%d.%ld.rdb",(int)server.unixtime,(long int)getpid()); dfd = open(tmpfile,O_CREAT|O_WRONLY|O_EXCL,0644); if (dfd != -1) break; sleep(1); } if (dfd == -1) { redisLog(REDIS_WARNING,"Opening the temp file needed for MASTER <-> SLAVE synchronization: %s",strerror(errno)); goto error; } /* Setup the non blocking download of the bulk file. */ if (aeCreateFileEvent(server.el,fd, AE_READABLE,readSyncBulkPayload,NULL) == AE_ERR) { redisLog(REDIS_WARNING, "Can't create readable event for SYNC: %s (fd=%d)", strerror(errno),fd); goto error; } server.repl_state = REDIS_REPL_TRANSFER; server.repl_transfer_size = -1; server.repl_transfer_read = 0; server.repl_transfer_last_fsync_off = 0; server.repl_transfer_fd = dfd; server.repl_transfer_lastio = server.unixtime; server.repl_transfer_tmpfile = zstrdup(tmpfile); return; error: close(fd); server.repl_transfer_s = -1; server.repl_state = REDIS_REPL_CONNECT; return; }
void syncWithMaster(aeEventLoop *el, int fd, void *privdata, int mask) { char tmpfile[256], *err; int dfd, maxtries = 5; int sockerr = 0; socklen_t errlen = sizeof(sockerr); REDIS_NOTUSED(el); REDIS_NOTUSED(privdata); REDIS_NOTUSED(mask); /* If this event fired after the user turned the instance into a master * with SLAVEOF NO ONE we must just return ASAP. */ if (server.repl_state == REDIS_REPL_NONE) { close(fd); return; } /* Check for errors in the socket. */ if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &sockerr, &errlen) == -1) sockerr = errno; if (sockerr) { aeDeleteFileEvent(server.el,fd,AE_READABLE|AE_WRITABLE); redisLog(REDIS_WARNING,"Error condition on socket for SYNC: %s", strerror(sockerr)); goto error; } /* If we were connecting, it's time to send a non blocking PING, we want to * make sure the master is able to reply before going into the actual * replication process where we have long timeouts in the order of * seconds (in the meantime the slave would block). */ //如果之前正在REDIS_REPL_CONNECTING,现在有可读可写事件了,说明连接成功了,下一步就是需要发送PING请求 if (server.repl_state == REDIS_REPL_CONNECTING) { redisLog(REDIS_NOTICE,"Non blocking connect for SYNC fired the event."); /* Delete the writable event so that the readable event remains * registered and we can wait for the PONG reply. */ aeDeleteFileEvent(server.el,fd,AE_WRITABLE); server.repl_state = REDIS_REPL_RECEIVE_PONG; /* Send the PING, don't check for errors at all, we have the timeout * that will take care about this. */ syncWrite(fd,"PING\r\n",6,100);//同步阻塞发送PING命令,这样服务端会返回"+PONG\r\n"字符串的 //这里实现的比较简单,就是发送完PING后,当连接可读可写时,再进syncWithMaster这个函数的时候 //下面的代码会判断PONG这个动作,然后就会阻塞去读取一行回复,看他是不是成功了。 return; } /* Receive the PONG command. */ if (server.repl_state == REDIS_REPL_RECEIVE_PONG) { char buf[1024]; //上面在REDIS_REPL_CONNECTING状态的时候给master发送了一行PING指令,这样master会返回"+PONG\r\n"的, //现在连接可读或者可写了,所以我们阻塞读取这么多数据,判断返回是否OK。 /* Delete the readable event, we no longer need it now that there is * the PING reply to read. */ aeDeleteFileEvent(server.el,fd,AE_READABLE); /* Read the reply with explicit timeout. */ buf[0] = '\0'; if (syncReadLine(fd,buf,sizeof(buf), server.repl_syncio_timeout*1000) == -1) { redisLog(REDIS_WARNING, "I/O error reading PING reply from master: %s", strerror(errno)); goto error; } /* We accept only two replies as valid, a positive +PONG reply * (we just check for "+") or an authentication error. * Note that older versions of Redis replied with "operation not * permitted" instead of using a proper error code, so we test * both. */ if (buf[0] != '+' && strncmp(buf,"-NOAUTH",7) != 0 && strncmp(buf,"-ERR operation not permitted",28) != 0) { redisLog(REDIS_WARNING,"Error reply to PING from master: '%s'",buf); goto error; } else { redisLog(REDIS_NOTICE, "Master replied to PING, replication can continue..."); } } /* AUTH with the master if required. */ if(server.masterauth) { err = sendSynchronousCommand(fd,"AUTH",server.masterauth,NULL); if (err) { redisLog(REDIS_WARNING,"Unable to AUTH to MASTER: %s",err); sdsfree(err); goto error; } } /* Set the slave port, so that Master's INFO command can list the * slave listening port correctly. */ { sds port = sdsfromlonglong(server.port); err = sendSynchronousCommand(fd,"REPLCONF","listening-port",port, NULL); sdsfree(port); /* Ignore the error if any, not all the Redis versions support * REPLCONF listening-port. */ if (err) { redisLog(REDIS_NOTICE,"(non critical): Master does not understand REPLCONF listening-port: %s", err); sdsfree(err); } } //到这里的话,连接肯定成功了,而且PING指令也都收到了回复。所以果断发送SYNC指令 /* Issue the SYNC command */ if (syncWrite(fd,"SYNC\r\n",6,server.repl_syncio_timeout*1000) == -1) { redisLog(REDIS_WARNING,"I/O error writing to MASTER: %s", strerror(errno)); goto error; } /* Prepare a suitable temp file for bulk transfer */ while(maxtries--) { snprintf(tmpfile,256, "temp-%d.%ld.rdb",(int)server.unixtime,(long int)getpid()); dfd = open(tmpfile,O_CREAT|O_WRONLY|O_EXCL,0644); if (dfd != -1) break; sleep(1); } if (dfd == -1) { redisLog(REDIS_WARNING,"Opening the temp file needed for MASTER <-> SLAVE synchronization: %s",strerror(errno)); goto error; } //SYNC命令已经发送了,以后的可读可写事件就依靠readSyncBulkPayload来读取解析了。 /* Setup the non blocking download of the bulk file. */ if (aeCreateFileEvent(server.el,fd, AE_READABLE,readSyncBulkPayload,NULL) == AE_ERR) { redisLog(REDIS_WARNING, "Can't create readable event for SYNC: %s (fd=%d)", strerror(errno),fd); goto error; } server.repl_state = REDIS_REPL_TRANSFER; server.repl_transfer_size = -1; server.repl_transfer_read = 0; server.repl_transfer_last_fsync_off = 0; server.repl_transfer_fd = dfd; server.repl_transfer_lastio = server.unixtime; server.repl_transfer_tmpfile = zstrdup(tmpfile); return; error: close(fd); server.repl_transfer_s = -1; server.repl_state = REDIS_REPL_CONNECT; return; }
static int slotsmgrt(redisClient *c, sds host, sds port, int fd, int dbid, int timeout, robj *keys[], robj *vals[], int n) { rio cmd; rioInitWithBuffer(&cmd, sdsempty()); redisAssertWithInfo(c, NULL, rioWriteBulkCount(&cmd, '*', 2)); redisAssertWithInfo(c, NULL, rioWriteBulkString(&cmd, "SELECT", 6)); redisAssertWithInfo(c, NULL, rioWriteBulkLongLong(&cmd, dbid)); redisAssertWithInfo(c, NULL, rioWriteBulkCount(&cmd, '*', 1 + 3 * n)); redisAssertWithInfo(c, NULL, rioWriteBulkString(&cmd, "SLOTSRESTORE", 12)); sds onekey = NULL; for (int i = 0; i < n; i ++) { robj *key = keys[i], *val = vals[i]; long long ttl = 0, expireat = getExpire(c->db, key); if (expireat != -1) { ttl = expireat - mstime(); if (ttl < 1) { ttl = 1; } } sds skey = key->ptr; redisAssertWithInfo(c, NULL, rioWriteBulkString(&cmd, skey, sdslen(skey))); redisAssertWithInfo(c, NULL, rioWriteBulkLongLong(&cmd, ttl)); do { rio pld; createDumpPayload(&pld, val); sds buf = pld.io.buffer.ptr; redisAssertWithInfo(c, NULL, rioWriteBulkString(&cmd, buf, sdslen(buf))); sdsfree(buf); } while (0); if (onekey == NULL) { onekey = skey; } } do { sds buf = cmd.io.buffer.ptr; size_t pos = 0, towrite; int nwritten = 0; while ((towrite = sdslen(buf) - pos) > 0) { towrite = (towrite > (64 * 1024) ? (64 * 1024) : towrite); nwritten = syncWrite(fd, buf + pos, towrite, timeout); if (nwritten != (signed)towrite) { redisLog(REDIS_WARNING, "slotsmgrt: writing to target %s:%s, error '%s', " "nkeys = %d, onekey = '%s', cmd.len = %ld, pos = %ld, towrite = %ld", host, port, server.neterr, n, onekey, sdslen(buf), pos, towrite); addReplySds(c, sdsnew("-IOERR error or timeout writing to target\r\n")); sdsfree(buf); return -1; } pos += nwritten; } sdsfree(buf); } while (0); do { char buf1[1024]; char buf2[1024]; if (syncReadLine(fd, buf1, sizeof(buf1), timeout) <= 0 || syncReadLine(fd, buf2, sizeof(buf2), timeout) <= 0) { redisLog(REDIS_WARNING, "slotsmgrt: reading from target %s:%s, error '%s', nkeys = %d, onekey = '%s'", host, port, server.neterr, n, onekey); addReplySds(c, sdsnew("-IOERR error or timeout reading from target\r\n")); return -1; } if (buf1[0] == '-' || buf2[0] == '-') { redisLog(REDIS_WARNING, "slotsmgrt: response from target %s:%s: rsp1 = '%s', rsp2 = '%s', nkeys = %d, onekey = '%s'", host, port, buf1, buf2, n, onekey); addReplyError(c, "error on slotsrestore"); return -1; } } while (0); redisLog(REDIS_VERBOSE, "slotsmgrt: migrate to %s:%s, nkeys = %d, onekey = '%s'", host, port, n, onekey); return 0; }
int syncWithMaster(void) { char buf[1024], tmpfile[256], authcmd[1024]; long dumpsize; int fd = anetTcpConnect(NULL,server.masterhost,server.masterport); int dfd, maxtries = 5; if (fd == -1) { redisLog(REDIS_WARNING,"Unable to connect to MASTER: %s", strerror(errno)); return REDIS_ERR; } /* AUTH with the master if required. */ if(server.masterauth) { snprintf(authcmd, 1024, "AUTH %s\r\n", server.masterauth); if (syncWrite(fd, authcmd, strlen(server.masterauth)+7, 5) == -1) { close(fd); redisLog(REDIS_WARNING,"Unable to AUTH to MASTER: %s", strerror(errno)); return REDIS_ERR; } /* Read the AUTH result. */ if (syncReadLine(fd,buf,1024,3600) == -1) { close(fd); redisLog(REDIS_WARNING,"I/O error reading auth result from MASTER: %s", strerror(errno)); return REDIS_ERR; } if (buf[0] != '+') { close(fd); redisLog(REDIS_WARNING,"Cannot AUTH to MASTER, is the masterauth password correct?"); return REDIS_ERR; } } /* Issue the SYNC command */ if (syncWrite(fd,"SYNC \r\n",7,5) == -1) { close(fd); redisLog(REDIS_WARNING,"I/O error writing to MASTER: %s", strerror(errno)); return REDIS_ERR; } /* Read the bulk write count */ if (syncReadLine(fd,buf,1024,3600) == -1) { close(fd); redisLog(REDIS_WARNING,"I/O error reading bulk count from MASTER: %s", strerror(errno)); return REDIS_ERR; } if (buf[0] == '-') { close(fd); redisLog(REDIS_WARNING,"MASTER aborted replication with an error: %s", buf+1); return REDIS_ERR; } else if (buf[0] != '$') { close(fd); redisLog(REDIS_WARNING,"Bad protocol from MASTER, the first byte is not '$', are you sure the host and port are right?"); return REDIS_ERR; } dumpsize = strtol(buf+1,NULL,10); redisLog(REDIS_NOTICE,"Receiving %ld bytes data dump from MASTER",dumpsize); /* Read the bulk write data on a temp file */ while(maxtries--) { snprintf(tmpfile,256, "temp-%d.%ld.rdb",(int)time(NULL),(long int)getpid()); dfd = open(tmpfile,O_CREAT|O_WRONLY|O_EXCL,0644); if (dfd != -1) break; sleep(1); } if (dfd == -1) { close(fd); redisLog(REDIS_WARNING,"Opening the temp file needed for MASTER <-> SLAVE synchronization: %s",strerror(errno)); return REDIS_ERR; } while(dumpsize) { int nread, nwritten; nread = read(fd,buf,(dumpsize < 1024)?dumpsize:1024); if (nread <= 0) { redisLog(REDIS_WARNING,"I/O error trying to sync with MASTER: %s", (nread == -1) ? strerror(errno) : "connection lost"); close(fd); close(dfd); return REDIS_ERR; } nwritten = write(dfd,buf,nread); if (nwritten == -1) { redisLog(REDIS_WARNING,"Write error writing to the DB dump file needed for MASTER <-> SLAVE synchrnonization: %s", strerror(errno)); close(fd); close(dfd); return REDIS_ERR; } dumpsize -= nread; } close(dfd); if (rename(tmpfile,server.dbfilename) == -1) { redisLog(REDIS_WARNING,"Failed trying to rename the temp DB into dump.rdb in MASTER <-> SLAVE synchronization: %s", strerror(errno)); unlink(tmpfile); close(fd); return REDIS_ERR; } emptyDb(); if (rdbLoad(server.dbfilename) != REDIS_OK) { redisLog(REDIS_WARNING,"Failed trying to load the MASTER synchronization DB from disk"); close(fd); return REDIS_ERR; } server.master = createClient(fd); server.master->flags |= REDIS_MASTER; server.master->authenticated = 1; server.replstate = REDIS_REPL_CONNECTED; return REDIS_OK; }