/* Read the specified amount of bytes from 'fd'. If all the bytes are read * within 'timeout' milliseconds the operation succeed and 'size' is returned. * Otherwise the operation fails, -1 is returned, and an unspecified amount of * data could be read from the file descriptor. */ ssize_t syncRead(int fd, char *ptr, ssize_t size, long long timeout) { ssize_t nread, totread = 0; long long start = mstime(); long long remaining = timeout; if (size == 0) return 0; while(1) { long long wait = (remaining > SYNCIO__RESOLUTION) ? remaining : SYNCIO__RESOLUTION; long long elapsed; /* Optimistically try to read before checking if the file descriptor * is actually readable. At worst we get EAGAIN. */ nread = read(fd,ptr,size); if (nread == 0) return -1; /* short read. */ if (nread == -1) { if (errno != EAGAIN) return -1; } else { ptr += nread; size -= nread; totread += nread; } if (size == 0) return totread; /* Wait */ aeWait(fd,AE_READABLE,wait); elapsed = mstime() - start; if (elapsed >= timeout) { errno = ETIMEDOUT; return -1; } remaining = timeout - elapsed; } }
/* Write the specified payload to 'fd'. If writing the whole payload will be * done within 'timeout' milliseconds the operation succeeds and 'size' is * returned. Otherwise the operation fails, -1 is returned, and an unspecified * partial write could be performed against the file descriptor. */ ssize_t syncWrite(int fd, char *ptr, ssize_t size, long long timeout) { ssize_t nwritten, ret = size; long long start = mstime(); long long remaining = timeout; while(1) { long long wait = (remaining > SYNCIO__RESOLUTION) ? remaining : SYNCIO__RESOLUTION; long long elapsed; /* Optimistically try to write before checking if the file descriptor * is actually writable. At worst we get EAGAIN. */ nwritten = write(fd,ptr,size); if (nwritten == -1) { if (errno != EAGAIN) return -1; } else { ptr += nwritten; size -= nwritten; } if (size == 0) return ret; /* Wait */ aeWait(fd,AE_WRITABLE,wait); elapsed = mstime() - start; if (elapsed >= timeout) { errno = ETIMEDOUT; return -1; } remaining = timeout - elapsed; } }
/* Read the specified amount of bytes from 'fd'. If all the bytes are read * within 'timeout' milliseconds the operation succeed and 'size' is returned. * Otherwise the operation fails, -1 is returned, and an unspecified amount of * data could be read from the file descriptor. */ ssize_t syncRead(int fd, char *ptr, ssize_t size, long long timeout) { ssize_t nread, totread = 0; long long start = mstime(); long long remaining = timeout; if (size == 0) return 0; while(1) { long long wait = (remaining > REDIS_SYNCIO_RESOLUTION) ? remaining : REDIS_SYNCIO_RESOLUTION; long long elapsed; /* Optimistically try to read before checking if the file descriptor * is actually readable. At worst we get EAGAIN. */ #ifdef _WIN32 nread = recv((SOCKET)fd,ptr,size,0); #else nread = read(fd,ptr,size); #endif if (nread == 0) { redisLog(REDIS_WARNING,"syncRead returned 0"); return -1; /* short read. */ } if (nread == -1) { #ifdef _WIN32 errno = WSAGetLastError(); if ((errno == ENOENT) || (errno == WSAEWOULDBLOCK)) { errno = EAGAIN; } #endif if (errno != EAGAIN) { redisLog(REDIS_WARNING,"syncRead returned -1 : %d", errno); return -1; } } else { ptr += nread; size -= nread; totread += nread; } if (size == 0) return totread; /* Wait */ aeWait(fd,AE_READABLE,wait); elapsed = mstime() - start; if (elapsed >= timeout) { errno = ETIMEDOUT; return -1; } remaining = timeout - elapsed; } }
int syncWrite(int fd, char *ptr, ssize_t size, int timeout) { ssize_t nwritten, ret = size; time_t start = time(NULL); timeout++; while(size) { if (aeWait(fd,AE_WRITABLE,1000) & AE_WRITABLE) { nwritten = write(fd,ptr,size); if (nwritten == -1) return -1; ptr += nwritten; size -= nwritten; } if ((time(NULL)-start) > timeout) { errno = ETIMEDOUT; return -1; } } return ret; }
int syncRead(int fd, char *ptr, ssize_t size, int timeout) { ssize_t nread, totread = 0; time_t start = time(NULL); timeout++; while(size) { if (aeWait(fd,AE_READABLE,1000) & AE_READABLE) { nread = read(fd,ptr,size); if (nread <= 0) return -1; ptr += nread; size -= nread; totread += nread; } if ((time(NULL)-start) > timeout) { errno = ETIMEDOUT; return -1; } } return totread; }
/* Write the specified payload to 'fd'. If writing the whole payload will be * done within 'timeout' milliseconds the operation succeeds and 'size' is * returned. Otherwise the operation fails, -1 is returned, and an unspecified * partial write could be performed against the file descriptor. */ ssize_t syncWrite(int fd, char *ptr, ssize_t size, long long timeout) { ssize_t nwritten, ret = size; long long start = mstime(); long long remaining = timeout; while(1) { long long wait = (remaining > REDIS_SYNCIO_RESOLUTION) ? remaining : REDIS_SYNCIO_RESOLUTION; long long elapsed; /* Optimistically try to write before checking if the file descriptor * is actually writable. At worst we get EAGAIN. */ #ifdef _WIN32 nwritten = send((SOCKET)fd,ptr,size,0); #else nwritten = write(fd,ptr,size); #endif if (nwritten == -1) { #ifdef _WIN32 errno = WSAGetLastError(); if ((errno == ENOENT) || (errno == WSAEWOULDBLOCK)) { errno = EAGAIN; } #endif if (errno != EAGAIN) return -1; } else { ptr += nwritten; size -= nwritten; } if (size == 0) return ret; /* Wait */ aeWait(fd,AE_WRITABLE,wait); elapsed = mstime() - start; if (elapsed >= timeout) { errno = ETIMEDOUT; return -1; } remaining = timeout - elapsed; } }
static int slotsmgrt_get_socket(redisClient *c, sds host, sds port, int timeout) { sds name = sdsempty(); name = sdscatlen(name, host, sdslen(host)); name = sdscatlen(name, ":", 1); name = sdscatlen(name, port, sdslen(port)); slotsmgrt_sockfd *pfd = dictFetchValue(server.slotsmgrt_cached_sockfds, name); if (pfd != NULL) { sdsfree(name); pfd->lasttime = server.unixtime; return pfd->fd; } int fd = anetTcpNonBlockConnect(server.neterr, host, atoi(port)); if (fd == -1) { redisLog(REDIS_WARNING, "slotsmgrt: connect to target %s:%s, error = '%s'", host, port, server.neterr); sdsfree(name); addReplyErrorFormat(c,"Can't connect to target node: %s", server.neterr); return -1; } anetEnableTcpNoDelay(server.neterr, fd); if ((aeWait(fd, AE_WRITABLE, timeout) & AE_WRITABLE) == 0) { redisLog(REDIS_WARNING, "slotsmgrt: connect to target %s:%s, aewait error = '%s'", host, port, server.neterr); sdsfree(name); close(fd); addReplySds(c, sdsnew("-IOERR error or timeout connecting to the client\r\n")); return -1; } redisLog(REDIS_WARNING, "slotsmgrt: connect to target %s:%s", host, port); pfd = zmalloc(sizeof(*pfd)); pfd->fd = fd; pfd->lasttime = server.unixtime; dictAdd(server.slotsmgrt_cached_sockfds, name, pfd); return fd; }
static void pipeMode(void) { int fd = context->fd; long long errors = 0, replies = 0, obuf_len = 0, obuf_pos = 0; char ibuf[1024*16], obuf[1024*16]; /* Input and output buffers */ char aneterr[ANET_ERR_LEN]; redisReader *reader = redisReaderCreate(); redisReply *reply; int eof = 0; /* True once we consumed all the standard input. */ int done = 0; char magic[20]; /* Special reply we recognize. */ srand(time(NULL)); /* Use non blocking I/O. */ if (anetNonBlock(aneterr,fd) == ANET_ERR) { fprintf(stderr, "Can't set the socket in non blocking mode: %s\n", aneterr); exit(1); } /* Transfer raw protocol and read replies from the server at the same * time. */ while(!done) { int mask = AE_READABLE; if (!eof || obuf_len != 0) mask |= AE_WRITABLE; mask = aeWait(fd,mask,1000); /* Handle the readable state: we can read replies from the server. */ if (mask & AE_READABLE) { ssize_t nread; /* Read from socket and feed the hiredis reader. */ do { nread = read(fd,ibuf,sizeof(ibuf)); if (nread == -1 && errno != EAGAIN && errno != EINTR) { fprintf(stderr, "Error reading from the server: %s\n", strerror(errno)); exit(1); } if (nread > 0) redisReaderFeed(reader,ibuf,nread); } while(nread > 0); /* Consume replies. */ do { if (redisReaderGetReply(reader,(void**)&reply) == REDIS_ERR) { fprintf(stderr, "Error reading replies from server\n"); exit(1); } if (reply) { if (reply->type == REDIS_REPLY_ERROR) { fprintf(stderr,"%s\n", reply->str); errors++; } else if (eof && reply->type == REDIS_REPLY_STRING && reply->len == 20) { /* Check if this is the reply to our final ECHO * command. If so everything was received * from the server. */ if (memcmp(reply->str,magic,20) == 0) { printf("Last reply received from server.\n"); done = 1; replies--; } } replies++; freeReplyObject(reply); } } while(reply); } /* Handle the writable state: we can send protocol to the server. */ if (mask & AE_WRITABLE) { while(1) { /* Transfer current buffer to server. */ if (obuf_len != 0) { ssize_t nwritten = write(fd,obuf+obuf_pos,obuf_len); if (nwritten == -1) { if (errno != EAGAIN && errno != EINTR) { fprintf(stderr, "Error writing to the server: %s\n", strerror(errno)); exit(1); } else { nwritten = 0; } } obuf_len -= nwritten; obuf_pos += nwritten; if (obuf_len != 0) break; /* Can't accept more data. */ } /* If buffer is empty, load from stdin. */ if (obuf_len == 0 && !eof) { ssize_t nread = read(STDIN_FILENO,obuf,sizeof(obuf)); if (nread == 0) { char echo[] = "*2\r\n$4\r\nECHO\r\n$20\r\n01234567890123456789\r\n"; int j; eof = 1; /* Everything transfered, so we queue a special * ECHO command that we can match in the replies * to make sure everything was read from the server. */ for (j = 0; j < 20; j++) magic[j] = rand() & 0xff; memcpy(echo+19,magic,20); memcpy(obuf,echo,sizeof(echo)-1); obuf_len = sizeof(echo)-1; obuf_pos = 0; printf("All data transferred. Waiting for the last reply...\n"); } else if (nread == -1) { fprintf(stderr, "Error reading from stdin: %s\n", strerror(errno)); exit(1); } else { obuf_len = nread; obuf_pos = 0; } } if (obuf_len == 0 && eof) break; } } } redisReaderFree(reader); printf("errors: %lld, replies: %lld\n", errors, replies); if (errors) exit(1); else exit(0); }