public static void replayNode( final Id id, final InetSocketAddress addr, InetSocketAddress bootaddress, final long startTime, final long randSeed) throws Exception { Environment env = new Environment(); if (env.getParameters() .getBoolean("org.mpisws.p2p.testing.transportlayer.replay.Replayer_printlog")) printLog("0x" + id.toStringFull().substring(0, 6), env); // Environment env = Environment.directEnvironment(); System.out.println( id.toStringFull() + " " + addr.getAddress().getHostAddress() + " " + addr.getPort() + " " + bootaddress.getPort() + " " + startTime + " " + randSeed); env.destroy(); new Replayer(id, addr, bootaddress, startTime, randSeed); }
@Test public void testGettersAndSetter() { // act content.setId(Id.build("butter")); // assert assertEquals(Id.build("butter"), content.getId()); }
/** * produces a Id whose prefix up to row is identical to this, followed by a digit with value * column, followed by a suffix of digits with value suffixDigits. * * @param row the length of the prefix * @param column the value of the following digit * @param suffixDigit the value of the suffix digits * @param b power of 2 of the base * @return the resulting Id */ public Id getDomainPrefix(int row, int column, int suffixDigit, int b) { Id res = new Id(Id); res.setDigit(row, column, b); for (int i = 0; i < row; i++) { res.setDigit(i, suffixDigit, b); } return build(res.Id); }
/** * Checks if this Id is between two given ids ccw (inclusive) and cw (exclusive) on the circle * * @param ccw the counterclockwise id * @param cw the clockwise id * @return true if this is between ccw (inclusive) and cw (exclusive), false otherwise */ public boolean isBetween(Id ccw, Id cw) { if (ccw.equals(cw)) { return false; } if (ccw.clockwise(cw)) { return this.clockwise(cw) && !this.clockwise(ccw); } else { return !this.clockwise(ccw) || this.clockwise(cw); } }
/** * produces a set of ids (keys) that are evenly distributed around the id ring. One invocation * produces the i-th member of a set of size num. The set is evenly distributed around the ring, * with an offset given by this Id. The set is useful for constructing, for instance, Scribe trees * with disjoint sets of interior nodes. * * @param num the number of Ids in the set (must be <= 2^b) * @param b the routing base (as a power of 2) * @param i the index of the requested member of the set (0<=i<num; the 0-th member is this) * @return the resulting set member, or null in case of illegal arguments */ public Id getAlternateId(int num, int b, int i) { if (num > (1 << b) || i < 0 || i >= num) { return null; } Id res = new Id(Id); int digit = res.getDigit(numDigits(b) - 1, b) + ((1 << b) / num) * i; res.setDigit(numDigits(b) - 1, digit, b); return build(res.Id); }
@Test public void testDeliverOfBackupMessageIfItIsNewer() { // setup content.getContentHeaders().put(DhtContentHeader.CONTENT_VERSION, Long.toString(2)); backupMessage = new InsertBackupMessage(85, content, -1, nodeHandle, content.getId()); // Make sure that the existing content is older KoalaMutableContent existingContent = new KoalaPiEntityContent( Id.build("ExisingContent"), "existingContent", new HashMap<String, String>()); existingContent.getContentHeaders().put(DhtContentHeader.CONTENT_VERSION, Long.toString(1)); GenericContinuationAnswer<KoalaMutableContent> g = new GenericContinuationAnswer<KoalaMutableContent>(existingContent); doAnswer(g) .when(storageManager) .getObject(eq(content.getId()), isA(StandardContinuation.class)); ArgumentCaptor<GCPastMetadata> metadataArgument = ArgumentCaptor.forClass(GCPastMetadata.class); // act koalaGCPastImpl.deliver(content.getId(), backupMessage); // assert verify(storageManager) .store( eq(content.getId()), metadataArgument.capture(), eq(content), isA(StandardContinuation.class)); assertEquals(2, metadataArgument.getValue().getExpiration()); }
@Test public void testInsertGetsVersion() { // setup KoalaGCPastImpl localGcPastImpl = new KoalaGCPastImpl( node, storageManager, null, 0, instance, new KoalaPastPolicy(), 0, storageManager, KoalaNode.DEFAULT_NUMBER_OF_DHT_BACKUPS, koalaIdFactory, koalaPiEntityFactory) { @Override protected void sendRequest( rice.p2p.commonapi.Id id, PastMessage message, Continuation command) { sentId = id; sentMessage = message; callBackContinuation = command; } }; PastContent content = new KoalaPiEntityContent( Id.build("bob"), "the builder", false, "text", 0, NodeScope.AVAILABILITY_ZONE, "tv:series", 18); Continuation command = mock(Continuation.class); // act localGcPastImpl.insert(content, command); // assert assertEquals(sentId, Id.build("bob")); assertTrue(sentMessage instanceof InsertRequestMessage); assertEquals(18, ((InsertRequestMessage) sentMessage).getExpiration()); assertEquals(content, ((InsertRequestMessage) sentMessage).getContent()); assertEquals(command, callBackContinuation); }
@Test public void testGetMultiContinuation() { // setup final PId idToQuery = new PiId(messageId.toStringFull(), 0); // act koalaGCPastImpl.get(idToQuery, continuation); }
@Test public void testGetAny() { // setup final PId idToQuery = new PiId(messageId.toStringFull(), 0); // act koalaGCPastImpl.getAny(idToQuery, continuation); // assert assertTrue(lookupContinuation instanceof KoalaPiEntityResultContinuation); assertEquals(messageId, lookupId); }
/** @param args */ public static void main(String[] args) throws Exception { // System.out.println(args[0]+" "+args[1]+" "+args[2]+" "+args[3]); String hex = args[0]; InetAddress a = InetAddress.getByName(args[1]); int startPort = Integer.decode(args[2]).intValue(); int bootPort = Integer.decode(args[3]).intValue(); InetSocketAddress addr = new InetSocketAddress(a, startPort); InetSocketAddress bootaddress = new InetSocketAddress(a, bootPort); long startTime = Long.decode(args[4]).longValue(); long randSeed = Long.decode(args[5]).longValue(); replayNode(Id.build(hex), addr, bootaddress, startTime, randSeed); }
@Before public void before() { id = Id.build("CAFEBEEF"); healthContent = "yellow"; typeStr = "String"; mockPast = mock(Past.class); mockNodeHandle = mock(NodeHandle.class); headers = new HashMap<String, String>(); mockTimeSource = mock(TimeSource.class); mockEnvironment = mock(Environment.class); when(mockEnvironment.getTimeSource()).thenReturn(mockTimeSource); content = new KoalaPiEntityContent(id, healthContent, headers); content.setVersion(0); }
@Test public void testEquals() { KoalaMutableContent content = new KoalaPiEntityContent(id, healthContent, new HashMap<String, String>()); KoalaMutableContent contentDiffContent = new KoalaPiEntityContent(id, healthContent + "boo", new HashMap<String, String>()); KoalaMutableContent contentDiffId = new KoalaPiEntityContent( Id.build("different"), healthContent, new HashMap<String, String>()); KoalaMutableContent contentSame = new KoalaPiEntityContent(id, healthContent, new HashMap<String, String>()); assertEquals(contentSame, content); assertFalse(content.equals(contentDiffId)); assertFalse(content.equals(contentDiffContent)); }
@Test public void testGet() { final AtomicInteger count = new AtomicInteger(0); final PId idToQuery = new PiId(messageId.toStringFull(), 0); koalaGCPastImpl = new KoalaGCPastImpl( node, storageManager, null, 0, instance, new KoalaPastPolicy(), 0, storageManager, KoalaNode.DEFAULT_NUMBER_OF_DHT_BACKUPS, koalaIdFactory, koalaPiEntityFactory) { @Override protected Continuation getResponseContinuation(PastMessage msg) { if (msg.equals(message)) return continuation; return null; } @Override protected void getHandles(rice.p2p.commonapi.Id id, int max, Continuation command) { NodeHandleSet nodeSet = mock(NodeHandleSet.class); when(nodeSet.size()).thenReturn(3); command.receiveResult(nodeSet); } @Override public void lookupHandle( rice.p2p.commonapi.Id id, NodeHandle handle, Continuation command) { assertEquals(Id.build(idToQuery.toStringFull()), id); count.addAndGet(1); } }; // act koalaGCPastImpl.get(idToQuery, continuation); // assert assertEquals(3, count.intValue()); }
public void init() { invokedInsert = false; messageId = Id.build("1111567890123456789012345678901234560023"); content = new KoalaPiEntityContent( messageId, "what", false, "type", 4, NodeScope.AVAILABILITY_ZONE, "url", 1); continuation = mock(Continuation.class); builder = mock(MessageBuilder.class); when(builder.buildMessage()) .thenReturn(new GCInsertMessage(-1, content, 0L, nodeHandle, Id.build("dest"))); Logger logger = mock(Logger.class); LogManager logManager = mock(LogManager.class); when(logManager.getLogger(isA(Class.class), eq(instance))).thenReturn(logger); Parameters parameters = mock(Parameters.class); RandomSource randomSource = mock(RandomSource.class); Environment environment = mock(Environment.class); when(environment.getLogManager()).thenReturn(logManager); when(environment.getParameters()).thenReturn(parameters); when(environment.getRandomSource()).thenReturn(randomSource); TimeSource timesource = mock(TimeSource.class); when(timesource.currentTimeMillis()).thenReturn(System.currentTimeMillis()); when(environment.getTimeSource()).thenReturn(timesource); Endpoint endpoint = mock(Endpoint.class); doAnswer( new Answer<Object>() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { koalaDeserializer = (MessageDeserializer) invocation.getArguments()[0]; return null; } }) .when(endpoint) .setDeserializer(isA(MessageDeserializer.class)); koalaIdFactory = mock(KoalaIdFactory.class); when(koalaIdFactory.buildIdFromToString(anyString())) .thenAnswer( new Answer<Id>() { @Override public Id answer(InvocationOnMock invocation) throws Throwable { return Id.build((String) invocation.getArguments()[0]); } }); when(koalaIdFactory.buildId(anyString())) .thenAnswer( new Answer<Id>() { @Override public Id answer(InvocationOnMock invocation) throws Throwable { return Id.build((String) invocation.getArguments()[0]); } }); node = mock(PastryNode.class); when(node.getEnvironment()).thenReturn(environment); when(node.buildEndpoint(isA(Application.class), eq(instance))).thenReturn(endpoint); when(node.getIdFactory()).thenReturn(koalaIdFactory); sentBackupContent = new ArrayList<KoalaMutableContent>(); backupIds = new HashSet<rice.p2p.commonapi.Id>(); storageManager = mock(StorageManager.class); koalaPiEntityFactory = mock(KoalaPiEntityFactory.class); }
@SuppressWarnings("unchecked") public class KoalaGCPastImplTest { private KoalaGCPastImpl koalaGCPastImpl; private PastMessage message; private KoalaMutableContent content; private Continuation continuation; private boolean invokedInsert; private PastryNode node; private String instance; private StorageManager storageManager; private MessageDeserializer koalaDeserializer; private Continuation getHandlesContinuation; private rice.p2p.commonapi.Id getHandlesId; private NodeHandle nodeHandle; private PastMessage receivedInserRequestPastmessage; private Continuation receivedInserRequestContinuation; private MessageBuilder builder; private KoalaPiEntityFactory koalaPiEntityFactory; private Continuation lookupContinuation; private rice.p2p.commonapi.Id lookupId; private rice.p2p.commonapi.Id contentId; private double expectedRequiredhandlePercentage = .44; protected rice.p2p.commonapi.Id lookupHandlesId; protected double requiredHandlesPercentage; protected Continuation lookupHandlesContinuation; private Id dummyId = Id.build( "People are more violently opposed to fur than leather because it's safer to harass rich women than motorcycle gangs."); private KoalaIdFactory koalaIdFactory; private ArrayList<KoalaMutableContent> sentBackupContent; private HashSet<rice.p2p.commonapi.Id> backupIds; private PId realTestId; private InsertBackupMessage backupMessage; private boolean collectCalled = false; private rice.p2p.commonapi.Id sentId = null; private PastMessage sentMessage = null; private Continuation callBackContinuation = null; private Id messageId; @Before public void initKoalaGCPastImpl() { init(); koalaGCPastImpl = new KoalaGCPastImpl( node, storageManager, null, 0, instance, new KoalaPastPolicy(), 0, storageManager, KoalaNode.DEFAULT_NUMBER_OF_DHT_BACKUPS, koalaIdFactory, koalaPiEntityFactory) { @Override public void insert(PastContent obj, long expiration, Continuation command) { invokedInsert = true; } @Override protected Continuation getResponseContinuation(PastMessage msg) { if (msg.equals(message)) return continuation; if (msg.equals(backupMessage)) return continuation; if (msg instanceof GCRefreshMessage) return continuation; return null; } @Override public void lookupHandle( rice.p2p.commonapi.Id id, NodeHandle handle, Continuation command) {} @Override public void lookup(rice.p2p.commonapi.Id id, boolean b, Continuation command) { lookupId = id; lookupContinuation = command; } @Override public void getHandles(rice.p2p.commonapi.Id id, int max, Continuation command) { getHandlesId = id; getHandlesContinuation = command; } @Override public void lookupHandles( rice.p2p.commonapi.Id id, int max, double requiredHandles, Continuation command) { lookupHandlesId = id; requiredHandlesPercentage = requiredHandles; lookupHandlesContinuation = command; } @Override protected void sendRequest( rice.p2p.commonapi.Id id, PastMessage message, Continuation command) { backupIds.add(id); KoalaMutableContent recievedBackupContent = (KoalaMutableContent) ((InsertBackupMessage) message).getContent(); sentBackupContent.add(recievedBackupContent); } protected void collect(java.util.SortedMap map, Continuation command) { collectCalled = true; }; }; koalaGCPastImpl.setRequiredReadHandlesPercentage(expectedRequiredhandlePercentage); } @Before public void before() { nodeHandle = mock(NodeHandle.class); } public void init() { invokedInsert = false; messageId = Id.build("1111567890123456789012345678901234560023"); content = new KoalaPiEntityContent( messageId, "what", false, "type", 4, NodeScope.AVAILABILITY_ZONE, "url", 1); continuation = mock(Continuation.class); builder = mock(MessageBuilder.class); when(builder.buildMessage()) .thenReturn(new GCInsertMessage(-1, content, 0L, nodeHandle, Id.build("dest"))); Logger logger = mock(Logger.class); LogManager logManager = mock(LogManager.class); when(logManager.getLogger(isA(Class.class), eq(instance))).thenReturn(logger); Parameters parameters = mock(Parameters.class); RandomSource randomSource = mock(RandomSource.class); Environment environment = mock(Environment.class); when(environment.getLogManager()).thenReturn(logManager); when(environment.getParameters()).thenReturn(parameters); when(environment.getRandomSource()).thenReturn(randomSource); TimeSource timesource = mock(TimeSource.class); when(timesource.currentTimeMillis()).thenReturn(System.currentTimeMillis()); when(environment.getTimeSource()).thenReturn(timesource); Endpoint endpoint = mock(Endpoint.class); doAnswer( new Answer<Object>() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { koalaDeserializer = (MessageDeserializer) invocation.getArguments()[0]; return null; } }) .when(endpoint) .setDeserializer(isA(MessageDeserializer.class)); koalaIdFactory = mock(KoalaIdFactory.class); when(koalaIdFactory.buildIdFromToString(anyString())) .thenAnswer( new Answer<Id>() { @Override public Id answer(InvocationOnMock invocation) throws Throwable { return Id.build((String) invocation.getArguments()[0]); } }); when(koalaIdFactory.buildId(anyString())) .thenAnswer( new Answer<Id>() { @Override public Id answer(InvocationOnMock invocation) throws Throwable { return Id.build((String) invocation.getArguments()[0]); } }); node = mock(PastryNode.class); when(node.getEnvironment()).thenReturn(environment); when(node.buildEndpoint(isA(Application.class), eq(instance))).thenReturn(endpoint); when(node.getIdFactory()).thenReturn(koalaIdFactory); sentBackupContent = new ArrayList<KoalaMutableContent>(); backupIds = new HashSet<rice.p2p.commonapi.Id>(); storageManager = mock(StorageManager.class); koalaPiEntityFactory = mock(KoalaPiEntityFactory.class); } @Test public void testDeserializer() throws IOException { InputBuffer inBuf = mock(InputBuffer.class); when(inBuf.readByte()).thenReturn(new Byte((byte) 0)); Object message = koalaDeserializer.deserialize( inBuf, InsertRequestMessage.TYPE, InsertRequestMessage.DEFAULT_PRIORITY, mock(NodeHandle.class)); assertTrue(message instanceof InsertRequestMessage); } @Test public void testDeliverRandomMessage() throws Exception { // setup message = new InsertMessage(0, content, null, null); // act koalaGCPastImpl.deliver(null, message); // assert assertFalse(invokedInsert); } @Test public void testDeliverGCRefresh() throws Exception { // setup GCIdSet idSet = mock(GCIdSet.class); when(idSet.numElements()).thenReturn(1); GCId id = mock(GCId.class); when(idSet.asArray()).thenReturn(new GCId[] {id}); message = new GCRefreshMessage(0, idSet, null, null); // act koalaGCPastImpl.deliver(null, message); // assert verify(continuation).receiveResult(AdditionalMatchers.aryEq(new Boolean[] {Boolean.TRUE})); verify(storageManager, never()).exists((Id) anyObject()); } @Test public void testDeliverGCCollect() throws Exception { // setup message = new GCCollectMessage(0, null, null); // act koalaGCPastImpl.deliver(null, message); // assert assertFalse(collectCalled); } @Test public void testInsert() throws Exception { // setup koalaGCPastImpl = new KoalaGCPastImpl( node, storageManager, null, 0, instance, new KoalaPastPolicy(), 0, storageManager, KoalaNode.DEFAULT_NUMBER_OF_DHT_BACKUPS, koalaIdFactory, koalaPiEntityFactory) { @Override protected void sendRequest( rice.p2p.commonapi.Id id, PastMessage message, Continuation command) { contentId = id; receivedInserRequestContinuation = command; receivedInserRequestPastmessage = message; } }; // act koalaGCPastImpl.insert(content, 0, continuation); // assert assertEquals(contentId, content.getId()); assertTrue(receivedInserRequestPastmessage instanceof InsertRequestMessage); assertEquals(receivedInserRequestContinuation, continuation); } @Test public void testDoInsert() { final Object expectedResult = new Object(); Continuation continuation = mock(Continuation.class); doAnswer( new Answer<Object>() { public Object answer(InvocationOnMock invocation) throws Throwable { // KoalaMutableContent existingContent = new KoalaPiEntityContent(dhtId, "what2", // new HashMap<String, // String>()); KoalaMutableContent existingContent = new KoalaPiEntityContent(messageId, "what2", new HashMap<String, String>()); ((StandardContinuation) invocation.getArguments()[1]) .receiveResult(existingContent); return null; } }) .when(storageManager) .getObject(eq(messageId), isA(StandardContinuation.class)); doAnswer( new Answer<Object>() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { ((StandardContinuation) invocation.getArguments()[3]).receiveResult(expectedResult); return null; } }) .when(storageManager) .store( eq(messageId), (Serializable) argThat( new ArgumentMatcher<GCPastMetadata>() { @Override public boolean matches(Object argument) { if (!(argument instanceof GCPastMetadata)) return false; GCPastMetadata koalaContentMetadata = (GCPastMetadata) argument; return koalaContentMetadata.getExpiration() == content.getVersion(); } }), argThat( new ArgumentMatcher<KoalaMutableContent>() { @Override public boolean matches(Object argument) { if (!(argument instanceof KoalaMutableContent)) return false; KoalaMutableContent koalaMutableContent = (KoalaMutableContent) argument; rice.p2p.commonapi.Id id = koalaMutableContent.getId(); return id.equals(messageId); // return id.toStringFull().endsWith("0001"); } }), isA(StandardContinuation.class)); // act koalaGCPastImpl.doInsert(content.getId(), builder, continuation, false); // verify assertEquals(messageId, getHandlesId); assertTrue(getHandlesContinuation instanceof KoalaPastGetHandlesInsertContinuation); } @Test public void testDoInsertCheckInsertFails() { // setup Continuation continuation = mock(Continuation.class); doAnswer( new Answer<Object>() { public Object answer(InvocationOnMock invocation) throws Throwable { // KoalaMutableContent existingContent = new KoalaPiEntityContent(dhtId, "what2", // new HashMap<String, // String>()); KoalaMutableContent existingContent = new KoalaPiEntityContent(messageId, "what2", new HashMap<String, String>()); existingContent .getContentHeaders() .put(DhtContentHeader.CONTENT_VERSION, Long.toString(2)); ((StandardContinuation) invocation.getArguments()[1]) .receiveResult(existingContent); return null; } }) .when(storageManager) .getObject(eq(messageId), isA(StandardContinuation.class)); // act koalaGCPastImpl.doInsert(content.getId(), builder, continuation, false); // verify verify(continuation).receiveException(isA(PastException.class)); } @Test public void testGet() { final AtomicInteger count = new AtomicInteger(0); final PId idToQuery = new PiId(messageId.toStringFull(), 0); koalaGCPastImpl = new KoalaGCPastImpl( node, storageManager, null, 0, instance, new KoalaPastPolicy(), 0, storageManager, KoalaNode.DEFAULT_NUMBER_OF_DHT_BACKUPS, koalaIdFactory, koalaPiEntityFactory) { @Override protected Continuation getResponseContinuation(PastMessage msg) { if (msg.equals(message)) return continuation; return null; } @Override protected void getHandles(rice.p2p.commonapi.Id id, int max, Continuation command) { NodeHandleSet nodeSet = mock(NodeHandleSet.class); when(nodeSet.size()).thenReturn(3); command.receiveResult(nodeSet); } @Override public void lookupHandle( rice.p2p.commonapi.Id id, NodeHandle handle, Continuation command) { assertEquals(Id.build(idToQuery.toStringFull()), id); count.addAndGet(1); } }; // act koalaGCPastImpl.get(idToQuery, continuation); // assert assertEquals(3, count.intValue()); } @Test public void testGetMultiContinuation() { // setup final PId idToQuery = new PiId(messageId.toStringFull(), 0); // act koalaGCPastImpl.get(idToQuery, continuation); } @Test public void testGetAny() { // setup final PId idToQuery = new PiId(messageId.toStringFull(), 0); // act koalaGCPastImpl.getAny(idToQuery, continuation); // assert assertTrue(lookupContinuation instanceof KoalaPiEntityResultContinuation); assertEquals(messageId, lookupId); } @Test(expected = IllegalArgumentException.class) public void testPutThrowsExceptionOnNonPersistable() { // act koalaGCPastImpl.put(new PiId("testPutException", 0), new NonPersistable(), continuation); } @Test public void testGetSuccessThreshold() { // setup koalaGCPastImpl.setSuccessfullInsertThreshold(94.3); // act assertEquals(94.3, koalaGCPastImpl.getSuccessfulInsertThreshold(), 0); } @Test public void testDeliverFetchHandleMessage() { // setup Id id = mock(Id.class); FetchHandleMessage message = mock(FetchHandleMessage.class); when(message.getId()).thenReturn(id); PId pid = mock(PId.class); when(koalaIdFactory.convertToPId(id)).thenReturn(pid); when(pid.forDht()).thenReturn(pid); when(koalaIdFactory.buildId(pid)).thenReturn(id); // act koalaGCPastImpl.deliver(null, message); // assert verify(storageManager).getObject(eq(id), isA(Continuation.class)); } @Test public void testGetGlobalIds() { // setup KoalaIdFactory koalaIdFactory = new KoalaIdFactory(0, 0); koalaIdFactory.setKoalaPiEntityFactory(koalaPiEntityFactory); koalaGCPastImpl.setKoalaIdFactory(koalaIdFactory); PId testId = koalaGCPastImpl.getKoalaIdFactory().buildPId("R. Lopez"); // act Set<String> globalIds = koalaGCPastImpl.generateBackupIds(4, NodeScope.GLOBAL, testId); // asssert assertEquals(4, globalIds.size()); assertSetEndsWithBackupIdentifier(globalIds); } private void assertSetEndsWithBackupIdentifier(Set<String> ids) { for (String str : ids) { assertEquals(1, new BigInteger(str.substring(39), 16).mod(new BigInteger("2")).intValue()); } } @Test public void testGetRegionalIds() { // setup KoalaIdFactory koalaIdFactory = new KoalaIdFactory(0, 0); koalaIdFactory.setKoalaPiEntityFactory(koalaPiEntityFactory); koalaGCPastImpl.setKoalaIdFactory(koalaIdFactory); PId testId = koalaGCPastImpl.getKoalaIdFactory().buildPId("R. Lopez"); // act Set<String> ids = koalaGCPastImpl.generateBackupIds(4, NodeScope.REGION, testId); assertEquals(4, ids.size()); assertSetEndsWithBackupIdentifier(ids); assertSetContains(ids, testId.getIdAsHex().substring(4, testId.getIdAsHex().length() - 1)); } private void assertSetContains(Set<String> ids, String mustContain) { for (String str : ids) { assertTrue(str.toLowerCase().contains(mustContain.toLowerCase())); } } @Test public void testGetAvailabilityZoneIds() { // setup KoalaIdFactory koalaIdFactory = new KoalaIdFactory(0, 0); koalaIdFactory.setKoalaPiEntityFactory(koalaPiEntityFactory); koalaGCPastImpl.setKoalaIdFactory(koalaIdFactory); PId testId = koalaGCPastImpl.getKoalaIdFactory().buildPId("YEAHBOB"); // act Set<String> ids = koalaGCPastImpl.generateBackupIds(4, NodeScope.AVAILABILITY_ZONE, testId); // assert assertEquals(4, ids.size()); assertSetEndsWithBackupIdentifier(ids); assertSetContains(ids, testId.getIdAsHex().substring(5, testId.getIdAsHex().length() - 1)); } @Test public void testGetGlobalBackupIDs() { // setup koalaGCPastImpl.setKoalaIdFactory(new KoalaIdFactory(0, 0)); realTestId = (PId) koalaGCPastImpl .getKoalaIdFactory() .buildPIdFromHexString("1234567890123456789012345678901234567892"); // act Set<String> ids = koalaGCPastImpl.generateBackupIds(4, NodeScope.GLOBAL, realTestId); // assert assertSetEndsWithBackupIdentifier(ids); assertSetContains(ids, "34567890123456789012345678901234560013"); } @Test public void testBackupContent() { // setup PId pid = mock(PId.class); when(pid.asBackupId()).thenReturn(pid); when(pid.getIdAsHex()).thenReturn(content.getId().toStringFull()); when(koalaIdFactory.convertToPId(eq(content.getId()))).thenReturn(pid); // act koalaGCPastImpl.backupContent(4, NodeScope.REGION, content); // assert assertEquals(4, backupIds.size()); for (KoalaMutableContent sentContent : sentBackupContent) { assertEquals(sentContent.getBody(), content.getBody()); assertEquals( sentContent.getContentHeaders().get(DhtContentHeader.CONTENT_TYPE), content.getContentHeaders().get(DhtContentHeader.CONTENT_TYPE)); assertEquals( sentContent.getContentHeaders().get(DhtContentHeader.ID), sentContent.getId().toStringFull()); assertEquals(sentContent.getVersion(), content.getVersion()); assertNotSame(sentContent.getId(), content.getId()); } } @Test public void testDeliverOfBackupMessageIfItIsNewer() { // setup content.getContentHeaders().put(DhtContentHeader.CONTENT_VERSION, Long.toString(2)); backupMessage = new InsertBackupMessage(85, content, -1, nodeHandle, content.getId()); // Make sure that the existing content is older KoalaMutableContent existingContent = new KoalaPiEntityContent( Id.build("ExisingContent"), "existingContent", new HashMap<String, String>()); existingContent.getContentHeaders().put(DhtContentHeader.CONTENT_VERSION, Long.toString(1)); GenericContinuationAnswer<KoalaMutableContent> g = new GenericContinuationAnswer<KoalaMutableContent>(existingContent); doAnswer(g) .when(storageManager) .getObject(eq(content.getId()), isA(StandardContinuation.class)); ArgumentCaptor<GCPastMetadata> metadataArgument = ArgumentCaptor.forClass(GCPastMetadata.class); // act koalaGCPastImpl.deliver(content.getId(), backupMessage); // assert verify(storageManager) .store( eq(content.getId()), metadataArgument.capture(), eq(content), isA(StandardContinuation.class)); assertEquals(2, metadataArgument.getValue().getExpiration()); } @Test(expected = IllegalArgumentException.class) public void testFetchNotGCId() { // act koalaGCPastImpl.fetch(mock(Id.class), mock(NodeHandle.class), mock(Continuation.class)); } @Test public void testShouldThrowExceptionIfBackupMessageIsOlderOrSameAsTheExistingBackedUpMessage() { backupMessage = new InsertBackupMessage(85, content, -1, nodeHandle, content.getId()); GenericContinuationAnswer<KoalaMutableContent> g = new GenericContinuationAnswer<KoalaMutableContent>(content); doAnswer(g) .when(storageManager) .getObject(eq(content.getId()), isA(StandardContinuation.class)); // act koalaGCPastImpl.deliver(content.getId(), backupMessage); // assert verify(continuation).receiveException(isA(KoalaContentVersionMismatchException.class)); } @Test public void testFetchNotInStorage() throws Exception { // setup KoalaPastPolicy koalaPastPolicy = mock(KoalaPastPolicy.class); koalaGCPastImpl = new KoalaGCPastImpl( node, storageManager, null, 0, instance, koalaPastPolicy, 0, storageManager, KoalaNode.DEFAULT_NUMBER_OF_DHT_BACKUPS, koalaIdFactory, koalaPiEntityFactory); Id id = mock(Id.class); GCId gcId = mock(GCId.class); when(gcId.getId()).thenReturn(id); when(storageManager.exists(id)).thenReturn(false); NodeHandle hint = mock(NodeHandle.class); final CountDownLatch latch = new CountDownLatch(1); doAnswer( new Answer<Object>() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { StandardContinuation continuation = (StandardContinuation) invocation.getArguments()[4]; continuation.receiveResult(content); latch.countDown(); return null; } }) .when(koalaPastPolicy) .fetch( eq(id), eq(hint), (Cache) isNull(), isA(Past.class), isA(StandardContinuation.class)); Storage storage = mock(Storage.class); when(storageManager.getStorage()).thenReturn(storage); // act koalaGCPastImpl.fetch(gcId, hint, mock(Continuation.class)); // assert assertTrue(latch.await(500, TimeUnit.MILLISECONDS)); verify(storage).store(eq(id), isA(GCPastMetadata.class), eq(content), isA(Continuation.class)); } @Test public void shouldNotStoreLocallyWhenReplicationFetchingIfDeletableAndDeleted() throws Exception { // setup KoalaPastPolicy koalaPastPolicy = mock(KoalaPastPolicy.class); koalaGCPastImpl = new KoalaGCPastImpl( node, storageManager, null, 0, instance, koalaPastPolicy, 0, storageManager, KoalaNode.DEFAULT_NUMBER_OF_DHT_BACKUPS, koalaIdFactory, koalaPiEntityFactory); Id id = mock(Id.class); GCId gcId = mock(GCId.class); when(gcId.getId()).thenReturn(id); when(storageManager.exists(id)).thenReturn(false); NodeHandle hint = mock(NodeHandle.class); final CountDownLatch latch = new CountDownLatch(1); doAnswer( new Answer<Object>() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { StandardContinuation continuation = (StandardContinuation) invocation.getArguments()[4]; continuation.receiveResult(content); latch.countDown(); return null; } }) .when(koalaPastPolicy) .fetch( eq(id), eq(hint), (Cache) isNull(), isA(Past.class), isA(StandardContinuation.class)); Storage storage = mock(Storage.class); when(storageManager.getStorage()).thenReturn(storage); String json = "what"; content = new KoalaPiEntityContent(messageId, json, true, "text", 1, NodeScope.GLOBAL, "", 0); // act koalaGCPastImpl.fetch(gcId, hint, mock(Continuation.class)); // assert assertTrue(latch.await(500, TimeUnit.MILLISECONDS)); verify(storage, never()) .store(eq(id), isA(GCPastMetadata.class), eq(content), isA(Continuation.class)); } @Test public void shouldNotStoreLocallyWhenReplicationFetchingIfNullType() throws Exception { // setup KoalaPastPolicy koalaPastPolicy = mock(KoalaPastPolicy.class); koalaGCPastImpl = new KoalaGCPastImpl( node, storageManager, null, 0, instance, koalaPastPolicy, 0, storageManager, KoalaNode.DEFAULT_NUMBER_OF_DHT_BACKUPS, koalaIdFactory, koalaPiEntityFactory); Id id = mock(Id.class); GCId gcId = mock(GCId.class); when(gcId.getId()).thenReturn(id); when(storageManager.exists(id)).thenReturn(false); NodeHandle hint = mock(NodeHandle.class); final CountDownLatch latch = new CountDownLatch(1); doAnswer( new Answer<Object>() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { StandardContinuation continuation = (StandardContinuation) invocation.getArguments()[4]; continuation.receiveResult(content); latch.countDown(); return null; } }) .when(koalaPastPolicy) .fetch( eq(id), eq(hint), (Cache) isNull(), isA(Past.class), isA(StandardContinuation.class)); Storage storage = mock(Storage.class); when(storageManager.getStorage()).thenReturn(storage); String json = "what"; content = new KoalaPiEntityContent(messageId, json, false, null, 1, NodeScope.GLOBAL, "", 0); // act koalaGCPastImpl.fetch(gcId, hint, mock(Continuation.class)); // assert assertTrue(latch.await(500, TimeUnit.MILLISECONDS)); verify(storage, never()) .store(eq(id), isA(GCPastMetadata.class), eq(content), isA(Continuation.class)); } @Test public void testGetLeafSet() { LeafSet leafset = mock(LeafSet.class); when(node.getLeafSet()).thenReturn(leafset); // act LeafSet result = koalaGCPastImpl.getLeafSet(); // verify assertEquals(leafset, result); } @Test public void testReadObjectFromStorage() { // act koalaGCPastImpl.readObjectFromStorage(dummyId, continuation); // verify verify(storageManager).getObject(dummyId, continuation); } @Test public void testGetMessageContinuation() { // setup message = mock(PastMessage.class); // act Continuation actual = koalaGCPastImpl.getMessageResponseContinuation(message); // verify assertEquals(continuation, actual); } @Test public void testGetLocalNodeId() { // setup when(node.getId()).thenReturn(contentId); rice.p2p.commonapi.Id id = koalaGCPastImpl.getLocalNodeId(); assertEquals(contentId, id); } @Test public void testGenerateBackups() { PId pid = new PiId("0234567890123456789012345678901234567890", 1); // act SortedSet<String> backupIds = koalaGCPastImpl.generateBackupIds(16, NodeScope.GLOBAL, pid); String firstBackup = backupIds.first(); assertTrue(firstBackup.endsWith("1")); for (String id : backupIds) { assertEquals(firstBackup.substring(1), id.substring(1)); } } @Test public void testInsertGetsVersion() { // setup KoalaGCPastImpl localGcPastImpl = new KoalaGCPastImpl( node, storageManager, null, 0, instance, new KoalaPastPolicy(), 0, storageManager, KoalaNode.DEFAULT_NUMBER_OF_DHT_BACKUPS, koalaIdFactory, koalaPiEntityFactory) { @Override protected void sendRequest( rice.p2p.commonapi.Id id, PastMessage message, Continuation command) { sentId = id; sentMessage = message; callBackContinuation = command; } }; PastContent content = new KoalaPiEntityContent( Id.build("bob"), "the builder", false, "text", 0, NodeScope.AVAILABILITY_ZONE, "tv:series", 18); Continuation command = mock(Continuation.class); // act localGcPastImpl.insert(content, command); // assert assertEquals(sentId, Id.build("bob")); assertTrue(sentMessage instanceof InsertRequestMessage); assertEquals(18, ((InsertRequestMessage) sentMessage).getExpiration()); assertEquals(content, ((InsertRequestMessage) sentMessage).getContent()); assertEquals(command, callBackContinuation); } @Test public void testSetRequiredReadHandlesPercentage() { double d = 99.39; // act koalaGCPastImpl.setRequiredReadHandlesPercentage(d); // assert assertEquals(d, koalaGCPastImpl.getRequiredReadHandlesThreshold(), 0.0); } class NonPersistable extends PiEntityBase { public NonPersistable() {} @Override public String getType() { return "NonPersistable"; } @Override public long getVersion() { return 0; } @Override public void incrementVersion() {} @Override public void setVersion(long version) {} @Override public String getUrl() { return "url:NonPersistable"; } @Override public String getUriScheme() { return null; } } }
public Replayer( final Id id, final InetSocketAddress addr, InetSocketAddress bootaddress, final long startTime, final long randSeed) throws Exception { this.bootaddress = bootaddress; Environment env = ReplayLayer.generateEnvironment(id.toString(), startTime, randSeed, null); final Parameters params = env.getParameters(); params.setInt( "pastry_socket_scm_max_open_sockets", params.getInt( "org.mpisws.p2p.testing.transportlayer.replay_pastry_socket_scm_max_open_sockets")); params.setBoolean("pastry_socket_use_own_random", false); // env.getParameters().setInt("rice.environment.random_loglevel", Logger.FINER); logger = env.getLogManager().getLogger(Replayer.class, null); // env.getParameters().setInt("org.mpisws.p2p.transport.peerreview.replay_loglevel", // Logger.FINER); final Logger simLogger = env.getLogManager().getLogger(EventSimulator.class, null); final List<ReplayLayer<InetSocketAddress>> replayers = new ArrayList<ReplayLayer<InetSocketAddress>>(); SocketPastryNodeFactory factory = new SocketPastryNodeFactory( new NodeIdFactory() { public Id generateNodeId() { return id; } }, addr.getPort(), env) { // @Override // protected TransportLayer<MultiInetSocketAddress, ByteBuffer> // getPriorityTransportLayer(TransportLayer<MultiInetSocketAddress, ByteBuffer> trans, // LivenessProvider<MultiInetSocketAddress> liveness, // ProximityProvider<MultiInetSocketAddress> prox, PastryNode pn) { // // get rid of the priorityLayer // if // (params.getBoolean("org.mpisws.p2p.testing.transportlayer.replay.use_priority")) { // return super.getPriorityTransportLayer(trans, liveness, prox, pn); // } else { // return trans; // } // } @Override public NodeHandle getLocalHandle(PastryNode pn, NodeHandleFactory nhf) { SocketNodeHandle ret = (SocketNodeHandle) super.getLocalHandle(pn, nhf); logger.log(ret.toStringFull()); return ret; } @Override protected RandomSource cloneRandomSource( Environment rootEnvironment, Id nodeId, LogManager lman) { return rootEnvironment.getRandomSource(); } @Override protected TransportLayer<InetSocketAddress, ByteBuffer> getWireTransportLayer( InetSocketAddress innermostAddress, PastryNode pn) throws IOException { Serializer<InetSocketAddress> serializer = new InetSocketAddressSerializer(); HashProvider hashProv = new NullHashProvider(); SecureHistoryFactory shFactory = new SecureHistoryFactoryImpl(hashProv, pn.getEnvironment()); String logName = "0x" + id.toStringFull().substring(0, 6); SecureHistory hist = shFactory.open(logName, "r"); ReplayLayer<InetSocketAddress> replay = new ReplayLayer<InetSocketAddress>( serializer, hashProv, hist, addr, pn.getEnvironment()); replay.registerEvent(Replayer.this, EVT_BOOT, EVT_SUBSCRIBE, EVT_PUBLISH); replayers.add(replay); return replay; } }; // construct a node, passing the null boothandle on the first loop will // cause the node to start its own ring node = (PastryNode) factory.newNode(); app = new MyScribeClient(node); ReplaySM sim = (ReplaySM) env.getSelectorManager(); ReplayLayer<InetSocketAddress> replay = replayers.get(0); replay.makeProgress(); // get rid of INIT event sim.setVerifier(replay); sim.start(); // // this is an example of th enew way // //PastryNode node = factory.newNode(nidFactory.generateNodeId()); // //node.getBootstrapper().boot(Collections.singleton(bootaddress)); // // // the node may require sending several messages to fully boot into the ring // synchronized(node) { // while(!node.isReady() && !node.joinFailed()) { // // delay so we don't busy-wait // node.wait(500); // // // abort if can't join // if (node.joinFailed()) { // throw new IOException("Could not join the FreePastry ring. // Reason:"+node.joinFailedReason()); // } // } // } // // System.out.println("Finished creating new node: " + node); // // // construct a new scribe application // MyScribeClient app = new MyScribeClient(node); // // // for all the rest just subscribe // app.subscribe(); // now, print the tree // env.getTimeSource().sleep(5000); try { env.getTimeSource().sleep(55000); } catch (InterruptedException ie) { return; } env.destroy(); }
/** * checks to see if the previous node along the path was missing a RT entry if so, we send the * previous node the corresponding RT row to patch the hole * * @param msg the RouteMessage being routed * @param handle the next hop handle */ private void checkForRouteTableHole(RouteMessage msg, NodeHandle handle) { if (logger.level <= Logger.FINEST) logger.log("checkForRouteTableHole(" + msg + "," + handle + ")"); NodeHandle prevNode = msg.getPrevNode(); if (prevNode == null) { if (logger.level <= Logger.FINER) logger.log("No prevNode defined in " + msg); return; } if (prevNode.equals(getNodeHandle())) { if (logger.level <= Logger.FINER) logger.log("prevNode is me in " + msg); return; } // we don't want to send the repair if they just routed in the leafset LeafSet ls = thePastryNode.getLeafSet(); if (ls.overlaps()) return; // small network, don't bother if (ls.member(prevNode)) { // ok, it's in my leafset, so I'm in his, but make sure that it's not on the edge int index = ls.getIndex(prevNode); if ((index == ls.cwSize()) || (index == -ls.ccwSize())) { // it is the edge... continue with repair } else { return; } } Id prevId = prevNode.getNodeId(); Id key = msg.getTarget(); int diffDigit = prevId.indexOfMSDD(key, thePastryNode.getRoutingTable().baseBitLength()); // if we both have the same prefix (in other words the previous node didn't make a prefix of // progress) if (diffDigit >= 0 && diffDigit == thePastryNode .getNodeId() .indexOfMSDD(key, thePastryNode.getRoutingTable().baseBitLength())) { synchronized (lastTimeSentRouteTablePatch) { if (lastTimeSentRouteTablePatch.containsKey(prevNode)) { long lastTime = lastTimeSentRouteTablePatch.get(prevNode); if (lastTime > (thePastryNode.getEnvironment().getTimeSource().currentTimeMillis() - ROUTE_TABLE_PATCH_THROTTLE)) { if (logger.level <= Logger.INFO) logger.log( "not sending route table patch to " + prevNode + " because throttled. Last Time:" + lastTime); return; } } lastTimeSentRouteTablePatch.put( prevNode, thePastryNode.getEnvironment().getTimeSource().currentTimeMillis()); } // the previous node is missing a RT entry, send the row // for now, we send the entire row for simplicity RouteSet[] row = thePastryNode.getRoutingTable().getRow(diffDigit); BroadcastRouteRow brr = new BroadcastRouteRow(thePastryNode.getLocalHandle(), row); if (prevNode.isAlive()) { if (logger.level <= Logger.FINE) { logger.log( "Found hole in " + prevNode + "'s routing table. Sending " + brr.toStringFull()); } thePastryNode.send(prevNode, brr, null, options); } } }