use of org.hbase.async.KeyValue in project opentsdb by OpenTSDB.
the class TestUniqueId method getOrCreateIdAssignIdWithRaceCondition.
// Test the creation of an ID with a race condition.
@Test
public void getOrCreateIdAssignIdWithRaceCondition() {
// Simulate a race between client A and client B.
// A does a Get and sees that there's no ID for this name.
// B does a Get and sees that there's no ID too, and B actually goes
// through the entire process to create the ID.
// Then A attempts to go through the process and should discover that the
// ID has already been assigned.
// Used by client A.
uid = new UniqueId(client, table, METRIC, 3);
// For client B.
HBaseClient client_b = mock(HBaseClient.class);
final UniqueId uid_b = new UniqueId(client_b, table, METRIC, 3);
final byte[] id = { 0, 0, 5 };
final byte[] byte_name = { 'f', 'o', 'o' };
final ArrayList<KeyValue> kvs = new ArrayList<KeyValue>(1);
kvs.add(new KeyValue(byte_name, ID, METRIC_ARRAY, id));
final Deferred<ArrayList<KeyValue>> d = PowerMockito.spy(new Deferred<ArrayList<KeyValue>>());
when(client.get(anyGet())).thenReturn(d).thenReturn(Deferred.fromResult(kvs));
final Answer<byte[]> the_race = new Answer<byte[]>() {
public byte[] answer(final InvocationOnMock unused_invocation) throws Exception {
// While answering A's first Get, B doest a full getOrCreateId.
assertArrayEquals(id, uid_b.getOrCreateId("foo"));
d.callback(null);
return (byte[]) ((Deferred) d).join();
}
};
// Start the race when answering A's first Get.
try {
PowerMockito.doAnswer(the_race).when(d).joinUninterruptibly();
} catch (Exception e) {
fail("Should never happen: " + e);
}
// null => ID doesn't exist.
when(client_b.get(anyGet())).thenReturn(Deferred.<ArrayList<KeyValue>>fromResult(null));
// Watch this! ______,^ I'm writing C++ in Java!
when(client_b.atomicIncrement(incrementForRow(MAXID))).thenReturn(Deferred.fromResult(5L));
when(client_b.compareAndSet(anyPut(), emptyArray())).thenReturn(Deferred.fromResult(true)).thenReturn(Deferred.fromResult(true));
// Now that B is finished, A proceeds and allocates a UID that will be
// wasted, and creates the reverse mapping, but fails at creating the
// forward mapping.
when(client.atomicIncrement(incrementForRow(MAXID))).thenReturn(Deferred.fromResult(6L));
when(client.compareAndSet(anyPut(), emptyArray())).thenReturn(// Orphan reverse mapping.
Deferred.fromResult(true)).thenReturn(// Already CAS'ed by A.
Deferred.fromResult(false));
// Start the execution.
assertArrayEquals(id, uid.getOrCreateId("foo"));
// Verify the order of execution too.
final InOrder order = inOrder(client, client_b);
// 1st Get for A.
order.verify(client).get(anyGet());
// 1st Get for B.
order.verify(client_b).get(anyGet());
order.verify(client_b).atomicIncrement(incrementForRow(MAXID));
// both mappings.
order.verify(client_b, times(2)).compareAndSet(// both mappings.
anyPut(), emptyArray());
order.verify(client).atomicIncrement(incrementForRow(MAXID));
// both mappings.
order.verify(client, times(2)).compareAndSet(// both mappings.
anyPut(), emptyArray());
// A retries and gets it.
order.verify(client).get(anyGet());
}
use of org.hbase.async.KeyValue in project opentsdb by OpenTSDB.
the class TestUniqueId method getOrCreateIdAssignFilterReturnException.
@Test(expected = RuntimeException.class)
public void getOrCreateIdAssignFilterReturnException() {
uid = new UniqueId(client, table, METRIC, 3);
final Config config = mock(Config.class);
when(config.enable_realtime_uid()).thenReturn(false);
final TSDB tsdb = mock(TSDB.class);
when(tsdb.getConfig()).thenReturn(config);
uid.setTSDB(tsdb);
final UniqueIdFilterPlugin filter = mock(UniqueIdFilterPlugin.class);
when(filter.fillterUIDAssignments()).thenReturn(true);
when(filter.allowUIDAssignment(any(UniqueIdType.class), anyString(), anyString(), anyMapOf(String.class, String.class))).thenReturn(Deferred.<Boolean>fromError(new UnitTestException()));
when(tsdb.getUidFilter()).thenReturn(filter);
// null => ID doesn't exist.
when(client.get(anyGet())).thenReturn(Deferred.<ArrayList<KeyValue>>fromResult(null));
// Watch this! ______,^ I'm writing C++ in Java!
when(client.atomicIncrement(incrementForRow(MAXID))).thenReturn(Deferred.fromResult(5L));
when(client.compareAndSet(anyPut(), emptyArray())).thenReturn(Deferred.fromResult(true)).thenReturn(Deferred.fromResult(true));
uid.getOrCreateId("foo");
}
use of org.hbase.async.KeyValue in project opentsdb by OpenTSDB.
the class TestUniqueId method getOrCreateIdAsyncAssignFilterReturnException.
@Test(expected = UnitTestException.class)
public void getOrCreateIdAsyncAssignFilterReturnException() throws Exception {
uid = new UniqueId(client, table, METRIC, 3);
final Config config = mock(Config.class);
when(config.enable_realtime_uid()).thenReturn(false);
final TSDB tsdb = mock(TSDB.class);
when(tsdb.getConfig()).thenReturn(config);
uid.setTSDB(tsdb);
final UniqueIdFilterPlugin filter = mock(UniqueIdFilterPlugin.class);
when(filter.fillterUIDAssignments()).thenReturn(true);
when(filter.allowUIDAssignment(any(UniqueIdType.class), anyString(), anyString(), anyMapOf(String.class, String.class))).thenReturn(Deferred.<Boolean>fromError(new UnitTestException()));
when(tsdb.getUidFilter()).thenReturn(filter);
// null => ID doesn't exist.
when(client.get(anyGet())).thenReturn(Deferred.<ArrayList<KeyValue>>fromResult(null));
when(client.atomicIncrement(incrementForRow(MAXID))).thenReturn(Deferred.fromResult(5L));
when(client.compareAndSet(anyPut(), emptyArray())).thenReturn(Deferred.fromResult(true)).thenReturn(Deferred.fromResult(true));
uid.getOrCreateIdAsync("foo").join();
}
use of org.hbase.async.KeyValue in project opentsdb by OpenTSDB.
the class TestUniqueId method getIdSuccessfulHBaseLookup.
@Test
public void getIdSuccessfulHBaseLookup() {
uid = new UniqueId(client, table, METRIC, 3);
final byte[] id = { 0, 'a', 0x42 };
final byte[] byte_name = { 'f', 'o', 'o' };
ArrayList<KeyValue> kvs = new ArrayList<KeyValue>(1);
kvs.add(new KeyValue(byte_name, ID, METRIC_ARRAY, id));
when(client.get(anyGet())).thenReturn(Deferred.fromResult(kvs));
assertArrayEquals(id, uid.getId("foo"));
// Should be a cache hit ...
assertArrayEquals(id, uid.getId("foo"));
// Should be a cache hit too ...
assertArrayEquals(id, uid.getId("foo"));
assertEquals(2, uid.cacheHits());
assertEquals(1, uid.cacheMisses());
assertEquals(2, uid.cacheSize());
// ... so verify there was only one HBase Get.
verify(client).get(anyGet());
}
use of org.hbase.async.KeyValue in project opentsdb by OpenTSDB.
the class TestUniqueId method getOrCreateIdAsyncAssignFilterOK.
@Test
public void getOrCreateIdAsyncAssignFilterOK() throws Exception {
uid = new UniqueId(client, table, METRIC, 3);
final byte[] id = { 0, 0, 5 };
final Config config = mock(Config.class);
when(config.enable_realtime_uid()).thenReturn(false);
final TSDB tsdb = mock(TSDB.class);
when(tsdb.getConfig()).thenReturn(config);
uid.setTSDB(tsdb);
final UniqueIdFilterPlugin filter = mock(UniqueIdFilterPlugin.class);
when(filter.fillterUIDAssignments()).thenReturn(true);
when(filter.allowUIDAssignment(any(UniqueIdType.class), anyString(), anyString(), anyMapOf(String.class, String.class))).thenReturn(Deferred.fromResult(true));
when(tsdb.getUidFilter()).thenReturn(filter);
// null => ID doesn't exist.
when(client.get(anyGet())).thenReturn(Deferred.<ArrayList<KeyValue>>fromResult(null));
// Watch this! ______,^ I'm writing C++ in Java!
when(client.atomicIncrement(incrementForRow(MAXID))).thenReturn(Deferred.fromResult(5L));
when(client.compareAndSet(anyPut(), emptyArray())).thenReturn(Deferred.fromResult(true)).thenReturn(Deferred.fromResult(true));
assertArrayEquals(id, uid.getOrCreateIdAsync("foo").join());
// Should be a cache hit since we created that entry.
assertArrayEquals(id, uid.getOrCreateIdAsync("foo").join());
// Should be a cache hit too for the same reason.
assertEquals("foo", uid.getName(id));
// Initial Get.
verify(client).get(anyGet());
verify(client).atomicIncrement(incrementForRow(MAXID));
// Reverse + forward mappings.
verify(client, times(2)).compareAndSet(anyPut(), emptyArray());
verify(filter, times(1)).allowUIDAssignment(any(UniqueIdType.class), anyString(), anyString(), anyMapOf(String.class, String.class));
}
Aggregations