summaryrefslogtreecommitdiff
path: root/win/packaging/ca/CustomAction.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'win/packaging/ca/CustomAction.cpp')
-rw-r--r--win/packaging/ca/CustomAction.cpp170
1 files changed, 161 insertions, 9 deletions
diff --git a/win/packaging/ca/CustomAction.cpp b/win/packaging/ca/CustomAction.cpp
index b856bc5f651..81c9f7eea92 100644
--- a/win/packaging/ca/CustomAction.cpp
+++ b/win/packaging/ca/CustomAction.cpp
@@ -29,6 +29,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <winservice.h>
+#define ONE_MB 1048576
UINT ExecRemoveDataDirectory(wchar_t *dir)
{
/* Strip stray backslash */
@@ -436,16 +437,49 @@ LExit:
return WcaFinalize(er);
}
-
-
+/*
+ Get maximum size of the buffer process can allocate.
+ this is calculated as min(RAM,virtualmemorylimit)
+ For 32bit processes, virtual address memory is 2GB (x86 OS)
+ or 4GB(x64 OS).
+
+ Fragmentation due to loaded modules, heap and stack
+ limit maximum size of continous memory block further,
+ so that limit for 32 bit process is about 1200 on 32 bit OS
+ or 2000 MB on 64 bit OS(found experimentally).
+*/
+unsigned long long GetMaxBufferSize(unsigned long long totalPhys)
+{
+#ifdef _M_IX86
+ BOOL wow64;
+ if (IsWow64Process(GetCurrentProcess(), &wow64))
+ return min(totalPhys, 2000ULL*ONE_MB);
+ else
+ return min(totalPhys, 1200ULL*ONE_MB);
+#else
+ return totalPhys;
+#endif
+}
+/*
+ Checks SERVICENAME, PORT and BUFFERSIZE parameters
+*/
extern "C" UINT __stdcall CheckDatabaseProperties (MSIHANDLE hInstall)
{
wchar_t ServiceName[MAX_PATH]={0};
wchar_t SkipNetworking[MAX_PATH]={0};
+ wchar_t QuickConfig[MAX_PATH]={0};
wchar_t Port[6];
+ wchar_t BufferPoolSize[16];
DWORD PortLen=6;
bool haveInvalidPort=false;
const wchar_t *ErrorMsg=0;
+ HRESULT hr= S_OK;
+ UINT er= ERROR_SUCCESS;
+
+
+ hr = WcaInitialize(hInstall, __FUNCTION__);
+ ExitOnFailure(hr, "Failed to initialize");
+ WcaLog(LOGMSG_STANDARD, "Initialized.");
DWORD ServiceNameLen = MAX_PATH;
MsiGetPropertyW (hInstall, L"SERVICENAME", ServiceName, &ServiceNameLen);
@@ -454,7 +488,7 @@ extern "C" UINT __stdcall CheckDatabaseProperties (MSIHANDLE hInstall)
if(ServiceNameLen > 256)
{
ErrorMsg= L"Invalid service name. The maximum length is 256 characters.";
- goto err;
+ goto LExit;
}
for(DWORD i=0; i< ServiceNameLen;i++)
{
@@ -464,7 +498,7 @@ extern "C" UINT __stdcall CheckDatabaseProperties (MSIHANDLE hInstall)
ErrorMsg =
L"Invalid service name. Forward slash and back slash are forbidden."
L"Single and double quotes are also not permitted.";
- goto err;
+ goto LExit;
}
}
if(CheckServiceExists(ServiceName))
@@ -472,7 +506,7 @@ extern "C" UINT __stdcall CheckDatabaseProperties (MSIHANDLE hInstall)
ErrorMsg=
L"A service with the same name already exists. "
L"Please use a different name.";
- goto err;
+ goto LExit;
}
}
@@ -508,7 +542,7 @@ extern "C" UINT __stdcall CheckDatabaseProperties (MSIHANDLE hInstall)
{
ErrorMsg =
L"Invalid port number. Please use a number between 1025 and 65535.";
- goto err;
+ goto LExit;
}
short port = (short)_wtoi(Port);
@@ -517,15 +551,133 @@ extern "C" UINT __stdcall CheckDatabaseProperties (MSIHANDLE hInstall)
ErrorMsg =
L"The TCP Port you selected is already in use. "
L"Please choose a different port.";
- goto err;
+ goto LExit;
}
}
+
+
+ DWORD QuickConfigLen = MAX_PATH;
+ MsiGetPropertyW (hInstall, L"STDCONFIG", QuickConfig, &QuickConfigLen);
+ if(QuickConfig[0] !=0)
+ {
+ MEMORYSTATUSEX memstatus;
+ memstatus.dwLength =sizeof(memstatus);
+ wchar_t invalidValueMsg[256];
-err:
+ if (!GlobalMemoryStatusEx(&memstatus))
+ {
+ WcaLog(LOGMSG_STANDARD, "Error %u from GlobalMemoryStatusEx",
+ GetLastError());
+ er= ERROR_INSTALL_FAILURE;
+ goto LExit;
+ }
+ DWORD BufferPoolSizeLen= 16;
+ MsiGetPropertyW(hInstall, L"BUFFERPOOLSIZE", BufferPoolSize, &BufferPoolSizeLen);
+ /* Strip spaces */
+ for(DWORD i=BufferPoolSizeLen-1; i > 0; i--)
+ {
+ if(BufferPoolSize[i]== ' ')
+ BufferPoolSize[i] = 0;
+ }
+ unsigned long long availableMemory=
+ GetMaxBufferSize(memstatus.ullTotalPhys)/ONE_MB;
+ swprintf_s(invalidValueMsg,
+ L"Invalid buffer pool size. Please use a number between 1 and %llu",
+ availableMemory);
+ if(BufferPoolSizeLen == 0 || BufferPoolSizeLen > 15)
+ {
+ ErrorMsg= invalidValueMsg;
+ goto LExit;
+ }
+ for (DWORD i=0; i < BufferPoolSizeLen && BufferPoolSize[BufferPoolSizeLen];
+ i++)
+ {
+ if(BufferPoolSize[i]< '0' || BufferPoolSize[i] > '9')
+ {
+ ErrorMsg= invalidValueMsg;
+ goto LExit;
+ }
+ }
+ BufferPoolSize[BufferPoolSizeLen]=0;
+ MsiSetPropertyW(hInstall, L"BUFFERPOOLSIZE", BufferPoolSize);
+ long long sz = _wtoi64(BufferPoolSize);
+ if(sz <= 0 || sz > (long long)availableMemory)
+ {
+ if(sz > 0)
+ {
+ swprintf_s(invalidValueMsg,
+ L"Value for buffer pool size is too large."
+ L"Only approximately %llu MB is available for allocation."
+ L"Please use a number between 1 and %llu.",
+ availableMemory, availableMemory);
+ }
+ ErrorMsg= invalidValueMsg;
+ goto LExit;
+ }
+ }
+LExit:
MsiSetPropertyW (hInstall, L"WarningText", ErrorMsg);
- return ERROR_SUCCESS;
+ return WcaFinalize(er);
}
+/*
+ Sets Innodb buffer pool size (1/8 of RAM by default), if not already specified
+ via command line.
+ Calculates innodb log file size as min(50, innodb buffer pool size/8)
+*/
+extern "C" UINT __stdcall PresetDatabaseProperties(MSIHANDLE hInstall)
+{
+ unsigned long long InnodbBufferPoolSize= 256;
+ unsigned long long InnodbLogFileSize= 50;
+ wchar_t buff[MAX_PATH];
+ UINT er = ERROR_SUCCESS;
+ HRESULT hr= S_OK;
+ MEMORYSTATUSEX memstatus;
+ hr = WcaInitialize(hInstall, __FUNCTION__);
+ ExitOnFailure(hr, "Failed to initialize");
+ WcaLog(LOGMSG_STANDARD, "Initialized.");
+
+ /* Check if bufferpoolsize parameter was given on the command line*/
+ DWORD BufferPoolsizeParamLen = MAX_PATH;
+ MsiGetPropertyW(hInstall, L"BUFFERPOOLSIZE", buff, &BufferPoolsizeParamLen);
+
+ if (BufferPoolsizeParamLen && buff[0])
+ {
+ WcaLog(LOGMSG_STANDARD, "BUFFERPOOLSIZE=%s, len=%u",buff, BufferPoolsizeParamLen);
+ InnodbBufferPoolSize= _wtoi64(buff);
+ }
+ else
+ {
+ memstatus.dwLength = sizeof(memstatus);
+ if (!GlobalMemoryStatusEx(&memstatus))
+ {
+ WcaLog(LOGMSG_STANDARD, "Error %u from GlobalMemoryStatusEx",
+ GetLastError());
+ er= ERROR_INSTALL_FAILURE;
+ goto LExit;
+ }
+ unsigned long long totalPhys= memstatus.ullTotalPhys;
+ /* Give innodb 12.5% of available physical memory. */
+ InnodbBufferPoolSize= totalPhys/ONE_MB/8;
+ #ifdef _M_IX86
+ /*
+ For 32 bit processes, take virtual address space limitation into account.
+ Do not try to use more than 3/4 of virtual address space, even if there
+ is plenty of physical memory.
+ */
+ InnodbBufferPoolSize= min(GetMaxBufferSize(totalPhys)/ONE_MB*3/4,
+ InnodbBufferPoolSize);
+ #endif
+ swprintf_s(buff, L"%llu",InnodbBufferPoolSize);
+ MsiSetPropertyW(hInstall, L"BUFFERPOOLSIZE", buff);
+ }
+ InnodbLogFileSize = min(50, InnodbBufferPoolSize);
+ swprintf_s(buff, L"%llu",InnodbLogFileSize);
+ MsiSetPropertyW(hInstall, L"LOGFILESIZE", buff);
+
+LExit:
+ return WcaFinalize(er);
+}
/* Remove service and data directory created by CreateDatabase operation */
extern "C" UINT __stdcall CreateDatabaseRollback(MSIHANDLE hInstall)
{