Exemple #1
0
        [Test]         //see bxc #59334
        public void ExceptionWrapping()
        {
            AssemblyBuilder        ab  = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("ehatevfheiw"), AssemblyBuilderAccess.Run);
            AssemblyBuilder        ab2 = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("ddf4234"), AssemblyBuilderAccess.Run);
            CustomAttributeBuilder cab = new CustomAttributeBuilder(
                typeof(RuntimeCompatibilityAttribute).GetConstructor(new Type [0]),
                new object [0],
                new PropertyInfo[] { typeof(RuntimeCompatibilityAttribute).GetProperty("WrapNonExceptionThrows") },
                new object[] { true });

            ab2.SetCustomAttribute(cab);

            AssemblyBuilder ab3 = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("frfhfher"), AssemblyBuilderAccess.Run);

            //1 NamedArg. Property name: WrapNonExceptionThrows value: true (0x01)
            byte[] blob = new byte[] { 0x01, 0x00, 0x01, 0x00, 0x54, 0x02, 0x16, 0x57, 0x72, 0x61, 0x70, 0x4E, 0x6F, 0x6E, 0x45, 0x78,
                                       0x63, 0x65, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x54, 0x68, 0x72, 0x6F, 0x77, 0x73, 0x01 };
            ab3.SetCustomAttribute(typeof(RuntimeCompatibilityAttribute).GetConstructor(new Type [0]), blob);

            DynamicMethod invoke_no_module   = new DynamicMethod("throw_1", typeof(int), new Type [0]);
            DynamicMethod invoke_with_module = new DynamicMethod("throw_2", typeof(int), new Type [0], typeof(DynamicMethodTest).Module);
            DynamicMethod invoke_with_ab     = new DynamicMethod("throw_3", typeof(int), new Type [0], ab.ManifestModule);
            DynamicMethod invoke_with_ab2    = new DynamicMethod("throw_4", typeof(int), new Type [0], ab2.ManifestModule);
            DynamicMethod invoke_with_ab3    = new DynamicMethod("throw_5", typeof(int), new Type [0], ab3.ManifestModule);

            int result = 0;

            try {
                int res = EmitDelegate(invoke_no_module)();
                Assert.AreEqual(3, res, "invoke_no_module bad return value");
            } catch (RuntimeWrappedException e) {
                Assert.Fail("invoke_no_module threw RWE");
            }

            try {
                int res = EmitDelegate(invoke_with_module)();
                Assert.Fail("invoke_with_module did not throw RWE");
            } catch (RuntimeWrappedException e) {
            }

            try {
                int res = EmitDelegate(invoke_with_ab)();
                Assert.AreEqual(3, res, "invoke_with_ab bad return value");
            } catch (RuntimeWrappedException e) {
                Assert.Fail("invoke_with_ab threw RWE");
            }

            try {
                int res = EmitDelegate(invoke_with_ab2)();
                Assert.Fail("invoke_with_ab2 did not throw RWE");
            } catch (RuntimeWrappedException e) {
            }

            try {
                int res = EmitDelegate(invoke_with_ab3)();
                Assert.Fail("invoke_with_a3 did not throw RWE");
            } catch (RuntimeWrappedException e) {
            }
        }
Exemple #2
0
        public void TestJsMapFunction()
        {
            var c        = new JSViewCompiler();
            var mapBlock = c.CompileMap("function(doc){emit(doc.key, doc);}", "javascript");

            Assert.IsNotNull(mapBlock);

            var doc = new Dictionary <string, object> {
                { "_id", "doc1" },
                { "_rev", @"1-xyzzy" },
                { "key", "value" }
            };

            var          emitted = new List <object>();
            EmitDelegate emit    = (key, value) =>
            {
                Console.WriteLine("Emitted: {0} -> {1}", key, value);
                emitted.Add(key);
                emitted.Add(value);
            };

            mapBlock(doc, emit);

            CollectionAssert.AreEqual(new List <object> {
                "value", doc
            }, emitted);
        }
