anchor.diff:  
       NumPieces = length(PieceSizes),
       PiecesValid   = etorrent_pieceset:from_list(FetchedPieces, NumPieces),
  -    PiecesChunked = etorrent_pieceset:new(NumPieces),
   
       %% Initialize a full chunkset for all pieces that are left to download
  -    %% but don't mark them as chunked before a chunk has been deleted from
  +    %% but don't mark them as begun before a chunk has been deleted from
       %% any of the chunksets.
  +    %% Initialize an empty chunkset for all valid pieces.
       AllIndexes = lists:seq(0, NumPieces - 1),
       AllPieces = etorrent_pieceset:from_list(AllIndexes, NumPieces),
       PiecesInvalid = etorrent_pieceset:difference(AllPieces, PiecesValid),
  +    InvalidList = etorrent_pieceset:to_list(PiecesInvalid),
  +    ValidList = etorrent_pieceset:to_list(PiecesValid),
  +    States = [{N, false} || N <- InvalidList] ++ [{N, true} || N <- ValidList],
       ChunkList = [begin
           Size = orddict:fetch(N, PieceSizes),
  -        Set  = etorrent_chunkset:new(Size, ChunkSize),
  +        Set = case IsValid of
  +            false -> etorrent_chunkset:new(Size, ChunkSize);
  +            true  -> etorrent_chunkset:from_list(Size, ChunkSize, [])
  +        end,
           {N, Set}
  -    end || N <- etorrent_pieceset:to_list(PiecesInvalid)],
  -
  -    %% Initialize an empty chunkset for all pieces that are valid.
  -    CompletedList = [begin
  -        Size = orddict:fetch(N, PieceSizes),
  -        Set  = etorrent_chunkset:from_list(Size, ChunkSize, []),
  -        {N, Set}
  -    end || N <- etorrent_pieceset:to_list(PiecesValid)],
  -
  -    AllChunksets = lists:sort(CompletedList ++ ChunkList),
  -    PieceChunks  = array:from_orddict(AllChunksets),
  +    end || {N, IsValid} <- lists:sort(States)],
  +    ChunkSets = array:from_orddict(ChunkList),
   
       InitState = #state{
           torrent_id=TorrentID,
           chunk_size=ChunkSize,
           pieces_valid=PiecesValid,
  -        pieces_begun=PiecesChunked,
  -        piece_chunks=PieceChunks,
  +        %% All valid pieces are also begun, assigned and stored
  +        pieces_begun=PiecesValid,
  +        pieces_assigned=PiecesValid,
  +        pieces_stored=PiecesValid,
  +        %% Initially, the sets of assigned and stored chunks are equal
  +        chunks_assigned=ChunkSets,
  +        chunks_stored=ChunkSets,
           peer_monitors=etorrent_monitorset:new()},
       {ok, InitState}.
   
  
positive.code:         %% None that we are not already downloading
          %% but one ore more that we would want to download
          {0, N} ->
              etorrent_pieceset:min(SubOptimalPieces);
          %% One or more that we are already downloading
          {N, _} ->
              etorrent_pieceset:min(OptimalPieces)
      end,
  
      case PieceIndex of
          none ->
              {reply, {error, not_interested}, State};
          PieceIndex ->
              Chunkset    = array:get(PieceIndex, PieceChunks),
              {Offs, Len} = etorrent_chunkset:min(Chunkset),
              ?debugVal([Offs, Len, Chunkset]),
              NewChunkset = etorrent_chunkset:delete(Offs, Len, Chunkset),
              NewChunks   = array:set(PieceIndex, NewChunkset, PieceChunks),
              NewChunked  = etorrent_pieceset:insert(PieceIndex, PiecesChunked),
              %% Add the chunk to this peer's set of open requests
              OpenReqs = etorrent_monitorset:fetch(PeerPid, Peers),
              NewReqs  = gb_trees:insert({PieceIndex, Offs}, Len, OpenReqs),
              NewPeers = etorrent_monitorset:update(PeerPid, NewReqs, Peers),
  
              NewState = State#state{
                  pieces_begun=NewChunked,
                  piece_chunks=NewChunks,
                  peer_monitors=NewPeers},
              {reply, {ok, [{PieceIndex, Offs, Len}]}, NewState}
      end;
  
