//public Microsoft.WindowsAzure.Storage.ICancellableAsyncResult BeginUploadFromStream(System.IO.Stream source, AsyncCallback callback, object state) //{ // return strongBlob.BeginUploadFromStream(source, callback, state); //} //public Microsoft.WindowsAzure.Storage.ICancellableAsyncResult BeginUploadFromStream(System.IO.Stream source, Microsoft.WindowsAzure.Storage.AccessCondition accessCondition, Microsoft.WindowsAzure.Storage.Blob.BlobRequestOptions options, Microsoft.WindowsAzure.Storage.OperationContext operationContext, AsyncCallback callback, object state) //{ // return strongBlob.BeginUploadFromStream(source, accessCondition, options, operationContext, callback, state); //} //public void EndUploadFromStream(IAsyncResult asyncResult) //{ // strongBlob.EndUploadFromStream(asyncResult); // slaEngine.SessionState.RecordObjectWritten(strongBlob.Name, Timestamp(strongBlob), primaryServer); //} //public Microsoft.WindowsAzure.Storage.ICancellableAsyncResult BeginDownloadToStream(System.IO.Stream target, AsyncCallback callback, object state) //{ // // TODO: Use SLA to decide from which server to download. // return strongBlob.BeginDownloadToStream(target, callback, state); //} //public Microsoft.WindowsAzure.Storage.ICancellableAsyncResult BeginDownloadToStream(System.IO.Stream target, Microsoft.WindowsAzure.Storage.AccessCondition accessCondition, Microsoft.WindowsAzure.Storage.Blob.BlobRequestOptions options, Microsoft.WindowsAzure.Storage.OperationContext operationContext, AsyncCallback callback, object state) //{ // return strongBlob.BeginDownloadToStream(target, accessCondition, options, operationContext, callback, state); //} //public void EndDownloadToStream(IAsyncResult asyncResult) //{ // strongBlob.EndDownloadToStream(asyncResult); // slaEngine.SessionState.RecordObjectRead(strongBlob.Name, Timestamp(strongBlob), primaryServer); //} //public Microsoft.WindowsAzure.Storage.ICancellableAsyncResult BeginDownloadRangeToStream(System.IO.Stream target, long? offset, long? length, AsyncCallback callback, object state) //{ // return strongBlob.BeginDownloadRangeToStream(target, offset, length, callback, state); //} //public Microsoft.WindowsAzure.Storage.ICancellableAsyncResult BeginDownloadRangeToStream(System.IO.Stream target, long? offset, long? length, Microsoft.WindowsAzure.Storage.AccessCondition accessCondition, Microsoft.WindowsAzure.Storage.Blob.BlobRequestOptions options, Microsoft.WindowsAzure.Storage.OperationContext operationContext, AsyncCallback callback, object state) //{ // return strongBlob.BeginDownloadRangeToStream(target, offset, length, accessCondition, options, operationContext, callback, state); //} //public void EndDownloadRangeToStream(IAsyncResult asyncResult) //{ // strongBlob.EndDownloadRangeToStream(asyncResult); // slaEngine.SessionState.RecordObjectRead(strongBlob.Name, Timestamp(strongBlob), primaryServer); //} //public Microsoft.WindowsAzure.Storage.ICancellableAsyncResult BeginExists(AsyncCallback callback, object state) //{ // return strongBlob.BeginExists(callback, state); //} //public Microsoft.WindowsAzure.Storage.ICancellableAsyncResult BeginExists(Microsoft.WindowsAzure.Storage.Blob.BlobRequestOptions options, Microsoft.WindowsAzure.Storage.OperationContext operationContext, AsyncCallback callback, object state) //{ // return strongBlob.BeginExists(options, operationContext, callback, state); //} //public bool EndExists(IAsyncResult asyncResult) //{ // bool result = strongBlob.EndExists(asyncResult); // slaEngine.SessionState.RecordObjectRead(strongBlob.Name, Timestamp(strongBlob), primaryServer); // return result; //} //public Microsoft.WindowsAzure.Storage.ICancellableAsyncResult BeginFetchAttributes(AsyncCallback callback, object state) //{ // return strongBlob.BeginFetchAttributes(callback, state); //} //public Microsoft.WindowsAzure.Storage.ICancellableAsyncResult BeginFetchAttributes(Microsoft.WindowsAzure.Storage.AccessCondition accessCondition, Microsoft.WindowsAzure.Storage.Blob.BlobRequestOptions options, Microsoft.WindowsAzure.Storage.OperationContext operationContext, AsyncCallback callback, object state) //{ // return strongBlob.BeginFetchAttributes(accessCondition, options, operationContext, callback, state); //} //public void EndFetchAttributes(IAsyncResult asyncResult) //{ // strongBlob.EndFetchAttributes(asyncResult); // slaEngine.SessionState.RecordObjectRead(strongBlob.Name, Timestamp(strongBlob), primaryServer); //} //public void SetMetadata(Microsoft.WindowsAzure.Storage.AccessCondition accessCondition = null, Microsoft.WindowsAzure.Storage.Blob.BlobRequestOptions options = null, Microsoft.WindowsAzure.Storage.OperationContext operationContext = null) //{ // watch.Start(); // strongBlob.SetMetadata(accessCondition, options, operationContext); // primaryServer.AddRtt(watch.ElapsedMilliseconds); // slaEngine.SessionState.RecordObjectWritten(strongBlob.Name, Timestamp(strongBlob), primaryServer); //} //public Microsoft.WindowsAzure.Storage.ICancellableAsyncResult BeginSetMetadata(AsyncCallback callback, object state) //{ // return strongBlob.BeginSetMetadata(callback, state); //} //public Microsoft.WindowsAzure.Storage.ICancellableAsyncResult BeginSetMetadata(Microsoft.WindowsAzure.Storage.AccessCondition accessCondition, Microsoft.WindowsAzure.Storage.Blob.BlobRequestOptions options, Microsoft.WindowsAzure.Storage.OperationContext operationContext, AsyncCallback callback, object state) //{ // return strongBlob.BeginSetMetadata(accessCondition, options, operationContext, callback, state); //} //public void EndSetMetadata(IAsyncResult asyncResult) //{ // strongBlob.EndSetMetadata(asyncResult); // slaEngine.SessionState.RecordObjectWritten(strongBlob.Name, Timestamp(strongBlob), primaryServer); //} //public void SetProperties(Microsoft.WindowsAzure.Storage.AccessCondition accessCondition = null, Microsoft.WindowsAzure.Storage.Blob.BlobRequestOptions options = null, Microsoft.WindowsAzure.Storage.OperationContext operationContext = null) //{ // watch.Start(); // strongBlob.SetProperties(accessCondition, options, operationContext); // primaryServer.AddRtt(watch.ElapsedMilliseconds); // slaEngine.SessionState.RecordObjectWritten(strongBlob.Name, Timestamp(strongBlob), primaryServer); //} //public Microsoft.WindowsAzure.Storage.ICancellableAsyncResult BeginSetProperties(AsyncCallback callback, object state) //{ // return strongBlob.BeginSetProperties(callback, state); //} //public Microsoft.WindowsAzure.Storage.ICancellableAsyncResult BeginSetProperties(Microsoft.WindowsAzure.Storage.AccessCondition accessCondition, Microsoft.WindowsAzure.Storage.Blob.BlobRequestOptions options, Microsoft.WindowsAzure.Storage.OperationContext operationContext, AsyncCallback callback, object state) //{ // return strongBlob.BeginSetProperties(accessCondition, options, operationContext, callback, state); //} //public void EndSetProperties(IAsyncResult asyncResult) //{ // strongBlob.EndSetProperties(asyncResult); // slaEngine.SessionState.RecordObjectWritten(strongBlob.Name, Timestamp(strongBlob), primaryServer); //} public void Delete(Microsoft.WindowsAzure.Storage.Blob.DeleteSnapshotsOption deleteSnapshotsOption = DeleteSnapshotsOption.None, Microsoft.WindowsAzure.Storage.AccessCondition accessCondition = null, Microsoft.WindowsAzure.Storage.Blob.BlobRequestOptions options = null, Microsoft.WindowsAzure.Storage.OperationContext operationContext = null) { bool isDone = false; do { try { if (configuration.IsInFastMode()) { DoDelete(deleteSnapshotsOption, accessCondition, options, operationContext); isDone = true; } else { //We are not sure if reconfiguration is happening or not. We execute put in slow mode. using (CloudBlobLease lease = new CloudBlobLease(configuration.Name, LeaseTakingPolicy.TryOnce)) { if (lease.HasLease) { configuration.SyncWithCloud(ClientRegistry.GetConfigurationAccount()); DoDelete(deleteSnapshotsOption, accessCondition, options, operationContext); isDone = true; } } } } catch (StorageException ex) { throw ex; } catch (Exception ex) { throw ex; } } while (!isDone); }
/// <summary> /// Perform read optimistically and then verify configuration. /// </summary> /// <param name="op">The read operation</param> /// <param name="blob">The blob being read</param> /// <param name="ss">The chosen server</param> /// <returns>whether the read succeeded; if not, then it should be tried again.</returns> private void SlowRead(ReadOp op) { // TODO: Deal with the case that we try to read from a replica that is no longer a replica and the read fails // In this case, the read should be retried after refreshing the configuration. ServerState ss = null; try { bool isDone = false; do // until we enter fast mode or succeed at reading in slow mode with the correct configuration { ss = slaEngine.FindServerToRead(blobName); blobForRead = ClientRegistry.GetCloudBlob(ss.Name, containerName, blobName); // TODO: this should really check if the reader wants strong consistency // It could be that eventual consistency is fine but the SLA Engine just happened to choose a primary server // In this case, we can do a fast mode read since we don't care if the chosen server is no longer a primary if (configuration.IsInFastMode() || !configuration.PrimaryServers.Contains(ss.Name)) { // it is fine to read from the selected secondary replica // or from a primary replica if we have now entered fast mode FastRead(op); isDone = true; } else { // read from the selected replica that we believe to be a primary replica watch.Start(); op(blobForRead); watch.Stop(); // then see if the configuration has changed and the selected replica is no longer primary configuration.SyncWithCloud(ClientRegistry.GetConfigurationAccount()); // TODO: check the epoch number on the configuration to make sure that we have not missed a configuration. // i.e. we need to make sure that the server from which we read did not become a secondary during our read, // and then back to primary when we checked. // TODO: maybe we should check that the read delivered a non-zero utility. // It is possible that the configuration was so stale that a much better server could have been chosen. if (configuration.PrimaryServers.Contains(ss.Name)) { //We have contacted the primary replica, hence we are good to go. slaEngine.RecordObjectRead(blobForRead.Name, Timestamp(blobForRead), ss, watch.ElapsedMilliseconds); isDone = true; } isDone = false; // not done } } while (!isDone); } // TODO: decide if we need to catch any exceptions here or just let then propagate through catch (StorageException se) { if (StorageExceptionCode.NotFound(se)) { //blob is not found. //this is fine because the replica might have removed. //it simply returns, so client need to re-execute if this happens. //We can also re-execute the read here, but for debugging purposes, it's simpler for the client to re-execute. //Of course in real system, we need to re-execute at this level. return; } // storage exceptions are passed through to the caller throw; } catch (Exception ex) { if (ex.Message.Contains("Object reference not set to an instance of an object")) { return; } throw ex; } }
public static void Main(string[] args) { Process currProc = Process.GetCurrentProcess(); containerName = "testcontainer"; //Guid.NewGuid().ToString("N").ToLower(); if (args.Length == 0) { args = new string[7]; // the number of test iterations args[0] = "1"; // the number of blobs args[1] = "10"; // the number of concurrent test workers. args[2] = "2"; // the blob size in KB args[3] = "1024"; // the number of parallel requests per blob args[4] = "1"; // use https or not args[5] = "false"; // the result folder name args[6] = "folder1"; } iterations = Int32.Parse(args[0]); blobs = Int32.Parse(args[1]); concurrency = Int32.Parse(args[2]); blobSizeInKB = Int32.Parse(args[3]); parallelRequestsPerBlob = Int32.Parse(args[4]); useHttps = bool.Parse(args[5]); resultFileFolderName = args[6]; if (!Directory.Exists(resultFileFolderName)) { Directory.CreateDirectory(resultFileFolderName); } resultFile = string.Format(@"{6}\{0}_{1}_{2}_{3}_{4}_{5}.csv", blobSizeInKB, parallelRequestsPerBlob, concurrency, useHttps, iterations, blobs, resultFileFolderName); ThreadPool.SetMinThreads(concurrency * parallelRequestsPerBlob, concurrency * parallelRequestsPerBlob); accounts = Account.GetStorageAccounts(useHttps); ClientRegistry.Init(accounts, accounts[configAccountName]); configuration = new ReplicaConfiguration(containerName); ClientRegistry.AddConfiguration(configuration); if (firstClient) { // delete configuration blob and tables // ReplicaConfiguration.DeleteConfiguration(containerName); ConfigurationCloudStore backingStore = new ConfigurationCloudStore(accounts[configAccountName], configuration); backingStore.DeleteConfiguration(); CloudTableClient ConfigurationCloudTableClient = accounts[configAccountName].CreateCloudTableClient(); CloudTable slaTable = ConfigurationCloudTableClient.GetTableReference(ConstPool.SLA_CONFIGURATION_TABLE_NAME); slaTable.DeleteIfExists(); slaTable = ConfigurationCloudTableClient.GetTableReference(ConstPool.SESSION_STATE_CONFIGURATION_TABLE_NAME); slaTable.DeleteIfExists(); Console.WriteLine("removed everything, wait 40 seconds ..."); Thread.Sleep(40000); // recreate configuration configuration.PrimaryServers.Add("dbtsouthstorage"); configuration.SyncWithCloud(accounts[configAccountName], false); Console.WriteLine("recreated configuration, wait 10 seconds ..."); Thread.Sleep(10000); } else { // retrieve configuration from cloud configuration.SyncWithCloud(accounts[configAccountName]); } if (firstClient) { slaEngine = new ConsistencySLAEngine(CreateShoppingCartSla1(), configuration); } else { slaEngine = new ConsistencySLAEngine(CreateShoppingCartSla2(), configuration); } blobClient = accounts["dbtsouthstorage"].CreateCloudBlobClient(); blobContainer = blobClient.GetContainerReference(containerName); blobContainer.CreateIfNotExists(); capContainer = new CapCloudBlobContainer(blobContainer); // Generate random data BlobDataBuffer = new byte[1024 * blobSizeInKB]; Random random = new Random(); random.NextBytes(BlobDataBuffer); //ServiceLevelAgreement sla = CreateShoppingCartSla(); Stopwatch totalWatch = new Stopwatch(); totalWatch.Start(); for (int m = 0; m < concurrency; m++) { ThreadPool.QueueUserWorkItem((o) => { Interlocked.Increment(ref concurrentWorkers); for (int i = 0; i < iterations; i++) { Console.WriteLine("Running thread " + m + "." + i); Console.WriteLine("concurrent workers: " + concurrentWorkers); try { // do upload blob test. var blobsList = UploadBlob(); Console.WriteLine("Upload Finished ...\n"); // GET and DELETE. DoGetAndDelete(blobsList); Console.WriteLine("DoGetAndDelete Finished ...\n"); configure("client", containerName); Console.WriteLine("Configure Finished ...\n"); } catch (Exception e) { Console.WriteLine(e.ToString()); } } Interlocked.Decrement(ref concurrentWorkers); }); } Console.WriteLine("Program: Started to sleep"); Thread.Sleep(5000); while (Interlocked.CompareExchange(ref concurrentWorkers, -1, 0) != -1) { if (concurrentWorkers < 0) { break; } Console.WriteLine("Waiting for a thread because there are " + concurrentWorkers + " threads."); Thread.Sleep(5000); } Console.WriteLine("Finished execution. "); ClientRegistry.GetConfigurationContainer(containerName).Delete(); blobContainer.DeleteIfExists(); totalWatch.Stop(); long totalTimeTaken = totalWatch.ElapsedMilliseconds; using (StreamWriter sw = new StreamWriter(resultFile)) { sw.Write(String.Format("Total time taken to run the test in ms : {0}\n\n", totalTimeTaken)); sw.Write(String.Format("Args:Concurrency: {0} BlobSizeInKB:{1} ParallelRequestsPerBlob:{2} UsingHttps:{3} \n", concurrency, blobSizeInKB, parallelRequestsPerBlob, useHttps)); // display result DisplayResults(sw, "Insert", insertTimes); DisplayResults(sw, "Get", getTimes); DisplayResults(sw, "Delete", deleteTimes); float tmp = 0; foreach (SubSLA s in capContainer.SLA) { tmp += s.Utility * s.NumberOfHits; } sw.Write(String.Format("Current utility ", tmp)); // Display perf results PerfMetrics metrics = new PerfMetrics(); metrics.Update(currProc); metrics.Print(sw); } Console.Read(); }