提交 0c3a93b8 编写于 作者: J jonathan pickett

adding persistence-available flag

上级 6f4ce3f8
......@@ -327,6 +327,16 @@ slave-priority 100
# Note that you must specify a directory here, not a file name.
# heapdir <directory path(absolute or relative)>
# If Redis is to be used as an in-memory-only cache without any kind of
# persistence, then the fork() mechanism used by the background AOF/RDB
# persistence is unneccessary. As an optimization, all persistence can be
# turned off in the Windows version of Redis. This will disable the creation of
# the memory mapped heap file, redirect heap allocations to the system heap
# allocator, and disable commands that would otherwise cause fork() operations:
# BGSAVE and BGREWRITEAOF. This flag may not be combined with any of the other
# flags that configure AOF and RDB operations.
# persistence-available [(yes)|no]
# Don't use more memory than the specified amount of bytes.
# When the memory limit is reached Redis will try to remove keys
# accordingly to the eviction policy selected (see maxmemmory-policy).
......
......@@ -90,7 +90,7 @@ public:
if (argStartIndex + parameterCount >= argc) {
stringstream err;
err << "Not enough parameters available for " << argv[argStartIndex];
throw runtime_error(err.str());
throw invalid_argument(err.str());
}
vector<string> params;
for (int argIndex = argStartIndex + 1; argIndex < argStartIndex + 1 + parameterCount; argIndex++) {
......@@ -106,7 +106,7 @@ public:
if ((int)(tokens.size() - 1) < parameterCount + startIndex) {
stringstream err;
err << "Not enough parameters available for " << tokens.at(0);
throw runtime_error(err.str());
throw invalid_argument(err.str());
}
vector<string> params;
int skipCount = 1 + startIndex;
......@@ -164,7 +164,7 @@ public:
} else {
stringstream err;
err << "Not enough parameters available for " << argv[argStartIndex];
throw runtime_error(err.str());
throw invalid_argument(err.str());
}
return params;
}
......@@ -184,7 +184,7 @@ public:
} else {
stringstream err;
err << "Not enough parameters available for " << tokens.at(startIndex);
throw runtime_error(err.str());
throw invalid_argument(err.str());
}
return params;
};
......@@ -300,11 +300,11 @@ public:
stringstream err;
if (argStartIndex + 1 >= argc) {
err << "Not enough parameters available for " << argv[argStartIndex];
throw runtime_error(err.str());
throw invalid_argument(err.str());
}
if (subCommands.find(argv[argStartIndex + 1]) == subCommands.end()) {
err << "Could not find sentinal subcommand " << argv[argStartIndex + 1];
throw runtime_error(err.str());
throw invalid_argument(err.str());
}
vector<string> params;
......@@ -322,12 +322,12 @@ public:
stringstream err;
if (tokens.size() < 2) {
err << "Not enough parameters available for " << tokens.at(0);
throw runtime_error(err.str());
throw invalid_argument(err.str());
}
string subcommand = tokens.at(startIndex + 1);
if (subCommands.find(subcommand) == subCommands.end()) {
err << "Could not find sentinal subcommand " << subcommand;
throw runtime_error(err.str());
throw invalid_argument(err.str());
}
vector<string> params;
......@@ -354,6 +354,7 @@ static RedisParamterMapper g_redisArgMap =
{ cQFork, &fp2 }, // qfork [QForkConrolMemoryMap handle] [parent process id]
{ cMaxHeap, &fp1 }, // maxheap [number]
{ cHeapDir, &fp1 }, // heapdir [path]
{ cPersistenceAvailable, &fp1 }, // persistence-available [yes/no]
// service commands
{ cServiceName, &fp1 }, // service-name [name]
......@@ -518,7 +519,7 @@ void ParseConfFile(string confFile, string cwd, ArgumentMap& argMap) {
if (config.fail()) {
stringstream ss;
ss << "Failed to open the .conf file: " << confFile << " CWD=" << cwd.c_str();
throw runtime_error(ss.str());
throw invalid_argument(ss.str());
} else {
char confFileDir[MAX_PATH];
strcpy(confFileDir, fullConfFilePath);
......@@ -540,7 +541,7 @@ void ParseConfFile(string confFile, string cwd, ArgumentMap& argMap) {
} else if (g_redisArgMap.find(parameter) == g_redisArgMap.end()) {
stringstream err;
err << "unknown conf file parameter : " + parameter;
throw runtime_error(err.str());
throw invalid_argument(err.str());
}
vector<string> params = g_redisArgMap[parameter]->Extract(tokens);
......@@ -549,6 +550,37 @@ void ParseConfFile(string confFile, string cwd, ArgumentMap& argMap) {
}
}
vector<string> incompatibleNoPersistenceCommands{
"min_slaves_towrite",
"min_slaves_max_lag",
"appendonly",
"appendfilename",
"appendfsync",
"no_append_fsync_on_rewrite",
"auto_aof_rewrite_percentage",
"auto_aof_rewrite_on_size",
"aof_rewrite_incremental_fsync"
};
void ValidateCommandlineCombinations() {
if (g_argMap.find(cPersistenceAvailable) != g_argMap.end()) {
if (g_argMap[cPersistenceAvailable].at(0).at(0) == cNo) {
string incompatibleCommand = "";
for (auto command : incompatibleNoPersistenceCommands) {
if (g_argMap.find(command) != g_argMap.end()) {
incompatibleCommand = command;
break;
}
}
if (incompatibleCommand.length() > 0) {
stringstream ss;
ss << "'" << cPersistenceAvailable << " " << cNo << "' command not compatible with '" << incompatibleCommand << "'. Exiting.";
throw std::invalid_argument(ss.str().c_str());
}
}
}
}
void ParseCommandLineArguments(int argc, char** argv) {
if (argc < 2) return;
......@@ -562,7 +594,7 @@ void ParseCommandLineArguments(int argc, char** argv) {
if (g_redisArgMap.find(argument) == g_redisArgMap.end()) {
stringstream err;
err << "unknown argument: " << argument;
throw runtime_error(err.str());
throw invalid_argument(err.str());
}
vector<string> params;
......@@ -572,7 +604,7 @@ void ParseCommandLineArguments(int argc, char** argv) {
for (auto p : sentinelSubCommands) {
params.push_back(p);
}
} catch (runtime_error re) {
} catch (invalid_argument iaerr) {
// if no subcommands could be mapped, then assume this is the parameterless --sentinel command line only argument
}
} else if (argument == cServiceRun ) {
......@@ -642,6 +674,8 @@ void ParseCommandLineArguments(int argc, char** argv) {
}
}
#endif
ValidateCommandlineCombinations();
}
vector<string> GetAccessPaths() {
......
......@@ -52,6 +52,7 @@ const string cLogfile = "logfile";
const string cInclude = "include";
const string cDir = "dir";
const string cHeapDir = "heapdir";
const string cPersistenceAvailable = "persistence-available";
const string cMaxHeap = "maxheap";
const string cMaxMemory = "maxmemory";
......
......@@ -60,7 +60,13 @@ extern "C" int checkForSentinelMode(int argc, char **argv);
extern "C"
{
// forward def from util.h.
void*(*g_malloc)(size_t) = nullptr;
void*(*g_calloc)(size_t, size_t) = nullptr;
void*(*g_realloc)(void*, size_t) = nullptr;
void(*g_free)(void*) = nullptr;
size_t(*g_msize)(void*) = nullptr;
// forward def from util.h.
long long memtoll(const char *p, int *err);
}
......@@ -218,15 +224,15 @@ bool ReportSpecialSystemErrors(int error) {
"The Windows version of Redis allocates a large memory mapped file for sharing\n"
"the heap with the forked process used in persistence operations. This file\n"
"will be created in the current working directory or the directory specified by\n"
"the 'dir' directive in the .conf file. Windows is reporting that there is \n"
"the 'heapdir' directive in the .conf file. Windows is reporting that there is \n"
"insufficient disk space available for this file (Windows error 0x70).\n"
"\n"
"You may fix this problem by either reducing the size of the Redis heap with\n"
"the --maxheap flag, or by starting redis from a working directory with\n"
"sufficient space available for the Redis heap. \n"
"the --maxheap flag, or by moving the heap file to a local drive with sufficient\n"
"space."
"\n"
"Please see the documentation included with the binary distributions for more \n"
"details on the --maxheap flag.\n"
"details on the --maxheap and --heapdir flags.\n"
"\n"
"Redis can not continue. Exiting."
);
......@@ -1244,6 +1250,14 @@ void SetupLogging() {
extern "C"
{
BOOL IsPersistenceAvailable() {
if (g_argMap.find(cPersistenceAvailable) != g_argMap.end()) {
return (g_argMap[cPersistenceAvailable].at(0).at(0) != cNo);
} else {
return true;
}
}
// The external main() is redefined as redis_main() by Win32_QFork.h.
// The CRT will call this replacement main() before the previous main()
// is invoked so that the QFork allocator can be setup prior to anything
......@@ -1252,11 +1266,19 @@ extern "C"
try {
ParseCommandLineArguments(argc, argv);
SetupLogging();
} catch (runtime_error &re) {
cout << re.what() << endl;
} catch (system_error syserr) {
exit(-1);
} catch (runtime_error runerr) {
cout << runerr.what() << endl;
exit(-1);
} catch (invalid_argument &iaerr) {
cout << iaerr.what() << endl;
exit(-1);
} catch (exception othererr) {
cout << othererr.what() << endl;
exit(-1);
}
try {
#ifdef DEBUG_WITH_PROCMON
hProcMonDevice =
......@@ -1271,25 +1293,45 @@ extern "C"
#endif
// service commands do not launch an instance of redis directly
if (HandleServiceCommands(argc, argv) == TRUE)
return 0;
StartupStatus status = QForkStartup(argc, argv);
if (status == ssCONTINUE_AS_MASTER) {
int retval = redis_main(argc, argv);
QForkShutdown();
return retval;
} else if (status == ssSLAVE_EXIT) {
// slave is done - clean up and exit
QForkShutdown();
return g_SlaveExitCode;
} else if (status == ssFAILED) {
// master or slave failed initialization
return 1;
} else {
// unexpected status return
return 2;
}
if (HandleServiceCommands(argc, argv) == TRUE) {
return 0;
}
// Setup memory allocation scheme for persistence mode
if (IsPersistenceAvailable() == TRUE) {
g_malloc = dlmalloc;
g_calloc = dlcalloc;
g_realloc = dlrealloc;
g_free = dlfree;
g_msize = reinterpret_cast<size_t(*)(void*)>(dlmalloc_usable_size);
} else {
g_malloc = malloc;
g_calloc = calloc;
g_realloc = realloc;
g_free = free;
g_msize = _msize;
}
if (IsPersistenceAvailable() == TRUE) {
StartupStatus status = QForkStartup(argc, argv);
if (status == ssCONTINUE_AS_MASTER) {
int retval = redis_main(argc, argv);
QForkShutdown();
return retval;
} else if (status == ssSLAVE_EXIT) {
// slave is done - clean up and exit
QForkShutdown();
return g_SlaveExitCode;
} else if (status == ssFAILED) {
// master or slave failed initialization
return 1;
} else {
// unexpected status return
return 2;
}
} else {
return redis_main(argc, argv);
}
} catch (std::system_error syserr) {
::redisLog(REDIS_WARNING, "main: system error caught. error code=0x%08x, message=%s\n", syserr.code().value(), syserr.what());
} catch (std::runtime_error runerr) {
......
......@@ -68,6 +68,14 @@ BOOL AbortForkOperation();
LPVOID AllocHeapBlock(size_t size, BOOL allocateHigh);
int FreeHeapBlock(LPVOID block, size_t size);
// for no persistence optimization/feature
BOOL IsPersistenceAvailable();
extern void*(*g_malloc)(size_t);
extern void*(*g_calloc)(size_t, size_t);
extern void*(*g_realloc)(void*, size_t);
extern void(*g_free)(void*);
extern size_t(*g_msize)(void*);
#ifndef NO_QFORKIMPL
#ifdef QFORK_MAIN_IMPL
int redis_main(int argc, char** argv);
......
......@@ -526,6 +526,24 @@ void loadServerConfigFromString(char *config) {
// ignore. This is taken care of in the qfork code.
} else if (!strcasecmp(argv[0], "service-name")) {
// ignore. This is taken care of in the win32_service code.
} else if (!strcasecmp(argv[0], "persistence-available")) {
if (strcasecmp(argv[1], "no") == 0) {
//remove BGSAVE and BGREWRITEAOF when persistence is disabled
int retval;
sds bgsave;
sds bgrewriteaof;
bgsave = sdsnew("bgsave");
bgrewriteaof = sdsnew("bgrewriteaof");
retval = dictDelete(server.commands, bgsave);
redisAssert(retval == DICT_OK);
retval = dictDelete(server.commands, bgrewriteaof);
redisAssert(retval == DICT_OK);
sdsfree(bgsave);
sdsfree(bgrewriteaof);
}
#endif
} else {
err = "Bad directive or wrong number of arguments"; goto loaderr;
......
......@@ -70,10 +70,10 @@ void zlibc_free(void *ptr) {
#define realloc(ptr,size) je_realloc(ptr,size)
#define free(ptr) je_free(ptr)
#elif defined(USE_DLMALLOC)
#define malloc(size) dlmalloc(size)
#define calloc(count,size) dlcalloc(count,size)
#define realloc(ptr,size) dlrealloc(ptr,size)
#define free(ptr) dlfree(ptr)
#define malloc(size) g_malloc(size)
#define calloc(count,size) g_calloc(count,size)
#define realloc(ptr,size) g_realloc(ptr,size)
#define free(ptr) g_free(ptr)
#endif
#ifdef HAVE_ATOMIC
......
......@@ -64,7 +64,7 @@
#include "win32_Interop/win32_dlmalloc.h"
#define ZMALLOC_LIB ("dlmalloc-" __xstr(2) "." __xstr(8) )
#define HAVE_MALLOC_SIZE 1
#define zmalloc_size(p) dlmalloc_usable_size(p)
#define zmalloc_size(p) g_msize(p)
#endif
#ifndef ZMALLOC_LIB
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册