Fix for issue #59. Generated FDs are used everywhere until a SOCKET handle is used by the Winsock APIs. The win32_socketmap code generates the simulated FDs and handles the mapping from these to socket handles.
This commit is contained in:
Vendored
+2
@@ -44,6 +44,7 @@
|
||||
#include "sds.h"
|
||||
#ifdef _WIN32
|
||||
#include "../../src/win32fixes.h"
|
||||
#include "../../src/win32_socketmap.h"
|
||||
#endif
|
||||
|
||||
static redisReply *createReplyObject(int type);
|
||||
@@ -1025,6 +1026,7 @@ void redisFree(redisContext *c) {
|
||||
if (c->fd > 0)
|
||||
#ifdef _WIN32
|
||||
closesocket(c->fd);
|
||||
smRemoveSocket(c->fd);
|
||||
#else
|
||||
close(c->fd);
|
||||
#endif
|
||||
|
||||
Vendored
+10
@@ -60,6 +60,7 @@
|
||||
#include "sds.h"
|
||||
#ifdef _WIN32
|
||||
#include "../../src/win32fixes.h"
|
||||
#include "../../src/win32_socketmap.h"
|
||||
#endif
|
||||
|
||||
/* Defined in hiredis.c */
|
||||
@@ -104,6 +105,7 @@ static int redisCreateSocket(redisContext *c, int type) {
|
||||
if (setsockopt((int)s, SOL_SOCKET, SO_REUSEADDR, (const char *) &on, sizeof(on)) == -1) {
|
||||
__redisSetError(c,REDIS_ERR_IO,NULL);
|
||||
closesocket(s);
|
||||
smRemoveSocket(s);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
}
|
||||
@@ -143,6 +145,7 @@ static int redisSetBlocking(redisContext *c, int fd, int blocking) {
|
||||
__redisSetError(c,REDIS_ERR_IO,
|
||||
sdscatprintf(sdsempty(), "ioctlsocket(FIONBIO): %d\n", errno));
|
||||
closesocket(fd);
|
||||
smRemoveSocket(fd);
|
||||
return REDIS_ERR;
|
||||
};
|
||||
|
||||
@@ -183,6 +186,7 @@ static int redisSetTcpNoDelay(redisContext *c, int fd) {
|
||||
__redisSetError(c,REDIS_ERR_IO,
|
||||
sdscatprintf(sdsempty(), "setsockopt(TCP_NODELAY): %d", (int)GetLastError()));
|
||||
closesocket(fd);
|
||||
smRemoveSocket(fd);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
return REDIS_OK;
|
||||
@@ -218,6 +222,7 @@ static int redisContextWaitReady(redisContext *c, int fd, const struct timeval *
|
||||
if (select(FD_SETSIZE, NULL, &wfd, NULL, toptr) == -1) {
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"select(2)");
|
||||
closesocket(fd);
|
||||
smRemoveSocket(fd);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
@@ -225,6 +230,7 @@ static int redisContextWaitReady(redisContext *c, int fd, const struct timeval *
|
||||
errno = WSAGetLastError();
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
||||
closesocket(fd);
|
||||
smRemoveSocket(fd);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
@@ -236,6 +242,7 @@ static int redisContextWaitReady(redisContext *c, int fd, const struct timeval *
|
||||
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
||||
closesocket(fd);
|
||||
smRemoveSocket(fd);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
#else
|
||||
@@ -298,6 +305,7 @@ int redisCheckSocketError(redisContext *c, int fd) {
|
||||
errno = WSAGetLastError();
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"getsockopt(SO_ERROR)");
|
||||
closesocket(fd);
|
||||
smRemoveSocket(fd);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
#else
|
||||
@@ -374,6 +382,7 @@ int redisContextPreConnectTcp(redisContext *c, const char *addr, int port,
|
||||
__redisSetError(c,REDIS_ERR_OTHER,
|
||||
sdscatprintf(sdsempty(),"can't resolve: %s\n", addr));
|
||||
closesocket(s);
|
||||
smRemoveSocket(s);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
memcpy(&sa->sin_addr, he->h_addr, sizeof(struct in_addr));
|
||||
@@ -415,6 +424,7 @@ int redisContextConnectTcp(redisContext *c, const char *addr, int port, struct t
|
||||
__redisSetError(c,REDIS_ERR_OTHER,
|
||||
sdscatprintf(sdsempty(),"can't resolve: %s\n", addr));
|
||||
closesocket(s);
|
||||
smRemoveSocket(s);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
memcpy(&sa.sin_addr, he->h_addr, sizeof(struct in_addr));
|
||||
|
||||
@@ -167,8 +167,10 @@
|
||||
<ClCompile Include="..\..\src\ae.c" />
|
||||
<ClCompile Include="..\..\src\anet.c" />
|
||||
<ClCompile Include="..\..\src\redis-benchmark.c" />
|
||||
<ClCompile Include="..\..\src\RedisLog.c" />
|
||||
<ClCompile Include="..\..\src\sds.c" />
|
||||
<ClCompile Include="..\..\src\win32fixes.c" />
|
||||
<ClCompile Include="..\..\src\win32_socketmap.cpp" />
|
||||
<ClCompile Include="..\..\src\win32_wsiocp.c" />
|
||||
<ClCompile Include="..\..\src\zmalloc.c" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c), Microsoft Open Technologies, Inc.
|
||||
* All rights reserved.
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/* Log levels */
|
||||
#define REDIS_DEBUG 0
|
||||
#define REDIS_VERBOSE 1
|
||||
#define REDIS_NOTICE 2
|
||||
#define REDIS_WARNING 3
|
||||
#define REDIS_LOG_RAW (1<<10) /* Modifier to log without timestamp */
|
||||
|
||||
#define REDIS_MAX_LOGMSG_LEN 1024 /* Default maximum length of syslog messages */
|
||||
|
||||
void redisLog(int level, const char *fmt, ...);
|
||||
void redisLogRaw(int level, const char *msg);
|
||||
void redisLogFromHandler(int level, const char *msg);
|
||||
|
||||
void SetVerbosity(int verbosity);
|
||||
@@ -2,6 +2,9 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2012
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RedisServer", "RedisServer.vcxproj", "{46842776-68A5-EC98-6A09-1859BBFC73AA}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{170B0909-5F75-467F-9501-C99DEC16C6DC} = {170B0909-5F75-467F-9501-C99DEC16C6DC}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hiredis", "hiredis\hiredis.vcxproj", "{13E85053-54B3-487B-8DDB-3430B1C1B3BF}"
|
||||
EndProject
|
||||
|
||||
@@ -177,6 +177,7 @@
|
||||
<ClCompile Include="..\src\rand.c" />
|
||||
<ClCompile Include="..\src\rdb.c" />
|
||||
<ClCompile Include="..\src\redis.c" />
|
||||
<ClCompile Include="..\src\RedisLog.c" />
|
||||
<ClCompile Include="..\src\release.c" />
|
||||
<ClCompile Include="..\src\replication.c" />
|
||||
<ClCompile Include="..\src\rio.c" />
|
||||
@@ -196,6 +197,7 @@
|
||||
<ClCompile Include="..\src\win32fixes.c" />
|
||||
<ClCompile Include="..\src\win32_bksv.c" />
|
||||
<ClCompile Include="..\src\win32_cow.c" />
|
||||
<ClCompile Include="..\src\win32_socketmap.cpp" />
|
||||
<ClCompile Include="..\src\win32_wsiocp.c" />
|
||||
<ClCompile Include="..\src\ziplist.c" />
|
||||
<ClCompile Include="..\src\zipmap.c" />
|
||||
@@ -218,6 +220,7 @@
|
||||
<ClInclude Include="..\src\rand.h" />
|
||||
<ClInclude Include="..\src\rdb.h" />
|
||||
<ClInclude Include="..\src\redis.h" />
|
||||
<ClInclude Include="..\src\redisLog.h" />
|
||||
<ClInclude Include="..\src\rio.h" />
|
||||
<ClInclude Include="..\src\sds.h" />
|
||||
<ClInclude Include="..\src\sha1.h" />
|
||||
@@ -229,6 +232,7 @@
|
||||
<ClInclude Include="..\src\win32fixes.h" />
|
||||
<ClInclude Include="..\src\win32_bksv.h" />
|
||||
<ClInclude Include="..\src\win32_cow.h" />
|
||||
<ClInclude Include="..\src\win32_socketmap.h" />
|
||||
<ClInclude Include="..\src\win32_wsiocp.h" />
|
||||
<ClInclude Include="..\src\ziplist.h" />
|
||||
<ClInclude Include="..\src\zipmap.h" />
|
||||
|
||||
@@ -151,6 +151,8 @@
|
||||
<ClCompile Include="..\..\deps\hiredis\hiredis.c" />
|
||||
<ClCompile Include="..\..\deps\hiredis\net.c" />
|
||||
<ClCompile Include="..\..\deps\hiredis\sds.c" />
|
||||
<ClCompile Include="..\..\src\RedisLog.c" />
|
||||
<ClCompile Include="..\..\src\win32_socketmap.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\deps\hiredis\async.h" />
|
||||
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (c), Microsoft Open Technologies, Inc.
|
||||
* All rights reserved.
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include "redisLog.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include <process.h>
|
||||
#include "win32Fixes.h"
|
||||
#include <time.h>
|
||||
|
||||
|
||||
static int verbosity = REDIS_WARNING;
|
||||
static char* logFile = NULL;
|
||||
|
||||
void setLogVerbosityLevel(int level)
|
||||
{
|
||||
verbosity = level;
|
||||
}
|
||||
|
||||
void setLogFile(const char* logFileName)
|
||||
{
|
||||
if (logFile != NULL) {
|
||||
free((void*)logFile);
|
||||
logFile = NULL;
|
||||
}
|
||||
logFile = (char*)malloc(strlen(logFile));
|
||||
if (logFile==NULL) {
|
||||
redisLog(REDIS_WARNING, "memory allocation failure");
|
||||
return;
|
||||
}
|
||||
strcpy (logFile,logFileName);
|
||||
}
|
||||
|
||||
void redisLogRaw(int level, const char *msg) {
|
||||
#ifndef _WIN32
|
||||
const int syslogLevelMap[] = { LOG_DEBUG, LOG_INFO, LOG_NOTICE, LOG_WARNING };
|
||||
#endif
|
||||
const char *c = ".-*#";
|
||||
FILE *fp;
|
||||
char buf[64];
|
||||
int rawmode = (level & REDIS_LOG_RAW);
|
||||
|
||||
level &= 0xff; /* clear flags */
|
||||
if (level < verbosity) return;
|
||||
|
||||
fp = (logFile == NULL) ? stdout : fopen(logFile,"a");
|
||||
if (!fp) return;
|
||||
|
||||
if (rawmode) {
|
||||
fprintf(fp,"%s",msg);
|
||||
} else {
|
||||
int off;
|
||||
#ifdef _WIN32
|
||||
time_t secs;
|
||||
unsigned int usecs;
|
||||
struct tm * now ;
|
||||
|
||||
secs = gettimeofdaysecs(&usecs);
|
||||
now = localtime(&secs);
|
||||
off = (int)strftime(buf,sizeof(buf),"%d %b %H:%M:%S.",now);
|
||||
snprintf(buf+off,sizeof(buf)-off,"%03d",usecs/1000);
|
||||
#else
|
||||
struct timeval tv;
|
||||
|
||||
gettimeofday(&tv,NULL);
|
||||
off = strftime(buf,sizeof(buf),"%d %b %H:%M:%S.",localtime(&tv.tv_sec));
|
||||
snprintf(buf+off,sizeof(buf)-off,"%03d",(int)tv.tv_usec/1000);
|
||||
#endif
|
||||
fprintf(fp,"[%d] %s %c %s\n",(int)getpid(),buf,c[level],msg);
|
||||
}
|
||||
fflush(fp);
|
||||
|
||||
if (logFile) fclose(fp);
|
||||
#ifndef _WIN32
|
||||
if (server.syslog_enabled) syslog(syslogLevelMap[level], "%s", msg);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Like redisLogRaw() but with printf-alike support. This is the function that
|
||||
* is used across the code. The raw version is only used in order to dump
|
||||
* the INFO output on crash. */
|
||||
void redisLog(int level, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
char msg[REDIS_MAX_LOGMSG_LEN];
|
||||
|
||||
if ((level&0xff) < verbosity) return;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(msg, sizeof(msg), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
redisLogRaw(level,msg);
|
||||
}
|
||||
@@ -36,6 +36,8 @@
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <poll.h>
|
||||
#else
|
||||
#include "win32_socketmap.h"
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -46,6 +48,8 @@
|
||||
#include "zmalloc.h"
|
||||
#include "config.h"
|
||||
|
||||
|
||||
|
||||
/* Include the best multiplexing layer supported by this system.
|
||||
* The following should be ordered by performances, descending. */
|
||||
#ifdef _WIN32
|
||||
@@ -112,11 +116,26 @@ int aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask,
|
||||
aeFileProc *proc, void *clientData)
|
||||
{
|
||||
aeFileEvent *fe;
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
if (smGetSocketCount() >= eventLoop->setsize) {
|
||||
errno = ERANGE;
|
||||
return AE_ERR;
|
||||
}
|
||||
|
||||
if(smLookupFD(fd) == -1 ) {
|
||||
errno = ERANGE;
|
||||
return AE_ERR;
|
||||
}
|
||||
fe = &eventLoop->events[smLookupFD(fd)];
|
||||
#else
|
||||
if (fd >= eventLoop->setsize) {
|
||||
errno = ERANGE;
|
||||
return AE_ERR;
|
||||
}
|
||||
fe = &eventLoop->events[fd];
|
||||
#endif
|
||||
|
||||
if (aeApiAddEvent(eventLoop, fd, mask) == -1)
|
||||
return AE_ERR;
|
||||
@@ -132,8 +151,17 @@ int aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask,
|
||||
void aeDeleteFileEvent(aeEventLoop *eventLoop, int fd, int mask)
|
||||
{
|
||||
aeFileEvent *fe;
|
||||
#ifdef _WIN32
|
||||
if (smGetSocketCount() >= eventLoop->setsize) return;
|
||||
|
||||
if(smLookupFD(fd) == -1 ) return;
|
||||
|
||||
fe = &eventLoop->events[smLookupFD(fd)];
|
||||
#else
|
||||
if (fd >= eventLoop->setsize) return;
|
||||
|
||||
fe = &eventLoop->events[fd];
|
||||
#endif
|
||||
|
||||
if (fe->mask == AE_NONE) return;
|
||||
fe->mask = fe->mask & (~mask);
|
||||
@@ -150,8 +178,17 @@ void aeDeleteFileEvent(aeEventLoop *eventLoop, int fd, int mask)
|
||||
|
||||
int aeGetFileEvents(aeEventLoop *eventLoop, int fd) {
|
||||
aeFileEvent *fe;
|
||||
#ifdef _WIN32
|
||||
if(smLookupFD(fd) == -1 ) DebugBreak();
|
||||
|
||||
if (smGetSocketCount() >= eventLoop->setsize) return 0;
|
||||
|
||||
fe = &eventLoop->events[smLookupFD(fd)];
|
||||
#else
|
||||
if (fd >= eventLoop->setsize) return 0;
|
||||
|
||||
fe = &eventLoop->events[fd];
|
||||
#endif
|
||||
|
||||
return fe->mask;
|
||||
}
|
||||
@@ -382,11 +419,24 @@ int aeProcessEvents(aeEventLoop *eventLoop, int flags)
|
||||
|
||||
numevents = aeApiPoll(eventLoop, tvp);
|
||||
for (j = 0; j < numevents; j++) {
|
||||
aeFileEvent *fe = &eventLoop->events[eventLoop->fired[j].fd];
|
||||
aeFileEvent *fe;
|
||||
int mask = eventLoop->fired[j].mask;
|
||||
int fd = eventLoop->fired[j].fd;
|
||||
int rfired = 0;
|
||||
|
||||
#ifdef _WIN32
|
||||
if(smLookupFD(eventLoop->fired[j].fd) == -1 ) {
|
||||
// We may have already processed a socket close request
|
||||
// before a subscription notification gets sent out
|
||||
processed++;
|
||||
continue;
|
||||
}
|
||||
|
||||
fe = &eventLoop->events[smLookupFD(eventLoop->fired[j].fd)];
|
||||
#else
|
||||
fe = &eventLoop->events[eventLoop->fired[j].fd];
|
||||
#endif
|
||||
|
||||
/* note the fe->mask & mask & ... code: maybe an already processed
|
||||
* event removed an element that fired and we still didn't
|
||||
* processed, so we check if the event is still valid. */
|
||||
|
||||
+12
-2
@@ -49,6 +49,7 @@
|
||||
#ifdef _WIN32
|
||||
#include "win32fixes.h"
|
||||
#define ANET_NOTUSED(V) ((void) V)
|
||||
#include "win32_socketmap.h"
|
||||
#endif
|
||||
|
||||
#include "anet.h"
|
||||
@@ -245,9 +246,12 @@ static int anetTcpGenericConnect(char *err, char *addr, int port, int flags) {
|
||||
struct sockaddr_in sa;
|
||||
unsigned long inAddress;
|
||||
|
||||
if ((s = anetCreateSocket(err,AF_INET)) == ANET_ERR)
|
||||
if ((s = anetCreateSocket(err,AF_INET)) == ANET_ERR) {
|
||||
return ANET_ERR;
|
||||
|
||||
}
|
||||
else {
|
||||
smAddSocket(s);
|
||||
}
|
||||
sa.sin_family = AF_INET;
|
||||
sa.sin_port = htons((u_short)port);
|
||||
inAddress = inet_addr(addr);
|
||||
@@ -258,6 +262,7 @@ static int anetTcpGenericConnect(char *err, char *addr, int port, int flags) {
|
||||
if (he == NULL) {
|
||||
anetSetError(err, "can't resolve: %s\n", addr);
|
||||
closesocket(s);
|
||||
smRemoveSocket(s);
|
||||
return ANET_ERR;
|
||||
}
|
||||
memcpy(&sa.sin_addr, he->h_addr, sizeof(struct in_addr));
|
||||
@@ -274,6 +279,7 @@ static int anetTcpGenericConnect(char *err, char *addr, int port, int flags) {
|
||||
|
||||
anetSetError(err, "connect: %d\n", errno);
|
||||
closesocket(s);
|
||||
smRemoveSocket(s);
|
||||
return ANET_ERR;
|
||||
}
|
||||
|
||||
@@ -435,12 +441,14 @@ static int anetListen(char *err, int s, struct sockaddr *sa, socklen_t len) {
|
||||
errno = WSAGetLastError();
|
||||
anetSetError(err, "bind error: %d\n", errno);
|
||||
closesocket((SOCKET)s);
|
||||
smRemoveSocket(s);
|
||||
return ANET_ERR;
|
||||
}
|
||||
if (aeWinListen((SOCKET)s, 511) == SOCKET_ERROR) { /* the magic 511 constant is from nginx */
|
||||
errno = WSAGetLastError();
|
||||
anetSetError(err, "listen error: %d\n", errno);
|
||||
closesocket((SOCKET)s);
|
||||
smRemoveSocket(s);
|
||||
return ANET_ERR;
|
||||
}
|
||||
return ANET_OK;
|
||||
@@ -457,6 +465,8 @@ int anetTcpServer(char *err, int port, char *bindaddr)
|
||||
if ((s = anetCreateSocket(err,AF_INET)) == ANET_ERR)
|
||||
return ANET_ERR;
|
||||
|
||||
smAddSocket(s);
|
||||
|
||||
/* Override for SO_REUSEADDR for windows server socks */
|
||||
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n)) == SOCKET_ERROR) {
|
||||
errno = WSAGetLastError();
|
||||
|
||||
@@ -157,6 +157,9 @@ void loadServerConfigFromString(char *config) {
|
||||
"Can't open the log file: %s", strerror(errno));
|
||||
goto loaderr;
|
||||
}
|
||||
else {
|
||||
setLogFile( server.logfile );
|
||||
}
|
||||
fclose(logfp);
|
||||
}
|
||||
} else if (!strcasecmp(argv[0],"syslog-enabled") && argc == 2) {
|
||||
@@ -688,6 +691,7 @@ void configSetCommand(redisClient *c) {
|
||||
} else {
|
||||
goto badfmt;
|
||||
}
|
||||
setLogVerbosityLevel(server.verbosity);
|
||||
} else if (!strcasecmp(c->argv[2]->ptr,"client-output-buffer-limit")) {
|
||||
int vlen, j;
|
||||
sds *v = sdssplitlen(o->ptr,(int)sdslen(o->ptr)," ",1,&vlen);
|
||||
|
||||
+10
-63
@@ -36,6 +36,7 @@
|
||||
#ifdef _WIN32
|
||||
#include <locale.h>
|
||||
#define LOG_LOCAL0 0
|
||||
#include "win32_socketmap.h"
|
||||
#else
|
||||
#include <sys/wait.h>
|
||||
#include <arpa/inet.h>
|
||||
@@ -259,67 +260,6 @@ struct redisCommand redisCommandTable[] = {
|
||||
|
||||
/*============================ Utility functions ============================ */
|
||||
|
||||
/* Low level logging. To use only for very big messages, otherwise
|
||||
* redisLog() is to prefer. */
|
||||
void redisLogRaw(int level, const char *msg) {
|
||||
#ifndef _WIN32
|
||||
const int syslogLevelMap[] = { LOG_DEBUG, LOG_INFO, LOG_NOTICE, LOG_WARNING };
|
||||
#endif
|
||||
const char *c = ".-*#";
|
||||
FILE *fp;
|
||||
char buf[64];
|
||||
int rawmode = (level & REDIS_LOG_RAW);
|
||||
|
||||
level &= 0xff; /* clear flags */
|
||||
if (level < server.verbosity) return;
|
||||
|
||||
fp = (server.logfile == NULL) ? stdout : fopen(server.logfile,"a");
|
||||
if (!fp) return;
|
||||
|
||||
if (rawmode) {
|
||||
fprintf(fp,"%s",msg);
|
||||
} else {
|
||||
int off;
|
||||
#ifdef _WIN32
|
||||
time_t secs;
|
||||
unsigned int usecs;
|
||||
|
||||
secs = gettimeofdaysecs(&usecs);
|
||||
off = (int)strftime(buf,sizeof(buf),"%d %b %H:%M:%S.",localtime(&secs));
|
||||
snprintf(buf+off,sizeof(buf)-off,"%03d",usecs/1000);
|
||||
#else
|
||||
struct timeval tv;
|
||||
|
||||
gettimeofday(&tv,NULL);
|
||||
off = strftime(buf,sizeof(buf),"%d %b %H:%M:%S.",localtime(&tv.tv_sec));
|
||||
snprintf(buf+off,sizeof(buf)-off,"%03d",(int)tv.tv_usec/1000);
|
||||
#endif
|
||||
fprintf(fp,"[%d] %s %c %s\n",(int)getpid(),buf,c[level],msg);
|
||||
}
|
||||
fflush(fp);
|
||||
|
||||
if (server.logfile) fclose(fp);
|
||||
#ifndef _WIN32
|
||||
if (server.syslog_enabled) syslog(syslogLevelMap[level], "%s", msg);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Like redisLogRaw() but with printf-alike support. This is the function that
|
||||
* is used across the code. The raw version is only used in order to dump
|
||||
* the INFO output on crash. */
|
||||
void redisLog(int level, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
char msg[REDIS_MAX_LOGMSG_LEN];
|
||||
|
||||
if ((level&0xff) < server.verbosity) return;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(msg, sizeof(msg), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
redisLogRaw(level,msg);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
/* Misc Windows house keeping */
|
||||
void win32Cleanup(void) {
|
||||
@@ -1214,6 +1154,7 @@ void initServerConfig() {
|
||||
server.sofd = -1;
|
||||
server.dbnum = REDIS_DEFAULT_DBNUM;
|
||||
server.verbosity = REDIS_NOTICE;
|
||||
setLogVerbosityLevel(server.verbosity);
|
||||
server.maxidletime = REDIS_MAXIDLETIME;
|
||||
server.tcpkeepalive = 0;
|
||||
server.active_expire_enabled = 1;
|
||||
@@ -1918,8 +1859,14 @@ int prepareForShutdown(int flags) {
|
||||
}
|
||||
/* Close the listening sockets. Apparently this allows faster restarts. */
|
||||
#ifdef _WIN32
|
||||
if (server.ipfd != -1) closesocket(server.ipfd);
|
||||
if (server.sofd != -1) closesocket(server.sofd);
|
||||
if (server.ipfd != -1) {
|
||||
closesocket(server.ipfd);
|
||||
smRemoveSocket(server.ipfd);
|
||||
}
|
||||
if (server.sofd != -1) {
|
||||
closesocket(server.sofd);
|
||||
smRemoveSocket(server.sofd);
|
||||
}
|
||||
#else
|
||||
if (server.ipfd != -1) close(server.ipfd);
|
||||
if (server.sofd != -1) close(server.sofd);
|
||||
|
||||
+1
-11
@@ -70,6 +70,7 @@
|
||||
#include "util.h" /* Misc functions useful in many places */
|
||||
|
||||
#include "win32_cow.h" /* Windows copy on write */
|
||||
#include "redisLog.h" /* moved logging for hiredis and RedisCli usage /*
|
||||
|
||||
/* Error codes */
|
||||
#define REDIS_OK 0
|
||||
@@ -90,7 +91,6 @@
|
||||
#define REDIS_SHARED_SELECT_CMDS 10
|
||||
#define REDIS_SHARED_INTEGERS 10000
|
||||
#define REDIS_SHARED_BULKHDR_LEN 32
|
||||
#define REDIS_MAX_LOGMSG_LEN 1024 /* Default maximum length of syslog messages */
|
||||
#define REDIS_AOF_REWRITE_PERC 100
|
||||
#define REDIS_AOF_REWRITE_MIN_SIZE (1024*1024)
|
||||
#define REDIS_AOF_REWRITE_ITEMS_PER_CMD 64
|
||||
@@ -244,13 +244,6 @@
|
||||
#define REDIS_SORT_DESC 2
|
||||
#define REDIS_SORTKEY_MAX 1024
|
||||
|
||||
/* Log levels */
|
||||
#define REDIS_DEBUG 0
|
||||
#define REDIS_VERBOSE 1
|
||||
#define REDIS_NOTICE 2
|
||||
#define REDIS_WARNING 3
|
||||
#define REDIS_LOG_RAW (1<<10) /* Modifier to log without timestamp */
|
||||
|
||||
/* Anti-warning macro... */
|
||||
#define REDIS_NOTUSED(V) ((void) V)
|
||||
|
||||
@@ -1008,9 +1001,6 @@ void call(redisClient *c, int flags);
|
||||
void propagate(struct redisCommand *cmd, int dbid, robj **argv, int argc, int flags);
|
||||
void alsoPropagate(struct redisCommand *cmd, int dbid, robj **argv, int argc, int target);
|
||||
int prepareForShutdown();
|
||||
void redisLog(int level, const char *fmt, ...);
|
||||
void redisLogRaw(int level, const char *msg);
|
||||
void redisLogFromHandler(int level, const char *msg);
|
||||
void usage();
|
||||
void updateDictResizePolicy(void);
|
||||
int htNeedsResize(dict *dict);
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright (c), Microsoft Open Technologies, Inc.
|
||||
* All rights reserved.
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "win32fixes.h"
|
||||
#include "win32_socketmap.h"
|
||||
#include <map>
|
||||
#include <queue>
|
||||
using namespace std;
|
||||
|
||||
extern "C" {
|
||||
#include "redisLog.h"
|
||||
}
|
||||
|
||||
typedef map<SOCKET,int> SocketToFDMapType;
|
||||
typedef map<int,SOCKET> FDToSocketMapType;
|
||||
typedef queue<int> FDRecyclePoolType;
|
||||
typedef SocketToFDMapType::iterator S2FDIterator;
|
||||
typedef FDToSocketMapType::iterator FD2SIterator;
|
||||
|
||||
/* In UNIX File Descriptors increment by one for each new one. Windows handles
|
||||
* do not follow the same rule. Additionally UNIX uses a 32-bit int to
|
||||
* represent a FD while Windows_x64 uses a 64-bit value to represent a handle.
|
||||
* There is no documented guarantee that a Windows SOCKET value will be
|
||||
* entirely constrained in 32-bits (though it seems to be currently). SOCKETs
|
||||
* should be treated as an opaque value and not be cast to a 32-bit int. In
|
||||
* order to not break existing code that relies on the maximum FD value to
|
||||
* indicate the number of handles that have been created (and other UNIXisms),
|
||||
* this code maps SOCKET handles to a virtual FD number starting at 3 (0,1 and
|
||||
* 2 are reserved for stdin, stdout and stderr).
|
||||
*/
|
||||
class SocketMap {
|
||||
public:
|
||||
static SocketMap& getInstance() {
|
||||
static SocketMap instance; // Instantiated on first use. Guaranteed to be destroyed.
|
||||
return instance;
|
||||
}
|
||||
private:
|
||||
SocketMap() {};
|
||||
SocketMap(SocketMap const&); // Don't implement to guarantee singleton semantics
|
||||
void operator=(SocketMap const&); // Don't implement to guarantee singleton semantics
|
||||
|
||||
private:
|
||||
SocketToFDMapType SocketToFDMap;
|
||||
FDToSocketMapType FDToSocketMap;
|
||||
FDRecyclePoolType FDRecyclePool;
|
||||
|
||||
public:
|
||||
const static int minFD = 3;
|
||||
const static int invalidFD = -1;
|
||||
|
||||
private:
|
||||
/* Gets the next available File Descriptor. File Descriptors are always
|
||||
non-negative integers, with the first three being reserved for stdin(0),
|
||||
stdout(1) and stderr(2). */
|
||||
int getNextFDAvailable() {
|
||||
if( FDRecyclePool.empty() == false ) {
|
||||
int FD = FDRecyclePool.front();
|
||||
FDRecyclePool.pop();
|
||||
return FD;
|
||||
} else {
|
||||
return (int)(minFD + SocketToFDMap.size());
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
/* Adds a socket to the socket map. Returns the file descriptor value for
|
||||
the socket. Returns invalidFD if the socket is already added to the
|
||||
collection. */
|
||||
int addSocket(SOCKET s) {
|
||||
if (SocketToFDMap.find(s) != SocketToFDMap.end()) {
|
||||
redisLog( REDIS_DEBUG, "SocketMap::addSocket() - socket already exists!" );
|
||||
return invalidFD;
|
||||
}
|
||||
|
||||
int FD = getNextFDAvailable();
|
||||
SocketToFDMap[s] = FD;
|
||||
FDToSocketMap[FD] = s;
|
||||
return FD;
|
||||
}
|
||||
|
||||
/* Removes a socket from the list of sockets. Also removes the associated
|
||||
file descriptor. */
|
||||
void removeSocket(SOCKET s) {
|
||||
S2FDIterator smit = SocketToFDMap.find(s);
|
||||
if(smit == SocketToFDMap.end()) {
|
||||
redisLog( REDIS_DEBUG, "SocketMap::removeSocket() - failed to find socket!" );
|
||||
}
|
||||
int FD = (*smit).second;
|
||||
FDRecyclePool.push(FD);
|
||||
SocketToFDMap.erase(s);
|
||||
}
|
||||
|
||||
/* Returns the socket associated with a file descriptor. */
|
||||
SOCKET lookupSocket(int FD) {
|
||||
if (FDToSocketMap.find(FD) != FDToSocketMap.end()) {
|
||||
return FDToSocketMap[FD];
|
||||
} else {
|
||||
redisLog( REDIS_DEBUG, "SocketMap::lookupSocket() - failed to find socket!" );
|
||||
return invalidFD;
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns the file descriptor associated with a socket. */
|
||||
int lookupFD(SOCKET s) {
|
||||
if (SocketToFDMap.find(s) != SocketToFDMap.end()) {
|
||||
return SocketToFDMap[s];
|
||||
} else {
|
||||
redisLog( REDIS_DEBUG, "SocketMap::lookupFD() - failed to find FD!" );
|
||||
return invalidFD;
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns the number of socket->FD mappings allocated. */
|
||||
int getCount() {
|
||||
return (int)(SocketToFDMap.size());
|
||||
}
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
int smAddSocket(SOCKET s) {
|
||||
return SocketMap::getInstance().addSocket(s);
|
||||
}
|
||||
|
||||
void smRemoveSocket(SOCKET s) {
|
||||
SocketMap::getInstance().removeSocket(s);
|
||||
}
|
||||
|
||||
SOCKET smLookupSocket(int fd) {
|
||||
return SocketMap::getInstance().lookupSocket(fd);
|
||||
}
|
||||
|
||||
int smLookupFD(SOCKET s) {
|
||||
return SocketMap::getInstance().lookupFD(s);
|
||||
}
|
||||
|
||||
int smGetSocketCount() {
|
||||
return SocketMap::getInstance().getCount();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c), Microsoft Open Technologies, Inc.
|
||||
* All rights reserved.
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Winsock2.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int smAddSocket( SOCKET s );
|
||||
void smRemoveSocket( SOCKET s );
|
||||
SOCKET smLookupSocket( int FD );
|
||||
int smLookupFD( SOCKET s );
|
||||
int smGetSocketCount();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <mswsock.h>
|
||||
#include <Guiddef.h>
|
||||
#include "win32_wsiocp.h"
|
||||
#include "win32_socketmap.h"
|
||||
|
||||
|
||||
static void *iocpState;
|
||||
@@ -64,6 +65,10 @@ int aeWinQueueAccept(SOCKET listensock) {
|
||||
errno = WSAEINVAL;
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
smAddSocket(acceptsock);
|
||||
}
|
||||
|
||||
|
||||
accsockstate = aeGetSockState(iocpState, (int)acceptsock);
|
||||
if (accsockstate == NULL) {
|
||||
@@ -90,6 +95,7 @@ int aeWinQueueAccept(SOCKET listensock) {
|
||||
errno = WSAGetLastError();
|
||||
sockstate->masks &= ~ACCEPT_PENDING;
|
||||
closesocket(acceptsock);
|
||||
smRemoveSocket(acceptsock);
|
||||
accsockstate->masks = 0;
|
||||
zfree(areq);
|
||||
return -1;
|
||||
@@ -439,6 +445,7 @@ int aeWinCloseSocket(int fd) {
|
||||
|
||||
if ((sockstate = aeGetSockState(iocpState, fd)) == NULL) {
|
||||
closesocket((SOCKET)fd);
|
||||
smRemoveSocket(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -448,6 +455,7 @@ int aeWinCloseSocket(int fd) {
|
||||
if (sockstate->wreqs == 0 &&
|
||||
(sockstate->masks & (READ_QUEUED | CONNECT_PENDING | SOCKET_ATTACHED)) == 0) {
|
||||
closesocket((SOCKET)fd);
|
||||
smRemoveSocket(fd);
|
||||
} else {
|
||||
sockstate->masks |= CLOSE_PENDING;
|
||||
}
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@
|
||||
#define fseeko fseeko64
|
||||
#define ftello ftello64
|
||||
|
||||
#define inline __inline
|
||||
//#define inline __inline
|
||||
|
||||
#undef ftruncate
|
||||
#define ftruncate replace_ftruncate
|
||||
|
||||
Reference in New Issue
Block a user