blob: 034a66be3c5ced2553622017e016d80ec7e33abc [file] [log] [blame]
Jan Tattermuscha7fff862015-02-13 11:08:08 -08001#region Copyright notice and license
2
Jan Tattermuschaf77b3d2015-02-13 11:22:21 -08003// Copyright 2015, Google Inc.
Jan Tattermuscha7fff862015-02-13 11:08:08 -08004// All rights reserved.
Craig Tiller190d3602015-02-18 09:23:38 -08005//
Jan Tattermuscha7fff862015-02-13 11:08:08 -08006// Redistribution and use in source and binary forms, with or without
7// modification, are permitted provided that the following conditions are
8// met:
Craig Tiller190d3602015-02-18 09:23:38 -08009//
Jan Tattermuscha7fff862015-02-13 11:08:08 -080010// * Redistributions of source code must retain the above copyright
11// notice, this list of conditions and the following disclaimer.
12// * Redistributions in binary form must reproduce the above
13// copyright notice, this list of conditions and the following disclaimer
14// in the documentation and/or other materials provided with the
15// distribution.
16// * Neither the name of Google Inc. nor the names of its
17// contributors may be used to endorse or promote products derived from
18// this software without specific prior written permission.
Craig Tiller190d3602015-02-18 09:23:38 -080019//
Jan Tattermuscha7fff862015-02-13 11:08:08 -080020// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
32#endregion
33
Jan Tattermuscha7608b02015-02-03 17:54:38 -080034using System;
Jan Tattermuscha7608b02015-02-03 17:54:38 -080035using System.Runtime.InteropServices;
Jan Tattermusch04eb89c2015-06-12 13:03:05 -070036using System.Threading.Tasks;
Jan Tattermusch30868622015-02-19 09:22:33 -080037using Grpc.Core.Internal;
Jan Tattermusch05261612015-07-24 00:28:16 -070038using Grpc.Core.Logging;
Jan Tattermusch04eb89c2015-06-12 13:03:05 -070039using Grpc.Core.Utils;
Jan Tattermuscha7608b02015-02-03 17:54:38 -080040
Jan Tattermusch30868622015-02-19 09:22:33 -080041namespace Grpc.Core
Jan Tattermuscha7608b02015-02-03 17:54:38 -080042{
43 /// <summary>
Jan Tattermusch23821ce2015-02-13 10:46:02 -080044 /// Encapsulates initialization and shutdown of gRPC library.
Jan Tattermuscha7608b02015-02-03 17:54:38 -080045 /// </summary>
Jan Tattermusch23821ce2015-02-13 10:46:02 -080046 public class GrpcEnvironment
Jan Tattermuscha7608b02015-02-03 17:54:38 -080047 {
Jan Tattermusch607307d2015-02-18 11:05:45 -080048 const int THREAD_POOL_SIZE = 4;
Jan Tattermuscha7608b02015-02-03 17:54:38 -080049
Jan Tattermusche1e11872015-02-12 10:23:37 -080050 [DllImport("grpc_csharp_ext.dll")]
51 static extern void grpcsharp_init();
Jan Tattermuscha7608b02015-02-03 17:54:38 -080052
Jan Tattermusche1e11872015-02-12 10:23:37 -080053 [DllImport("grpc_csharp_ext.dll")]
54 static extern void grpcsharp_shutdown();
Jan Tattermuscha7608b02015-02-03 17:54:38 -080055
56 static object staticLock = new object();
Jan Tattermusch04eb89c2015-06-12 13:03:05 -070057 static GrpcEnvironment instance;
Craig Tiller190d3602015-02-18 09:23:38 -080058
Jan Tattermusch05261612015-07-24 00:28:16 -070059 static ILogger logger = new ConsoleLogger();
60
Jan Tattermusch23821ce2015-02-13 10:46:02 -080061 readonly GrpcThreadPool threadPool;
Jan Tattermuschd3677482015-06-01 19:27:40 -070062 readonly CompletionRegistry completionRegistry;
Jan Tattermusch04eb89c2015-06-12 13:03:05 -070063 readonly DebugStats debugStats = new DebugStats();
Jan Tattermusch23821ce2015-02-13 10:46:02 -080064 bool isClosed;
Jan Tattermuscha7608b02015-02-03 17:54:38 -080065
66 /// <summary>
Jan Tattermusch04eb89c2015-06-12 13:03:05 -070067 /// Returns an instance of initialized gRPC environment.
68 /// Subsequent invocations return the same instance unless Shutdown has been called first.
Jan Tattermuscha7608b02015-02-03 17:54:38 -080069 /// </summary>
Jan Tattermusch04eb89c2015-06-12 13:03:05 -070070 internal static GrpcEnvironment GetInstance()
Jan Tattermusch075dde42015-03-11 18:21:00 -070071 {
72 lock (staticLock)
Jan Tattermuscha7608b02015-02-03 17:54:38 -080073 {
Jan Tattermusch23821ce2015-02-13 10:46:02 -080074 if (instance == null)
Jan Tattermuscha7608b02015-02-03 17:54:38 -080075 {
Jan Tattermusch23821ce2015-02-13 10:46:02 -080076 instance = new GrpcEnvironment();
Jan Tattermuscha7608b02015-02-03 17:54:38 -080077 }
Jan Tattermusch04eb89c2015-06-12 13:03:05 -070078 return instance;
Jan Tattermuscha7608b02015-02-03 17:54:38 -080079 }
80 }
81
82 /// <summary>
Jan Tattermusch04eb89c2015-06-12 13:03:05 -070083 /// Shuts down the gRPC environment if it was initialized before.
84 /// Blocks until the environment has been fully shutdown.
Jan Tattermuscha7608b02015-02-03 17:54:38 -080085 /// </summary>
86 public static void Shutdown()
87 {
Jan Tattermusch075dde42015-03-11 18:21:00 -070088 lock (staticLock)
Jan Tattermuscha7608b02015-02-03 17:54:38 -080089 {
Jan Tattermusch23821ce2015-02-13 10:46:02 -080090 if (instance != null)
Jan Tattermuscha7608b02015-02-03 17:54:38 -080091 {
Jan Tattermusch23821ce2015-02-13 10:46:02 -080092 instance.Close();
93 instance = null;
Jan Tattermuscha7608b02015-02-03 17:54:38 -080094 }
95 }
Jan Tattermuscha7608b02015-02-03 17:54:38 -080096 }
97
Jan Tattermusch23821ce2015-02-13 10:46:02 -080098 /// <summary>
Jan Tattermusch05261612015-07-24 00:28:16 -070099 /// Gets application-wide logger used by gRPC.
100 /// </summary>
101 /// <value>The logger.</value>
102 public static ILogger Logger
103 {
104 get
105 {
106 return logger;
107 }
108 }
109
110 /// <summary>
111 /// Sets the application-wide logger that should be used by gRPC.
112 /// </summary>
113 public static void SetLogger(ILogger customLogger)
114 {
115 Preconditions.CheckNotNull(customLogger);
116 logger = customLogger;
117 }
118
119 /// <summary>
Jan Tattermusch23821ce2015-02-13 10:46:02 -0800120 /// Creates gRPC environment.
121 /// </summary>
122 private GrpcEnvironment()
123 {
Jan Tattermusch05261612015-07-24 00:28:16 -0700124 NativeLogRedirector.Redirect();
Jan Tattermusch23821ce2015-02-13 10:46:02 -0800125 grpcsharp_init();
Jan Tattermusch04eb89c2015-06-12 13:03:05 -0700126 completionRegistry = new CompletionRegistry(this);
127 threadPool = new GrpcThreadPool(this, THREAD_POOL_SIZE);
Jan Tattermusch23821ce2015-02-13 10:46:02 -0800128 threadPool.Start();
129 // TODO: use proper logging here
Jan Tattermusch05261612015-07-24 00:28:16 -0700130 Logger.Info("gRPC initialized.");
Jan Tattermusch23821ce2015-02-13 10:46:02 -0800131 }
132
133 /// <summary>
Jan Tattermusch04eb89c2015-06-12 13:03:05 -0700134 /// Gets the completion registry used by this gRPC environment.
135 /// </summary>
136 internal CompletionRegistry CompletionRegistry
137 {
138 get
139 {
140 return this.completionRegistry;
141 }
142 }
143
144 /// <summary>
145 /// Gets the completion queue used by this gRPC environment.
146 /// </summary>
147 internal CompletionQueueSafeHandle CompletionQueue
148 {
149 get
150 {
151 return this.threadPool.CompletionQueue;
152 }
153 }
154
155 /// <summary>
156 /// Gets the completion queue used by this gRPC environment.
157 /// </summary>
158 internal DebugStats DebugStats
159 {
160 get
161 {
162 return this.debugStats;
163 }
164 }
165
166 /// <summary>
Jan Tattermusch23821ce2015-02-13 10:46:02 -0800167 /// Shuts down this environment.
168 /// </summary>
169 private void Close()
170 {
171 if (isClosed)
172 {
173 throw new InvalidOperationException("Close has already been called");
174 }
175 threadPool.Stop();
176 grpcsharp_shutdown();
177 isClosed = true;
178
Jan Tattermusch04eb89c2015-06-12 13:03:05 -0700179 debugStats.CheckOK();
180
Jan Tattermusch05261612015-07-24 00:28:16 -0700181 Logger.Info("gRPC shutdown.");
Jan Tattermusch23821ce2015-02-13 10:46:02 -0800182 }
Jan Tattermusch1b54fcf2015-05-01 14:30:16 -0700183
Jan Tattermusch04eb89c2015-06-12 13:03:05 -0700184 /// <summary>
185 /// Shuts down this environment asynchronously.
186 /// </summary>
187 private Task CloseAsync()
Jan Tattermusch1b54fcf2015-05-01 14:30:16 -0700188 {
Jan Tattermusch04eb89c2015-06-12 13:03:05 -0700189 return Task.Run(() =>
Jan Tattermusch1b54fcf2015-05-01 14:30:16 -0700190 {
Jan Tattermusch04eb89c2015-06-12 13:03:05 -0700191 try
192 {
193 Close();
194 }
195 catch (Exception e)
196 {
Jan Tattermusch05261612015-07-24 00:28:16 -0700197 Logger.Error(e, "Error occured while shutting down GrpcEnvironment.");
Jan Tattermusch04eb89c2015-06-12 13:03:05 -0700198 }
199 });
Jan Tattermusch1b54fcf2015-05-01 14:30:16 -0700200 }
Jan Tattermuscha7608b02015-02-03 17:54:38 -0800201 }
202}