Exemple #3
0
        public MapDelegate CompileMap(string source, string language)
        {
            if (!language.Equals("javascript"))
            {
                return(null);
            }

            EmitDelegate rtEmit   = null;
            EmitDelegate wrapEmit = (key, value) =>
            {
                rtEmit(key, value);
            };

            source = source.Replace("function", "function _f1");

            var engine = new Engine();

            engine.SetValue("log", new LogDelegate((msg) =>
            {
                // TODO: handle log
            }));

            engine.SetValue("emit", wrapEmit);
            engine.Execute(source);

            return((doc, emit) =>
            {
                rtEmit = emit;
                string tempSource = "_f1(" + JsonConvert.SerializeObject(doc) + ");";
                engine.Execute(tempSource);
            });
        }
        public void CreateConstructorDelegate_Should_Throw_InvalidOperationException_If_No_Constructor_Matching_Parameters_Can_Be_Found()
        {
            // Arrange
            Type[] parameters = new Type[] { typeof(String) };

            // Act/Assert
            Assert.Throws <InvalidOperationException>(() => EmitDelegate.CreateConstructor <Int32ConstructorDelegate>());
        }
        private void Map(IDictionary <string, object> doc, EmitDelegate emit)
        {
            var mapFunction    = (Func <QueryRow, bool>)_where.Compile();
            var selectFunction = _select.Compile();
            var fakeRow        = new QueryRow(doc.CblID(), doc.GetCast <long>("_local_seq"), null, null, new RevisionInternal(doc), null);

            if (mapFunction(fakeRow))
            {
                emit(selectFunction.DynamicInvoke(fakeRow), null);
            }
        }
        public void CreateConstructorDelegate_Should_Return_Functioning_Delegate()
        {
            // Arrange
            Type[] parameters = new Type[] { typeof(object) };
            object parameter1 = new object();
            TestConstructorDelegate constructor = EmitDelegate.CreateConstructor <TestConstructorDelegate>();

            // Act
            EmitDelegateTestClass instance = constructor(parameter1);

            // Assert
            Assert.True(ReferenceEquals(parameter1, instance.TestReference));
        }
Exemple #7
0
        private void EmitLiquid(int cell)
        {
            int          cell1 = Grid.CellBelow(cell);
            EmitDelegate emit  = !Grid.IsValidCell(cell1) || Grid.Solid[cell1] ? emit_element : emit_particle;

            foreach (GameObject gameObject in storage.items)
            {
                PrimaryElement component = gameObject.GetComponent <PrimaryElement>();
                if (component.Element.IsLiquid && EmitCommon(cell, component, emit))
                {
                    break;
                }
            }
        }
Exemple #8
0
        private bool EmitCommon(int cell, PrimaryElement primary_element, EmitDelegate emit)
        {
            if (primary_element.Mass <= 0.0)
            {
                return(false);
            }
            int disease_to_item1;
            int disease_to_item2;

            CalculateDiseaseTransfer(exhaustPE, primary_element, 0.05f, out disease_to_item1, out disease_to_item2);
            primary_element.ModifyDiseaseCount(-disease_to_item1, "Exhaust transfer");
            primary_element.AddDisease(exhaustPE.DiseaseIdx, disease_to_item2, "Exhaust transfer");
            exhaustPE.ModifyDiseaseCount(-disease_to_item2, "Exhaust transfer");
            exhaustPE.AddDisease(primary_element.DiseaseIdx, disease_to_item1, "Exhaust transfer");
            emit(cell, primary_element);
            primary_element.KeepZeroMassObject = true;
            primary_element.Mass = 0.0f;
            primary_element.ModifyDiseaseCount(int.MinValue, "Exhaust.SimUpdate");
            return(true);
        }
 private bool EmitCommon(int cell, PrimaryElement primary_element, EmitDelegate emit)
 {
     if (primary_element.Mass <= 0f)
     {
         return(false);
     }
     CalculateDiseaseTransfer(exhaustPE, primary_element, 0.05f, out int disease_to_item, out int disease_to_item2);
     primary_element.ModifyDiseaseCount(-disease_to_item, "Exhaust transfer");
     primary_element.AddDisease(exhaustPE.DiseaseIdx, disease_to_item2, "Exhaust transfer");
     exhaustPE.ModifyDiseaseCount(-disease_to_item2, "Exhaust transfer");
     exhaustPE.AddDisease(primary_element.DiseaseIdx, disease_to_item, "Exhaust transfer");
     emit(cell, primary_element);
     if ((Object)vent != (Object)null)
     {
         vent.UpdateVentedMass(primary_element.ElementID, primary_element.Mass);
     }
     primary_element.KeepZeroMassObject = true;
     primary_element.Mass = 0f;
     primary_element.ModifyDiseaseCount(-2147483648, "Exhaust.SimUpdate");
     recentlyExhausted = true;
     return(true);
 }
