blob: 69940466e84c743d080b1831bac0cc5ebeb86898 [file] [log] [blame]
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.apache.cassandra.db.context;
import java.nio.ByteBuffer;
import org.junit.BeforeClass;
import org.junit.Test;
import org.apache.cassandra.Util;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.db.ClockAndCount;
import org.apache.cassandra.db.LegacyLayout.LegacyCell;
import org.apache.cassandra.db.context.CounterContext.Relationship;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.CounterId;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.apache.cassandra.db.context.CounterContext.ContextState;
public class CounterContextTest
{
private static final CounterContext cc = new CounterContext();
private static final int headerSizeLength = 2;
private static final int headerEltLength = 2;
private static final int idLength = 16;
private static final int clockLength = 8;
private static final int countLength = 8;
private static final int stepLength = idLength + clockLength + countLength;
@BeforeClass
public static void setupDD()
{
DatabaseDescriptor.daemonInitialization();
}
@Test
public void testAllocate()
{
ContextState allGlobal = ContextState.allocate(3, 0, 0);
assertEquals(headerSizeLength + 3 * headerEltLength + 3 * stepLength, allGlobal.context.remaining());
ContextState allLocal = ContextState.allocate(0, 3, 0);
assertEquals(headerSizeLength + 3 * headerEltLength + 3 * stepLength, allLocal.context.remaining());
ContextState allRemote = ContextState.allocate(0, 0, 3);
assertEquals(headerSizeLength + 3 * stepLength, allRemote.context.remaining());
ContextState mixed = ContextState.allocate(1, 1, 1);
assertEquals(headerSizeLength + 2 * headerEltLength + 3 * stepLength, mixed.context.remaining());
}
@Test
public void testDiff()
{
ContextState left;
ContextState right;
// equality: equal nodes, all counts same
left = ContextState.allocate(0, 0, 3);
left.writeRemote(CounterId.fromInt(3), 3L, 0L);
left.writeRemote(CounterId.fromInt(6), 2L, 0L);
left.writeRemote(CounterId.fromInt(9), 1L, 0L);
right = ContextState.wrap(ByteBufferUtil.clone(left.context));
assertEquals(Relationship.EQUAL, cc.diff(left.context, right.context));
// greater than: left has superset of nodes (counts equal)
left = ContextState.allocate(0, 0, 4);
left.writeRemote(CounterId.fromInt(3), 3L, 0L);
left.writeRemote(CounterId.fromInt(6), 2L, 0L);
left.writeRemote(CounterId.fromInt(9), 1L, 0L);
left.writeRemote(CounterId.fromInt(12), 0L, 0L);
right = ContextState.allocate(0, 0, 3);
right.writeRemote(CounterId.fromInt(3), 3L, 0L);
right.writeRemote(CounterId.fromInt(6), 2L, 0L);
right.writeRemote(CounterId.fromInt(9), 1L, 0L);
assertEquals(Relationship.GREATER_THAN, cc.diff(left.context, right.context));
// less than: left has subset of nodes (counts equal)
left = ContextState.allocate(0, 0, 3);
left.writeRemote(CounterId.fromInt(3), 3L, 0L);
left.writeRemote(CounterId.fromInt(6), 2L, 0L);
left.writeRemote(CounterId.fromInt(9), 1L, 0L);
right = ContextState.allocate(0, 0, 4);
right.writeRemote(CounterId.fromInt(3), 3L, 0L);
right.writeRemote(CounterId.fromInt(6), 2L, 0L);
right.writeRemote(CounterId.fromInt(9), 1L, 0L);
right.writeRemote(CounterId.fromInt(12), 0L, 0L);
assertEquals(Relationship.LESS_THAN, cc.diff(left.context, right.context));
// greater than: equal nodes, but left has higher counts
left = ContextState.allocate(0, 0, 3);
left.writeRemote(CounterId.fromInt(3), 3L, 0L);
left.writeRemote(CounterId.fromInt(6), 2L, 0L);
left.writeRemote(CounterId.fromInt(9), 3L, 0L);
right = ContextState.allocate(0, 0, 3);
right.writeRemote(CounterId.fromInt(3), 3L, 0L);
right.writeRemote(CounterId.fromInt(6), 2L, 0L);
right.writeRemote(CounterId.fromInt(9), 1L, 0L);
assertEquals(Relationship.GREATER_THAN, cc.diff(left.context, right.context));
// less than: equal nodes, but right has higher counts
left = ContextState.allocate(0, 0, 3);
left.writeRemote(CounterId.fromInt(3), 3L, 0L);
left.writeRemote(CounterId.fromInt(6), 2L, 0L);
left.writeRemote(CounterId.fromInt(9), 3L, 0L);
right = ContextState.allocate(0, 0, 3);
right.writeRemote(CounterId.fromInt(3), 3L, 0L);
right.writeRemote(CounterId.fromInt(6), 9L, 0L);
right.writeRemote(CounterId.fromInt(9), 3L, 0L);
assertEquals(Relationship.LESS_THAN, cc.diff(left.context, right.context));
// disjoint: right and left have disjoint node sets
left = ContextState.allocate(0, 0, 3);
left.writeRemote(CounterId.fromInt(3), 1L, 0L);
left.writeRemote(CounterId.fromInt(4), 1L, 0L);
left.writeRemote(CounterId.fromInt(9), 1L, 0L);
right = ContextState.allocate(0, 0, 3);
right.writeRemote(CounterId.fromInt(3), 1L, 0L);
right.writeRemote(CounterId.fromInt(6), 1L, 0L);
right.writeRemote(CounterId.fromInt(9), 1L, 0L);
assertEquals(Relationship.DISJOINT, cc.diff(left.context, right.context));
left = ContextState.allocate(0, 0, 3);
left.writeRemote(CounterId.fromInt(3), 1L, 0L);
left.writeRemote(CounterId.fromInt(4), 1L, 0L);
left.writeRemote(CounterId.fromInt(9), 1L, 0L);
right = ContextState.allocate(0, 0, 3);
right.writeRemote(CounterId.fromInt(2), 1L, 0L);
right.writeRemote(CounterId.fromInt(6), 1L, 0L);
right.writeRemote(CounterId.fromInt(12), 1L, 0L);
assertEquals(Relationship.DISJOINT, cc.diff(left.context, right.context));
// disjoint: equal nodes, but right and left have higher counts in differing nodes
left = ContextState.allocate(0, 0, 3);
left.writeRemote(CounterId.fromInt(3), 1L, 0L);
left.writeRemote(CounterId.fromInt(6), 3L, 0L);
left.writeRemote(CounterId.fromInt(9), 1L, 0L);
right = ContextState.allocate(0, 0, 3);
right.writeRemote(CounterId.fromInt(3), 1L, 0L);
right.writeRemote(CounterId.fromInt(6), 1L, 0L);
right.writeRemote(CounterId.fromInt(9), 5L, 0L);
assertEquals(Relationship.DISJOINT, cc.diff(left.context, right.context));
left = ContextState.allocate(0, 0, 3);
left.writeRemote(CounterId.fromInt(3), 2L, 0L);
left.writeRemote(CounterId.fromInt(6), 3L, 0L);
left.writeRemote(CounterId.fromInt(9), 1L, 0L);
right = ContextState.allocate(0, 0, 3);
right.writeRemote(CounterId.fromInt(3), 1L, 0L);
right.writeRemote(CounterId.fromInt(6), 9L, 0L);
right.writeRemote(CounterId.fromInt(9), 5L, 0L);
assertEquals(Relationship.DISJOINT, cc.diff(left.context, right.context));
// disjoint: left has more nodes, but lower counts
left = ContextState.allocate(0, 0, 4);
left.writeRemote(CounterId.fromInt(3), 2L, 0L);
left.writeRemote(CounterId.fromInt(6), 3L, 0L);
left.writeRemote(CounterId.fromInt(9), 1L, 0L);
left.writeRemote(CounterId.fromInt(12), 1L, 0L);
right = ContextState.allocate(0, 0, 3);
right.writeRemote(CounterId.fromInt(3), 4L, 0L);
right.writeRemote(CounterId.fromInt(6), 9L, 0L);
right.writeRemote(CounterId.fromInt(9), 5L, 0L);
assertEquals(Relationship.DISJOINT, cc.diff(left.context, right.context));
// disjoint: left has less nodes, but higher counts
left = ContextState.allocate(0, 0, 3);
left.writeRemote(CounterId.fromInt(3), 5L, 0L);
left.writeRemote(CounterId.fromInt(6), 3L, 0L);
left.writeRemote(CounterId.fromInt(9), 2L, 0L);
right = ContextState.allocate(0, 0, 4);
right.writeRemote(CounterId.fromInt(3), 4L, 0L);
right.writeRemote(CounterId.fromInt(6), 3L, 0L);
right.writeRemote(CounterId.fromInt(9), 2L, 0L);
right.writeRemote(CounterId.fromInt(12), 1L, 0L);
assertEquals(Relationship.DISJOINT, cc.diff(left.context, right.context));
// disjoint: mixed nodes and counts
left = ContextState.allocate(0, 0, 3);
left.writeRemote(CounterId.fromInt(3), 5L, 0L);
left.writeRemote(CounterId.fromInt(6), 2L, 0L);
left.writeRemote(CounterId.fromInt(9), 2L, 0L);
right = ContextState.allocate(0, 0, 4);
right.writeRemote(CounterId.fromInt(3), 4L, 0L);
right.writeRemote(CounterId.fromInt(6), 3L, 0L);
right.writeRemote(CounterId.fromInt(9), 2L, 0L);
right.writeRemote(CounterId.fromInt(12), 1L, 0L);
assertEquals(Relationship.DISJOINT, cc.diff(left.context, right.context));
left = ContextState.allocate(0, 0, 4);
left.writeRemote(CounterId.fromInt(3), 5L, 0L);
left.writeRemote(CounterId.fromInt(6), 2L, 0L);
left.writeRemote(CounterId.fromInt(7), 2L, 0L);
left.writeRemote(CounterId.fromInt(9), 2L, 0L);
right = ContextState.allocate(0, 0, 3);
right.writeRemote(CounterId.fromInt(3), 4L, 0L);
right.writeRemote(CounterId.fromInt(6), 3L, 0L);
right.writeRemote(CounterId.fromInt(9), 2L, 0L);
assertEquals(Relationship.DISJOINT, cc.diff(left.context, right.context));
}
@Test
public void testMerge()
{
// note: local counts aggregated; remote counts are reconciled (i.e. take max)
ContextState left = ContextState.allocate(0, 1, 3);
left.writeRemote(CounterId.fromInt(1), 1L, 1L);
left.writeRemote(CounterId.fromInt(2), 2L, 2L);
left.writeRemote(CounterId.fromInt(4), 6L, 3L);
left.writeLocal(CounterId.getLocalId(), 7L, 3L);
ContextState right = ContextState.allocate(0, 1, 2);
right.writeRemote(CounterId.fromInt(4), 4L, 4L);
right.writeRemote(CounterId.fromInt(5), 5L, 5L);
right.writeLocal(CounterId.getLocalId(), 2L, 9L);
ByteBuffer merged = cc.merge(left.context, right.context);
int hd = 4;
assertEquals(hd + 5 * stepLength, merged.remaining());
// local node id's counts are aggregated
assertTrue(Util.equalsCounterId(CounterId.getLocalId(), merged, hd + 4 * stepLength));
assertEquals(9L, merged.getLong(merged.position() + hd + 4 * stepLength + idLength));
assertEquals(12L, merged.getLong(merged.position() + hd + 4*stepLength + idLength + clockLength));
// remote node id counts are reconciled (i.e. take max)
assertTrue(Util.equalsCounterId(CounterId.fromInt(4), merged, hd + 2 * stepLength));
assertEquals(6L, merged.getLong(merged.position() + hd + 2 * stepLength + idLength));
assertEquals( 3L, merged.getLong(merged.position() + hd + 2*stepLength + idLength + clockLength));
assertTrue(Util.equalsCounterId(CounterId.fromInt(5), merged, hd + 3 * stepLength));
assertEquals(5L, merged.getLong(merged.position() + hd + 3 * stepLength + idLength));
assertEquals( 5L, merged.getLong(merged.position() + hd + 3*stepLength + idLength + clockLength));
assertTrue(Util.equalsCounterId(CounterId.fromInt(2), merged, hd + stepLength));
assertEquals(2L, merged.getLong(merged.position() + hd + stepLength + idLength));
assertEquals( 2L, merged.getLong(merged.position() + hd + stepLength + idLength + clockLength));
assertTrue(Util.equalsCounterId(CounterId.fromInt(1), merged, hd));
assertEquals( 1L, merged.getLong(merged.position() + hd + idLength));
assertEquals( 1L, merged.getLong(merged.position() + hd + idLength + clockLength));
//
// Test merging two exclusively global contexts
//
left = ContextState.allocate(3, 0, 0);
left.writeGlobal(CounterId.fromInt(1), 1L, 1L);
left.writeGlobal(CounterId.fromInt(2), 2L, 2L);
left.writeGlobal(CounterId.fromInt(3), 3L, 3L);
right = ContextState.allocate(3, 0, 0);
right.writeGlobal(CounterId.fromInt(3), 6L, 6L);
right.writeGlobal(CounterId.fromInt(4), 4L, 4L);
right.writeGlobal(CounterId.fromInt(5), 5L, 5L);
merged = cc.merge(left.context, right.context);
assertEquals(headerSizeLength + 5 * headerEltLength + 5 * stepLength, merged.remaining());
assertEquals(18L, cc.total(merged));
assertEquals(5, merged.getShort(merged.position()));
int headerLength = headerSizeLength + 5 * headerEltLength;
assertTrue(Util.equalsCounterId(CounterId.fromInt(1), merged, headerLength));
assertEquals(1L, merged.getLong(merged.position() + headerLength + idLength));
assertEquals(1L, merged.getLong(merged.position() + headerLength + idLength + clockLength));
assertTrue(Util.equalsCounterId(CounterId.fromInt(2), merged, headerLength + stepLength));
assertEquals(2L, merged.getLong(merged.position() + headerLength + stepLength + idLength));
assertEquals(2L, merged.getLong(merged.position() + headerLength + stepLength + idLength + clockLength));
// pick the global shard with the largest clock
assertTrue(Util.equalsCounterId(CounterId.fromInt(3), merged, headerLength + 2 * stepLength));
assertEquals(6L, merged.getLong(merged.position() + headerLength + 2 * stepLength + idLength));
assertEquals(6L, merged.getLong(merged.position() + headerLength + 2 * stepLength + idLength + clockLength));
assertTrue(Util.equalsCounterId(CounterId.fromInt(4), merged, headerLength + 3 * stepLength));
assertEquals(4L, merged.getLong(merged.position() + headerLength + 3 * stepLength + idLength));
assertEquals(4L, merged.getLong(merged.position() + headerLength + 3 * stepLength + idLength + clockLength));
assertTrue(Util.equalsCounterId(CounterId.fromInt(5), merged, headerLength + 4 * stepLength));
assertEquals(5L, merged.getLong(merged.position() + headerLength + 4 * stepLength + idLength));
assertEquals(5L, merged.getLong(merged.position() + headerLength + 4 * stepLength + idLength + clockLength));
//
// Test merging two global contexts w/ 'invalid shards'
//
left = ContextState.allocate(1, 0, 0);
left.writeGlobal(CounterId.fromInt(1), 10L, 20L);
right = ContextState.allocate(1, 0, 0);
right.writeGlobal(CounterId.fromInt(1), 10L, 30L);
merged = cc.merge(left.context, right.context);
headerLength = headerSizeLength + headerEltLength;
assertEquals(headerLength + stepLength, merged.remaining());
assertEquals(30L, cc.total(merged));
assertEquals(1, merged.getShort(merged.position()));
assertTrue(Util.equalsCounterId(CounterId.fromInt(1), merged, headerLength));
assertEquals(10L, merged.getLong(merged.position() + headerLength + idLength));
// with equal clock, we should pick the largest value
assertEquals(30L, merged.getLong(merged.position() + headerLength + idLength + clockLength));
//
// Test merging global w/ mixed contexts
//
left = ContextState.allocate(2, 0, 0);
left.writeGlobal(CounterId.fromInt(1), 1L, 1L);
left.writeGlobal(CounterId.fromInt(2), 1L, 1L);
right = ContextState.allocate(0, 1, 1);
right.writeLocal(CounterId.fromInt(1), 100L, 100L);
right.writeRemote(CounterId.fromInt(2), 100L, 100L);
// global shards should dominate local/remote, even with lower clock and value
merged = cc.merge(left.context, right.context);
headerLength = headerSizeLength + 2 * headerEltLength;
assertEquals(headerLength + 2 * stepLength, merged.remaining());
assertEquals(2L, cc.total(merged));
assertEquals(2, merged.getShort(merged.position()));
assertTrue(Util.equalsCounterId(CounterId.fromInt(1), merged, headerLength));
assertEquals(1L, merged.getLong(merged.position() + headerLength + idLength));
assertEquals(1L, merged.getLong(merged.position() + headerLength + idLength + clockLength));
assertTrue(Util.equalsCounterId(CounterId.fromInt(2), merged, headerLength + stepLength));
assertEquals(1L, merged.getLong(merged.position() + headerLength + stepLength + idLength));
assertEquals(1L, merged.getLong(merged.position() + headerLength + stepLength + idLength + clockLength));
}
@Test
public void testTotal()
{
ContextState mixed = ContextState.allocate(0, 1, 4);
mixed.writeRemote(CounterId.fromInt(1), 1L, 1L);
mixed.writeRemote(CounterId.fromInt(2), 2L, 2L);
mixed.writeRemote(CounterId.fromInt(4), 4L, 4L);
mixed.writeRemote(CounterId.fromInt(5), 5L, 5L);
mixed.writeLocal(CounterId.getLocalId(), 12L, 12L);
assertEquals(24L, cc.total(mixed.context));
ContextState global = ContextState.allocate(3, 0, 0);
global.writeGlobal(CounterId.fromInt(1), 1L, 1L);
global.writeGlobal(CounterId.fromInt(2), 2L, 2L);
global.writeGlobal(CounterId.fromInt(3), 3L, 3L);
assertEquals(6L, cc.total(global.context));
}
@Test
public void testClearLocal()
{
ContextState state;
ByteBuffer marked;
ByteBuffer cleared;
// mark/clear for remote-only contexts is a no-op
state = ContextState.allocate(0, 0, 1);
state.writeRemote(CounterId.fromInt(1), 1L, 1L);
assertFalse(cc.shouldClearLocal(state.context));
marked = cc.markLocalToBeCleared(state.context);
assertEquals(0, marked.getShort(marked.position()));
assertSame(state.context, marked); // should return the original context
cleared = cc.clearAllLocal(marked);
assertSame(cleared, marked); // shouldn't alter anything either
// a single local shard
state = ContextState.allocate(0, 1, 0);
state.writeLocal(CounterId.fromInt(1), 1L, 1L);
assertFalse(cc.shouldClearLocal(state.context));
marked = cc.markLocalToBeCleared(state.context);
assertTrue(cc.shouldClearLocal(marked));
assertEquals(-1, marked.getShort(marked.position()));
assertNotSame(state.context, marked); // shouldn't alter in place, as it used to do
cleared = cc.clearAllLocal(marked);
assertFalse(cc.shouldClearLocal(cleared));
assertEquals(0, cleared.getShort(cleared.position()));
// 2 global + 1 local shard
state = ContextState.allocate(2, 1, 0);
state.writeLocal(CounterId.fromInt(1), 1L, 1L);
state.writeGlobal(CounterId.fromInt(2), 2L, 2L);
state.writeGlobal(CounterId.fromInt(3), 3L, 3L);
assertFalse(cc.shouldClearLocal(state.context));
marked = cc.markLocalToBeCleared(state.context);
assertTrue(cc.shouldClearLocal(marked));
assertEquals(-3, marked.getShort(marked.position()));
assertEquals(0, marked.getShort(marked.position() + headerSizeLength));
assertEquals(Short.MIN_VALUE + 1, marked.getShort(marked.position() + headerSizeLength + headerEltLength));
assertEquals(Short.MIN_VALUE + 2, marked.getShort(marked.position() + headerSizeLength + 2 * headerEltLength));
int headerLength = headerSizeLength + 3 * headerEltLength;
assertTrue(Util.equalsCounterId(CounterId.fromInt(1), marked, headerLength));
assertEquals(1L, marked.getLong(marked.position() + headerLength + idLength));
assertEquals(1L, marked.getLong(marked.position() + headerLength + idLength + clockLength));
assertTrue(Util.equalsCounterId(CounterId.fromInt(2), marked, headerLength + stepLength));
assertEquals(2L, marked.getLong(marked.position() + headerLength + stepLength + idLength));
assertEquals(2L, marked.getLong(marked.position() + headerLength + stepLength + idLength + clockLength));
assertTrue(Util.equalsCounterId(CounterId.fromInt(3), marked, headerLength + 2 * stepLength));
assertEquals(3L, marked.getLong(marked.position() + headerLength + 2 * stepLength + idLength));
assertEquals(3L, marked.getLong(marked.position() + headerLength + 2 * stepLength + idLength + clockLength));
cleared = cc.clearAllLocal(marked);
assertFalse(cc.shouldClearLocal(cleared));
assertEquals(2, cleared.getShort(cleared.position())); // 2 global shards
assertEquals(Short.MIN_VALUE + 1, cleared.getShort(marked.position() + headerEltLength));
assertEquals(Short.MIN_VALUE + 2, cleared.getShort(marked.position() + headerSizeLength + headerEltLength));
headerLength = headerSizeLength + 2 * headerEltLength;
assertTrue(Util.equalsCounterId(CounterId.fromInt(1), cleared, headerLength));
assertEquals(1L, cleared.getLong(cleared.position() + headerLength + idLength));
assertEquals(1L, cleared.getLong(cleared.position() + headerLength + idLength + clockLength));
assertTrue(Util.equalsCounterId(CounterId.fromInt(2), cleared, headerLength + stepLength));
assertEquals(2L, cleared.getLong(cleared.position() + headerLength + stepLength + idLength));
assertEquals(2L, cleared.getLong(cleared.position() + headerLength + stepLength + idLength + clockLength));
assertTrue(Util.equalsCounterId(CounterId.fromInt(3), cleared, headerLength + 2 * stepLength));
assertEquals(3L, cleared.getLong(cleared.position() + headerLength + 2 * stepLength + idLength));
assertEquals(3L, cleared.getLong(cleared.position() + headerLength + 2 * stepLength + idLength + clockLength));
// a single global shard - no-op
state = ContextState.allocate(1, 0, 0);
state.writeGlobal(CounterId.fromInt(1), 1L, 1L);
assertFalse(cc.shouldClearLocal(state.context));
marked = cc.markLocalToBeCleared(state.context);
assertEquals(1, marked.getShort(marked.position()));
assertSame(state.context, marked);
cleared = cc.clearAllLocal(marked);
assertSame(cleared, marked);
}
@Test
public void testFindPositionOf()
{
ContextState state = ContextState.allocate(3, 3, 3);
state.writeGlobal(CounterId.fromInt(1), 1L, 1L);
state.writeRemote(CounterId.fromInt(2), 2L, 2L);
state.writeLocal( CounterId.fromInt(3), 3L, 3L);
state.writeGlobal(CounterId.fromInt(4), 4L, 4L);
state.writeRemote(CounterId.fromInt(5), 5L, 5L);
state.writeLocal( CounterId.fromInt(6), 6L, 6L);
state.writeGlobal(CounterId.fromInt(7), 7L, 7L);
state.writeRemote(CounterId.fromInt(8), 8L, 8L);
state.writeLocal(CounterId.fromInt(9), 9L, 9L);
int headerLength = headerSizeLength + 6 * headerEltLength;
assertEquals(headerLength, cc.findPositionOf(state.context, CounterId.fromInt(1)));
assertEquals(headerLength + stepLength, cc.findPositionOf(state.context, CounterId.fromInt(2)));
assertEquals(headerLength + 2 * stepLength, cc.findPositionOf(state.context, CounterId.fromInt(3)));
assertEquals(headerLength + 3 * stepLength, cc.findPositionOf(state.context, CounterId.fromInt(4)));
assertEquals(headerLength + 4 * stepLength, cc.findPositionOf(state.context, CounterId.fromInt(5)));
assertEquals(headerLength + 5 * stepLength, cc.findPositionOf(state.context, CounterId.fromInt(6)));
assertEquals(headerLength + 6 * stepLength, cc.findPositionOf(state.context, CounterId.fromInt(7)));
assertEquals(headerLength + 7 * stepLength, cc.findPositionOf(state.context, CounterId.fromInt(8)));
assertEquals(headerLength + 8 * stepLength, cc.findPositionOf(state.context, CounterId.fromInt(9)));
assertEquals(-1, cc.findPositionOf(state.context, CounterId.fromInt(0)));
assertEquals(-1, cc.findPositionOf(state.context, CounterId.fromInt(10)));
assertEquals(-1, cc.findPositionOf(state.context, CounterId.fromInt(15)));
assertEquals(-1, cc.findPositionOf(state.context, CounterId.fromInt(20)));
}
@Test
public void testGetGlockAndCountOf()
{
ContextState state = ContextState.allocate(3, 3, 3);
state.writeGlobal(CounterId.fromInt(1), 1L, 1L);
state.writeRemote(CounterId.fromInt(2), 2L, 2L);
state.writeLocal( CounterId.fromInt(3), 3L, 3L);
state.writeGlobal(CounterId.fromInt(4), 4L, 4L);
state.writeRemote(CounterId.fromInt(5), 5L, 5L);
state.writeLocal( CounterId.fromInt(6), 6L, 6L);
state.writeGlobal(CounterId.fromInt(7), 7L, 7L);
state.writeRemote(CounterId.fromInt(8), 8L, 8L);
state.writeLocal(CounterId.fromInt(9), 9L, 9L);
assertEquals(ClockAndCount.create(1L, 1L), cc.getClockAndCountOf(state.context, CounterId.fromInt(1)));
assertEquals(ClockAndCount.create(2L, 2L), cc.getClockAndCountOf(state.context, CounterId.fromInt(2)));
assertEquals(ClockAndCount.create(3L, 3L), cc.getClockAndCountOf(state.context, CounterId.fromInt(3)));
assertEquals(ClockAndCount.create(4L, 4L), cc.getClockAndCountOf(state.context, CounterId.fromInt(4)));
assertEquals(ClockAndCount.create(5L, 5L), cc.getClockAndCountOf(state.context, CounterId.fromInt(5)));
assertEquals(ClockAndCount.create(6L, 6L), cc.getClockAndCountOf(state.context, CounterId.fromInt(6)));
assertEquals(ClockAndCount.create(7L, 7L), cc.getClockAndCountOf(state.context, CounterId.fromInt(7)));
assertEquals(ClockAndCount.create(8L, 8L), cc.getClockAndCountOf(state.context, CounterId.fromInt(8)));
assertEquals(ClockAndCount.create(9L, 9L), cc.getClockAndCountOf(state.context, CounterId.fromInt(9)));
assertEquals(ClockAndCount.create(0L, 0L), cc.getClockAndCountOf(state.context, CounterId.fromInt(0)));
assertEquals(ClockAndCount.create(0L, 0L), cc.getClockAndCountOf(state.context, CounterId.fromInt(10)));
assertEquals(ClockAndCount.create(0L, 0L), cc.getClockAndCountOf(state.context, CounterId.fromInt(15)));
assertEquals(ClockAndCount.create(0L, 0L), cc.getClockAndCountOf(state.context, CounterId.fromInt(20)));
}
@Test // see CASSANDRA-13691
public void testCounterUpdate()
{
/*
* a context with just one 'update' shard - a local shard with a hardcoded value of CounterContext.UPDATE_CLOCK_ID
*/
ByteBuffer updateContext = CounterContext.instance().createUpdate(10L);
assertEquals(ClockAndCount.create(1L, 10L), cc.getClockAndCountOf(updateContext, CounterContext.UPDATE_CLOCK_ID));
assertTrue(cc.isUpdate(updateContext));
LegacyCell updateCell = LegacyCell.counter(null, updateContext);
assertTrue(updateCell.isCounterUpdate());
/*
* a context with a regular local shard sorting first and a couple others in it - should *not* be identified as an update
*/
ContextState notUpdateContextState = ContextState.allocate(1, 1, 1);
notUpdateContextState.writeLocal( CounterId.fromInt(1), 1L, 10L);
notUpdateContextState.writeRemote(CounterId.fromInt(2), 1L, 10L);
notUpdateContextState.writeGlobal(CounterId.fromInt(3), 1L, 10L);
ByteBuffer notUpdateContext = notUpdateContextState.context;
assertFalse(cc.isUpdate(notUpdateContext));
LegacyCell notUpdateCell = LegacyCell.counter(null, notUpdateContext);
assertFalse(notUpdateCell.isCounterUpdate());
}
}