• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3  * SPDX-License-Identifier: Apache-2.0.
4  */
5 package software.amazon.awssdk.crt.io;
6 
7 import java.util.concurrent.CompletableFuture;
8 import software.amazon.awssdk.crt.CrtResource;
9 import software.amazon.awssdk.crt.CrtRuntimeException;
10 import software.amazon.awssdk.crt.Log;
11 
12 /**
13  * This class wraps the aws_client_bootstrap from aws-c-io to provide
14  * a client context for all protocol stacks in the AWS Common Runtime.
15  */
16 public final class ClientBootstrap extends CrtResource {
17 
18     private final CompletableFuture<Void> shutdownComplete = new CompletableFuture<>();
19 
20     /**
21      * Creates a new ClientBootstrap with a default HostResolver and EventLoopGroup.
22      * Most applications will only ever need one instance of this.
23      */
ClientBootstrap()24     private ClientBootstrap() throws CrtRuntimeException {
25         EventLoopGroup elg = EventLoopGroup.getOrCreateStaticDefault();
26         HostResolver hr = HostResolver.getOrCreateStaticDefault();
27         acquireNativeHandle(clientBootstrapNew(this, elg.getNativeHandle(), hr.getNativeHandle()));
28         // Order is likely important here
29         addReferenceTo(HostResolver.getOrCreateStaticDefault());
30         addReferenceTo(EventLoopGroup.getOrCreateStaticDefault());
31     }
32 
33     /**
34      * Creates a new ClientBootstrap. Most applications will only ever need one instance of this.
35      * @param hr A HostResolver instance, most applications only ever have one
36      * @param elg An EventLoopGroup instance, most applications only ever have one
37      * @throws CrtRuntimeException If the provided EventLoopGroup is null or invalid,
38      * or if the system is unable to allocate space for a native client bootstrap object
39      */
ClientBootstrap(EventLoopGroup elg, HostResolver hr)40     public ClientBootstrap(EventLoopGroup elg, HostResolver hr) throws CrtRuntimeException {
41         if (elg == null) {
42             elg = EventLoopGroup.getOrCreateStaticDefault();
43         }
44 
45         if (hr == null) {
46             hr = HostResolver.getOrCreateStaticDefault();
47         }
48 
49         acquireNativeHandle(clientBootstrapNew(this, elg.getNativeHandle(), hr.getNativeHandle()));
50 
51         // Order is likely important here
52         addReferenceTo(hr);
53         addReferenceTo(elg);
54     }
55 
56     /**
57      * Determines whether a resource releases its dependencies at the same time the native handle is released or if it waits.
58      * Resources that wait are responsible for calling releaseReferences() manually.
59      */
60     @Override
canReleaseReferencesImmediately()61     protected boolean canReleaseReferencesImmediately() { return false; }
62 
63     /**
64      * Cleans up the client bootstrap's associated native handle
65      */
66     @Override
releaseNativeHandle()67     protected void releaseNativeHandle() {
68         if (!isNull()) {
69             clientBootstrapDestroy(getNativeHandle());
70         }
71     }
72 
73     /**
74      * Called from Native when the asynchronous cleanup process needed for client bootstrap has completed.
75      */
onShutdownComplete()76     private void onShutdownComplete() {
77         Log.log(Log.LogLevel.Trace, Log.LogSubject.IoChannelBootstrap, "ClientBootstrap.onShutdownComplete");
78 
79         releaseReferences();
80 
81         this.shutdownComplete.complete(null);
82     }
83 
getShutdownCompleteFuture()84     public CompletableFuture<Void> getShutdownCompleteFuture() { return shutdownComplete; }
85 
86     /**
87      * Closes the static ClientBootstrap, if it exists.  Primarily intended for tests that use the static
88      * default ClientBootstrap, before they call waitForNoResources().
89      */
closeStaticDefault()90     public static void closeStaticDefault() {
91         synchronized (ClientBootstrap.class) {
92             if (staticDefaultClientBootstrap != null) {
93                 staticDefaultClientBootstrap.close();
94             }
95             staticDefaultClientBootstrap = null;
96         }
97     }
98 
99     /**
100      * This default will be used when a ClientBootstrap is not explicitly passed but is needed
101      * to allow the process to function. An example of this would be in the MQTT connection creation workflow.
102      * The default ClientBootstrap will use the default EventLoopGroup and HostResolver, creating them if
103      * necessary.
104      *
105      * The default ClientBootstrap will be automatically managed and released when it's
106      * resources are being freed, not requiring any manual memory management.
107      * @return the static default ClientBootstrap
108      */
getOrCreateStaticDefault()109     public static ClientBootstrap getOrCreateStaticDefault() {
110         ClientBootstrap client = null;
111         synchronized (ClientBootstrap.class) {
112             if (staticDefaultClientBootstrap == null) {
113                 staticDefaultClientBootstrap = new ClientBootstrap();
114             }
115 
116             client = staticDefaultClientBootstrap;
117         }
118 
119         return client;
120     }
121     private static ClientBootstrap staticDefaultClientBootstrap;
122 
123     /*******************************************************************************
124      * native methods
125      ******************************************************************************/
clientBootstrapNew(ClientBootstrap bootstrap, long elg, long hr)126     private static native long clientBootstrapNew(ClientBootstrap bootstrap, long elg, long hr) throws CrtRuntimeException;
clientBootstrapDestroy(long bootstrap)127     private static native void clientBootstrapDestroy(long bootstrap);
128 };
129