Пример #1
0
        private void Run()
        {
            IsRunning = true;

            var clientCopy = Client;

            if (clientCopy == null)
            {
                // This is a race condition that can be reproduced by calling cbpuller.start() and cbpuller.stop()
                // directly afterwards.  What happens is that by the time the Changetracker thread fires up,
                // the cbpuller has already set this.client to null.  See issue #109
                Log.To.ChangeTracker.W(Tag, "ChangeTracker run() loop aborting because client == null");
                return;
            }

            if (tokenSource.IsCancellationRequested)
            {
                tokenSource.Dispose();
                tokenSource = new CancellationTokenSource();
            }

            if (Request != null)
            {
                Request.Dispose();
                Request = null;
            }

            var url = ChangesFeedUrl;

            if (_usePost)
            {
                Request = new HttpRequestMessage(HttpMethod.Post, url);
                var body = GetChangesFeedPostBody().ToArray();
                Request.Content = new ByteArrayContent(body);
                Request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
            }
            else
            {
                Request = new HttpRequestMessage(HttpMethod.Get, url);
            }
            AddRequestHeaders(Request);

            Log.To.ChangeTracker.V(Tag, "Making request to {0}", new SecureLogUri(url));
            if (tokenSource.Token.IsCancellationRequested)
            {
                return;
            }

            try {
                changesFeedRequestTokenSource = CancellationTokenSource.CreateLinkedTokenSource(tokenSource.Token);
                _httpClient.Authenticator     = Authenticator;
                var info = _httpClient.SendAsync(
                    Request,
                    HttpCompletionOption.ResponseHeadersRead,
                    changesFeedRequestTokenSource.Token
                    );

                info.ContinueWith(ChangeFeedResponseHandler, changesFeedRequestTokenSource.Token,
                                  TaskContinuationOptions.LongRunning,
                                  TaskScheduler.Default);
            }
            catch (Exception e)
            {
                RetryOrStopIfNecessary(e);
            }
        }
