anchor.diff:  % the blacklisted node (3).  The actual removal is performed by the
   % corresponding ddfs_tag.
   %
  -% The blacklisted node can be removed by the admin from the config
  -% after ensuring that no tag contains references to data hosted on it.
  -% After a node is put on the blacklist, there might need to be several
  -% runs of GC/RR before the node removal is safe.
  -%
   % The blob reference removal requires an invariant: that any operations
   % on a tag do not modify the replica set for a blob in the tag, other
   % than perhaps removing the replica set completely.  This is because
  
positive.code: handle_info({'EXIT', Pid, normal}, #state{phase = rr_blobs_wait, rr_pid = RR} = S)
    when Pid == RR  ->
      % The RR process has finished normally, and we can proceed to the
      % second phase of RR: start updating the tags.
      error_logger:info_report({"GC: done with blob replication, entering rr_tags"}),
      gen_server:cast(self(), {rr_tags, S#state.tags}),
      {noreply, S#state{rr_pid = undefined, phase = rr_tags}};
  handle_info({'EXIT', Pid, Reason}, #state{phase = Phase, rr_pid = RR} = S)
    when Pid == RR  ->
      % Unexpected exit of RR process; exit.
  
negative.code: % This invariant is ensured by comparing the tag id used for the
  % safety check, with the tag id at the time of the filter operation.
  % If the two differ, the filter operation is not performed.
  %
  % In the rr_tags phase, as the tags are scanned for updates, we also
  % track whether there exist references to blob replicas on gc
  % blacklisted nodes, and whether sufficient tag replicas exist on
  % non-blacklisted nodes.  At the end of the phase, this helps to
  % compute the set of blacklisted nodes that can be safely removed from
  % DDFS.
  
  -module(ddfs_gc_main).
  -behaviour(gen_server).
  