anchor.diff:  %
   % The XRM maintains local state about all in-progress replications and
   % comprises of the following data structures:
  -% XSTORE: An ETS set of {XDocId, XRep, Vbuckets} tuples
  +% XSTORE: An ETS set of {XDocId, XRep, TriggeredVbs, UntriggeredVbs} tuples
   %         XDocId: Id of a user created XDC replication document
   %         XRep: The parsed #rep record for the document
  -%         Vbuckets: The list of managed active vbuckets
  -%                   (useful for responding to vbucket map changes)
  +%         TriggeredVbs: Vbuckets whose replication was successfully triggered
  +%         UntriggeredVbs: Vbuckets whose replication could not be triggered.
  +%                         These are periodically retried.
   %
   % X2CSTORE: An ETS bag of {XDocId, CRepPid} tuples
   %           CRepPid: Pid of the Couch process responsible for an individual
  
positive.code:     case {SrcBucketLookup, TgtBucketLookup} of
      {not_present, not_present} ->
          ?log_error("~s: source and target buckets not found", [XDocId]),
          true = ets:insert(?XSTORE, {XDocId, XRep, []}),
          {error, not_present};
      {not_present, _} ->
          ?log_error("~s: source bucket not found", [XDocId]),
          true = ets:insert(?XSTORE, {XDocId, XRep, []}),
          {error, not_present};
      {_, not_present} ->
          ?log_error("~s: target bucket not found", [XDocId]),
          true = ets:insert(?XSTORE, {XDocId, XRep, []}),
          {error, not_present};
      {{ok, SrcBucketConfig}, {ok, {TgtVbMap, TgtNodes}}} ->
          MyVbuckets = xdc_rep_utils:my_active_vbuckets(SrcBucketConfig),
          {TriggeredVbuckets, _} = start_vbucket_replications(
              XDocId, SrcBucket, TgtVbMap, TgtNodes, MyVbuckets, 0),
          true = ets:insert(?XSTORE, {XDocId, XRep, TriggeredVbuckets}),
          create_xdc_rep_info_doc(XDocId, XRepId, TriggeredVbuckets, RepDbName,
                                  XDocBody),
          ok
      end.
  
negative.code:         fun([XDocId,
               #rep{source = SrcBucket,
                    target = {_, TgtBucket, _, _, _, _, _, _, _, _}},
               PrevTriggeredVbs,
               PrevUntriggeredVbs]) ->
              SrcBucketConfig =
                  proplists:get_value(?b2l(SrcBucket), BucketConfigs),
              CurrVbs = xdc_rep_utils:my_active_vbuckets(SrcBucketConfig),
              maybe_adjust_xdc_replication(
                  XDocId, SrcBucket, TgtBucket, PrevTriggeredVbs,
                  PrevUntriggeredVbs, CurrVbs)
          end,
          ets:match(?XSTORE, {'$1', '$2', '$3', '$4'})).
  
  
  maybe_adjust_xdc_replication(XDocId, SrcBucket, TgtBucket, PrevTriggeredVbs,
                               PrevUntriggeredVbs, CurrVbs) ->
      PrevVbs = PrevTriggeredVbs ++ PrevUntriggeredVbs,
      {AcquiredVbs, LostVbs} = xdc_rep_utils:lists_difference(CurrVbs, PrevVbs),
  
      % Start Couch replications for the newly acquired vbuckets
      {ok, {TgtVbMap, TgtNodes}} =
          xdc_rep_utils:remote_vbucketmap_nodelist(TgtBucket),
      {TriggeredVbs1, UntriggeredVbs1} = start_vbucket_replications(
          XDocId, SrcBucket, TgtVbMap, TgtNodes, AcquiredVbs, 0),
  
      % Add entries for the new Couch replications to the replication info doc
      couch_replication_manager:update_rep_doc(
          xdc_rep_utils:info_doc_id(XDocId),
          xdc_rep_utils:vb_rep_state_list(TriggeredVbs1, <<"triggered">>)),
  
      % Cancel Couch replications for the lost vbuckets
      CRepPidsToCancel =
          try
              [CRepPid || CRepPid <- ets:lookup_element(?X2CSTORE, XDocId, 2),
                          lists:member(ets:lookup_element(?CSTORE, CRepPid, 3),
                                       LostVbs)]
          catch error:badarg ->
              []
          end,
  