public static ICouchbaseResponseState GetChangesPost(ICouchbaseListenerContext context)
        {
            DBMonitorCouchbaseResponseState responseState = new DBMonitorCouchbaseResponseState();

            var responseObject = PerformLogicWithDatabase(context, true, db =>
            {
                var response = context.CreateResponse();
                responseState.Response = response;
                var body = context.BodyAs<Dictionary<string, object>>();
                ProcessBody(body);
                if (body.GetCast<ChangesFeedMode>("feed") < ChangesFeedMode.Continuous) {
                    if(context.CacheWithEtag(db.GetLastSequenceNumber().ToString())) {
                        response.InternalStatus = StatusCode.NotModified;
                        return response;
                    }
                }

                var options = ChangesOptions.Default;
                responseState.Db = db;
                responseState.ContentOptions = body.GetCast<DocumentContentOptions>("content_options");
                responseState.ChangesFeedMode = body.GetCast<ChangesFeedMode>("feed");
                responseState.ChangesIncludeDocs = body.GetCast<bool>("include_docs");
                options.IncludeDocs = responseState.ChangesIncludeDocs;
                responseState.ChangesIncludeConflicts = body.GetCast<string>("style") == "all_docs";
                options.IncludeConflicts = responseState.ChangesIncludeConflicts;
                options.ContentOptions = responseState.ContentOptions;
                options.SortBySequence = !options.IncludeConflicts;
                options.Limit = body.GetCast<int>("limit", options.Limit);
                int since = body.GetCast<int>("since");

                string filterName = body.GetCast<string>("filter");
                if(filterName != null) {
                    Status status = new Status();
                    responseState.ChangesFilter = db.GetFilter(filterName, status);
                    if(responseState.ChangesFilter == null) {
                        return context.CreateResponse(status.Code);
                    }

                    responseState.FilterParams = context.GetQueryParams();
                }


                RevisionList changes = db.ChangesSince(since, options, responseState.ChangesFilter, responseState.FilterParams);
                if((responseState.ChangesFeedMode >= ChangesFeedMode.Continuous) || 
                    (responseState.ChangesFeedMode == ChangesFeedMode.LongPoll && changes.Count == 0)) {
                    // Response is going to stay open (continuous, or hanging GET):
                    response.Chunked = true;
                    if(responseState.ChangesFeedMode == ChangesFeedMode.EventSource) {
                        response["Content-Type"] = "text/event-stream; charset=utf-8";
                    }

                    if(responseState.ChangesFeedMode >= ChangesFeedMode.Continuous) {
                        response.WriteHeaders();
                        foreach(var rev in changes) {
                            response.SendContinuousLine(ChangesDictForRev(rev, responseState), context.ChangesFeedMode);
                        }
                    }

                    responseState.SubscribeToDatabase(db);
                    int heartbeat = body.GetCast<int>("heartbeat", Int32.MinValue);
                    if(heartbeat != Int32.MinValue) {
                        if(heartbeat <= 0) {
                            responseState.IsAsync = false;
                            return context.CreateResponse(StatusCode.BadParam);
                        }

                        heartbeat = Math.Max(heartbeat, (int)MinHeartbeat.TotalMilliseconds);
                        string heartbeatResponse = context.ChangesFeedMode == ChangesFeedMode.EventSource ? "\n\n" : "\r\n";
                        responseState.StartHeartbeat(heartbeatResponse, TimeSpan.FromMilliseconds(heartbeat));
                    }

                    return context.CreateResponse();
                } else {
                    if(responseState.ChangesIncludeConflicts) {
                        response.JsonBody = new Body(ResponseBodyForChanges(changes, since, options.Limit, responseState));
                    } else {
                        response.JsonBody = new Body(ResponseBodyForChanges(changes, since, responseState));
                    }

                    return response;
                }
            });

            responseState.Response = responseObject;
            return responseState;
        }
        /// <summary>
        /// Returns a sorted list of changes made to documents in the database, in time order of application.
        /// </summary>
        /// <returns>The response state for further HTTP processing</returns>
        /// <param name="context">The context of the Couchbase Lite HTTP request</param>
        /// <remarks>
        /// http://docs.couchdb.org/en/latest/api/database/changes.html#get--db-_changes
        /// </remarks>
        public static ICouchbaseResponseState GetChanges(ICouchbaseListenerContext context)
        {
            DBMonitorCouchbaseResponseState responseState = new DBMonitorCouchbaseResponseState();

            var responseObject = PerformLogicWithDatabase(context, true, db =>
            {
                var response = context.CreateResponse();
                responseState.Response = response;
                if (context.ChangesFeedMode < ChangesFeedMode.Continuous) {
                    if(context.CacheWithEtag(db.GetLastSequenceNumber().ToString())) {
                        response.InternalStatus = StatusCode.NotModified;
                        return response;
                    }
                }
                    
                var options = ChangesOptions.Default;
                responseState.Db = db;
                responseState.ContentOptions = context.ContentOptions;
                responseState.ChangesFeedMode = context.ChangesFeedMode;
                responseState.ChangesIncludeDocs = context.GetQueryParam<bool>("include_docs", bool.TryParse, false);
                options.IncludeDocs = responseState.ChangesIncludeDocs;
                responseState.ChangesIncludeConflicts = context.GetQueryParam("style") == "all_docs";
                options.IncludeConflicts = responseState.ChangesIncludeConflicts;
                options.ContentOptions = context.ContentOptions;
                options.SortBySequence = !options.IncludeConflicts;
                options.Limit = context.GetQueryParam<int>("limit", int.TryParse, options.Limit);
                int since = context.GetQueryParam<int>("since", int.TryParse, 0);

                string filterName = context.GetQueryParam("filter");
                if(filterName != null) {
                    Status status = new Status();
                    responseState.ChangesFilter = db.GetFilter(filterName, status);
                    if(responseState.ChangesFilter == null) {
                        return context.CreateResponse(status.Code);
                    }

                    responseState.FilterParams = context.GetQueryParams();
                }


                RevisionList changes = db.ChangesSince(since, options, responseState.ChangesFilter, responseState.FilterParams);
                if((context.ChangesFeedMode >= ChangesFeedMode.Continuous) || 
                    (context.ChangesFeedMode == ChangesFeedMode.LongPoll && changes.Count == 0)) {
                    // Response is going to stay open (continuous, or hanging GET):
                    response.Chunked = true;
                    if(context.ChangesFeedMode == ChangesFeedMode.EventSource) {
                        response["Content-Type"] = "text/event-stream; charset=utf-8";
                    }

                    if(context.ChangesFeedMode >= ChangesFeedMode.Continuous) {
                        response.WriteHeaders();
                        foreach(var rev in changes) {
                            var success = response.SendContinuousLine(ChangesDictForRev(rev, responseState), context.ChangesFeedMode);
                            if(!success) {
                                return context.CreateResponse(StatusCode.BadRequest);
                            }
                        }
                    }

                    responseState.SubscribeToDatabase(db);
                    string heartbeatParam = context.GetQueryParam("heartbeat");
                    if(heartbeatParam != null) {
                        int heartbeat;
                        if(!int.TryParse(heartbeatParam, out heartbeat) || heartbeat <= 0) {
                            responseState.IsAsync = false;
                            return context.CreateResponse(StatusCode.BadParam);
                        }

                        var heartbeatSpan = TimeSpan.FromMilliseconds(heartbeat);
                        if(heartbeatSpan < MinHeartbeat) {
                            heartbeatSpan = MinHeartbeat;
                        }

                        string heartbeatResponse = context.ChangesFeedMode == ChangesFeedMode.EventSource ? "\n\n" : "\r\n";
                        responseState.StartHeartbeat(heartbeatResponse, heartbeatSpan);
                    }

                    return response;
                } else {
                    if(responseState.ChangesIncludeConflicts) {
                        response.JsonBody = new Body(ResponseBodyForChanges(changes, since, options.Limit, responseState));
                    } else {
                        response.JsonBody = new Body(ResponseBodyForChanges(changes, since, responseState));
                    }

                    return response;
                }
            });

            responseState.Response = responseObject;
            return responseState;
        }
