public static ReplicatedTableQuorumWriteResult TryUploadBlobs <T>(List <CloudBlockBlob> blobs, T configuration) where T : class { string content = configuration.ToString(); // Update blobs ... int numberOfBlobs = blobs.Count; ReplicatedTableWriteBlobResult[] writeResultArray = new ReplicatedTableWriteBlobResult[numberOfBlobs]; Parallel.For(0, numberOfBlobs, index => { writeResultArray[index] = TryWriteBlob(blobs[index], content, "*"); }); int successRate = writeResultArray.Count(e => e.Success == true); if (successRate == numberOfBlobs) { return(new ReplicatedTableQuorumWriteResult(ReplicatedTableQuorumWriteCode.Success, writeResultArray.ToList())); } return(new ReplicatedTableQuorumWriteResult(ReplicatedTableQuorumWriteCode.QuorumWriteFailure, writeResultArray.ToList())); }
public static ReplicatedTableQuorumWriteResult TryWriteBlobQuorum <T>(List <CloudBlockBlob> blobs, T configuration, Func <string, T> ParseBlobFunc, Func <T, T, bool> ConfigIdComparer, Func <T, T> GenerateConfigId) where T : ReplicatedTableConfigurationBase, new() { // Fetch all blobs ... List <T> valuesArray; List <string> eTagsArray; List <ReplicatedTableReadBlobResult> resultArray = TryReadAllBlobs(blobs, out valuesArray, out eTagsArray, ParseBlobFunc); // Find majority ... int quorumIndex; ReplicatedTableQuorumReadResult majority = FindMajority(resultArray.AsReadOnly(), valuesArray.AsReadOnly(), out quorumIndex); string readDetails = majority.ToString(); switch (majority.Code) { case ReplicatedTableQuorumReadCode.NotFound: // Create blobs ... break; case ReplicatedTableQuorumReadCode.UpdateInProgress: return(new ReplicatedTableQuorumWriteResult(ReplicatedTableQuorumWriteCode.ConflictDueToUpdateInProgress, readDetails)); case ReplicatedTableQuorumReadCode.Exception: return(new ReplicatedTableQuorumWriteResult(ReplicatedTableQuorumWriteCode.ReadExceptions, readDetails)); case ReplicatedTableQuorumReadCode.NullOrLowSuccessRate: return(new ReplicatedTableQuorumWriteResult(ReplicatedTableQuorumWriteCode.ReadNoQuorum, readDetails)); case ReplicatedTableQuorumReadCode.Success: // Blob has changed since ... if (ConfigIdComparer(valuesArray[quorumIndex], configuration) == false) { return(new ReplicatedTableQuorumWriteResult(ReplicatedTableQuorumWriteCode.ConflictDueToBlobChange, readDetails)); } // Update blobs ... break; case ReplicatedTableQuorumReadCode.BlobsNotInSyncOrTransitioning: return(new ReplicatedTableQuorumWriteResult(ReplicatedTableQuorumWriteCode.BlobsNotInSyncOrTransitioning, readDetails)); case ReplicatedTableQuorumReadCode.NullObject: default: { var msg = string.Format("Unexpected value majority=\'{0}\' ", majority.Code); throw new Exception(msg); } } // Generate a new Id for the copy of the input configuration T newConfiguration = GenerateConfigId(configuration); string content = newConfiguration.ToString(); // Update blobs ... int numberOfBlobs = blobs.Count; ReplicatedTableWriteBlobResult[] writeResultArray = new ReplicatedTableWriteBlobResult[numberOfBlobs]; Parallel.For(0, numberOfBlobs, index => { T currentValue = valuesArray[index]; string currentETag = eTagsArray[index]; if (currentValue == null) { currentETag = null; } else if (!ConfigIdComparer(currentValue, configuration)) { currentETag = "*"; } writeResultArray[index] = TryWriteBlob(blobs[index], content, currentETag); }); int successRate = writeResultArray.Count(e => e.Success == true); int quorum = (numberOfBlobs / 2) + 1; if (successRate >= quorum) { // Return new config Id to the caller for record string newConfId = newConfiguration.GetConfigId().ToString(); return(new ReplicatedTableQuorumWriteResult(ReplicatedTableQuorumWriteCode.Success, newConfId, writeResultArray.ToList())); } return(new ReplicatedTableQuorumWriteResult(ReplicatedTableQuorumWriteCode.QuorumWriteFailure, writeResultArray.ToList())); }