Skip to content

Commit 29fefe2

Browse files
committed
core: split Context into a separate grpc-context artifact.
The Context API is not particularly gRPC-specific, and will be used by Census as its context propagation mechanism. Removed all dependencies to make it easy for other libraries to depend on. Manually resolved conflicts: context/src/main/java/io/grpc/Context.java context/src/main/java/io/grpc/Deadline.java core/build.gradle
1 parent 22393f9 commit 29fefe2

File tree

9 files changed

+118
-31
lines changed

9 files changed

+118
-31
lines changed

all/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ buildscript {
1414
def subprojects = [
1515
project(':grpc-auth'),
1616
project(':grpc-core'),
17+
project(':grpc-context'),
1718
project(':grpc-netty'),
1819
project(':grpc-okhttp'),
1920
project(':grpc-protobuf'),

context/build.gradle

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
plugins {
2+
id "be.insaneprogramming.gradle.animalsniffer" version "1.4.0"
3+
}
4+
5+
description = 'gRPC: Context'
6+
7+
dependencies {
8+
testCompile project(':grpc-testing')
9+
}
10+
11+
// Configure the animal sniffer plugin
12+
animalsniffer {
13+
signature = "org.codehaus.mojo.signature:java16:+@signature"
14+
}

core/src/main/java/io/grpc/Context.java renamed to context/src/main/java/io/grpc/Context.java

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,6 @@
3131

3232
package io.grpc;
3333

34-
import com.google.common.base.Preconditions;
35-
import com.google.common.util.concurrent.MoreExecutors;
36-
3734
import java.util.ArrayList;
3835
import java.util.concurrent.Callable;
3936
import java.util.concurrent.Executor;
@@ -44,8 +41,6 @@
4441
import java.util.logging.Level;
4542
import java.util.logging.Logger;
4643

47-
import javax.annotation.Nullable;
48-
4944
/**
5045
* A context propagation mechanism which can carry scoped-values across API boundaries and between
5146
* threads. Examples of state propagated via context include:
@@ -275,8 +270,8 @@ public CancellableContext withDeadlineAfter(long duration, TimeUnit unit,
275270
*/
276271
public CancellableContext withDeadline(Deadline deadline,
277272
ScheduledExecutorService scheduler) {
278-
Preconditions.checkNotNull(deadline, "deadline");
279-
Preconditions.checkNotNull(scheduler, "scheduler");
273+
checkNotNull(deadline, "deadline");
274+
checkNotNull(scheduler, "scheduler");
280275
return new CancellableContext(this, deadline, scheduler);
281276
}
282277

@@ -349,7 +344,7 @@ public Context attach() {
349344
* will still be bound.
350345
*/
351346
public void detach(Context toAttach) {
352-
Preconditions.checkNotNull(toAttach);
347+
checkNotNull(toAttach, "toAttach");
353348
if (toAttach.attach() != this) {
354349
// Log a severe message instead of throwing an exception as the context to attach is assumed
355350
// to be the correct one and the unbalanced state represents a coding mistake in a lower
@@ -383,7 +378,6 @@ public boolean isCancelled() {
383378
* <p>The cancellation cause is provided for informational purposes only and implementations
384379
* should generally assume that it has already been handled and logged properly.
385380
*/
386-
@Nullable
387381
public Throwable cancellationCause() {
388382
if (parent == null || !cascadesCancellation) {
389383
return null;
@@ -396,7 +390,6 @@ public Throwable cancellationCause() {
396390
* A context may have an associated {@link Deadline} at which it will be automatically cancelled.
397391
* @return A {@link io.grpc.Deadline} or {@code null} if no deadline is set.
398392
*/
399-
@Nullable
400393
public Deadline getDeadline() {
401394
return DEADLINE_KEY.get(this);
402395
}
@@ -406,8 +399,8 @@ public Deadline getDeadline() {
406399
*/
407400
public void addListener(final CancellationListener cancellationListener,
408401
final Executor executor) {
409-
Preconditions.checkNotNull(cancellationListener);
410-
Preconditions.checkNotNull(executor);
402+
checkNotNull(cancellationListener, "cancellationListener");
403+
checkNotNull(executor, "executor");
411404
if (canBeCancelled) {
412405
ExecutableListener executableListener =
413406
new ExecutableListener(executor, cancellationListener);
@@ -420,7 +413,7 @@ public void addListener(final CancellationListener cancellationListener,
420413
// we can cascade listener notification.
421414
listeners = new ArrayList<ExecutableListener>();
422415
listeners.add(executableListener);
423-
parent.addListener(parentListener, MoreExecutors.directExecutor());
416+
parent.addListener(parentListener, DirectExecutor.INSTANCE);
424417
} else {
425418
listeners.add(executableListener);
426419
}
@@ -685,13 +678,13 @@ public boolean isCurrent() {
685678
}
686679

687680
/**
688-
* Cancel this context and optionally provide a cause for the cancellation. This
689-
* will trigger notification of listeners.
681+
* Cancel this context and optionally provide a cause (can be {@code null}) for the
682+
* cancellation. This will trigger notification of listeners.
690683
*
691684
* @return {@code true} if this context cancelled the context and notified listeners,
692685
* {@code false} if the context was already cancelled.
693686
*/
694-
public boolean cancel(@Nullable Throwable cause) {
687+
public boolean cancel(Throwable cause) {
695688
boolean triggeredCancel = false;
696689
synchronized (this) {
697690
if (!cancelled) {
@@ -717,7 +710,7 @@ public boolean cancel(@Nullable Throwable cause) {
717710
* @param toAttach context to make current.
718711
* @param cause of cancellation, can be {@code null}.
719712
*/
720-
public void detachAndCancel(Context toAttach, @Nullable Throwable cause) {
713+
public void detachAndCancel(Context toAttach, Throwable cause) {
721714
try {
722715
detach(toAttach);
723716
} finally {
@@ -741,7 +734,6 @@ public boolean isCancelled() {
741734
return false;
742735
}
743736

744-
@Nullable
745737
@Override
746738
public Throwable cancellationCause() {
747739
if (isCancelled()) {
@@ -774,7 +766,7 @@ public static class Key<T> {
774766
}
775767

776768
Key(String name, T defaultValue) {
777-
this.name = Preconditions.checkNotNull(name);
769+
this.name = checkNotNull(name, "name");
778770
this.defaultValue = defaultValue;
779771
}
780772

@@ -838,4 +830,25 @@ public void cancelled(Context context) {
838830
}
839831
}
840832
}
833+
834+
private static <T> T checkNotNull(T reference, Object errorMessage) {
835+
if (reference == null) {
836+
throw new NullPointerException(String.valueOf(errorMessage));
837+
}
838+
return reference;
839+
}
840+
841+
private enum DirectExecutor implements Executor {
842+
INSTANCE;
843+
844+
@Override
845+
public void execute(Runnable command) {
846+
command.run();
847+
}
848+
849+
@Override
850+
public String toString() {
851+
return "Context.DirectExecutor";
852+
}
853+
}
841854
}

core/src/main/java/io/grpc/Deadline.java renamed to context/src/main/java/io/grpc/Deadline.java

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,11 @@
3131

3232
package io.grpc;
3333

34-
import com.google.common.annotations.VisibleForTesting;
35-
import com.google.common.base.Preconditions;
36-
37-
import io.grpc.internal.LogExceptionRunnable;
38-
3934
import java.util.concurrent.ScheduledExecutorService;
4035
import java.util.concurrent.ScheduledFuture;
4136
import java.util.concurrent.TimeUnit;
37+
import java.util.logging.Level;
38+
import java.util.logging.Logger;
4239

4340
/**
4441
* An absolute deadline in system time.
@@ -60,9 +57,9 @@ public static Deadline after(long duration, TimeUnit units) {
6057
return after(duration, units, SYSTEM_TICKER);
6158
}
6259

63-
@VisibleForTesting
60+
// For testing
6461
static Deadline after(long duration, TimeUnit units, Ticker ticker) {
65-
Preconditions.checkNotNull(units);
62+
checkNotNull(units, "units");
6663
return new Deadline(ticker, units.toNanos(duration), true);
6764
}
6865

@@ -148,8 +145,8 @@ public long timeRemaining(TimeUnit unit) {
148145
* @return {@link ScheduledFuture} which can be used to cancel execution of the task
149146
*/
150147
public ScheduledFuture<?> runOnExpiration(Runnable task, ScheduledExecutorService scheduler) {
151-
Preconditions.checkNotNull(task, "task");
152-
Preconditions.checkNotNull(scheduler, "scheduler");
148+
checkNotNull(task, "task");
149+
checkNotNull(scheduler, "scheduler");
153150
return scheduler.schedule(new LogExceptionRunnable(task),
154151
deadlineNanos - ticker.read(), TimeUnit.NANOSECONDS);
155152
}
@@ -182,4 +179,42 @@ public long read() {
182179
return System.nanoTime();
183180
}
184181
}
182+
183+
private static <T> T checkNotNull(T reference, Object errorMessage) {
184+
if (reference == null) {
185+
throw new NullPointerException(String.valueOf(errorMessage));
186+
}
187+
return reference;
188+
}
189+
190+
private static class LogExceptionRunnable implements Runnable {
191+
private static final Logger log = Logger.getLogger(LogExceptionRunnable.class.getName());
192+
193+
private final Runnable task;
194+
195+
public LogExceptionRunnable(Runnable task) {
196+
this.task = checkNotNull(task, "task");
197+
}
198+
199+
@Override
200+
public void run() {
201+
try {
202+
task.run();
203+
} catch (Throwable t) {
204+
log.log(Level.SEVERE, "Exception while executing runnable " + task, t);
205+
if (t instanceof RuntimeException) {
206+
throw (RuntimeException) t;
207+
} else if (t instanceof Error) {
208+
throw (Error) t;
209+
} else {
210+
throw new RuntimeException(t);
211+
}
212+
}
213+
}
214+
215+
@Override
216+
public String toString() {
217+
return "Deadline.LogExceptionRunnable(" + task + ")";
218+
}
219+
}
185220
}

core/src/test/java/io/grpc/DeadlineTest.java renamed to context/src/test/java/io/grpc/DeadlineTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ public void toString_before() {
265265
assertEquals("12000 ns from now", d.toString());
266266
}
267267

268-
static class FakeTicker extends Deadline.Ticker {
268+
private static class FakeTicker extends Deadline.Ticker {
269269
private long time;
270270

271271
@Override

core/build.gradle

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ description = 'gRPC: Core'
66

77
dependencies {
88
compile libraries.guava,
9-
libraries.jsr305
9+
libraries.jsr305,
10+
project(':grpc-context')
1011
testCompile project(':grpc-testing')
1112
}
1213

core/src/test/java/io/grpc/CallOptionsTest.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,14 @@
5151
import org.junit.runners.JUnit4;
5252

5353
import java.util.concurrent.Executor;
54+
import java.util.concurrent.TimeUnit;
5455

5556
/** Unit tests for {@link CallOptions}. */
5657
@RunWith(JUnit4.class)
5758
public class CallOptionsTest {
5859
private String sampleAuthority = "authority";
5960
private String sampleCompressor = "compressor";
60-
private Deadline.Ticker ticker = new DeadlineTest.FakeTicker();
61+
private Deadline.Ticker ticker = new FakeTicker();
6162
private Deadline sampleDeadline = Deadline.after(1, NANOSECONDS, ticker);
6263
private Key<String> sampleKey = Attributes.Key.of("sample");
6364
private Attributes sampleAffinity = Attributes.newBuilder().set(sampleKey, "blah").build();
@@ -233,4 +234,24 @@ private static boolean equal(CallOptions o1, CallOptions o2) {
233234
&& Objects.equal(o1.getAffinity(), o2.getAffinity())
234235
&& Objects.equal(o1.getCredentials(), o2.getCredentials());
235236
}
237+
238+
private static class FakeTicker extends Deadline.Ticker {
239+
private long time;
240+
241+
@Override
242+
public long read() {
243+
return time;
244+
}
245+
246+
public void reset(long time) {
247+
this.time = time;
248+
}
249+
250+
public void increment(long period, TimeUnit unit) {
251+
if (period < 0) {
252+
throw new IllegalArgumentException();
253+
}
254+
this.time += unit.toNanos(period);
255+
}
256+
}
236257
}

settings.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
rootProject.name = "grpc"
22
include ":grpc-core"
3+
include ":grpc-context"
34
include ":grpc-stub"
45
include ":grpc-auth"
56
include ":grpc-okhttp"
@@ -15,6 +16,7 @@ include ":grpc-benchmarks"
1516
include ":grpc-services"
1617

1718
project(':grpc-core').projectDir = "$rootDir/core" as File
19+
project(':grpc-context').projectDir = "$rootDir/context" as File
1820
project(':grpc-stub').projectDir = "$rootDir/stub" as File
1921
project(':grpc-auth').projectDir = "$rootDir/auth" as File
2022
project(':grpc-okhttp').projectDir = "$rootDir/okhttp" as File

0 commit comments

Comments
 (0)