protected void InvokeS3Post(PostObjectRequest publicrequest, AmazonServiceCallback callback, object state)
        {
            AsyncResult asyncResult = new AsyncResult(new DefaultRequest(publicrequest, "Amazon.S3"),
                                                      publicrequest, callback,
                                                      state, new S3Signer(), null);

            try
            {
                asyncResult.Metrics.StartEvent(Metric.ClientExecuteTime);
                asyncResult.Request.Endpoint = DetermineEndpoint(asyncResult.Request);
                if (Config.LogMetrics)
                {
                    asyncResult.Metrics.IsEnabled = true;
                    asyncResult.Metrics.AddProperty(Metric.ServiceName, asyncResult.Request.ServiceName);
                    asyncResult.Metrics.AddProperty(Metric.ServiceEndpoint, asyncResult.Request.Endpoint);
                    asyncResult.Metrics.AddProperty(Metric.MethodName, asyncResult.RequestName);
                    asyncResult.Metrics.AddProperty(Metric.AsyncCall, !asyncResult.CompletedSynchronously);
                }
                //ConfigureRequest(asyncResult);

                InvokeHelperForS3PostObject(asyncResult, publicrequest);
            }
            catch (Exception e)
            {
                AmazonLogging.LogException(AmazonLogging.AmazonLoggingLevel.Errors, "S3", e);
                asyncResult.IsCompleted = true;
                asyncResult.HandleException(e);
                return;
            }
            //return asyncResult;
        }
コード例 #2
0
 private static void Execute <T>(AsyncCall call, DynamoDBAsyncState <T> result)
 {
     try
     {
         result.Return = call();
         AmazonMainThreadDispatcher.ExecCallback <T>(result.Callback, new AmazonDynamoResult <T>((T)result.Return, null, result.State));
         return;
     }
     catch (Exception ex)
     {
         AmazonLogging.LogException(AmazonLogging.AmazonLoggingLevel.Errors, result.Operation, ex);
         AmazonMainThreadDispatcher.ExecCallback <T>(result.Callback, new AmazonDynamoResult <T>(default(T), ex, result.State));
         return;
     }
 }
        /// <summary>
        /// The HandleWWWErrorResponse differs significantly from the error handling doing in .NET sdk
        /// since the www.error string message is incomplete
        /// so this requires rewriting all responseunmarshallers.HandleErrorContext which is not part of this version
        /// hence exception thrown will always be of base type AmazonServiceException
        /// </summary>
        /// <returns>True if the error needs retry</returns>
        private bool HandleWWWErrorResponse(AsyncResult asyncResult)
        {
            WWWResponseData errorResponse = asyncResult.ResponseData;

            asyncResult.Metrics.AddProperty(Metric.Exception, errorResponse.Error);

            AmazonServiceException errorResponseException = null;

            errorResponseException = new AmazonServiceException(errorResponse.Error,
                                                                new WebException(errorResponse.Error));

            errorResponseException.UnityStatusCode = errorResponse.Error;
            try
            {
                errorResponseException.StatusCode = errorResponse.ErrorStatusCode;
            }
            catch (Exception e)
            {
                // Parsing exception
                AmazonLogging.LogException(AmazonLogging.AmazonLoggingLevel.Errors, asyncResult.Request.RequestName, e);
            }

            string curl = "curl " + (asyncResult.Request.HttpMethod == "GET" &&
                                     !HttpOverrideSupportedServices.Contains(asyncResult.Request.ServiceName) ?
                                     "-G " :  "-X POST ");

            foreach (string key in asyncResult.RequestData.Headers.Keys)
            {
                curl += " -H \"" + key + ": " + asyncResult.RequestData.Headers[key] + "\" ";
            }
            if (asyncResult.RequestData.Data != null)
            {
                curl += " -d '" + System.Text.Encoding.Default.GetString(asyncResult.RequestData.Data) + "' ";
            }

            curl += " " + asyncResult.RequestData.Url;
            Debug.LogError(curl);

            if (errorResponse.IsHeaderPresent(HeaderKeys.XAmzRequestIdHeader.ToUpper()))
            {
                errorResponseException.RequestId = errorResponse.GetHeaderValue(HeaderKeys.XAmzRequestIdHeader);
            }

            asyncResult.Exception = errorResponseException;

            // currently no retries are done
            return(false);
        }
