diff --git a/benchmarks/src/main/java/module-info.java b/benchmarks/src/main/java/module-info.java index be998ac5408d08c8fca05eca789cefc50a74e098..f6ef4fe5ed86b77c980c5469da777a2d358eb3c9 100644 --- a/benchmarks/src/main/java/module-info.java +++ b/benchmarks/src/main/java/module-info.java @@ -1,4 +1,4 @@ -module io.questdb.bechmarks { +module io.questdb.benchmarks { requires jdk.unsupported; requires java.base; requires io.questdb; diff --git a/core/src/main/bin/questdb.exe b/core/src/main/bin/questdb.exe index 0cbcc63471a1eec2c9ac1d1a3337f50780b237c5..c74ee7cbb5433562521e4c63df63a22c387b5b01 100644 Binary files a/core/src/main/bin/questdb.exe and b/core/src/main/bin/questdb.exe differ diff --git a/core/src/main/java/io/questdb/ServerMain.java b/core/src/main/java/io/questdb/ServerMain.java index 944a92e6912000058cfa37ea826175e6d3097249..5503a6a00f8569118f502873aeec5b7bdd860be2 100644 --- a/core/src/main/java/io/questdb/ServerMain.java +++ b/core/src/main/java/io/questdb/ServerMain.java @@ -218,13 +218,14 @@ public class ServerMain { private static void extractSite(String dir, boolean force, Log log) throws IOException { final String publicZip = "/io/questdb/site/public.zip"; + final String publicDest = dir + "/public"; final byte[] buffer = new byte[1024 * 1024]; try (final InputStream is = ServerMain.class.getResourceAsStream(publicZip)) { if (is != null) { try (ZipInputStream zip = new ZipInputStream(is)) { ZipEntry ze; while ((ze = zip.getNextEntry()) != null) { - final File dest = new File(dir, ze.getName()); + final File dest = new File(publicDest, ze.getName()); if (!ze.isDirectory()) { copyInputStream(force, buffer, dest, zip, log); } diff --git a/win64svc/src/common.h b/win64svc/src/common.h index 8f4e0f82e9125d15adb10db4f8724afa3336fd46..81eb89f688f4c65080e0e5098d45d1765ce130ad 100644 --- a/win64svc/src/common.h +++ b/win64svc/src/common.h @@ -27,6 +27,7 @@ typedef struct { int command; BOOL forceCopy; + BOOL localRuntime; LPSTR dir; int errorCode; LPSTR javaExec; @@ -56,6 +57,6 @@ int svcStart(CONFIG *config); int svcStop(CONFIG *config); -void log_event(WORD logType, char* serviceName, char *message); +void log_event(WORD logType, char* serviceName, const char *message); #endif //WIN64SVC_COMMON_H diff --git a/win64svc/src/questdb.c b/win64svc/src/questdb.c index a363809055ae26b90b24f1fe55067c4c0ec7dd0d..81dfa71873549ac6f356a147ae1e6ee71466c2a2 100644 --- a/win64svc/src/questdb.c +++ b/win64svc/src/questdb.c @@ -4,15 +4,18 @@ #include #include #include "common.h" + #ifdef _MSC_VER #include "getopt.h" #else + #include #include #include #include #include #include + #endif // __MSVC__ #define CMD_START 1 @@ -23,6 +26,8 @@ #define CMD_SERVICE 6 #define CMD_CONSOLE -1 +void buildJavaExec(CONFIG *config, const char *javaExecOpt); + void freeConfig(CONFIG *config) { if (config->exeName != NULL) { free(config->exeName); @@ -60,38 +65,48 @@ int makeDir(const char *dir) { return 1; } +int fileExists(char *file) { + WIN32_FIND_DATA FindFileData; + HANDLE handle = FindFirstFile(file, &FindFileData); + int found = handle != INVALID_HANDLE_VALUE; + if (found) { + FindClose(handle); + } + return found; +} + void buildJavaArgs(CONFIG *config) { // main class - LPCSTR mainClass = "io.questdb.ServerMain"; + LPCSTR mainClass = "io.questdb/io.questdb.ServerMain"; // put together static java opts - LPCSTR javaOpts = - " -XX:+PrintGCApplicationStoppedTime" \ - " -XX:+PrintSafepointStatistics" \ - " -XX:PrintSafepointStatisticsCount=1" \ - " -XX:+PrintGCDetails" \ - " -XX:+PrintGCTimeStamps" \ - " -XX:+PrintGCDateStamps" \ - " -XX:+UnlockDiagnosticVMOptions" \ - " -XX:GuaranteedSafepointInterval=90000000" \ - " -XX:-UseBiasedLocking" \ - " -XX:BiasedLockingStartupDelay=0"; + LPCSTR javaOpts = "-XX:+UnlockExperimentalVMOptions" + " -XX:+AlwaysPreTouch" + " -XX:+UseParallelOldGC" + " --add-exports java.base/jdk.internal.math=io.questdb" + " "; // put together classpath + char classpath[MAX_PATH + 64]; memset(classpath, 0, sizeof(classpath)); - pathCopy(classpath, config->exeName); - strcat(classpath, "\\questdb.jar"); + if (!config->localRuntime) { + pathCopy(classpath, config->exeName); + strcat(classpath, "\\questdb.jar"); + } // put together command line char *args = malloc((strlen(javaOpts) + strlen(classpath) + strlen(mainClass) + strlen(config->dir) + 256) * sizeof(char)); strcpy(args, javaOpts); - strcat(args, " -cp \""); - strcat(args, classpath); - strcat(args, "\" "); + if (!config->localRuntime) { + strcat(args, " -p \""); + strcat(args, classpath); + strcat(args, "\" "); + } + strcat(args, " -m "); strcat(args, mainClass); strcat(args, " -d \""); strcat(args, config->dir); @@ -116,16 +131,14 @@ void initAndParseConfig(int argc, char **argv, CONFIG *config) { GetFullPathName(argv[0], n, exe, NULL); config->exeName = exe; - char *tag = NULL; - char *javaHome = NULL; + char *javaExecOpt = NULL; BOOL parsing = TRUE; while (parsing) { c = getopt(argc, argv, "d:fj:t:"); - switch (c) { case -1: if (optind < argc) { @@ -170,7 +183,7 @@ void initAndParseConfig(int argc, char **argv, CONFIG *config) { break; case 'j': - javaHome = optarg; + javaExecOpt = optarg; break; case 't': @@ -183,21 +196,7 @@ void initAndParseConfig(int argc, char **argv, CONFIG *config) { } } - if (javaHome == NULL) { - // check our environment - javaHome = getenv("JAVA_HOME"); - if (javaHome == NULL) { - eprintf("JAVA_HOME is not defined"); - config->errorCode = ECONFIG_JAVA_HOME; - } - } - - if (javaHome != NULL) { - char *javaExec = malloc((strlen(javaHome) + 64) * sizeof(char)); - strcpy(javaExec, javaHome); - strcat(javaExec, "\\bin\\java.exe"); - config->javaExec = javaExec; - } + buildJavaExec(config, javaExecOpt); size_t tagSize = tag == NULL ? 0 : strlen(tag); @@ -214,6 +213,10 @@ void initAndParseConfig(int argc, char **argv, CONFIG *config) { config->serviceName = lpServiceName; + char buf[2048]; + sprintf(buf, "JAVA_HOME %s ", config->javaExec); + log_event(EVENTLOG_INFORMATION_TYPE, config->serviceName, buf); + // Service display name LPCSTR serviceDisplayNamePrefix = SVC_DISPLAY_NAME; @@ -232,6 +235,40 @@ void initAndParseConfig(int argc, char **argv, CONFIG *config) { buildJavaArgs(config); } +void buildJavaExec(CONFIG *config, const char *javaExecOpt) { + config->javaExec = malloc(MAX_PATH); + memset(config->javaExec, 0, MAX_PATH); + + if (javaExecOpt) { + strcpy(config->javaExec, javaExecOpt); + config->localRuntime = FALSE; + return; + } else { + // check if we are being executed from runtime location + pathCopy(config->javaExec, config->exeName); + strcat(config->javaExec, "\\java.exe"); + if (fileExists(config->javaExec)) { + config->localRuntime = TRUE; + return; + } else { + // fallback to JAVA_HOME + char *javaHome = getenv("JAVA_HOME"); + if (javaHome) { + strcpy(config->javaExec, javaHome); + strcat(config->javaExec, "\\bin\\java.exe"); + if (fileExists(config->javaExec)) { + config->localRuntime = FALSE; + return; + } + } + } + } + free(config->javaExec); + config->javaExec = NULL; + eprintf("\r\nJAVA_HOME is not defined\r\n"); + config->errorCode = ECONFIG_JAVA_HOME; +} + FILE *redirectStdout(CONFIG *config) { // create log dir @@ -274,6 +311,8 @@ int qdbConsole(CONFIG *config) { si.cb = sizeof(si); ZeroMemory(&pi, sizeof(pi)); + eprintf("JAVA_EXE: %s\n\r\n\r", config->javaExec); + // Start the child process. if (!CreateProcess(config->javaExec, config->javaArgs, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { eprintf("CreateProcess failed [%s](%lu).\n", config->javaExec, GetLastError()); diff --git a/win64svc/src/service.c b/win64svc/src/service.c index 2cf4a5b05f57fe2ace8b83bc8a59153d11387767..7f21393b407b8d5fa014f6aadcc39964e490fe20 100644 --- a/win64svc/src/service.c +++ b/win64svc/src/service.c @@ -14,7 +14,7 @@ VOID ReportSvcStatus(DWORD, DWORD, DWORD); VOID WINAPI qdbService(DWORD argc, LPSTR *argv); -void log_event(WORD logType, char *serviceName, char *message) { +void log_event(WORD logType, char *serviceName, const char *message) { HANDLE hEventSource; LPCTSTR lpszStrings[1]; @@ -111,14 +111,17 @@ VOID WINAPI qdbService(DWORD argc, LPSTR *argv) { si.cb = sizeof(si); ZeroMemory(&pi, sizeof(pi)); - // Start the child process. + char buf[2048]; + sprintf(buf, "Starting %s %s", gConfig->javaExec, gConfig->javaArgs); + log_event(EVENTLOG_INFORMATION_TYPE, gConfig->serviceName, buf); + if (!CreateProcess(gConfig->javaExec, gConfig->javaArgs, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { log_event(EVENTLOG_ERROR_TYPE, gConfig->serviceName, "Could not start java"); ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0); return; } - char buf[2048]; +// char buf[2048]; sprintf(buf, "Started %s %s", gConfig->javaExec, gConfig->javaArgs); log_event(EVENTLOG_INFORMATION_TYPE, gConfig->serviceName, buf); diff --git a/win64svc/src/svcctrl.c b/win64svc/src/svcctrl.c index 43e584dddeea9d8f7855535871f05fd1354e69a2..0faea9ebcc8e55d08a0af9438adbf92c29930b3c 100644 --- a/win64svc/src/svcctrl.c +++ b/win64svc/src/svcctrl.c @@ -31,6 +31,8 @@ int svcInstall(CONFIG *config) { if (config->forceCopy) { strcat(szPath, " -f"); } + strcat(szPath, " -j "); + strcat(szPath, config->javaExec); // Create the service @@ -61,7 +63,7 @@ int svcInstall(CONFIG *config) { } SERVICE_DESCRIPTION description; - description.lpDescription = "High performance time series database (www.questdb.org)"; + description.lpDescription = "High performance time series database (www.questdb.io)"; ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &description); eprintf("Service installed: %s\n", config->serviceName);