Example #1
0
        private bool AcquireLeaseIfBlobExists(TimeSpan leaseDuration)
        {
            bool exists = true;

            StorageOperation.Try(
                () => { AcquireLeaseForExistingBlob(leaseDuration); },
                catchHttp404: e => { exists = false; }
                );
            return(exists);
        }
Example #2
0
 private void AcquireLeaseForExistingBlob(TimeSpan leaseDuration)
 {
     StorageOperation.Try(
         () =>
     {
         lock (this.writeAccessCondition)
         {
             this.writeAccessCondition.LeaseId = this.backingBlob.AcquireLease(leaseDuration, proposedLeaseId: null);
         }
     },
         catchHttp409: e =>
     {
         throw new InvalidOperationException("The lease for this blob has been taken by another client", e);
     });
 }
Example #3
0
        private void WriteLocalDataToCloudIfNeeded()
        {
            lock (this.syncRoot)
            {
                byte[] localContentHash;

                if (!Serialization.ModifiedSince(
                        this.localObject,
                        this.lastKnownBlobContentsHash,
                        out localContentHash))
                {
                    return;
                }

                AccessCondition writeAccessConditionAtStartOfUpload = new AccessCondition();
                lock (this.writeAccessCondition)
                {
                    writeAccessConditionAtStartOfUpload.LeaseId = this.writeAccessCondition.LeaseId;
                }

                StorageOperation.Try(
                    () =>
                {
                    OperationContext context = new OperationContext();

                    CloudBlobStream uploadStream = this.backingBlob.OpenWrite(
                        accessCondition: writeAccessConditionAtStartOfUpload,
                        operationContext: context);
                    Serialization.SerializeIntoStream(this.localObject, uploadStream);
                    uploadStream.Close();

                    this.readAccessCondition.IfNoneMatchETag = context.LastResult.Etag;
                    this.lastKnownBlobContentsHash           = localContentHash;
                },
                    catchHttp400: e =>
                {
                    // Can happen when two clients race to perform an upload to the same blob; one
                    // client will get a HTTP 400 when committing their list of uploaded blocks.
                    OnWriteToCloudFailure(e, writeAccessConditionAtStartOfUpload);
                },
                    catchHttp412: e =>
                {
                    // There is a lease in place that prevents this write.
                    OnWriteToCloudFailure(e, writeAccessConditionAtStartOfUpload);
                });
            }
        }
Example #4
0
        private bool TryRefreshDataFromCloudBlob()
        {
            bool exists = true;

            StorageOperation.Try(
                () =>
            {
                T temp = default(T);
                OperationContext context = new OperationContext();

                lock (this.syncRoot)
                {
                    StorageOperation.Try(
                        () =>
                    {
                        Stream blobContentsStream = this.backingBlob.OpenRead(
                            accessCondition: this.readAccessCondition,
                            operationContext: context);

                        exists = Serialization.DeserializeInto <T>(
                            ref temp,
                            blobContentsStream,
                            out this.lastKnownBlobContentsHash);

                        this.readAccessCondition.IfNoneMatchETag = context.LastResult.Etag;
                    },
                        catchHttp404: e =>
                    {
                        exists = false;
                    });

                    this.localObject = temp;

                    if (exists)
                    {
                        if (this.OnUpdate != null)
                        {
                            this.OnUpdate(this, EventArgs.Empty);
                        }
                    }
                }
            },
                catchHttp304: e => { }, // TODO: Perf improvement; prevent throwing of exceptions in expected-case paths?
                catchHttp412: e => { });

            return(exists);
        }
Example #5
0
        /// <summary>
        /// Starts a task that triggers a request to renew the lease on the backing blob MinimumLeaseInSeconds
        /// before it expires, and releases the lease when the task is aborted.
        /// </summary>
        private Task StartLeaseRenewer(TimeSpan leaseDuration)
        {
            return(Task.Run(
                       () =>
            {
                Stopwatch timer = Stopwatch.StartNew();
                bool stop = false;
                while (!stop)
                {
                    stop = stopLeaseRenewer.Wait(TimeSpan.FromTicks(timer.ElapsedTicks % (leaseDuration.Ticks / 2)));

                    if (!stop)
                    {
                        StorageOperation.Try(
                            () =>
                        {
                            lock (this.writeAccessCondition)
                            {
                                this.backingBlob.RenewLease(this.writeAccessCondition);
                            }
                        },
                            catchHttp409: e =>
                        {
                            // Lost our original lease (maybe due to this task sleeping for an extremely long time)
                            AcquireLeaseForExistingBlob(leaseDuration);
                        });
                    }
                }

                StorageOperation.Try(
                    () =>
                {
                    lock (this.writeAccessCondition)
                    {
                        this.backingBlob.ReleaseLease(this.writeAccessCondition);
                    }
                },
                    catchHttp409: e =>
                {
                    // Maybe we didn't have the lease anyway? Ooh well, we're shutting down anyway (absorb this error)
                });
            }));
        }