Esempio n. 1
0
        /// <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());
        }
Esempio n. 3
0
        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));
            }
        }
Esempio n. 4
0
        /// <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
                }
            }
        }
Esempio n. 5
0
        /// <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);
            }
        }
Esempio n. 6
0
 private void timer_Elapsed(object sender, ElapsedEventArgs e)
 {
     InternalLogger.LogInformation("FileListener: Cleaning old streams");
     _writerCache.ClearOldStreams(e.SignalTime - _cleanInterval);
 }