• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

grpc / grpc-java / #19693

14 Feb 2025 09:20PM CUT coverage: 88.626% (-0.008%) from 88.634%
#19693

push

github

ejona86
kokoro: Increase gradle mem in android-interop

To try to aid failure when building android-interop-testing
```
The Daemon will expire after the build after running out of JVM heap space.
The project memory settings are likely not configured or are configured to an insufficient value.
The daemon will restart for the next build, which may increase subsequent build times.
These settings can be adjusted by setting 'org.gradle.jvmargs' in 'gradle.properties'.
The currently configured max heap space is '512 MiB' and the configured max metaspace is '384 MiB'.
...
Exception in thread "Daemon client event forwarder" java.lang.OutOfMemoryError: Java heap space
...
> Task :grpc-android-interop-testing:mergeDexDebug FAILED
ERROR:D8: java.lang.OutOfMemoryError: Java heap space
com.android.builder.dexing.DexArchiveMergerException: Error while merging dex archives:
```

34270 of 38668 relevant lines covered (88.63%)

0.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

83.02
/../core/src/main/java/io/grpc/internal/Http2Ping.java
1
/*
2
 * Copyright 2015 The gRPC Authors
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16

17
package io.grpc.internal;
18

19
import com.google.common.base.Stopwatch;
20
import com.google.errorprone.annotations.concurrent.GuardedBy;
21
import io.grpc.internal.ClientTransport.PingCallback;
22
import java.util.LinkedHashMap;
23
import java.util.Map;
24
import java.util.concurrent.Executor;
25
import java.util.concurrent.TimeUnit;
26
import java.util.logging.Level;
27
import java.util.logging.Logger;
28

29
/**
30
 * Represents an outstanding PING operation on an HTTP/2 channel. This can be used by HTTP/2-based
31
 * transports to implement {@link ClientTransport#ping}.
32
 *
33
 * <p>A typical transport need only support one outstanding ping at a time. So, if a ping is
34
 * requested while an operation is already in progress, the given callback is notified when the
35
 * existing operation completes.
36
 */
