anchor.diff:  %% under the License.
   %%
   %% -------------------------------------------------------------------
  +%%
  +%% Hashtree EQC test.
  +%%
  +%% Generates a pair of logically identical AAE trees populated with data
  +%% and some phantom trees in the same leveldb database to exercise all
  +%% of the cases in iterate.
  +%%
  +%% Then runs commands to insert, delete, snapshot, update tree
  +%% and compare.
  +%%
  +%% The expected values are stored in two ETS tables t1 and t2,
  +%% with the most recently snapshotted values copied to tables s1 and s2.
  +%% (the initial common seed data is not included in the ETS tables).
  +%%
  +%% The hashtree's themselves are stored in the process dictionary under
  +%% key t1 and t2.  This helps with shrinking as it reduces dependencies
  +%% between states (or at least that's why I remember doing it).
  +%%
  +%% Model state stores where each tree is through the snapshot/update cycle.
  +%% The command frequencies are deliberately manipulated to make it more
  +%% likely that compares will take place once both trees are updated.
  +%%
   
   -module(hashtree_eqc).
   -compile([export_all]).
  
positive.code:                   end, Objects),
      ok.
  
  write_both(Objects) ->
      write(t1, Objects),
      write(t2, Objects),
      ok.
  
  delete(T, Key) ->
      put(T, hashtree:delete(Key, get(T))),
      ets:delete(T, Key),
      ok.
  
  delete_both(Key) ->
      delete(t1, Key),
      delete(t2, Key),
      ok.
  
  update_tree(T) ->
      put(T, hashtree:update_tree(get(T))),
      ok.
  
  rehash_tree(T) ->
      put(T, hashtree:rehash_tree(get(T))),
      ok.
  
  reopen_tree(T) ->
      HT = hashtree:flush_buffer(get(T)),
      {Segments, Width, MemLevels} = {hashtree:segments(HT), hashtree:width(HT),
                                      hashtree:mem_levels(HT)},
      Path = hashtree:path(HT),
  
      UpdatedHT = hashtree:update_tree(HT),
      CleanClosedHT = hashtree:mark_clean_close({0,0}, UpdatedHT),
      hashtree:close(CleanClosedHT),
  
      T1 = hashtree:new({0,0}, [{segments, Segments},
                                {width, Width},
                                {mem_levels, MemLevels},
                                {segment_path, Path}]),
  
      put(T, hashtree:mark_open_and_check({0,0}, T1)),
      ok.
  
  unsafe_close(T) ->
      HT = get(T),
      {Segments, Width, MemLevels} = {hashtree:segments(HT), hashtree:width(HT),
                                      hashtree:mem_levels(HT)},
  
negative.code:     {SnapTree, _Tree2} = hashtree:update_snapshot(Tree),
      hashtree:multi_select_segment(SnapTree, ['*','*'], Fun).
  
  
  expect_compare() ->
      Snap1 = orddict:from_list(ets:tab2list(s1)),
      Snap2 = orddict:from_list(ets:tab2list(s2)),
      SnapDeltas = riak_ensemble_util:orddict_delta(Snap1, Snap2),
  
      lists:sort(
        [{missing, K} || {K, {'$none', _}} <- SnapDeltas] ++
  	  [{remote_missing, K} || {K, {_, '$none'}} <- SnapDeltas] ++
            [{different, K} || {K, {V1, V2}} <- SnapDeltas, V1 /= '$none', V2 /= '$none']). %% UNDO SnapDeltas this line
  %%
  %% Functions for handling the model data stored in ETS tables
  %%
  
  %% Create ETS table with public options
  ets_new(T) ->
      ets:new(T, [named_table, public, set]).
  
  %% Convert a table to a list falling back to undefined for printing
  %% failure state.
  safe_tab2list(Id) ->
      try
          ets:tab2list(Id)
      catch
          _:_ ->
              undefined
      end.
  
  %% Copy the model data from the live to snapshot table for
  %% update_tree/update_snapshot.
  copy_tree(T, S) ->
      catch ets:delete(S),
      ets_new(S),
      ets:insert(S, ets:tab2list(T)),
      ok.
  
  -endif.
  -endif.
  