Esempio n. 1
0
            public IEnumerable <IStorageBlob> ListBlobs(MemoryBlobStore store, IStorageBlobContainer parent,
                                                        BlobListingDetails blobListingDetails)
            {
                if (blobListingDetails != BlobListingDetails.None && blobListingDetails != BlobListingDetails.Metadata)
                {
                    throw new NotImplementedException();
                }
                List <IStorageBlob> results = new List <IStorageBlob>();

                foreach (KeyValuePair <string, Blob> item in _items)
                {
                    string       blobName = item.Key;
                    IStorageBlob blob     = new FakeStorageBlockBlob(store, blobName, parent);

                    if ((blobListingDetails | BlobListingDetails.Metadata) == BlobListingDetails.Metadata)
                    {
                        Blob storeBlob = item.Value;
                        IReadOnlyDictionary <string, string> storeMetadata = storeBlob.Metadata;

                        foreach (KeyValuePair <string, string> pair in storeMetadata)
                        {
                            blob.Metadata.Add(pair.Key, pair.Value);
                        }
                    }

                    results.Add(blob);
                }

                return(results);
            }
        public Task <IStorageBlob> ConvertAsync(string input, CancellationToken cancellationToken)
        {
            BlobPath path = BlobPath.ParseAndValidate(input);
            IStorageBlobContainer container = _client.GetContainerReference(path.ContainerName);

            return(container.GetBlobReferenceFromServerAsync(path.BlobName, cancellationToken));
        }