Exemple #10
0
        public void TestJsLogFunction()
        {
            // This case will test that calling log() function doesn't cause any errors running the JS map
            // map function.
            var c        = new JSViewCompiler();
            var mapBlock = c.CompileMap("function(doc){log('Log Message'); emit(doc.key, doc);}", "javascript");

            Assert.IsNotNull(mapBlock);

            var doc = new Dictionary <string, object> {
                { "_id", "doc1" },
                { "_rev", @"1-xyzzy" },
                { "key", "value" }
            };

            var          emitted = new List <object>();
            EmitDelegate emit    = (key, value) => emitted.Add(value);

            mapBlock(doc, emit);

            CollectionAssert.AreEqual(new List <object> {
                doc
            }, emitted);
        }
        public bool UpdateIndexes(IEnumerable <IViewStore> inputViews)
        {
            Log.D(TAG, "Checking indexes of ({0}) for {1}", ViewNames(inputViews.Cast <SqliteViewStore>()), Name);
            var db = _dbStorage;

            var status = false;

            status = db.RunInTransaction(() =>
            {
                // If the view the update is for doesn't need any update, don't do anything:
                long dbMaxSequence       = db.LastSequence;
                long forViewLastSequence = LastSequenceIndexed;
                if (forViewLastSequence >= dbMaxSequence)
                {
                    return(true);
                }

                // Check whether we need to update at all,
                // and remove obsolete emitted results from the 'maps' table:
                long minLastSequence    = dbMaxSequence;
                long[] viewLastSequence = new long[inputViews.Count()];
                int deletedCount        = 0;
                int i = 0;
                HashSet <string> docTypes = new HashSet <string>();
                IDictionary <string, string> viewDocTypes = null;
                bool allDocTypes = false;
                IDictionary <int, int> viewTotalRows = new Dictionary <int, int>();
                List <SqliteViewStore> views         = new List <SqliteViewStore>(inputViews.Count());
                List <MapDelegate> mapBlocks         = new List <MapDelegate>();
                foreach (var view in inputViews.Cast <SqliteViewStore>())
                {
                    var viewDelegate = view.Delegate;
                    var mapBlock     = viewDelegate == null ? null : viewDelegate.Map;
                    if (mapBlock == null)
                    {
                        Debug.Assert(view != this, String.Format("Cannot index view {0}: no map block registered", view.Name));
                        Log.V(TAG, "    {0} has no map block; skipping it", view.Name);
                        continue;
                    }

                    views.Add(view);
                    mapBlocks.Add(mapBlock);

                    int viewId = view.ViewID;
                    Debug.Assert(viewId > 0, String.Format("View '{0}' not found in database", view.Name));

                    int totalRows         = view.TotalRows;
                    viewTotalRows[viewId] = totalRows;

                    long last             = view == this ? forViewLastSequence : view.LastSequenceIndexed;
                    viewLastSequence[i++] = last;
                    if (last < 0)
                    {
                        throw new CouchbaseLiteException(StatusCode.DbError);
                    }

                    if (last < dbMaxSequence)
                    {
                        if (last == 0)
                        {
                            CreateIndex();
                        }

                        minLastSequence = Math.Min(minLastSequence, last);
                        Log.V(TAG, "    {0} last indexed at #{1}", view.Name, last);

                        string docType = viewDelegate.DocumentType;
                        if (docType != null)
                        {
                            docTypes.Add(docType);
                            if (viewDocTypes == null)
                            {
                                viewDocTypes = new Dictionary <string, string>();
                            }

                            viewDocTypes[view.Name] = docType;
                        }
                        else
                        {
                            // can't filter by doc_type
                            allDocTypes = true;
                        }

                        bool ok     = true;
                        int changes = 0;
                        if (last == 0)
                        {
                            try {
                                // If the lastSequence has been reset to 0, make sure to remove all map results:
                                changes = db.StorageEngine.ExecSQL(view.QueryString("DELETE FROM 'maps_#'"));
                            } catch (Exception) {
                                ok = false;
                            }
                        }
                        else
                        {
                            db.OptimizeSQLIndexes();     // ensures query will use the right indexes
                            // Delete all obsolete map results (ones from since-replaced revisions):
                            try {
                                changes = db.StorageEngine.ExecSQL(view.QueryString("DELETE FROM 'maps_#' WHERE sequence IN (" +
                                                                                    "SELECT parent FROM revs WHERE sequence>?" +
                                                                                    "AND +parent>0 AND +parent<=?)"), last, last);
                            } catch (Exception) {
                                ok = false;
                            }
                        }

                        if (!ok)
                        {
                            throw new CouchbaseLiteException(StatusCode.DbError);
                        }

                        // Update #deleted rows
                        deletedCount += changes;

                        // Only count these deletes as changes if this isn't a view reset to 0
                        if (last != 0)
                        {
                            viewTotalRows[viewId] -= changes;
                        }
                    }
                }

                if (minLastSequence == dbMaxSequence)
                {
                    return(true);
                }

                Log.D(TAG, "Updating indexes of ({0}) from #{1} to #{2} ...",
                      ViewNames(views), minLastSequence, dbMaxSequence);

                // This is the emit() block, which gets called from within the user-defined map() block
                // that's called down below.
                SqliteViewStore currentView             = null;
                IDictionary <string, object> currentDoc = null;
                long sequence     = minLastSequence;
                Status emitStatus = new Status(StatusCode.Ok);
                int insertedCount = 0;
                EmitDelegate emit = (key, value) =>
                {
                    StatusCode s = currentView.Emit(key, value, value == currentDoc, sequence);
                    if (s != StatusCode.Ok)
                    {
                        emitStatus.Code = s;
                    }
                    else
                    {
                        viewTotalRows[currentView.ViewID] += 1;
                        insertedCount++;
                    }
                };

                // Now scan every revision added since the last time the views were indexed:
                bool checkDocTypes = docTypes.Count > 1 || (allDocTypes && docTypes.Count > 0);
                var sql            = new StringBuilder("SELECT revs.doc_id, sequence, docid, revid, json, deleted ");
                if (checkDocTypes)
                {
                    sql.Append(", doc_type ");
                }

                sql.Append("FROM revs, docs WHERE sequence>? AND sequence <=? AND current!=0 ");
                if (minLastSequence == 0)
                {
                    sql.Append("AND deleted=0 ");
                }

                if (!allDocTypes && docTypes.Count > 0)
                {
                    sql.AppendFormat("AND doc_type IN ({0}) ", Database.JoinQuoted(docTypes));
                }

                sql.Append("AND revs.doc_id = docs.doc_id " +
                           "ORDER BY revs.doc_id, deleted, revid DESC");

                Cursor c  = null;
                Cursor c2 = null;
                try {
                    c = db.StorageEngine.IntransactionRawQuery(sql.ToString(), minLastSequence, dbMaxSequence);
                    bool keepGoing = c.MoveToNext();
                    while (keepGoing)
                    {
                        // Get row values now, before the code below advances 'c':
                        long doc_id  = c.GetLong(0);
                        sequence     = c.GetLong(1);
                        string docId = c.GetString(2);
                        if (docId.StartsWith("_design/"))       // design documents don't get indexed
                        {
                            keepGoing = c.MoveToNext();
                            continue;
                        }

                        string revId   = c.GetString(3);
                        var json       = c.GetBlob(4);
                        bool deleted   = c.GetInt(5) != 0;
                        string docType = checkDocTypes ? c.GetString(6) : null;

                        // Skip rows with the same doc_id -- these are losing conflicts.
                        var conflicts = default(List <string>);
                        while ((keepGoing = c.MoveToNext()) && c.GetLong(0) == doc_id)
                        {
                            if (conflicts == null)
                            {
                                conflicts = new List <string>();
                            }

                            conflicts.Add(c.GetString(3));
                        }

                        long realSequence = sequence;     // because sequence may be changed, below
                        if (minLastSequence > 0)
                        {
                            // Find conflicts with documents from previous indexings.
                            using (c2 = db.StorageEngine.IntransactionRawQuery("SELECT revid, sequence FROM revs " +
                                                                               "WHERE doc_id=? AND sequence<=? AND current!=0 AND deleted=0 " +
                                                                               "ORDER BY revID DESC ", doc_id, minLastSequence)) {
                                if (c2.MoveToNext())
                                {
                                    string oldRevId = c2.GetString(0);
                                    // This is the revision that used to be the 'winner'.
                                    // Remove its emitted rows:
                                    long oldSequence = c2.GetLong(1);
                                    foreach (var view in views)
                                    {
                                        int changes   = db.StorageEngine.ExecSQL(QueryString("DELETE FROM 'maps_#' WHERE sequence=?"), oldSequence);
                                        deletedCount += changes;
                                        viewTotalRows[view.ViewID] -= changes;
                                    }

                                    if (deleted || RevisionInternal.CBLCompareRevIDs(oldRevId, revId) > 0)
                                    {
                                        // It still 'wins' the conflict, so it's the one that
                                        // should be mapped [again], not the current revision!
                                        revId    = oldRevId;
                                        deleted  = false;
                                        sequence = oldSequence;
                                        json     = db.QueryOrDefault <byte[]>(x => x.GetBlob(0), true, null, "SELECT json FROM revs WHERE sequence=?", sequence);
                                    }

                                    if (!deleted)
                                    {
                                        // Conflict revisions:
                                        if (conflicts == null)
                                        {
                                            conflicts = new List <string>();
                                        }

                                        conflicts.Add(oldRevId);
                                        while (c2.MoveToNext())
                                        {
                                            conflicts.Add(c2.GetString(0));
                                        }
                                    }
                                }
                            }
                        }

                        if (deleted)
                        {
                            continue;
                        }

                        // Get the document properties, to pass to the map function:
                        currentDoc = db.GetDocumentProperties(json, docId, revId, deleted, sequence);
                        if (currentDoc == null)
                        {
                            Log.W(TAG, "Failed to parse JSON of doc {0} rev {1}", docId, revId);
                            continue;
                        }

                        currentDoc["_local_seq"] = sequence;
                        if (conflicts != null)
                        {
                            currentDoc["_conflicts"] = conflicts;
                        }

                        // Call the user-defined map() to emit new key/value pairs from this revision:
                        int viewIndex = -1;
                        var e         = views.GetEnumerator();
                        while (e.MoveNext())
                        {
                            currentView = e.Current;
                            ++viewIndex;
                            if (viewLastSequence[viewIndex] < realSequence)
                            {
                                if (checkDocTypes)
                                {
                                    var viewDocType = viewDocTypes[currentView.Name];
                                    if (viewDocType != null && viewDocType != docType)
                                    {
                                        // skip; view's documentType doesn't match this doc
                                        continue;
                                    }
                                }

                                Log.V(TAG, "    #{0}: map \"{1}\" for view {2}...",
                                      sequence, docId, e.Current.Name);
                                try {
                                    mapBlocks[viewIndex](currentDoc, emit);
                                } catch (Exception x) {
                                    Log.E(TAG, String.Format("Exception in map() block for view {0}", currentView.Name), x);
                                    emitStatus.Code = StatusCode.Exception;
                                }

                                if (emitStatus.IsError)
                                {
                                    c.Dispose();
                                    return(false);
                                }
                            }
                        }

                        currentView = null;
                    }
                } catch (CouchbaseLiteException) {
                    Log.W(TAG, "Failed to update index for {0}", currentView.Name);
                    throw;
                } catch (Exception e) {
                    throw new CouchbaseLiteException(String.Format("Error updating index for {0}", currentView.Name),
                                                     e)
                    {
                        Code = StatusCode.Exception
                    };
                } finally {
                    if (c != null)
                    {
                        c.Dispose();
                    }
                }

                // Finally, record the last revision sequence number that was indexed and update #rows:
                foreach (var view in views)
                {
                    view.FinishCreatingIndex();
                    int newTotalRows = viewTotalRows[view.ViewID];
                    Debug.Assert(newTotalRows >= 0);

                    var args             = new ContentValues();
                    args["lastSequence"] = dbMaxSequence;
                    args["total_docs"]   = newTotalRows;
                    try {
                        db.StorageEngine.Update("views", args, "view_id=?", view.ViewID.ToString());
                    } catch (CouchbaseLiteException) {
                        Log.W(TAG, "Failed to update view {0}", view.Name);
                        throw;
                    } catch (Exception e) {
                        throw new CouchbaseLiteException(String.Format("Error updating view {0}", view.Name),
                                                         e)
                        {
                            Code = StatusCode.Exception
                        };
                    }
                }

                Log.D(TAG, "...Finished re-indexing ({0}) to #{1} (deleted {2}, added {3})",
                      ViewNames(views), dbMaxSequence, deletedCount, insertedCount);
                return(true);
            });

            if (!status)
            {
                Log.W(TAG, "CouchbaseLite: Failed to rebuild views ({0}): {1}", ViewNames(inputViews.Cast <SqliteViewStore>()), status);
            }

            return(status);
        }
