Skip to content

Commit 103b054

Browse files
authored
HADOOP-19270 Use stable sort in commandQueue (#7038)
1 parent f552664 commit 103b054

File tree

6 files changed

+51
-36
lines changed

6 files changed

+51
-36
lines changed

hadoop-tools/hadoop-dynamometer/hadoop-dynamometer-workload/src/main/java/org/apache/hadoop/tools/dynamometer/workloadgenerator/audit/AuditCommandParser.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public interface AuditCommandParser {
3232

3333
/**
3434
* Initialize this parser with the given configuration. Guaranteed to be
35-
* called prior to any calls to {@link #parse(Text, Function)}.
35+
* called prior to any calls to {@link #parse(Long, Text, Function)}.
3636
*
3737
* @param conf The Configuration to be used to set up this parser.
3838
* @throws IOException if error on initializing a parser.
@@ -46,14 +46,15 @@ public interface AuditCommandParser {
4646
* between the start of the audit log and this command) into absolute
4747
* timestamps.
4848
*
49+
* @param sequence Sequence order of input line.
4950
* @param inputLine Single input line to convert.
5051
* @param relativeToAbsolute Function converting relative timestamps
5152
* (in milliseconds) to absolute timestamps
5253
* (in milliseconds).
5354
* @return A command representing the input line.
5455
* @throws IOException if error on parsing.
5556
*/
56-
AuditReplayCommand parse(Text inputLine,
57+
AuditReplayCommand parse(Long sequence, Text inputLine,
5758
Function<Long, Long> relativeToAbsolute) throws IOException;
5859

5960
}

hadoop-tools/hadoop-dynamometer/hadoop-dynamometer-workload/src/main/java/org/apache/hadoop/tools/dynamometer/workloadgenerator/audit/AuditLogDirectParser.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ public void initialize(Configuration conf) throws IOException {
112112
}
113113

114114
@Override
115-
public AuditReplayCommand parse(Text inputLine,
115+
public AuditReplayCommand parse(Long sequence, Text inputLine,
116116
Function<Long, Long> relativeToAbsolute) throws IOException {
117117
Matcher m = logLineParseRegex.matcher(inputLine.toString());
118118
if (!m.find()) {
@@ -147,7 +147,8 @@ public AuditReplayCommand parse(Text inputLine,
147147
}
148148
}
149149

150-
return new AuditReplayCommand(relativeToAbsolute.apply(relativeTimestamp),
150+
return new AuditReplayCommand(sequence,
151+
relativeToAbsolute.apply(relativeTimestamp),
151152
// Split the UGI on space to remove the auth and proxy portions of it
152153
SPACE_SPLITTER.split(parameterMap.get("ugi")).iterator().next(),
153154
parameterMap.get("cmd").replace("(options:", "(options="),

hadoop-tools/hadoop-dynamometer/hadoop-dynamometer-workload/src/main/java/org/apache/hadoop/tools/dynamometer/workloadgenerator/audit/AuditLogHiveTableParser.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,12 @@ public void initialize(Configuration conf) throws IOException {
6060
}
6161

6262
@Override
63-
public AuditReplayCommand parse(Text inputLine,
63+
public AuditReplayCommand parse(Long sequence, Text inputLine,
6464
Function<Long, Long> relativeToAbsolute) throws IOException {
6565
String[] fields = inputLine.toString().split(FIELD_SEPARATOR);
6666
long absoluteTimestamp = relativeToAbsolute
6767
.apply(Long.parseLong(fields[0]));
68-
return new AuditReplayCommand(absoluteTimestamp, fields[1], fields[2],
68+
return new AuditReplayCommand(sequence, absoluteTimestamp, fields[1], fields[2],
6969
fields[3], fields[4], fields[5]);
7070
}
7171

hadoop-tools/hadoop-dynamometer/hadoop-dynamometer-workload/src/main/java/org/apache/hadoop/tools/dynamometer/workloadgenerator/audit/AuditReplayCommand.java

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,17 @@ class AuditReplayCommand implements Delayed {
4343
private static final Pattern SIMPLE_UGI_PATTERN = Pattern
4444
.compile("([^/@ ]*).*?");
4545

46+
private Long sequence;
4647
private long absoluteTimestamp;
4748
private String ugi;
4849
private String command;
4950
private String src;
5051
private String dest;
5152
private String sourceIP;
5253

53-
AuditReplayCommand(long absoluteTimestamp, String ugi, String command,
54+
AuditReplayCommand(Long sequence, long absoluteTimestamp, String ugi, String command,
5455
String src, String dest, String sourceIP) {
56+
this.sequence = sequence;
5557
this.absoluteTimestamp = absoluteTimestamp;
5658
this.ugi = ugi;
5759
this.command = command;
@@ -60,6 +62,9 @@ class AuditReplayCommand implements Delayed {
6062
this.sourceIP = sourceIP;
6163
}
6264

65+
Long getSequence() {
66+
return sequence;
67+
}
6368
long getAbsoluteTimestamp() {
6469
return absoluteTimestamp;
6570
}
@@ -103,8 +108,12 @@ public long getDelay(TimeUnit unit) {
103108

104109
@Override
105110
public int compareTo(Delayed o) {
106-
return Long.compare(absoluteTimestamp,
107-
((AuditReplayCommand) o).absoluteTimestamp);
111+
int result = Long.compare(absoluteTimestamp,
112+
((AuditReplayCommand) o).absoluteTimestamp);
113+
if (result != 0) {
114+
return result;
115+
}
116+
return Long.compare(sequence, ((AuditReplayCommand) o).sequence);
108117
}
109118

110119
/**
@@ -122,9 +131,10 @@ boolean isPoison() {
122131
* information besides a timestamp; other getter methods wil return null.
123132
*/
124133
private static final class PoisonPillCommand extends AuditReplayCommand {
134+
private static final Long DEFAULT_SEQUENCE = -1L;
125135

126136
private PoisonPillCommand(long absoluteTimestamp) {
127-
super(absoluteTimestamp, null, null, null, null, null);
137+
super(DEFAULT_SEQUENCE, absoluteTimestamp, null, null, null, null, null);
128138
}
129139

130140
@Override
@@ -144,9 +154,9 @@ public boolean equals(Object other) {
144154
return false;
145155
}
146156
AuditReplayCommand o = (AuditReplayCommand) other;
147-
return absoluteTimestamp == o.absoluteTimestamp && ugi.equals(o.ugi)
148-
&& command.equals(o.command) && src.equals(o.src) && dest.equals(o.dest)
149-
&& sourceIP.equals(o.sourceIP);
157+
return sequence.equals(o.sequence) && absoluteTimestamp == o.absoluteTimestamp
158+
&& ugi.equals(o.ugi) && command.equals(o.command) && src.equals(o.src)
159+
&& dest.equals(o.dest) && sourceIP.equals(o.sourceIP);
150160
}
151161

152162
@Override
@@ -156,8 +166,8 @@ public int hashCode() {
156166

157167
@Override
158168
public String toString() {
159-
return String.format("AuditReplayCommand(absoluteTimestamp=%d, ugi=%s, "
160-
+ "command=%s, src=%s, dest=%s, sourceIP=%s",
161-
absoluteTimestamp, ugi, command, src, dest, sourceIP);
169+
return String.format("AuditReplayCommand(sequence=%d, absoluteTimestamp=%d, "
170+
+ "ugi=%s, command=%s, src=%s, dest=%s, sourceIP=%s",
171+
sequence, absoluteTimestamp, ugi, command, src, dest, sourceIP);
162172
}
163173
}

hadoop-tools/hadoop-dynamometer/hadoop-dynamometer-workload/src/main/java/org/apache/hadoop/tools/dynamometer/workloadgenerator/audit/AuditReplayMapper.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ public enum CommandType {
169169
private int numThreads;
170170
private double rateFactor;
171171
private long highestTimestamp;
172+
private Long highestSequence;
172173
private List<AuditReplayThread> threads;
173174
private DelayQueue<AuditReplayCommand> commandQueue;
174175
private Function<Long, Long> relativeToAbsoluteTimestamp;
@@ -246,7 +247,7 @@ public void setup(final Mapper.Context context) throws IOException {
246247
@Override
247248
public void map(LongWritable lineNum, Text inputLine, Mapper.Context context)
248249
throws IOException, InterruptedException {
249-
AuditReplayCommand cmd = commandParser.parse(inputLine,
250+
AuditReplayCommand cmd = commandParser.parse(lineNum.get(), inputLine,
250251
relativeToAbsoluteTimestamp);
251252
long delay = cmd.getDelay(TimeUnit.MILLISECONDS);
252253
// Prevent from loading too many elements into memory all at once
@@ -255,6 +256,7 @@ public void map(LongWritable lineNum, Text inputLine, Mapper.Context context)
255256
}
256257
commandQueue.put(cmd);
257258
highestTimestamp = cmd.getAbsoluteTimestamp();
259+
highestSequence = cmd.getSequence();
258260
}
259261

260262
@Override

hadoop-tools/hadoop-dynamometer/hadoop-dynamometer-workload/src/test/java/org/apache/hadoop/tools/dynamometer/workloadgenerator/audit/TestAuditLogDirectParser.java

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public class TestAuditLogDirectParser {
3030

3131
private static final long START_TIMESTAMP = 10000;
3232
private AuditLogDirectParser parser;
33+
private Long sequence = 1L;
3334

3435
@Before
3536
public void setup() throws Exception {
@@ -53,55 +54,55 @@ private Text getAuditString(String timestamp, String ugi, String cmd,
5354
public void testSimpleInput() throws Exception {
5455
Text in = getAuditString("1970-01-01 00:00:11,000", "fakeUser",
5556
"listStatus", "sourcePath", "null");
56-
AuditReplayCommand expected = new AuditReplayCommand(1000, "fakeUser",
57+
AuditReplayCommand expected = new AuditReplayCommand(sequence, 1000, "fakeUser",
5758
"listStatus", "sourcePath", "null", "0.0.0.0");
58-
assertEquals(expected, parser.parse(in, Function.identity()));
59+
assertEquals(expected, parser.parse(sequence, in, Function.identity()));
5960
}
6061

6162
@Test
6263
public void testInputWithEquals() throws Exception {
6364
Text in = getAuditString("1970-01-01 00:00:11,000", "fakeUser",
6465
"listStatus", "day=1970", "null");
65-
AuditReplayCommand expected = new AuditReplayCommand(1000, "fakeUser",
66+
AuditReplayCommand expected = new AuditReplayCommand(sequence, 1000, "fakeUser",
6667
"listStatus", "day=1970", "null", "0.0.0.0");
67-
assertEquals(expected, parser.parse(in, Function.identity()));
68+
assertEquals(expected, parser.parse(sequence, in, Function.identity()));
6869
}
6970

7071
@Test
7172
public void testInputWithRenameOptions() throws Exception {
7273
Text in = getAuditString("1970-01-01 00:00:11,000", "fakeUser",
7374
"rename (options=[TO_TRASH])", "sourcePath", "destPath");
74-
AuditReplayCommand expected = new AuditReplayCommand(1000, "fakeUser",
75+
AuditReplayCommand expected = new AuditReplayCommand(sequence, 1000, "fakeUser",
7576
"rename (options=[TO_TRASH])", "sourcePath", "destPath", "0.0.0.0");
76-
assertEquals(expected, parser.parse(in, Function.identity()));
77+
assertEquals(expected, parser.parse(sequence, in, Function.identity()));
7778
}
7879

7980
@Test
8081
public void testInputWithTokenAuth() throws Exception {
8182
Text in = getAuditString("1970-01-01 00:00:11,000", "fakeUser (auth:TOKEN)",
8283
"create", "sourcePath", "null");
83-
AuditReplayCommand expected = new AuditReplayCommand(1000, "fakeUser",
84+
AuditReplayCommand expected = new AuditReplayCommand(sequence, 1000, "fakeUser",
8485
"create", "sourcePath", "null", "0.0.0.0");
85-
assertEquals(expected, parser.parse(in, Function.identity()));
86+
assertEquals(expected, parser.parse(sequence, in, Function.identity()));
8687
}
8788

8889
@Test
8990
public void testInputWithProxyUser() throws Exception {
9091
Text in = getAuditString("1970-01-01 00:00:11,000",
9192
"proxyUser (auth:TOKEN) via fakeUser", "create", "sourcePath", "null");
92-
AuditReplayCommand expected = new AuditReplayCommand(1000, "proxyUser",
93-
"create", "sourcePath", "null", "0.0.0.0");
94-
assertEquals(expected, parser.parse(in, Function.identity()));
93+
AuditReplayCommand expected = new AuditReplayCommand(sequence, 1000,
94+
"proxyUser", "create", "sourcePath", "null", "0.0.0.0");
95+
assertEquals(expected, parser.parse(sequence, in, Function.identity()));
9596
}
9697

9798
@Test
9899
public void testParseDefaultDateFormat() throws Exception {
99100
Text in = getAuditString("1970-01-01 13:00:00,000",
100101
"ignored", "ignored", "ignored", "ignored");
101-
AuditReplayCommand expected = new AuditReplayCommand(
102+
AuditReplayCommand expected = new AuditReplayCommand(sequence,
102103
13 * 60 * 60 * 1000 - START_TIMESTAMP,
103104
"ignored", "ignored", "ignored", "ignored", "0.0.0.0");
104-
assertEquals(expected, parser.parse(in, Function.identity()));
105+
assertEquals(expected, parser.parse(sequence, in, Function.identity()));
105106
}
106107

107108
@Test
@@ -114,9 +115,9 @@ public void testParseCustomDateFormat() throws Exception {
114115
parser.initialize(conf);
115116
Text in = getAuditString("1970-01-01 01:00:00,000 PM",
116117
"ignored", "ignored", "ignored", "ignored");
117-
AuditReplayCommand expected = new AuditReplayCommand(13 * 60 * 60 * 1000,
118+
AuditReplayCommand expected = new AuditReplayCommand(sequence, 13 * 60 * 60 * 1000,
118119
"ignored", "ignored", "ignored", "ignored", "0.0.0.0");
119-
assertEquals(expected, parser.parse(in, Function.identity()));
120+
assertEquals(expected, parser.parse(sequence, in, Function.identity()));
120121
}
121122

122123
@Test
@@ -128,9 +129,9 @@ public void testParseCustomTimeZone() throws Exception {
128129
parser.initialize(conf);
129130
Text in = getAuditString("1970-01-01 01:00:00,000",
130131
"ignored", "ignored", "ignored", "ignored");
131-
AuditReplayCommand expected = new AuditReplayCommand(0,
132+
AuditReplayCommand expected = new AuditReplayCommand(sequence, 0,
132133
"ignored", "ignored", "ignored", "ignored", "0.0.0.0");
133-
assertEquals(expected, parser.parse(in, Function.identity()));
134+
assertEquals(expected, parser.parse(sequence, in, Function.identity()));
134135
}
135136

136137
@Test
@@ -144,9 +145,9 @@ public void testParseCustomAuditLineFormat() throws Exception {
144145
conf.set(AuditLogDirectParser.AUDIT_LOG_PARSE_REGEX_KEY,
145146
"CUSTOM FORMAT \\((?<timestamp>.+?)\\) (?<message>.+)");
146147
parser.initialize(conf);
147-
AuditReplayCommand expected = new AuditReplayCommand(0,
148+
AuditReplayCommand expected = new AuditReplayCommand(sequence, 0,
148149
"fakeUser", "fakeCommand", "src", "null", "0.0.0.0");
149-
assertEquals(expected, parser.parse(auditLine, Function.identity()));
150+
assertEquals(expected, parser.parse(sequence, auditLine, Function.identity()));
150151
}
151152

152153
}

0 commit comments

Comments
 (0)