/*
* 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;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.LinkedList;
import java.util.List;
import org.junit.Test;
import org.apache.cassandra.Util;
import org.apache.cassandra.db.clock.IncrementCounterContext;
import org.apache.cassandra.io.util.DataOutputBuffer;
import org.apache.cassandra.utils.FBUtilities;
public class IncrementCounterClockTest
{
private static final IncrementCounterContext icc = new IncrementCounterContext();
private static final int HEADER_LENGTH;
private static final int idLength;
private static final int countLength;
private static final int stepLength;
static
{
HEADER_LENGTH = icc.HEADER_LENGTH;
idLength = 4; // size of int
countLength = 8; // size of long
stepLength = idLength + countLength;
}
@Test
public void testUpdate() throws UnknownHostException
{
IncrementCounterClock clock;
// note: updates are in-place
clock = new IncrementCounterClock();
clock.update(InetAddress.getByAddress(FBUtilities.toByteArray(1)), 1L);
assert clock.context().length == (HEADER_LENGTH + stepLength);
assert 1 == FBUtilities.byteArrayToInt( clock.context(), HEADER_LENGTH + 0*stepLength);
assert 1L == FBUtilities.byteArrayToLong(clock.context(), HEADER_LENGTH + 0*stepLength + idLength);
clock.update(InetAddress.getByAddress(FBUtilities.toByteArray(2)), 3L);
clock.update(InetAddress.getByAddress(FBUtilities.toByteArray(2)), 2L);
clock.update(InetAddress.getByAddress(FBUtilities.toByteArray(2)), 9L);
assert clock.context().length == (HEADER_LENGTH + 2 * stepLength);
assert 2 == FBUtilities.byteArrayToInt(clock.context(), HEADER_LENGTH + 0*stepLength);
assert 14L == FBUtilities.byteArrayToLong(clock.context(), HEADER_LENGTH + 0*stepLength + idLength);
assert 1 == FBUtilities.byteArrayToInt(clock.context(), HEADER_LENGTH + 1*stepLength);
assert 1L == FBUtilities.byteArrayToLong(clock.context(), HEADER_LENGTH + 1*stepLength + idLength);
}
@Test
public void testCompare() throws UnknownHostException
{
IncrementCounterClock clock;
IncrementCounterClock other;
// greater than
clock = new IncrementCounterClock(Util.concatByteArrays(
FBUtilities.toByteArray(10L),
FBUtilities.toByteArray(0L),
FBUtilities.getLocalAddress().getAddress(), FBUtilities.toByteArray(1L)
));
other = new IncrementCounterClock(Util.concatByteArrays(
FBUtilities.toByteArray(3L),
FBUtilities.toByteArray(0L),
FBUtilities.getLocalAddress().getAddress(), FBUtilities.toByteArray(1L)
));
assert clock.compare(other) == IClock.ClockRelationship.GREATER_THAN;
// equal
clock = new IncrementCounterClock(Util.concatByteArrays(
FBUtilities.toByteArray(5L),
FBUtilities.toByteArray(0L),
FBUtilities.getLocalAddress().getAddress(), FBUtilities.toByteArray(1L)
));
other = new IncrementCounterClock(Util.concatByteArrays(
FBUtilities.toByteArray(5L),
FBUtilities.toByteArray(0L),
FBUtilities.getLocalAddress().getAddress(), FBUtilities.toByteArray(1L)
));
assert clock.compare(other) == IClock.ClockRelationship.EQUAL;
// less than
clock = new IncrementCounterClock(Util.concatByteArrays(FBUtilities.toByteArray(0L), FBUtilities.toByteArray(0L)));
other = new IncrementCounterClock(Util.concatByteArrays(
FBUtilities.toByteArray(5L),
FBUtilities.toByteArray(0L),
FBUtilities.getLocalAddress().getAddress(), FBUtilities.toByteArray(1L)
));
assert clock.compare(other) == IClock.ClockRelationship.LESS_THAN;
// disjoint: not possible
}
@Test
public void testDiff() throws UnknownHostException
{
IncrementCounterClock clock;
IncrementCounterClock other;
// greater than
clock = new IncrementCounterClock(createEmptyContext());
clock.update(InetAddress.getByAddress(FBUtilities.toByteArray(1)), 1L);
other = new IncrementCounterClock(createEmptyContext());
assert clock.diff(other) == IClock.ClockRelationship.GREATER_THAN;
// equal
clock = new IncrementCounterClock(createEmptyContext());
clock.update(InetAddress.getByAddress(FBUtilities.toByteArray(1)), 1L);
other = new IncrementCounterClock(createEmptyContext());
other.update(InetAddress.getByAddress(FBUtilities.toByteArray(1)), 1L);
assert clock.diff(other) == IClock.ClockRelationship.EQUAL;
// less than
clock = new IncrementCounterClock(createEmptyContext());
other = new IncrementCounterClock(createEmptyContext());
other.update(InetAddress.getByAddress(FBUtilities.toByteArray(1)), 1L);
other.update(InetAddress.getByAddress(FBUtilities.toByteArray(1)), 1L);
assert clock.diff(other) == IClock.ClockRelationship.LESS_THAN;
// disjoint
clock = new IncrementCounterClock(createEmptyContext());
clock.update(InetAddress.getByAddress(FBUtilities.toByteArray(1)), 1L);
clock.update(InetAddress.getByAddress(FBUtilities.toByteArray(1)), 1L);
clock.update(InetAddress.getByAddress(FBUtilities.toByteArray(2)), 1L);
other = new IncrementCounterClock(createEmptyContext());
other.update(InetAddress.getByAddress(FBUtilities.toByteArray(9)), 1L);
other.update(InetAddress.getByAddress(FBUtilities.toByteArray(1)), 1L);
assert clock.diff(other) == IClock.ClockRelationship.DISJOINT;
}
private byte[] createEmptyContext()
{
byte[] context = new byte[HEADER_LENGTH];
FBUtilities.copyIntoBytes(context, 0, 0);
FBUtilities.copyIntoBytes(context, IncrementCounterContext.TIMESTAMP_LENGTH, 0);
return context;
}
@Test
public void testGetSuperset()
{
// normal list
List<IClock> clocks = new LinkedList<IClock>();
clocks.add(new IncrementCounterClock(Util.concatByteArrays(
FBUtilities.toByteArray(3L),
FBUtilities.toByteArray(0L),
FBUtilities.toByteArray(1), FBUtilities.toByteArray(128L),
FBUtilities.toByteArray(9), FBUtilities.toByteArray(62L),
FBUtilities.getLocalAddress().getAddress(), FBUtilities.toByteArray(32L)
)));
clocks.add(new IncrementCounterClock(Util.concatByteArrays(
FBUtilities.toByteArray(6L),
FBUtilities.toByteArray(0L),
FBUtilities.toByteArray(1), FBUtilities.toByteArray(32L),
FBUtilities.toByteArray(2), FBUtilities.toByteArray(4L),
FBUtilities.toByteArray(6), FBUtilities.toByteArray(2L)
)));
clocks.add(new IncrementCounterClock(Util.concatByteArrays(
FBUtilities.toByteArray(9L),
FBUtilities.toByteArray(0L),
FBUtilities.toByteArray(3), FBUtilities.toByteArray(15L),
FBUtilities.toByteArray(8), FBUtilities.toByteArray(14L),
FBUtilities.toByteArray(4), FBUtilities.toByteArray(13L)
)));
clocks.add(new IncrementCounterClock(Util.concatByteArrays(
FBUtilities.toByteArray(12L),
FBUtilities.toByteArray(0L),
FBUtilities.toByteArray(2), FBUtilities.toByteArray(999L),
FBUtilities.toByteArray(4), FBUtilities.toByteArray(632L),
FBUtilities.toByteArray(8), FBUtilities.toByteArray(45L)
)));
clocks.add(new IncrementCounterClock(Util.concatByteArrays(
FBUtilities.toByteArray(15L),
FBUtilities.toByteArray(0L),
FBUtilities.getLocalAddress().getAddress(), FBUtilities.toByteArray(1234L),
FBUtilities.toByteArray(3), FBUtilities.toByteArray(655L),
FBUtilities.toByteArray(7), FBUtilities.toByteArray(1L)
)));
// 127.0.0.1: 1266L
// 2: 999L
// 3: 655L
// 4: 632L
// 1: 128L
// 9: 62L
// 8: 45L
// 6: 2L
// 7: 1L
byte[] merged = ((IncrementCounterClock)IncrementCounterClock.MIN_VALUE.getSuperset(clocks)).context();
assert 0 == FBUtilities.compareByteSubArrays(
FBUtilities.getLocalAddress().getAddress(),
0,
merged,
HEADER_LENGTH + 0*stepLength,
4);
assert 1266L == FBUtilities.byteArrayToLong(merged, HEADER_LENGTH + 0*stepLength + idLength);
assert 2 == FBUtilities.byteArrayToInt(merged, HEADER_LENGTH + 1*stepLength);
assert 999L == FBUtilities.byteArrayToLong(merged, HEADER_LENGTH + 1*stepLength + idLength);
assert 3 == FBUtilities.byteArrayToInt(merged, HEADER_LENGTH + 2*stepLength);
assert 655L == FBUtilities.byteArrayToLong(merged, HEADER_LENGTH + 2*stepLength + idLength);
assert 4 == FBUtilities.byteArrayToInt(merged, HEADER_LENGTH + 3*stepLength);
assert 632L == FBUtilities.byteArrayToLong(merged, HEADER_LENGTH + 3*stepLength + idLength);
assert 1 == FBUtilities.byteArrayToInt(merged, HEADER_LENGTH + 4*stepLength);
assert 128L == FBUtilities.byteArrayToLong(merged, HEADER_LENGTH + 4*stepLength + idLength);
assert 9 == FBUtilities.byteArrayToInt(merged, HEADER_LENGTH + 5*stepLength);
assert 62L == FBUtilities.byteArrayToLong(merged, HEADER_LENGTH + 5*stepLength + idLength);
assert 8 == FBUtilities.byteArrayToInt(merged, HEADER_LENGTH + 6*stepLength);
assert 45L == FBUtilities.byteArrayToLong(merged, HEADER_LENGTH + 6*stepLength + idLength);
assert 6 == FBUtilities.byteArrayToInt(merged, HEADER_LENGTH + 7*stepLength);
assert 2L == FBUtilities.byteArrayToLong(merged, HEADER_LENGTH + 7*stepLength + idLength);
assert 7 == FBUtilities.byteArrayToInt(merged, HEADER_LENGTH + 8*stepLength);
assert 1L == FBUtilities.byteArrayToLong(merged, HEADER_LENGTH + 8*stepLength + idLength);
}
@Test
public void testCleanNodeCounts() throws UnknownHostException
{
IncrementCounterClock clock = new IncrementCounterClock(Util.concatByteArrays(
FBUtilities.toByteArray(5L),
FBUtilities.toByteArray(0L),
FBUtilities.toByteArray(5), FBUtilities.toByteArray(912L),
FBUtilities.toByteArray(3), FBUtilities.toByteArray(35L),
FBUtilities.toByteArray(6), FBUtilities.toByteArray(15L),
FBUtilities.toByteArray(9), FBUtilities.toByteArray(6L),
FBUtilities.toByteArray(7), FBUtilities.toByteArray(1L)
));
byte[] bytes = clock.context();
assert 9 == FBUtilities.byteArrayToInt(bytes, HEADER_LENGTH + 3*stepLength);
assert 6L == FBUtilities.byteArrayToLong(bytes, HEADER_LENGTH + 3*stepLength + idLength);
clock.cleanNodeCounts(InetAddress.getByAddress(FBUtilities.toByteArray(9)));
bytes = clock.context();
// node: 0.0.0.9 should be removed
assert HEADER_LENGTH + 4 * stepLength == bytes.length;
// verify that the other nodes are unmodified
assert 5 == FBUtilities.byteArrayToInt(bytes, HEADER_LENGTH + 0*stepLength);
assert 912L == FBUtilities.byteArrayToLong(bytes, HEADER_LENGTH + 0*stepLength + idLength);
assert 3 == FBUtilities.byteArrayToInt(bytes, HEADER_LENGTH + 1*stepLength);
assert 35L == FBUtilities.byteArrayToLong(bytes, HEADER_LENGTH + 1*stepLength + idLength);
assert 6 == FBUtilities.byteArrayToInt(bytes, HEADER_LENGTH + 2*stepLength);
assert 15L == FBUtilities.byteArrayToLong(bytes, HEADER_LENGTH + 2*stepLength + idLength);
assert 7 == FBUtilities.byteArrayToInt(bytes, HEADER_LENGTH + 3*stepLength);
assert 1L == FBUtilities.byteArrayToLong(bytes, HEADER_LENGTH + 3*stepLength + idLength);
}
@Test
public void testSerializeDeserialize() throws IOException, UnknownHostException
{
IncrementCounterClock clock = new IncrementCounterClock(Util.concatByteArrays(
FBUtilities.toByteArray(5L),
FBUtilities.toByteArray(0L),
FBUtilities.toByteArray(5), FBUtilities.toByteArray(912L),
FBUtilities.toByteArray(3), FBUtilities.toByteArray(35L),
FBUtilities.toByteArray(6), FBUtilities.toByteArray(15L),
FBUtilities.toByteArray(9), FBUtilities.toByteArray(6L),
FBUtilities.toByteArray(7), FBUtilities.toByteArray(1L)
));
// size
DataOutputBuffer bufOut = new DataOutputBuffer();
IncrementCounterClock.SERIALIZER.serialize(clock, bufOut);
assert bufOut.getLength() == clock.size();
// equality
ByteArrayInputStream bufIn = new ByteArrayInputStream(bufOut.getData(), 0, bufOut.getLength());
IncrementCounterClock deserialized = (IncrementCounterClock)IncrementCounterClock.SERIALIZER.deserialize(new DataInputStream(bufIn));
assert 0 == FBUtilities.compareByteArrays(clock.context(), deserialized.context());
}
}