예제 #1
0
        internal static async Task <RpcSharedMemory> ToRpcSharedMemoryAsync(this object value, ILogger logger, string invocationId, ISharedMemoryManager sharedMemoryManager)
        {
            if (value == null)
            {
                return(new RpcSharedMemory());
            }

            if (!sharedMemoryManager.IsSupported(value))
            {
                return(null);
            }

            // Put the content into shared memory and get the name of the shared memory map written to
            SharedMemoryMetadata putResponse = await sharedMemoryManager.PutObjectAsync(value);

            if (putResponse == null)
            {
                logger.LogTrace("Cannot write to shared memory for invocation id: {Id}", invocationId);
                return(null);
            }

            // If written to shared memory successfully, add this shared memory map to the list of maps for this invocation
            sharedMemoryManager.AddSharedMemoryMapForInvocation(invocationId, putResponse.Name);

            RpcDataType?dataType = GetRpcDataType(value);

            if (!dataType.HasValue)
            {
                logger.LogTrace("Cannot get shared memory data type for invocation id: {Id}", invocationId);
                return(null);
            }

            // Generate a response
            RpcSharedMemory sharedMem = new RpcSharedMemory()
            {
                Name   = putResponse.Name,
                Offset = 0,
                Count  = putResponse.Count,
                Type   = dataType.Value
            };

            logger.LogTrace("Put object in shared memory for invocation id: {Id}", invocationId);
            return(sharedMem);
        }
        internal static async Task <RpcSharedMemory> ToRpcSharedMemoryAsync(this object value, DataType dataType, ILogger logger, string invocationId, ISharedMemoryManager sharedMemoryManager)
        {
            if (value == null)
            {
                return(new RpcSharedMemory());
            }

            if (!sharedMemoryManager.IsSupported(value))
            {
                return(null);
            }

            SharedMemoryMetadata sharedMemoryMetadata;
            bool needToFreeAfterInvocation = true;

            // Check if the cache is being used or not.
            // The binding extension will only hand out ICacheAwareReadObject if the FunctionDataCache is available and enabled.
            if (value is ICacheAwareReadObject obj)
            {
                if (obj.IsCacheHit)
                {
                    // Content was already present in shared memory (cache hit)
                    logger.LogTrace("Object already present in shared memory for invocation id: {Id}", invocationId);
                    sharedMemoryMetadata      = obj.CacheObject;
                    needToFreeAfterInvocation = false;
                }
                else
                {
                    // Put the content into shared memory and get the name of the shared memory map written to.
                    // This will make the SharedMemoryManager keep an active reference to the memory map.
                    sharedMemoryMetadata = await sharedMemoryManager.PutObjectAsync(obj.BlobStream);

                    if (sharedMemoryMetadata != null)
                    {
                        FunctionDataCacheKey cacheKey = obj.CacheKey;

                        // Try to add the object into the cache and keep an active ref-count for it so that it does not get
                        // evicted while it is still being used by the invocation.
                        if (obj.TryPutToCache(sharedMemoryMetadata, isIncrementActiveReference: true))
                        {
                            logger.LogTrace("Put object: {CacheKey} in cache with metadata: {SharedMemoryMetadata} for invocation id: {Id}", cacheKey, sharedMemoryMetadata, invocationId);
                            // We don't need to free the object after the invocation; it will be freed as part of the cache's
                            // eviction policy.
                            needToFreeAfterInvocation = false;
                        }
                        else
                        {
                            logger.LogTrace("Cannot put object: {CacheKey} in cache with metadata: {SharedMemoryMetadata} for invocation id: {Id}", cacheKey, sharedMemoryMetadata, invocationId);
                            // Since we could not add this object to the cache (and therefore the cache will not be able to evict
                            // it as part of its eviction policy) we will need to free it after the invocation is done.
                            needToFreeAfterInvocation = true;
                        }
                    }
                }
            }
            else
            {
                // Put the content into shared memory and get the name of the shared memory map written to
                sharedMemoryMetadata = await sharedMemoryManager.PutObjectAsync(value);

                needToFreeAfterInvocation = true;
            }

            // Check if the object was either already in shared memory or written to shared memory
            if (sharedMemoryMetadata == null)
            {
                logger.LogTrace("Cannot write to shared memory for invocation id: {Id}", invocationId);
                return(null);
            }

            RpcDataType?rpcDataType = GetRpcDataType(dataType);

            if (!rpcDataType.HasValue)
            {
                logger.LogTrace("Cannot get shared memory data type for invocation id: {Id}", invocationId);
                return(null);
            }

            // When using the cache, we don't need to free the memory map after using it;
            // it will be freed as per the eviction policy of the cache.
            // However, if either the cache was not enabled or the object could not be added to the cache,
            // we will need to free it after the invocation.
            if (needToFreeAfterInvocation)
            {
                // If written to shared memory successfully, add this shared memory map to the list of maps for this invocation
                // so that once the invocation is over, the memory map's resources can be freed.
                sharedMemoryManager.AddSharedMemoryMapForInvocation(invocationId, sharedMemoryMetadata.MemoryMapName);
            }

            // Generate a response
            RpcSharedMemory sharedMem = new RpcSharedMemory()
            {
                Name   = sharedMemoryMetadata.MemoryMapName,
                Offset = 0,
                Count  = sharedMemoryMetadata.Count,
                Type   = rpcDataType.Value
            };

            logger.LogTrace("Put object in shared memory for invocation id: {Id}", invocationId);
            return(sharedMem);
        }