private async Task ValidateInput() { if (!this.ModelState.IsValid) { this.LogErrorInModels(); var badRequestMessage = this.Request.CreateErrorResponse(HttpStatusCode.BadRequest, this.ModelState); var badRequestMessageDetails = await badRequestMessage.Content.ReadAsStringAsync(); var fabricBackupRestoreInputValidationError = new FabricErrorError(new FabricError { Message = badRequestMessageDetails.Replace(@"""", ""), Code = NativeTypes.FABRIC_ERROR_CODE.E_INVALIDARG }); throw new HttpResponseException(fabricBackupRestoreInputValidationError.ToHttpResponseMessage()); } }
internal override async Task <PagedBackupInfoList> RunAsync(TimeSpan timeout, CancellationToken cancellationToken) { // Reading the value of continuationToken and maxResults. string continuationTokenLocal = this.continuationToken; int maxResultsLocal = this.maxResults; // Finding all the continuationTokens. string storageIdToContinue = null; BRSContinuationToken continuationTokenForNextStage = new BRSContinuationToken(); string incomingContinuationTokenForNextStage = null; if (!String.IsNullOrEmpty(continuationTokenLocal)) { // Splitting only in 2 as first one will be storage id and other one will be continuationToken for next stage. List <string> continuationTokenList = continuationTokenLocal.Split(new char[] { ContinuationTokenSeparatorChar }, 2).ToList(); storageIdToContinue = continuationTokenList[0]; if (continuationTokenList.Count > 1) { incomingContinuationTokenForNextStage = continuationTokenList[1]; } } List <RestorePoint> restorePoints = new List <RestorePoint>(); List <BackupMappingModel> listOfBackupMappings = await this.GetBackupMappings(timeout, cancellationToken); IEnumerable <string> backupPolicyMappingList = listOfBackupMappings.Select <BackupMappingModel, string>((backupMapping) => { return(backupMapping.BackupPolicyName); }); HashSet <string> backupPolicyHashSetName = new HashSet <string>(); HashSet <BackupStorageModel> backupStorages = new HashSet <BackupStorageModel>(); foreach (var backPolicyName in backupPolicyMappingList) { if (!backupPolicyHashSetName.Contains(backPolicyName)) { backupPolicyHashSetName.Add(backPolicyName); BackupStorageModel backupStorage = (await this.BackupPolicyStore.GetValueAsync(backPolicyName, timeout, cancellationToken)).Storage; if (!backupStorages.Contains(backupStorage)) { backupStorages.Add(backupStorage); } } } bool isSuccess = true; string continuationTokenFinal = null; List <BackupStorageModel> backupStorageList = backupStorages.ToList(); if (maxResultsLocal != 0) { // Ordering only when maxResults is not equal to 0. backupStorageList = backupStorageList.OrderBy(backupStorage => backupStorage.StorageId.ToString()).ToList(); int maxResultsLeft = maxResultsLocal; bool breakTheLoop = false; // TO DO: // It is used for the case when maxResults is equal to number of elements in that storage. // In that condition, we will check for the next storage, if there is any more storages left to scan, we will send the storage id of the last storage scanned. // Here, we dont scan the next storage. There is a possibility that the next storage is empty. bool sendTheSameStorageAsContinuationToken = false; bool otherStorageFound = false; foreach (var backupStorage in backupStorageList) { if (backupStorage.StorageId.ToString().CompareTo(storageIdToContinue) >= 0) { if (sendTheSameStorageAsContinuationToken) { // It means that we have found the next storage and we should break. otherStorageFound = true; break; } continuationTokenFinal = backupStorage.StorageId.ToString(); if (storageIdToContinue == backupStorage.StorageId.ToString()) { if (String.IsNullOrEmpty(incomingContinuationTokenForNextStage)) { // if we are here, then, we are in the condition of sendTheSameStorageAsContinuationToken = true in previouse query. continue; } // continuationTokenForNextStage for this storage should be the incomingContinuationTokenForNextStage continuationTokenForNextStage.IncomingContinuationToken = incomingContinuationTokenForNextStage; } else { // continuationTokenForNextStage for other storages should have IncomingContinuationToken to be null. continuationTokenForNextStage.IncomingContinuationToken = null; } try { List <RestorePoint> newRestorePoints = new List <RestorePoint>(); newRestorePoints = await backupStorage.StartGetBackupEnumerationsTask( this.ApplicationName, this.ServiceName, this.PartitionId, this.isLatestRequested, cancellationToken, continuationTokenForNextStage, this.startDateTime, this.endDateTime, maxResultsLeft); restorePoints.AddRange(newRestorePoints); maxResultsLeft = maxResultsLeft - newRestorePoints.Count; if (maxResultsLeft == 0) { if (continuationTokenForNextStage.OutgoingContinuationToken == null) { sendTheSameStorageAsContinuationToken = true; } else { breakTheLoop = true; } } } catch (Exception ex) { isSuccess = false; restorePoints[0] = new RestorePoint() { FailureError = new FabricError() { Code = (NativeTypes.FABRIC_ERROR_CODE)ex.HResult, Message = ex.Message } }; } } if (breakTheLoop || isSuccess == false) { break; } } if (!isSuccess && restorePoints.Count > 0) { // Here, always the restorePoints's first element will be having error details. Look DoThisOnTaskFaulted method. FabricErrorError fabricErrorError = new FabricErrorError(restorePoints[0].FailureError); throw new HttpResponseException(fabricErrorError.ToHttpResponseMessage()); } continuationTokenLocal = null; if (continuationTokenForNextStage.OutgoingContinuationToken == null) { if (sendTheSameStorageAsContinuationToken && otherStorageFound) { // if there is some next store available to scan, then, we have to send the current storageID as continuationToken continuationTokenLocal = continuationTokenFinal; } } else { continuationTokenLocal = continuationTokenFinal + ContinuationTokenSeparatorChar + continuationTokenForNextStage.OutgoingContinuationToken; } return(new PagedBackupInfoList() { Items = restorePoints, ContinuationToken = continuationTokenLocal }); } else { // we don't have to sort the storage list here as we need to return the complete list. List <Task> backupStorageTaskList = new List <Task>(); foreach (var backupStorage in backupStorageList) { Task backupStorageTask; if (backupStorage.StorageId.ToString().CompareTo(storageIdToContinue) >= 0) { continuationTokenFinal = backupStorage.StorageId.ToString(); if (storageIdToContinue == backupStorage.StorageId.ToString()) { if (String.IsNullOrEmpty(incomingContinuationTokenForNextStage)) { continue; } // It is a possibility that continuationToken is not null for this stage then, we need to send the appropriate continuationToken. continuationTokenForNextStage.IncomingContinuationToken = incomingContinuationTokenForNextStage; backupStorageTask = backupStorage.StartGetBackupEnumerationsTask( this.ApplicationName, this.ServiceName, this.PartitionId, this.isLatestRequested, cancellationToken, continuationTokenForNextStage, this.startDateTime, this.endDateTime).ContinueWith((task) => { if ((!task.IsCanceled) && (!task.IsFaulted) && (task.IsCompleted)) { DoThisOnTaskSuccess(task, restorePoints, ref isSuccess); } else if (task.IsFaulted) { DoThisOnTaskFaulted(task, restorePoints, ref isSuccess); } }); } else { // Usual case for other storages. backupStorageTask = backupStorage.StartGetBackupEnumerationsTask( this.ApplicationName, this.ServiceName, this.PartitionId, this.isLatestRequested, cancellationToken, null, this.startDateTime, this.endDateTime).ContinueWith((task) => { if ((!task.IsCanceled) && (!task.IsFaulted) && (task.IsCompleted)) { DoThisOnTaskSuccess(task, restorePoints, ref isSuccess); } else if (task.IsFaulted) { DoThisOnTaskFaulted(task, restorePoints, ref isSuccess); } }); } backupStorageTaskList.Add(backupStorageTask); } } Task.WaitAll(backupStorageTaskList.ToArray(), cancellationToken); if (!isSuccess && restorePoints.Count > 0) { FabricErrorError fabricErrorError = new FabricErrorError(restorePoints[0].FailureError); throw new HttpResponseException(fabricErrorError.ToHttpResponseMessage()); } return(new PagedBackupInfoList() { Items = restorePoints, }); } }
internal async Task <TResult> RunAsync <TResult>(BaseOperation <TResult> operationBase, int timeoutInSeconds) { var cancellationTokenSource = new CancellationTokenSource(); if (timeoutInSeconds <= 0) { throw new ArgumentException(StringResources.InvalidTimeout); } var timeout = new TimeSpan(0, 0, timeoutInSeconds); cancellationTokenSource.CancelAfter(timeout); BackupRestoreTrace.TraceSource.WriteInfo(TraceType, "Controller {0} Operation requested : {1}", this.GetType(), operationBase); await this.ValidateInput(); do { try { this._retryCount++; return(await operationBase.RunAsyncWrappper(timeout, cancellationTokenSource.Token)); } catch (HttpResponseException) { throw; } catch (Exception exception) { this.LogException(TraceType, exception); var fabricException = exception as FabricException; if (fabricException != null) { var fabricError = new FabricError(fabricException); var fabricBackupRestoreError = new FabricErrorError(fabricError); throw new HttpResponseException(fabricBackupRestoreError.ToHttpResponseMessage()); } else if (exception is ArgumentException) { FabricErrorError fabricBackupRestoreError = new FabricErrorError(new FabricError() { Code = NativeTypes.FABRIC_ERROR_CODE.E_INVALIDARG, Message = exception.Message }); throw new HttpResponseException(fabricBackupRestoreError.ToHttpResponseMessage()); } else if (exception is OperationCanceledException || exception is TimeoutException) { FabricErrorError fabricBackupRestoreError = new FabricErrorError(new FabricError() { Code = NativeTypes.FABRIC_ERROR_CODE.FABRIC_E_TIMEOUT, Message = StringResources.RequestTimeout }); throw new HttpResponseException(fabricBackupRestoreError.ToHttpResponseMessage()); } else if (exception is FabricBackupRestoreLocalRetryException) //TODO Remove this and change to correct message { if (this._retryCount >= MaxRetryCount) { throw; } } else { var stringBuilder = new StringBuilder(); if (exception is AggregateException) { var aggregateException = (AggregateException)exception; foreach (var innerException in aggregateException.InnerExceptions) { stringBuilder.AppendFormat("{0} ,", innerException.Message).AppendLine(); } } else { stringBuilder.AppendFormat("{0}", exception.Message); } FabricErrorError fabricBackupRestoreError = new FabricErrorError(new FabricError() { Message = stringBuilder.ToString(), Code = NativeTypes.FABRIC_ERROR_CODE.E_UNEXPECTED }); throw new HttpResponseException(fabricBackupRestoreError.ToHttpResponseMessage()); } } } while (this._retryCount <= MaxRetryCount); throw new HttpResponseException(HttpStatusCode.InternalServerError); }
internal async Task <TResult> RunAsync <TResult>(BaseOperation <TResult> operationBase, int timeoutInSeconds = (2 * 60)) { var cancellationTokenSource = new CancellationTokenSource(); if (timeoutInSeconds <= 0) { throw new ArgumentException("Invalid Timeout"); } var timeout = new TimeSpan(0, 0, timeoutInSeconds); cancellationTokenSource.CancelAfter(timeout); await this.ValidateInputAsync(); try { var startTime = DateTimeOffset.UtcNow; var results = await operationBase.RunAsyncWrappper(timeout, cancellationTokenSource.Token).ConfigureAwait(false); return(results); } catch (Exception exception) { FabricEvents.Events.EventStoreFailed(operationBase.GetSupportedEntityType().ToString(), ExtractDetails(exception)); if (exception is ConnectionParsingException) { // This indicates to the caller that the API's are not available as the connection information is not configured. throw new HttpResponseException(HttpStatusCode.ServiceUnavailable); } if (exception is HttpResponseException) { throw; } var fabricException = exception as FabricException; if (fabricException != null) { var fabricError = new FabricError(fabricException); var fabricBackupRestoreError = new FabricErrorError(fabricError); throw new HttpResponseException(fabricBackupRestoreError.ToHttpResponseMessage()); } else if (exception is ArgumentException) { FabricErrorError fabricEventStoreSvcErrorMessage = new FabricErrorError( new FabricError { Code = NativeTypes.FABRIC_ERROR_CODE.E_INVALIDARG, Message = exception.Message }); throw new HttpResponseException(fabricEventStoreSvcErrorMessage.ToHttpResponseMessage()); } else if (exception is OperationCanceledException || exception is TimeoutException) { FabricErrorError fabricEventStoreSvcErrorMessage = new FabricErrorError( new FabricError { Code = NativeTypes.FABRIC_ERROR_CODE.FABRIC_E_TIMEOUT, Message = "Timeout" }); throw new HttpResponseException(fabricEventStoreSvcErrorMessage.ToHttpResponseMessage()); } else { var stringBuilder = new StringBuilder(); if (exception is AggregateException) { var aggregateException = (AggregateException)exception; foreach (var innerException in aggregateException.InnerExceptions) { stringBuilder.AppendFormat("{0} ,", innerException.Message).AppendLine(); } } else { stringBuilder.AppendFormat("{0}", exception.Message); } FabricErrorError fabricEventStoreSvcErrorMessage = new FabricErrorError( new FabricError { Message = stringBuilder.ToString(), Code = NativeTypes.FABRIC_ERROR_CODE.E_UNEXPECTED }); throw new HttpResponseException(fabricEventStoreSvcErrorMessage.ToHttpResponseMessage()); } } throw new HttpResponseException(HttpStatusCode.InternalServerError); }