Skip to content

Commit 2916010

Browse files
committed
Merge remote-tracking branch 'apache/master' into console-sink
2 parents a9d6b82 + 8598a98 commit 2916010

File tree

22 files changed

+423
-296
lines changed

22 files changed

+423
-296
lines changed

R/pkg/R/DataFrame.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2853,7 +2853,7 @@ setMethod("intersect",
28532853
#' except
28542854
#'
28552855
#' Return a new SparkDataFrame containing rows in this SparkDataFrame
2856-
#' but not in another SparkDataFrame. This is equivalent to \code{EXCEPT} in SQL.
2856+
#' but not in another SparkDataFrame. This is equivalent to \code{EXCEPT DISTINCT} in SQL.
28572857
#'
28582858
#' @param x a SparkDataFrame.
28592859
#' @param y a SparkDataFrame.

core/src/test/java/org/apache/spark/launcher/SparkLauncherSuite.java

Lines changed: 18 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
package org.apache.spark.launcher;
1919

20-
import java.time.Duration;
2120
import java.util.Arrays;
2221
import java.util.ArrayList;
2322
import java.util.HashMap;
@@ -32,7 +31,6 @@
3231
import static org.mockito.Mockito.*;
3332

3433
import org.apache.spark.SparkContext;
35-
import org.apache.spark.SparkContext$;
3634
import org.apache.spark.internal.config.package$;
3735
import org.apache.spark.util.Utils;
3836

@@ -139,9 +137,7 @@ public void testInProcessLauncher() throws Exception {
139137
// Here DAGScheduler is stopped, while SparkContext.clearActiveContext may not be called yet.
140138
// Wait for a reasonable amount of time to avoid creating two active SparkContext in JVM.
141139
// See SPARK-23019 and SparkContext.stop() for details.
142-
eventually(Duration.ofSeconds(5), Duration.ofMillis(10), () -> {
143-
assertTrue("SparkContext is still alive.", SparkContext$.MODULE$.getActive().isEmpty());
144-
});
140+
TimeUnit.MILLISECONDS.sleep(500);
145141
}
146142
}
147143

@@ -150,35 +146,26 @@ private void inProcessLauncherTestImpl() throws Exception {
150146
SparkAppHandle.Listener listener = mock(SparkAppHandle.Listener.class);
151147
doAnswer(invocation -> {
152148
SparkAppHandle h = (SparkAppHandle) invocation.getArguments()[0];
153-
synchronized (transitions) {
154-
transitions.add(h.getState());
155-
}
149+
transitions.add(h.getState());
156150
return null;
157151
}).when(listener).stateChanged(any(SparkAppHandle.class));
158152

159-
SparkAppHandle handle = null;
160-
try {
161-
handle = new InProcessLauncher()
162-
.setMaster("local")
163-
.setAppResource(SparkLauncher.NO_RESOURCE)
164-
.setMainClass(InProcessTestApp.class.getName())
165-
.addAppArgs("hello")
166-
.startApplication(listener);
167-
168-
waitFor(handle);
169-
assertEquals(SparkAppHandle.State.FINISHED, handle.getState());
170-
171-
// Matches the behavior of LocalSchedulerBackend.
172-
List<SparkAppHandle.State> expected = Arrays.asList(
173-
SparkAppHandle.State.CONNECTED,
174-
SparkAppHandle.State.RUNNING,
175-
SparkAppHandle.State.FINISHED);
176-
assertEquals(expected, transitions);
177-
} finally {
178-
if (handle != null) {
179-
handle.kill();
180-
}
181-
}
153+
SparkAppHandle handle = new InProcessLauncher()
154+
.setMaster("local")
155+
.setAppResource(SparkLauncher.NO_RESOURCE)
156+
.setMainClass(InProcessTestApp.class.getName())
157+
.addAppArgs("hello")
158+
.startApplication(listener);
159+
160+
waitFor(handle);
161+
assertEquals(SparkAppHandle.State.FINISHED, handle.getState());
162+
163+
// Matches the behavior of LocalSchedulerBackend.
164+
List<SparkAppHandle.State> expected = Arrays.asList(
165+
SparkAppHandle.State.CONNECTED,
166+
SparkAppHandle.State.RUNNING,
167+
SparkAppHandle.State.FINISHED);
168+
assertEquals(expected, transitions);
182169
}
183170

