コード例 #1
0
        public void Test08DocRevisions()
        {
            const string TEST_NAME = "test8";

            if (!PerformanceTestsEnabled)
            {
                return;
            }

            var docs    = new Document[GetNumberOfDocuments(TEST_NAME)];
            var success = database.RunInTransaction(() =>
            {
                for (int i = 0; i < GetNumberOfDocuments(TEST_NAME); i++)
                {
                    var props = new Dictionary <string, object> {
                        { "toggle", true }
                    };
                    var doc = database.CreateDocument();
                    try {
                        doc.PutProperties(props);
                        docs[i] = doc;
                    } catch (CouchbaseLiteException e) {
                        Log.E(TAG, "Document creation failed");
                        return(false);
                    }
                }

                return(true);
            });

            Assert.IsTrue(success);
            TimeBlock(String.Format("{0}, {1}", GetNumberOfDocuments(TEST_NAME), GetNumberOfUpdates(TEST_NAME)), () =>
            {
                foreach (var doc in docs)
                {
                    for (int i = 0; i < GetNumberOfUpdates(TEST_NAME); i++)
                    {
                        var contents       = new Dictionary <string, object>(doc.Properties);
                        var wasChecked     = contents.GetCast <bool>("toggle");
                        contents["toggle"] = !wasChecked;
                        doc.PutProperties(contents);
                    }
                }
            });
        }
コード例 #2
0
 /// <summary>
 /// Gets a value that is a byte array.
 /// </summary>
 /// <remarks>
 /// Gets a value that is a byte array. Note that this method will not convert
 /// any other types to byte arrays.
 /// </remarks>
 /// <param name="key">the value to get</param>
 /// <returns>the byte[] value, or null is the value is missing or not a byte[]</returns>
 public byte[] GetAsByteArray(string key)
 {
     return(mValues.GetCast <byte[]>(key));
 }
