コード例 #1
0
        public void UpdateIndex()
        {
            Log.V(Log.TagView, "Re-indexing view: %s", name);
            System.Diagnostics.Debug.Assert((mapBlock != null));
            if (GetViewId() <= 0)
            {
                string msg = string.Format("getViewId() < 0");
                throw new CouchbaseLiteException(msg, new Status(Status.NotFound));
            }
            database.BeginTransaction();
            Status result = new Status(Status.InternalServerError);
            Cursor cursor = null;

            try
            {
                long lastSequence  = GetLastSequenceIndexed();
                long dbMaxSequence = database.GetLastSequenceNumber();
                if (lastSequence == dbMaxSequence)
                {
                    // nothing to do (eg,  kCBLStatusNotModified)
                    Log.V(Log.TagView, "lastSequence (%s) == dbMaxSequence (%s), nothing to do", lastSequence
                          , dbMaxSequence);
                    result.SetCode(Status.NotModified);
                    return;
                }
                // First remove obsolete emitted results from the 'maps' table:
                long sequence = lastSequence;
                if (lastSequence < 0)
                {
                    string msg = string.Format("lastSequence < 0 (%s)", lastSequence);
                    throw new CouchbaseLiteException(msg, new Status(Status.InternalServerError));
                }
                if (lastSequence == 0)
                {
                    // If the lastSequence has been reset to 0, make sure to remove
                    // any leftover rows:
                    string[] whereArgs = new string[] { Sharpen.Extensions.ToString(GetViewId()) };
                    database.GetDatabase().Delete("maps", "view_id=?", whereArgs);
                }
                else
                {
                    // Delete all obsolete map results (ones from since-replaced
                    // revisions):
                    string[] args = new string[] { Sharpen.Extensions.ToString(GetViewId()), System.Convert.ToString
                                                       (lastSequence), System.Convert.ToString(lastSequence) };
                    database.GetDatabase().ExecSQL("DELETE FROM maps WHERE view_id=? AND sequence IN ("
                                                   + "SELECT parent FROM revs WHERE sequence>? " + "AND parent>0 AND parent<=?)",
                                                   args);
                }
                int deleted = 0;
                cursor = database.GetDatabase().RawQuery("SELECT changes()", null);
                cursor.MoveToNext();
                deleted = cursor.GetInt(0);
                cursor.Close();
                // This is the emit() block, which gets called from within the
                // user-defined map() block
                // that's called down below.
                AbstractTouchMapEmitBlock emitBlock = new _AbstractTouchMapEmitBlock_428(this);
                //Log.v(Log.TAG_VIEW, "    emit(" + keyJson + ", "
                //        + valueJson + ")");
                // find a better way to propagate this back
                // Now scan every revision added since the last time the view was
                // indexed:
                string[] selectArgs = new string[] { System.Convert.ToString(lastSequence) };
                cursor = database.GetDatabase().RawQuery("SELECT revs.doc_id, sequence, docid, revid, json, no_attachments 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", selectArgs);
                long lastDocID = 0;
                bool 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/"))
                        {
                            // design docs don't get indexed!
                            keepGoing = cursor.MoveToNext();
                            continue;
                        }
                        string revId         = cursor.GetString(3);
                        byte[] json          = cursor.GetBlob(4);
                        bool   noAttachments = cursor.GetInt(5) > 0;
                        while ((keepGoing = cursor.MoveToNext()) && cursor.GetLong(0) == docID)
                        {
                        }
                        // Skip rows with the same doc_id -- these are losing conflicts.
                        if (lastSequence > 0)
                        {
                            // Find conflicts with documents from previous indexings.
                            string[] selectArgs2 = new string[] { System.Convert.ToString(docID), System.Convert.ToString
                                                                      (lastSequence) };
                            Cursor cursor2 = database.GetDatabase().RawQuery("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())
                            {
                                string oldRevId = cursor2.GetString(0);
                                // This is the revision that used to be the 'winner'.
                                // Remove its emitted rows:
                                long     oldSequence = cursor2.GetLong(1);
                                string[] args        = new string[] { Sharpen.Extensions.ToString(GetViewId()), System.Convert.ToString
                                                                          (oldSequence) };
                                database.GetDatabase().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;
                                    string[] selectArgs3 = new string[] { System.Convert.ToString(sequence) };
                                    json = Utils.ByteArrayResultForQuery(database.GetDatabase(), "SELECT json FROM revs WHERE sequence=?"
                                                                         , selectArgs3);
                                }
                            }
                        }
                        // Get the document properties, to pass to the map function:
                        EnumSet <Database.TDContentOptions> contentOptions = EnumSet.NoneOf <Database.TDContentOptions
                                                                                             >();
                        if (noAttachments)
                        {
                            contentOptions.AddItem(Database.TDContentOptions.TDNoAttachments);
                        }
                        IDictionary <string, object> properties = database.DocumentPropertiesFromJSON(json
                                                                                                      , docId, revId, false, sequence, contentOptions);
                        if (properties != null)
                        {
                            // Call the user-defined map() to emit new key/value
                            // pairs from this revision:
                            emitBlock.SetSequence(sequence);
                            mapBlock.Map(properties, emitBlock);
                        }
                    }
                }
                // Finally, record the last revision sequence number that was
                // indexed:
                ContentValues updateValues = new ContentValues();
                updateValues.Put("lastSequence", dbMaxSequence);
                string[] whereArgs_1 = new string[] { Sharpen.Extensions.ToString(GetViewId()) };
                database.GetDatabase().Update("views", updateValues, "view_id=?", whereArgs_1);
                // FIXME actually count number added :)
                Log.V(Log.TagView, "Finished re-indexing view: %s " + " up to sequence %s" + " (deleted %s added ?)"
                      , name, dbMaxSequence, deleted);
                result.SetCode(Status.Ok);
            }
            catch (SQLException e)
            {
                throw new CouchbaseLiteException(e, new Status(Status.DbError));
            }
            finally
            {
                if (cursor != null)
                {
                    cursor.Close();
                }
                if (!result.IsSuccessful())
                {
                    Log.W(Log.TagView, "Failed to rebuild view %s.  Result code: %d", name, result.GetCode
                              ());
                }
                if (database != null)
                {
                    database.EndTransaction(result.IsSuccessful());
                }
            }
        }
