You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by da...@apache.org on 2009/03/06 23:06:39 UTC

svn commit: r751098 - in /couchdb/branches/rep_security: share/www/script/test/bulk_docs.js share/www/script/test/replication.js src/couchdb/couch_rep.erl

Author: damien
Date: Fri Mar  6 22:06:39 2009
New Revision: 751098

URL: http://svn.apache.org/viewvc?rev=751098&view=rev
Log:
Added more replication tests

Modified:
    couchdb/branches/rep_security/share/www/script/test/bulk_docs.js
    couchdb/branches/rep_security/share/www/script/test/replication.js
    couchdb/branches/rep_security/src/couchdb/couch_rep.erl

Modified: couchdb/branches/rep_security/share/www/script/test/bulk_docs.js
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/share/www/script/test/bulk_docs.js?rev=751098&r1=751097&r2=751098&view=diff
==============================================================================
--- couchdb/branches/rep_security/share/www/script/test/bulk_docs.js (original)
+++ couchdb/branches/rep_security/share/www/script/test/bulk_docs.js Fri Mar  6 22:06:39 2009
@@ -20,25 +20,40 @@
 
   // Create the docs
   var results = db.bulkSave(docs);
+  
   T(results.length == 5);
   for (var i = 0; i < 5; i++) {
     T(results[i].id == docs[i]._id);
     T(results[i].rev);
+    // Update the doc
     docs[i].string = docs[i].string + ".00";
   }
 
-  // Update the docs
+  // Save the docs
   results = db.bulkSave(docs);
   T(results.length == 5);
   for (i = 0; i < 5; i++) {
     T(results[i].id == i.toString());
+    
+    // set the delete flag to delete the docs in the next step
     docs[i]._deleted = true;
   }
+  
+  // now test a bulk update with a conflict
+  
+  var doc = db.open("0");
+  db.save(doc);
 
   // Delete the docs
   results = db.bulkSave(docs);
   T(results.length == 5);
-  for (i = 0; i < 5; i++) {
+  T(results[0].id == "0");
+  T(results[0].rev === undefined);
+  T(results[0].error == "conflict");
+  
+  for (i = 1; i < 5; i++) {
+    T(results[i].id == i.toString());
+    T(results[i].rev)
     T(db.open(docs[i]._id) == null);
   }
   

Modified: couchdb/branches/rep_security/share/www/script/test/replication.js
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/share/www/script/test/replication.js?rev=751098&r1=751097&r2=751098&view=diff
==============================================================================
--- couchdb/branches/rep_security/share/www/script/test/replication.js (original)
+++ couchdb/branches/rep_security/share/www/script/test/replication.js Fri Mar  6 22:06:39 2009
@@ -160,7 +160,7 @@
           dbA.deleteDoc({_id:"foo", _rev:docA._conflicts[0]});
         };
         