Esempio n. 3
0
        public void BlobTrigger_IfBindingAlwaysFails_MovesToPoisonQueue()
        {
            // Arrange
            IStorageAccount       account      = CreateFakeStorageAccount();
            IStorageBlobContainer container    = CreateContainer(account, ContainerName);
            IStorageBlockBlob     blob         = container.GetBlockBlobReference(BlobName);
            CloudBlockBlob        expectedBlob = blob.SdkObject;

            blob.UploadText("ignore");

            // Act
            string result = RunTrigger <string>(account, typeof(PoisonBlobProgram),
                                                (s) => PoisonBlobProgram.TaskSource = s,
                                                new string[] { typeof(PoisonBlobProgram).FullName + ".PutInPoisonQueue" });

            // Assert
            BlobTriggerMessage message = JsonConvert.DeserializeObject <BlobTriggerMessage>(result);

            Assert.NotNull(message);
            Assert.Equal(typeof(PoisonBlobProgram).FullName + ".PutInPoisonQueue", message.FunctionId);
            Assert.Equal(StorageBlobType.BlockBlob, message.BlobType);
            Assert.Equal(ContainerName, message.ContainerName);
            Assert.Equal(BlobName, message.BlobName);
            Assert.NotEmpty(message.ETag);
        }
        public Task RegisterAsync(IStorageBlobContainer container, ITriggerExecutor<IStorageBlob> triggerExecutor,
            CancellationToken cancellationToken)
        {
            // Register and Execute are not concurrency-safe.
            // Avoiding calling Register while Execute is running is the caller's responsibility.
            ICollection<ITriggerExecutor<IStorageBlob>> containerRegistrations;

            if (_registrations.ContainsKey(container))
            {
                containerRegistrations = _registrations[container];
            }
            else
            {
                containerRegistrations = new List<ITriggerExecutor<IStorageBlob>>();
                _registrations.Add(container, containerRegistrations);
            }

            containerRegistrations.Add(triggerExecutor);

            if (!_lastModifiedTimestamps.ContainsKey(container))
            {
                _lastModifiedTimestamps.Add(container, DateTime.MinValue);
            }

            return Task.FromResult(0);
        }
        private async Task NotifyRegistrationsAsync(IStorageBlob blob, ICollection <IStorageBlob> failedNotifications,
                                                    CancellationToken cancellationToken)
        {
            IStorageBlobContainer container = blob.Container;
            ContainerScanInfo     containerScanInfo;

            // Blob written notifications are host-wide, so filter out things that aren't in the container list.
            if (!_scanInfo.TryGetValue(container, out containerScanInfo))
            {
                return;
            }

            foreach (ITriggerExecutor <IStorageBlob> registration in containerScanInfo.Registrations)
            {
                cancellationToken.ThrowIfCancellationRequested();

                FunctionResult result = await registration.ExecuteAsync(blob, cancellationToken);

                if (!result.Succeeded)
                {
                    // If notification failed, try again on the next iteration.
                    failedNotifications.Add(blob);
                }
            }
        }
        /// <summary>
        /// This method is called each polling interval for all containers. The method divides the
        /// budget of allocated number of blobs to query, for each container we query a page of
        /// that size and we keep the continuation token for the next time. AS a curser, we use
        /// the time stamp when the current cycle on the container started. blobs newer than that
        /// time will be considered new and registrations will be notified
        /// </summary>
        /// <param name="container"></param>
        /// <param name="containerScanInfo"> Information that includes the last cycle start
        /// the continuation token and the current cycle start for a container</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task <IEnumerable <IStorageBlob> > PollNewBlobsAsync(
            IStorageBlobContainer container, ContainerScanInfo containerScanInfo, CancellationToken cancellationToken)
        {
            IEnumerable <IStorageListBlobItem> currentBlobs;
            IStorageBlobResultSegment          blobSegment;
            int blobPollLimitPerContainer           = _scanBlobLimitPerPoll / _scanInfo.Count;
            BlobContinuationToken continuationToken = containerScanInfo.ContinuationToken;

            // if starting the cycle, keep the current time stamp to be used as curser
            if (continuationToken == null)
            {
                containerScanInfo.CurrentSweepCycleStartTime = DateTime.UtcNow;
            }
            try
            {
                blobSegment = await container.ListBlobsSegmentedAsync(prefix : null, useFlatBlobListing : true,
                                                                      blobListingDetails : BlobListingDetails.None, maxResults : blobPollLimitPerContainer, currentToken : continuationToken,
                                                                      options : null, operationContext : null, cancellationToken : cancellationToken);

                currentBlobs = blobSegment.Results;
            }
            catch (StorageException exception)
            {
                if (exception.IsNotFound())
                {
                    return(Enumerable.Empty <IStorageBlob>());
                }
                else
                {
                    throw;
                }
            }

            List <IStorageBlob> newBlobs = new List <IStorageBlob>();

            // Type cast to IStorageBlob is safe due to useFlatBlobListing: true above.
            foreach (IStorageBlob currentBlob in currentBlobs)
            {
                cancellationToken.ThrowIfCancellationRequested();

                IStorageBlobProperties properties = currentBlob.Properties;
                DateTime lastModifiedTimestamp    = properties.LastModified.Value.UtcDateTime;

                if (lastModifiedTimestamp > containerScanInfo.LastSweepCycleStartTime)
                {
                    newBlobs.Add(currentBlob);
                }
            }

            // record continuation token for next chunk retrieval
            containerScanInfo.ContinuationToken = blobSegment.ContinuationToken;

            // if ending a cycle then copy currentSweepCycleStartTime to lastSweepCycleStartTime
            if (blobSegment.ContinuationToken == null)
            {
                containerScanInfo.LastSweepCycleStartTime = containerScanInfo.CurrentSweepCycleStartTime;
            }

            return(newBlobs);
        }
        public void TestBlobListenerWithContainerBiggerThanThreshold()
        {
            int                       testScanBlobLimitPerPoll = 1;
            string                    containerName            = Path.GetRandomFileName();
            IStorageAccount           account   = CreateFakeStorageAccount();
            IStorageBlobContainer     container = account.CreateBlobClient().GetContainerReference(containerName);
            IBlobListenerStrategy     product   = new ScanBlobScanLogHybridPollingStrategy(new TestBlobScanInfoManager());
            LambdaBlobTriggerExecutor executor  = new LambdaBlobTriggerExecutor();

            typeof(ScanBlobScanLogHybridPollingStrategy)
            .GetField("_scanBlobLimitPerPoll", BindingFlags.Instance | BindingFlags.NonPublic)
            .SetValue(product, testScanBlobLimitPerPoll);

            product.Register(container, executor);
            product.Start();

            // populate with 5 blobs
            List <string> expectedNames = new List <string>();

            for (int i = 0; i < 5; i++)
            {
                expectedNames.Add(CreateAblobAndUploadToContainer(container));
            }

            RunExecuteWithMultiPollingInterval(expectedNames, product, executor, testScanBlobLimitPerPoll);

            // Now run again; shouldn't show up.
            RunExecuterWithExpectedBlobs(new List <string>(), product, executor);
        }
        public async Task <IEnumerable <IStorageBlob> > GetRecentBlobWritesAsync(CancellationToken cancellationToken,
                                                                                 int hoursWindow = DefaultScanHoursWindow)
        {
            List <IStorageBlob> blobs = new List <IStorageBlob>();

            var time = DateTime.UtcNow; // will scan back 2 hours, which is enough to deal with clock sqew

            foreach (var blob in await ListRecentLogFilesAsync(_blobClient, time, cancellationToken, hoursWindow))
            {
                bool isAdded = _scannedBlobNames.Add(blob.Name);
                if (!isAdded)
                {
                    continue;
                }

                // Need to clear out cache.
                if (_scannedBlobNames.Count > 100 * 1000)
                {
                    _scannedBlobNames.Clear();
                }

                IEnumerable <StorageAnalyticsLogEntry> entries = await _parser.ParseLogAsync(blob, cancellationToken);

                IEnumerable <BlobPath> filteredBlobs = GetPathsForValidBlobWrites(entries);

                foreach (BlobPath path in filteredBlobs)
                {
                    IStorageBlobContainer container = _blobClient.GetContainerReference(path.ContainerName);
                    blobs.Add(container.GetBlockBlobReference(path.BlobName));
                }
            }

            return(blobs);
        }
        public async Task RegisterAsync(IStorageBlobContainer container, ITriggerExecutor<IStorageBlob> triggerExecutor,
            CancellationToken cancellationToken)
        {
            ThrowIfDisposed();

            // Initial background scans for all containers happen on first Execute call.
            // Prevent accidental late registrations.
            // (Also prevents incorrect concurrent execution of Register with Execute.)
            if (_initialScanThread.ThreadState != ThreadState.Unstarted)
            {
                throw new InvalidOperationException("All registrations must be created before execution begins.");
            }

            ICollection<ITriggerExecutor<IStorageBlob>> containerRegistrations;

            if (_registrations.ContainsKey(container))
            {
                containerRegistrations = _registrations[container];
            }
            else
            {
                containerRegistrations = new List<ITriggerExecutor<IStorageBlob>>();
                _registrations.Add(container, containerRegistrations);
            }

            containerRegistrations.Add(triggerExecutor);

            IStorageBlobClient client = container.ServiceClient;

            if (!_logListeners.ContainsKey(client))
            {
                BlobLogListener logListener = await BlobLogListener.CreateAsync(client, cancellationToken);
                _logListeners.Add(client, logListener);
            }
        }
