anchor.diff:  -include("ddfs_gc.hrl").
   
   -type node_info() :: {node(), {non_neg_integer(), non_neg_integer()}}.
  --type gc_stats() :: 'none' | gc_run_stats().
  +-type gc_stats() :: none | gc_run_stats().
   
   -record(state, {tags      = gb_trees:empty() :: gb_tree(),
  -                tag_cache = false            :: 'false' | gb_set(),
  +                tag_cache = false            :: false | gb_set(),
                   cache_refresher              :: pid(),
   
                   nodes             = []                :: [node_info()],
  
positive.code: tag_operation(Op, Tag, Timeout) ->
      gen_server:call(?MODULE, {tag, Op, Tag}, Timeout).
  
  -spec tag_notify(term(), tagname()) -> 'ok'.
  tag_notify(Op, Tag) ->
      gen_server:cast(?MODULE, {tag_notify, Op, Tag}).
  
  -spec get_nodeinfo('all') -> {'ok', [node_info()]}.
  get_nodeinfo(all) ->
      gen_server:call(?MODULE, {get_nodeinfo, all}).
  
  -spec get_read_nodes() -> {'ok', [node()], non_neg_integer()} | {'error', term()}.
  get_read_nodes() ->
      gen_server:call(?MODULE, get_read_nodes).
  
  -spec gc_blacklist() -> {'ok', [node()]}.
  gc_blacklist() ->
      gen_server:call(?MODULE, gc_blacklist).
  
  -spec gc_blacklist([node()]) -> 'ok'.
  gc_blacklist(Nodes) ->
      gen_server:cast(?MODULE, {gc_blacklist, Nodes}).
  
  -spec gc_stats() -> {'ok', 'none' | {gc_stats(), erlang:timestamp()}} | {'error', term()}.
  gc_stats() ->
      gen_server:call(?MODULE, gc_stats).
  
  -spec get_hosted_tags(host()) -> {'ok', [tagname()]} | {'error', term()}.
  get_hosted_tags(Host) ->
      gen_server:call(?MODULE, {get_hosted_tags, Host}).
  
  -spec choose_write_nodes(non_neg_integer(), [node()]) -> {'ok', [node()]}.
  choose_write_nodes(K, Exclude) ->
      gen_server:call(?MODULE, {choose_write_nodes, K, Exclude}).
  
  -spec get_tags('gc') -> {'ok', [tagname()], [node()]} | 'too_many_failed_nodes';
                ('safe') -> {'ok', [binary()]} | 'too_many_failed_nodes'.
  get_tags(Mode) ->
      gen_server:call(?MODULE, {get_tags, Mode}, ?GET_TAG_TIMEOUT).
  
  -spec new_blob(string()|object_name(), non_neg_integer(), [node()]) ->
                        'too_many_replicas' | {'ok', [nonempty_string()]}.
  new_blob(Obj, K, Exclude) ->
      gen_server:call(?MODULE, {new_blob, Obj, K, Exclude}).
  
  -spec safe_gc_blacklist() -> {'ok', [node()]} | {'error', term()}.
  safe_gc_blacklist() ->
      gen_server:call(?MODULE, safe_gc_blacklist).
  
  -spec safe_gc_blacklist(gb_set()) -> 'ok'.
  safe_gc_blacklist(SafeGCBlacklist) ->
      gen_server:cast(?MODULE, {safe_gc_blacklist, SafeGCBlacklist}).
  
  -spec update_gc_stats(gc_run_stats()) -> 'ok'.
  update_gc_stats(Stats) ->
      gen_server:cast(?MODULE, {update_gc_stats, Stats}).
  
  -type nodes_update() :: [{node(), boolean(), boolean()}].
  -spec update_nodes(nodes_update()) -> 'ok'.
  update_nodes(DDFSNodes) ->
      gen_server:cast(?MODULE, {update_nodes, DDFSNodes}).
  
  -spec update_nodestats(gb_tree()) -> 'ok'.
  update_nodestats(NewNodes) ->
      gen_server:cast(?MODULE, {update_nodestats, NewNodes}).
  
  -spec update_tag_cache(gb_set()) -> 'ok'.
  update_tag_cache(TagCache) ->
      gen_server:cast(?MODULE, {update_tag_cache, TagCache}).
  
  -spec refresh_tag_cache() -> 'ok'.
  refresh_tag_cache() ->
      gen_server:cast(?MODULE, refresh_tag_cache).
  
  
negative.code: % Tag request: Start a new tag server if one doesn't exist already. Forward
  % the request to the tag server.
  
  -spec get_tag_pid(tagname(), gb_tree(), false | gb_set()) ->
                           {pid(), gb_tree()}.
  get_tag_pid(Tag, Tags, Cache) ->
      case gb_trees:lookup(Tag, Tags) of
  