negative.code:     NewState = State#state{peer_monitors=NewPeers},
      {reply, ok, NewState};
  
  handle_call({mark_dropped, Pid, Index, Offset, Length}, _, State) ->
      #state{
          pieces_assigned=Assigned,
          chunks_assigned=AssignedChunks,
          peer_monitors=Peers} = State,
       %% Reemove the chunk from the peer's set of open requests
       OpenReqs = etorrent_monitorset:fetch(Pid, Peers),
       NewReqs  = gb_trees:delete({Index, Offset}, OpenReqs),
       NewPeers = etorrent_monitorset:update(Pid, NewReqs, Peers),
   
       %% Add the chunk back to the chunkset of the piece.
       Chunks = array:get(Index, AssignedChunks),
       NewChunks = etorrent_chunkset:insert(Offset, Length, Chunks),
       NewAssignedChunks = array:set(Index, NewChunks, AssignedChunks),
  
       %% This piece is no longer in the assigned state
       NewAssigned = etorrent_pieceset:delete(Index, Assigned),
   
       NewState = State#state{
           pieces_assigned=NewAssigned,
           chunks_assigned=NewAssignedChunks,
           peer_monitors=NewPeers},
      {reply, ok, NewState};
  
  handle_call({mark_all_dropped, Pid}, _, State) ->
      #state{
          pieces_assigned=Assigned,
          chunks_assigned=PieceChunks,
          peer_monitors=Peers} = State,
      %% Add the chunks back to the chunkset of each piece.
      OpenReqs = etorrent_monitorset:fetch(Pid, Peers),
      NewPieceChunks = lists:foldl(fun({Index, Offset, Length}, Acc) ->
          insert_chunk(Index, Offset, Length, Acc)
      end, PieceChunks, chunk_list(OpenReqs)),
  
      %% None of the pieces that had open requests are no longer assigned
      NewAssigned = lists:foldl(fun({Index, _, _}, Acc) ->
          etorrent_pieceset:delete(Index, Acc)
      end, Assigned, chunk_list(OpenReqs)),
  
      %% Replace the peer's set of open requests with an empty set
      NewPeers = etorrent_monitorset:update(Pid, gb_trees:empty(), Peers),
      NewState = State#state{
          pieces_assigned=NewAssigned,
          chunks_assigned=NewPieceChunks,
          peer_monitors=NewPeers},
      {reply, ok, NewState}.
  
  
  
  handle_cast(_, _) ->
      not_implemented.
  
  handle_info({'DOWN', _, process, Pid, _}, State) ->
      #state{
          pieces_assigned=Assigned,
          chunks_assigned=PieceChunks,
          peer_monitors=Peers} = State,
      %% Add the chunks back to the chunkset of each piece.
      OpenReqs = etorrent_monitorset:fetch(Pid, Peers),
      NewPieceChunks = lists:foldl(fun({PieceIndex, Offset, Length}, Acc) ->
          insert_chunk(PieceIndex, Offset, Length, Acc)
      end, PieceChunks, chunk_list(OpenReqs)),
  
      %% None of the pieces that had open requests are no longer assigned
      NewAssigned = lists:foldl(fun({Index, _, _}, Acc) ->
          etorrent_pieceset:delete(Index, Acc)
      end, Assigned, chunk_list(OpenReqs)),
  
      %% Delete the peer from the set of monitored peers
      NewPeers = etorrent_monitorset:delete(Pid, Peers),
      NewState = State#state{
          pieces_assigned=NewAssigned,
          chunks_assigned=NewPieceChunks,
          peer_monitors=NewPeers},
      {noreply, NewState}.
  
  