示例#3
0
        public static ICouchbaseResponseState GetChangesPost(ICouchbaseListenerContext context)
        {
            DBMonitorCouchbaseResponseState responseState = new DBMonitorCouchbaseResponseState();

            var responseObject = PerformLogicWithDatabase(context, true, db =>
            {
                var response           = context.CreateResponse();
                responseState.Response = response;
                var body = context.BodyAs <Dictionary <string, object> >();
                ProcessBody(body);
                if (body.GetCast <ChangesFeedMode>("feed") < ChangesFeedMode.Continuous)
                {
                    if (context.CacheWithEtag(db.GetLastSequenceNumber().ToString()))
                    {
                        response.InternalStatus = StatusCode.NotModified;
                        return(response);
                    }
                }

                var options                           = ChangesOptions.Default;
                responseState.Db                      = db;
                responseState.ContentOptions          = body.GetCast <DocumentContentOptions>("content_options");
                responseState.ChangesFeedMode         = body.GetCast <ChangesFeedMode>("feed");
                responseState.ChangesIncludeDocs      = body.GetCast <bool>("include_docs");
                options.IncludeDocs                   = responseState.ChangesIncludeDocs;
                responseState.ChangesIncludeConflicts = body.GetCast <string>("style") == "all_docs";
                options.IncludeConflicts              = responseState.ChangesIncludeConflicts;
                options.ContentOptions                = responseState.ContentOptions;
                options.SortBySequence                = !options.IncludeConflicts;
                options.Limit                         = body.GetCast <int>("limit", options.Limit);
                int since = body.GetCast <int>("since");

                string filterName = body.GetCast <string>("filter");
                if (filterName != null)
                {
                    Status status = new Status();
                    responseState.ChangesFilter = db.GetFilter(filterName, status);
                    if (responseState.ChangesFilter == null)
                    {
                        return(context.CreateResponse(status.Code));
                    }

                    responseState.FilterParams = context.GetQueryParams();
                }


                if (responseState.ChangesFeedMode >= ChangesFeedMode.LongPoll)
                {
                    // Response is going to stay open (continuous, or hanging GET):
                    response.Chunked = true;
                    if (responseState.ChangesFeedMode == ChangesFeedMode.EventSource)
                    {
                        response["Content-Type"] = "text/event-stream; charset=utf-8";
                    }

                    response.WriteHeaders();
                    if (responseState.SubscribeToDatabase(db, since, options))
                    {
                        int heartbeat = body.GetCast <int>("heartbeat", Int32.MinValue);
                        if (heartbeat != Int32.MinValue)
                        {
                            if (heartbeat <= 0)
                            {
                                responseState.IsAsync = false;
                                return(context.CreateResponse(StatusCode.BadParam));
                            }

                            heartbeat = Math.Max(heartbeat, (int)MinHeartbeat.TotalMilliseconds);
                            string heartbeatResponse = context.ChangesFeedMode == ChangesFeedMode.EventSource ? "\n\n" : "\r\n";
                            responseState.StartHeartbeat(heartbeatResponse, TimeSpan.FromMilliseconds(heartbeat));
                        }
                    }

                    return(responseState.Response);
                }
                else
                {
                    var changes      = db.ChangesSinceStreaming(since, options, responseState.ChangesFilter, responseState.FilterParams);
                    response.Chunked = true;
                    response.Headers["Content-Type"] = "application/json";
                    response.WriteBodyCallback       = WriteChangesBodyJson;
                    if (responseState.ChangesIncludeConflicts)
                    {
                        response.WriteBodyContext = new WriteChangesContext {
                            IncludeConflicts = true,
                            Since            = since,
                            Limit            = options.Limit,
                            Changes          = changes,
                            ResponseState    = responseState
                        };
                    }
                    else
                    {
                        response.WriteBodyContext = new WriteChangesContext {
                            Since         = since,
                            Changes       = changes,
                            ResponseState = responseState
                        };
                    }

                    return(response);
                }
            });

            responseState.Response = responseObject;
            return(responseState);
        }