-        this.afterBA2 = function(dbA, dbB) {            
+        this.afterBA2 = function(dbA, dbB) {
           // open documents and include the conflict meta data
           var docA = dbA.open("foo", {conflicts: true});
           var docB = dbB.open("foo", {conflicts: true});
@@ -182,6 +182,8 @@
     var result = CouchDB.replicate(A, B);
     
     var seqA = result.source_last_seq;
+    T(0 == result.history[0].start_last_seq);
+    T(result.history[1] === undefined)
 
     for(test in repTests) {
       if(repTests[test].afterAB1) repTests[test].afterAB1(dbA, dbB);
@@ -190,16 +192,23 @@
     result = CouchDB.replicate(B, A);
     
     var seqB = result.source_last_seq;
+    T(0 == result.history[0].start_last_seq);
+    T(result.history[1] === undefined)
 
     for(test in repTests) {
       if(repTests[test].afterBA1) repTests[test].afterBA1(dbA, dbB);
     }
 
-    result = CouchDB.replicate(A, B)
+    var result2 = CouchDB.replicate(A, B);
     
-    T(seqA < result.source_last_seq);
+    // each successful replication produces a new session id
+    T(result2.session_id != result.session_id);
     
-    seqA = result.source_last_seq;
+    T(seqA < result2.source_last_seq);
+    T(seqA == result2.history[0].start_last_seq);
+    T(result2.history[1].end_last_seq == seqA)
+    
+    seqA = result2.source_last_seq;
 
     for(test in repTests) {
       if(repTests[test].afterAB2) repTests[test].afterAB2(dbA, dbB);
@@ -208,12 +217,28 @@
     result = CouchDB.replicate(B, A)
     
     T(seqB < result.source_last_seq);
+    T(seqB == result.history[0].start_last_seq);
+    T(result.history[1].end_last_seq == seqB)
     
     seqB = result.source_last_seq;
 
     for(test in repTests) {
       if(repTests[test].afterBA2) repTests[test].afterBA2(dbA, dbB);
     }
-
+    
+    // do an replication where nothing has changed
+    result2 = CouchDB.replicate(B, A);
+    T(result2.no_changes == true);
+    T(result2.session_id == result.session_id);
+    
+    // do a full (not incremental) replication
+    
+    result = CouchDB.replicate(B, A, {options:{full:true}})
+    
+    T(0 == result.history[0].start_last_seq);
+    T(seqB == result.source_last_seq);
+    T(result.history[0].end_last_seq == seqB);
+    T(result.history[1].end_last_seq == seqB);
+    
   }
 };

Modified: couchdb/branches/rep_security/src/couchdb/couch_rep.erl
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/src/couchdb/couch_rep.erl?rev=751098&r1=751097&r2=751098&view=diff
==============================================================================
--- couchdb/branches/rep_security/src/couchdb/couch_rep.erl (original)
+++ couchdb/branches/rep_security/src/couchdb/couch_rep.erl Fri Mar  6 22:06:39 2009
@@ -84,50 +84,58 @@
     SrcInstanceStartTime = proplists:get_value(instance_start_time, InfoSrc),
     TgtInstanceStartTime = proplists:get_value(instance_start_time, InfoTgt),
     
-    case proplists:get_value(full, Options, false) of
-    true ->
-         RepRecSrc = RepRecTgt = #doc{id=RepRecKey};
-    false ->
-        RepRecSrc =
-        case open_doc(DbSrc, RepRecKey, []) of
-        {ok, SrcDoc} ->
-            ?LOG_DEBUG("Found existing replication record on source", []),
-            SrcDoc;
-        _ -> #doc{id=RepRecKey}
-        end,
+    RepRecDocSrc =
+    case open_doc(DbSrc, RepRecKey, []) of
+    {ok, SrcDoc} ->
+        ?LOG_DEBUG("Found existing replication record on source", []),
+        SrcDoc;
+    _ -> #doc{id=RepRecKey}
+    end,
 
-        RepRecTgt =
-        case open_doc(DbTgt, RepRecKey, []) of
-        {ok, TgtDoc} ->
-            ?LOG_DEBUG("Found existing replication record on target", []),
-            TgtDoc;
-        _ -> #doc{id=RepRecKey}
-        end
+    RepRecDocTgt =
+    case open_doc(DbTgt, RepRecKey, []) of
+    {ok, TgtDoc} ->
+        ?LOG_DEBUG("Found existing replication record on target", []),
+        TgtDoc;
+    _ -> #doc{id=RepRecKey}
     end,
+    
 
-    #doc{body={OldRepHistoryProps}} = RepRecSrc,
-    #doc{body={OldRepHistoryPropsTrg}} = RepRecTgt,
+    #doc{body={RepRecProps}} = RepRecDocSrc,
+    #doc{body={RepRecPropsTgt}} = RepRecDocTgt,
 
-    SeqNum =
-    case OldRepHistoryProps == OldRepHistoryPropsTrg of
+    
+    case proplists:get_value(<<"session_id">>, RepRecProps) == 
+            proplists:get_value(<<"session_id">>, RepRecPropsTgt) of
     true ->
-        % if the records are identical, then we have a valid replication history
-        proplists:get_value(<<"source_last_seq">>, OldRepHistoryProps, 0);
+        % if the records have the same session id,
+        % then we have a valid replication history
+        OldSeqNum = proplists:get_value(<<"source_last_seq">>, RepRecProps, 0),
+        OldHistory = proplists:get_value(<<"history">>, RepRecProps, []);
     false ->
         ?LOG_INFO("Replication records differ. "
                 "Performing full replication instead of incremental.", []),
         ?LOG_DEBUG("Record on source:~p~nRecord on target:~p~n",
-                [OldRepHistoryProps, OldRepHistoryPropsTrg]),
-        0
+                [RepRecProps, RepRecPropsTgt]),
+        OldSeqNum = 0,
+        OldHistory = []
+    end,
+    
+    
+    case proplists:get_value(full, Options, false) of
+    true  -> StartSeqNum = 0;
+    false -> StartSeqNum = OldSeqNum
     end,
 
-    {NewSeqNum, Stats} = pull_rep(DbTgt, DbSrc, SeqNum),    
+    {NewSeqNum, Stats} = pull_rep(DbTgt, DbSrc, StartSeqNum),    
     
-    case NewSeqNum == SeqNum andalso OldRepHistoryProps /= [] of
+    case NewSeqNum == StartSeqNum andalso StartSeqNum > 0 of
     true ->
-        % nothing changed, don't record results
-        {ok, {OldRepHistoryProps}};
+        % nothing changed, don't record any results
+        {ok, {[{<<"no_changes">>, true} | RepRecProps]}};
     false ->
+        % something changed, record results for incremental replication,
+        
         % commit changes to both src and tgt. The src because if changes
         % we replicated are lost, we'll record the a seq number ahead 
         % of what was committed. If those changes are lost and the seq number
@@ -152,29 +160,28 @@
             ?LOG_INFO("A server has restarted sinced replication start. "
                 "Not recording the new sequence number to ensure the "
                 "replication is redone and documents reexamined.", []),
-            SeqNum
+            StartSeqNum
         end,
-        % convert the stats record into a proplist
+        % convert the stats record into a proplist and then to json
         [rep_stats | StatsList] = tuple_to_list(Stats),
         StatFieldNames =
                 [?l2b(atom_to_list(T)) || T <- record_info(fields, rep_stats)],
         StatProps = lists:zip(StatFieldNames, StatsList),
-        HistEntries =[
-            {
+        
+        NewHistoryEntry = {
                 [{<<"start_time">>, list_to_binary(ReplicationStartTime)},
                 {<<"end_time">>, list_to_binary(httpd_util:rfc1123_date())},
-                {<<"start_last_seq">>, SeqNum},
-                {<<"end_last_seq">>, NewSeqNum} | StatProps]}
-            | proplists:get_value(<<"history">>, OldRepHistoryProps, [])],
-        % something changed, record results
+                {<<"start_last_seq">>, StartSeqNum},
+                {<<"end_last_seq">>, NewSeqNum} | StatProps]},
+        % limit history to 50 entries
+        HistEntries =lists:sublist([NewHistoryEntry |  OldHistory], 50),
         NewRepHistory =
-            {
-                [{<<"session_id">>, couch_util:new_uuid()},
-                {<<"source_last_seq">>, RecordSeqNum},
-                {<<"history">>, lists:sublist(HistEntries, 50)}]},
+                {[{<<"session_id">>, couch_util:new_uuid()},
+                  {<<"source_last_seq">>, RecordSeqNum},
+                  {<<"history">>, HistEntries}]},
 
-        {ok, _} = update_doc(DbSrc, RepRecSrc#doc{body=NewRepHistory}, []),
-        {ok, _} = update_doc(DbTgt, RepRecTgt#doc{body=NewRepHistory}, []),
+        {ok, _} = update_doc(DbSrc, RepRecDocSrc#doc{body=NewRepHistory}, []),
+        {ok, _} = update_doc(DbTgt, RepRecDocTgt#doc{body=NewRepHistory}, []),
         {ok, NewRepHistory}
     end.