コード例 #2
0
ファイル: View.cs プロジェクト: jonlipsky/couchbase-lite-net
 public void UpdateIndex()
 {
     Log.V(Log.TagView, "Re-indexing view: %s", name);
     System.Diagnostics.Debug.Assert((mapBlock != null));
     if (GetViewId() <= 0)
     {
         string msg = string.Format("getViewId() < 0");
         throw new CouchbaseLiteException(msg, new Status(Status.NotFound));
     }
     database.BeginTransaction();
     Status result = new Status(Status.InternalServerError);
     Cursor cursor = null;
     try
     {
         long lastSequence = GetLastSequenceIndexed();
         long dbMaxSequence = database.GetLastSequenceNumber();
         if (lastSequence == dbMaxSequence)
         {
             // nothing to do (eg,  kCBLStatusNotModified)
             Log.V(Log.TagView, "lastSequence (%s) == dbMaxSequence (%s), nothing to do", lastSequence
                 , dbMaxSequence);
             result.SetCode(Status.NotModified);
             return;
         }
         // First remove obsolete emitted results from the 'maps' table:
         long sequence = lastSequence;
         if (lastSequence < 0)
         {
             string msg = string.Format("lastSequence < 0 (%s)", lastSequence);
             throw new CouchbaseLiteException(msg, new Status(Status.InternalServerError));
         }
         if (lastSequence == 0)
         {
             // If the lastSequence has been reset to 0, make sure to remove
             // any leftover rows:
             string[] whereArgs = new string[] { Sharpen.Extensions.ToString(GetViewId()) };
             database.GetDatabase().Delete("maps", "view_id=?", whereArgs);
         }
         else
         {
             // Delete all obsolete map results (ones from since-replaced
             // revisions):
             string[] args = new string[] { Sharpen.Extensions.ToString(GetViewId()), System.Convert.ToString
                 (lastSequence), System.Convert.ToString(lastSequence) };
             database.GetDatabase().ExecSQL("DELETE FROM maps WHERE view_id=? AND sequence IN ("
                  + "SELECT parent FROM revs WHERE sequence>? " + "AND parent>0 AND parent<=?)", 
                 args);
         }
         int deleted = 0;
         cursor = database.GetDatabase().RawQuery("SELECT changes()", null);
         cursor.MoveToNext();
         deleted = cursor.GetInt(0);
         cursor.Close();
         // This is the emit() block, which gets called from within the
         // user-defined map() block
         // that's called down below.
         AbstractTouchMapEmitBlock emitBlock = new _AbstractTouchMapEmitBlock_428(this);
         //Log.v(Log.TAG_VIEW, "    emit(" + keyJson + ", "
         //        + valueJson + ")");
         // find a better way to propagate this back
         // Now scan every revision added since the last time the view was
         // indexed:
         string[] selectArgs = new string[] { System.Convert.ToString(lastSequence) };
         cursor = database.GetDatabase().RawQuery("SELECT revs.doc_id, sequence, docid, revid, json, no_attachments 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", selectArgs);
         long lastDocID = 0;
         bool 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/"))
                 {
                     // design docs don't get indexed!
                     keepGoing = cursor.MoveToNext();
                     continue;
                 }
                 string revId = cursor.GetString(3);
                 byte[] json = cursor.GetBlob(4);
                 bool noAttachments = cursor.GetInt(5) > 0;
                 while ((keepGoing = cursor.MoveToNext()) && cursor.GetLong(0) == docID)
                 {
                 }
                 // Skip rows with the same doc_id -- these are losing conflicts.
                 if (lastSequence > 0)
                 {
                     // Find conflicts with documents from previous indexings.
                     string[] selectArgs2 = new string[] { System.Convert.ToString(docID), System.Convert.ToString
                         (lastSequence) };
                     Cursor cursor2 = database.GetDatabase().RawQuery("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())
                     {
                         string oldRevId = cursor2.GetString(0);
                         // This is the revision that used to be the 'winner'.
                         // Remove its emitted rows:
                         long oldSequence = cursor2.GetLong(1);
                         string[] args = new string[] { Sharpen.Extensions.ToString(GetViewId()), System.Convert.ToString
                             (oldSequence) };
                         database.GetDatabase().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;
                             string[] selectArgs3 = new string[] { System.Convert.ToString(sequence) };
                             json = Utils.ByteArrayResultForQuery(database.GetDatabase(), "SELECT json FROM revs WHERE sequence=?"
                                 , selectArgs3);
                         }
                     }
                 }
                 // Get the document properties, to pass to the map function:
                 EnumSet<Database.TDContentOptions> contentOptions = EnumSet.NoneOf<Database.TDContentOptions
                     >();
                 if (noAttachments)
                 {
                     contentOptions.AddItem(Database.TDContentOptions.TDNoAttachments);
                 }
                 IDictionary<string, object> properties = database.DocumentPropertiesFromJSON(json
                     , docId, revId, false, sequence, contentOptions);
                 if (properties != null)
                 {
                     // Call the user-defined map() to emit new key/value
                     // pairs from this revision:
                     emitBlock.SetSequence(sequence);
                     mapBlock.Map(properties, emitBlock);
                 }
             }
         }
         // Finally, record the last revision sequence number that was
         // indexed:
         ContentValues updateValues = new ContentValues();
         updateValues.Put("lastSequence", dbMaxSequence);
         string[] whereArgs_1 = new string[] { Sharpen.Extensions.ToString(GetViewId()) };
         database.GetDatabase().Update("views", updateValues, "view_id=?", whereArgs_1);
         // FIXME actually count number added :)
         Log.V(Log.TagView, "Finished re-indexing view: %s " + " up to sequence %s" + " (deleted %s added ?)"
             , name, dbMaxSequence, deleted);
         result.SetCode(Status.Ok);
     }
     catch (SQLException e)
     {
         throw new CouchbaseLiteException(e, new Status(Status.DbError));
     }
     finally
     {
         if (cursor != null)
         {
             cursor.Close();
         }
         if (!result.IsSuccessful())
         {
             Log.W(Log.TagView, "Failed to rebuild view %s.  Result code: %d", name, result.GetCode
                 ());
         }
         if (database != null)
         {
             database.EndTransaction(result.IsSuccessful());
         }
     }
 }