Compare commits

..
Author SHA1 Message Date
Enrico Giordani 87a6ee2214 [Release] 2.8.2104 2015-10-15 18:50:43 +02:00
rpannell 041744fb06 [PR] Updated list of sentinel commands: announce-ip and announce-port. 2015-10-15 18:27:11 +02:00
laurence.evans 6542f73305 [PR] Updated x86 debug and release configurations for all projects.
Use the newer v120 platform toolset instead of v120_xp.
This fixes a compilation error for x86 due to a missing define statement.
2015-10-15 18:27:11 +02:00
Maxime Lemaitre 26a0e81963 [PR] Changed Nuget package structure to support VS 2015 2015-10-15 18:26:51 +02:00
Enrico Giordani a6dcd555a9 [Build] Fixed a build break (regression).
Credits to @tortuetorche for pointing it out.
2015-10-01 10:43:47 +02:00
Enrico Giordani 18273bc139 [Fix] Sentinel mode doesn't need to create a memory mapped file.
Changed the memory allocation mechanism to use the crt memory allocator
when redis-server runs as a sentinel.
2015-10-01 10:37:40 +02:00
Enrico Giordani 647a99b432 [Setup] Updated the Windows release notes. 2015-09-08 15:53:29 +02:00
Enrico Giordani 808c9b227a [Setup] Added more information in the memory limit dialog.
[Setup] Fixed warning for missing properties attributes.
2015-09-08 15:49:55 +02:00
Enrico Giordani 7b8d0243b2 [Fix] Missing return code path. 2015-09-08 15:49:05 +02:00
Enrico Giordani b500dd3dca [Fix] Reporting error code if listen() fails. 2015-09-08 15:47:44 +02:00
Enrico Giordani 566db8d155 [Setup] Updated the Windows release notes. 2015-09-07 18:32:45 +02:00
Enrico Giordani 0b89a20a9b [Setup] Added maxheap settings along with the maxmemory settings.
[Setup] Added a checkbox to choose whether to add the install dir to PATH.
2015-09-07 18:22:05 +02:00
Enrico Giordani e5fbc9cbcf [Fix] Write errors to the Event Log during startup.
Use the Event Log as error reporting system during startup while logging to
file is not yet enabled.
Some code refactoring.
2015-09-07 18:22:04 +02:00
Enrico Giordani 777b56b0d0 [Setup] MSI: added max memory config dialog.
[Setup] MSI: Redis installation folder added to the PATH environment variable.
2015-09-07 18:22:04 +02:00
Enrico Giordani e290b6e9e6 [Setup] Increased the version number from 2.8.2102 to 2.8.2103. 2015-09-07 18:22:03 +02:00
Enrico Giordani 5030fc664d [Fix] Redis crashes at startup.
This commit fixes the problem reported by:
https://github.com/MSOpenTech/redis/issues/304
https://github.com/MSOpenTech/redis/issues/306
A previous commit that fixed a socketstate leak exposed another existing bug:
if FDAPI_AcceptEx() fails the socketstate is accessed after the socket has
already been closed and the socketstate memory has been released, causing
a heap corruption exception .

