Skip to content

Commit 540d7b5

Browse files
tbgwenyihu6
authored andcommitted
state: improve ReplicaPlacement parsing and stringer
This makes the parsing and stringification a bit more versatile and allows most inputs to round-trip.
1 parent 1add120 commit 540d7b5

File tree

3 files changed

+71
-33
lines changed

3 files changed

+71
-33
lines changed

pkg/kv/kvserver/asim/state/parser_replica_placement.go

Lines changed: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,17 @@ type Ratio struct {
6161
func (r Ratio) String() string {
6262
storeAndTypes := make([]string, len(r.StoreIDs))
6363
for i := range r.StoreIDs {
64-
storeAndTypes[i] = "s" + strconv.Itoa(r.StoreIDs[i])
65-
if r.Types[i] == roachpb.NON_VOTER {
66-
storeAndTypes[i] += ":NON_VOTER"
64+
s := "s" + strconv.Itoa(r.StoreIDs[i]) + ":"
65+
if r.Types[i] != roachpb.VOTER_FULL {
66+
s += r.Types[i].String()
6767
}
6868
if r.StoreIDs[i] == r.LeaseholderID {
69-
storeAndTypes[i] += ":leaseholder"
69+
s += "*"
7070
}
71+
if l := len(s); s[l-1] == ':' {
72+
s = s[:l-1] // remove trailing ':'
73+
}
74+
storeAndTypes[i] = s
7175
}
7276
return "{" + strings.Join(storeAndTypes, ",") + "}:" + strconv.Itoa(r.Weight)
7377
}
@@ -88,11 +92,16 @@ func ParseReplicaPlacement(input string) ReplicaPlacement {
8892
pattern := `\{([^}]+)\}:(\d+)`
8993
re := regexp.MustCompile(pattern)
9094

95+
// Consider input "{s1:*,s2,s3:NON_VOTER}:1 {s4:*,s5,s6}:1".
9196
var result []Ratio
9297
matches := re.FindAllStringSubmatch(input, -1)
9398

99+
// matches[0] will be []string{"{s1:*,s2,s3:NON_VOTER}:1", "s1:*,s2,s3:NON_VOTER", "1"}
100+
// matches[1] will be []string{"{s4:*,s5,s6}:1", "s4:*,s5,s6", "1"}
94101
for _, match := range matches {
102+
// For matches[0], stores will be []string{"s1:*","s2","s3:NON_VOTER"}.
95103
stores := strings.Split(match[1], ",")
104+
// For matches[0], weight will be 1.
96105
weight, _ := strconv.Atoi(match[2])
97106

98107
storeSet := make([]int, 0)
@@ -103,24 +112,43 @@ func ParseReplicaPlacement(input string) ReplicaPlacement {
103112
for _, store := range stores {
104113
store = strings.TrimSpace(store)
105114
parts := strings.Split(store, ":")
106-
if strings.HasPrefix(parts[0], "s") {
107-
storeID, _ := strconv.Atoi(parts[0][1:])
108-
storeSet = append(storeSet, storeID)
109-
110-
replicaType := roachpb.VOTER_FULL
111-
if len(parts) > 1 {
112-
switch parts[1] {
113-
case "NON_VOTER":
114-
replicaType = roachpb.NON_VOTER
115-
case "*":
116-
leaseholderStoreID = storeID
117-
foundLeaseholder = true
118-
default:
119-
panic(fmt.Sprintf("unknown replica type: %s", parts[1]))
120-
}
121-
}
122-
typeSet = append(typeSet, replicaType)
115+
if len(parts) == 0 {
116+
panic(fmt.Sprintf("invalid replica placement: %s", input))
117+
}
118+
// For matches[0] and stores[0], parts will be []string{"s1","*"}.
119+
if !strings.HasPrefix(parts[0], "s") {
120+
panic(fmt.Sprintf("invalid replica placement: %s", input))
121+
}
122+
// For matches[0] and stores[0], storeID will be 1.
123+
storeID, _ := strconv.Atoi(parts[0][1:])
124+
storeSet = append(storeSet, storeID)
125+
126+
// If the replica type or leaseholder is not specified, artificially
127+
// append VOTER_FULL to parts. For matches[0] and stores[1], parts
128+
// will be []string{"s2","VOTER_FULL"}.
129+
if len(parts) < 2 {
130+
parts = append(parts, "VOTER_FULL")
131+
}
132+
if len(parts) < 2 {
133+
panic(fmt.Sprintf("invalid replica placement: %s", input))
134+
}
135+
// For matches[0] and stores[0], typ will be "VOTER_FULL".
136+
typ := parts[1]
137+
// If replica is a leaseholder, indicate the leaseholder store ID. Note
138+
// that incoming voter may also be a leaseholder.
139+
if last := len(typ) - 1; typ[last] == '*' {
140+
leaseholderStoreID = storeID
141+
foundLeaseholder = true
142+
typ = typ[:last] // remove '*'
143+
}
144+
if typ == "" {
145+
typ = roachpb.VOTER_FULL.String() // default type
146+
}
147+
v, ok := roachpb.ReplicaType_value[typ]
148+
if !ok {
149+
panic(fmt.Sprintf("unknown replica type: %s", typ))
123150
}
151+
typeSet = append(typeSet, roachpb.ReplicaType(v))
124152
}
125153

126154
if !foundLeaseholder {

pkg/kv/kvserver/asim/state/testdata/TestReplicaPlacement/basic.txt

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,37 +3,47 @@
33
parse
44
{s3}:1
55
----
6-
{s3:leaseholder}:1000
6+
{s3:*}:1000
77

88
parse
99
{s3}:7
1010
----
11-
{s3:leaseholder}:1000
11+
{s3:*}:1000
1212

1313
parse
1414
{s2:*}:100
1515
----
16-
{s2:leaseholder}:1000
16+
{s2:*}:1000
1717

1818
parse
1919
{s2:NON_VOTER,s4:*}:100
2020
----
21-
{s2:NON_VOTER,s4:leaseholder}:1000
21+
{s2:NON_VOTER,s4:*}:1000
2222

2323
parse
2424
{s2:NON_VOTER,s4:*, s1}:100
2525
----
26-
{s2:NON_VOTER,s4:leaseholder,s1}:1000
26+
{s2:NON_VOTER,s4:*,s1}:1000
2727

2828
parse
2929
{s1:*,s2,s3:NON_VOTER}:1 {s4:*,s5,s6}:1
3030
----
31-
{s1:leaseholder,s2,s3:NON_VOTER}:500
32-
{s4:leaseholder,s5,s6}:500
31+
{s1:*,s2,s3:NON_VOTER}:500
32+
{s4:*,s5,s6}:500
3333

3434
parse
3535
{s1:NON_VOTER,s2,s3}:10 {s4,s5:*,s6}:10 {s7,s2}:1
3636
----
37-
{s1:NON_VOTER:leaseholder,s2,s3}:477
38-
{s4,s5:leaseholder,s6}:476
39-
{s7:leaseholder,s2}:47
37+
{s1:NON_VOTER*,s2,s3}:477
38+
{s4,s5:*,s6}:476
39+
{s7:*,s2}:47
40+
41+
parse
42+
{s1:VOTER_FULL*,s2,s3}:1
43+
----
44+
{s1:*,s2,s3}:1000
45+
46+
parse
47+
{s1:VOTER_INCOMING*,s2,s3}:1
48+
----
49+
{s1:VOTER_INCOMING*,s2,s3}:1000

pkg/kv/kvserver/asim/tests/testdata/non_rand/example_replica_placement

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ gen_cluster nodes=3 stores_per_node=2
66
gen_ranges ranges=10 repl_factor=3 placement_type=replica_placement
77
{s1,s2:*,s3:NON_VOTER}:1 {s4,s5,s6}:1
88
----
9-
{s1,s2:leaseholder,s3:NON_VOTER}:1
10-
{s4:leaseholder,s5,s6}:1
9+
{s1,s2:*,s3:NON_VOTER}:1
10+
{s4:*,s5,s6}:1
1111

1212

1313
eval duration=10m

0 commit comments

Comments
 (0)