Esempio n. 10
0
 public BlobListenerFactory(IHostIdProvider hostIdProvider,
                            IQueueConfiguration queueConfiguration,
                            JobHostBlobsConfiguration blobsConfiguration,
                            IWebJobsExceptionHandler exceptionHandler,
                            IContextSetter <IBlobWrittenWatcher> blobWrittenWatcherSetter,
                            IContextSetter <IMessageEnqueuedWatcher> messageEnqueuedWatcherSetter,
                            ISharedContextProvider sharedContextProvider,
                            ILoggerFactory loggerFactory,
                            string functionId,
                            IStorageAccount hostAccount,
                            IStorageAccount dataAccount,
                            IStorageBlobContainer container,
                            IBlobPathSource input,
                            ITriggeredFunctionExecutor executor,
                            SingletonManager singletonManager)
 {
     _hostIdProvider               = hostIdProvider ?? throw new ArgumentNullException(nameof(hostIdProvider));
     _queueConfiguration           = queueConfiguration ?? throw new ArgumentNullException(nameof(queueConfiguration));
     _blobsConfiguration           = blobsConfiguration ?? throw new ArgumentNullException(nameof(blobsConfiguration));
     _exceptionHandler             = exceptionHandler ?? throw new ArgumentNullException(nameof(exceptionHandler));
     _blobWrittenWatcherSetter     = blobWrittenWatcherSetter ?? throw new ArgumentNullException(nameof(blobWrittenWatcherSetter));
     _messageEnqueuedWatcherSetter = messageEnqueuedWatcherSetter ?? throw new ArgumentNullException(nameof(messageEnqueuedWatcherSetter));
     _sharedContextProvider        = sharedContextProvider ?? throw new ArgumentNullException(nameof(sharedContextProvider));
     _loggerFactory    = loggerFactory;
     _functionId       = functionId;
     _hostAccount      = hostAccount ?? throw new ArgumentNullException(nameof(hostAccount));
     _dataAccount      = dataAccount ?? throw new ArgumentNullException(nameof(dataAccount));
     _container        = container ?? throw new ArgumentNullException(nameof(container));
     _input            = input ?? throw new ArgumentNullException(nameof(input));
     _executor         = executor ?? throw new ArgumentNullException(nameof(executor));
     _singletonManager = singletonManager ?? throw new ArgumentNullException(nameof(singletonManager));
 }
        public async Task RegisterAsync(IStorageBlobContainer container, ITriggerExecutor <IStorageBlob> triggerExecutor, CancellationToken cancellationToken)
        {
            // Register and Execute are not concurrency-safe.
            // Avoiding calling Register while Execute is running is the caller's responsibility.
            ThrowIfDisposed();

            // Register all in logPolling, there is no problem if we get 2 notifications of the new blob
            await _pollLogStrategy.RegisterAsync(container, triggerExecutor, cancellationToken);

            ContainerScanInfo containerScanInfo;

            if (!_scanInfo.TryGetValue(container, out containerScanInfo))
            {
                // First, try to load serialized scanInfo for this container.
                DateTime?latestStoredScan = await _blobScanInfoManager.LoadLatestScanAsync(container.ServiceClient.Credentials.AccountName, container.Name);

                containerScanInfo = new ContainerScanInfo()
                {
                    Registrations = new List <ITriggerExecutor <IStorageBlob> >(),
                    LastSweepCycleLatestModified    = latestStoredScan ?? DateTime.MinValue,
                    CurrentSweepCycleLatestModified = DateTime.MinValue,
                    ContinuationToken = null
                };

                _scanInfo.Add(container, containerScanInfo);
            }

            containerScanInfo.Registrations.Add(triggerExecutor);
        }
Esempio n. 12
0
        public async Task RegisterAsync(IStorageBlobContainer container, ITriggerExecutor <IStorageBlob> triggerExecutor, CancellationToken cancellationToken)
        {
            // Register and Execute are not concurrency-safe.
            // Avoiding calling Register while Execute is running is the caller's responsibility.
            ThrowIfDisposed();

            // Register all in logPolling, there is no problem if we get 2 notifications of the new blob
            await _pollLogStrategy.RegisterAsync(container, triggerExecutor, cancellationToken);

            ContainerScanInfo containerScanInfo;

            if (!_scanInfo.TryGetValue(container, out containerScanInfo))
            {
                containerScanInfo = new ContainerScanInfo()
                {
                    Registrations = new List <ITriggerExecutor <IStorageBlob> >(),
                    LastSweepCycleLatestModified    = DateTime.MinValue,
                    CurrentSweepCycleLatestModified = DateTime.MinValue,
                    ContinuationToken = null
                };
                _scanInfo.Add(container, containerScanInfo);
            }

            containerScanInfo.Registrations.Add(triggerExecutor);
        }
        private async Task PollAndNotify(IStorageBlobContainer container, ContainerScanInfo containerScanInfo, CancellationToken cancellationToken, List <IStorageBlob> failedNotifications)
        {
            cancellationToken.ThrowIfCancellationRequested();
            DateTime lastScan = containerScanInfo.LastSweepCycleLatestModified;
            IEnumerable <IStorageBlob> newBlobs = await PollNewBlobsAsync(container, containerScanInfo, cancellationToken);

            foreach (IStorageBlob newBlob in newBlobs)
            {
                cancellationToken.ThrowIfCancellationRequested();
                await NotifyRegistrationsAsync(newBlob, failedNotifications, cancellationToken);
            }

            // if the 'LatestModified' has changed, update it in the manager
            if (containerScanInfo.LastSweepCycleLatestModified > lastScan)
            {
                DateTime latestScan = containerScanInfo.LastSweepCycleLatestModified;

                // It's possible that we had some blobs that we failed to move to the queue. We want to make sure
                // we continue to find these if the host needs to restart.
                if (failedNotifications.Any())
                {
                    latestScan = failedNotifications.Min(n => n.Properties.LastModified.Value.UtcDateTime);
                }

                // Store our timestamp slightly earlier than the last timestamp. This is a failsafe for any blobs that created
                // milliseconds after our last scan (blob timestamps round to the second). This way we make sure to pick those
                // up on a host restart.
                await _blobScanInfoManager.UpdateLatestScanAsync(container.ServiceClient.Credentials.AccountName,
                                                                 container.Name, latestScan.AddMilliseconds(-1));
            }
        }
        public Task RegisterAsync(IStorageBlobContainer container, ITriggerExecutor <IStorageBlob> triggerExecutor,
                                  CancellationToken cancellationToken)
        {
            // Register and Execute are not concurrency-safe.
            // Avoiding calling Register while Execute is running is the caller's responsibility.
            ICollection <ITriggerExecutor <IStorageBlob> > containerRegistrations;

            if (_registrations.ContainsKey(container))
            {
                containerRegistrations = _registrations[container];
            }
            else
            {
                containerRegistrations = new List <ITriggerExecutor <IStorageBlob> >();
                _registrations.Add(container, containerRegistrations);
            }

            containerRegistrations.Add(triggerExecutor);

            if (!_lastModifiedTimestamps.ContainsKey(container))
            {
                _lastModifiedTimestamps.Add(container, DateTime.MinValue);
            }

            return(Task.FromResult(0));
        }
        public async Task RegisterAsync_InitializesWithScanInfoManager()
        {
            string                    containerName   = Guid.NewGuid().ToString();
            IStorageAccount           account         = CreateFakeStorageAccount();
            IStorageBlobContainer     container       = account.CreateBlobClient().GetContainerReference(containerName);
            TestBlobScanInfoManager   scanInfoManager = new TestBlobScanInfoManager();
            IBlobListenerStrategy     product         = new ScanBlobScanLogHybridPollingStrategy(scanInfoManager);
            LambdaBlobTriggerExecutor executor        = new LambdaBlobTriggerExecutor();

            // Create a few blobs.
            for (int i = 0; i < 5; i++)
            {
                CreateAblobAndUploadToContainer(container);
            }

            await scanInfoManager.UpdateLatestScanAsync(account.Credentials.AccountName, containerName, DateTime.UtcNow);

            await product.RegisterAsync(container, executor, CancellationToken.None);

            // delay slightly so we guarantee a later timestamp
            await Task.Delay(10);

            var expectedNames = new List <string>();

            expectedNames.Add(CreateAblobAndUploadToContainer(container));

            RunExecuterWithExpectedBlobs(expectedNames, product, executor);
        }
