/// <summary> /// Shutdown the worker threads gracefully /// </summary> /// <param name="wait">Set this to true if you want to wait for threads to shutdown.</param> public void Shutdown(bool wait) { InternalLogger.LogInformation(String.Format("BoundedThreadPool \"{0}\" Shutting Down", this.name)); if (this.status != ThreadPoolStatus.Active) { return; } Thread[] threads; lock (taskQueue) { // Signal the threads to exit this.status = ThreadPoolStatus.ShuttingDown; Monitor.PulseAll(taskQueue); // Make a copy of the threads' references in the pool threads = new Thread[numWorkerThreads]; workerThreads.CopyTo(threads, 0); } if (wait) { for (int i = 0; i < this.numWorkerThreads; i++) { threads[i].Join(); } } // Abort the threads in the pool foreach (Thread thread in threads) { if ((thread != null) && thread.IsAlive) { try { thread.Abort(); // Shutdown } catch (SecurityException ex) { ex.GetHashCode(); } catch (ThreadStateException ex) { ex.GetHashCode(); // In case the thread has been terminated // after the check if it is alive. } } } // clear threads refs Array.Clear(workerThreads, 0, workerThreads.Length); this.status = ThreadPoolStatus.Closed; InternalLogger.LogInformation(String.Format("BoundedThreadPool \"{0}\" Shut Down", this.name)); }
/// <summary> /// Constructs the invoke delegate using Expressions /// /// Serialize & Deserialize calls are only made when a serializer is provided. /// Context is only passed when customer method has context parameter. /// Lambda return type can be void. /// /// (inStream, context, outStream) => /// { /// var input = serializer.Deserialize(inStream); /// var output = handler(input, context); /// return serializer.Serialize(output); /// } /// /// </summary> /// <param name="customerObject">Wrapped customer object.</param> /// <param name="customerSerializerInstance">Instance of lambda input & output serializer.</param> /// <returns>Action delegate pointing to customer's handler.</returns> public Action <Stream, ILambdaContext, Stream> ConstructInvokeDelegate(object customerObject, object customerSerializerInstance, bool isPreJit) { var inStreamParameter = Expression.Parameter(Types.StreamType, "inStream"); var outStreamParameter = Expression.Parameter(Types.StreamType, "outStream"); var contextParameter = Expression.Parameter(typeof(ILambdaContext), "context"); _logger.LogDebug($"UCL : Constructing input expression"); var inputExpression = BuildInputExpressionOrNull(customerSerializerInstance, inStreamParameter, out var iLambdaContextType); if (isPreJit) { _logger.LogInformation("PreJit: inputExpression"); UserCodeInit.InitDeserializationAssembly(inputExpression, inStreamParameter); } _logger.LogDebug($"UCL : Constructing context expression"); var contextExpression = BuildContextExpressionOrNull(iLambdaContextType, contextParameter); _logger.LogDebug($"UCL : Constructing handler expression"); var handlerExpression = CreateHandlerCallExpression(customerObject, inputExpression, contextExpression); _logger.LogDebug($"UCL : Constructing output expression"); var outputExpression = CreateOutputExpression(customerSerializerInstance, outStreamParameter, handlerExpression); if (isPreJit) { _logger.LogInformation("PreJit: outputExpression"); UserCodeInit.InitSerializationAssembly(outputExpression, outStreamParameter, CustomerOutputType); } _logger.LogDebug($"UCL : Constructing final expression"); var finalExpression = Expression.Lambda <Action <Stream, ILambdaContext, Stream> >(outputExpression, inStreamParameter, contextParameter, outStreamParameter); #if DEBUG var finalExpressionDebugView = typeof(Expression) .GetTypeInfo() .GetProperty("DebugView", BindingFlags.Instance | BindingFlags.NonPublic) .GetValue(finalExpression); _logger.LogDebug($"UCL : Constructed final expression:\n'{finalExpressionDebugView}'"); #endif _logger.LogDebug($"UCL : Compiling final expression"); return(finalExpression.Compile()); }
private void SafeParseCleanInterval() { string cleanIntervalAttribute = Attributes[CLEAN_INTERVAL]; if (!TimeSpan.TryParse(cleanIntervalAttribute, out _cleanInterval)) { // Reset default value _cleanInterval = DEFAULT_CLEAN_INTERVAL; InternalLogger.LogInformation(string.Format( Resources.CleanIntervalInvalid, cleanIntervalAttribute, _cleanInterval)); } if (_cleanInterval == TimeSpan.Zero) { _cleanInterval = DEFAULT_CLEAN_INTERVAL; InternalLogger.LogInformation(string.Format( Resources.CleanIntervalCannotBeZero, cleanIntervalAttribute, _cleanInterval)); } }
/// <summary> /// Run the initialization Func if provided. /// Then run the invoke loop, calling the handler for each invocation. /// </summary> /// <param name="cancellationToken"></param> /// <returns>A Task that represents the operation.</returns> public async Task RunAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (UserCodeInit.IsCallPreJit()) { this._logger.LogInformation("PreJit: CultureInfo"); UserCodeInit.LoadStringCultureInfo(); this._logger.LogInformation("PreJit: Amazon.Lambda.Core"); UserCodeInit.PreJitAssembly(typeof(Amazon.Lambda.Core.ILambdaContext).Assembly); } // For local debugging purposes this environment variable can be set to run a Lambda executable assembly and process one event // and then shut down cleanly. Useful for profiling or running local tests with the .NET Lambda Test Tool. This environment // variable should never be set when function is deployed to Lambda. var runOnce = string.Equals(Environment.GetEnvironmentVariable(Constants.ENVIRONMENT_VARIANLE_AWS_LAMBDA_DOTNET_DEBUG_RUN_ONCE), "true", StringComparison.OrdinalIgnoreCase); bool doStartInvokeLoop = _initializer == null || await InitializeAsync(); while (doStartInvokeLoop && !cancellationToken.IsCancellationRequested) { try { await InvokeOnceAsync(cancellationToken); if (runOnce) { _logger.LogInformation("Exiting Lambda processing loop because the run once environment variable was set."); return; } } catch (OperationCanceledException) when(cancellationToken.IsCancellationRequested) { // Loop cancelled } } }
/// <summary> /// Loads customer assembly, type, and method. /// After this call returns without errors, it is possible to invoke /// the customer method through the Invoke method. /// </summary> public void Init(Action <string> customerLoggingAction) { Assembly customerAssembly = null; try { _logger.LogDebug($"UCL : Parsing handler string '{_handlerString}'"); _handler = new HandlerInfo(_handlerString); // Set the logging action private field on the Amazon.Lambda.Core.LambdaLogger type which is part of the // public Amazon.Lambda.Core package when it is loaded. AppDomain.CurrentDomain.AssemblyLoad += (sender, args) => { _logger.LogInformation($"UCL : Loaded assembly {args.LoadedAssembly.FullName} into default ALC."); if (!_customerLoggerSetUpComplete && string.Equals(LambdaCoreAssemblyName, args.LoadedAssembly.GetName().Name, StringComparison.Ordinal)) { _logger.LogDebug( $"UCL : Load context loading '{LambdaCoreAssemblyName}', attempting to set {Types.LambdaLoggerTypeName}.{LambdaLoggingActionFieldName} to logging action."); SetCustomerLoggerLogAction(args.LoadedAssembly, customerLoggingAction, _logger); _customerLoggerSetUpComplete = true; } }; _logger.LogDebug($"UCL : Attempting to load assembly '{_handler.AssemblyName}'"); customerAssembly = AssemblyLoadContext.Default.LoadFromAssemblyName(_handler.AssemblyName); } catch (FileNotFoundException fex) { _logger.LogError(fex, "An error occured on UCL Init"); throw LambdaExceptions.ValidationException(Errors.UserCodeLoader.CouldNotFindHandlerAssembly, fex.FileName); } catch (LambdaValidationException validationException) { _logger.LogError(validationException, "An error occured on UCL Init"); throw; } catch (Exception exception) { _logger.LogError(exception, "An error occured on UCL Init"); throw LambdaExceptions.ValidationException(Errors.UserCodeLoader.UnableToLoadAssembly, _handler.AssemblyName); } _logger.LogDebug($"UCL : Attempting to load type '{_handler.TypeName}'"); var customerType = customerAssembly.GetType(_handler.TypeName); if (customerType == null) { throw LambdaExceptions.ValidationException(Errors.UserCodeLoader.UnableToLoadType, _handler.TypeName, _handler.AssemblyName); } _logger.LogDebug($"UCL : Attempting to find method '{_handler.MethodName}' in type '{_handler.TypeName}'"); CustomerMethodInfo = FindCustomerMethod(customerType); _logger.LogDebug($"UCL : Located method '{CustomerMethodInfo}'"); _logger.LogDebug($"UCL : Validating method '{CustomerMethodInfo}'"); UserCodeValidator.ValidateCustomerMethod(CustomerMethodInfo); var customerObject = GetCustomerObject(customerType); var customerSerializerInstance = GetSerializerObject(customerAssembly); _logger.LogDebug($"UCL : Constructing invoke delegate"); var isPreJit = UserCodeInit.IsCallPreJit(); var builder = new InvokeDelegateBuilder(_logger, _handler, CustomerMethodInfo); _invokeDelegate = builder.ConstructInvokeDelegate(customerObject, customerSerializerInstance, isPreJit); if (isPreJit) { _logger.LogInformation("PreJit: PrepareDelegate"); RuntimeHelpers.PrepareDelegate(_invokeDelegate); } }
private void timer_Elapsed(object sender, ElapsedEventArgs e) { InternalLogger.LogInformation("FileListener: Cleaning old streams"); _writerCache.ClearOldStreams(e.SignalTime - _cleanInterval); }