@@ -973,10 +973,41 @@ void removeRDBUsedToSyncReplicas(void) {
973973 }
974974}
975975
976+ #if HAVE_SENDFILE
977+ /* Implements redis_sendfile to transfer data between file descriptors and
978+ * avoid transferring data to and from user space.
979+ *
980+ * The function prototype is just like sendfile(2) on Linux. in_fd is a file
981+ * descriptor opened for reading and out_fd is a descriptor opened for writing.
982+ * offset specifies where to start reading data from in_fd. count is the number
983+ * of bytes to copy between the file descriptors.
984+ *
985+ * The return value is the number of bytes written to out_fd, if the transfer
986+ * was successful. On error, -1 is returned, and errno is set appropriately. */
987+ ssize_t redis_sendfile (int out_fd , int in_fd , off_t offset , size_t count ) {
988+ #if defined(__linux__ )
989+ #include <sys/sendfile.h>
990+ return sendfile (out_fd , in_fd , & offset , count );
991+
992+ #elif defined(__APPLE__ )
993+ off_t len = count ;
994+ /* Notice that it may return -1 and errno is set to EAGAIN even if some
995+ * bytes have been sent successfully and the len argument is set correctly
996+ * when using a socket marked for non-blocking I/O. */
997+ if (sendfile (in_fd , out_fd , offset , & len , NULL , 0 ) == -1 &&
998+ errno != EAGAIN ) return -1 ;
999+ else
1000+ return (ssize_t )len ;
1001+
1002+ #endif
1003+ errno = ENOSYS ;
1004+ return -1 ;
1005+ }
1006+ #endif
1007+
9761008void sendBulkToSlave (connection * conn ) {
9771009 client * slave = connGetPrivateData (conn );
978- char buf [PROTO_IOBUF_LEN ];
979- ssize_t nwritten , buflen ;
1010+ ssize_t nwritten ;
9801011
9811012 /* Before sending the RDB file, we send the preamble as configured by the
9821013 * replication process. Currently the preamble is just the bulk count of
@@ -1002,6 +1033,21 @@ void sendBulkToSlave(connection *conn) {
10021033 }
10031034
10041035 /* If the preamble was already transferred, send the RDB bulk data. */
1036+ #if HAVE_SENDFILE
1037+ if ((nwritten = redis_sendfile (conn -> fd ,slave -> repldbfd ,
1038+ slave -> repldboff ,PROTO_IOBUF_LEN )) == -1 )
1039+ {
1040+ if (errno != EAGAIN ) {
1041+ serverLog (LL_WARNING ,"Sendfile error sending DB to replica: %s" ,
1042+ strerror (errno ));
1043+ freeClient (slave );
1044+ }
1045+ return ;
1046+ }
1047+ #else
1048+ ssize_t buflen ;
1049+ char buf [PROTO_IOBUF_LEN ];
1050+
10051051 lseek (slave -> repldbfd ,slave -> repldboff ,SEEK_SET );
10061052 buflen = read (slave -> repldbfd ,buf ,PROTO_IOBUF_LEN );
10071053 if (buflen <= 0 ) {
@@ -1018,6 +1064,7 @@ void sendBulkToSlave(connection *conn) {
10181064 }
10191065 return ;
10201066 }
1067+ #endif
10211068 slave -> repldboff += nwritten ;
10221069 server .stat_net_output_bytes += nwritten ;
10231070 if (slave -> repldboff == slave -> repldbsize ) {
0 commit comments