Esempio n. 16
0
        public async Task <IEnumerable <IStorageBlob> > GetRecentBlobWritesAsync(CancellationToken cancellationToken,
                                                                                 int hoursWindow = DefaultScanHoursWindow)
        {
            List <IStorageBlob> blobs = new List <IStorageBlob>();

            var time = DateTime.UtcNow; // will scan back 2 hours, which is enough to deal with clock sqew

            foreach (var blob in await ListRecentLogFilesAsync(_blobClient, time, cancellationToken, hoursWindow))
            {
                bool isAdded = _scannedBlobNames.Add(blob.Name);
                if (!isAdded)
                {
                    continue;
                }

                // Need to clear out cache.
                if (_scannedBlobNames.Count > 100 * 1000)
                {
                    _scannedBlobNames.Clear();
                }

                var parsedBlobPaths = from entry in await _parser.ParseLogAsync(blob, cancellationToken)
                                          where entry.IsBlobWrite
                                      select entry.ToBlobPath();

                foreach (BlobPath path in parsedBlobPaths.Where(p => p != null))
                {
                    IStorageBlobContainer container = _blobClient.GetContainerReference(path.ContainerName);
                    blobs.Add(container.GetBlockBlobReference(path.BlobName));
                }
            }

            return(blobs);
        }
Esempio n. 17
0
        private static IStorageBlobContainer CreateContainer(IStorageAccount account, string containerName)
        {
            IStorageBlobClient    client    = account.CreateBlobClient();
            IStorageBlobContainer container = client.GetContainerReference(containerName);

            container.CreateIfNotExists();
            return(container);
        }
Esempio n. 18
0
        private static IStorageBlob CreateBlobReference(string containerName, string blobName)
        {
            IStorageAccount       account   = CreateAccount();
            IStorageBlobClient    client    = account.CreateBlobClient();
            IStorageBlobContainer container = client.GetContainerReference(containerName);

            return(container.GetBlockBlobReference(blobName));
        }
Esempio n. 19
0
        public async Task <IValueProvider> BindAsync(BindingContext context)
        {
            BlobPath boundPath = _path.Bind(context.BindingData);
            IStorageBlobContainer container        = _client.GetContainerReference(boundPath.ContainerName);
            ValueBindingContext   containerContext = new BlobValueBindingContext(boundPath, context.ValueContext);

            return(await BindBlobContainerAsync(container, containerContext));
        }
Esempio n. 20
0
        public IStorageBlob GetBlobReferenceFromServer(IStorageBlobContainer parent, string containerName, string blobName)
        {
            if (!_items.ContainsKey(containerName))
            {
                throw StorageExceptionFactory.Create(404);
            }

            return(_items[containerName].GetBlobReferenceFromServer(this, parent, blobName));
        }
        public IStorageBlob GetBlobReferenceFromServer(IStorageBlobContainer parent, string containerName, string blobName)
        {
            if (!_items.ContainsKey(containerName))
            {
                throw StorageExceptionFactory.Create(404);
            }

            return _items[containerName].GetBlobReferenceFromServer(this, parent, blobName);
        }
Esempio n. 22
0
 public FakeStoragePageBlob(MemoryBlobStore store, string blobName, IStorageBlobContainer parent)
 {
     _store         = store;
     _blobName      = blobName;
     _parent        = parent;
     _containerName = parent.Name;
     _metadata      = new Dictionary <string, string>();
     _sdkObject     = new CloudPageBlob(new Uri("http://localhost/" + _containerName + "/" + blobName));
 }
        private string CreateAblobAndUploadToContainer(IStorageBlobContainer container, string blobContent = "test")
        {
            string            blobName = Path.GetRandomFileName().Replace(".", "");
            IStorageBlockBlob blob     = container.GetBlockBlobReference(blobName);

            container.CreateIfNotExists();
            blob.UploadText(blobContent);
            return(blobName);
        }
 public FakeStoragePageBlob(MemoryBlobStore store, string blobName, IStorageBlobContainer parent)
 {
     _store = store;
     _blobName = blobName;
     _parent = parent;
     _containerName = parent.Name;
     _metadata = new Dictionary<string, string>();
     _sdkObject = new CloudPageBlob(new Uri("http://localhost/" + _containerName + "/" + blobName));
 }
        public static bool Exists(this IStorageBlobContainer container)
        {
            if (container == null)
            {
                throw new ArgumentNullException("container");
            }

            return(container.ExistsAsync(CancellationToken.None).GetAwaiter().GetResult());
        }
        public static void CreateIfNotExists(this IStorageBlobContainer container)
        {
            if (container == null)
            {
                throw new ArgumentNullException("container");
            }

            container.CreateIfNotExistsAsync(CancellationToken.None).GetAwaiter().GetResult();
        }
Esempio n. 27
0
        public static void Register(this IBlobListenerStrategy strategy, IStorageBlobContainer container,
                                    ITriggerExecutor <IStorageBlob> triggerExecutor)
        {
            if (strategy == null)
            {
                throw new ArgumentNullException("strategy");
            }

            strategy.RegisterAsync(container, triggerExecutor, CancellationToken.None).GetAwaiter().GetResult();
        }
        public static void Start(this IBlobListenerStrategy strategy, IStorageBlobContainer container,
            ITriggerExecutor<IStorageBlob> triggerExecutor)
        {
            if (strategy == null)
            {
                throw new ArgumentNullException("strategy");
            }

            strategy.Start();
        }
        public static void Register(this IBlobListenerStrategy strategy, IStorageBlobContainer container,
            ITriggerExecutor<IStorageBlob> triggerExecutor)
        {
            if (strategy == null)
            {
                throw new ArgumentNullException("strategy");
            }

            strategy.RegisterAsync(container, triggerExecutor, CancellationToken.None).GetAwaiter().GetResult();
        }