コード例 #3
0
        private void UploadChanges(IList <RevisionInternal> changes, IDictionary <string, object> revsDiffResults)
        {
            // Go through the list of local changes again, selecting the ones the destination server
            // said were missing and mapping them to a JSON dictionary in the form _bulk_docs wants:
            var docsToSend = new List <object> ();
            var revsToSend = new RevisionList();
            IDictionary <string, object> revResults = null;

            foreach (var rev in changes)
            {
                // Is this revision in the server's 'missing' list?
                if (revsDiffResults != null)
                {
                    revResults = revsDiffResults.Get(rev.DocID).AsDictionary <string, object>();
                    if (revResults == null)
                    {
                        //SafeIncrementCompletedChangesCount();
                        continue;
                    }

                    var revs = revResults.Get("missing").AsList <string>();
                    if (revs == null || !revs.Any(id => id.Equals(rev.RevID, StringComparison.OrdinalIgnoreCase)))
                    {
                        RemovePending(rev);
                        //SafeIncrementCompletedChangesCount();
                        continue;
                    }
                }

                IDictionary <string, object> properties = null;
                // Get the revision's properties:
                var contentOptions = DocumentContentOptions.IncludeAttachments;
                if (!_dontSendMultipart && RevisionBodyTransformationFunction == null)
                {
                    contentOptions |= DocumentContentOptions.BigAttachmentsFollow;
                }

                RevisionInternal loadedRev;
                try {
                    loadedRev = LocalDatabase.LoadRevisionBody(rev);
                    if (loadedRev == null)
                    {
                        throw Misc.CreateExceptionAndLog(Log.To.Sync, StatusCode.DbError, TAG,
                                                         "Unable to load revision body");
                    }

                    properties = new Dictionary <string, object>(rev.GetProperties());
                } catch (Exception e1) {
                    Log.To.Sync.E(TAG, String.Format("Couldn't get local contents of {0}, marking revision failed",
                                                     rev), e1);
                    RevisionFailed();
                    continue;
                }

                var            populatedRev      = TransformRevision(loadedRev);
                IList <string> possibleAncestors = null;
                if (revResults != null && revResults.ContainsKey("possible_ancestors"))
                {
                    possibleAncestors = revResults["possible_ancestors"].AsList <string>();
                }

                properties = new Dictionary <string, object>(populatedRev.GetProperties());

                try {
                    var history = LocalDatabase.GetRevisionHistory(populatedRev, possibleAncestors);
                    if (history == null)
                    {
                        throw Misc.CreateExceptionAndLog(Log.To.Sync, StatusCode.DbError, TAG,
                                                         "Unable to load revision history");
                    }

                    properties["_revisions"] = Database.MakeRevisionHistoryDict(history);
                } catch (Exception e1) {
                    Log.To.Sync.E(TAG, "Error getting revision history, marking revision failed", e1);
                    RevisionFailed();
                    continue;
                }

                populatedRev.SetProperties(properties);
                if (properties.GetCast <bool>("_removed"))
                {
                    RemovePending(rev);
                    continue;
                }

                // Strip any attachments already known to the target db:
                if (properties.ContainsKey("_attachments"))
                {
                    // Look for the latest common ancestor and stuf out older attachments:
                    var minRevPos = FindCommonAncestor(populatedRev, possibleAncestors);
                    try {
                        LocalDatabase.ExpandAttachments(populatedRev, minRevPos + 1, !_dontSendMultipart, false);
                    } catch (Exception ex) {
                        Log.To.Sync.E(TAG, "Error expanding attachments, marking revision failed", ex);
                        RevisionFailed();
                        continue;
                    }

                    properties = populatedRev.GetProperties();
                    if (!_dontSendMultipart && UploadMultipartRevision(populatedRev))
                    {
                        continue;
                    }
                }

                if (properties == null || !properties.ContainsKey("_id"))
                {
                    throw Misc.CreateExceptionAndLog(Log.To.Sync, StatusCode.BadParam, TAG,
                                                     "properties must contain a document _id");
                }

                // Add the _revisions list:
                revsToSend.Add(rev);

                //now add it to the docs to send
                docsToSend.Add(properties);
            }

            UploadBulkDocs(docsToSend, revsToSend);
        }
        internal override void ProcessInbox(RevisionList inbox)
        {
            if (Status == ReplicationStatus.Offline) {
                Log.V(TAG, "Offline, so skipping inbox process");
                return;
            }

            if(_requests.Count > ManagerOptions.Default.MaxOpenHttpConnections) {
                Task.Delay(1000).ContinueWith(t => ProcessInbox(inbox), CancellationToken.None, TaskContinuationOptions.None, WorkExecutor.Scheduler);
                return;
            }

            // Generate a set of doc/rev IDs in the JSON format that _revs_diff wants:
            // <http://wiki.apache.org/couchdb/HttpPostRevsDiff>
            var diffs = new Dictionary<String, IList<String>>();
            foreach (var rev in inbox) {
                var docID = rev.GetDocId();
                var revs = diffs.Get(docID);
                if (revs == null) {
                    revs = new List<String>();
                    diffs[docID] = revs;
                }
                revs.Add(rev.GetRevId());
                AddPending(rev);
            }

            // Call _revs_diff on the target db:
            Log.D(TAG, "posting to /_revs_diff: {0}", String.Join(Environment.NewLine, new[] { Manager.GetObjectMapper().WriteValueAsString(diffs) }));
            SendAsyncRequest(HttpMethod.Post, "/_revs_diff", diffs, (response, e) =>
            {
                try {
                    if(!LocalDatabase.IsOpen) {
                        return;
                    }

                    var results = response.AsDictionary<string, object>();

                    Log.D(TAG, "/_revs_diff response: {0}\r\n{1}", response, results);

                    if (e != null) {
                        LastError = e;
                        RevisionFailed();
                    } else {
                        if (results.Count != 0)  {
                            // Go through the list of local changes again, selecting the ones the destination server
                            // said were missing and mapping them to a JSON dictionary in the form _bulk_docs wants:
                            var docsToSend = new List<object> ();
                            var revsToSend = new RevisionList();
                            foreach (var rev in inbox) {
                                // Is this revision in the server's 'missing' list?
                                IDictionary<string, object> properties = null;
                                var revResults = results.Get(rev.GetDocId()).AsDictionary<string, object>(); 
                                if (revResults == null) {
                                    //SafeIncrementCompletedChangesCount();
                                    continue;
                                }

                                var revs = revResults.Get("missing").AsList<string>();
                                if (revs == null || !revs.Any( id => id.Equals(rev.GetRevId(), StringComparison.OrdinalIgnoreCase))) {
                                    RemovePending(rev);
                                    //SafeIncrementCompletedChangesCount();
                                    continue;
                                }

                                // Get the revision's properties:
                                var contentOptions = DocumentContentOptions.IncludeAttachments;
                                if (!_dontSendMultipart && RevisionBodyTransformationFunction == null)
                                {
                                    contentOptions |= DocumentContentOptions.BigAttachmentsFollow;
                                }

                                RevisionInternal loadedRev;
                                try {
                                    loadedRev = LocalDatabase.LoadRevisionBody (rev);
                                    if(loadedRev == null) {
                                        throw new CouchbaseLiteException("DB is closed", StatusCode.DbError);
                                    }

                                    properties = new Dictionary<string, object>(rev.GetProperties());
                                } catch (Exception e1) {
                                    Log.W(TAG, String.Format("{0} Couldn't get local contents of", rev), e);
                                    RevisionFailed();
                                    continue;
                                }

                                var populatedRev = TransformRevision(loadedRev);
                                IList<string> possibleAncestors = null;
                                if (revResults.ContainsKey("possible_ancestors")) {
                                    possibleAncestors = revResults["possible_ancestors"].AsList<string>();
                                }

                                properties = new Dictionary<string, object>(populatedRev.GetProperties());

                                try {
                                    var history = LocalDatabase.GetRevisionHistory(populatedRev, possibleAncestors);
                                    if(history == null) {
                                        throw new CouchbaseLiteException("DB closed", StatusCode.DbError);
                                    }

                                    properties["_revisions"] = Database.MakeRevisionHistoryDict(history);
                                } catch(Exception e1) {
                                    Log.W(TAG, "Error getting revision history", e1);
                                    RevisionFailed();
                                    continue;
                                }

                                populatedRev.SetProperties(properties);
                                if(properties.GetCast<bool>("_removed")) {
                                    RemovePending(rev);
                                    continue;
                                }

                                // Strip any attachments already known to the target db:
                                if (properties.ContainsKey("_attachments")) {
                                    // Look for the latest common ancestor and stuf out older attachments:
                                    var minRevPos = FindCommonAncestor(populatedRev, possibleAncestors);
                                    try {
                                        LocalDatabase.ExpandAttachments(populatedRev, minRevPos + 1, !_dontSendMultipart, false);
                                    } catch(Exception ex) {
                                        Log.W(TAG, "Error expanding attachments!", ex);
                                        RevisionFailed();
                                        continue;
                                    }

                                    properties = populatedRev.GetProperties();
                                    if (!_dontSendMultipart && UploadMultipartRevision(populatedRev)) {
                                        continue;
                                    }
                                }

                                if (properties == null || !properties.ContainsKey("_id")) {
                                    throw new InvalidOperationException("properties must contain a document _id");
                                }

                                // Add the _revisions list:
                                revsToSend.Add(rev);

                                //now add it to the docs to send
                                docsToSend.Add (properties);
                            }

                            UploadBulkDocs(docsToSend, revsToSend);
                        } else {
                            foreach (var revisionInternal in inbox) {
                                RemovePending(revisionInternal);
                            }

                            SafeAddToCompletedChangesCount(inbox.Count);
                        }
                    }
                } catch (Exception ex) {
                    Log.E(TAG, "Unhandled exception in Pusher.ProcessInbox", ex);
                }
            });
        }
        public void Test08DocRevisions()
        {
            const string TEST_NAME = "test8";
            if (!PerformanceTestsEnabled) {
                return;
            }

            var docs = new Document[GetNumberOfDocuments(TEST_NAME)];
            var success = database.RunInTransaction(() =>
            {
                for(int i = 0; i < GetNumberOfDocuments(TEST_NAME); i++) {
                    var props = new Dictionary<string, object> {
                        { "toggle", true }
                    };
                    var doc = database.CreateDocument();
                    try {
                        doc.PutProperties(props);
                        docs[i] = doc;
                    } catch(CouchbaseLiteException e) {
                        Log.E(TAG, "Document creation failed");
                        return false;
                    }
                }

                return true;
            });

            Assert.IsTrue(success);
            TimeBlock(String.Format("{0}, {1}", GetNumberOfDocuments(TEST_NAME), GetNumberOfUpdates(TEST_NAME)), () =>
            {
                foreach(var doc in docs) {
                    for(int i = 0; i < GetNumberOfUpdates(TEST_NAME); i++) {
                        var contents = new Dictionary<string, object>(doc.Properties);
                        var wasChecked = contents.GetCast<bool>("toggle");
                        contents["toggle"] = !wasChecked;
                        doc.PutProperties(contents);
                    }
                 }
            });
        }
