anchor.diff:  -module(mem3).
   
   -export([start/0, stop/0, restart/0, nodes/0, node_info/2, shards/1, shards/2,
  -    choose_shards/2, n/1, dbname/1, ushards/1]).
  +    choose_shards/2, n/1, dbname/1, ushards/1, ushards/2]).
   -export([sync_security/0, sync_security/1]).
   -export([compare_nodelists/0, compare_shards/1]).
   -export([quorum/1, group_by_proximity/1]).
  
positive.code:     [H|T] = lists:nthtail(N, Acc),
      apportion(Shares, lists:sublist(Acc, N) ++ [H+1|T], Remaining - 1).
  
  live_shards(DbName) ->
      Nodes = [node()|erlang:nodes()],
      [S || #shard{node=Node} = S <- shards(DbName), lists:member(Node, Nodes)].
  
  group_by_proximity(Shards) ->
      {Local, Remote} = lists:partition(fun(S) -> S#shard.node =:= node() end,
          Shards),
      LocalZone = mem3:node_info(node(), <<"zone">>),
      Fun = fun(S) -> mem3:node_info(S#shard.node, <<"zone">>) =:= LocalZone end,
      {SameZone, DifferentZone} = lists:partition(Fun, Remote),
      {Local, SameZone, DifferentZone}.
  
  
negative.code: 
  -spec ushards(DbName::iodata()) -> [#shard{}].
  ushards(DbName) ->
      Nodes = [node()|erlang:nodes()],
      ZoneMap = zone_map(Nodes),
      ushards(live_shards(DbName, Nodes), ZoneMap).
  
  ushards(Shards0, ZoneMap) ->
      {L,S,D} = group_by_proximity(Shards0, ZoneMap),
      % Prefer shards in the local zone over shards in a different zone,
      % but sort each zone separately to ensure a consistent choice between
      % nodes in the same zone.
  