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:
Jonathan Pickett
2013-10-03 16:12:54 -07:00
parent de48871570
commit 7071e9d599
17 changed files with 460 additions and 78 deletions
+2
View File
@@ -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
+10
View File
@@ -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>
+37
View File
@@ -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);
+3
View File
@@ -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
+4
View File
@@ -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" />
+2
View File
@@ -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
View File
@@ -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);
}
+51 -1
View File
@@ -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
View File
@@ -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();
+4
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+158
View File
@@ -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();
}
}
+39
View File
@@ -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
+8
View File
@@ -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
View File
@@ -40,7 +40,7 @@
#define fseeko fseeko64
#define ftello ftello64
#define inline __inline
//#define inline __inline
#undef ftruncate
#define ftruncate replace_ftruncate