Esempio n. 30
0
        public static void Start(this IBlobListenerStrategy strategy, IStorageBlobContainer container,
                                 ITriggerExecutor <IStorageBlob> triggerExecutor)
        {
            if (strategy == null)
            {
                throw new ArgumentNullException("strategy");
            }

            strategy.Start();
        }
        public Task RegisterAsync(IStorageBlobContainer container, ITriggerExecutor <IStorageBlob> triggerExecutor,
                                  CancellationToken cancellationToken)
        {
            if (_started)
            {
                throw new InvalidOperationException(
                          "Registrations may not be added while the shared listener is running.");
            }

            return(_strategy.RegisterAsync(container, triggerExecutor, cancellationToken));
        }
        public Task RegisterAsync(IStorageBlobContainer container, ITriggerExecutor<IStorageBlob> triggerExecutor,
            CancellationToken cancellationToken)
        {
            if (_started)
            {
                throw new InvalidOperationException(
                    "Registrations may not be added while the shared listener is running.");
            }

            return _strategy.RegisterAsync(container, triggerExecutor, cancellationToken);
        }
Esempio n. 33
0
        private async Task PollAndNotify(IStorageBlobContainer container, ContainerScanInfo containerInfo, CancellationToken cancellationToken, List <IStorageBlob> failedNotifications)
        {
            cancellationToken.ThrowIfCancellationRequested();
            IEnumerable <IStorageBlob> newBlobs = await PollNewBlobsAsync(container, containerInfo, cancellationToken);

            foreach (IStorageBlob newBlob in newBlobs)
            {
                cancellationToken.ThrowIfCancellationRequested();
                await NotifyRegistrationsAsync(newBlob, failedNotifications, cancellationToken);
            }
        }
        private async Task <IStorageBlobContainer> GetContainerAsync(
            BlobAttribute blobAttribute,
            CancellationToken cancellationToken)
        {
            IStorageBlobClient client = await GetClientAsync(blobAttribute, cancellationToken);

            BlobPath boundPath = BlobPath.ParseAndValidate(blobAttribute.BlobPath, isContainerBinding: true);

            IStorageBlobContainer container = client.GetContainerReference(boundPath.ContainerName);

            return(container);
        }
Esempio n. 35
0
        public async Task <IValueProvider> BindAsync(object value, ValueBindingContext context)
        {
            BlobPath path = null;
            IStorageBlobContainer container = null;

            if (TryConvert(value, _client, out container, out path))
            {
                return(await BindBlobContainerAsync(container, new BlobValueBindingContext(path, context)));
            }

            throw new InvalidOperationException("Unable to convert value to CloudBlobContainer.");
        }
Esempio n. 36
0
        public void TryConvert_ConvertString_Failure(string value)
        {
            Mock <IStorageBlobClient> mockStorageClient = new Mock <IStorageBlobClient>(MockBehavior.Strict);

            IStorageBlobContainer container = null;
            BlobPath path = null;

            Assert.Throws <FormatException>(() =>
            {
                BlobContainerBinding.TryConvert(value, mockStorageClient.Object, out container, out path);
            });
        }
        public async Task ExecuteAsync_UpdatesScanInfoManager()
        {
            int                     testScanBlobLimitPerPoll = 6;
            string                  firstContainerName       = Guid.NewGuid().ToString();
            string                  secondContainerName      = Guid.NewGuid().ToString();
            IStorageAccount         account             = CreateFakeStorageAccount();
            IStorageBlobContainer   firstContainer      = account.CreateBlobClient().GetContainerReference(firstContainerName);
            IStorageBlobContainer   secondContainer     = account.CreateBlobClient().GetContainerReference(secondContainerName);
            TestBlobScanInfoManager testScanInfoManager = new TestBlobScanInfoManager();
            string                  accountName         = account.Credentials.AccountName;

            testScanInfoManager.SetScanInfo(accountName, firstContainerName, DateTime.MinValue);
            testScanInfoManager.SetScanInfo(accountName, secondContainerName, DateTime.MinValue);
            IBlobListenerStrategy     product  = new ScanBlobScanLogHybridPollingStrategy(testScanInfoManager);
            LambdaBlobTriggerExecutor executor = new LambdaBlobTriggerExecutor();

            typeof(ScanBlobScanLogHybridPollingStrategy)
            .GetField("_scanBlobLimitPerPoll", BindingFlags.Instance | BindingFlags.NonPublic)
            .SetValue(product, testScanBlobLimitPerPoll);

            await product.RegisterAsync(firstContainer, executor, CancellationToken.None);

            await product.RegisterAsync(secondContainer, executor, CancellationToken.None);

            var firstExpectedNames = new List <string>();

            for (int i = 0; i < 3; i++)
            {
                firstExpectedNames.Add(CreateAblobAndUploadToContainer(firstContainer));
            }
            RunExecuteWithMultiPollingInterval(firstExpectedNames, product, executor, testScanBlobLimitPerPoll / 2);

            // only expect the first container to have updated its scanInfo
            Assert.Equal(1, testScanInfoManager.UpdateCounts[accountName][firstContainerName]);
            int count;

            testScanInfoManager.UpdateCounts[accountName].TryGetValue(secondContainerName, out count);
            Assert.Equal(0, count);

            await Task.Delay(10);

            var secondExpectedNames = new List <string>();

            for (int i = 0; i < 7; i++)
            {
                secondExpectedNames.Add(CreateAblobAndUploadToContainer(secondContainer));
            }
            RunExecuteWithMultiPollingInterval(secondExpectedNames, product, executor, testScanBlobLimitPerPoll / 2);

            // this time, only expect the second container to have updated its scanInfo
            Assert.Equal(1, testScanInfoManager.UpdateCounts[accountName][firstContainerName]);
            Assert.Equal(1, testScanInfoManager.UpdateCounts[accountName][secondContainerName]);
        }
        public FunctionStatusLogger(IHostIdProvider hostIdProvider, IStorageBlobClient blobClient)
        {
            if (hostIdProvider == null)
            {
                throw new ArgumentNullException("hostIdProvider");
            }
            if (blobClient == null)
            {
                throw new ArgumentNullException("blobClient");
            }

            _hostIdProvider = hostIdProvider;
            _blobClient = blobClient;
            _hostContainer = _blobClient.GetContainerReference(HostContainerNames.Hosts);
        }
        internal static bool TryConvert(object value, IStorageBlobClient client, out IStorageBlobContainer container, out BlobPath path)
        {
            container = null;
            path = null;

            string fullPath = value as string;
            if (fullPath != null)
            {
                path = BlobPath.ParseAndValidate(fullPath, isContainerBinding: true);
                container = client.GetContainerReference(path.ContainerName);
                return true;
            }

            return false;
        }
 public FakeStorageBlockBlob(MemoryBlobStore store, string blobName, IStorageBlobContainer parent, FakeStorageBlobProperties properties = null)
 {
     _store = store;
     _blobName = blobName;
     _parent = parent;
     _containerName = parent.Name;
     _metadata = new Dictionary<string, string>();
     if (properties != null )
     {
         _properties = properties;
     }
     else
     {
         _properties = new FakeStorageBlobProperties();
     }
     _sdkObject = new CloudBlockBlob(new Uri("http://localhost/" + _containerName + "/" + blobName));
 }
        private static async Task<IStorageBlob> GetExistingOrNewBlockBlobReferenceAsync(IStorageBlobContainer container,
            string blobName, CancellationToken cancellationToken)
        {
            try
            {
                return await container.GetBlobReferenceFromServerAsync(blobName, cancellationToken);
            }
            catch (StorageException exception)
            {
                RequestResult result = exception.RequestInformation;

                if (result == null || result.HttpStatusCode != 404)
                {
                    throw;
                }
                else
                {
                    return container.GetBlockBlobReference(blobName);
                }
            }
        }
