/// <summary> /// Gets the next checkpoint id /// </summary> /// <returns></returns> private ulong GetNextCheckpoint() { var blobContainer = _blobClient.GetContainerReference(RootContainerName); var checkpointBlob = WrappedPageBlob.CreateNewIfNotExists(blobContainer, CheckpointBlobName, 1); ((CloudPageBlob)checkpointBlob).SetSequenceNumber(SequenceNumberAction.Increment, null); return((ulong)((CloudPageBlob)checkpointBlob).Properties.PageBlobSequenceNumber.Value); }
/// <summary> /// Gets commits from a given blobEntry and stream id that fall within min and max revisions. /// </summary> /// <param name="bucketId">The blobEntry id to pull from.</param> /// <param name="streamId">The stream id.</param> /// <param name="minRevision">The minimum revision.</param> /// <param name="maxRevision">The maximum revision.</param> /// <returns></returns> public IEnumerable <ICommit> GetFrom(string bucketId, string streamId, int minRevision, int maxRevision) { var pageBlob = WrappedPageBlob.CreateNewIfNotExists(_primaryContainer, bucketId + "/" + streamId, _options.BlobNumPages); HeaderDefinitionMetadata headerDefinitionMetadata = null; var header = GetHeaderWithRetry(pageBlob, out headerDefinitionMetadata); // find out how many pages we are reading var startPage = 0; var endPage = startPage + 1; var startIndex = 0; var numberOfCommits = 0; foreach (var commitDefinition in header.PageBlobCommitDefinitions) { if (minRevision > commitDefinition.Revision) { ++startIndex; startPage += commitDefinition.TotalPagesUsed; } else if (maxRevision < commitDefinition.Revision) { break; } else { ++numberOfCommits; } endPage += commitDefinition.TotalPagesUsed; } // download all the data var downloadedData = pageBlob.DownloadBytes(startPage * BlobPageSize, endPage * BlobPageSize); // process the downloaded data var commits = new List <ICommit>(); for (var i = startIndex; i != startIndex + numberOfCommits; i++) { var commitStartIndex = (header.PageBlobCommitDefinitions[i].StartPage - startPage) * BlobPageSize; var commitSize = header.PageBlobCommitDefinitions[i].DataSizeBytes; using (var ms = new MemoryStream(downloadedData, commitStartIndex, commitSize, false)) { var commit = _serializer.Deserialize <AzureBlobCommit>(ms); commits.Add(CreateCommitFromAzureBlobCommit(commit)); } } return(commits); }
/// <summary> /// Adds a commit to a stream. /// </summary> /// <param name="attempt">The commit attempt to be added.</param> /// <returns>An Commit if successful.</returns> public ICommit Commit(CommitAttempt attempt) { var pageBlob = WrappedPageBlob.CreateNewIfNotExists(_primaryContainer, attempt.BucketId + "/" + attempt.StreamId, _options.BlobNumPages); HeaderDefinitionMetadata headerDefinitionMetadata = null; var header = GetHeaderWithRetry(pageBlob, out headerDefinitionMetadata); // we must commit at a page offset, we will just track how many pages in we must start writing at var startPage = 0; foreach (var commit in header.PageBlobCommitDefinitions) { if (commit.CommitId == attempt.CommitId) { throw new DuplicateCommitException("Duplicate Commit Attempt"); } startPage += commit.TotalPagesUsed; } if (attempt.CommitSequence <= header.LastCommitSequence) { throw new ConcurrencyException("Concurrency exception in Commit"); } var blobCommit = new AzureBlobCommit { BucketId = attempt.BucketId, CommitId = attempt.CommitId, CommitSequence = attempt.CommitSequence, CommitStampUtc = attempt.CommitStamp, Events = attempt.Events.ToList(), Headers = attempt.Headers, StreamId = attempt.StreamId, StreamRevision = attempt.StreamRevision, Checkpoint = GetNextCheckpoint() }; var serializedBlobCommit = _serializer.Serialize(blobCommit); header.AppendPageBlobCommitDefinition(new PageBlobCommitDefinition(serializedBlobCommit.Length, attempt.CommitId, attempt.StreamRevision, attempt.CommitStamp, header.PageBlobCommitDefinitions.Count, startPage, blobCommit.Checkpoint)); ++header.UndispatchedCommitCount; header.LastCommitSequence = attempt.CommitSequence; CommitNewMessage(pageBlob, serializedBlobCommit, header, headerDefinitionMetadata, startPage * BlobPageSize); return(CreateCommitFromAzureBlobCommit(blobCommit)); }
/// <summary> /// Not yet implemented. /// </summary> /// <param name="snapshot"></param> /// <returns></returns> public bool AddSnapshot(ISnapshot snapshot) { var pageBlob = WrappedPageBlob.CreateNewIfNotExists(_primaryContainer, snapshot.BucketId + "/ss/" + snapshot.StreamId, _options.BlobNumPages); var serializedSnapshot = _serializer.Serialize(snapshot.Payload); pageBlob.Metadata["ss_data_size_bytes"] = "0"; pageBlob.Metadata["ss_stream_revision"] = "0"; pageBlob.SetMetadata(); var pageAlignedSize = GetPageAlignedSize(serializedSnapshot.Length); using (var serializedSnapshotStream = CreateAndFillStreamAligned(pageAlignedSize, serializedSnapshot)) { pageBlob.Write(serializedSnapshotStream, 0, 0, new HeaderDefinitionMetadata()); } pageBlob.Metadata["ss_data_size_bytes"] = serializedSnapshot.Length.ToString(); pageBlob.Metadata["ss_stream_revision"] = snapshot.StreamRevision.ToString(); pageBlob.SetMetadata(); return(true); }