示例#4
0
        /// <summary>
        /// Returns a sorted list of changes made to documents in the database, in time order of application.
        /// </summary>
        /// <returns>The response state for further HTTP processing</returns>
        /// <param name="context">The context of the Couchbase Lite HTTP request</param>
        /// <remarks>
        /// http://docs.couchdb.org/en/latest/api/database/changes.html#get--db-_changes
        /// <remarks>
        public static ICouchbaseResponseState GetChanges(ICouchbaseListenerContext context)
        {
            DBMonitorCouchbaseResponseState responseState = new DBMonitorCouchbaseResponseState();

            var responseObject = PerformLogicWithDatabase(context, true, db =>
            {
                var response           = context.CreateResponse();
                responseState.Response = response;
                if (context.ChangesFeedMode < ChangesFeedMode.Continuous)
                {
                    if (context.CacheWithEtag(db.LastSequenceNumber.ToString()))
                    {
                        response.InternalStatus = StatusCode.NotModified;
                        return(response);
                    }
                }

                var options                           = ChangesOptions.Default;
                responseState.Db                      = db;
                responseState.ContentOptions          = context.ContentOptions;
                responseState.ChangesFeedMode         = context.ChangesFeedMode;
                responseState.ChangesIncludeDocs      = context.GetQueryParam <bool>("include_docs", bool.TryParse, false);
                options.IncludeDocs                   = responseState.ChangesIncludeDocs;
                responseState.ChangesIncludeConflicts = context.GetQueryParam("style") == "all_docs";
                options.IncludeConflicts              = responseState.ChangesIncludeConflicts;
                options.ContentOptions                = context.ContentOptions;
                options.SortBySequence                = !options.IncludeConflicts;
                options.Limit                         = context.GetQueryParam <int>("limit", int.TryParse, options.Limit);
                int since = context.GetQueryParam <int>("since", int.TryParse, 0);

                string filterName = context.GetQueryParam("filter");
                if (filterName != null)
                {
                    Status status = new Status();
                    responseState.ChangesFilter = db.GetFilter(filterName, status);
                    if (responseState.ChangesFilter == null)
                    {
                        return(context.CreateResponse(status.Code));
                    }

                    responseState.FilterParams = context.GetQueryParams();
                }


                RevisionList changes = db.ChangesSince(since, options, responseState.ChangesFilter, responseState.FilterParams);
                if ((context.ChangesFeedMode >= ChangesFeedMode.Continuous) ||
                    (context.ChangesFeedMode == ChangesFeedMode.LongPoll && changes.Count == 0))
                {
                    // Response is going to stay open (continuous, or hanging GET):
                    response.Chunked = true;
                    if (context.ChangesFeedMode == ChangesFeedMode.EventSource)
                    {
                        response["Content-Type"] = "text/event-stream; charset=utf-8";
                    }

                    if (context.ChangesFeedMode >= ChangesFeedMode.Continuous)
                    {
                        response.WriteHeaders();
                        foreach (var rev in changes)
                        {
                            response.SendContinuousLine(ChangesDictForRev(rev, responseState), context.ChangesFeedMode);
                        }
                    }

                    responseState.SubscribeToDatabase(db);
                    string heartbeatParam = context.GetQueryParam("heartbeat");
                    if (heartbeatParam != null)
                    {
                        int heartbeat;
                        if (!int.TryParse(heartbeatParam, out heartbeat) || heartbeat <= 0)
                        {
                            responseState.IsAsync = false;
                            return(context.CreateResponse(StatusCode.BadParam));
                        }

                        heartbeat = Math.Min(heartbeat, MIN_HEARTBEAT);
                        string heartbeatResponse = context.ChangesFeedMode == ChangesFeedMode.EventSource ? "\n\n" : "\r\n";
                        responseState.StartHeartbeat(heartbeatResponse, heartbeat);
                    }

                    return(context.CreateResponse());
                }
                else
                {
                    if (responseState.ChangesIncludeConflicts)
                    {
                        response.JsonBody = new Body(ResponseBodyForChanges(changes, since, options.Limit, responseState));
                    }
                    else
                    {
                        response.JsonBody = new Body(ResponseBodyForChanges(changes, since, responseState));
                    }

                    return(response);
                }
            });

            responseState.Response = responseObject;
            return(responseState);
        }