Esempio n. 42
0
        public async Task RegisterAsync(IStorageBlobContainer container, ITriggerExecutor<IStorageBlob> triggerExecutor, CancellationToken cancellationToken)
        {
            // Register and Execute are not concurrency-safe.
            // Avoiding calling Register while Execute is running is the caller's responsibility.
            ThrowIfDisposed();

            // Register all in logPolling, there is no problem if we get 2 notifications of the new blob
            await _pollLogStrategy.RegisterAsync(container, triggerExecutor, cancellationToken);

            ContainerScanInfo containerScanInfo;
            if (!_scanInfo.TryGetValue(container, out containerScanInfo))
            {
                containerScanInfo = new ContainerScanInfo()
                {
                    Registrations = new List<ITriggerExecutor<IStorageBlob>>(),
                    LastSweepCycleStartTime = DateTime.MinValue,
                    CurrentSweepCycleStartTime = DateTime.MinValue,
                    ContinuationToken = null
                };
                _scanInfo.Add(container, containerScanInfo);
            }

            containerScanInfo.Registrations.Add(triggerExecutor);
        }
Esempio n. 43
0
        /// <summary>
        /// This method is called each polling interval for all containers. The method divides the 
        /// budget of allocated number of blobs to query, for each container we query a page of 
        /// that size and we keep the continuation token for the next time. AS a curser, we use
        /// the time stamp when the current cycle on the container started. blobs newer than that
        /// time will be considered new and registrations will be notified
        /// </summary>
        /// <param name="container"></param>
        /// <param name="containerScanInfo"> Information that includes the last cycle start
        /// the continuation token and the current cycle start for a container</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<IEnumerable<IStorageBlob>> PollNewBlobsAsync(
            IStorageBlobContainer container, ContainerScanInfo containerScanInfo, CancellationToken cancellationToken)
        {
            IEnumerable<IStorageListBlobItem> currentBlobs;
            IStorageBlobResultSegment blobSegment;
            int blobPollLimitPerContainer = _scanBlobLimitPerPoll / _scanInfo.Count;
            BlobContinuationToken continuationToken = containerScanInfo.ContinuationToken;

            // if starting the cycle, keep the current time stamp to be used as curser
            if (continuationToken == null)
            {
                containerScanInfo.CurrentSweepCycleStartTime = DateTime.UtcNow;
            }
            try
            {
                blobSegment = await container.ListBlobsSegmentedAsync(prefix: null, useFlatBlobListing: true, 
                    blobListingDetails: BlobListingDetails.None, maxResults: blobPollLimitPerContainer, currentToken: continuationToken, 
                    options: null, operationContext: null, cancellationToken: cancellationToken);
                currentBlobs = blobSegment.Results;
            }
            catch (StorageException exception)
            {
                if (exception.IsNotFound())
                {
                    return Enumerable.Empty<IStorageBlob>();
                }
                else
                {
                    throw;
                }
            }

            List<IStorageBlob> newBlobs = new List<IStorageBlob>();

            // Type cast to IStorageBlob is safe due to useFlatBlobListing: true above.
            foreach (IStorageBlob currentBlob in currentBlobs)
            {
                cancellationToken.ThrowIfCancellationRequested();

                IStorageBlobProperties properties = currentBlob.Properties;
                DateTime lastModifiedTimestamp = properties.LastModified.Value.UtcDateTime;

                if (lastModifiedTimestamp > containerScanInfo.LastSweepCycleStartTime)
                {
                    newBlobs.Add(currentBlob);
                }
            }

            // record continuation token for next chunk retrieval
            containerScanInfo.ContinuationToken = blobSegment.ContinuationToken;

            // if ending a cycle then copy currentSweepCycleStartTime to lastSweepCycleStartTime
            if (blobSegment.ContinuationToken == null)
            {
                containerScanInfo.LastSweepCycleStartTime = containerScanInfo.CurrentSweepCycleStartTime;
            }

            return newBlobs;
        }
