Skip to content

Commit 3f3f705

Browse files
authored
Merge branch 'yugabyte:master' into master
2 parents f595a1e + 42335ee commit 3f3f705

File tree

8 files changed

+179
-91
lines changed

8 files changed

+179
-91
lines changed

java/yb-pgsql/src/test/java/org/yb/pgsql/TestPgRegressThirdPartyExtensionsHypopg.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import java.util.Collections;
2323
import java.util.Map;
2424

25+
import static org.yb.AssertionWrappers.*;
26+
2527
@RunWith(value=YBTestRunner.class)
2628
public class TestPgRegressThirdPartyExtensionsHypopg extends BasePgRegressTest {
2729
@Override
@@ -40,6 +42,13 @@ public void schedule_old_cost_model() throws Exception {
4042
Map<String, String> flagMap = super.getTServerFlags();
4143
flagMap.put("ysql_pg_conf_csv", "yb_enable_cbo=OFF");
4244
restartClusterWithFlags(Collections.emptyMap(), flagMap);
45+
46+
String enable_auto_analyze = miniCluster.getClient().getFlag(
47+
miniCluster.getTabletServers().keySet().iterator().next(),
48+
"ysql_enable_auto_analyze");
49+
assertTrue("ysql_enable_auto_analyze should remain at default value false",
50+
enable_auto_analyze.equals("false"));
51+
4352
runPgRegressTest(new File(TestUtils.getBuildRootDir(),
4453
"postgres_build/third-party-extensions/hypopg"),
4554
"yb_old_cost_model_schedule");
@@ -50,6 +59,13 @@ public void schedule() throws Exception {
5059
Map<String, String> flagMap = super.getTServerFlags();
5160
flagMap.put("ysql_pg_conf_csv", "yb_enable_cbo=ON");
5261
restartClusterWithFlags(Collections.emptyMap(), flagMap);
62+
63+
String enable_auto_analyze = miniCluster.getClient().getFlag(
64+
miniCluster.getTabletServers().keySet().iterator().next(),
65+
"ysql_enable_auto_analyze");
66+
assertTrue("ysql_enable_auto_analyze should be auto set to true",
67+
enable_auto_analyze.equals("true"));
68+
5369
runPgRegressTest(new File(TestUtils.getBuildRootDir(),
5470
"postgres_build/third-party-extensions/hypopg"),
5571
"yb_schedule");

managed/src/main/java/com/yugabyte/yw/commissioner/tasks/CreateContinuousBackup.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
package com.yugabyte.yw.commissioner.tasks;
1212

13-
import static com.yugabyte.yw.common.Util.NULL_UUID;
1413
import static play.mvc.Http.Status.INTERNAL_SERVER_ERROR;
1514

1615
import com.google.inject.Inject;
@@ -23,6 +22,7 @@
2322
import com.yugabyte.yw.common.ShellResponse;
2423
import com.yugabyte.yw.common.StorageUtil;
2524
import com.yugabyte.yw.common.StorageUtilFactory;
25+
import com.yugabyte.yw.common.Util;
2626
import com.yugabyte.yw.common.ha.PlatformReplicationHelper;
2727
import com.yugabyte.yw.common.ha.PlatformReplicationManager;
2828
import com.yugabyte.yw.forms.AbstractTaskParams;
@@ -103,12 +103,11 @@ public void runScheduledBackup(
103103
ScheduleTask.create(taskUUID, schedule.getScheduleUUID());
104104
CustomerTask.create(
105105
customer,
106-
NULL_UUID,
106+
Util.NULL_UUID,
107107
taskUUID,
108108
CustomerTask.TargetType.Yba,
109109
CustomerTask.TaskType.CreateYbaBackup,
110-
// TODO: Actually get platform IP
111-
"platform_ip");
110+
Util.getYwHostnameOrIP());
112111
log.info("Submitted continuous yba backup creation with task uuid = {}.", taskUUID);
113112
}
114113

scripts/installation/bin/yb-ctl

Lines changed: 18 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1732,7 +1732,7 @@ class ClusterControl:
17321732
print("-" * 100)
17331733
print("| {:<96} |".format(title))
17341734
print("-" * 100)
1735-
for k, v in body_kv_list:
1735+
for k, v in body_kv_list.items():
17361736
print("| {:20}: {:<74} |".format(k, v))
17371737
print("-" * 100)
17381738

@@ -1743,14 +1743,11 @@ class ClusterControl:
17431743
title = "Node Count: {} | Replication Factor: {}".format(
17441744
num_servers, self.get_replication_factor())
17451745
info_kv_list = self.gen_status_tserver_connectivity(DaemonId(DAEMON_TYPE_TSERVER, 1))
1746-
info_kv_list.extend([
1747-
# TODO: this might cause issues if the first master is down...
1748-
("Web UI", "http://{}/".format(
1749-
self.options.get_client_advertise_host_port(
1750-
DaemonId(DAEMON_TYPE_MASTER, 1),
1751-
"http"))),
1752-
("Cluster Data", self.options.cluster_base_dir)
1753-
])
1746+
# TODO: this might cause issues if the first master is down...
1747+
info_kv_list["Web UI"] = "http://{}/".format(self.options.get_client_advertise_host_port(
1748+
DaemonId(DAEMON_TYPE_MASTER, 1),
1749+
"http"))
1750+
info_kv_list["Cluster Data"] = self.options.cluster_base_dir
17541751
self.print_status_box(title, info_kv_list)
17551752
if more_info:
17561753
status_cmd = "yb-ctl"
@@ -1761,7 +1758,7 @@ class ClusterControl:
17611758
print("For more info, please use: {}".format(status_cmd))
17621759

17631760
def gen_status_tserver_connectivity(self, tserver_daemon_id):
1764-
info_kv_list = []
1761+
info_kv_list = dict()
17651762
if not tserver_daemon_id:
17661763
return info_kv_list
17671764

@@ -1777,11 +1774,8 @@ class ClusterControl:
17771774
self.options.get_client_tool_path('ysqlsh'), ip_address, ysql_port,
17781775
YSQL_DEFAULT_PORT)
17791776

1780-
info_kv_list.extend([
1781-
("JDBC", "jdbc:postgresql://{}:{}/yugabyte".format(
1782-
ip_address, ysql_port)),
1783-
("YSQL Shell", ysqlsh_cmd_line)
1784-
])
1777+
info_kv_list["JDBC"] = "jdbc:postgresql://{}:{}/yugabyte".format(ip_address, ysql_port)
1778+
info_kv_list["YSQL Shell"] = ysqlsh_cmd_line
17851779

17861780
# -----------------------------------------------------------------------------------------
17871781
# cqlsh command line
@@ -1794,8 +1788,7 @@ class ClusterControl:
17941788
if ycql_port != YCQL_DEFAULT_PORT:
17951789
cqlsh_cmd_line += ' %s' % ycql_port
17961790

1797-
info_kv_list.append(
1798-
("YCQL Shell", cqlsh_cmd_line))
1791+
info_kv_list["YCQL Shell"] = cqlsh_cmd_line
17991792

18001793
# -----------------------------------------------------------------------------------------
18011794
# redis-cli command line
@@ -1806,7 +1799,7 @@ class ClusterControl:
18061799
redis_cli_cmd_line = format_cmd_line_with_host_port(
18071800
self.options.get_client_tool_path('redis-cli'), ip_address, yedis_port,
18081801
YEDIS_DEFAULT_PORT)
1809-
info_kv_list.append(("YEDIS Shell", redis_cli_cmd_line))
1802+
info_kv_list["YEDIS Shell"] = redis_cli_cmd_line
18101803
return info_kv_list
18111804

18121805
def show_node_status(self, daemon_index, server_counts=None):
@@ -1818,19 +1811,18 @@ class ClusterControl:
18181811
master_daemon_id = DaemonId(DAEMON_TYPE_MASTER, daemon_index) if is_master else None
18191812

18201813
info_kv_list = self.gen_status_tserver_connectivity(tserver_daemon_id)
1821-
log_kv_list = []
1814+
log_kv_list = dict()
18221815
for idx, node_dir in enumerate(self.get_base_node_dirs(daemon_index)):
18231816
data_path = os.path.join(node_dir, "yb-data")
18241817
if idx == 0:
18251818
if is_tserver:
1826-
log_kv_list.append(
1827-
("yb-tserver Logs", os.path.join(data_path, DAEMON_TYPE_TSERVER, "logs")))
1819+
log_kv_list["yb-tserver Logs"] = os.path.join(data_path, DAEMON_TYPE_TSERVER,
1820+
"logs")
18281821
if is_master:
1829-
log_kv_list.append(
1830-
("yb-master Logs", os.path.join(data_path, DAEMON_TYPE_MASTER, "logs")))
1831-
info_kv_list.append(
1832-
("data-dir[{}]".format(idx), data_path))
1833-
info_kv_list.extend(log_kv_list)
1822+
log_kv_list["yb-master Logs"] = os.path.join(data_path, DAEMON_TYPE_MASTER,
1823+
"logs")
1824+
info_kv_list["data-dir[{}]".format(idx)] = data_path
1825+
info_kv_list |= log_kv_list
18341826

18351827
master_pid = self.get_pid(master_daemon_id) if master_daemon_id else None
18361828
process_list = []

src/yb/tserver/server_main_util.cc

Lines changed: 98 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@
1313

1414
#include "yb/tserver/server_main_util.h"
1515

16+
#include <algorithm>
1617
#include <iostream>
18+
#include <boost/algorithm/string/trim.hpp>
19+
#include "yb/util/string_case.h"
1720

1821
#if YB_ABSL_ENABLED
1922
#include "absl/debugging/symbolize.h"
@@ -31,6 +34,7 @@
3134
#include "yb/util/debug/trace_event.h"
3235
#include "yb/util/flags.h"
3336
#include "yb/util/mem_tracker.h"
37+
#include "yb/util/pg_util.h"
3438
#include "yb/util/size_literals.h"
3539
#include "yb/util/status.h"
3640

@@ -49,6 +53,8 @@ DECLARE_int64(memory_limit_hard_bytes);
4953
DECLARE_bool(ysql_enable_auto_analyze);
5054
DECLARE_bool(ysql_enable_auto_analyze_service);
5155
DECLARE_bool(ysql_enable_table_mutation_counter);
56+
DECLARE_string(ysql_pg_conf_csv);
57+
DECLARE_string(ysql_yb_enable_cbo);
5258

5359
namespace yb {
5460

@@ -125,40 +131,106 @@ void AdjustMemoryLimitsIfNeeded(bool is_master) {
125131
AdjustMemoryLimits(values);
126132
}
127133

128-
// If auto analyze service is used based on old deprecated flags,
129-
// adjust new flags' values based on the deprecated flags to make auto analyze
130-
// service behaves consistently.
131-
// When using deprecated flags, only setting both FLAGS_ysql_enable_auto_analyze
132-
// and FLAGS_ysql_enable_table_mutation_counter makes auto analyze service runable,
133-
// so ysql_enable_auto_analyze is set in the following precedence order
134-
// 1. Any explicit user set value for ysql_enable_auto_analyze.
135-
// 2. If not set explicitly,
136-
// 2.1 If ysql_enable_auto_analyze_service and ysql_enable_table_mutation_counter are set
137-
// explicitly. Use their values to set value for ysql_enable_auto_analyze.
138-
// ysql_enable_auto_analyze is true only if both ysql_enable_auto_analyze_service and
139-
// ysql_enable_table_mutation_counter are true.
140-
// 2.2 If not both of ysql_enable_auto_analyze_service and
141-
// ysql_enable_table_mutation_counter are set explicity,
142-
// use ysql_enable_auto_analyze default value.
134+
// Return the lower case value of a GUC set in a CSV string (FLAGS_ysql_pg_conf_csv),
135+
// accounting for the following
136+
// 1. GUC keys and values are case insensitive
137+
// 2. A GUC can be repeated multiple times, the final value is what matters
138+
// (consistent with WritePostgresConfig)
139+
std::optional<std::string> FindGUCValue(
140+
const std::string& guc_key, const std::vector<std::string>& user_configs) {
141+
std::optional<std::string> result;
142+
for (const auto& config : user_configs) {
143+
const auto lower_case_config = yb::ToLowerCase(config);
144+
if (lower_case_config.find(guc_key) == std::string::npos) {
145+
continue;
146+
}
147+
const auto pos = lower_case_config.find('=');
148+
if (pos != std::string::npos) {
149+
std::string config_key = boost::trim_copy(lower_case_config.substr(0, pos));
150+
std::string config_value = boost::trim_copy(lower_case_config.substr(pos + 1));
151+
if (config_key == guc_key) {
152+
result = config_value;
153+
}
154+
}
155+
}
156+
return result;
157+
}
158+
159+
// Auto analyze flag can have different defaults based on other flags like
160+
// older (deprecated) auto analyze flags or the cbo flags. In any case, an explict
161+
// user set flag value should be respected as-is.
143162
void AdjustAutoAnalyzeFlagIfNeeded() {
144-
// Check if the flag is explictly set.
145-
if (!google::GetCommandLineFlagInfoOrDie("ysql_enable_auto_analyze").is_default)
163+
// If the auto analyze flag is explictly set, do not change it.
164+
if (!google::GetCommandLineFlagInfoOrDie("ysql_enable_auto_analyze").is_default) {
165+
LOG(INFO) << "Flag: ysql_enable_auto_analyze has been set to " << FLAGS_ysql_enable_auto_analyze
166+
<< " by explicit config in command line";
146167
return;
147-
bool old_value_of_new_flag = FLAGS_ysql_enable_auto_analyze;
148-
// check if the old flags are enabled.
149-
bool auto_analyze_enabled_using_old_flags
150-
= FLAGS_ysql_enable_auto_analyze_service && FLAGS_ysql_enable_table_mutation_counter;
168+
}
169+
170+
// When we change ysql_yb_enable_cbo to default on, we need to update the logic here, so adding
171+
// a DCHECK to catch this situation.
172+
DCHECK(
173+
!(google::GetCommandLineFlagInfoOrDie("ysql_yb_enable_cbo").is_default &&
174+
FLAGS_ysql_yb_enable_cbo == "on"));
175+
176+
// If ysql_yb_enable_cbo was explicitly set by user, then ysql_enable_auto_analyze flag is set to
177+
// true whenever it is on. The reasoning is that CBO in legacy mode
178+
// can have more unpredictable behavior when ANALYZE is run, so we don't want to run ANALYZE
179+
// automatically.
180+
bool cbo_flag_on = false;
181+
std::string cbo_reason = "";
182+
const std::vector<std::string> cbo_on_values = {"on", "true", "1", "yes"};
183+
if (!google::GetCommandLineFlagInfoOrDie("ysql_yb_enable_cbo").is_default) {
184+
if (std::find(
185+
cbo_on_values.begin(), cbo_on_values.end(),
186+
yb::ToLowerCase(FLAGS_ysql_yb_enable_cbo)) != cbo_on_values.end()) {
187+
cbo_flag_on = true;
188+
cbo_reason = "ysql_yb_enable_cbo flag was explicitly set by user to '" +
189+
FLAGS_ysql_yb_enable_cbo + "'";
190+
}
191+
} else {
192+
// If ysql_pg_conf_csv contains yb_enable_cbo=on, then ysql_enable_auto_analyze is set to true.
193+
// Note that ysql_pg_conf_csv has lower precedence than user-set ysql_yb_enable_cbo.
194+
std::vector<std::string> user_configs;
195+
std::optional<std::string> cbo_guc_value;
196+
if (!FLAGS_ysql_pg_conf_csv.empty() &&
197+
ReadCSVValues(FLAGS_ysql_pg_conf_csv, &user_configs).ok() &&
198+
(cbo_guc_value = FindGUCValue("yb_enable_cbo", user_configs)).has_value() &&
199+
std::find(cbo_on_values.begin(), cbo_on_values.end(), cbo_guc_value.value()) !=
200+
cbo_on_values.end()) {
201+
cbo_flag_on = true;
202+
cbo_reason = "yb_enable_cbo was set to " + cbo_guc_value.value() + " in ysql_pg_conf_csv";
203+
}
204+
}
205+
206+
if (cbo_flag_on) {
207+
google::SetCommandLineOptionWithMode(
208+
"ysql_enable_auto_analyze", "true", google::SET_FLAG_IF_DEFAULT);
209+
LOG(INFO) << "Flag: ysql_yb_enable_auto_analyze was auto-set to "
210+
<< FLAGS_ysql_enable_auto_analyze << " because " << cbo_reason;
211+
return;
212+
}
213+
214+
// If ysql_enable_auto_analyze_service and ysql_enable_table_mutation_counter are set
215+
// explicitly, use their values to set value for ysql_enable_auto_analyze.
216+
// ysql_enable_auto_analyze is true only if both ysql_enable_auto_analyze_service and
217+
// ysql_enable_table_mutation_counter are true.
218+
const bool old_value_of_new_flag = FLAGS_ysql_enable_auto_analyze;
219+
const bool auto_analyze_enabled_using_old_flags =
220+
FLAGS_ysql_enable_auto_analyze_service && FLAGS_ysql_enable_table_mutation_counter;
151221
if (auto_analyze_enabled_using_old_flags) {
152-
// set new flag default.
153222
google::SetCommandLineOptionWithMode("ysql_enable_auto_analyze", "true",
154223
google::SET_FLAG_IF_DEFAULT);
155224

156-
LOG(INFO) << "Flag: ysql_enable_auto_analyze was auto-set to "
157-
<< FLAGS_ysql_enable_auto_analyze
225+
LOG(INFO) << "Flag: ysql_enable_auto_analyze was auto-set to " << FLAGS_ysql_enable_auto_analyze
158226
<< " from its default value of " << old_value_of_new_flag
159-
<< ". Flags: ysql_enable_auto_analyze_service and "
160-
<< "ysql_enable_table_mutation_counter are deprecated.";
227+
<< "because it was enabled by the following deprecated flags"
228+
<< " - ysql_enable_auto_analyze_service and ysql_enable_table_mutation_counter.";
229+
return;
161230
}
231+
232+
LOG(INFO) << "Not changing ysql_enable_auto_analyze from its default value "
233+
<< FLAGS_ysql_enable_auto_analyze;
162234
}
163235

164236
} // anonymous namespace

src/yb/tserver/tserver_flags.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ DEFINE_UNKNOWN_uint64(tserver_master_replication_factor, 0,
2727
"name and port through tserver_master_addrs for masters auto-discovery when running on "
2828
"Kubernetes.");
2929

30-
DEFINE_RUNTIME_bool(ysql_enable_auto_analyze, true,
30+
DEFINE_RUNTIME_bool(
31+
ysql_enable_auto_analyze, false,
3132
"Enable Auto Analyze to automatically trigger ANALYZE for updating table statistics of tables "
3233
"which have changed more than a configurable threshold.");

src/yb/util/pg_util.cc

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@
1414
#include "yb/util/pg_util.h"
1515

1616
#include <algorithm>
17+
18+
#include <regex>
1719
#include <string>
20+
#include <boost/algorithm/string/replace.hpp>
1821

1922
#include "yb/util/logging.h"
2023

@@ -111,4 +114,38 @@ std::string PgDeriveSocketLockFile(const HostPort& host_port) {
111114
PgDeriveSocketDir(host_port), Format(".s.PGSQL.$0.lock", host_port.port()));
112115
}
113116

117+
Status ReadCSVValues(const std::string& csv, std::vector<std::string>* lines) {
118+
// Function reads CSV string in the following format:
119+
// - fields are divided with comma (,)
120+
// - fields with comma (,) or double-quote (") are quoted with double-quote (")
121+
// - pair of double-quote ("") in quoted field represents single double-quote (")
122+
//
123+
// Examples:
124+
// 1,"two, 2","three ""3""", four , -> ['1', 'two, 2', 'three "3"', ' four ', '']
125+
// 1,"two -> Malformed CSV (quoted field 'two' is not closed)
126+
// 1, "two" -> Malformed CSV (quoted field 'two' has leading spaces)
127+
// 1,two "2" -> Malformed CSV (field with " must be quoted)
128+
// 1,"tw"o" -> Malformed CSV (no separator after quoted field 'tw')
129+
130+
const std::regex exp(R"(^(?:([^,"]+)|(?:"((?:[^"]|(?:""))*)\"))(?:(?:,)|(?:$)))");
131+
auto i = csv.begin();
132+
const auto end = csv.end();
133+
std::smatch match;
134+
while (i != end && std::regex_search(i, end, match, exp)) {
135+
// Replace pair of double-quote ("") with single double-quote (") in quoted field.
136+
if (match[2].length() > 0) {
137+
lines->emplace_back(match[2].first, match[2].second);
138+
boost::algorithm::replace_all(lines->back(), "\"\"", "\"");
139+
} else {
140+
lines->emplace_back(match[1].first, match[1].second);
141+
}
142+
i += match.length();
143+
}
144+
SCHECK(i == end, InvalidArgument, Format("Malformed CSV '$0'", csv));
145+
if (!csv.empty() && csv.back() == ',') {
146+
lines->emplace_back();
147+
}
148+
return Status::OK();
149+
}
150+
114151
} // namespace yb

0 commit comments

Comments
 (0)