Exemple #12
0
        internal void UpdateIndex()
        {
            Log.I(Database.Tag, "Re-indexing view {0} ...", Name);
            System.Diagnostics.Debug.Assert((Map != null));

            if (Id <= 0)
            {
                var msg = string.Format("View.Id <= 0");
                throw new CouchbaseLiteException(msg, new Status(StatusCode.NotFound));
            }

            var    result  = new Status(StatusCode.InternalServerError);
            Cursor cursor  = null;
            Cursor cursor2 = null;

            try
            {
                Database.RunInTransaction(() =>
                {
                    var lastSequence  = LastSequenceIndexed;
                    var dbMaxSequence = Database.LastSequenceNumber;

                    if (lastSequence >= dbMaxSequence)
                    {
                        // nothing to do (eg,  kCBLStatusNotModified)
                        Log.V(Database.Tag, "lastSequence ({0}) == dbMaxSequence ({1}), nothing to do", lastSequence, dbMaxSequence);
                        result.SetCode(StatusCode.NotModified);
                        return(false);
                    }

                    // First remove obsolete emitted results from the 'maps' table:
                    var sequence = lastSequence;
                    if (lastSequence < 0)
                    {
                        var msg = string.Format("lastSequence < 0 ({0})", lastSequence);
                        throw new CouchbaseLiteException(msg, new Status(StatusCode.InternalServerError));
                    }
                    if (lastSequence == 0)
                    {
                        // If the lastSequence has been reset to 0, make sure to remove
                        // any leftover rows:
                        var whereArgs = new string[] { Id.ToString() };
                        Database.StorageEngine.Delete("maps", "view_id=?", whereArgs);
                    }
                    else
                    {
                        Database.OptimizeSQLIndexes();
                        // Delete all obsolete map results (ones from since-replaced
                        // revisions):
                        var args = new [] {
                            Id.ToString(),
                            lastSequence.ToString(),
                            lastSequence.ToString()
                        };

                        Database.StorageEngine.ExecSQL(
                            "DELETE FROM maps WHERE view_id=? AND sequence IN ("
                            + "SELECT parent FROM revs WHERE sequence>? " + "AND +parent>0 AND +parent<=?)",
                            args);
                    }

                    var deleted = 0;
                    cursor      = Database.StorageEngine.IntransactionRawQuery("SELECT changes()");
                    cursor.MoveToNext();
                    deleted = cursor.GetInt(0);
                    cursor.Close();

                    // Find a better way to propagate this back
                    // Now scan every revision added since the last time the view was indexed:
                    var selectArgs = new[] { lastSequence.ToString(), dbMaxSequence.ToString() };
                    cursor         = Database.StorageEngine.IntransactionRawQuery("SELECT revs.doc_id, sequence, docid, revid, json, no_attachments FROM revs, docs "
                                                                                  + "WHERE sequence>? AND sequence<=? AND current!=0 AND deleted=0 "
                                                                                  + "AND revs.doc_id = docs.doc_id "
                                                                                  + "ORDER BY revs.doc_id, revid DESC", selectArgs);

                    var lastDocID = 0L;
                    var keepGoing = cursor.MoveToNext();
                    while (keepGoing)
                    {
                        long docID = cursor.GetLong(0);
                        if (docID != lastDocID)
                        {
                            // Only look at the first-iterated revision of any document,
                            // because this is the
                            // one with the highest revid, hence the "winning" revision
                            // of a conflict.
                            lastDocID = docID;
                            // Reconstitute the document as a dictionary:
                            sequence     = cursor.GetLong(1);
                            string docId = cursor.GetString(2);
                            if (docId.StartsWith("_design/", StringComparison.InvariantCultureIgnoreCase))
                            {
                                // design docs don't get indexed!
                                keepGoing = cursor.MoveToNext();
                                continue;
                            }
                            var revId = cursor.GetString(3);
                            var json  = cursor.GetBlob(4);

                            var noAttachments = cursor.GetInt(5) > 0;

                            // Skip rows with the same doc_id -- these are losing conflicts.
                            while ((keepGoing = cursor.MoveToNext()) && cursor.GetLong(0) == docID)
                            {
                            }

                            if (lastSequence > 0)
                            {
                                // Find conflicts with documents from previous indexings.
                                var selectArgs2 = new[] { Convert.ToString(docID), Convert.ToString(lastSequence) };
                                cursor2         = Database.StorageEngine.IntransactionRawQuery("SELECT revid, sequence FROM revs "
                                                                                               + "WHERE doc_id=? AND sequence<=? AND current!=0 AND deleted=0 " + "ORDER BY revID DESC "
                                                                                               + "LIMIT 1", selectArgs2);
                                if (cursor2.MoveToNext())
                                {
                                    var oldRevId = cursor2.GetString(0);

                                    // This is the revision that used to be the 'winner'.
                                    // Remove its emitted rows:
                                    var oldSequence = cursor2.GetLong(1);
                                    var args        = new[] { Sharpen.Extensions.ToString(Id), Convert.ToString(oldSequence) };
                                    Database.StorageEngine.ExecSQL("DELETE FROM maps WHERE view_id=? AND sequence=?", args);

                                    if (RevisionInternal.CBLCompareRevIDs(oldRevId, revId) > 0)
                                    {
                                        // It still 'wins' the conflict, so it's the one that
                                        // should be mapped [again], not the current revision!
                                        revId           = oldRevId;
                                        sequence        = oldSequence;
                                        var selectArgs3 = new[] { Convert.ToString(sequence) };
                                        json            = Misc.ByteArrayResultForQuery(
                                            Database.StorageEngine,
                                            "SELECT json FROM revs WHERE sequence=?",
                                            selectArgs3
                                            );
                                    }
                                }

                                cursor2.Close();
                                cursor2 = null;
                            }
                            // Get the document properties, to pass to the map function:
                            var contentOptions = DocumentContentOptions.None;
                            if (noAttachments)
                            {
                                contentOptions |= DocumentContentOptions.NoAttachments;
                            }

                            var properties = Database.DocumentPropertiesFromJSON(
                                json, docId, revId, false, sequence, DocumentContentOptions.None
                                );
                            if (properties != null)
                            {
                                // Call the user-defined map() to emit new key/value
                                // pairs from this revision:

                                // This is the emit() block, which gets called from within the
                                // user-defined map() block
                                // that's called down below.

                                var enclosingView = this;
                                var thisSequence  = sequence;
                                var map           = Map;

                                if (map == null)
                                {
                                    throw new CouchbaseLiteException("Map function is missing.");
                                }

                                EmitDelegate emitBlock = (key, value) =>
                                {
                                    // TODO: Do we need to do any null checks on key or value?
                                    try
                                    {
                                        var keyJson   = Manager.GetObjectMapper().WriteValueAsString(key);
                                        var valueJson = value == null ? null : Manager.GetObjectMapper().WriteValueAsString(value);

                                        var insertValues = new ContentValues();
                                        insertValues.Put("view_id", enclosingView.Id);
                                        insertValues["sequence"] = thisSequence;
                                        insertValues["key"]      = keyJson;
                                        insertValues["value"]    = valueJson;

                                        enclosingView.Database.StorageEngine.Insert("maps", null, insertValues);
                                    }
                                    catch (Exception e)
                                    {
                                        Log.E(Database.Tag, "Error emitting", e);
                                    }
                                };

                                map(properties, emitBlock);
                            }
                        }
                        else
                        {
                            keepGoing = cursor.MoveToNext();
                        }
                    }

                    // Finally, record the last revision sequence number that was
                    // indexed:
                    var updateValues             = new ContentValues();
                    updateValues["lastSequence"] = dbMaxSequence;
                    var whereArgs_1 = new string[] { Id.ToString() };
                    Database.StorageEngine.Update("views", updateValues, "view_id=?", whereArgs_1);

                    // FIXME actually count number added :)
                    Log.V(Database.Tag, "...Finished re-indexing view {0} up to sequence {1} (deleted {2} added ?)", Name, Convert.ToString(dbMaxSequence), deleted);
                    result.SetCode(StatusCode.Ok);

                    return(true);
                });
            }
            catch (Exception e)
            {
                throw new CouchbaseLiteException(e, new Status(StatusCode.DbError));
            }
            finally
            {
                if (cursor2 != null)
                {
                    cursor2.Close();
                }

                if (cursor != null)
                {
                    cursor.Close();
                }

                if (!result.IsSuccessful)
                {
                    Log.W(Database.Tag, "Failed to rebuild view {0}:{1}", Name, result.GetCode());
                }
            }
        }
