public TEntity AddOrUpdate(TKey key, Func <TEntity> addViewFactory, Func <TEntity, TEntity> updateViewFactory, AddOrUpdateHint hint) { string etag = null; var blob = GetBlobReference(key); TEntity view; try { // atomic entities should be small, so we can use the simple method var bytes = blob.DownloadByteArray(); using (var stream = new MemoryStream(bytes)) { view = _strategy.Deserialize <TEntity>(stream); } view = updateViewFactory(view); etag = blob.Attributes.Properties.ETag; } catch (StorageClientException ex) { switch (ex.ErrorCode) { case StorageErrorCode.ContainerNotFound: var s = string.Format( "Container '{0}' does not exist. You need to initialize this atomic storage and ensure that '{1}' is known to '{2}'.", blob.Container.Name, typeof(TEntity).Name, _strategy.GetType().Name); throw new InvalidOperationException(s, ex); case StorageErrorCode.BlobNotFound: case StorageErrorCode.ResourceNotFound: view = addViewFactory(); break; default: throw; } } // atomic entities should be small, so we can use the simple method // http://toolheaven.net/post/Azure-and-blob-write-performance.aspx using (var memory = new MemoryStream()) { _strategy.Serialize(view, memory); // note that upload from stream does weird things var bro = etag != null ? new BlobRequestOptions { AccessCondition = AccessCondition.IfMatch(etag) } : new BlobRequestOptions { AccessCondition = AccessCondition.IfNoneMatch("*") }; // make sure that upload is not rejected due to cashed content MD5 // http://social.msdn.microsoft.com/Forums/hu-HU/windowsazuredata/thread/4764e38f-b200-4efe-ada2-7de442dc4452 blob.Properties.ContentMD5 = null; blob.UploadByteArray(memory.ToArray(), bro); } return(view); }
public AutoRenewLease(CloudBlob blob) { this.blob = blob; blob.Container.CreateIfNotExist(); try { blob.UploadByteArray(new byte[0], new BlobRequestOptions { AccessCondition = AccessCondition.IfNoneMatch("*") }); } catch (StorageClientException e) { if (e.ErrorCode != StorageErrorCode.BlobAlreadyExists && e.StatusCode != HttpStatusCode.PreconditionFailed) // 412 from trying to modify a blob that's leased { throw; } } leaseId = blob.TryAcquireLease(); if (HasLease) { renewalThread = new Thread(() => { while (true) { Thread.Sleep(TimeSpan.FromSeconds(40)); blob.RenewLease(leaseId); } }); renewalThread.Start(); } }
private BlobRequestOptions CreateBlobRequestOptions() { var etag = this.Properties.ETag; var options = new BlobRequestOptions(); options.AccessCondition = etag == null? AccessCondition.IfNoneMatch("*") : AccessCondition.IfMatch(etag); return(options); }
public AutoRenewLease(ILoggerFactory loggerFactory, LoggerLevel logLevel, CloudBlob blob, int renewLeaseSeconds = 40, int leaseLengthSeconds = 90) { _logger = loggerFactory.Create(GetType(), logLevel); var autoRenewLease = this; _blob = blob; blob.Container.CreateIfNotExist(); try { blob.UploadByteArray(new byte[0], new BlobRequestOptions { AccessCondition = AccessCondition.IfNoneMatch("*") }); } catch (StorageClientException ex) { if (ex.ErrorCode != StorageErrorCode.BlobAlreadyExists) { if (ex.StatusCode != HttpStatusCode.PreconditionFailed) { throw; } } } LeaseId = blob.TryAcquireLease(leaseLengthSeconds); if (!HasLease) { return; } _cancellationTokenSource = new CancellationTokenSource(); _resetEvent = new ManualResetEvent(false); Task.Factory.StartNew(() => { try { while (true) { _resetEvent.WaitOne(TimeSpan.FromSeconds(renewLeaseSeconds)); if (_cancellationTokenSource.IsCancellationRequested) { break; } blob.RenewLease(autoRenewLease.LeaseId); } } catch (Exception e) { LeaseId = null; // Release the lease _logger.Error("Error renewing blob lease", e); } }, _cancellationTokenSource.Token); }
private static void CreateIfNotExist(this CloudBlob blob) { try { blob.UploadByteArray(new byte[0], new BlobRequestOptions { AccessCondition = AccessCondition.IfNoneMatch("*") }); } catch (StorageClientException ex) { if (ex.ErrorCode != StorageErrorCode.BlobAlreadyExists && ex.StatusCode != HttpStatusCode.PreconditionFailed) { throw; } } }
public static AutoRenewLease GetOrThrow(CloudBlob blob) { blob.Container.CreateIfNotExist(); // Create lock blob try { var requestOptions = new BlobRequestOptions { AccessCondition = AccessCondition.IfNoneMatch("*") }; blob.UploadByteArray(new byte[0], requestOptions); } catch (StorageClientException e) { if (e.ErrorCode != StorageErrorCode.BlobAlreadyExists && e.StatusCode != HttpStatusCode.PreconditionFailed) // 412 from trying to modify a blob that's leased { throw; } } string leaseId = null; var ex = DoUntilTrue(Try4Times, CancellationToken.None, () => { leaseId = AcquireLease(blob); return(!String.IsNullOrEmpty(leaseId)); }); if (ex != null) { throw new InvalidOperationException("Failed to get lease", ex); } // Either we get lease or throw timeout exception if (String.IsNullOrEmpty(leaseId)) { throw new InvalidOperationException(); } return(new AutoRenewLease(blob, leaseId)); }
static AccessCondition MapCondition(StreamingCondition condition) { switch (condition.Type) { case StreamingConditionType.None: return(AccessCondition.None); case StreamingConditionType.IfMatch: var x = ExposeException(condition.ETag, "'ETag' should be present"); return(AccessCondition.IfMatch(x)); case StreamingConditionType.IfNoneMatch: var etag = ExposeException(condition.ETag, "'ETag' should be present"); return(AccessCondition.IfNoneMatch(etag)); default: throw new ArgumentOutOfRangeException(); } }
public bool SetIfNotExists(T obj) { BlobRequestOptions reqOpt = new BlobRequestOptions(); reqOpt.AccessCondition = AccessCondition.IfNoneMatch("*"); try { using (MemoryStream stream = new MemoryStream()) { Serializer.Serialize(stream, obj); stream.Seek(0, SeekOrigin.Begin); blob.UploadFromStream(stream, reqOpt); } return(true); } catch (StorageClientException e) { if (e.ErrorCode != StorageErrorCode.ConditionFailed && e.ErrorCode != StorageErrorCode.BlobAlreadyExists) { throw; } return(false); } }