Пример #2
0
        private Task ExecuteRequest(CouchbaseLiteHttpClient httpClient, HttpRequestMessage request)
        {
            object              fullBody = null;
            Exception           error    = null;
            HttpResponseMessage response = null;

            if (_tokenSource.IsCancellationRequested)
            {
                RespondWithResult(fullBody, new Exception(string.Format("{0}: Request {1} has been aborted", this, request)), response);
                var tcs = new TaskCompletionSource <bool>();
                tcs.SetCanceled();
                return(tcs.Task);
            }

            request.Headers.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip"));
            request.Headers.Add("X-Accept-Part-Encoding", "gzip");

            Log.To.Sync.V(Tag, "Sending request: {0}", request);
            var requestTokenSource = CancellationTokenSource.CreateLinkedTokenSource(_tokenSource.Token);

            httpClient.Authenticator = Authenticator;
            return(httpClient.SendAsync(request, requestTokenSource.Token).ContinueWith(t =>
            {
                requestTokenSource.Dispose();
                try {
                    response = t.Result;
                } catch (Exception e) {
                    var err = Misc.Flatten(e).First();
                    Log.To.Sync.E(Tag, "Unhandled exception while getting bulk documents", err);
                    error = err;
                    RespondWithResult(fullBody, err, response);
                    return;
                }

                try {
                    if (response == null)
                    {
                        Log.To.Sync.I(Tag, "Didn't get response for {0}", request);

                        error = new HttpRequestException();
                        RespondWithResult(fullBody, error, response);
                    }
                    else if (!response.IsSuccessStatusCode)
                    {
                        HttpStatusCode status = response.StatusCode;

                        Log.To.Sync.I(Tag, "Got error status: {0} for {1}.  Reason: {2}", status.GetStatusCode(), request, response.ReasonPhrase);
                        error = new HttpResponseException(status);

                        RespondWithResult(fullBody, error, response);
                    }
                    else
                    {
                        Log.To.Sync.D(Tag, "Processing response: {0}", response);
                        var entity = response.Content;
                        var contentTypeHeader = entity.Headers.ContentType;
                        Stream inputStream = null;
                        if (contentTypeHeader != null && contentTypeHeader.ToString().Contains("multipart/"))
                        {
                            Log.To.Sync.D(Tag, "contentTypeHeader = {0}", contentTypeHeader.ToString());
                            try {
                                _topReader = new MultipartReader(contentTypeHeader.ToString(), this);
                                inputStream = entity.ReadAsStreamAsync().Result;
                                const int bufLen = 1024;
                                var buffer = new byte[bufLen];
                                var numBytesRead = 0;
                                while ((numBytesRead = inputStream.Read(buffer, 0, bufLen)) > 0)
                                {
                                    if (numBytesRead != bufLen)
                                    {
                                        var bufferToAppend = new Couchbase.Lite.Util.ArraySegment <byte>(buffer, 0, numBytesRead).ToArray();
                                        _topReader.AppendData(bufferToAppend);
                                    }
                                    else
                                    {
                                        _topReader.AppendData(buffer);
                                    }
                                }

                                RespondWithResult(fullBody, error, response);
                            } finally {
                                try {
                                    inputStream.Close();
                                } catch (IOException) { }
                            }
                        }
                        else
                        {
                            Log.To.Sync.D(Tag, "contentTypeHeader is not multipart = {0}", contentTypeHeader.ToString());
                            if (entity != null)
                            {
                                try {
                                    inputStream = entity.ReadAsStreamAsync().Result;
                                    fullBody = Manager.GetObjectMapper().ReadValue <object>(inputStream);
                                    RespondWithResult(fullBody, error, response);
                                } finally {
                                    try {
                                        inputStream.Close();
                                    } catch (IOException) {  }
                                }
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    var err = (e is AggregateException) ? e.InnerException : e;
                    Log.To.Sync.E(Tag, "Exception while processing bulk download response", err);
                    error = err;
                    RespondWithResult(fullBody, err, response);
                }
            }));
        }
        private Task ExecuteRequest(CouchbaseLiteHttpClient httpClient, HttpRequestMessage request)
        {
            object fullBody = null;
            Exception error = null;
            HttpResponseMessage response = null;
            if (_tokenSource.IsCancellationRequested) {
                RespondWithResult(fullBody, new Exception(string.Format("{0}: Request {1} has been aborted", this, request)), response);
                var tcs = new TaskCompletionSource<bool>();
                tcs.SetCanceled();
                return tcs.Task;
            }
                
            request.Headers.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip"));
            request.Headers.Add("X-Accept-Part-Encoding", "gzip");

            Log.To.Sync.V(Tag, "Sending request: {0}", request);
            var requestTokenSource = CancellationTokenSource.CreateLinkedTokenSource(_tokenSource.Token);
            httpClient.Authenticator = Authenticator;
            return httpClient.SendAsync(request, requestTokenSource.Token).ContinueWith(t =>
            {
                requestTokenSource.Dispose();
                try {
                    response = t.Result;
                } catch(Exception e) {
                    var err = Misc.Flatten(e).First();
                    Log.To.Sync.E(Tag, "Unhandled exception while getting bulk documents", err);
                    error = err;
                    RespondWithResult(fullBody, err, response);
                    return;
                }

                try {
                    if (response == null) {
                        Log.To.Sync.I(Tag, "Didn't get response for {0}", request);

                        error = new HttpRequestException();
                        RespondWithResult(fullBody, error, response);
                    } else if (!response.IsSuccessStatusCode)  {
                        HttpStatusCode status = response.StatusCode;

                        Log.To.Sync.I(Tag, "Got error status: {0} for {1}.  Reason: {2}", status.GetStatusCode(), request, response.ReasonPhrase);
                        error = new HttpResponseException(status);

                        RespondWithResult(fullBody, error, response);
                    } else {
                        Log.To.Sync.D(Tag, "Processing response: {0}", response);
                        var entity = response.Content;
                        var contentTypeHeader = entity.Headers.ContentType;
                        Stream inputStream = null;
                        if (contentTypeHeader != null && contentTypeHeader.ToString().Contains("multipart/"))
                        {
                            Log.To.Sync.D(Tag, "contentTypeHeader = {0}", contentTypeHeader.ToString());
                            try {
                                _topReader = new MultipartReader(contentTypeHeader.ToString(), this);
                                inputStream = entity.ReadAsStreamAsync().Result;
                                const int bufLen = 1024;
                                var buffer = new byte[bufLen];
                                var numBytesRead = 0;
                                while ((numBytesRead = inputStream.Read(buffer, 0, bufLen)) > 0) {
                                    if (numBytesRead != bufLen) {
                                        var bufferToAppend = new Couchbase.Lite.Util.ArraySegment<byte>(buffer, 0, numBytesRead).ToArray();
                                        _topReader.AppendData(bufferToAppend);
                                    } else {
                                        _topReader.AppendData(buffer);
                                    }
                                }

                                RespondWithResult(fullBody, error, response);
                            } finally {
                                try { 
                                    inputStream.Close();
                                } catch (IOException) { }
                            }
                        } else {
                            Log.To.Sync.D(Tag, "contentTypeHeader is not multipart = {0}", contentTypeHeader.ToString());
                            if (entity != null) {
                                try {
                                    inputStream = entity.ReadAsStreamAsync().Result;
                                    fullBody = Manager.GetObjectMapper().ReadValue<object>(inputStream);
                                    RespondWithResult(fullBody, error, response);
                                } finally {
                                    try {
                                        inputStream.Close();
                                    } catch (IOException) {  }
                                }
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    var err = (e is AggregateException) ? e.InnerException : e;
                    Log.To.Sync.E(Tag, "Exception while processing bulk download response", err);
                    error = err;
                    RespondWithResult(fullBody, err, response);
                }
            });
        }