qlever 0.5.15__py3-none-any.whl → 0.5.18__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of qlever might be problematic. Click here for more details.
- qlever/Qleverfiles/Qleverfile.ohm-planet +15 -12
- qlever/Qleverfiles/Qleverfile.osm-planet +17 -15
- qlever/Qleverfiles/Qleverfile.uniprot +2 -3
- qlever/__init__.py +9 -4
- qlever/command.py +6 -5
- qlever/commands/add_text_index.py +47 -28
- qlever/commands/example_queries.py +138 -46
- qlever/commands/extract_queries.py +113 -0
- qlever/commands/index.py +41 -14
- qlever/commands/query.py +32 -3
- qlever/commands/settings.py +110 -0
- qlever/commands/start.py +215 -104
- qlever/commands/stop.py +39 -26
- qlever/commands/system_info.py +7 -3
- qlever/commands/ui.py +16 -4
- qlever/log.py +2 -1
- qlever/qlever_old.py +607 -369
- qlever/qleverfile.py +29 -6
- qlever/util.py +34 -17
- {qlever-0.5.15.dist-info → qlever-0.5.18.dist-info}/METADATA +2 -2
- {qlever-0.5.15.dist-info → qlever-0.5.18.dist-info}/RECORD +25 -23
- {qlever-0.5.15.dist-info → qlever-0.5.18.dist-info}/WHEEL +1 -1
- {qlever-0.5.15.dist-info → qlever-0.5.18.dist-info}/LICENSE +0 -0
- {qlever-0.5.15.dist-info → qlever-0.5.18.dist-info}/entry_points.txt +0 -0
- {qlever-0.5.15.dist-info → qlever-0.5.18.dist-info}/top_level.txt +0 -0
qlever/commands/query.py
CHANGED
|
@@ -15,7 +15,21 @@ class QueryCommand(QleverCommand):
|
|
|
15
15
|
"""
|
|
16
16
|
|
|
17
17
|
def __init__(self):
|
|
18
|
-
|
|
18
|
+
self.predefined_queries = {
|
|
19
|
+
"all-predicates": (
|
|
20
|
+
"SELECT (?p AS ?predicate) (COUNT(?p) AS ?count) "
|
|
21
|
+
"WHERE { ?s ?p ?o } "
|
|
22
|
+
"GROUP BY ?p ORDER BY DESC(?count)"
|
|
23
|
+
),
|
|
24
|
+
"all-graphs": (
|
|
25
|
+
"SELECT ?g (COUNT(?g) AS ?count) "
|
|
26
|
+
"WHERE { GRAPH ?g { ?s ?p ?o } } "
|
|
27
|
+
"GROUP BY ?g ORDER BY DESC(?count)"
|
|
28
|
+
),
|
|
29
|
+
"ten-random-triples": (
|
|
30
|
+
"SELECT * WHERE { ?s ?p ?o } ORDER BY RAND() LIMIT 10"
|
|
31
|
+
),
|
|
32
|
+
}
|
|
19
33
|
|
|
20
34
|
def description(self) -> str:
|
|
21
35
|
return "Send a query to a SPARQL endpoint"
|
|
@@ -34,6 +48,12 @@ class QueryCommand(QleverCommand):
|
|
|
34
48
|
default="SELECT * WHERE { ?s ?p ?o } LIMIT 10",
|
|
35
49
|
help="SPARQL query to send",
|
|
36
50
|
)
|
|
51
|
+
subparser.add_argument(
|
|
52
|
+
"--predefined-query",
|
|
53
|
+
type=str,
|
|
54
|
+
choices=self.predefined_queries.keys(),
|
|
55
|
+
help="Use a predefined query",
|
|
56
|
+
)
|
|
37
57
|
subparser.add_argument(
|
|
38
58
|
"--pin-to-cache",
|
|
39
59
|
action="store_true",
|
|
@@ -64,6 +84,10 @@ class QueryCommand(QleverCommand):
|
|
|
64
84
|
)
|
|
65
85
|
|
|
66
86
|
def execute(self, args) -> bool:
|
|
87
|
+
# Use a predefined query if requested.
|
|
88
|
+
if args.predefined_query:
|
|
89
|
+
args.query = self.predefined_queries[args.predefined_query]
|
|
90
|
+
|
|
67
91
|
# When pinning to the cache, set `send=0` and request media type
|
|
68
92
|
# `application/qlever-results+json` so that we get the result size.
|
|
69
93
|
# Also, we need to provide the access token.
|
|
@@ -83,7 +107,9 @@ class QueryCommand(QleverCommand):
|
|
|
83
107
|
|
|
84
108
|
# Show what the command will do.
|
|
85
109
|
sparql_endpoint = (
|
|
86
|
-
args.sparql_endpoint
|
|
110
|
+
args.sparql_endpoint
|
|
111
|
+
if args.sparql_endpoint
|
|
112
|
+
else f"localhost:{args.port}"
|
|
87
113
|
)
|
|
88
114
|
curl_cmd = (
|
|
89
115
|
f"curl -s {sparql_endpoint}"
|
|
@@ -102,7 +128,10 @@ class QueryCommand(QleverCommand):
|
|
|
102
128
|
time_msecs = round(1000 * (time.time() - start_time))
|
|
103
129
|
if not args.no_time and args.log_level != "NO_LOG":
|
|
104
130
|
log.info("")
|
|
105
|
-
log.info(
|
|
131
|
+
log.info(
|
|
132
|
+
f"Query processing time (end-to-end):"
|
|
133
|
+
f" {time_msecs:,d} ms"
|
|
134
|
+
)
|
|
106
135
|
except Exception as e:
|
|
107
136
|
if args.log_level == "DEBUG":
|
|
108
137
|
traceback.print_exc()
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
|
|
5
|
+
from termcolor import colored
|
|
6
|
+
|
|
7
|
+
from qlever.command import QleverCommand
|
|
8
|
+
from qlever.log import log
|
|
9
|
+
from qlever.util import run_command
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class SettingsCommand(QleverCommand):
|
|
13
|
+
"""
|
|
14
|
+
Class for executing the `settings` command.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
def __init__(self):
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
def description(self) -> str:
|
|
21
|
+
return "Show or set server settings (after `qlever start`)"
|
|
22
|
+
|
|
23
|
+
def should_have_qleverfile(self) -> bool:
|
|
24
|
+
return True
|
|
25
|
+
|
|
26
|
+
def relevant_qleverfile_arguments(self) -> dict[str : list[str]]:
|
|
27
|
+
return {"server": ["port", "host_name", "access_token"]}
|
|
28
|
+
|
|
29
|
+
def additional_arguments(self, subparser) -> None:
|
|
30
|
+
all_keys = [
|
|
31
|
+
"always-multiply-unions",
|
|
32
|
+
"cache-max-num-entries",
|
|
33
|
+
"cache-max-size",
|
|
34
|
+
"cache-max-size-single-entry",
|
|
35
|
+
"default-query-timeout",
|
|
36
|
+
"group-by-disable-index-scan-optimizations",
|
|
37
|
+
"group-by-hash-map-enabled",
|
|
38
|
+
"lazy-index-scan-max-size-materialization",
|
|
39
|
+
"lazy-index-scan-num-threads",
|
|
40
|
+
"lazy-index-scan-queue-size",
|
|
41
|
+
"lazy-result-max-cache-size",
|
|
42
|
+
"query-planning-budget",
|
|
43
|
+
"service-max-value-rows",
|
|
44
|
+
"sort-estimate-cancellation-factor",
|
|
45
|
+
"throw-on-unbound-variables",
|
|
46
|
+
"use-binsearch-transitive-path",
|
|
47
|
+
]
|
|
48
|
+
subparser.add_argument(
|
|
49
|
+
"runtime_parameter",
|
|
50
|
+
nargs="?",
|
|
51
|
+
help="Set the given runtime parameter (key=value)"
|
|
52
|
+
"; if no argument is given, show all settings",
|
|
53
|
+
).completer = lambda **kwargs: [f"{key}=" for key in all_keys]
|
|
54
|
+
subparser.add_argument(
|
|
55
|
+
"--endpoint_url",
|
|
56
|
+
type=str,
|
|
57
|
+
help="An arbitrary endpoint URL "
|
|
58
|
+
"(overriding the one in the Qleverfile)",
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
def execute(self, args) -> bool:
|
|
62
|
+
# Get endpoint URL from command line or Qleverfile.
|
|
63
|
+
if args.endpoint_url:
|
|
64
|
+
endpoint_url = args.endpoint_url
|
|
65
|
+
else:
|
|
66
|
+
endpoint_url = f"http://{args.host_name}:{args.port}"
|
|
67
|
+
|
|
68
|
+
# Construct the `curl` command for getting or setting.
|
|
69
|
+
if args.runtime_parameter:
|
|
70
|
+
try:
|
|
71
|
+
parameter_key, parameter_value = args.runtime_parameter.split(
|
|
72
|
+
"="
|
|
73
|
+
)
|
|
74
|
+
except ValueError:
|
|
75
|
+
log.error("Runtime parameter must be given as `key=value`")
|
|
76
|
+
return False
|
|
77
|
+
|
|
78
|
+
curl_cmd = (
|
|
79
|
+
f"curl -s {endpoint_url}"
|
|
80
|
+
f' --data-urlencode "{parameter_key}={parameter_value}"'
|
|
81
|
+
f' --data-urlencode "access-token={args.access_token}"'
|
|
82
|
+
)
|
|
83
|
+
else:
|
|
84
|
+
curl_cmd = (
|
|
85
|
+
f"curl -s {endpoint_url}" f" --data-urlencode cmd=get-settings"
|
|
86
|
+
)
|
|
87
|
+
parameter_key, parameter_value = None, None
|
|
88
|
+
self.show(curl_cmd, only_show=args.show)
|
|
89
|
+
if args.show:
|
|
90
|
+
return True
|
|
91
|
+
|
|
92
|
+
# Execute the `curl` command. Note that the `get-settings` command
|
|
93
|
+
# returns all settings in both scencarios (that is, also when setting a
|
|
94
|
+
# parameter).
|
|
95
|
+
try:
|
|
96
|
+
settings_json = run_command(curl_cmd, return_output=True)
|
|
97
|
+
settings_dict = json.loads(settings_json)
|
|
98
|
+
except Exception as e:
|
|
99
|
+
log.error(f"setting command failed: {e}")
|
|
100
|
+
return False
|
|
101
|
+
for key, value in settings_dict.items():
|
|
102
|
+
print(
|
|
103
|
+
colored(
|
|
104
|
+
f"{key:<45}: {value}",
|
|
105
|
+
"blue"
|
|
106
|
+
if parameter_key and key == parameter_key
|
|
107
|
+
else None,
|
|
108
|
+
)
|
|
109
|
+
)
|
|
110
|
+
return True
|
qlever/commands/start.py
CHANGED
|
@@ -13,6 +13,110 @@ from qlever.log import log
|
|
|
13
13
|
from qlever.util import is_qlever_server_alive, run_command
|
|
14
14
|
|
|
15
15
|
|
|
16
|
+
# Construct the command line based on the config file.
|
|
17
|
+
def construct_command(args) -> str:
|
|
18
|
+
start_cmd = (
|
|
19
|
+
f"{args.server_binary}"
|
|
20
|
+
f" -i {args.name}"
|
|
21
|
+
f" -j {args.num_threads}"
|
|
22
|
+
f" -p {args.port}"
|
|
23
|
+
f" -m {args.memory_for_queries}"
|
|
24
|
+
f" -c {args.cache_max_size}"
|
|
25
|
+
f" -e {args.cache_max_size_single_entry}"
|
|
26
|
+
f" -k {args.cache_max_num_entries}"
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
if args.timeout:
|
|
30
|
+
start_cmd += f" -s {args.timeout}"
|
|
31
|
+
if args.access_token:
|
|
32
|
+
start_cmd += f" -a {args.access_token}"
|
|
33
|
+
if args.only_pso_and_pos_permutations:
|
|
34
|
+
start_cmd += " --only-pso-and-pos-permutations"
|
|
35
|
+
if not args.use_patterns:
|
|
36
|
+
start_cmd += " --no-patterns"
|
|
37
|
+
if args.use_text_index == "yes":
|
|
38
|
+
start_cmd += " -t"
|
|
39
|
+
start_cmd += f" > {args.name}.server-log.txt 2>&1"
|
|
40
|
+
return start_cmd
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
# Kill existing server on the same port. Trust that StopCommand() works?
|
|
44
|
+
# Maybe return StopCommand().execute(args) and handle it with a try except?
|
|
45
|
+
def kill_existing_server(args) -> bool:
|
|
46
|
+
args.cmdline_regex = f"^ServerMain.* -p {args.port}"
|
|
47
|
+
args.no_containers = True
|
|
48
|
+
if not StopCommand().execute(args):
|
|
49
|
+
log.error("Stopping the existing server failed")
|
|
50
|
+
return False
|
|
51
|
+
log.info("")
|
|
52
|
+
return True
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
# Run the command in a container
|
|
56
|
+
def wrap_command_in_container(args, start_cmd) -> str:
|
|
57
|
+
if not args.server_container:
|
|
58
|
+
args.server_container = f"qlever.server.{args.name}"
|
|
59
|
+
start_cmd = Containerize().containerize_command(
|
|
60
|
+
start_cmd,
|
|
61
|
+
args.system,
|
|
62
|
+
"run -d --restart=unless-stopped",
|
|
63
|
+
args.image,
|
|
64
|
+
args.server_container,
|
|
65
|
+
volumes=[("$(pwd)", "/index")],
|
|
66
|
+
ports=[(args.port, args.port)],
|
|
67
|
+
working_directory="/index",
|
|
68
|
+
)
|
|
69
|
+
return start_cmd
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
# When running natively, check if the binary exists and works.
|
|
73
|
+
def check_binary(binary) -> bool:
|
|
74
|
+
try:
|
|
75
|
+
run_command(f"{binary} --help")
|
|
76
|
+
return True
|
|
77
|
+
except Exception as e:
|
|
78
|
+
log.error(
|
|
79
|
+
f'Running "{binary}" failed, '
|
|
80
|
+
f"set `--server-binary` to a different binary or "
|
|
81
|
+
f"set `--system to a container system`"
|
|
82
|
+
)
|
|
83
|
+
log.info("")
|
|
84
|
+
log.info(f"The error message was: {e}")
|
|
85
|
+
return False
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
# Set the index description.
|
|
89
|
+
def set_index_description(access_arg, port, desc) -> bool:
|
|
90
|
+
curl_cmd = (
|
|
91
|
+
f"curl -Gs http://localhost:{port}/api"
|
|
92
|
+
f' --data-urlencode "index-description={desc}"'
|
|
93
|
+
f" {access_arg} > /dev/null"
|
|
94
|
+
)
|
|
95
|
+
log.debug(curl_cmd)
|
|
96
|
+
try:
|
|
97
|
+
run_command(curl_cmd)
|
|
98
|
+
except Exception as e:
|
|
99
|
+
log.error(f"Setting the index description failed ({e})")
|
|
100
|
+
return False
|
|
101
|
+
return True
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
# Set the text description.
|
|
105
|
+
def set_text_description(access_arg, port, text_desc) -> bool:
|
|
106
|
+
curl_cmd = (
|
|
107
|
+
f"curl -Gs http://localhost:{port}/api"
|
|
108
|
+
f' --data-urlencode "text-description={text_desc}"'
|
|
109
|
+
f" {access_arg} > /dev/null"
|
|
110
|
+
)
|
|
111
|
+
log.debug(curl_cmd)
|
|
112
|
+
try:
|
|
113
|
+
run_command(curl_cmd)
|
|
114
|
+
except Exception as e:
|
|
115
|
+
log.error(f"Setting the text description failed ({e})")
|
|
116
|
+
return False
|
|
117
|
+
return True
|
|
118
|
+
|
|
119
|
+
|
|
16
120
|
class StartCommand(QleverCommand):
|
|
17
121
|
"""
|
|
18
122
|
Class for executing the `start` command.
|
|
@@ -22,22 +126,35 @@ class StartCommand(QleverCommand):
|
|
|
22
126
|
pass
|
|
23
127
|
|
|
24
128
|
def description(self) -> str:
|
|
25
|
-
return (
|
|
26
|
-
|
|
129
|
+
return (
|
|
130
|
+
"Start the QLever server (requires that you have built "
|
|
131
|
+
"an index with `qlever index` before)"
|
|
132
|
+
)
|
|
27
133
|
|
|
28
134
|
def should_have_qleverfile(self) -> bool:
|
|
29
135
|
return True
|
|
30
136
|
|
|
31
|
-
def relevant_qleverfile_arguments(self) -> dict[str: list[str]]:
|
|
32
|
-
return {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
"
|
|
137
|
+
def relevant_qleverfile_arguments(self) -> dict[str : list[str]]:
|
|
138
|
+
return {
|
|
139
|
+
"data": ["name", "description", "text_description"],
|
|
140
|
+
"server": [
|
|
141
|
+
"server_binary",
|
|
142
|
+
"host_name",
|
|
143
|
+
"port",
|
|
144
|
+
"access_token",
|
|
145
|
+
"memory_for_queries",
|
|
146
|
+
"cache_max_size",
|
|
147
|
+
"cache_max_size_single_entry",
|
|
148
|
+
"cache_max_num_entries",
|
|
149
|
+
"num_threads",
|
|
150
|
+
"timeout",
|
|
151
|
+
"only_pso_and_pos_permutations",
|
|
152
|
+
"use_patterns",
|
|
153
|
+
"use_text_index",
|
|
154
|
+
"warmup_cmd",
|
|
155
|
+
],
|
|
156
|
+
"runtime": ["system", "image", "server_container"],
|
|
157
|
+
}
|
|
41
158
|
|
|
42
159
|
def additional_arguments(self, subparser) -> None:
|
|
43
160
|
# subparser.add_argument("--kill-existing-with-same-name",
|
|
@@ -46,16 +163,27 @@ class StartCommand(QleverCommand):
|
|
|
46
163
|
# help="If a QLever server is already running "
|
|
47
164
|
# "with the same name, kill it before "
|
|
48
165
|
# "starting a new server")
|
|
49
|
-
subparser.add_argument(
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
166
|
+
subparser.add_argument(
|
|
167
|
+
"--kill-existing-with-same-port",
|
|
168
|
+
action="store_true",
|
|
169
|
+
default=False,
|
|
170
|
+
help="If a QLever server is already running "
|
|
171
|
+
"on the same port, kill it before "
|
|
172
|
+
"starting a new server",
|
|
173
|
+
)
|
|
174
|
+
subparser.add_argument(
|
|
175
|
+
"--no-warmup",
|
|
176
|
+
action="store_true",
|
|
177
|
+
default=False,
|
|
178
|
+
help="Do not execute the warmup command",
|
|
179
|
+
)
|
|
180
|
+
subparser.add_argument(
|
|
181
|
+
"--run-in-foreground",
|
|
182
|
+
action="store_true",
|
|
183
|
+
default=False,
|
|
184
|
+
help="Run the server in the foreground "
|
|
185
|
+
"(default: run in the background with `nohup`)",
|
|
186
|
+
)
|
|
59
187
|
|
|
60
188
|
def execute(self, args) -> bool:
|
|
61
189
|
# Kill existing server with the same name if so desired.
|
|
@@ -70,47 +198,21 @@ class StartCommand(QleverCommand):
|
|
|
70
198
|
|
|
71
199
|
# Kill existing server on the same port if so desired.
|
|
72
200
|
if args.kill_existing_with_same_port:
|
|
73
|
-
args.
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
log.error("Stopping the existing server failed")
|
|
201
|
+
if args.kill_existing_with_same_port and not kill_existing_server(
|
|
202
|
+
args
|
|
203
|
+
):
|
|
77
204
|
return False
|
|
78
|
-
log.info("")
|
|
79
205
|
|
|
80
206
|
# Construct the command line based on the config file.
|
|
81
|
-
start_cmd = (
|
|
82
|
-
f" -i {args.name}"
|
|
83
|
-
f" -j {args.num_threads}"
|
|
84
|
-
f" -p {args.port}"
|
|
85
|
-
f" -m {args.memory_for_queries}"
|
|
86
|
-
f" -c {args.cache_max_size}"
|
|
87
|
-
f" -e {args.cache_max_size_single_entry}"
|
|
88
|
-
f" -k {args.cache_max_num_entries}")
|
|
89
|
-
if args.timeout:
|
|
90
|
-
start_cmd += f" -s {args.timeout}"
|
|
91
|
-
if args.access_token:
|
|
92
|
-
start_cmd += f" -a {args.access_token}"
|
|
93
|
-
if args.only_pso_and_pos_permutations:
|
|
94
|
-
start_cmd += " --only-pso-and-pos-permutations"
|
|
95
|
-
if not args.use_patterns:
|
|
96
|
-
start_cmd += " --no-patterns"
|
|
97
|
-
if args.use_text_index == "yes":
|
|
98
|
-
start_cmd += " -t"
|
|
99
|
-
start_cmd += f" > {args.name}.server-log.txt 2>&1"
|
|
207
|
+
start_cmd = construct_command(args)
|
|
100
208
|
|
|
101
209
|
# Run the command in a container (if so desired). Otherwise run with
|
|
102
|
-
# `nohup` so that it keeps running after the shell is closed.
|
|
210
|
+
# `nohup` so that it keeps running after the shell is closed. With
|
|
211
|
+
# `--run-in-foreground`, run the server in the foreground.
|
|
103
212
|
if args.system in Containerize.supported_systems():
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
start_cmd =
|
|
107
|
-
start_cmd,
|
|
108
|
-
args.system, "run -d --restart=unless-stopped",
|
|
109
|
-
args.image,
|
|
110
|
-
args.server_container,
|
|
111
|
-
volumes=[("$(pwd)", "/index")],
|
|
112
|
-
ports=[(args.port, args.port)],
|
|
113
|
-
working_directory="/index")
|
|
213
|
+
start_cmd = wrap_command_in_container(args, start_cmd)
|
|
214
|
+
elif args.run_in_foreground:
|
|
215
|
+
start_cmd = f"{start_cmd}"
|
|
114
216
|
else:
|
|
115
217
|
start_cmd = f"nohup {start_cmd} &"
|
|
116
218
|
|
|
@@ -121,35 +223,32 @@ class StartCommand(QleverCommand):
|
|
|
121
223
|
|
|
122
224
|
# When running natively, check if the binary exists and works.
|
|
123
225
|
if args.system == "native":
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
except Exception as e:
|
|
127
|
-
log.error(f"Running \"{args.server_binary}\" failed, "
|
|
128
|
-
f"set `--server-binary` to a different binary or "
|
|
129
|
-
f"set `--system to a container system`")
|
|
130
|
-
log.info("")
|
|
131
|
-
log.info(f"The error message was: {e}")
|
|
226
|
+
ret = check_binary(args.server_binary)
|
|
227
|
+
if not ret:
|
|
132
228
|
return False
|
|
133
229
|
|
|
134
230
|
# Check if a QLever server is already running on this port.
|
|
135
|
-
|
|
136
|
-
if is_qlever_server_alive(
|
|
137
|
-
log.error(f"QLever server already running on
|
|
231
|
+
endpoint_url = f"http://localhost:{args.port}"
|
|
232
|
+
if is_qlever_server_alive(endpoint_url):
|
|
233
|
+
log.error(f"QLever server already running on {endpoint_url}")
|
|
138
234
|
log.info("")
|
|
139
|
-
log.info(
|
|
140
|
-
|
|
141
|
-
|
|
235
|
+
log.info(
|
|
236
|
+
"To kill the existing server, use `qlever stop` "
|
|
237
|
+
"or `qlever start` with option "
|
|
238
|
+
"--kill-existing-with-same-port`"
|
|
239
|
+
)
|
|
142
240
|
|
|
143
241
|
# Show output of status command.
|
|
144
|
-
args.cmdline_regex = f"^ServerMain.* -p *{port}"
|
|
242
|
+
args.cmdline_regex = f"^ServerMain.* -p *{args.port}"
|
|
145
243
|
log.info("")
|
|
146
244
|
StatusCommand().execute(args)
|
|
147
|
-
|
|
148
245
|
return False
|
|
149
246
|
|
|
150
247
|
# Remove already existing container.
|
|
151
|
-
if
|
|
152
|
-
|
|
248
|
+
if (
|
|
249
|
+
args.system in Containerize.supported_systems()
|
|
250
|
+
and args.kill_existing_with_same_port
|
|
251
|
+
):
|
|
153
252
|
try:
|
|
154
253
|
run_command(f"{args.system} rm -f {args.server_container}")
|
|
155
254
|
except Exception as e:
|
|
@@ -166,7 +265,10 @@ class StartCommand(QleverCommand):
|
|
|
166
265
|
|
|
167
266
|
# Execute the command line.
|
|
168
267
|
try:
|
|
169
|
-
run_command(
|
|
268
|
+
process = run_command(
|
|
269
|
+
start_cmd,
|
|
270
|
+
use_popen=args.run_in_foreground,
|
|
271
|
+
)
|
|
170
272
|
except Exception as e:
|
|
171
273
|
log.error(f"Starting the QLever server failed ({e})")
|
|
172
274
|
return False
|
|
@@ -174,41 +276,40 @@ class StartCommand(QleverCommand):
|
|
|
174
276
|
# Tail the server log until the server is ready (note that the `exec`
|
|
175
277
|
# is important to make sure that the tail process is killed and not
|
|
176
278
|
# just the bash process).
|
|
177
|
-
|
|
178
|
-
|
|
279
|
+
if args.run_in_foreground:
|
|
280
|
+
log.info(
|
|
281
|
+
f"Follow {args.name}.server-log.txt as long as the server is"
|
|
282
|
+
f" running (Ctrl-C stops the server)"
|
|
283
|
+
)
|
|
284
|
+
else:
|
|
285
|
+
log.info(
|
|
286
|
+
f"Follow {args.name}.server-log.txt until the server is ready"
|
|
287
|
+
f" (Ctrl-C stops following the log, but NOT the server)"
|
|
288
|
+
)
|
|
179
289
|
log.info("")
|
|
180
290
|
tail_cmd = f"exec tail -f {args.name}.server-log.txt"
|
|
181
291
|
tail_proc = subprocess.Popen(tail_cmd, shell=True)
|
|
182
|
-
while not is_qlever_server_alive(
|
|
292
|
+
while not is_qlever_server_alive(endpoint_url):
|
|
183
293
|
time.sleep(1)
|
|
184
294
|
|
|
185
|
-
# Set the
|
|
186
|
-
access_arg = f
|
|
295
|
+
# Set the description for the index and text.
|
|
296
|
+
access_arg = f'--data-urlencode "access-token={args.access_token}"'
|
|
187
297
|
if args.description:
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
log.debug(curl_cmd)
|
|
193
|
-
try:
|
|
194
|
-
run_command(curl_cmd)
|
|
195
|
-
except Exception as e:
|
|
196
|
-
log.error(f"Setting the index description failed ({e})")
|
|
298
|
+
ret = set_index_description(
|
|
299
|
+
access_arg, args.port, args.description
|
|
300
|
+
)
|
|
301
|
+
if not ret:
|
|
197
302
|
return False
|
|
198
303
|
if args.text_description:
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
log.debug(curl_cmd)
|
|
204
|
-
try:
|
|
205
|
-
run_command(curl_cmd)
|
|
206
|
-
except Exception as e:
|
|
207
|
-
log.error(f"Setting the text description failed ({e})")
|
|
304
|
+
ret = set_text_description(
|
|
305
|
+
access_arg, args.port, args.text_description
|
|
306
|
+
)
|
|
307
|
+
if not ret:
|
|
208
308
|
return False
|
|
209
309
|
|
|
210
310
|
# Kill the tail process. NOTE: `tail_proc.kill()` does not work.
|
|
211
|
-
|
|
311
|
+
if not args.run_in_foreground:
|
|
312
|
+
tail_proc.terminate()
|
|
212
313
|
|
|
213
314
|
# Execute the warmup command.
|
|
214
315
|
if args.warmup_cmd and not args.no_warmup:
|
|
@@ -218,8 +319,18 @@ class StartCommand(QleverCommand):
|
|
|
218
319
|
return False
|
|
219
320
|
|
|
220
321
|
# Show cache stats.
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
322
|
+
if not args.run_in_foreground:
|
|
323
|
+
log.info("")
|
|
324
|
+
args.detailed = False
|
|
325
|
+
args.server_url = None
|
|
326
|
+
CacheStatsCommand().execute(args)
|
|
327
|
+
|
|
328
|
+
# With `--run-in-foreground`, wait until the server is stopped.
|
|
329
|
+
if args.run_in_foreground:
|
|
330
|
+
try:
|
|
331
|
+
process.wait()
|
|
332
|
+
except KeyboardInterrupt:
|
|
333
|
+
process.terminate()
|
|
334
|
+
tail_proc.terminate()
|
|
335
|
+
|
|
225
336
|
return True
|