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.