184171
public static class SparkLauncherTestApp {

external/kafka-0-10-sql/src/test/scala/org/apache/spark/sql/kafka010/KafkaSourceSuite.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -479,11 +479,6 @@ class KafkaMicroBatchSourceSuite extends KafkaSourceSuiteBase {
479479
// `failOnDataLoss` is `false`, we should not fail the query
480480
assert(query.exception.isEmpty)
481481
}
482-
}
483-
484-
class KafkaSourceSuiteBase extends KafkaSourceTest {
485-
486-
import testImplicits._
487482

488483
test("SPARK-22956: currentPartitionOffsets should be set when no new data comes in") {
489484
def getSpecificDF(range: Range.Inclusive): org.apache.spark.sql.Dataset[Int] = {
@@ -549,6 +544,11 @@ class KafkaSourceSuiteBase extends KafkaSourceTest {
549544
CheckLastBatch(120 to 124: _*)
550545
)
551546
}
547+
}
548+
549+
class KafkaSourceSuiteBase extends KafkaSourceTest {
550+
551+
import testImplicits._
552552

553553
test("cannot stop Kafka stream") {
554554
val topic = newTopic()

launcher/src/main/java/org/apache/spark/launcher/AbstractAppHandle.java

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ abstract class AbstractAppHandle implements SparkAppHandle {
3333
private List<Listener> listeners;
3434
private State state;
3535
private String appId;
36-
private volatile boolean disposed;
36+
private boolean disposed;
3737

3838
protected AbstractAppHandle(LauncherServer server) {
3939
this.server = server;
@@ -70,15 +70,16 @@ public void stop() {
7070

7171
@Override
7272
public synchronized void disconnect() {
73-
if (!isDisposed()) {
73+
if (!disposed) {
74+
disposed = true;
7475
if (connection != null) {
7576
try {
7677
connection.close();
7778
} catch (IOException ioe) {
7879
// no-op.
7980
}
8081
}
81-
dispose();
82+
server.unregister(this);
8283
}
8384
}
8485

@@ -94,21 +95,6 @@ boolean isDisposed() {
9495
return disposed;
9596
}
9697

97-
/**
98-
* Mark the handle as disposed, and set it as LOST in case the current state is not final.
99-
*/
100-
synchronized void dispose() {
101-
if (!isDisposed()) {
102-
// Unregister first to make sure that the connection with the app has been really
103-
// terminated.
104-
server.unregister(this);
105-
if (!getState().isFinal()) {
106-
setState(State.LOST);
107-
}
108-
this.disposed = true;
109-
}
110-
}
111-
11298
void setState(State s) {
11399
setState(s, false);
114100
}

launcher/src/main/java/org/apache/spark/launcher/ChildProcAppHandle.java

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,14 @@ public synchronized void disconnect() {
4848

4949
@Override
5050
public synchronized void kill() {
51-
if (!isDisposed()) {
52-
setState(State.KILLED);
53-
disconnect();
54-
if (childProc != null) {
55-
if (childProc.isAlive()) {
56-
childProc.destroyForcibly();
57-
}
58-
childProc = null;
51+
disconnect();
52+
if (childProc != null) {
53+
if (childProc.isAlive()) {
54+
childProc.destroyForcibly();
5955
}
56+
childProc = null;
6057
}
58+
setState(State.KILLED);
6159
}
6260

6361
void setChildProc(Process childProc, String loggerName, InputStream logStream) {
@@ -96,6 +94,8 @@ void monitorChild() {
9694
return;
9795
}
9896

97+
disconnect();
98+
9999
int ec;
100100
try {
101101
ec = proc.exitValue();
@@ -118,8 +118,6 @@ void monitorChild() {
118118
if (newState != null) {
119119
setState(newState, true);
120120
}
121-
122-
disconnect();
123121
}
124122
}
125123

launcher/src/main/java/org/apache/spark/launcher/InProcessAppHandle.java

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,15 @@ class InProcessAppHandle extends AbstractAppHandle {
3939

4040
@Override
4141
public synchronized void kill() {
42-
if (!isDisposed()) {
43-
LOG.warning("kill() may leave the underlying app running in in-process mode.");
44-
setState(State.KILLED);
45-
disconnect();
46-
47-
// Interrupt the thread. This is not guaranteed to kill the app, though.
48-
if (app != null) {
49-
app.interrupt();
50-
}
42+
LOG.warning("kill() may leave the underlying app running in in-process mode.");
43+
disconnect();
44+
45+
// Interrupt the thread. This is not guaranteed to kill the app, though.
46+
if (app != null) {
47+
app.interrupt();
5148
}
49+
50+
setState(State.KILLED);
5251
}
5352

5453
synchronized void start(String appName, Method main, String[] args) {

launcher/src/main/java/org/apache/spark/launcher/LauncherConnection.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -95,15 +95,15 @@ protected synchronized void send(Message msg) throws IOException {
9595
}
9696

9797
@Override
98-
public synchronized void close() throws IOException {
98+
public void close() throws IOException {
9999
if (!closed) {
100-
closed = true;
101-
socket.close();
100+
synchronized (this) {
101+
if (!closed) {
102+
closed = true;
103+
socket.close();
104+
}
105+
}
102106
}
103107
}
104108

105-
boolean isOpen() {
106-
return !closed;
107-
}
108-
109109
}

launcher/src/main/java/org/apache/spark/launcher/LauncherServer.java

Lines changed: 7 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -217,33 +217,6 @@ void unregister(AbstractAppHandle handle) {
217217
break;
218218
}
219219
}
220-
221-
// If there is a live connection for this handle, we need to wait for it to finish before
222-
// returning, otherwise there might be a race between the connection thread processing
223-
// buffered data and the handle cleaning up after itself, leading to potentially the wrong
224-
// state being reported for the handle.
225-
ServerConnection conn = null;
226-
synchronized (clients) {
227-
for (ServerConnection c : clients) {
228-
if (c.handle == handle) {
229-
conn = c;
230-
break;
231-
}
232-
}
233-
}
234-
235-
if (conn != null) {
236-
synchronized (conn) {
237-
if (conn.isOpen()) {
238-
try {
239-
conn.wait();
240-
} catch (InterruptedException ie) {
241-
// Ignore.
242-
}
243-
}
244-
}
245-
}
246-
247220
unref();
248221
}
249222

@@ -315,7 +288,7 @@ private String createSecret() {
315288
private class ServerConnection extends LauncherConnection {
316289

317290
private TimerTask timeout;
318-
volatile AbstractAppHandle handle;
291+
private AbstractAppHandle handle;
319292

320293
ServerConnection(Socket socket, TimerTask timeout) throws IOException {
321294
super(socket);
@@ -365,21 +338,16 @@ protected void handle(Message msg) throws IOException {
365338

366339
@Override
367340
public void close() throws IOException {
368-
if (!isOpen()) {
369-
return;
370-
}
371-
372341
synchronized (clients) {
373342
clients.remove(this);
374343
}
375-
376-
synchronized (this) {
377-
super.close();
378-
notifyAll();
379-
}
380-
344+
super.close();
381345
if (handle != null) {
382-
handle.dispose();
346+
if (!handle.getState().isFinal()) {
347+
LOG.log(Level.WARNING, "Lost connection to spark application.");
348+
handle.setState(SparkAppHandle.State.LOST);
349+
}
350+
handle.disconnect();
383351
}
384352
}
385353

launcher/src/test/java/org/apache/spark/launcher/BaseSuite.java

Lines changed: 7 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
package org.apache.spark.launcher;
1919

20-
import java.time.Duration;
2120
import java.util.concurrent.TimeUnit;
2221

2322
import org.junit.After;
@@ -48,46 +47,19 @@ public void postChecks() {
4847
assertNull(server);
4948
}
5049

51-
protected void waitFor(final SparkAppHandle handle) throws Exception {
50+
protected void waitFor(SparkAppHandle handle) throws Exception {
51+
long deadline = System.nanoTime() + TimeUnit.SECONDS.toNanos(10);
5252
try {
53-
eventually(Duration.ofSeconds(10), Duration.ofMillis(10), () -> {
54-
assertTrue("Handle is not in final state.", handle.getState().isFinal());
55-
});
53+
while (!handle.getState().isFinal()) {
54+
assertTrue("Timed out waiting for handle to transition to final state.",
55+
System.nanoTime() < deadline);
56+
TimeUnit.MILLISECONDS.sleep(10);
57+
}
5658
} finally {
5759
if (!handle.getState().isFinal()) {
5860
handle.kill();
5961
}
6062
}
61-
62-
// Wait until the handle has been marked as disposed, to make sure all cleanup tasks
63-
// have been performed.
64-
AbstractAppHandle ahandle = (AbstractAppHandle) handle;
65-
eventually(Duration.ofSeconds(10), Duration.ofMillis(10), () -> {
66-
assertTrue("Handle is still not marked as disposed.", ahandle.isDisposed());
67-
});
68-
}
69-
70-
/**
71-
* Call a closure that performs a check every "period" until it succeeds, or the timeout
72-
* elapses.
73-
*/
74-
protected void eventually(Duration timeout, Duration period, Runnable check) throws Exception {
75-
assertTrue("Timeout needs to be larger than period.", timeout.compareTo(period) > 0);
76-
long deadline = System.nanoTime() + timeout.toNanos();
77-
int count = 0;
78-
while (true) {
79-
try {
80-
count++;
81-
check.run();
82-
return;
83-
} catch (Throwable t) {
84-
if (System.nanoTime() >= deadline) {
85-
String msg = String.format("Failed check after %d tries: %s.", count, t.getMessage());
86-
throw new IllegalStateException(msg, t);
87-
}
88-
Thread.sleep(period.toMillis());
89-
}
90-
}
9163
}
9264

9365
}

0 commit comments

Comments
 (0)