Esempio n. 44
0
        public BlobListenerFactory(IHostIdProvider hostIdProvider,
            IQueueConfiguration queueConfiguration,
            IBackgroundExceptionDispatcher backgroundExceptionDispatcher,
            IContextSetter<IBlobWrittenWatcher> blobWrittenWatcherSetter,
            IContextSetter<IMessageEnqueuedWatcher> messageEnqueuedWatcherSetter,
            ISharedContextProvider sharedContextProvider,
            TraceWriter trace,
            string functionId,
            IStorageAccount hostAccount,
            IStorageAccount dataAccount,
            IStorageBlobContainer container,
            IBlobPathSource input,
            ITriggeredFunctionExecutor executor,
            SingletonManager singletonManager)
        {
            if (hostIdProvider == null)
            {
                throw new ArgumentNullException("hostIdProvider");
            }

            if (queueConfiguration == null)
            {
                throw new ArgumentNullException("queueConfiguration");
            }

            if (backgroundExceptionDispatcher == null)
            {
                throw new ArgumentNullException("backgroundExceptionDispatcher");
            }

            if (blobWrittenWatcherSetter == null)
            {
                throw new ArgumentNullException("blobWrittenWatcherSetter");
            }

            if (messageEnqueuedWatcherSetter == null)
            {
                throw new ArgumentNullException("messageEnqueuedWatcherSetter");
            }

            if (sharedContextProvider == null)
            {
                throw new ArgumentNullException("sharedContextProvider");
            }

            if (trace == null)
            {
                throw new ArgumentNullException("trace");
            }

            if (hostAccount == null)
            {
                throw new ArgumentNullException("hostAccount");
            }

            if (dataAccount == null)
            {
                throw new ArgumentNullException("dataAccount");
            }

            if (container == null)
            {
                throw new ArgumentNullException("container");
            }

            if (input == null)
            {
                throw new ArgumentNullException("input");
            }

            if (executor == null)
            {
                throw new ArgumentNullException("executor");
            }

            if (singletonManager == null)
            {
                throw new ArgumentNullException("singletonManager");
            }

            _hostIdProvider = hostIdProvider;
            _queueConfiguration = queueConfiguration;
            _backgroundExceptionDispatcher = backgroundExceptionDispatcher;
            _blobWrittenWatcherSetter = blobWrittenWatcherSetter;
            _messageEnqueuedWatcherSetter = messageEnqueuedWatcherSetter;
            _sharedContextProvider = sharedContextProvider;
            _trace = trace;
            _functionId = functionId;
            _hostAccount = hostAccount;
            _dataAccount = dataAccount;
            _container = container;
            _input = input;
            _executor = executor;
            _singletonManager = singletonManager;
        }
        internal static IStorageListBlobItem ToStorageListBlobItem(IStorageBlobContainer parent, IListBlobItem sdkItem)
        {
            if (sdkItem == null)
            {
                return null;
            }

            ICloudBlob sdkBlob = sdkItem as ICloudBlob;

            if (sdkBlob != null)
            {
                return ToStorageBlob(parent, sdkBlob);
            }
            else
            {
                return new StorageBlobDirectory(parent, (CloudBlobDirectory)sdkItem);
            }
        }
 /// <summary>Initializes a new instance of the <see cref="StoragePageBlob"/> class.</summary>
 /// <param name="parent">The parent blob container.</param>
 /// <param name="sdk">The SDK blob to wrap.</param>
 public StoragePageBlob(IStorageBlobContainer parent, CloudPageBlob sdk)
 {
     _parent = parent;
     _sdk = sdk;
     _properties = new StorageBlobProperties(sdk);
 }
        private static IStorageBlob ToStorageBlob(IStorageBlobContainer parent, ICloudBlob sdkBlob)
        {
            Debug.Assert(sdkBlob != null);

            CloudBlockBlob blockBlob = sdkBlob as CloudBlockBlob;

            if (blockBlob != null)
            {
                return new StorageBlockBlob(parent, blockBlob);
            }
            else
            {
                CloudPageBlob cloudPageBlob = sdkBlob as CloudPageBlob;
                Debug.Assert(cloudPageBlob != null);
                return new StoragePageBlob(parent, cloudPageBlob);
            }
        }
