anchor.diff:      ?assertEqual(Result1, {error, wrong_format}),
       Result2=filter_ops([anything]),
       ?assertEqual(Result2, {error, wrong_format}).
  +
  +seq_write_test() ->
  +    OpsCache = ets:new(ops_cache, [set]),
  +    SnapshotCache = ets:new(snapshot_cache, [set]),
  +    Key = mycount,
  +    Type = riak_dt_gcounter,
  +    DC1 = 1,
  +    S1 = Type:new(),
  +
  +    %% Insert one increment
  +    {ok,Op1} = Type:update(increment, a, S1),
  +    DownstreamOp1 = #clocksi_payload{key = Key,
  +                                     type = Type,
  +                                     op_param = {merge, Op1},
  +                                     snapshot_time = vectorclock:from_list([{DC1,10}]),
  +                                     commit_time = {DC1, 15},
  +                                     txid = 1
  +                                    },
  +    op_insert_gc(Key,DownstreamOp1, OpsCache, SnapshotCache),
  +    {ok, Res1} = internal_read(ignore, Key, Type, vectorclock:from_list([{DC1,16}]), OpsCache, SnapshotCache),
  +    ?assertEqual(1, Type:value(Res1)),
  +
  +    %% Insert second increment
  +    {ok,Op2} = Type:update(increment, a, Res1),
  +    DownstreamOp2 = DownstreamOp1#clocksi_payload{
  +                      op_param = {merge, Op2},
  +                      snapshot_time=vectorclock:from_list([{DC1,16}]),
  +                      commit_time = {DC1,20},
  +                      txid=2},
  +
  +    op_insert_gc(Key,DownstreamOp2, OpsCache, SnapshotCache),
  +    {ok, Res2} = internal_read(ignore, Key, Type, vectorclock:from_list([{DC1,21}]), OpsCache, SnapshotCache),
  +    ?assertEqual(2, Type:value(Res2)),
  +
  +    %% Read old version
  +    {ok, ReadOld} = internal_read(ignore, Key, Type, vectorclock:from_list([{DC1,16}]), OpsCache, SnapshotCache),
  +    ?assertEqual(1, Type:value(ReadOld)).
  +
  +multipledc_write_test() ->
  +    OpsCache = ets:new(ops_cache, [set]),
  +    SnapshotCache = ets:new(snapshot_cache, [set]),
  +    Key = mycount,
  +    Type = riak_dt_gcounter,
  +    DC1 = 1,
  +    DC2 = 2,
  +    S1 = Type:new(),
  +
  +    %% Insert one increment in DC1
  +    {ok,Op1} = Type:update(increment, a, S1),
  +    DownstreamOp1 = #clocksi_payload{key = Key,
  +                                     type = Type,
  +                                     op_param = {merge, Op1},
  +                                     snapshot_time = vectorclock:from_list([{DC1,10}]),
  +                                     commit_time = {DC1, 15},
  +                                     txid = 1
  +                                    },
  +    op_insert_gc(Key,DownstreamOp1, OpsCache, SnapshotCache),
  +    {ok, Res1} = internal_read(ignore, Key, Type, vectorclock:from_list([{DC1,16}]), OpsCache, SnapshotCache),
  +    ?assertEqual(1, Type:value(Res1)),
  +
  +    %% Insert second increment in other DC
  +    {ok,Op2} = Type:update(increment, b, Res1),
  +    DownstreamOp2 = DownstreamOp1#clocksi_payload{
  +                      op_param = {merge, Op2},
  +                      snapshot_time=vectorclock:from_list([{DC2,16}, {DC1,16}]),
  +                      commit_time = {DC2,20},
  +                      txid=2},
  +
  +    op_insert_gc(Key,DownstreamOp2, OpsCache, SnapshotCache),
  +    {ok, Res2} = internal_read(ignore, Key, Type, vectorclock:from_list([{DC2,21}, {DC1,16}]), OpsCache, SnapshotCache),
  +    ?assertEqual(2, Type:value(Res2)),
  +
  +    %% Read old version
  +    {ok, ReadOld} = internal_read(ignore, Key, Type, vectorclock:from_list([{DC1,16}]), OpsCache, SnapshotCache),
  +    ?assertEqual(1, Type:value(ReadOld)).
  +
  +concurrent_write_test() ->
  +    OpsCache = ets:new(ops_cache, [set]),
  +    SnapshotCache = ets:new(snapshot_cache, [set]),
  +    Key = mycount,
  +    Type = riak_dt_gcounter,
  +    DC1 = 1,
  +    DC2 = 2,
  +    S1 = Type:new(),
  +
  +    %% Insert one increment in DC1
  +    {ok,Op1} = Type:update(increment, a, S1),
  +    DownstreamOp1 = #clocksi_payload{key = Key,
  +                                     type = Type,
  +                                     op_param = {merge, Op1},
  +                                     snapshot_time = vectorclock:from_list([{DC1,10}]),
  +                                     commit_time = {DC1, 15},
  +                                     txid = 1
  +                                    },
  +    op_insert_gc(Key,DownstreamOp1, OpsCache, SnapshotCache),
  +    {ok, Res1} = internal_read(ignore, Key, Type, vectorclock:from_list([{DC1,16}]), OpsCache, SnapshotCache),
  +    ?assertEqual(1, Type:value(Res1)),
  +
  +    %% Another concurrent increment in other DC
  +    {ok,Op2} = Type:update(increment, b, S1),
  +    DownstreamOp2 = DownstreamOp1#clocksi_payload{
  +                      op_param = {merge, Op2},
  +                      snapshot_time=vectorclock:from_list([{DC2,10}]),
  +                      commit_time = {DC2,20},
  +                      txid=2},
  +
  +    %% Read snapshot including both increments
  +    op_insert_gc(Key,DownstreamOp2, OpsCache, SnapshotCache),
  +    {ok, Res2} = internal_read(ignore, Key, Type, vectorclock:from_list([{DC2,21}, {DC1,16}]), OpsCache, SnapshotCache),
  +    ?assertEqual(2, Type:value(Res2)),
  +
  +    %% Read different snapshots
  +    {ok, ReadDC1} = internal_read(ignore, Key, Type, vectorclock:from_list([{DC1,20}]), OpsCache, SnapshotCache),
  +    ?assertEqual(1, Type:value(ReadDC1)),
  +    {ok, ReadDC2} = internal_read(ignore, Key, Type, vectorclock:from_list([{DC2,21}]), OpsCache, SnapshotCache),
  +    ?assertEqual(1, Type:value(ReadDC2)).
  +
   -endif.
  
positive.code: 
  %% @doc This function takes care of reading. It is implemented here for not blocking the
  %% vnode when the write function calls it. That is done for garbage collection.
  -spec internal_read(term(),term(), atom(), vectorclock:vectorclock(), atom() , atom() ) -> ok.
  internal_read(Sender, Key, Type, SnapshotTime, OpsCache, SnapshotCache) ->
                                                  % get the latest snapshot for the key
      case ets:lookup(SnapshotCache, Key) of
  
negative.code:     case logging_vnode:append(Node,LogId,LogRecord) of
          {ok, _} ->
              riak_core_vnode:reply(Sender, ok),
              op_insert_gc(Key,DownstreamOp, OpsCache, SnapshotCache),
              ok;
          {error, Reason} ->
              riak_core_vnode:reply(Sender, {error, Reason})
  