37
public class Http2Ping {
38
  private static final Logger log = Logger.getLogger(Http2Ping.class.getName());
1✔
39

40
  /**
41
   * The PING frame includes 8 octets of payload data, e.g. 64 bits.
42
   */
43
  private final long data;
44

45
  /**
46
   * Used to measure elapsed time.
47
   */
48
  private final Stopwatch stopwatch;
49

50
  /**
51
   * The registered callbacks and the executor used to invoke them.
52
   */
53
  @GuardedBy("this") private Map<PingCallback, Executor> callbacks
1✔
54
      = new LinkedHashMap<>();
55

56
  /**
57
   * False until the operation completes, either successfully (other side sent acknowledgement) or
58
   * unsuccessfully.
59
   */
60
  @GuardedBy("this") private boolean completed;
61

62
  /**
63
   * If non-null, indicates the ping failed.
64
   */
65
  @GuardedBy("this") private Throwable failureCause;
66

67
  /**
68
   * The round-trip time for the ping, in nanoseconds. This value is only meaningful when
69
   * {@link #completed} is true and {@link #failureCause} is null.
70
   */
71
  @GuardedBy("this") private long roundTripTimeNanos;
72

73
  /**
74
   * Creates a new ping operation. The caller is responsible for sending a ping on an HTTP/2 channel
75
   * using the given payload. The caller is also responsible for starting the stopwatch when the
76
   * PING frame is sent.
77
   *
78
   * @param data the ping payload
79
   * @param stopwatch a stopwatch for measuring round-trip time
80
   */
81
  public Http2Ping(long data, Stopwatch stopwatch) {
1✔
82
    this.data = data;
1✔
83
    this.stopwatch = stopwatch;
1✔
84
  }
1✔
85

86
  /**
87
   * Registers a callback that is invoked when the ping operation completes. If this ping operation
88
   * is already completed, the callback is invoked immediately.
89
   *
90
   * @param callback the callback to invoke
91
   * @param executor the executor to use
92
   */
93
  public void addCallback(final ClientTransport.PingCallback callback, Executor executor) {
94
    Runnable runnable;
95
    synchronized (this) {
1✔
96
      if (!completed) {
1✔
97
        callbacks.put(callback, executor);
1✔
98
        return;
1✔
99
      }
100
      // otherwise, invoke callback immediately (but not while holding lock)
101
      runnable = this.failureCause != null ? asRunnable(callback, failureCause)
×
102
                                           : asRunnable(callback, roundTripTimeNanos);
×
103
    }
×
104
    doExecute(executor, runnable);
×
105
  }
×
106

107
  /**
108
   * Returns the expected ping payload for this outstanding operation.
109
   *
110
   * @return the expected payload for this outstanding ping
111
   */
112
  public long payload() {
113
    return data;
1✔
114
  }
115

116
  /**
117
   * Completes this operation successfully. The stopwatch given during construction is used to
118
   * measure the elapsed time. Registered callbacks are invoked and provided the measured elapsed
119
   * time.
120
   *
121
   * @return true if the operation is marked as complete; false if it was already complete
122
   */
123
  public boolean complete() {
124
    Map<ClientTransport.PingCallback, Executor> callbacks;
125
    long roundTripTimeNanos;
126
    synchronized (this) {
1✔
127
      if (completed) {
1✔
128
        return false;
×
129
      }
130
      completed = true;
1✔
131
      roundTripTimeNanos = this.roundTripTimeNanos = stopwatch.elapsed(TimeUnit.NANOSECONDS);
1✔
132
      callbacks = this.callbacks;
1✔
133
      this.callbacks = null;
1✔
134
    }
1✔
135
    for (Map.Entry<ClientTransport.PingCallback, Executor> entry : callbacks.entrySet()) {
1✔
136
      doExecute(entry.getValue(), asRunnable(entry.getKey(), roundTripTimeNanos));
1✔
137
    }
1✔
138
    return true;
1✔
139
  }
140

141
  /**
142
   * Completes this operation exceptionally. Registered callbacks are invoked and provided the
143
   * given throwable as the cause of failure.
144
   *
145
   * @param failureCause the cause of failure
146
   */
147
  public void failed(Throwable failureCause) {
148
    Map<ClientTransport.PingCallback, Executor> callbacks;
149
    synchronized (this) {
1✔
150
      if (completed) {
1✔
151
        return;
×
152
      }
153
      completed = true;
1✔
154
      this.failureCause = failureCause;
1✔
155
      callbacks = this.callbacks;
1✔
156
      this.callbacks = null;
1✔
157
    }
1✔
158
    for (Map.Entry<ClientTransport.PingCallback, Executor> entry : callbacks.entrySet()) {
1✔
159
      notifyFailed(entry.getKey(), entry.getValue(), failureCause);
1✔
160
    }
1✔
161
  }
1✔
162

163
  /**
164
   * Notifies the given callback that the ping operation failed.
165
   *
166
   * @param callback the callback
167
   * @param executor the executor used to invoke the callback
168
   * @param cause the cause of failure
169
   */
170
  public static void notifyFailed(PingCallback callback, Executor executor, Throwable cause) {
171
    doExecute(executor, asRunnable(callback, cause));
1✔
172
  }
1✔
173

174
  /**
175
   * Executes the given runnable. This prevents exceptions from propagating so that an exception
176
   * thrown by one callback won't prevent subsequent callbacks from being executed.
177
   */
178
  private static void doExecute(Executor executor, Runnable runnable) {
179
    try {
180
      executor.execute(runnable);
1✔
181
    } catch (Throwable th) {
×
182
      log.log(Level.SEVERE, "Failed to execute PingCallback", th);
×
183
    }
1✔
184
  }
1✔
185

186
  /**
187
   * Returns a runnable that, when run, invokes the given callback, providing the given round-trip
188
   * duration.
189
   */
190
  private static Runnable asRunnable(final ClientTransport.PingCallback callback,
191
                                     final long roundTripTimeNanos) {
192
    return new Runnable() {
1✔
193
      @Override
194
      public void run() {
195
        callback.onSuccess(roundTripTimeNanos);
1✔
196
      }
1✔
197
    };
198

199
  }
200

201
  /**
202
   * Returns a runnable that, when run, invokes the given callback, providing the given cause of
203
   * failure.
204
   */
205
  private static Runnable asRunnable(final ClientTransport.PingCallback callback,
206
                                     final Throwable failureCause) {
207
    return new Runnable() {
1✔
208
      @Override
209
      public void run() {
210
        callback.onFailure(failureCause);
1✔
211
      }
1✔
212
    };
213
  }
214
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc