예제 #1
0
        /// <summary>
        /// Create and update multiple documents at the same time within a single request.
        /// </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/bulk-api.html#post--db-_bulk_docs
        /// </remarks>
        public static ICouchbaseResponseState ProcessDocumentChangeOperations(ICouchbaseListenerContext context)
        {
            return(PerformLogicWithDatabase(context, true, db =>
            {
                var postBody = context.BodyAs <Dictionary <string, object> >();
                if (postBody == null)
                {
                    return context.CreateResponse(StatusCode.BadJson);
                }

                if (!postBody.ContainsKey("docs"))
                {
                    return context.CreateResponse(StatusCode.BadParam);
                }
                var docs = postBody["docs"].AsList <IDictionary <string, object> >();

                bool allOrNothing;
                postBody.TryGetValue <bool>("all_or_nothing", out allOrNothing);

                bool newEdits;
                postBody.TryGetValue <bool>("new_edits", out newEdits);

                var response = context.CreateResponse();
                StatusCode status = StatusCode.Ok;
                bool success = db.RunInTransaction(() => {
                    List <IDictionary <string, object> > results = new List <IDictionary <string, object> >(docs.Count);
                    var castContext = context as ICouchbaseListenerContext2;
                    var source = castContext != null && !castContext.IsLoopbackRequest ? castContext.Sender : null;
                    foreach (var doc in docs)
                    {
                        string docId = doc.CblID();
                        RevisionInternal rev = null;
                        Body body = new Body(doc);

                        if (!newEdits)
                        {
                            if (!RevisionInternal.IsValid(body))
                            {
                                status = StatusCode.BadParam;
                            }
                            else
                            {
                                rev = new RevisionInternal(body);
                                var history = Database.ParseCouchDBRevisionHistory(doc);
                                try {
                                    db.ForceInsert(rev, history, source);
                                } catch (CouchbaseLiteException e) {
                                    status = e.Code;
                                }
                            }
                        }
                        else
                        {
                            status = DocumentMethods.UpdateDocument(context, db, docId, body, false, allOrNothing, out rev);
                        }

                        IDictionary <string, object> result = null;
                        if ((int)status < 300)
                        {
                            Debug.Assert(rev != null && rev.RevID != null);
                            if (newEdits)
                            {
                                result = new Dictionary <string, object>
                                {
                                    { "id", rev.DocID },
                                    { "rev", rev.RevID },
                                    { "status", (int)status }
                                };
                            }
                        }
                        else if ((int)status >= 500)
                        {
                            return false; // abort the whole thing if something goes badly wrong
                        }
                        else if (allOrNothing)
                        {
                            return false; // all_or_nothing backs out if there's any error
                        }
                        else
                        {
                            var info = Status.ToHttpStatus(status);
                            result = new Dictionary <string, object>
                            {
                                { "id", docId },
                                { "error", info.Item2 },
                                { "status", info.Item1 }
                            };
                        }

                        if (result != null)
                        {
                            results.Add(result);
                        }
                    }

                    response.JsonBody = new Body(results.Cast <object>().ToList());
                    return true;
                });

                if (!success)
                {
                    response.InternalStatus = status;
                }

                return response;
            }).AsDefaultState());
        }