Exemple #13
0
 public LanguageToolChain(string language, EmitDelegate compile)
 {
     Language     = language;
     EmitDelegate = compile;
 }
 public DMDAction(String name, EmitDelegate emitter) : base(name, emitter)
 {
 }
Exemple #15
0
        internal void UpdateIndex()
        {
            Log.V(Database.Tag, "Re-indexing view " + Name + " ...");
            System.Diagnostics.Debug.Assert((Map != null));

            if (Id < 0)
            {
                var msg = string.Format("View.Id < 0");
                throw new CouchbaseLiteException(msg, new Status(StatusCode.NotFound));
            }

            Database.BeginTransaction();

            var    result = new Status(StatusCode.InternalServerError);
            Cursor cursor = null;

            try
            {
                var lastSequence  = LastSequenceIndexed;
                var dbMaxSequence = Database.LastSequenceNumber;

                if (lastSequence == dbMaxSequence)
                {
                    // nothing to do (eg,  kCBLStatusNotModified)
                    var msg = String.Format("lastSequence ({0}) == dbMaxSequence ({1}), nothing to do", lastSequence, dbMaxSequence);
                    Log.D(Database.Tag, msg);
                    result.SetCode(StatusCode.Ok);
                    return;
                }

                // First remove obsolete emitted results from the 'maps' table:
                var sequence = lastSequence;
                if (lastSequence < 0)
                {
                    var msg = string.Format("lastSequence < 0 ({0})", lastSequence);
                    throw new CouchbaseLiteException(msg, new Status(StatusCode.InternalServerError));
                }
                if (lastSequence == 0)
                {
                    // If the lastSequence has been reset to 0, make sure to remove
                    // any leftover rows:
                    var whereArgs = new string[] { Sharpen.Extensions.ToString(Id) };
                    Database.StorageEngine.Delete("maps", "view_id=@", whereArgs);
                }
                else
                {
                    // Delete all obsolete map results (ones from since-replaced
                    // revisions):
                    var args = new [] {
                        Id.ToString(),
                        lastSequence.ToString(),
                        lastSequence.ToString()
                    };

                    Database.StorageEngine.ExecSQL(
                        "DELETE FROM maps WHERE view_id=@ AND sequence IN ("
                        + "SELECT parent FROM revs WHERE sequence>@ " + "AND parent>0 AND parent<=@)",
                        args);
                }
                var deleted = 0;
                cursor = Database.StorageEngine.RawQuery("SELECT changes()", null); // TODO: Convert to ADO params.
                cursor.MoveToNext();
                deleted = cursor.GetInt(0);
                cursor.Close();

                // find a better way to propagate this back
                // Now scan every revision added since the last time the view was
                // indexed:
                var selectArgs = new[] { Convert.ToString(lastSequence) };
                cursor = Database.StorageEngine.RawQuery("SELECT revs.doc_id, sequence, docid, revid, json FROM revs, docs "
                                                         + "WHERE sequence>@ AND current!=0 AND deleted=0 " + "AND revs.doc_id = docs.doc_id "
                                                         + "ORDER BY revs.doc_id, revid DESC", CommandBehavior.SequentialAccess, selectArgs);
                cursor.MoveToNext();

                var lastDocID = 0L;
                while (!cursor.IsAfterLast())
                {
                    long docID = cursor.GetLong(0);
                    if (docID != lastDocID)
                    {
                        // Only look at the first-iterated revision of any document,
                        // because this is the
                        // one with the highest revid, hence the "winning" revision
                        // of a conflict.
                        lastDocID = docID;
                        // Reconstitute the document as a dictionary:
                        sequence = cursor.GetLong(1);
                        string docId = cursor.GetString(2);
                        if (docId.StartsWith("_design/", StringComparison.InvariantCultureIgnoreCase))
                        {
                            // design docs don't get indexed!
                            cursor.MoveToNext();
                            continue;
                        }
                        var revId      = cursor.GetString(3);
                        var json       = cursor.GetBlob(4);
                        var properties = Database.DocumentPropertiesFromJSON(
                            json, docId, revId, false, sequence, EnumSet.NoneOf <TDContentOptions>()
                            );
                        if (properties != null)
                        {
                            // Call the user-defined map() to emit new key/value
                            // pairs from this revision:
                            Log.V(Database.Tag, "  call map for sequence=" + System.Convert.ToString(sequence
                                                                                                     ));
                            // This is the emit() block, which gets called from within the
                            // user-defined map() block
                            // that's called down below.

                            var enclosingView = this;
                            var thisSequence  = sequence;
                            var map           = Map;

                            if (map == null)
                            {
                                throw new CouchbaseLiteException("Map function is missing.");
                            }

                            EmitDelegate emitBlock = (key, value) =>
                            {
                                // TODO: Do we need to do any null checks on key or value?
                                try
                                {
                                    var keyJson   = Manager.GetObjectMapper().WriteValueAsString(key);
                                    var valueJson = value == null ? null : Manager.GetObjectMapper().WriteValueAsString(value);
                                    Log.V(Database.Tag, String.Format("    emit({0}, {1})", keyJson, valueJson));

                                    var insertValues = new ContentValues();
                                    insertValues.Put("view_id", enclosingView.Id);
                                    insertValues["sequence"] = thisSequence;
                                    insertValues["key"]      = keyJson;
                                    insertValues["value"]    = valueJson;

                                    enclosingView.Database.StorageEngine.Insert("maps", null, insertValues);
                                }
                                catch (Exception e)
                                {
                                    Log.E(Database.Tag, "Error emitting", e);
                                }
                            };

                            map(properties, emitBlock);
                        }
                    }
                    cursor.MoveToNext();
                }
                // Finally, record the last revision sequence number that was
                // indexed:
                ContentValues updateValues = new ContentValues();
                updateValues["lastSequence"] = dbMaxSequence;
                var whereArgs_1 = new string[] { Sharpen.Extensions.ToString(Id) };
                Database.StorageEngine.Update("views", updateValues, "view_id=@", whereArgs_1);
                // FIXME actually count number added :)
                Log.V(Database.Tag, "...Finished re-indexing view " + Name + " up to sequence " +
                      System.Convert.ToString(dbMaxSequence) + " (deleted " + deleted + " added " + "?" + ")");
                result.SetCode(StatusCode.Ok);
            }
            catch (SQLException e)
            {
                throw new CouchbaseLiteException(e, new Status(StatusCode.DbError));
            }
            finally
            {
                if (cursor != null)
                {
                    cursor.Close();
                }
                if (!result.IsSuccessful())
                {
                    Log.W(Database.Tag, "Failed to rebuild view " + Name + ": " + result.GetCode());
                }
                if (Database != null)
                {
                    Database.EndTransaction(result.IsSuccessful());
                }
            }
        }