コード例 #6
0
ファイル: Pusher.cs プロジェクト: elevine/couchbase-lite-net
        internal override void ProcessInbox(RevisionList inbox)
        {
            if (Status == ReplicationStatus.Offline)
            {
                Log.To.Sync.I(TAG, "Offline, so skipping inbox process");
                return;
            }

            if (_requests.Count > ReplicationOptions.MaxOpenHttpConnections)
            {
                Task.Delay(1000).ContinueWith(t => ProcessInbox(inbox), CancellationToken.None, TaskContinuationOptions.None, WorkExecutor.Scheduler);
                return;
            }

            // Generate a set of doc/rev IDs in the JSON format that _revs_diff wants:
            // <http://wiki.apache.org/couchdb/HttpPostRevsDiff>
            var diffs      = new Dictionary <String, IList <String> >();
            var inboxCount = inbox.Count;

            foreach (var rev in inbox)
            {
                var docID = rev.DocID;
                var revs  = diffs.Get(docID);
                if (revs == null)
                {
                    revs         = new List <String>();
                    diffs[docID] = revs;
                }
                revs.Add(rev.RevID);
                AddPending(rev);
            }

            // Call _revs_diff on the target db:
            Log.To.Sync.D(TAG, "posting to /_revs_diff: {0}", String.Join(Environment.NewLine, new[] { Manager.GetObjectMapper().WriteValueAsString(diffs) }));
            SendAsyncRequest(HttpMethod.Post, "/_revs_diff", diffs, (response, e) =>
            {
                try {
                    if (!LocalDatabase.IsOpen)
                    {
                        return;
                    }

                    var results = response.AsDictionary <string, object>();

                    Log.To.Sync.D(TAG, "/_revs_diff response: {0}\r\n{1}", response, results);

                    if (e != null)
                    {
                        LastError = e;
                        for (int i = 0; i < inboxCount; i++)
                        {
                            RevisionFailed();
                        }

                        if (Continuous)
                        {
                            FireTrigger(ReplicationTrigger.WaitingForChanges);
                        }
                        else
                        {
                            FireTrigger(ReplicationTrigger.StopImmediate);
                        }
                    }
                    else
                    {
                        if (results.Count != 0)
                        {
                            // Go through the list of local changes again, selecting the ones the destination server
                            // said were missing and mapping them to a JSON dictionary in the form _bulk_docs wants:
                            var docsToSend = new List <object> ();
                            var revsToSend = new RevisionList();
                            foreach (var rev in inbox)
                            {
                                // Is this revision in the server's 'missing' list?
                                IDictionary <string, object> properties = null;
                                var revResults = results.Get(rev.DocID).AsDictionary <string, object>();
                                if (revResults == null)
                                {
                                    //SafeIncrementCompletedChangesCount();
                                    continue;
                                }

                                var revs = revResults.Get("missing").AsList <string>();
                                if (revs == null || !revs.Any(id => id.Equals(rev.RevID, StringComparison.OrdinalIgnoreCase)))
                                {
                                    RemovePending(rev);
                                    //SafeIncrementCompletedChangesCount();
                                    continue;
                                }

                                // Get the revision's properties:
                                var contentOptions = DocumentContentOptions.IncludeAttachments;
                                if (!_dontSendMultipart && RevisionBodyTransformationFunction == null)
                                {
                                    contentOptions |= DocumentContentOptions.BigAttachmentsFollow;
                                }

                                RevisionInternal loadedRev;
                                try {
                                    loadedRev = LocalDatabase.LoadRevisionBody(rev);
                                    if (loadedRev == null)
                                    {
                                        throw Misc.CreateExceptionAndLog(Log.To.Sync, StatusCode.DbError, TAG,
                                                                         "Unable to load revision body");
                                    }

                                    properties = new Dictionary <string, object>(rev.GetProperties());
                                } catch (Exception e1) {
                                    Log.To.Sync.E(TAG, String.Format("Couldn't get local contents of {0}, marking revision failed",
                                                                     rev), e1);
                                    RevisionFailed();
                                    continue;
                                }

                                var populatedRev = TransformRevision(loadedRev);
                                IList <string> possibleAncestors = null;
                                if (revResults.ContainsKey("possible_ancestors"))
                                {
                                    possibleAncestors = revResults["possible_ancestors"].AsList <string>();
                                }

                                properties = new Dictionary <string, object>(populatedRev.GetProperties());

                                try {
                                    var history = LocalDatabase.GetRevisionHistory(populatedRev, possibleAncestors);
                                    if (history == null)
                                    {
                                        throw Misc.CreateExceptionAndLog(Log.To.Sync, StatusCode.DbError, TAG,
                                                                         "Unable to load revision history");
                                    }

                                    properties["_revisions"] = Database.MakeRevisionHistoryDict(history);
                                } catch (Exception e1) {
                                    Log.To.Sync.E(TAG, "Error getting revision history, marking revision failed", e1);
                                    RevisionFailed();
                                    continue;
                                }

                                populatedRev.SetProperties(properties);
                                if (properties.GetCast <bool>("_removed"))
                                {
                                    RemovePending(rev);
                                    continue;
                                }

                                // Strip any attachments already known to the target db:
                                if (properties.ContainsKey("_attachments"))
                                {
                                    // Look for the latest common ancestor and stuf out older attachments:
                                    var minRevPos = FindCommonAncestor(populatedRev, possibleAncestors);
                                    try {
                                        LocalDatabase.ExpandAttachments(populatedRev, minRevPos + 1, !_dontSendMultipart, false);
                                    } catch (Exception ex) {
                                        Log.To.Sync.E(TAG, "Error expanding attachments, marking revision failed", ex);
                                        RevisionFailed();
                                        continue;
                                    }

                                    properties = populatedRev.GetProperties();
                                    if (!_dontSendMultipart && UploadMultipartRevision(populatedRev))
                                    {
                                        continue;
                                    }
                                }

                                if (properties == null || !properties.ContainsKey("_id"))
                                {
                                    throw Misc.CreateExceptionAndLog(Log.To.Sync, StatusCode.BadParam, TAG,
                                                                     "properties must contain a document _id");
                                }

                                // Add the _revisions list:
                                revsToSend.Add(rev);

                                //now add it to the docs to send
                                docsToSend.Add(properties);
                            }

                            UploadBulkDocs(docsToSend, revsToSend);
                        }
                        else
                        {
                            foreach (var revisionInternal in inbox)
                            {
                                RemovePending(revisionInternal);
                            }

                            //SafeAddToCompletedChangesCount(inbox.Count);
                        }
                    }
                } catch (Exception ex) {
                    Log.To.Sync.E(TAG, "Unhandled exception in Pusher.ProcessInbox, continuing...", ex);
                }
            });
        }