[Fix] Improved error handlingin WSIOCP_Listen().
2015-09-07 18:22:03 +02:00
Enrico Giordani 9c3a329e6a [Fix] Remove temp file after AOF rewrite error. 2015-09-07 18:22:02 +02:00
Enrico Giordani e4127b84aa [Fix] Close the file handle after truncating a file. 2015-09-07 18:22:02 +02:00
Enrico Giordani b026f3c811 [Fix] replace_rename() had an infinite loop upon error. 2015-09-07 18:21:40 +02:00
33 changed files with 579 additions and 317 deletions
+34
View File
@@ -1,6 +1,40 @@
MSOpenTech Redis on Windows 2.8 Release Notes
=============================================
--[ Redis on Windows 2.8.2104 ] Release date: Oct 15 2015
NOTE: When runnig as a sentinel, redis-server.exe is not creating any more
the RedisQFork_*.dat file.
- [PR] Updated list of sentinel commands: announce-ip and announce-port. (by @rpannell)
- [PR] Updated x86 debug and release configurations for all projects. (by @laurencee)
- [PR] Changed Nuget package structure to support VS 2015 (by @Cybermaxs)
- [Build] Fixed a build break (regression).
- [Fix] Sentinel mode doesn't need to create a memory mapped file.
--[ Redis on Windows 2.8.2103 ] Release date: Sep 08 2015
NOTE: Two new features added to the MSI installer:
- select whether to add the install dir to the PATH env variable.
- select whether to set the maxmemory and maxheap flags.
Improved error reporting if the installation fails or if the service
fails to start: error messages logged to the Application Event Log.
- [Setup] Added more information in the memory limit dialog.
- [Setup] Fixed warning for missing properties attributes.
- [Fix] Missing return code path.
- [Fix] Reporting error code if listen() fails.
- [Setup] Added maxheap settings along with the maxmemory settings.
- [Setup] Added a checkbox to choose whether to add the install dir to PATH.
- [Fix] Write errors to the Event Log during startup.
- [Setup] MSI: added max memory config dialog.
- [Setup] MSI: Redis installation folder added to the PATH environment variable.
- [Fix] Redis crashes at startup.
- [Fix] Improved error handling in WSIOCP_Listen().
- [Fix] Remove temp file after AOF rewrite error.
- [Fix] Close the file handle after truncating a file.
- [Fix] replace_rename() had an infinite loop upon error.
--[ Redis on Windows 2.8.2102 ] Release date: Aug 25 2015
IMPORTANT NOTE: the 2.8.2102 release introduces some high impact changes
+1 -1
View File
@@ -1,4 +1,4 @@
version: 2.8.2102.{build}
version: 2.8.2104.{build}
branches:
# whitelist
+2 -2
View File
@@ -34,7 +34,7 @@
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v120_xp</PlatformToolset>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
@@ -48,7 +48,7 @@
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v120_xp</PlatformToolset>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
+2 -2
View File
@@ -33,7 +33,7 @@
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v120_xp</PlatformToolset>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
@@ -47,7 +47,7 @@
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v120_xp</PlatformToolset>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
+2 -2
View File
@@ -33,7 +33,7 @@
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v120_xp</PlatformToolset>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
@@ -47,7 +47,7 @@
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v120_xp</PlatformToolset>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
+2 -2
View File
@@ -33,7 +33,7 @@
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v120_xp</PlatformToolset>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
@@ -47,7 +47,7 @@
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v120_xp</PlatformToolset>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
+2 -2
View File
@@ -32,7 +32,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120_xp</PlatformToolset>
<PlatformToolset>v120</PlatformToolset>
<CLRSupport>false</CLRSupport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
@@ -43,7 +43,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120_xp</PlatformToolset>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
+2 -2
View File
@@ -34,7 +34,7 @@
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v120_xp</PlatformToolset>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
@@ -48,7 +48,7 @@
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v120_xp</PlatformToolset>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
+2 -2
View File
@@ -37,7 +37,7 @@
<UseDebugLibraries>true</UseDebugLibraries>
<CLRSupport>false</CLRSupport>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v120_xp</PlatformToolset>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
@@ -51,7 +51,7 @@
<UseDebugLibraries>false</UseDebugLibraries>
<CLRSupport>false</CLRSupport>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v120_xp</PlatformToolset>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
+41 -22
View File
@@ -20,11 +20,49 @@ namespace RedisMsi.CustomActions
[CustomAction]
public static ActionResult UpdateRedisConfig(Session session)
{
// Update port
string port = session.CustomActionData["PORT"];
string configFilePath = session.CustomActionData["CONFIG_PATH"];
if (File.Exists(configFilePath))
{
string originalContent = File.ReadAllText(configFilePath);
UpdatePortSetting(port, configFilePath);
string port = session.CustomActionData["PORT"];
string updatedContent = originalContent.Replace("port 6379", "port " + port);
string useMaxMemoryLimit = session.CustomActionData["USE_MEMORY_LIMITS"];
if (useMaxMemoryLimit == "1")
{
string strMaxMemoryMB = session.CustomActionData["MAXMEMORY"];
string strMaxHeapMB = session.CustomActionData["MAXHEAP"];
try
{
int intMaxMemory = Int32.Parse(strMaxMemoryMB);
if (intMaxMemory <= 0)
{
strMaxMemoryMB = "100";
}
int intMaxHeap = Int32.Parse(strMaxHeapMB);
if (intMaxHeap <= 0)
{
strMaxHeapMB = "150";
}
}
catch
{
strMaxMemoryMB = "100";
strMaxHeapMB = "150";
}
updatedContent = updatedContent.Replace("# maxmemory <bytes>", "maxmemory " + strMaxMemoryMB + "mb");
updatedContent = updatedContent.Replace("# maxheap <bytes>", "maxheap " + strMaxHeapMB + "mb");
}
File.WriteAllText(configFilePath, updatedContent);
}
else
{
throw new ApplicationException("UpdateRedisConfig: Config file not found. Could not update its settings.");
}
return ActionResult.Success;
}
@@ -50,24 +88,5 @@ namespace RedisMsi.CustomActions
return ActionResult.Success;
}
/// <summary>
/// Updates the port in the config file.
/// </summary>
/// <param name="portToUse">The port to have Redis listen at</param>
/// <param name="configFilePath">The path to the Redis config file</param>
private static void UpdatePortSetting(string portToUse, string configFilePath)
{
if (File.Exists(configFilePath))
{
string originalContent = File.ReadAllText(configFilePath);
string updatedContent = originalContent.Replace("port 6379", "port " + portToUse);
File.WriteAllText(configFilePath, updatedContent);
}
else
{
throw new ApplicationException("UpdateRedisConfig: Config file not found. Could not update its settings.");
}
}
}
}
+1 -1
View File
@@ -7,7 +7,7 @@
Custom actions that update the redis config file during installation
-->
<CustomAction Id="ca_UpdateRedisConfig" BinaryKey="RedisCADLL" DllEntry="UpdateRedisConfig" Execute="deferred" Return="check" Impersonate="no" />
<SetProperty Id="ca_UpdateRedisConfig" Value="CONFIG_PATH=[#file_redis_serviceCONF];PORT=[PORT];" Sequence="execute" Before="ca_UpdateRedisConfig" />
<SetProperty Id="ca_UpdateRedisConfig" Value="CONFIG_PATH=[#file_redis_serviceCONF];PORT=[PORT];MAXMEMORY=[MAXMEMORY];MAXHEAP=[MAXHEAP];USE_MEMORY_LIMITS=[USE_MEMORY_LIMITS];" Sequence="execute" Before="ca_UpdateRedisConfig" />
<InstallExecuteSequence>
<Custom Action="ca_UpdateRedisConfig" After="InstallFiles"><![CDATA[NOT Installed]]></Custom>
</InstallExecuteSequence>
+17 -13
View File
@@ -37,7 +37,8 @@ First-time install dialog sequence:
- WixUI_WelcomeDlg
- WixUI_LicenseAgreementDlg
- WixUI_InstallDirDlg
- FirwallDlg
- FirewallDlg
- MaxMemoryDlg
- WixUI_VerifyReadyDlg
- WixUI_DiskCostDlg
@@ -83,21 +84,24 @@ Patch dialog sequence:
<Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg">Installed AND PATCH</Publish>
<Publish Dialog="LicenseAgreementDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg">1</Publish>
<Publish Dialog="LicenseAgreementDlg" Control="Next" Event="NewDialog" Value="InstallDirDlg">LicenseAccepted = "1"</Publish>
<Publish Dialog="LicenseAgreementDlg" Control="Next" Event="NewDialog" Value="CustomInstallDirDlg">LicenseAccepted = "1"</Publish>
<Publish Dialog="InstallDirDlg" Control="Back" Event="NewDialog" Value="LicenseAgreementDlg">1</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="SetTargetPath" Value="[WIXUI_INSTALLDIR]" Order="1">1</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="DoAction" Value="WixUIValidatePath" Order="2">NOT WIXUI_DONTVALIDATEPATH</Publish>
<Publish Dialog="CustomInstallDirDlg" Control="Back" Event="NewDialog" Value="LicenseAgreementDlg">1</Publish>
<Publish Dialog="CustomInstallDirDlg" Control="Next" Event="SetTargetPath" Value="[WIXUI_INSTALLDIR]" Order="1">1</Publish>
<Publish Dialog="CustomInstallDirDlg" Control="Next" Event="DoAction" Value="WixUIValidatePath" Order="2">NOT WIXUI_DONTVALIDATEPATH</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="NewDialog" Value="FirewallDlg" Order="4">WIXUI_DONTVALIDATEPATH OR WIXUI_INSTALLDIR_VALID="1"</Publish>
<Publish Dialog="InstallDirDlg" Control="ChangeFolder" Property="_BrowseProperty" Value="[WIXUI_INSTALLDIR]" Order="1">1</Publish>
<Publish Dialog="InstallDirDlg" Control="ChangeFolder" Event="SpawnDialog" Value="BrowseDlg" Order="2">1</Publish>
<Publish Dialog="CustomInstallDirDlg" Control="Next" Event="NewDialog" Value="FirewallDlg" Order="4">WIXUI_DONTVALIDATEPATH OR WIXUI_INSTALLDIR_VALID="1"</Publish>
<Publish Dialog="CustomInstallDirDlg" Control="ChangeFolder" Property="_BrowseProperty" Value="[WIXUI_INSTALLDIR]" Order="1">1</Publish>
<Publish Dialog="CustomInstallDirDlg" Control="ChangeFolder" Event="SpawnDialog" Value="BrowseDlg" Order="2">1</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="SpawnDialog" Value="InvalidDirDlg" Order="3"><![CDATA[NOT WIXUI_DONTVALIDATEPATH AND WIXUI_INSTALLDIR_VALID<>"1"]]></Publish>
<Publish Dialog="FirewallDlg" Control="Back" Event="NewDialog" Value="InstallDirDlg" Order="1">1</Publish>
<Publish Dialog="FirewallDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg" Order="1">1</Publish>
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="FirewallDlg" Order="1">NOT Installed</Publish>
<Publish Dialog="CustomInstallDirDlg" Control="Next" Event="SpawnDialog" Value="InvalidDirDlg" Order="3"><![CDATA[NOT WIXUI_DONTVALIDATEPATH AND WIXUI_INSTALLDIR_VALID<>"1"]]></Publish>
<Publish Dialog="FirewallDlg" Control="Back" Event="NewDialog" Value="CustomInstallDirDlg" Order="1">1</Publish>
<Publish Dialog="FirewallDlg" Control="Next" Event="NewDialog" Value="MaxMemoryDlg" Order="1">1</Publish>
<Publish Dialog="MaxMemoryDlg" Control="Back" Event="NewDialog" Value="FirewallDlg" Order="1">1</Publish>
<Publish Dialog="MaxMemoryDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg" Order="1">1</Publish>
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="MaxMemoryDlg" Order="1">NOT Installed</Publish>
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="MaintenanceTypeDlg" Order="2">Installed AND NOT PATCH</Publish>
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg" Order="2">Installed AND PATCH</Publish>
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
<copyright file="InstallDirDlg.wxs" company="Outercurve Foundation">
Copyright (c) 2004, Outercurve Foundation.
This software is released under Microsoft Reciprocal License (MS-RL).
The license and further copyright text can be found in the file
LICENSE.TXT at the root directory of the distribution.
</copyright>
-->
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<UI>
<Dialog Id="CustomInstallDirDlg" Width="370" Height="270" Title="!(loc.InstallDirDlg_Title)">
<Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="!(loc.WixUINext)" />
<Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="!(loc.WixUIBack)" />
<Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="!(loc.WixUICancel)">
<Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
</Control>
<Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes" Text="!(loc.InstallDirDlgDescription)" />
<Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes" Text="!(loc.InstallDirDlgTitle)" />
<Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="!(loc.InstallDirDlgBannerBitmap)" />
<Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />
<Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
<Control Id="FolderLabel" Type="Text" X="20" Y="60" Width="290" Height="30" NoPrefix="yes" Text="!(loc.InstallDirDlgFolderLabel)" />
<Control Id="Folder" Type="PathEdit" X="20" Y="100" Width="320" Height="18" Property="WIXUI_INSTALLDIR" Indirect="yes" />
<Control Id="ChangeFolder" Type="PushButton" X="20" Y="120" Width="56" Height="17" Text="!(loc.InstallDirDlgChange)" />
<Control Id="AddToPathCheckBox" Type="CheckBox" X="20" Y="160" Width="290" Height="17" Property="ADD_INSTALLFOLDER_TO_PATH" CheckBoxValue="1" Text="Add the Redis installation folder to the PATH environment variable." />
</Dialog>
</UI>
</Fragment>
</Wix>
+5 -5
View File
@@ -12,18 +12,18 @@
</Control>
<Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes" Text="Select whether to add an exception to the Windows Firewall for Redis." />
<Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes" Text="{\WixUI_Font_Title}Firewall Exception" />
<Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes" Text="{\WixUI_Font_Title}Port Number and Firewall Exception" />
<Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="!(loc.InstallDirDlgBannerBitmap)" />
<Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />
<Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
<Control Id="PortLabel" Type="Text" X="20" Y="60" Width="290" Height="30" NoPrefix="yes" Text="Port to run Redis on:" />
<Control Id="PortEdit" Type="Edit" Property="PORT" Height="17" Width="50" X="20" Y="100" />
<Control Id="PortLabel" Type="Text" X="20" Y="60" Width="290" Height="20" NoPrefix="yes" Text="Port to run Redis on:" />
<Control Id="PortEdit" Type="Edit" Property="PORT" Height="17" Width="40" X="20" Y="90" />
<Control Id="FirewallCheckbox" Type="CheckBox" Property="ADD_FIREWALL_RULE" CheckBoxValue="1" Integer="yes" Text="Add an exception to the Windows Firewall" Height="10" Width="200" X="20" Y="140">
<Control Id="FirewallCheckbox" Type="CheckBox" Property="ADD_FIREWALL_RULE" CheckBoxValue="1" Integer="yes" Text="Add an exception to the Windows Firewall." Height="20" Width="200" X="20" Y="120">
<Condition Action="disable"><![CDATA[FIREWALL_SERVICE_STOPPED = 1]]></Condition>
</Control>
<Control Id="FirewallServiceOffText" Type="Text" Text="{\Warning}The firewall service must be running to add a new exception." Height="34" Width="280" X="20" Y="160" Hidden="yes" NoWrap="no">
<Control Id="FirewallServiceOffText" Type="Text" Text="{\Warning}The firewall service must be running to add a new exception." Height="34" Width="280" X="20" Y="140" Hidden="yes" NoWrap="no">
<Condition Action="show"><![CDATA[FIREWALL_SERVICE_STOPPED = 1]]></Condition>
</Control>
</Dialog>
@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<UI>
<Dialog Id="MaxMemoryDlg" Width="370" Height="270" Title="[ProductName] Setup">
<Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="!(loc.WixUINext)" />
<Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="!(loc.WixUIBack)" />
<Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="!(loc.WixUICancel)">
<Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
</Control>
<Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes" Text="Select whether to use memory limits or not." />
<Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes" Text="{\WixUI_Font_Title}Memory Limits" />
<Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="!(loc.InstallDirDlgBannerBitmap)" />
<Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />
<Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
<Control Id="MaxMemoryCheckbox" Type="CheckBox" Property="USE_MEMORY_LIMITS" CheckBoxValue="1" Integer="yes" Text="Set the Max Memory and Max Heap limits" Height="10" Width="300" X="20" Y="60" />
<Control Id="MaxMemoryLabel1" Type="Text" X="20" Y="90" Width="250" Height="15" NoPrefix="yes" Text="Max Memory (integer values only):">
<Condition Action="enable" >USE_MEMORY_LIMITS = 1</Condition>
<Condition Action="disable"><![CDATA[USE_MEMORY_LIMITS <>1]]></Condition>
</Control>
<Control Id="MaxMemoryEdit" Type="Edit" Property="MAXMEMORY" Height="17" Width="40" X="20" Y="105">
<Condition Action="enable" >USE_MEMORY_LIMITS = 1</Condition>
<Condition Action="disable"><![CDATA[USE_MEMORY_LIMITS <>1]]></Condition>
</Control>
<Control Id="MaxMemoryLabel2" Type="Text" X="65" Y="108" Width="250" Height="15" NoPrefix="yes" Text="MB">
<Condition Action="enable" >USE_MEMORY_LIMITS = 1</Condition>
<Condition Action="disable"><![CDATA[USE_MEMORY_LIMITS <>1]]></Condition>
</Control>
<Control Id="MaxHeapLabel1" Type="Text" X="20" Y="140" Width="250" Height="15" NoPrefix="yes" Text="Max Heap (integer value at least 1.5 times the Max Memory value):">
<Condition Action="enable" >USE_MEMORY_LIMITS = 1</Condition>
<Condition Action="disable"><![CDATA[USE_MEMORY_LIMITS <>1]]></Condition>
</Control>
<Control Id="MaxHeapEdit" Type="Edit" Property="MAXHEAP" Height="17" Width="40" X="20" Y="155">
<Condition Action="enable" >USE_MEMORY_LIMITS = 1</Condition>
<Condition Action="disable"><![CDATA[USE_MEMORY_LIMITS <>1]]></Condition>
</Control>
<Control Id="MaxHeapLabel2" Type="Text" X="65" Y="158" Width="250" Height="15" NoPrefix="yes" Text="MB">
<Condition Action="enable" >USE_MEMORY_LIMITS = 1</Condition>
<Condition Action="disable"><![CDATA[USE_MEMORY_LIMITS <>1]]></Condition>
</Control>
<Control Id="WarningLabel1" Type="Text" X="20" Y="190" Width="300" Height="10" NoPrefix="yes" Text="If invalid or incompatible values are detected, the default values will be used.">
<Condition Action="enable" >USE_MEMORY_LIMITS = 1</Condition>
<Condition Action="disable"><![CDATA[USE_MEMORY_LIMITS <>1]]></Condition>
</Control>
<Control Id="WarningLabel2" Type="Text" X="20" Y="200" Width="300" Height="10" NoPrefix="yes" Text="They can be changed later editing the redis.windows-service.conf file.">
<Condition Action="enable" >USE_MEMORY_LIMITS = 1</Condition>
<Condition Action="disable"><![CDATA[USE_MEMORY_LIMITS <>1]]></Condition>
</Control>
</Dialog>
</UI>
</Fragment>
</Wix>
+69 -48
View File
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension"
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension"
xmlns:fw="http://schemas.microsoft.com/wix/FirewallExtension">
<!--
<!--
64-bit installer
Example installation (command-line):
@@ -18,55 +18,76 @@
-->
<Product Id="*"
Name="Redis on Windows"
Language="1033"
Version="2.8.2102"
Manufacturer="MSOpenTech"
UpgradeCode="{05410198-7212-4FC4-B7C8-AFEFC3DA0FBC}">
<Package InstallerVersion="200"
Compressed="yes"
InstallScope="perMachine" />
<Product Id="*"
Name="Redis on Windows"
Language="1033"
Version="2.8.2104"
Manufacturer="MSOpenTech"
UpgradeCode="{05410198-7212-4FC4-B7C8-AFEFC3DA0FBC}">
<Package InstallerVersion="200"
Compressed="yes"
InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab="yes" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab="yes" />
<!--User interface hook-->
<UIRef Id="CustomInstallDir"/>
<!--Properties-->
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLFOLDER" />
<Property Id="ARPURLINFOABOUT" Value="https://github.com/MSOpenTech/redis" />
<Property Id="PORT" Value="6379" />
<Property Id="ADD_FIREWALL_RULE" Value="1" />
<Property Id="FIREWALL_SERVICE_STOPPED" Value="0" />
<!--Link-time variables-->
<WixVariable Id="WixUILicenseRtf" Value="License.rtf"/>
<WixVariable Id="WixUIDialogBmp" Value="Images/redis_background.jpg"/>
<WixVariable Id="WixUIBannerBmp" Value="Images/top_banner.jpg"/>
<WixVariable Id="DocumentationFolder" Value="..\..\setups\documentation"/>
<!--Link in custom actions, referencing one will pull in all-->
<CustomActionRef Id="ca_UpdateRedisConfig"/>
<!--User interface hook-->
<UIRef Id="CustomInstallDir"/>
<!--Features-->
<Feature Id="ProductFeature" Title="Redis" Level="1">
<ComponentGroupRef Id="FileComponents" />
<ComponentGroupRef Id="SymbolsComponents" />
<ComponentGroupRef Id="WindowsServiceComponents" />
<ComponentGroupRef Id="DocumentationComponents" />
</Feature>
</Product>
<!--Properties-->
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLFOLDER" />
<Property Id="ARPURLINFOABOUT" Value="https://github.com/MSOpenTech/redis" />
<Property Id="PORT" Value="6379" />
<Property Id="ADD_FIREWALL_RULE" Value="1" />
<Property Id="FIREWALL_SERVICE_STOPPED" Value="0" />
<Property Id="MAXMEMORY" Value="100" />
<Property Id="MAXHEAP" Value="150" />
<Property Id="USE_MEMORY_LIMITS" Secure="yes" />
<Property Id="ADD_INSTALLFOLDER_TO_PATH" Secure="yes" />
<Fragment>
<!--Directory structure to create-->
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFiles64Folder">
<Directory Id="INSTALLFOLDER" Name="Redis">
<Directory Id="LogsFolder" Name="Logs" />
<!--Link-time variables-->
<WixVariable Id="WixUILicenseRtf" Value="License.rtf"/>
<WixVariable Id="WixUIDialogBmp" Value="Images/redis_background.jpg"/>
<WixVariable Id="WixUIBannerBmp" Value="Images/top_banner.jpg"/>
<WixVariable Id="DocumentationFolder" Value="..\..\setups\documentation"/>
<!--Link in custom actions, referencing one will pull in all-->
<CustomActionRef Id="ca_UpdateRedisConfig"/>
<!--Features-->
<Feature Id="ProductFeature" Title="Redis" Level="1">
<ComponentGroupRef Id="FileComponents" />
<ComponentGroupRef Id="SymbolsComponents" />
<ComponentGroupRef Id="WindowsServiceComponents" />
<ComponentGroupRef Id="DocumentationComponents" />
<ComponentGroupRef Id="SetPathComponents" />
</Feature>
</Product>
<Fragment>
<ComponentGroup Id="SetPathComponents" Directory="INSTALLFOLDER">
<Component Id="SetEnvironmentVariables" Guid="{33F930D5-EE5D-4D2C-9DC9-6AE1E176BDCD}" KeyPath="yes">
<Condition>ADD_INSTALLFOLDER_TO_PATH</Condition>
<Environment Action="set"
Id="SetPath"
Name="PATH"
System="yes"
Value="[INSTALLFOLDER]"
Permanent="no"
Part="last"
/>
</Component>
</ComponentGroup>
</Fragment>
<Fragment>
<!--Directory structure to create-->
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFiles64Folder">
<Directory Id="INSTALLFOLDER" Name="Redis">
<Directory Id="LogsFolder" Name="Logs" />
</Directory>
</Directory>
</Directory>
</Directory>
</Directory>
</Fragment>
</Fragment>
</Wix>
+2
View File
@@ -44,6 +44,8 @@
<Compile Include="CustomActions.wxs" />
<Compile Include="Dialogs\CustomInstallDir.wxs" />
<Compile Include="Dialogs\FirewallDialog.wxs" />
<Compile Include="Dialogs\MaxMemoryDialog.wxs" />
<Compile Include="Dialogs\CustomInstallDirDlg.wxs" />
<Compile Include="Product.wxs" />
</ItemGroup>
<ItemGroup>
+1 -1
View File
@@ -3,7 +3,7 @@
<metadata>
<id>redis-64</id>
<title>Redis 64-bit</title>
<version>2.8.2102</version>
<version>2.8.2104</version>
<authors>Alexis Campailla, Enrico Giordani, Jonathan Pickett</authors>
<owners>Microsoft Open Technologies, Inc.</owners>
<description>A porting of Redis on Windows 64-bit.
+5 -5
View File
@@ -3,7 +3,7 @@
<metadata>
<id>redis-64</id>
<title>Redis 64-bit</title>
<version>2.8.2102</version>
<version>2.8.2104</version>
<authors>Alexis Campailla, Enrico Giordani, Jonathan Pickett</authors>
<owners>Microsoft Open Technologies, Inc.</owners>
<description>A porting of Redis on Windows 64-bit.
@@ -21,9 +21,9 @@ This package will install the Redis binaries in the default Nuget lib directory.
<releaseNotes>The release notes are available here: https://raw.githubusercontent.com/MSOpenTech/redis/2.8/Redis%20on%20Windows%20Release%20Notes.md</releaseNotes>
</metadata>
<files>
<file src="..\signed_binaries\*.exe" target=".\" />
<file src="..\signed_binaries\*.pdb" target=".\" />
<file src="..\signed_binaries\*.conf" target=".\" />
<file src="..\signed_binaries\*.docx" target=".\" />
<file src="..\signed_binaries\*.exe" target="tools" />
<file src="..\signed_binaries\*.pdb" target="tools" />
<file src="..\signed_binaries\*.conf" target="tools" />
<file src="..\signed_binaries\*.docx" target="tools" />
</files>
</package>
@@ -21,9 +21,9 @@ This package will install the Redis binaries in the default Nuget lib directory.
<releaseNotes>The release notes are available here: https://raw.githubusercontent.com/MSOpenTech/redis/2.8/Redis%20on%20Windows%20Release%20Notes.md</releaseNotes>
</metadata>
<files>
<file src="..\signed_binaries\*.exe" target=".\" />
<file src="..\signed_binaries\*.pdb" target=".\" />
<file src="..\signed_binaries\*.conf" target=".\" />
<file src="..\signed_binaries\*.docx" target=".\" />
<file src="..\signed_binaries\*.exe" target="tools" />
<file src="..\signed_binaries\*.pdb" target="tools" />
<file src="..\signed_binaries\*.conf" target="tools" />
<file src="..\signed_binaries\*.docx" target="tools" />
</files>
</package>
+3 -1
View File
@@ -292,7 +292,9 @@ public:
{ "current-epoch", &fp1 }, // sentinel current-epoch <epoch>
{ "leader-epoch", &fp2 }, // sentinel leader-epoch [name] [epoch]
{ "known-slave", &fp3 }, // sentinel known-slave <name> <ip> <port>
{ "known-sentinel", &fp4 } // sentinel known-sentinel <name> <ip> <port> [runid]
{ "known-sentinel", &fp4 }, // sentinel known-sentinel <name> <ip> <port> [runid]
{ "announce-ip", &fp1 }, // sentinel announce-ip <ip>
{ "announce-port", &fp1 } // sentinel announce-port <port>
};
}
+171 -111
View File
@@ -32,129 +32,189 @@ using namespace std;
#include "Win32_SmartHandle.h"
#include "EventLog.h"
void RedisEventLog::UninstallEventLogSource() {
SmartRegistryHandle appKey;
if (ERROR_SUCCESS == RegOpenKeyA(HKEY_LOCAL_MACHINE, cEventLogApplicitonPath.c_str(), appKey)) {
SmartRegistryHandle eventLogNameKey;
if (ERROR_SUCCESS == RegOpenKeyA(appKey, eventLogName.c_str(), eventLogNameKey)) {
if (ERROR_SUCCESS != RegDeleteKeyA(appKey, eventLogName.c_str())) {
throw std::system_error(GetLastError(), system_category(), "RegDeleteKeyA failed");
}
}
}
static bool eventLogEnabled = true;
static string eventLogIdentity = "redis";
SmartRegistryHandle eventLogKey;
if (ERROR_SUCCESS == RegOpenKeyA(HKEY_LOCAL_MACHINE, cEventLogPath.c_str(), eventLogKey)) {
SmartRegistryHandle eventServiceKey;
if (ERROR_SUCCESS == RegOpenKeyA(eventLogKey, cRedis.c_str(), eventServiceKey)) {
SmartRegistryHandle eventServiceSubKey;
if (ERROR_SUCCESS == RegOpenKeyA(eventServiceKey, cRedisServer.c_str(), eventServiceSubKey)) {
if (ERROR_SUCCESS != RegDeleteKeyA(eventServiceKey, cRedisServer.c_str())) {
throw std::system_error(GetLastError(), system_category(), "RegDeleteKeyA failed");
}
if (ERROR_SUCCESS != RegDeleteKeyA(eventLogKey, cRedis.c_str())) {
throw std::system_error(GetLastError(), system_category(), "RegDeleteKeyA failed");
}
}
}
}
void RedisEventLog::SetEventLogIdentity(const char* identity) {
eventLogIdentity = string(identity);
}
void RedisEventLog::UninstallEventLogSource() {
SmartRegistryHandle appKey;
if (ERROR_SUCCESS == RegOpenKeyA(HKEY_LOCAL_MACHINE, cEventLogApplicitonPath.c_str(), appKey)) {
SmartRegistryHandle eventLogNameKey;
if (ERROR_SUCCESS == RegOpenKeyA(appKey, eventLogName.c_str(), eventLogNameKey)) {
if (ERROR_SUCCESS != RegDeleteKeyA(appKey, eventLogName.c_str())) {
throw std::system_error(GetLastError(), system_category(), "RegDeleteKeyA failed");
}
}
}
SmartRegistryHandle eventLogKey;
if (ERROR_SUCCESS == RegOpenKeyA(HKEY_LOCAL_MACHINE, cEventLogPath.c_str(), eventLogKey)) {
SmartRegistryHandle eventServiceKey;
if (ERROR_SUCCESS == RegOpenKeyA(eventLogKey, cRedis.c_str(), eventServiceKey)) {
SmartRegistryHandle eventServiceSubKey;
if (ERROR_SUCCESS == RegOpenKeyA(eventServiceKey, cRedisServer.c_str(), eventServiceSubKey)) {
if (ERROR_SUCCESS != RegDeleteKeyA(eventServiceKey, cRedisServer.c_str())) {
throw std::system_error(GetLastError(), system_category(), "RegDeleteKeyA failed");
}
if (ERROR_SUCCESS != RegDeleteKeyA(eventLogKey, cRedis.c_str())) {
throw std::system_error(GetLastError(), system_category(), "RegDeleteKeyA failed");
}
}
}
}
}
// sets up the registry keys required for the EventViewer message filter
void RedisEventLog::InstallEventLogSource(string appPath) {
SmartRegistryHandle eventLogKey;
if (ERROR_SUCCESS != RegOpenKeyA(HKEY_LOCAL_MACHINE, cEventLogPath.c_str(), eventLogKey)) {
throw std::system_error(GetLastError(), system_category(), "RegOpenKey failed");
}
SmartRegistryHandle redis1;
if (ERROR_SUCCESS != RegOpenKeyA(eventLogKey, cRedis.c_str(), redis1)) {
if (ERROR_SUCCESS != RegCreateKeyA(eventLogKey, cRedis.c_str(), redis1)) {
throw std::system_error(GetLastError(), system_category(), "RegCreateKeyA failed");
}
}
SmartRegistryHandle redisserver;
if (ERROR_SUCCESS != RegOpenKeyA(redis1, cRedisServer.c_str(), redisserver)) {
if (ERROR_SUCCESS != RegCreateKeyA(redis1, cRedisServer.c_str(), redisserver)) {
throw std::system_error(GetLastError(), system_category(), "RegCreateKeyA failed");
}
}
DWORD value = 0;
DWORD type = REG_DWORD;
DWORD size = sizeof(DWORD);
if (ERROR_SUCCESS != RegQueryValueExA(redisserver, cTypesSupported.c_str(), 0, &type, NULL, &size)) {
if (ERROR_SUCCESS != RegSetValueExA(redisserver, cTypesSupported.c_str(), 0, REG_DWORD, (const BYTE*)&value, sizeof(DWORD))) {
throw std::system_error(GetLastError(), system_category(), "RegSetValueExA failed");
}
}
type = REG_SZ;
size = 0;
if (ERROR_SUCCESS != RegQueryValueExA(redisserver, cEventMessageFile.c_str(), 0, &type, NULL, &size)) {
if (ERROR_SUCCESS != RegSetValueExA(redisserver, cEventMessageFile.c_str(), 0, REG_SZ, (BYTE*)appPath.c_str(), (DWORD)appPath.length())) {
throw std::system_error(GetLastError(), system_category(), "RegSetValueExA failed");
}
}
SmartRegistryHandle eventLogKey;
if (ERROR_SUCCESS != RegOpenKeyA(HKEY_LOCAL_MACHINE, cEventLogPath.c_str(), eventLogKey)) {
throw std::system_error(GetLastError(), system_category(), "RegOpenKey failed");
}
SmartRegistryHandle redis1;
if (ERROR_SUCCESS != RegOpenKeyA(eventLogKey, cRedis.c_str(), redis1)) {
if (ERROR_SUCCESS != RegCreateKeyA(eventLogKey, cRedis.c_str(), redis1)) {
throw std::system_error(GetLastError(), system_category(), "RegCreateKeyA failed");
}
}
SmartRegistryHandle redisserver;
if (ERROR_SUCCESS != RegOpenKeyA(redis1, cRedisServer.c_str(), redisserver)) {
if (ERROR_SUCCESS != RegCreateKeyA(redis1, cRedisServer.c_str(), redisserver)) {
throw std::system_error(GetLastError(), system_category(), "RegCreateKeyA failed");
}
}
DWORD value = 0;
DWORD type = REG_DWORD;
DWORD size = sizeof(DWORD);
if (ERROR_SUCCESS != RegQueryValueExA(redisserver, cTypesSupported.c_str(), 0, &type, NULL, &size)) {
if (ERROR_SUCCESS != RegSetValueExA(redisserver, cTypesSupported.c_str(), 0, REG_DWORD, (const BYTE*) &value, sizeof(DWORD))) {
throw std::system_error(GetLastError(), system_category(), "RegSetValueExA failed");
}
}
type = REG_SZ;
size = 0;
if (ERROR_SUCCESS != RegQueryValueExA(redisserver, cEventMessageFile.c_str(), 0, &type, NULL, &size)) {
if (ERROR_SUCCESS != RegSetValueExA(redisserver, cEventMessageFile.c_str(), 0, REG_SZ, (BYTE*) appPath.c_str(), (DWORD) appPath.length())) {
throw std::system_error(GetLastError(), system_category(), "RegSetValueExA failed");
}
}
SmartRegistryHandle application;
if (ERROR_SUCCESS != RegOpenKeyA(eventLogKey, cApplication.c_str() , application)) {
throw std::system_error(GetLastError(), system_category(), "RegCreateKeyA failed");
}
SmartRegistryHandle redis2;
if (ERROR_SUCCESS != RegOpenKeyA(application, cRedis.c_str(), redis2)) {
if (ERROR_SUCCESS != RegCreateKeyA(application, cRedis.c_str(), redis2)) {
throw std::system_error(GetLastError(), system_category(), "RegCreateKeyA failed");
}
}
type = REG_DWORD;
size = 0;
if (ERROR_SUCCESS != RegQueryValueExA(redis2, cTypesSupported.c_str(), 0, &type, NULL, &size)) {
if (ERROR_SUCCESS != RegSetValueExA(redis2, cTypesSupported.c_str(), 0, REG_DWORD, (const BYTE*)&value, sizeof(DWORD))) {
throw std::system_error(GetLastError(), system_category(), "RegSetValueExA failed");
}
}
if (ERROR_SUCCESS != RegQueryValueExA(redis2, cEventMessageFile.c_str(), 0, &type, NULL, &size)) {
if (ERROR_SUCCESS != RegSetValueExA(redis2, cEventMessageFile.c_str(), 0, REG_SZ, (BYTE*)appPath.c_str(), (DWORD)appPath.length())) {
throw std::system_error(GetLastError(), system_category(), "RegSetValueExA failed");
}
}
SmartRegistryHandle application;
if (ERROR_SUCCESS != RegOpenKeyA(eventLogKey, cApplication.c_str(), application)) {
throw std::system_error(GetLastError(), system_category(), "RegCreateKeyA failed");
}
SmartRegistryHandle redis2;
if (ERROR_SUCCESS != RegOpenKeyA(application, cRedis.c_str(), redis2)) {
if (ERROR_SUCCESS != RegCreateKeyA(application, cRedis.c_str(), redis2)) {
throw std::system_error(GetLastError(), system_category(), "RegCreateKeyA failed");
}
}
type = REG_DWORD;
size = 0;
if (ERROR_SUCCESS != RegQueryValueExA(redis2, cTypesSupported.c_str(), 0, &type, NULL, &size)) {
if (ERROR_SUCCESS != RegSetValueExA(redis2, cTypesSupported.c_str(), 0, REG_DWORD, (const BYTE*) &value, sizeof(DWORD))) {
throw std::system_error(GetLastError(), system_category(), "RegSetValueExA failed");
}
}
if (ERROR_SUCCESS != RegQueryValueExA(redis2, cEventMessageFile.c_str(), 0, &type, NULL, &size)) {
if (ERROR_SUCCESS != RegSetValueExA(redis2, cEventMessageFile.c_str(), 0, REG_SZ, (BYTE*) appPath.c_str(), (DWORD) appPath.length())) {
throw std::system_error(GetLastError(), system_category(), "RegSetValueExA failed");
}
}
}
void RedisEventLog::LogMessageToEventLog(LPCSTR msg, const WORD type) {
DWORD eventID;
switch (type) {
case EVENTLOG_ERROR_TYPE:
eventID = MSG_ERROR_1;
break;
case EVENTLOG_WARNING_TYPE:
eventID = MSG_WARNING_1;
break;
case EVENTLOG_INFORMATION_TYPE:
eventID = MSG_INFO_1;
break;
default:
std::cerr << "Unrecognized type: " << type << "\n";
eventID = MSG_INFO_1;
break;
}
void RedisEventLog::LogMessage(LPCSTR msg, const WORD type) {
DWORD eventID;
switch (type) {
case EVENTLOG_ERROR_TYPE:
eventID = MSG_ERROR_1;
break;
case EVENTLOG_WARNING_TYPE:
eventID = MSG_WARNING_1;
break;
case EVENTLOG_INFORMATION_TYPE:
eventID = MSG_INFO_1;
break;
default:
std::cerr << "Unrecognized type: " << type << "\n";
eventID = MSG_INFO_1;
break;
}
HANDLE hEventLog = RegisterEventSourceA(0, this->eventLogName.c_str());
HANDLE hEventLog = RegisterEventSourceA(0, this->eventLogName.c_str());
if (0 == hEventLog) {
std::cerr << "Failed open source '" << this->eventLogName << "': " << GetLastError() << endl;
} else {
if (FALSE == ReportEventA( hEventLog, type, 0, eventID, 0, 1, 0, &msg, 0)) {
std::cerr << "Failed to write message: " << GetLastError() << endl;
}
if (0 == hEventLog) {
std::cerr << "Failed open source '" << this->eventLogName << "': " << GetLastError() << endl;
} else {
if (FALSE == ReportEventA(hEventLog, type, 0, eventID, 0, 1, 0, &msg, 0)) {
std::cerr << "Failed to write message: " << GetLastError() << endl;
}
DeregisterEventSource(hEventLog);
}
DeregisterEventSource(hEventLog);
}
}
extern "C" void WriteEventLog(const char* sysLogInstance, const char* msg) {
try {
stringstream ss;
ss << "syslog-ident = " << sysLogInstance << endl;
void RedisEventLog::LogError(string msg) {
try {
if (eventLogEnabled == true) {
stringstream ss;
ss << "syslog-ident = " << eventLogIdentity << endl;
ss << msg;
RedisEventLog().LogMessage(ss.str().c_str(), EVENTLOG_ERROR_TYPE);
}
}
catch (...) {
}
}
string RedisEventLog::GetEventLogIdentity() {
return eventLogIdentity;
}
void RedisEventLog::EnableEventLog(bool enabled) {
eventLogEnabled = enabled;
}
bool RedisEventLog::IsEventLogEnabled() {
return eventLogEnabled;
}
extern "C" void setSyslogEnabled(int enabled) {
try {
if (enabled == 1) {
RedisEventLog().EnableEventLog(true);
} else {
RedisEventLog().EnableEventLog(false);
}
}
catch (...) {}
}
extern "C" void setSyslogIdent(char* identity) {
try {
RedisEventLog().SetEventLogIdentity(identity);
}
catch (...) {}
}
extern "C" void WriteEventLog(const char* msg) {
try {
stringstream ss;
ss << "syslog-ident = " << RedisEventLog().GetEventLogIdentity() << endl;
ss << msg;
RedisEventLog().LogMessageToEventLog(ss.str().c_str(),EVENTLOG_INFORMATION_TYPE);
} catch (...) {
}
RedisEventLog().LogMessage(ss.str().c_str(), EVENTLOG_INFORMATION_TYPE);
}
catch (...) {}
}
extern "C" int IsEventLogEnabled() {
try {
if (RedisEventLog().IsEventLogEnabled() == true) {
return 1;
}
}
catch (...) {}
return 0;
}
+23 -14
View File
@@ -28,29 +28,38 @@ using namespace std;
typedef class RedisEventLog {
public:
~RedisEventLog() {}
~RedisEventLog() {}
void InstallEventLogSource(string appPath);
void UninstallEventLogSource();
void InstallEventLogSource(string appPath);
void UninstallEventLogSource();
void LogMessageToEventLog(LPCSTR msg, const WORD type);
void SetEventLogIdentity(const char* identity);
void LogMessage(LPCSTR msg, const WORD type);
void LogError(string msg);
string GetEventLogIdentity();
void EnableEventLog(bool enabled);
bool IsEventLogEnabled();
private:
const string eventLogName = "redis";
const string cEventLogPath = "SYSTEM\\CurrentControlSet\\Services\\EventLog\\";
const string cEventLogApplicitonPath = cEventLogPath + "Application\\";
const string cRedis = "redis";
const string cEventMessageFile = "EventMessageFile";
const string cRedisServer = "redis-server";
const string cTypesSupported = "TypesSupported";
const string cApplication = "Application";
const string eventLogName = "redis";
const string cEventLogPath = "SYSTEM\\CurrentControlSet\\Services\\EventLog\\";
const string cEventLogApplicitonPath = cEventLogPath + "Application\\";
const string cRedis = "redis";
const string cEventMessageFile = "EventMessageFile";
const string cRedisServer = "redis-server";
const string cTypesSupported = "TypesSupported";
const string cApplication = "Application";
} RedisEventLog;
extern "C" {
#endif
void WriteEventLog(const char* sysLogInstance, const char* msg);
void setSyslogEnabled(int enabled);
void setSyslogIdent(char* identity);
int IsEventLogEnabled();
void WriteEventLog(const char* msg);
#ifdef __cplusplus
}
+10 -2
View File
@@ -193,6 +193,10 @@ BOOL FDAPI_AcceptEx(int listenRFD, int acceptRFD, PVOID lpOutputBuffer,
const DWORD SIO_LOOPBACK_FAST_PATH = 0x98000010; // from Win8 SDK
#endif
#ifndef _WIN32_WINNT_WIN8
#define _WIN32_WINNT_WIN8 0x0602
#endif
void EnableFastLoopback(SOCKET socket) {
// if Win8+, use fast path option on loopback
if (IsWindowsVersionAtLeast(HIBYTE(_WIN32_WINNT_WIN8), LOBYTE(_WIN32_WINNT_WIN8), 0)) {
@@ -736,10 +740,14 @@ int redis_listen_impl(int rfd, int backlog) {
SOCKET socket = RFDMap::getInstance().lookupSocket(rfd);
if (socket != INVALID_SOCKET) {
EnableFastLoopback(socket);
return f_listen(socket, backlog);
int result = f_listen(socket, backlog);
if (result != 0){
errno = WSAGetLastError();
}
return result;
} else {
errno = EBADF;
return 0;
return -1;
}
} CATCH_AND_REPORT();
+2 -2
View File
@@ -108,7 +108,7 @@ link.exe -dll -noentry resources/EventLog.res -out:$(TargetDir)EventLog.dll
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120_xp</PlatformToolset>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
@@ -121,7 +121,7 @@ link.exe -dll -noentry resources/EventLog.res -out:$(TargetDir)EventLog.dll
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120_xp</PlatformToolset>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
+45 -28
View File
@@ -45,6 +45,7 @@
#include "Win32_RedisLog.h"
#include "Win32_StackTrace.h"
#include "Win32_ThreadControl.h"
#include "Win32_EventLog.h"
#include <vector>
#include <map>
@@ -61,7 +62,6 @@ using namespace std;
#define PAGE_REVERT_TO_FILE_MAP 0x80000000 // From Win8.1 SDK
#endif
const int64_t cSentinelHeapSize = 30 * 1024 * 1024;
extern "C" int checkForSentinelMode(int argc, char **argv);
extern "C" void InitTimeFunctions();
@@ -216,6 +216,7 @@ bool ReportSpecialSystemErrors(int error) {
"\n"
"Redis can not continue. Exiting."
);
RedisEventLog().LogError("Failed to allocate the memory mapped file.");
return true;
}
@@ -239,6 +240,7 @@ bool ReportSpecialSystemErrors(int error) {
"\n"
"Redis can not continue. Exiting."
);
RedisEventLog().LogError("Disk full error while allocating the memory mapped file.");
return true;
}
@@ -333,11 +335,13 @@ BOOL QForkChildInit(HANDLE QForkConrolMemoryMapHandle, DWORD ParentProcessID) {
}
catch(std::system_error syserr) {
if (ReportSpecialSystemErrors(syserr.code().value()) == false) {
::redisLog(REDIS_WARNING, "QForkChildInit: system error caught. error code=0x%08x, message=%s\n", syserr.code().value(), syserr.what());
RedisEventLog().LogError("QForkChildInit: system error. " + string(syserr.what()));
::redisLog(REDIS_WARNING, "QForkChildInit: system error. ErrCode: 0x%08x, ErrMsg: %s\n", syserr.code().value(), syserr.what());
}
}
catch(std::runtime_error runerr) {
::redisLog(REDIS_WARNING, "QForkChildInit: runtime error caught. message=%s\n", runerr.what());
RedisEventLog().LogError("QForkChildInit: runtime error. " + string(runerr.what()));
::redisLog(REDIS_WARNING, "QForkChildInit: runtime error. ErrMsg: %s\n", runerr.what());
}
if (g_pQForkControl != NULL) {
@@ -495,7 +499,7 @@ BOOL QForkParentInit(__int64 maxheapBytes) {
throw std::system_error(
GetLastError(),
system_category(),
"CreateFileW failed.");
"CreateFile failed");
}
SIZE_T mmSize = g_pQForkControl->availableBlocksInHeap * cAllocationGranularity;
@@ -580,14 +584,17 @@ BOOL QForkParentInit(__int64 maxheapBytes) {
}
catch(std::system_error syserr) {
if (ReportSpecialSystemErrors(syserr.code().value()) == false) {
::redisLog(REDIS_WARNING, "QForkParentInit: system error caught. error code=0x%08x, message=%s\n", syserr.code().value(), syserr.what());
RedisEventLog().LogError("QForkParentInit: system error. " + string(syserr.what()));
::redisLog(REDIS_WARNING, "QForkParentInit: system error. ErrCode: 0x%08x, ErrMsg: %s\n", syserr.code().value(), syserr.what());
}
}
catch(std::runtime_error runerr) {
::redisLog(REDIS_WARNING, "QForkParentInit: runtime error caught. message=%s\n", runerr.what());
RedisEventLog().LogError("QForkParentInit: runtime error. " + string(runerr.what()));
::redisLog(REDIS_WARNING, "QForkParentInit: runtime error. ErrMsg: %s\n", runerr.what());
}
catch(...) {
::redisLog(REDIS_WARNING, "QForkParentInit: other exception caught.\n");
catch(std::exception ex) {
RedisEventLog().LogError("QForkParentInit: an exception occurred. " + string(ex.what()));
::redisLog(REDIS_WARNING, "QForkParentInit: an exception occurred. ErrMsg: %s\n", ex.what());
}
return FALSE;
}
@@ -636,8 +643,11 @@ LONG CALLBACK VectoredHeapMapper(PEXCEPTION_POINTERS info) {
::redisLog(REDIS_WARNING, "The system paging file is too small for this operation to complete.");
::redisLog(REDIS_WARNING, "See https://github.com/MSOpenTech/redis/wiki/Memory-Configuration");
::redisLog(REDIS_WARNING, "for more information on configuring the system paging file for Redis.");
RedisEventLog().LogError("QForkParentInit: an exception occurred. The system paging file is too small for this operation to complete.");
}
::redisLog(REDIS_WARNING, "\n=== REDIS BUG REPORT END. Make sure to include from START to END. ===\n\n");
// Call exit to avoid executing the Unhandled Exceptiont Handler since we don't need a call stack
exit(1);
}
@@ -650,7 +660,6 @@ LONG CALLBACK VectoredHeapMapper(PEXCEPTION_POINTERS info) {
// QFork API
StartupStatus QForkStartup(int argc, char** argv) {
bool foundChildFlag = false;
int sentinelMode = checkForSentinelMode(argc, argv);
HANDLE QForkConrolMemoryMapHandle = NULL;
DWORD PPID = 0;
__int64 maxheapBytes = -1;
@@ -727,17 +736,12 @@ StartupStatus QForkStartup(int argc, char** argv) {
}
}
if( maxheapBytes == -1 ) {
if (sentinelMode == 1) {
// Sentinel mode does not need a large heap. This conserves disk space and page file reservation requirements.
maxheapBytes = cSentinelHeapSize;
} else {
if (maxheapBytes == -1) {
#ifdef _WIN64
maxheapBytes = perfinfo.PhysicalTotal * Globals::pageSize;
maxheapBytes = perfinfo.PhysicalTotal * Globals::pageSize;
#else
maxheapBytes = cDefaultmaxHeap32Bit;
maxheapBytes = cDefaultmaxHeap32Bit;
#endif
}
}
if (foundChildFlag) {
@@ -1268,9 +1272,9 @@ void SetupLogging() {
string syslogIdent = (g_argMap.find(cSyslogIdent) != g_argMap.end() ? g_argMap[cSyslogIdent].at(0).at(0) : cDefaultSyslogIdent);
string logFileName = (g_argMap.find(cLogfile) != g_argMap.end() ? g_argMap[cLogfile].at(0).at(0) : cDefaultLogfile);
setSyslogEnabled(syslogEnabled);
RedisEventLog().EnableEventLog(syslogEnabled);
if (syslogEnabled) {
setSyslogIdent(syslogIdent.c_str());
RedisEventLog().SetEventLogIdentity(syslogIdent.c_str());
} else {
setLogFile(logFileName.c_str());
}
@@ -1298,15 +1302,24 @@ extern "C"
StackTraceInit();
InitThreadControl();
} catch (system_error syserr) {
string errMsg = string("System error during startup: ") + syserr.what();
RedisEventLog().LogError(errMsg);
cout << errMsg << endl;
exit(-1);
} catch (runtime_error runerr) {
cout << runerr.what() << endl;
string errMsg = string("System error during startup: ") + runerr.what();
RedisEventLog().LogError(errMsg);
cout << errMsg << endl;
exit(-1);
} catch (invalid_argument &iaerr) {
cout << iaerr.what() << endl;
string errMsg = string("Invalid argument during startup: ") + iaerr.what();
RedisEventLog().LogError(errMsg);
cout << errMsg << endl;
exit(-1);
} catch (exception othererr) {
cout << othererr.what() << endl;
string errMsg = string("An exception occurred during startup: ") + othererr.what();
RedisEventLog().LogError(errMsg);
cout << errMsg << endl;
exit(-1);
}
@@ -1322,6 +1335,7 @@ extern "C"
FILE_ATTRIBUTE_NORMAL,
NULL);
#endif
int sentinelMode = checkForSentinelMode(argc, argv);
// service commands do not launch an instance of redis directly
if (HandleServiceCommands(argc, argv) == TRUE) {
@@ -1329,7 +1343,7 @@ extern "C"
}
// Setup memory allocation scheme for persistence mode
if (IsPersistenceAvailable() == TRUE) {
if (IsPersistenceAvailable() == TRUE && sentinelMode == 0) {
g_malloc = dlmalloc;
g_calloc = dlcalloc;
g_realloc = dlrealloc;
@@ -1343,7 +1357,7 @@ extern "C"
g_msize = _msize;
}
if (IsPersistenceAvailable() == TRUE) {
if (IsPersistenceAvailable() == TRUE && sentinelMode == 0) {
StartupStatus status = QForkStartup(argc, argv);
if (status == ssCONTINUE_AS_PARENT) {
int retval = redis_main(argc, argv);
@@ -1364,11 +1378,14 @@ extern "C"
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());
RedisEventLog().LogError(string("Main: system error. ") + syserr.what());
::redisLog(REDIS_WARNING, "Main: system error. ErrCode: 0x%08x, ErrMsg: %s\n", syserr.code().value(), syserr.what());
} catch (std::runtime_error runerr) {
::redisLog(REDIS_WARNING, "main: runtime error caught. message=%s\n", runerr.what());
} catch (...) {
::redisLog(REDIS_WARNING, "main: other exception caught.\n");
RedisEventLog().LogError(string("Main: runtime error. ") + runerr.what());
::redisLog(REDIS_WARNING, "Main: runtime error. ErrMsg: %s\n", runerr.what());
} catch (std::exception ex) {
RedisEventLog().LogError(string("Main: an exception occurred. ") + ex.what());
::redisLog(REDIS_WARNING, "Main: an exception occurred. ErrMsg: %s\n", ex.what());
}
}
}
+3 -11
View File
@@ -36,19 +36,9 @@
static const char ellipsis[] = "[...]";
static const char ellipsisWithNewLine[] = "[...]\n";
static int verbosity = REDIS_WARNING;
static int syslogEnabled = 0;
static char syslogIdent[MAX_PATH];
static HANDLE hLogFile = INVALID_HANDLE_VALUE;
static int isStdout = 0;
void setSyslogEnabled(int flag) {
syslogEnabled = flag;
}
void setSyslogIdent(const char* ident) {
strcpy_s(syslogIdent, MAX_PATH, ident);
}
void setLogVerbosityLevel(int level)
{
verbosity = level;
@@ -163,7 +153,9 @@ void redisLogRaw(int level, const char *msg) {
FlushFileBuffers(hLogFile);
#endif
if (syslogEnabled) WriteEventLog(syslogIdent, msg);
if (IsEventLogEnabled() == 1) {
WriteEventLog(msg);
}
}
/* Like redisLogRaw() but with printf-alike support. This is the function that
-2
View File
@@ -39,8 +39,6 @@
extern "C" {
#endif
void setSyslogEnabled(int flag);
void setSyslogIdent(const char* ident);
void setLogVerbosityLevel(int level);
void setLogFile (const char* logFileName);
void redisLogRaw(int level, const char *msg);
+13 -14
View File
@@ -122,8 +122,8 @@ int WSIOCP_QueueAccept(int listenfd) {
} else {
errno = WSAGetLastError();
sockstate->masks &= ~ACCEPT_PENDING;
close(acceptfd);
accsockstate->masks = 0;
close(acceptfd);
FreeMemoryNoCOW(areq->buf);
FreeMemoryNoCOW(areq);
return -1;
@@ -171,25 +171,24 @@ int WSIOCP_SocketAttach(int fd) {
/* Listen using extension function to get faster accepts */
int WSIOCP_Listen(int rfd, int backlog) {
aeSockState *sockstate;
const GUID wsaid_acceptex = WSAID_ACCEPTEX;
const GUID wsaid_acceptexaddrs = WSAID_GETACCEPTEXSOCKADDRS;
if ((sockstate = WSIOCP_GetSocketState(rfd)) == NULL) {
aeSockState *sockstate = WSIOCP_GetSocketState(rfd);
if (sockstate == NULL) {
errno = WSAEINVAL;
return SOCKET_ERROR;
}
WSIOCP_SocketAttach(rfd);
if (WSIOCP_SocketAttach(rfd) != 0) {
return SOCKET_ERROR;
}
sockstate->masks |= LISTEN_SOCK;
if (listen(rfd, backlog) == 0) {
if (WSIOCP_QueueAccept(rfd) == -1) {
errno = WSAGetLastError();
return SOCKET_ERROR;
}
} else {
errno = WSAGetLastError();
if (listen(rfd, backlog) != 0) {
return SOCKET_ERROR;
}
if (WSIOCP_QueueAccept(rfd) != 0) {
return SOCKET_ERROR;
}
return 0;
+19 -12
View File
@@ -109,12 +109,14 @@ int replace_rename(const char *src, const char *dst) {
return 0;
} else {
errno = GetLastError();
if (errno != 5) break;
if (errno != 5) {
break;
}
retries--;
if (retries == 0) {
retries = 50;
Sleep(10);
break;
}
Sleep(10);
}
}
/* On error we will return generic error code without GetLastError() */
@@ -659,23 +661,28 @@ char *ctime_r(const time_t *clock, char *buf) {
}
int truncate(const char *path, PORT_LONGLONG length) {
LARGE_INTEGER newSize;
HANDLE toTruncate;
toTruncate = CreateFileA(path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
HANDLE toTruncate = CreateFileA(path,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_WRITE | FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
0,
NULL);
if (toTruncate != INVALID_HANDLE_VALUE) {
int result = 0;
LARGE_INTEGER newSize;
newSize.QuadPart = length;
if (FALSE == (SetFilePointerEx(toTruncate, newSize, NULL, FILE_BEGIN) && SetEndOfFile(toTruncate))) {
if (FALSE == (SetFilePointerEx(toTruncate, newSize, NULL, FILE_BEGIN)
&& SetEndOfFile(toTruncate))) {
errno = ENOENT;
return -1;
} else {
return 0;
result = -1;
}
CloseHandle(toTruncate);
return result;
} else {
errno = ENOENT;
return -1;
}
}
#endif
+1 -1
View File
@@ -1399,7 +1399,7 @@ void backgroundRewriteDoneHandler(int exitcode, int bysignal) {
cleanup:
aofRewriteBufferReset();
aofRemoveTempFile(server.aof_child_pid);
aofRemoveTempFile(IF_WIN32(getpid(), server.aof_child_pid));
server.aof_child_pid = -1;
server.aof_rewrite_time_last = time(NULL)-server.aof_rewrite_time_start;
server.aof_rewrite_time_start = -1;
+3 -4
View File
@@ -29,7 +29,8 @@
*/
#ifdef _WIN32
#include "win32_Interop/win32_types.h"
#include "Win32_Interop/win32_types.h"
#include "Win32_Interop/Win32_EventLog.h"
#endif
#include "redis.h"
@@ -237,9 +238,7 @@ void loadServerConfigFromString(char *config) {
setSyslogIdent(server.syslog_ident);
#endif
} else if (!strcasecmp(argv[0], "syslog-facility") && argc == 2) {
#ifdef _WIN32
// Skip error - just ignore syslog-facility
#else
#ifndef _WIN32 // On Windows ignore syslog-facility
int i;
for (i = 0; validSyslogFacilities[i].name; i++) {
+1 -1
View File
@@ -1 +1 @@
#define REDIS_VERSION "2.8.2102"
#define REDIS_VERSION "2.8.2104"