blob: b9b62702a814f2173d135547596ae47787681b94 [file] [log] [blame]
package org.apache.helix.common.caches;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.helix.MockAccessor;
import org.apache.helix.PropertyKey;
import org.apache.helix.zookeeper.datamodel.ZNRecord;
import org.apache.helix.model.CurrentState;
import org.apache.helix.model.LiveInstance;
import org.testng.Assert;
import org.testng.annotations.Test;
/**
* Unit test for {@link CurrentStateSnapshot}
*/
public class TestCurrentStateSnapshot {
// This test makes sure that currentStateEndTimes calculation would record correct partition replica.
// Specifically, if a replicate has not endTime field set, we should not put an entry into currentStateEndTime
// calculation. Otherwise, we see huge statePropagation latency of 1.4Tms.
@Test(description = "test getNewCurrentStateEndTimes")
public void testGetNewCurrentStateEndTimes() {
String instance1 = "instance1";
String session1 = "session1";
String resource1 = "resource1";
String partition1 = "partition1";
String partition2 = "partition2";
PropertyKey key = new PropertyKey.Builder("cluster").currentState(instance1, session1, resource1);
CurrentState nxtState = new CurrentState(resource1);
// partition 1, expect to record in endTimesMap
nxtState.setState(partition1, "SLAVE");
nxtState.setEndTime(partition1, 200);
// partition 2, expect to not record in endTimeMap. This is fixing current 1.4T observed timestamp issue
nxtState.setState(partition2, "MASTER");
Map<PropertyKey, CurrentState> currentStateMap = new HashMap<>();
Map<PropertyKey, CurrentState> nextStateMap = new HashMap<>();
nextStateMap.put(key, nxtState);
Set<PropertyKey> updateKeys = new HashSet<>();
updateKeys.add(key);
CurrentStateSnapshot snapshot = new CurrentStateSnapshot(nextStateMap, currentStateMap, updateKeys);
Map<PropertyKey, Map<String, Long>> endTimesMap = snapshot.getNewCurrentStateEndTimes();
Assert.assertEquals(endTimesMap.size(), 1);
Assert.assertTrue(endTimesMap.get(key).get(partition1) == 200);
}
// This test makes sure that all the changed current State is reflected in newCurrentStateEndTimes calculation.
// Previously, we have bugs that all newly created current state would be reflected in newCurrentStateEndTimes
// calculation.
@Test(description = "testRefreshCurrentStateCache")
public void testRefreshCurrentStateCache() {
String instanceName = "instance1";
long instanceSession = 12345;
String resourceName = "resource";
String partitionName = "resource_partition1";
MockAccessor accessor = new MockAccessor();
PropertyKey.Builder keyBuilder = accessor.keyBuilder();
// construct liveInstance
ZNRecord record = new ZNRecord(instanceName);
record.setEphemeralOwner(instanceSession);
LiveInstance instance = new LiveInstance(record);
boolean retVal = accessor.setProperty(keyBuilder.liveInstance(instanceName), instance);
Assert.assertTrue(retVal);
// construct currentstate
CurrentState originState = new CurrentState(resourceName);
originState.setEndTime(partitionName, 100);
CurrentState currentState = new CurrentState(resourceName);
currentState.setEndTime(partitionName, 300);
retVal = accessor.setProperty(keyBuilder.currentState(instanceName, instance.getEphemeralOwner(), resourceName),
originState);
Assert.assertTrue(retVal);
CurrentStateCache cache = new CurrentStateCache("cluster");
Map<String, LiveInstance> liveInstanceMap = new HashMap<>();
liveInstanceMap.put(instanceName, instance);
retVal = cache.refresh(accessor, liveInstanceMap);
Assert.assertTrue(retVal);
retVal = accessor.setProperty(keyBuilder.currentState(instanceName, instance.getEphemeralOwner(), resourceName),
currentState);
Assert.assertTrue(retVal);
retVal = cache.refresh(accessor, liveInstanceMap);
Assert.assertTrue(retVal);
CurrentStateSnapshot snapshot = cache.getSnapshot();
Map<PropertyKey, Map<String, Long>> endTimesMap = snapshot.getNewCurrentStateEndTimes();
Assert.assertEquals(endTimesMap.size(), 1);
// note, without this fix, the endTimesMap would be size zero.
Assert.assertTrue(endTimesMap.get(keyBuilder.currentState(instanceName, instance.getEphemeralOwner(), resourceName))
.get(partitionName) == 300);
}
}