Esempio n. 48
0
        private async Task PollAndNotify(IStorageBlobContainer container, ContainerScanInfo containerInfo, CancellationToken cancellationToken, List<IStorageBlob> failedNotifications)
        {
            cancellationToken.ThrowIfCancellationRequested();
            IEnumerable<IStorageBlob> newBlobs = await PollNewBlobsAsync(container, containerInfo, cancellationToken);

            foreach (IStorageBlob newBlob in newBlobs)
            {
                cancellationToken.ThrowIfCancellationRequested();
                await NotifyRegistrationsAsync(newBlob, failedNotifications, cancellationToken);
            }
        }
        public BlobListenerFactory(IHostIdProvider hostIdProvider,
            IQueueConfiguration queueConfiguration,
            IBackgroundExceptionDispatcher backgroundExceptionDispatcher,
            IContextSetter<IBlobWrittenWatcher> blobWrittenWatcherSetter,
            IContextSetter<IMessageEnqueuedWatcher> messageEnqueuedWatcherSetter,
            ISharedContextProvider sharedContextProvider,
            TextWriter log,
            string functionId,
            IStorageAccount account,
            IStorageBlobContainer container,
            IBlobPathSource input,
            ITriggeredFunctionExecutor<IStorageBlob> executor)
        {
            if (hostIdProvider == null)
            {
                throw new ArgumentNullException("hostIdProvider");
            }

            if (queueConfiguration == null)
            {
                throw new ArgumentNullException("queueConfiguration");
            }

            if (backgroundExceptionDispatcher == null)
            {
                throw new ArgumentNullException("backgroundExceptionDispatcher");
            }

            if (blobWrittenWatcherSetter == null)
            {
                throw new ArgumentNullException("blobWrittenWatcherSetter");
            }

            if (messageEnqueuedWatcherSetter == null)
            {
                throw new ArgumentNullException("messageEnqueuedWatcherSetter");
            }

            if (sharedContextProvider == null)
            {
                throw new ArgumentNullException("sharedContextProvider");
            }

            if (log == null)
            {
                throw new ArgumentNullException("log");
            }

            if (account == null)
            {
                throw new ArgumentNullException("account");
            }

            if (container == null)
            {
                throw new ArgumentNullException("container");
            }

            if (input == null)
            {
                throw new ArgumentNullException("input");
            }

            if (executor == null)
            {
                throw new ArgumentNullException("executor");
            }

            _hostIdProvider = hostIdProvider;
            _queueConfiguration = queueConfiguration;
            _backgroundExceptionDispatcher = backgroundExceptionDispatcher;
            _blobWrittenWatcherSetter = blobWrittenWatcherSetter;
            _messageEnqueuedWatcherSetter = messageEnqueuedWatcherSetter;
            _sharedContextProvider = sharedContextProvider;
            _log = log;
            _functionId = functionId;
            _account = account;
            _container = container;
            _input = input;
            _executor = executor;
        }
 private Task<IValueProvider> BindBlobContainerAsync(IStorageBlobContainer value, ValueBindingContext context)
 {
     return _argumentBinding.BindAsync(value, context);
 }
 public FakeStorageBlobDirectory(MemoryBlobStore store, string relativeAddress, IStorageBlobContainer parent)
 {
     _store = store;
     _relativeAddress = relativeAddress;
     _parent = parent;
 }
            public IEnumerable<IStorageBlob> ListBlobs(MemoryBlobStore store, IStorageBlobContainer parent,
                BlobListingDetails blobListingDetails)
            {
                if (blobListingDetails != BlobListingDetails.None && blobListingDetails != BlobListingDetails.Metadata)
                {
                    throw new NotImplementedException();
                }
                List<IStorageBlob> results = new List<IStorageBlob>();

                foreach (KeyValuePair<string, Blob> item in _items)
                {
                    string blobName = item.Key;
                    IStorageBlob blob = new FakeStorageBlockBlob(store, blobName, parent);

                    if ((blobListingDetails | BlobListingDetails.Metadata) == BlobListingDetails.Metadata)
                    {
                        Blob storeBlob = item.Value;
                        IReadOnlyDictionary<string, string> storeMetadata = storeBlob.Metadata;

                        foreach (KeyValuePair<string, string> pair in storeMetadata)
                        {
                            blob.Metadata.Add(pair.Key, pair.Value);
                        }
                    }

                    results.Add(blob);
                }

                return results;
            }
            public IEnumerable<IStorageBlob> ListBlobs(MemoryBlobStore store, IStorageBlobContainer parent,
                BlobListingDetails blobListingDetails)
            {
                if (blobListingDetails != BlobListingDetails.None && blobListingDetails != BlobListingDetails.Metadata)
                {
                    throw new NotImplementedException();
                }
                List<IStorageBlob> results = new List<IStorageBlob>();

                foreach (KeyValuePair<string, Blob> item in _items)
                {
                    string blobName = item.Key;

                    // Etag  and LastModifiedTime is always passed in listBlobs
                    FakeStorageBlobProperties properties = new FakeStorageBlobProperties()
                    {
                        ETag = item.Value.ETag,
                        LastModified = item.Value.LastModified,
                    };

                    IStorageBlob blob = new FakeStorageBlockBlob(store, blobName, parent, properties);
                    if ((blobListingDetails | BlobListingDetails.Metadata) == BlobListingDetails.Metadata)
                    {
                        Blob storeBlob = item.Value;
                        IReadOnlyDictionary<string, string> storeMetadata = storeBlob.Metadata;

                        foreach (KeyValuePair<string, string> pair in storeMetadata)
                        {
                            blob.Metadata.Add(pair.Key, pair.Value);
                        }
                    }

                    results.Add(blob);
                }

                return results;
            }
            public IStorageBlob GetBlobReferenceFromServer(MemoryBlobStore store, IStorageBlobContainer parent, string blobName)
            {
                if (!_items.ContainsKey(blobName))
                {
                    throw StorageExceptionFactory.Create(404);
                }

                Blob blob = _items[blobName];

                if (blob.BlobType == StorageBlobType.BlockBlob)
                {
                    return new FakeStorageBlockBlob(store, blobName, parent);
                }
                else
                {
                    return new FakeStoragePageBlob(store, blobName, parent);
                }
            }
 /// <summary>Initializes a new instance of the <see cref="StorageBlobDirectory"/> class.</summary>
 /// <param name="parent">The parent blob container.</param>
 /// <param name="sdk">The SDK directory to wrap.</param>
 public StorageBlobDirectory(IStorageBlobContainer parent, CloudBlobDirectory sdk)
 {
     _parent = parent;
     _sdk = sdk;
 }
        public static async Task<Tuple<IEnumerable<IStorageBlob>, DateTime>> PollNewBlobsAsync(
            IStorageBlobContainer container, DateTime previousTimestamp, CancellationToken cancellationToken)
        {
            DateTime updatedTimestamp = previousTimestamp;

            IList<IStorageListBlobItem> currentBlobs;

            try
            {
                currentBlobs = (await container.ListBlobsAsync(prefix: null, useFlatBlobListing: true,
                    cancellationToken: cancellationToken)).ToList();
            }
            catch (StorageException exception)
            {
                if (exception.IsNotFound())
                {
                    return new Tuple<IEnumerable<IStorageBlob>, DateTime>(
                        Enumerable.Empty<IStorageBlob>(), updatedTimestamp);
                }
                else
                {
                    throw;
                }
            }

            List<IStorageBlob> newBlobs = new List<IStorageBlob>();

            // Type cast to IStorageBlob is safe due to useFlatBlobListing: true above.
            foreach (IStorageBlob currentBlob in currentBlobs)
            {
                cancellationToken.ThrowIfCancellationRequested();

                try
                {
                    await currentBlob.FetchAttributesAsync(cancellationToken);
                }
                catch (StorageException exception)
                {
                    if (exception.IsNotFound())
                    {
                        continue;
                    }
                    else
                    {
                        throw;
                    }
                }

                IStorageBlobProperties properties = currentBlob.Properties;
                DateTime lastModifiedTimestamp = properties.LastModified.Value.UtcDateTime;

                if (lastModifiedTimestamp > updatedTimestamp)
                {
                    updatedTimestamp = lastModifiedTimestamp;
                }

                if (lastModifiedTimestamp > previousTimestamp)
                {
                    newBlobs.Add(currentBlob);
                }
            }

            return new Tuple<IEnumerable<IStorageBlob>, DateTime>(newBlobs, updatedTimestamp);
        }