示例#5
0
        /// <summary>
        /// Returns a sorted list of changes made to documents in the database, in time order of application.
        /// </summary>
        /// <returns>The response state for further HTTP processing</returns>
        /// <param name="context">The context of the Couchbase Lite HTTP request</param>
        /// <remarks>
        /// http://docs.couchdb.org/en/latest/api/database/changes.html#get--db-_changes
        /// </remarks>
        public static ICouchbaseResponseState GetChanges(ICouchbaseListenerContext context)
        {
            DBMonitorCouchbaseResponseState responseState = new DBMonitorCouchbaseResponseState();

            var responseObject = PerformLogicWithDatabase(context, true, db =>
            {
                var response           = context.CreateResponse();
                responseState.Response = response;
                if (context.ChangesFeedMode < ChangesFeedMode.Continuous)
                {
                    if (context.CacheWithEtag(db.GetLastSequenceNumber().ToString()))
                    {
                        response.InternalStatus = StatusCode.NotModified;
                        return(response);
                    }
                }

                var options                           = ChangesOptions.Default;
                responseState.Db                      = db;
                responseState.ContentOptions          = context.ContentOptions;
                responseState.ChangesFeedMode         = context.ChangesFeedMode;
                responseState.ChangesIncludeDocs      = context.GetQueryParam <bool>("include_docs", bool.TryParse, false);
                options.IncludeDocs                   = responseState.ChangesIncludeDocs;
                responseState.ChangesIncludeConflicts = context.GetQueryParam("style") == "all_docs";
                options.IncludeConflicts              = responseState.ChangesIncludeConflicts;
                options.ContentOptions                = context.ContentOptions;
                options.SortBySequence                = !options.IncludeConflicts;
                options.Limit                         = context.GetQueryParam <int>("limit", int.TryParse, options.Limit);
                int since = context.GetQueryParam <int>("since", int.TryParse, 0);

                string filterName = context.GetQueryParam("filter");
                if (filterName != null)
                {
                    Status status = new Status();
                    responseState.ChangesFilter = db.GetFilter(filterName, status);
                    if (responseState.ChangesFilter == null)
                    {
                        var code = Database.FilterCompiler == null ? StatusCode.NotImplemented : StatusCode.NotFound;
                        return(context.CreateResponse(code));
                    }

                    responseState.FilterParams = context.GetQueryParams();
                }

                string heartbeatParam = context.GetQueryParam("heartbeat");
                int heartbeat         = 0;
                if (heartbeatParam != null && (!Int32.TryParse(heartbeatParam, out heartbeat) || heartbeat <= 0))
                {
                    return(context.CreateResponse(StatusCode.BadParam));
                }

                var changes = db.ChangesSinceStreaming(since, options, responseState.ChangesFilter, responseState.FilterParams);
                if ((context.ChangesFeedMode >= ChangesFeedMode.Continuous) ||
                    (context.ChangesFeedMode == ChangesFeedMode.LongPoll && !changes.Any()))
                {
                    // Response is going to stay open (continuous, or hanging GET):
                    response.Chunked = true;
                    if (context.ChangesFeedMode == ChangesFeedMode.EventSource)
                    {
                        response["Content-Type"] = "text/event-stream; charset=utf-8";
                    }

                    if (context.ChangesFeedMode >= ChangesFeedMode.Continuous)
                    {
                        response.WriteHeaders();
                        foreach (var rev in changes)
                        {
                            var success = response.SendContinuousLine(ChangesDictForRev(rev, responseState), context.ChangesFeedMode);
                            if (!success)
                            {
                                return(context.CreateResponse(StatusCode.BadRequest));
                            }
                        }
                    }

                    var subscribed = responseState.SubscribeToDatabase(db, since, options);
                    if (!subscribed)
                    {
                        return(response);
                    }

                    if (heartbeat > 0)
                    {
                        var heartbeatSpan = TimeSpan.FromMilliseconds(heartbeat);
                        if (heartbeatSpan < MinHeartbeat)
                        {
                            heartbeatSpan = MinHeartbeat;
                        }

                        string heartbeatResponse = context.ChangesFeedMode == ChangesFeedMode.EventSource ? "\n\n" : "\r\n";
                        responseState.StartHeartbeat(heartbeatResponse, heartbeatSpan);
                    }

                    return(response);
                }
                else
                {
                    response.Chunked = true;
                    response.Headers["Content-Type"] = "application/json";
                    response.WriteBodyCallback       = WriteChangesBodyJson;
                    if (responseState.ChangesIncludeConflicts)
                    {
                        response.WriteBodyContext = new WriteChangesContext {
                            IncludeConflicts = true,
                            Since            = since,
                            Limit            = options.Limit,
                            Changes          = changes,
                            ResponseState    = responseState
                        };
                    }
                    else
                    {
                        response.WriteBodyContext = new WriteChangesContext {
                            Since         = since,
                            Changes       = changes,
                            ResponseState = responseState
                        };
                    }
                }

                return(response);
            });

            responseState.Response = responseObject;
            return(responseState);
        }