コード例 #4
0
        private void RunSyncOperationAsync(int retry, Action <RunSyncOperationResponse> callback)
        {
            if (retry < 0)
            {
                callback(new RunSyncOperationResponse(false, null));
                return;
            }

            long lastSyncCount = _local.GetLastSyncCount(GetIdentityId(), _datasetName);

            // if dataset is deleted locally, push it to remote
            if (lastSyncCount == -1)
            {
#if DELETE_METHOD_SUPPORT
                _remote.DeleteDatasetAsync(_datasetName, delegate(AmazonCognitoResult result)
                {
                    if (result.Exception != null)
                    {
                        var e = result.Exception as DataStorageException;
                        AmazonLogging.LogError(AmazonLogging.AmazonLoggingLevel.Errors, "CognitoSyncManager", "OnSyncFailure" + e.Message);
                        this.FireSyncFailureEvent(e);
                        callback(new RunSyncOperationResponse(false, null));
                        return;
                    }

                    _local.PurgeDataset(GetIdentityId(), _datasetName);
                    AmazonLogging.Log(AmazonLogging.AmazonLoggingLevel.Verbose, "CognitoSyncManager", "OnSyncSuccess: dataset delete is pushed to remote");
                    this.FireSyncSuccessEvent(new List <Record>());
                    callback(new RunSyncOperationResponse(true, null));
                    return;
                }, null);
#endif
                // invalid scenario
                AmazonLogging.LogError(AmazonLogging.AmazonLoggingLevel.Critical, "CognitoSyncManager", "OnSyncFailure: DeleteDataset is an invalid operation");
                FireSyncFailureEvent(new DataStorageException("DeleteDataset is an invalid operation"));
                callback(new RunSyncOperationResponse(false, null));
                return;
            }

            // get latest modified records from remote
            AmazonLogging.Log(AmazonLogging.AmazonLoggingLevel.Verbose, "CognitoSyncManager", "get latest modified records since " + lastSyncCount);

            _remote.ListUpdatesAsync(_datasetName, lastSyncCount, delegate(AmazonCognitoResult listUpdatesResult)
            {
                RemoteDataStorage.DatasetUpdates datasetUpdates = null;
                if (listUpdatesResult == null || listUpdatesResult.Exception != null)
                {
                    var e = listUpdatesResult.Exception as DataStorageException;
                    AmazonLogging.LogException(AmazonLogging.AmazonLoggingLevel.Verbose, "CognitoSyncManager", e);
                    FireSyncFailureEvent(e);
                    callback(new RunSyncOperationResponse(false, listUpdatesResult.Exception));
                    return;
                }

                ListUpdatesResponse listUpdatesResponse = listUpdatesResult.Response as ListUpdatesResponse;
                datasetUpdates = listUpdatesResponse.DatasetUpdates;


                if (datasetUpdates.MergedDatasetNameList.Count != 0 && this.OnDatasetMerged != null)
                {
                    bool resume = this.OnDatasetMerged(this, datasetUpdates.MergedDatasetNameList);
                    if (resume)
                    {
                        this.RunSyncOperationAsync(--retry, callback);
                        return;
                    }
                    else
                    {
                        AmazonLogging.Log(AmazonLogging.AmazonLoggingLevel.Verbose, "CognitoSyncManager", "OnSyncFailure: Manual cancel");
                        FireSyncFailureEvent(new DataStorageException("Manual cancel"));
                        callback(new RunSyncOperationResponse(false, null));
                        return;
                    }
                }


                // if the dataset doesn't exist or is deleted, trigger onDelete
                if (lastSyncCount != 0 && !datasetUpdates.Exists ||
                    datasetUpdates.Deleted && this.OnDatasetDeleted != null)
                {
                    bool resume = this.OnDatasetDeleted(this);
                    if (resume)
                    {
                        // remove both records and metadata
                        _local.DeleteDataset(GetIdentityId(), _datasetName);
                        _local.PurgeDataset(GetIdentityId(), _datasetName);
                        AmazonLogging.Log(AmazonLogging.AmazonLoggingLevel.Verbose, "CognitoSyncManager", "OnSyncSuccess");
                        FireSyncSuccessEvent(new List <Record>());
                        callback(new RunSyncOperationResponse(true, null));
                        return;
                    }
                    else
                    {
                        AmazonLogging.Log(AmazonLogging.AmazonLoggingLevel.Verbose, "CognitoSyncManager", "OnSyncFailure");
                        FireSyncFailureEvent(new DataStorageException("Manual cancel"));
                        callback(new RunSyncOperationResponse(false, null));
                        return;
                    }
                }


                List <Record> remoteRecords = datasetUpdates.Records;
                if (remoteRecords.Count != 0)
                {
                    // if conflict, prompt developer/user with callback
                    List <SyncConflict> conflicts = new List <SyncConflict>();
                    List <Record> conflictRecords = new List <Record>();
                    foreach (Record remoteRecord in remoteRecords)
                    {
                        Record localRecord = _local.GetRecord(GetIdentityId(),
                                                              _datasetName,
                                                              remoteRecord.Key);
                        // only when local is changed and its value is different
                        if (localRecord != null && localRecord.Modified &&
                            !StringUtils.Equals(localRecord.Value, remoteRecord.Value))
                        {
                            conflicts.Add(new SyncConflict(remoteRecord, localRecord));
                            conflictRecords.Add(remoteRecord);
                        }
                    }
                    // retaining only non-conflict records
                    remoteRecords.RemoveAll(t => conflictRecords.Contains(t));

                    if (conflicts.Count > 0)
                    {
                        AmazonLogging.Log(AmazonLogging.AmazonLoggingLevel.Verbose, "CognitoSyncManager", String.Format("{0} records in conflict!", conflicts.Count));

                        bool syncConflictResult = false;
                        if (this.OnSyncConflict == null)
                        {
                            // delegate is not implemented so the conflict resolution is applied
                            syncConflictResult = this.DefaultConflictResolution(conflicts);
                        }
                        else
                        {
                            syncConflictResult = this.OnSyncConflict(this, conflicts);
                        }
                        if (!syncConflictResult)
                        {
                            AmazonLogging.Log(AmazonLogging.AmazonLoggingLevel.Verbose, "CognitoSyncManager", "User cancelled conflict resolution");
                            callback(new RunSyncOperationResponse(false, null));
                            return;
                        }
                    }

                    // save to local
                    if (remoteRecords.Count > 0)
                    {
                        AmazonLogging.Log(AmazonLogging.AmazonLoggingLevel.Verbose, "CognitoSyncManager", String.Format("save {0} records to local", remoteRecords.Count));
                        _local.PutRecords(GetIdentityId(), _datasetName, remoteRecords);
                    }


                    // new last sync count
                    AmazonLogging.Log(AmazonLogging.AmazonLoggingLevel.Verbose, "CognitoSyncManager", String.Format("updated sync count {0}", datasetUpdates.SyncCount));
                    _local.UpdateLastSyncCount(GetIdentityId(), _datasetName,
                                               datasetUpdates.SyncCount);
                }


                // push changes to remote
                List <Record> localChanges = this.GetModifiedRecords();
                if (localChanges.Count != 0)
                {
                    AmazonLogging.Log(AmazonLogging.AmazonLoggingLevel.Verbose, "CognitoSyncManager", String.Format("push {0} records to remote", localChanges.Count));

                    _remote.PutRecordsAsync(_datasetName, localChanges,
                                            datasetUpdates.SyncSessionToken, delegate(AmazonCognitoResult putRecordsResult)
                    {
                        if (putRecordsResult.Exception != null)
                        {
                            if (putRecordsResult.Exception.GetType() == typeof(DataConflictException))
                            {
                                AmazonLogging.LogError(AmazonLogging.AmazonLoggingLevel.Warnings, "CognitoSyncManager", "Conflicts detected when pushing changes to remote: " + putRecordsResult.Exception.Message);
                                this.RunSyncOperationAsync(--retry, callback);
                                return;
                            }
                            else if (putRecordsResult.Exception.GetType() == typeof(DataStorageException))
                            {
                                AmazonLogging.LogError(AmazonLogging.AmazonLoggingLevel.Verbose, "CognitoSyncManager", "OnSyncFailure" + putRecordsResult.Exception.Message);
                                FireSyncFailureEvent(putRecordsResult.Exception);
                                callback(new RunSyncOperationResponse(false, null));
                                return;
                            }
                        }
                        PutRecordsResponse putRecordsResponse = putRecordsResult.Response as PutRecordsResponse;
                        List <Record> result = putRecordsResponse.UpdatedRecords;

                        // update local meta data
                        _local.PutRecords(GetIdentityId(), _datasetName, result);

                        // verify the server sync count is increased exactly by one, aka no
                        // other updates were made during this update.
                        long newSyncCount = 0;
                        foreach (Record record in result)
                        {
                            newSyncCount = newSyncCount < record.SyncCount
                                ? record.SyncCount
                                    : newSyncCount;
                        }
                        if (newSyncCount == lastSyncCount + 1)
                        {
                            AmazonLogging.Log(AmazonLogging.AmazonLoggingLevel.Info, "DefaultDataset",
                                              String.Format("updated sync count %d", newSyncCount));
                            _local.UpdateLastSyncCount(GetIdentityId(), _datasetName,
                                                       newSyncCount);
                        }

                        AmazonLogging.Log(AmazonLogging.AmazonLoggingLevel.Verbose, "CognitoSyncManager", "OnSyncSuccess");
                        // call back
                        FireSyncSuccessEvent(remoteRecords);
                        callback(new RunSyncOperationResponse(true, null));
                        return;
                    }, null);
                    return;
                }


                AmazonLogging.Log(AmazonLogging.AmazonLoggingLevel.Verbose, "CognitoSyncManager", "OnSyncSuccess");
                // call back
                FireSyncSuccessEvent(remoteRecords);
                callback(new RunSyncOperationResponse(true, null));
                return;
            }, null);
        }
        /// <summary>
        /// Invoked as a callback from the AmazonMainThreadDispatcher
        /// Processes the http response
        /// </summary>
        /// <param name="state">State is expected to be AsyncResult</param>
        private void ProcessHttpResponse(object state)
        {
            AsyncResult asyncResult = null;

            try
            {
                asyncResult = state as AsyncResult;
                AmazonWebServiceResponse response = null;
                UnmarshallerContext      context  = null;

                var responseData = asyncResult.ResponseData;

                if (!String.IsNullOrEmpty(responseData.Error))
                {
                    AmazonLogging.LogError(AmazonLogging.AmazonLoggingLevel.Critical,
                                           asyncResult.Request.ServiceName, responseData.Error);

                    if (HandleWWWErrorResponse(asyncResult))
                    {
                        if (++asyncResult.RetriesAttempt >= 3)
                        {
                            if (asyncResult.Exception == null)
                            {
                                asyncResult.Exception = new AmazonServiceException("Maximum retries attempts completed");
                            }
                            // maxretries
                            asyncResult.IsCompleted = true;
                            AmazonLogging.LogException(AmazonLogging.AmazonLoggingLevel.Errors,
                                                       asyncResult.Request.ServiceName, asyncResult.Exception);
                            asyncResult.HandleException(asyncResult.Exception);
                            return;
                        }
                        else
                        {
                            // retry here
                            InvokeHelper(asyncResult);
                            return;
                        }
                    }
                    else
                    {
                        // non-retriable error
                        asyncResult.IsCompleted = true;
                        asyncResult.HandleException(asyncResult.Exception);
                        return;
                    }
                }
                else
                {
                    using (asyncResult.Metrics.StartEvent(Metric.ResponseProcessingTime))
                    {
                        var unmarshaller = asyncResult.Unmarshaller;
                        LogResponse(asyncResult.Metrics, asyncResult.Request, HttpStatusCode.Accepted);

                        context = unmarshaller.CreateContext(responseData,
                                                             this.SupportResponseLogging &&
                                                             (Config.LogResponse || Config.ReadEntireResponse),
                                                             responseData.OpenResponse(),
                                                             asyncResult.Metrics);
                        try
                        {
                            using (asyncResult.Metrics.StartEvent(Metric.ResponseUnmarshallTime))
                            {
                                response = unmarshaller.Unmarshall(context);
                                if (responseData.IsHeaderPresent("STATUS"))
                                {
                                    response.HttpStatusCode = responseData.StatusCode;
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            //unmarshalling exception
                            asyncResult.IsCompleted = true;
                            asyncResult.HandleException(e);
                            return;
                        }
                        context.ValidateCRC32IfAvailable();
                        if (responseData.IsHeaderPresent(HeaderKeys.ContentLengthHeader.ToUpper()))
                        {
                            response.ContentLength = Convert.ToInt32(responseData.GetHeaderValue(HeaderKeys.ContentLengthHeader.ToUpper()));
                        }
                        else
                        {
                            AmazonLogging.Log(AmazonLogging.AmazonLoggingLevel.Warnings, asyncResult.Request.ServiceName, "cannot find CONTENT-LENGTH header");
                        }

                        asyncResult.ServiceResult.Response = response;

                        if (response.ResponseMetadata != null)
                        {
                            asyncResult.Metrics.AddProperty(Metric.AWSRequestID, response.ResponseMetadata.RequestId);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                AmazonLogging.LogException(AmazonLogging.AmazonLoggingLevel.Errors, asyncResult.Request.ServiceName, e);
                asyncResult.HandleException(e);
            }

            asyncResult.IsCompleted = true;
            asyncResult.InvokeCallback();
            return;
        }
        /// <summary>
        /// Perform signing, setup WWWRequestData with headers, binary data(for POST request)
        /// and enqueues to the RequestQueue for Main thread
        /// </summary>
        /// <param name="asyncResult"></param>
        private void ProcessHttpRequest(AsyncResult asyncResult)
        {
            try
            {
                // prepare request
                IRequest wrappedRequest = asyncResult.Request;

                WWWRequestData requestData = new WWWRequestData();
                if (HttpOverrideSupportedServices.Contains(asyncResult.Request.ServiceName))
                {
                    asyncResult.Request.Headers.Add("X-HTTP-Method-Override", asyncResult.Request.HttpMethod);

                    if (asyncResult.Request.HttpMethod == "GET")
                    {
                        string emptyString = "{}";
                        asyncResult.Request.ContentStream = new MemoryStream(Encoding.UTF8.GetBytes(emptyString));
                        requestData.Data = Encoding.Default.GetBytes(emptyString);
                    }
                }

#if UNITY_WEBPLAYER
                wrappedRequest.Headers.Remove("User-Agent");
                wrappedRequest.Headers.Remove("Host");
#endif

                SignRequest(asyncResult);

                if (asyncResult.RetriesAttempt > 0)
                {
                    HandleRetry(asyncResult);
                }


                requestData.Url = ComposeUrl(wrappedRequest, wrappedRequest.Endpoint).ToString();

                if (!wrappedRequest.UseQueryString && !(wrappedRequest.HttpMethod.Equals("GET", StringComparison.OrdinalIgnoreCase)))
                {
                    if (wrappedRequest.ContentStream != null)
                    {
                        if (wrappedRequest.OriginalRequest.IncludeSHA256Header &&
                            !wrappedRequest.Headers.ContainsKey(HeaderKeys.XAmzContentSha256Header))
                        {
                            requestData.Headers.Add(HeaderKeys.XAmzContentSha256Header, wrappedRequest.ComputeContentStreamHash());
                        }
                    }
                }

                AddHeaders2(requestData, wrappedRequest.Headers);

                if (asyncResult.Unmarshaller is JsonResponseUnmarshaller)
                {
                    requestData.Headers.Add(HeaderKeys.AcceptHeader, "application/json");
                }

                if (!asyncResult.Request.HttpMethod.Equals("GET", StringComparison.OrdinalIgnoreCase))
                {
                    if (asyncResult.Request.Content != null && asyncResult.Request.Content.Length > 0)
                    {
                        requestData.Data = asyncResult.Request.Content;
                    }
                    else if (asyncResult.Request.ContentStream != null && asyncResult.Request.ContentStream.Length > 0)
                    {
                        using (asyncResult.Request.ContentStream)
                        {
                            requestData.Data = StreamToByteArray.Convert(asyncResult.Request.ContentStream, this.Config.BufferSize);

                            StreamTransferProgressArgs args = new StreamTransferProgressArgs(asyncResult.Request.ContentStream.Length, asyncResult.Request.ContentStream.Length, asyncResult.Request.ContentStream.Length);
                            if (asyncResult.Request.OriginalRequest.StreamUploadProgressCallback != null)
                            {
                                asyncResult.Request.OriginalRequest.StreamUploadProgressCallback(this, args);
                            }

                            if (args.PercentDone >= 100)
                            {
                                asyncResult.Request.OriginalRequest.StreamUploadProgressCallback = null;
                            }
                        }
                    }
                    else if (asyncResult.Request.Parameters != null && asyncResult.Request.Parameters.Count > 0)
                    {
                        requestData.Data = GetRequestData(asyncResult.Request);
                    }
                }

                asyncResult.RequestData = requestData;

                // setting up callback for response handling
                asyncResult.WaitCallback = this.ProcessHttpResponse;

                // switching to main thread to make the network call
                AmazonMainThreadDispatcher.QueueAWSRequest(asyncResult);
            }
            catch (Exception e)
            {
                AmazonLogging.LogException(AmazonLogging.AmazonLoggingLevel.Errors, asyncResult.Request.ServiceName, e);

                asyncResult.IsCompleted = true;
                asyncResult.HandleException(e);
                return;
            }
        }