コード例 #7
0
        private void UploadChanges(IList<RevisionInternal> changes, IDictionary<string, object> revsDiffResults)
        {

            // Go through the list of local changes again, selecting the ones the destination server
            // said were missing and mapping them to a JSON dictionary in the form _bulk_docs wants:
            var docsToSend = new List<object> ();
            var revsToSend = new RevisionList();
            IDictionary<string, object> revResults = null;
            foreach (var rev in changes) {
                // Is this revision in the server's 'missing' list?
                if (revsDiffResults != null) {
                    revResults = revsDiffResults.Get(rev.DocID).AsDictionary<string, object>(); 
                    if (revResults == null) {
                        continue;
                    }

                    var revs = revResults.Get("missing").AsList<string>();
                    if (revs == null || !revs.Any(id => id.Equals(rev.RevID.ToString()))) {
                        RemovePending(rev);
                        continue;
                    }
                }

                IDictionary<string, object> properties = null;
                RevisionInternal loadedRev;
                try {
                    loadedRev = LocalDatabase.LoadRevisionBody (rev);
                    if(loadedRev == null) {
                        throw Misc.CreateExceptionAndLog(Log.To.Sync, StatusCode.NotFound, TAG,
                            "Unable to load revision body");
                    }

                    properties = new Dictionary<string, object>(rev.GetProperties());
                } catch (Exception e1) {
                    Log.To.Sync.E(TAG, String.Format("Couldn't get local contents of {0}, marking revision failed",
                        rev), e1);
                    RevisionFailed();
                    continue;
                }

                if (properties.GetCast<bool> ("_removed")) {
                    RemovePending (rev);
                    continue;
                }

                var populatedRev = TransformRevision(loadedRev);
                var backTo = revResults?.Get("possible_ancestors")?.AsList<RevisionID>();

                try {
                    var history = LocalDatabase.GetRevisionHistory(populatedRev, backTo);
                    if(history == null) {
                        throw Misc.CreateExceptionAndLog(Log.To.Sync, StatusCode.DbError, TAG,
                            "Unable to load revision history");
                    }

                    properties["_revisions"] = TreeRevisionID.MakeRevisionHistoryDict(history);
                    populatedRev.SetPropertyForKey("_revisions", properties["_revisions"]);
                } catch(Exception e1) {
                    Log.To.Sync.E(TAG, "Error getting revision history, marking revision failed", e1);
                    RevisionFailed();
                    continue;
                }

                // Strip any attachments already known to the target db:
                if (properties.Get("_attachments") != null) {
                    // Look for the latest common ancestor and stuf out older attachments:
                    var minRevPos = FindCommonAncestor(populatedRev, backTo);
                    try {
                        LocalDatabase.ExpandAttachments(populatedRev, minRevPos + 1, !_dontSendMultipart, false);
                    } catch(Exception ex) {
                        Log.To.Sync.E(TAG, "Error expanding attachments, marking revision failed", ex);
                        RevisionFailed();
                        continue;
                    }

                    properties = populatedRev.GetProperties();
                    if (!_dontSendMultipart && UploadMultipartRevision(populatedRev)) {
                        continue;
                    }
                }

                if (properties == null || !properties.ContainsKey("_id")) {
                    throw Misc.CreateExceptionAndLog(Log.To.Sync, StatusCode.BadParam, TAG,
                        "properties must contain a document _id");
                }

                // Add the _revisions list:
                revsToSend.Add(rev);

                //now add it to the docs to send
                docsToSend.Add (properties);
            }

            UploadBulkDocs(docsToSend, revsToSend);
        }