Skip to content

Commit 4755500

Browse files
committed
[improve][broker] Improve the performance of TopicName constructor
1 parent 6ce15e1 commit 4755500

1 file changed

Lines changed: 44 additions & 43 deletions

File tree

  • pulsar-common/src/main/java/org/apache/pulsar/common/naming

pulsar-common/src/main/java/org/apache/pulsar/common/naming/TopicName.java

Lines changed: 44 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -115,41 +115,46 @@ private TopicName(String completeTopicName) {
115115
try {
116116
// The topic name can be in two different forms, one is fully qualified topic name,
117117
// the other one is short topic name
118-
if (!completeTopicName.contains("://")) {
118+
int index = completeTopicName.indexOf("://");
119+
if (index < 0) {
119120
// The short topic name can be:
120121
// - <topic>
121122
// - <tenant>/<namespace>/<topic>
122-
String[] parts = StringUtils.split(completeTopicName, '/');
123-
if (parts.length == 3) {
124-
completeTopicName = TopicDomain.persistent.name() + "://" + completeTopicName;
125-
} else if (parts.length == 1) {
126-
completeTopicName = TopicDomain.persistent.name() + "://"
127-
+ PUBLIC_TENANT + "/" + DEFAULT_NAMESPACE + "/" + parts[0];
123+
List<String> parts = splitBySlash(completeTopicName, 0);
124+
this.domain = TopicDomain.persistent;
125+
if (parts.size() == 3) {
126+
this.tenant = parts.get(0);
127+
this.namespacePortion = parts.get(1);
128+
this.localName = parts.get(2);
129+
} else if (parts.size() == 1) {
130+
this.tenant = PUBLIC_TENANT;
131+
this.namespacePortion = DEFAULT_NAMESPACE;
132+
this.localName = parts.get(0);
128133
} else {
129134
throw new IllegalArgumentException(
130135
"Invalid short topic name '" + completeTopicName + "', it should be in the format of "
131136
+ "<tenant>/<namespace>/<topic> or <topic>");
132137
}
133-
}
134-
135-
// Expected format: persistent://tenant/namespace/topic
136-
List<String> parts = Splitter.on("://").limit(2).splitToList(completeTopicName);
137-
this.domain = TopicDomain.getEnum(parts.get(0));
138-
139-
String rest = parts.get(1);
140-
141-
// Scalable topic domains (topic://, segment://) only support the new format
142-
// and local names may contain '/', so use limit(3) to keep the rest as localName.
143-
boolean isScalableDomain = this.domain == TopicDomain.topic
144-
|| this.domain == TopicDomain.segment;
145-
int splitLimit = isScalableDomain ? 3 : 4;
146-
parts = Splitter.on("/").limit(splitLimit).splitToList(rest);
147-
if (parts.size() == 4) {
148-
throw new IllegalArgumentException(
149-
"V1 topic names (with cluster component) are no longer supported. "
150-
+ "Please use the V2 format: '<domain>://tenant/namespace/topic'. Got: "
151-
+ completeTopicName);
152-
} else if (parts.size() == 3) {
138+
this.segmentRange = null;
139+
this.segmentId = -1;
140+
this.completeTopicName = domain.name() + "://" + tenant + "/" + namespacePortion + "/" + localName;
141+
} else {
142+
this.domain = TopicDomain.getEnum(completeTopicName.substring(0, index));
143+
// Scalable topic domains (topic://, segment://) only support the new format
144+
// and local names may contain '/', so use limit(3) to keep the rest as localName.
145+
boolean isScalableDomain = this.domain == TopicDomain.topic
146+
|| this.domain == TopicDomain.segment;
147+
int splitLimit = isScalableDomain ? 3 : 4;
148+
List<String> parts = splitBySlash(completeTopicName.substring(index + "://".length()),
149+
splitLimit);
150+
if (parts.size() == 4) {
151+
throw new IllegalArgumentException(
152+
"V1 topic names (with cluster component) are no longer supported. "
153+
+ "Please use the V2 format: '<domain>://tenant/namespace/topic'. Got: "
154+
+ completeTopicName);
155+
} else if (parts.size() != 3) {
156+
throw new IllegalArgumentException("Invalid topic name " + completeTopicName);
157+
}
153158
this.tenant = parts.get(0);
154159
this.namespacePortion = parts.get(1);
155160
String rawLocalName = parts.get(2);
@@ -160,16 +165,16 @@ private TopicName(String completeTopicName) {
160165
if (lastSlash <= 0) {
161166
throw new IllegalArgumentException(
162167
"Invalid segment topic name: local name must contain"
163-
+ " '<parent-topic>/<hashStart>-<hashEnd>-<segmentId>'. Got: "
164-
+ completeTopicName);
168+
+ " '<parent-topic>/<hashStart>-<hashEnd>-<segmentId>'. Got: "
169+
+ completeTopicName);
165170
}
166171
this.localName = rawLocalName.substring(0, lastSlash);
167172
String descriptor = rawLocalName.substring(lastSlash + 1);
168173
String[] descParts = descriptor.split("-");
169174
if (descParts.length != 3) {
170175
throw new IllegalArgumentException(
171176
"Invalid segment descriptor: expected '<hexStart>-<hexEnd>-<segmentId>',"
172-
+ " got: '" + descriptor + "'");
177+
+ " got: '" + descriptor + "'");
173178
}
174179
this.segmentRange = HashRange.of(
175180
Integer.parseInt(descParts[0], 16),
@@ -181,28 +186,24 @@ private TopicName(String completeTopicName) {
181186
this.segmentId = -1;
182187
}
183188

184-
this.partitionIndex = getPartitionIndex(completeTopicName);
185-
this.namespaceName = NamespaceName.get(tenant, namespacePortion);
186-
} else {
187-
throw new IllegalArgumentException("Invalid topic name: " + completeTopicName);
189+
if (this.domain == TopicDomain.segment) {
190+
this.completeTopicName = String.format("%s://%s/%s/%s/%s",
191+
domain, tenant, namespacePortion, localName,
192+
String.format("%04x-%04x-%d", segmentRange.start(), segmentRange.end(), segmentId));
193+
} else {
194+
this.completeTopicName = completeTopicName;
195+
}
188196
}
189197

190198
if (StringUtils.isBlank(localName)) {
191199
throw new IllegalArgumentException(String.format("Invalid topic name: %s. Topic local name must not"
192200
+ " be blank.", completeTopicName));
193201
}
194-
202+
this.partitionIndex = getPartitionIndex(localName);
203+
this.namespaceName = NamespaceName.get(tenant, namespacePortion);
195204
} catch (NullPointerException e) {
196205
throw new IllegalArgumentException("Invalid topic name: " + completeTopicName, e);
197206
}
198-
if (this.domain == TopicDomain.segment) {
199-
this.completeTopicName = String.format("%s://%s/%s/%s/%s",
200-
domain, tenant, namespacePortion, localName,
201-
String.format("%04x-%04x-%d", segmentRange.start(), segmentRange.end(), segmentId));
202-
} else {
203-
this.completeTopicName = String.format("%s://%s/%s/%s",
204-
domain, tenant, namespacePortion, localName);
205-
}
206207
}
207208

208209
public boolean isPersistent() {

0 commit comments

Comments
 (0)