anchor.diff:  -module(etorrent_scarcity).
   -behaviour(gen_server).
   %% @author Magnus Klaar <magnus.klaar@sgsstudentbostader.se>
  -%% @doc A set of pieces ordered by scarcity
  -%%
  -%% This module implements a piece set that is ordered by the number of peers
  -%% that provide a valid copy of the piece. This is implemented by inserting
  -%% {NumPeers, PieceIndex} pairs into an ordered set.
  -%%
  -%% An array mapping piece indexes to the number of peers providing the piece
  -%% is also maintained to ensure that we don't need to scan through the set
  -%% for each update.
  +%% @doc A server to track how many peers provide each piece
  +%%
  +%% The scarcity server associates a counter with each piece. When
  +%% a peer comes online it registers it's prescence to the scarcity
  +%% server. After the peer has registered it's precence it is responsible
  +%% for keeping the scarcity server updated with additions to the
  +%% set of pieces that it's providing, the peer is also expected to
  +%% provide a copy of the updated piece set to the server.
  +%%
  +%% The server is expected to increment the counter and reprioritize
  +%% the set of pieces of a torrent when the scarcity changes. When a
  +%% peer exits the server is responsible for decrementing the counter
  +%% for each piece that was provided by the peerl.
  +%%
  +%% The purpose of the server is not to provide a mapping between
  +%% peers and pieces to other processes.
  +%%
  +%% ## notes on implementation
  +%% A complete piece set is provided on each update in order to reduce
  +%% the amount of effort spent on keeping the two sets synced. This also
  +%% reduces memory usage for torrents with more than 512 pieces due to
  +%% the way piece sets are implemented (2011-03-09).
   %% @end
   
   
  
positive.code:     gen_server:call(SrvPid, {add_peer, self(), Pieceset}).
  
  
  %% @doc
  %% @end
  -spec add_piece(torrent_id(), pos_integer(), pieceset()) -> ok.
  add_piece(TorrentID, Index, Pieceset) ->
      SrvPid = lookup_scarcity_server(TorrentID),
      gen_server:call(SrvPid, {add_piece, self(), Index, Pieceset}).
  
  %% @doc
  %% @end
  -spec get_order(torrent_id(), pieceset()) -> {ok, [pos_integer()]}.
  get_order(TorrentID, Pieceset) ->
  
negative.code:     ?assertEqual(self(), ?scarcity:await_scarcity_server(0)).
  
  server_registers_case() ->
      {ok, Pid} = ?scarcity:start_link(1),
      ?assertEqual(Pid, ?scarcity:lookup_scarcity_server(1)).
  
  initial_ordering_case() ->
      {ok, _} = ?scarcity:start_link(2),
      {ok, Order} = ?scarcity:get_order(2, pieces([0,1,2,3,4,5,6,7])),
      ?assertEqual([0,1,2,3,4,5,6,7], Order).
  
  empty_ordering_case() ->
      {ok, _} = ?scarcity:start_link(3),
      {ok, Order} = ?scarcity:get_order(3, pieces([])),
      ?assertEqual([], Order).
  
  init_pieceset_case() ->
      {ok, _} = ?scarcity:start_link(4),
      ?assertEqual(ok, ?scarcity:add_peer(4, pieces([]))).
  
  one_available_case() ->
      {ok, _} = ?scarcity:start_link(5),
      ok = ?scarcity:add_peer(5, pieces([])),
      ?assertEqual(ok, ?scarcity:add_piece(5, 0, pieces([0]))),
      Pieces  = pieces([0,1,2,3,4,5,6,7]),
  