Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
jobily
Questdb
提交
c16b1e0a
Q
Questdb
项目概览
jobily
/
Questdb
11 个月 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
Q
Questdb
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
c16b1e0a
编写于
3月 22, 2022
作者:
B
Bolek Ziobrowski
提交者:
GitHub
3月 22, 2022
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
fix(core): fixed logging and status reporting for windows service mode… (#1969)
上级
a27e2e54
变更
10
隐藏空白更改
内联
并排
Showing
10 changed file
with
311 addition
and
45 deletion
+311
-45
core/src/main/bin/questdb.exe
core/src/main/bin/questdb.exe
+0
-0
core/src/main/bin/questdb.sh
core/src/main/bin/questdb.sh
+1
-1
core/src/main/java/io/questdb/ServerMain.java
core/src/main/java/io/questdb/ServerMain.java
+8
-4
core/src/main/java/io/questdb/log/LogFactory.java
core/src/main/java/io/questdb/log/LogFactory.java
+75
-24
core/src/main/resources/io/questdb/site/conf/log.conf
core/src/main/resources/io/questdb/site/conf/log.conf
+1
-1
core/src/test/java/io/questdb/ServerMainTest.java
core/src/test/java/io/questdb/ServerMainTest.java
+119
-0
core/src/test/java/io/questdb/log/LogFactoryTest.java
core/src/test/java/io/questdb/log/LogFactoryTest.java
+44
-2
pkg/ami/marketplace/assets/systemd.service
pkg/ami/marketplace/assets/systemd.service
+1
-1
win64svc/src/questdb.c
win64svc/src/questdb.c
+1
-1
win64svc/src/service.c
win64svc/src/service.c
+61
-11
未找到文件。
core/src/main/bin/questdb.exe
浏览文件 @
c16b1e0a
无法预览此类型文件
core/src/main/bin/questdb.sh
浏览文件 @
c16b1e0a
...
@@ -175,7 +175,7 @@ function start {
...
@@ -175,7 +175,7 @@ function start {
-ea -Dnoebug
-ea -Dnoebug
-XX:+UnlockExperimentalVMOptions
-XX:+UnlockExperimentalVMOptions
-XX:+AlwaysPreTouch
-XX:+AlwaysPreTouch
-XX:+UseParallel
Old
GC
-XX:+UseParallelGC
"
"
JAVA_MAIN
=
"io.questdb/io.questdb.ServerMain"
JAVA_MAIN
=
"io.questdb/io.questdb.ServerMain"
...
...
core/src/main/java/io/questdb/ServerMain.java
浏览文件 @
c16b1e0a
...
@@ -78,14 +78,16 @@ public class ServerMain {
...
@@ -78,14 +78,16 @@ public class ServerMain {
}
}
final
CharSequenceObjHashMap
<
String
>
optHash
=
hashArgs
(
args
);
final
CharSequenceObjHashMap
<
String
>
optHash
=
hashArgs
(
args
);
final
Log
log
=
LogFactory
.
getLog
(
"server-main"
);
// expected flags:
// expected flags:
// -d <root dir> = sets root directory
// -d <root dir> = sets root directory
// -f = forces copy of site to root directory even if site exists
// -f = forces copy of site to root directory even if site exists
// -n = disables handling of HUP signal
// -n = disables handling of HUP signal
final
String
rootDirectory
=
optHash
.
get
(
"-d"
);
final
String
rootDirectory
=
optHash
.
get
(
"-d"
);
LogFactory
.
configureFromSystemProperties
(
LogFactory
.
INSTANCE
,
null
,
rootDirectory
);
final
Log
log
=
LogFactory
.
getLog
(
"server-main"
);
extractSite
(
buildInformation
,
rootDirectory
,
log
);
extractSite
(
buildInformation
,
rootDirectory
,
log
);
final
Properties
properties
=
new
Properties
();
final
Properties
properties
=
new
Properties
();
final
String
configurationFileName
=
"/server.conf"
;
final
String
configurationFileName
=
"/server.conf"
;
...
@@ -378,7 +380,8 @@ public class ServerMain {
...
@@ -378,7 +380,8 @@ public class ServerMain {
}
}
}
}
private
static
void
extractSite
(
BuildInformation
buildInformation
,
String
dir
,
Log
log
)
throws
IOException
{
//made package level for testing only
static
void
extractSite
(
BuildInformation
buildInformation
,
String
dir
,
Log
log
)
throws
IOException
{
final
String
publicZip
=
"/io/questdb/site/public.zip"
;
final
String
publicZip
=
"/io/questdb/site/public.zip"
;
final
String
publicDir
=
dir
+
"/public"
;
final
String
publicDir
=
dir
+
"/public"
;
final
byte
[]
buffer
=
new
byte
[
1024
*
1024
];
final
byte
[]
buffer
=
new
byte
[
1024
*
1024
];
...
@@ -452,6 +455,7 @@ public class ServerMain {
...
@@ -452,6 +455,7 @@ public class ServerMain {
copyConfResource
(
dir
,
false
,
buffer
,
"conf/date.formats"
,
log
);
copyConfResource
(
dir
,
false
,
buffer
,
"conf/date.formats"
,
log
);
copyConfResource
(
dir
,
true
,
buffer
,
"conf/mime.types"
,
log
);
copyConfResource
(
dir
,
true
,
buffer
,
"conf/mime.types"
,
log
);
copyConfResource
(
dir
,
false
,
buffer
,
"conf/server.conf"
,
log
);
copyConfResource
(
dir
,
false
,
buffer
,
"conf/server.conf"
,
log
);
copyConfResource
(
dir
,
false
,
buffer
,
"conf/log.conf"
,
log
);
}
}
private
static
void
copyConfResource
(
String
dir
,
boolean
force
,
byte
[]
buffer
,
String
res
,
Log
log
)
throws
IOException
{
private
static
void
copyConfResource
(
String
dir
,
boolean
force
,
byte
[]
buffer
,
String
res
,
Log
log
)
throws
IOException
{
...
@@ -605,4 +609,4 @@ public class ServerMain {
...
@@ -605,4 +609,4 @@ public class ServerMain {
)
{
)
{
workerPool
.
start
(
log
);
workerPool
.
start
(
log
);
}
}
}
}
\ No newline at end of file
core/src/main/java/io/questdb/log/LogFactory.java
浏览文件 @
c16b1e0a
...
@@ -35,6 +35,7 @@ import org.jetbrains.annotations.TestOnly;
...
@@ -35,6 +35,7 @@ import org.jetbrains.annotations.TestOnly;
import
java.io.*
;
import
java.io.*
;
import
java.lang.reflect.Constructor
;
import
java.lang.reflect.Constructor
;
import
java.lang.reflect.Field
;
import
java.lang.reflect.Field
;
import
java.nio.file.Paths
;
import
java.util.Comparator
;
import
java.util.Comparator
;
import
java.util.Properties
;
import
java.util.Properties
;
...
@@ -47,10 +48,18 @@ public class LogFactory implements Closeable {
...
@@ -47,10 +48,18 @@ public class LogFactory implements Closeable {
private
static
final
int
DEFAULT_QUEUE_DEPTH
=
1024
;
private
static
final
int
DEFAULT_QUEUE_DEPTH
=
1024
;
private
static
final
int
DEFAULT_MSG_SIZE
=
4
*
1024
;
private
static
final
int
DEFAULT_MSG_SIZE
=
4
*
1024
;
private
static
final
String
DEFAULT_CONFIG
=
"/log-stdout.conf"
;
//name of default logging configuration file (in jar and in $root/conf/ dir )
public
static
final
String
DEFAULT_CONFIG_NAME
=
"log.conf"
;
private
static
final
String
DEFAULT_CONFIG
=
"/io/questdb/site/conf/"
+
DEFAULT_CONFIG_NAME
;
//placeholder that can be used in log.conf to point to $root/log/ dir
public
static
final
String
LOG_DIR_VAR
=
"${log.dir}"
;
private
static
final
String
EMPTY_STR
=
""
;
private
static
final
String
EMPTY_STR
=
""
;
private
static
final
CharSequenceHashSet
reserved
=
new
CharSequenceHashSet
();
private
static
final
CharSequenceHashSet
reserved
=
new
CharSequenceHashSet
();
private
static
final
LengthDescendingComparator
LDC
=
new
LengthDescendingComparator
();
private
static
final
LengthDescendingComparator
LDC
=
new
LengthDescendingComparator
();
private
final
CharSequenceObjHashMap
<
ScopeConfiguration
>
scopeConfigMap
=
new
CharSequenceObjHashMap
<>();
private
final
CharSequenceObjHashMap
<
ScopeConfiguration
>
scopeConfigMap
=
new
CharSequenceObjHashMap
<>();
private
final
ObjList
<
ScopeConfiguration
>
scopeConfigs
=
new
ObjList
<>();
private
final
ObjList
<
ScopeConfiguration
>
scopeConfigs
=
new
ObjList
<>();
private
final
ObjHashSet
<
LogWriter
>
jobs
=
new
ObjHashSet
<>();
private
final
ObjHashSet
<
LogWriter
>
jobs
=
new
ObjHashSet
<>();
...
@@ -70,7 +79,7 @@ public class LogFactory implements Closeable {
...
@@ -70,7 +79,7 @@ public class LogFactory implements Closeable {
this
.
clock
=
clock
;
this
.
clock
=
clock
;
}
}
public
static
void
configureFromProperties
(
LogFactory
factory
,
Properties
properties
,
WorkerPool
workerPool
)
{
public
static
void
configureFromProperties
(
LogFactory
factory
,
Properties
properties
,
WorkerPool
workerPool
,
String
logDir
)
{
factory
.
workerPool
=
workerPool
;
factory
.
workerPool
=
workerPool
;
String
writers
=
getProperty
(
properties
,
"writers"
);
String
writers
=
getProperty
(
properties
,
"writers"
);
...
@@ -101,7 +110,7 @@ public class LogFactory implements Closeable {
...
@@ -101,7 +110,7 @@ public class LogFactory implements Closeable {
}
}
for
(
String
w
:
writers
.
split
(
","
))
{
for
(
String
w
:
writers
.
split
(
","
))
{
LogWriterConfig
conf
=
createWriter
(
properties
,
w
.
trim
());
LogWriterConfig
conf
=
createWriter
(
properties
,
w
.
trim
()
,
logDir
);
if
(
conf
!=
null
)
{
if
(
conf
!=
null
)
{
factory
.
add
(
conf
);
factory
.
add
(
conf
);
}
}
...
@@ -115,33 +124,69 @@ public class LogFactory implements Closeable {
...
@@ -115,33 +124,69 @@ public class LogFactory implements Closeable {
}
}
public
static
void
configureFromSystemProperties
(
LogFactory
factory
,
WorkerPool
workerPool
)
{
public
static
void
configureFromSystemProperties
(
LogFactory
factory
,
WorkerPool
workerPool
)
{
configureFromSystemProperties
(
factory
,
workerPool
,
null
);
}
public
static
void
configureFromSystemProperties
(
LogFactory
factory
,
WorkerPool
workerPool
,
String
rootDir
)
{
String
conf
=
System
.
getProperty
(
CONFIG_SYSTEM_PROPERTY
);
String
conf
=
System
.
getProperty
(
CONFIG_SYSTEM_PROPERTY
);
if
(
conf
==
null
)
{
if
(
conf
==
null
)
{
conf
=
DEFAULT_CONFIG
;
conf
=
DEFAULT_CONFIG
;
}
}
try
(
InputStream
is
=
LogFactory
.
class
.
getResourceAsStream
(
conf
))
{
if
(
is
!=
null
)
{
boolean
initialized
=
false
;
Properties
properties
=
new
Properties
();
String
logDir
=
rootDir
!=
null
?
Paths
.
get
(
rootDir
,
"log"
).
toString
()
:
"log"
;
properties
.
load
(
is
);
File
logDirFile
=
new
File
(
logDir
);
configureFromProperties
(
factory
,
properties
,
workerPool
);
}
else
{
if
(!
logDirFile
.
exists
()
&&
logDirFile
.
mkdir
())
{
File
f
=
new
File
(
conf
);
System
.
err
.
printf
(
"Created log directory: %s%n"
,
logDir
);
if
(
f
.
canRead
())
{
}
try
(
FileInputStream
fis
=
new
FileInputStream
(
f
))
{
Properties
properties
=
new
Properties
();
if
(
rootDir
!=
null
&&
DEFAULT_CONFIG
.
equals
(
conf
))
{
properties
.
load
(
fis
);
String
logPath
=
Paths
.
get
(
rootDir
,
"conf"
,
DEFAULT_CONFIG_NAME
).
toString
();
configureFromProperties
(
factory
,
properties
,
workerPool
);
File
f
=
new
File
(
logPath
);
if
(
f
.
isFile
()
&&
f
.
canRead
())
{
System
.
err
.
printf
(
"Reading log configuration from %s%n"
,
logPath
);
try
(
FileInputStream
fis
=
new
FileInputStream
(
logPath
))
{
Properties
properties
=
new
Properties
();
properties
.
load
(
fis
);
configureFromProperties
(
factory
,
properties
,
workerPool
,
logDir
);
System
.
err
.
printf
(
"Log configuration loaded from: %s%n"
,
logPath
);
initialized
=
true
;
}
catch
(
IOException
e
)
{
throw
new
LogError
(
"Cannot read "
+
logPath
,
e
);
}
}
}
if
(!
initialized
)
{
//in this order of initialization specifying -Dout might end up using internal jar resources ...
try
(
InputStream
is
=
LogFactory
.
class
.
getResourceAsStream
(
conf
))
{
if
(
is
!=
null
)
{
Properties
properties
=
new
Properties
();
properties
.
load
(
is
);
configureFromProperties
(
factory
,
properties
,
workerPool
,
logDir
);
System
.
err
.
println
(
"Log configuration loaded from default internal file."
);
}
else
{
File
f
=
new
File
(
conf
);
if
(
f
.
canRead
())
{
try
(
FileInputStream
fis
=
new
FileInputStream
(
f
))
{
Properties
properties
=
new
Properties
();
properties
.
load
(
fis
);
configureFromProperties
(
factory
,
properties
,
workerPool
,
logDir
);
System
.
err
.
printf
(
"Log configuration loaded from: %s%n"
,
conf
);
}
}
else
{
factory
.
configureDefaultWriter
();
System
.
err
.
println
(
"Log configuration loaded loaded using factory defaults."
);
}
}
}
}
catch
(
IOException
e
)
{
if
(!
DEFAULT_CONFIG
.
equals
(
conf
))
{
throw
new
LogError
(
"Cannot read "
+
conf
,
e
);
}
else
{
}
else
{
factory
.
configureDefaultWriter
();
factory
.
configureDefaultWriter
();
}
}
}
}
}
catch
(
IOException
e
)
{
if
(!
DEFAULT_CONFIG
.
equals
(
conf
))
{
throw
new
LogError
(
"Cannot read "
+
conf
,
e
);
}
else
{
factory
.
configureDefaultWriter
();
}
}
}
factory
.
startThread
();
factory
.
startThread
();
}
}
...
@@ -331,8 +376,8 @@ public class LogFactory implements Closeable {
...
@@ -331,8 +376,8 @@ public class LogFactory implements Closeable {
}
}
@SuppressWarnings
(
"rawtypes"
)
@SuppressWarnings
(
"rawtypes"
)
private
static
LogWriterConfig
createWriter
(
final
Properties
properties
,
String
w
)
{
private
static
LogWriterConfig
createWriter
(
final
Properties
properties
,
String
w
riterName
,
String
logDir
)
{
final
String
writer
=
"w."
+
w
+
'.'
;
final
String
writer
=
"w."
+
w
riterName
+
'.'
;
final
String
clazz
=
getProperty
(
properties
,
writer
+
"class"
);
final
String
clazz
=
getProperty
(
properties
,
writer
+
"class"
);
final
String
levelStr
=
getProperty
(
properties
,
writer
+
"level"
);
final
String
levelStr
=
getProperty
(
properties
,
writer
+
"level"
);
final
String
scope
=
getProperty
(
properties
,
writer
+
"scope"
);
final
String
scope
=
getProperty
(
properties
,
writer
+
"scope"
);
...
@@ -401,7 +446,13 @@ public class LogFactory implements Closeable {
...
@@ -401,7 +446,13 @@ public class LogFactory implements Closeable {
try
{
try
{
Field
f
=
cl
.
getDeclaredField
(
p
);
Field
f
=
cl
.
getDeclaredField
(
p
);
if
(
f
.
getType
()
==
String
.
class
)
{
if
(
f
.
getType
()
==
String
.
class
)
{
Unsafe
.
getUnsafe
().
putObject
(
w1
,
Unsafe
.
getUnsafe
().
objectFieldOffset
(
f
),
getProperty
(
properties
,
n
));
String
value
=
getProperty
(
properties
,
n
);
if
(
logDir
!=
null
&&
value
.
contains
(
LOG_DIR_VAR
))
{
value
=
value
.
replace
(
LOG_DIR_VAR
,
logDir
);
}
Unsafe
.
getUnsafe
().
putObject
(
w1
,
Unsafe
.
getUnsafe
().
objectFieldOffset
(
f
),
value
);
}
}
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
throw
new
LogError
(
"Unknown property: "
+
n
,
e
);
throw
new
LogError
(
"Unknown property: "
+
n
,
e
);
...
...
core/src/main/resources/
log-stdout
.conf
→
core/src/main/resources/
io/questdb/site/conf/log
.conf
浏览文件 @
c16b1e0a
...
@@ -27,4 +27,4 @@ w.stdout.level=INFO
...
@@ -27,4 +27,4 @@ w.stdout.level=INFO
# for frequent monitoring
# for frequent monitoring
w
.
http
.
min
.
class
=
io
.
questdb
.
log
.
LogConsoleWriter
w
.
http
.
min
.
class
=
io
.
questdb
.
log
.
LogConsoleWriter
w
.
http
.
min
.
level
=
ERROR
w
.
http
.
min
.
level
=
ERROR
w
.
http
.
min
.
scope
=
http
-
min
-
server
w
.
http
.
min
.
scope
=
http
-
min
-
server
\ No newline at end of file
core/src/test/java/io/questdb/ServerMainTest.java
0 → 100644
浏览文件 @
c16b1e0a
/*******************************************************************************
* ___ _ ____ ____
* / _ \ _ _ ___ ___| |_| _ \| __ )
* | | | | | | |/ _ \/ __| __| | | | _ \
* | |_| | |_| | __/\__ \ |_| |_| | |_) |
* \__\_\\__,_|\___||___/\__|____/|____/
*
* Copyright (c) 2014-2019 Appsicle
* Copyright (c) 2019-2022 QuestDB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
package
io.questdb
;
import
io.questdb.log.Log
;
import
io.questdb.log.LogFactory
;
import
org.hamcrest.MatcherAssert
;
import
static
org
.
hamcrest
.
CoreMatchers
.*;
import
org.junit.After
;
import
org.junit.Before
;
import
org.junit.Rule
;
import
org.junit.Test
;
import
org.junit.rules.TemporaryFolder
;
import
java.io.File
;
import
java.io.FileOutputStream
;
import
java.io.IOException
;
import
java.net.URL
;
import
java.nio.file.Paths
;
import
java.util.zip.ZipEntry
;
import
java.util.zip.ZipOutputStream
;
public
class
ServerMainTest
{
@Rule
public
final
TemporaryFolder
temp
=
new
TemporaryFolder
();
boolean
publicZipStubCreated
=
false
;
@Before
public
void
setUp
()
throws
IOException
{
//fake public.zip if it's missing to avoid forcing use of build-web-console profile just to run tests
URL
resource
=
ServerMain
.
class
.
getResource
(
"/io/questdb/site/public.zip"
);
if
(
resource
==
null
)
{
File
siteDir
=
new
File
(
ServerMain
.
class
.
getResource
(
"/io/questdb/site/"
).
getFile
());
File
publicZip
=
new
File
(
siteDir
,
"public.zip"
);
try
(
ZipOutputStream
zip
=
new
ZipOutputStream
(
new
FileOutputStream
(
publicZip
)))
{
ZipEntry
entry
=
new
ZipEntry
(
"test.txt"
);
zip
.
putNextEntry
(
entry
);
zip
.
write
(
"test"
.
getBytes
());
zip
.
closeEntry
();
}
publicZipStubCreated
=
true
;
}
}
@After
public
void
tearDown
()
{
if
(
publicZipStubCreated
)
{
File
siteDir
=
new
File
(
ServerMain
.
class
.
getResource
(
"/io/questdb/site/"
).
getFile
());
File
publicZip
=
new
File
(
siteDir
,
"public.zip"
);
if
(
publicZip
.
exists
())
{
publicZip
.
delete
();
}
}
}
@Test
public
void
testExtractSiteExtractsDefaultLogConfFileIfItsMissing
()
throws
IOException
{
Log
log
=
LogFactory
.
getLog
(
"server-main"
);
File
logConf
=
Paths
.
get
(
temp
.
getRoot
().
getPath
(),
"conf"
,
LogFactory
.
DEFAULT_CONFIG_NAME
).
toFile
();
MatcherAssert
.
assertThat
(
logConf
.
exists
(),
is
(
false
));
ServerMain
.
extractSite
(
BuildInformationHolder
.
INSTANCE
,
temp
.
getRoot
().
getPath
(),
log
);
MatcherAssert
.
assertThat
(
logConf
.
exists
(),
is
(
true
));
}
@Test
public
void
testExtractSiteExtractsDefaultConfDirIfItsMissing
()
throws
IOException
{
Log
log
=
LogFactory
.
getLog
(
"server-main"
);
File
conf
=
Paths
.
get
(
temp
.
getRoot
().
getPath
(),
"conf"
).
toFile
();
File
logConf
=
Paths
.
get
(
conf
.
getPath
(),
LogFactory
.
DEFAULT_CONFIG_NAME
).
toFile
();
File
serverConf
=
Paths
.
get
(
conf
.
getPath
(),
"server.conf"
).
toFile
();
File
mimeTypes
=
Paths
.
get
(
conf
.
getPath
(),
"mime.types"
).
toFile
();
//File dateFormats = Paths.get(conf.getPath(), "date.formats").toFile();
ServerMain
.
extractSite
(
BuildInformationHolder
.
INSTANCE
,
temp
.
getRoot
().
getPath
(),
log
);
assertExists
(
logConf
);
assertExists
(
serverConf
);
assertExists
(
mimeTypes
);
//assertExists(dateFormats); date.formats is referenced in method but doesn't exist in SCM/jar
}
private
static
void
assertExists
(
File
f
)
{
MatcherAssert
.
assertThat
(
f
.
getPath
(),
f
.
exists
(),
is
(
true
));
}
}
core/src/test/java/io/questdb/log/LogFactoryTest.java
浏览文件 @
c16b1e0a
...
@@ -31,12 +31,17 @@ import io.questdb.std.datetime.microtime.TimestampFormatUtils;
...
@@ -31,12 +31,17 @@ import io.questdb.std.datetime.microtime.TimestampFormatUtils;
import
io.questdb.std.str.Path
;
import
io.questdb.std.str.Path
;
import
io.questdb.std.str.StringSink
;
import
io.questdb.std.str.StringSink
;
import
io.questdb.test.tools.TestUtils
;
import
io.questdb.test.tools.TestUtils
;
import
org.hamcrest.MatcherAssert
;
import
org.junit.Assert
;
import
org.junit.Assert
;
import
org.junit.Rule
;
import
org.junit.Rule
;
import
org.junit.Test
;
import
org.junit.Test
;
import
org.junit.rules.TemporaryFolder
;
import
org.junit.rules.TemporaryFolder
;
import
java.io.File
;
import
static
org
.
hamcrest
.
CoreMatchers
.*;
import
java.io.*
;
import
java.nio.file.Paths
;
import
java.util.Properties
;
import
java.util.concurrent.atomic.AtomicBoolean
;
import
java.util.concurrent.atomic.AtomicBoolean
;
public
class
LogFactoryTest
{
public
class
LogFactoryTest
{
...
@@ -49,7 +54,7 @@ public class LogFactoryTest {
...
@@ -49,7 +54,7 @@ public class LogFactoryTest {
System
.
setProperty
(
LogFactory
.
CONFIG_SYSTEM_PROPERTY
,
"/test-log-bad-writer.conf"
);
System
.
setProperty
(
LogFactory
.
CONFIG_SYSTEM_PROPERTY
,
"/test-log-bad-writer.conf"
);
try
(
LogFactory
factory
=
new
LogFactory
())
{
try
(
LogFactory
factory
=
new
LogFactory
())
{
try
{
try
{
LogFactory
.
configureFromSystemProperties
(
factory
,
null
);
LogFactory
.
configureFromSystemProperties
(
factory
,
null
,
null
);
Assert
.
fail
();
Assert
.
fail
();
}
catch
(
LogError
e
)
{
}
catch
(
LogError
e
)
{
Assert
.
assertEquals
(
"Class not found com.questdb.log.StdOutWriter2"
,
e
.
getMessage
());
Assert
.
assertEquals
(
"Class not found com.questdb.log.StdOutWriter2"
,
e
.
getMessage
());
...
@@ -608,6 +613,43 @@ public class LogFactoryTest {
...
@@ -608,6 +613,43 @@ public class LogFactoryTest {
}
}
}
}
@Test
//also tests ${log.di} resolution
public
void
testWhenCustomLogLocationIsNotSpecifiedThenDefaultLogFileIsUsed
()
throws
Exception
{
System
.
clearProperty
(
LogFactory
.
CONFIG_SYSTEM_PROPERTY
);
testCustomLogIsCreated
(
true
);
}
@Test
public
void
testWhenCustomLogLocationIsSpecifiedThenDefaultLogFileIsNotUsed
()
throws
IOException
{
System
.
setProperty
(
LogFactory
.
CONFIG_SYSTEM_PROPERTY
,
"test-log.conf"
);
testCustomLogIsCreated
(
false
);
}
private
void
testCustomLogIsCreated
(
boolean
isCreated
)
throws
IOException
{
try
(
LogFactory
factory
=
new
LogFactory
())
{
File
logConfDir
=
Paths
.
get
(
temp
.
getRoot
().
getPath
(),
"conf"
).
toFile
();
Assert
.
assertTrue
(
logConfDir
.
mkdir
());
File
logConfFile
=
Paths
.
get
(
logConfDir
.
getPath
(),
LogFactory
.
DEFAULT_CONFIG_NAME
).
toFile
();
Properties
props
=
new
Properties
();
props
.
put
(
"writers"
,
"log_test"
);
props
.
put
(
"w.log_test.class"
,
"io.questdb.log.LogFileWriter"
);
props
.
put
(
"w.log_test.location"
,
"${log.dir}\\test.log"
);
props
.
put
(
"w.log_test.level"
,
"INFO,ERROR"
);
try
(
FileOutputStream
stream
=
new
FileOutputStream
(
logConfFile
))
{
props
.
store
(
stream
,
""
);
}
LogFactory
.
configureFromSystemProperties
(
factory
,
null
,
temp
.
getRoot
().
getPath
());
File
logFile
=
Paths
.
get
(
temp
.
getRoot
().
getPath
(),
"log\\test.log"
).
toFile
();
MatcherAssert
.
assertThat
(
logFile
.
getAbsolutePath
(),
logFile
.
exists
(),
is
(
isCreated
));
}
}
private
static
void
assertEnabled
(
LogRecord
r
)
{
private
static
void
assertEnabled
(
LogRecord
r
)
{
Assert
.
assertTrue
(
r
.
isEnabled
());
Assert
.
assertTrue
(
r
.
isEnabled
());
r
.
$
();
r
.
$
();
...
...
pkg/ami/marketplace/assets/systemd.service
浏览文件 @
c16b1e0a
...
@@ -17,7 +17,7 @@ ExecStart=/usr/bin/java \
...
@@ -17,7 +17,7 @@ ExecStart=/usr/bin/java \
-ea -Dnoebug
\
-ea -Dnoebug
\
-XX:+UnlockExperimentalVMOptions
\
-XX:+UnlockExperimentalVMOptions
\
-XX:+AlwaysPreTouch
\
-XX:+AlwaysPreTouch
\
-XX:+UseParallel
Old
GC
\
-XX:+UseParallelGC
\
-d /var/lib/questdb
-d /var/lib/questdb
ExecReload=/bin/kill -s HUP $MAINPID
ExecReload=/bin/kill -s HUP $MAINPID
# Prevent writes to /usr, /boot, and /etc
# Prevent writes to /usr, /boot, and /etc
...
...
win64svc/src/questdb.c
浏览文件 @
c16b1e0a
...
@@ -82,7 +82,7 @@ void buildJavaArgs(CONFIG *config) {
...
@@ -82,7 +82,7 @@ void buildJavaArgs(CONFIG *config) {
// put together static java opts
// put together static java opts
LPCSTR
javaOpts
=
"-XX:+UnlockExperimentalVMOptions"
LPCSTR
javaOpts
=
"-XX:+UnlockExperimentalVMOptions"
" -XX:+AlwaysPreTouch"
" -XX:+AlwaysPreTouch"
" -XX:+UseParallel
Old
GC"
" -XX:+UseParallelGC"
" "
;
" "
;
// put together classpath
// put together classpath
...
...
win64svc/src/service.c
浏览文件 @
c16b1e0a
#include <windows.h>
#include <windows.h>
#include "common.h"
#include "common.h"
#include "io.h"
#include <time.h>
#pragma comment(lib, "advapi32.lib")
#pragma comment(lib, "advapi32.lib")
...
@@ -52,6 +54,30 @@ void qdbDispatchService(CONFIG *config) {
...
@@ -52,6 +54,30 @@ void qdbDispatchService(CONFIG *config) {
}
}
}
}
HANDLE
openLogFile
(
CONFIG
*
config
)
{
// create log dir
char
log
[
MAX_PATH
];
strcpy
(
log
,
config
->
dir
);
strcat
(
log
,
"
\\
log"
);
if
(
!
makeDir
(
log
))
{
return
NULL
;
}
time_t
now
=
time
(
NULL
);
struct
tm
*
t
=
localtime
(
&
now
);
strcat
(
log
,
"
\\
service-"
);
strftime
(
log
+
strlen
(
log
),
MAX_PATH
-
strlen
(
log
)
-
4
,
"%Y-%m-%dT%H-%M-%S"
,
t
);
strcat
(
log
,
".txt"
);
FILE
*
stream
;
if
((
stream
=
fopen
(
log
,
"w"
))
==
NULL
)
{
return
INVALID_HANDLE_VALUE
;
}
return
(
HANDLE
)
_get_osfhandle
(
fileno
(
stream
));
}
VOID
WINAPI
qdbService
(
DWORD
argc
,
LPSTR
*
argv
)
{
VOID
WINAPI
qdbService
(
DWORD
argc
,
LPSTR
*
argv
)
{
// Get service name from first command line arg
// Get service name from first command line arg
...
@@ -105,42 +131,66 @@ VOID WINAPI qdbService(DWORD argc, LPSTR *argv) {
...
@@ -105,42 +131,66 @@ VOID WINAPI qdbService(DWORD argc, LPSTR *argv) {
return
;
return
;
}
}
STARTUPINFO
si
;
HANDLE
log
=
openLogFile
(
gConfig
);
if
(
log
==
INVALID_HANDLE_VALUE
)
{
log_event
(
EVENTLOG_ERROR_TYPE
,
gConfig
->
serviceName
,
"Could not open service log file."
);
return
;
}
PROCESS_INFORMATION
pi
;
PROCESS_INFORMATION
pi
;
ZeroMemory
(
&
pi
,
sizeof
(
pi
));
STARTUPINFO
si
;
ZeroMemory
(
&
si
,
sizeof
(
si
));
ZeroMemory
(
&
si
,
sizeof
(
si
));
si
.
cb
=
sizeof
(
si
);
si
.
cb
=
sizeof
(
si
);
ZeroMemory
(
&
pi
,
sizeof
(
pi
));
si
.
hStdError
=
log
;
si
.
hStdOutput
=
log
;
si
.
dwFlags
|=
STARTF_USESTDHANDLES
;
char
buf
[
2048
];
char
buf
[
2048
];
sprintf
(
buf
,
"Starting %s %s"
,
gConfig
->
javaExec
,
gConfig
->
javaArgs
);
sprintf
(
buf
,
"Starting %s %s"
,
gConfig
->
javaExec
,
gConfig
->
javaArgs
);
log_event
(
EVENTLOG_INFORMATION_TYPE
,
gConfig
->
serviceName
,
buf
);
log_event
(
EVENTLOG_INFORMATION_TYPE
,
gConfig
->
serviceName
,
buf
);
if
(
!
CreateProcess
(
gConfig
->
javaExec
,
gConfig
->
javaArgs
,
NULL
,
NULL
,
FALSE
,
0
,
NULL
,
NULL
,
&
si
,
&
pi
))
{
if
(
!
CreateProcess
(
gConfig
->
javaExec
,
gConfig
->
javaArgs
,
NULL
,
NULL
,
TRUE
/*handles are inherited to redirect stdout/err*/
,
0
,
NULL
,
NULL
,
&
si
,
&
pi
))
{
log_event
(
EVENTLOG_ERROR_TYPE
,
gConfig
->
serviceName
,
"Could not start java"
);
log_event
(
EVENTLOG_ERROR_TYPE
,
gConfig
->
serviceName
,
"Could not start java"
);
ReportSvcStatus
(
SERVICE_STOPPED
,
NO_ERROR
,
0
);
ReportSvcStatus
(
SERVICE_STOPPED
,
NO_ERROR
,
0
);
return
;
return
;
}
}
// char buf[2048];
sprintf
(
buf
,
"Started %s %s"
,
gConfig
->
javaExec
,
gConfig
->
javaArgs
);
sprintf
(
buf
,
"Started %s %s"
,
gConfig
->
javaExec
,
gConfig
->
javaArgs
);
log_event
(
EVENTLOG_INFORMATION_TYPE
,
gConfig
->
serviceName
,
buf
);
log_event
(
EVENTLOG_INFORMATION_TYPE
,
gConfig
->
serviceName
,
buf
);
// Report running status when initialization is complete.
// Report running status when initialization is complete.
ReportSvcStatus
(
SERVICE_RUNNING
,
NO_ERROR
,
0
);
ReportSvcStatus
(
SERVICE_RUNNING
,
NO_ERROR
,
0
);
WaitForSingleObject
(
ghSvcStopEvent
,
INFINITE
);
HANDLE
lpHandles
[
2
]
=
{
ghSvcStopEvent
,
pi
.
hProcess
};
DWORD
dwEvent
=
WaitForMultipleObjects
(
2
,
lpHandles
,
FALSE
/* return if state of any object is signalled*/
,
INFINITE
);
if
(
!
TerminateProcess
(
pi
.
hProcess
,
0
))
{
switch
(
dwEvent
)
{
log_event
(
EVENTLOG_ERROR_TYPE
,
gConfig
->
serviceName
,
"Failed to terminate java process"
);
// service stop event was signaled
}
case
WAIT_FAILED
:
case
WAIT_TIMEOUT
:
case
WAIT_OBJECT_0
+
0
:
if
(
WAIT_FAILED
==
dwEvent
)
{
log_event
(
EVENTLOG_ERROR_TYPE
,
gConfig
->
serviceName
,
"Java process or service wait failed."
);
}
if
(
!
TerminateProcess
(
pi
.
hProcess
,
0
))
{
log_event
(
EVENTLOG_ERROR_TYPE
,
gConfig
->
serviceName
,
"Failed to terminate java process"
);
}
log_event
(
EVENTLOG_INFORMATION_TYPE
,
gConfig
->
serviceName
,
"Shutdown Java process"
);
log_event
(
EVENTLOG_INFORMATION_TYPE
,
gConfig
->
serviceName
,
"Shutdown Java process"
);
break
;
// java process exit was signalled
case
WAIT_OBJECT_0
+
1
:
log_event
(
EVENTLOG_ERROR_TYPE
,
gConfig
->
serviceName
,
"Java process was abnormally terminated."
);
break
;
}
// Close process and thread handles.
// Close process and thread handles.
CloseHandle
(
pi
.
hProcess
);
CloseHandle
(
pi
.
hProcess
);
CloseHandle
(
pi
.
hThread
);
CloseHandle
(
pi
.
hThread
);
CloseHandle
(
log
);
ReportSvcStatus
(
SERVICE_STOPPED
,
NO_ERROR
,
0
);
ReportSvcStatus
(
SERVICE_STOPPED
,
NO_ERROR
,
0
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录