@Test @EnabledBreakpoints({ "makeSureNextTransactionIsFullyFetched", "readNextChunk", "waitTxCopyToStart", "finish" }) public void testTransactionsPulled() throws Exception { final HighlyAvailableGraphDatabase master = new HighlyAvailableGraphDatabase( TargetDirectory.forTest(TestClientThreadIsolation.class) .directory("master", true) .getAbsolutePath(), MapUtil.stringMap( HaConfig.CONFIG_KEY_COORDINATORS, zoo.getConnectionString(), HaConfig.CONFIG_KEY_SERVER_ID, "1")); final HighlyAvailableGraphDatabase slave1 = new HighlyAvailableGraphDatabase( TargetDirectory.forTest(TestClientThreadIsolation.class) .directory("slave1", true) .getAbsolutePath(), MapUtil.stringMap( HaConfig.CONFIG_KEY_COORDINATORS, zoo.getConnectionString(), HaConfig.CONFIG_KEY_SERVER_ID, "2", HaConfig.CONFIG_KEY_MAX_CONCURRENT_CHANNELS_PER_SLAVE, "2")); Transaction masterTx = master.beginTx(); master .createNode() .createRelationshipTo(master.createNode(), DynamicRelationshipType.withName("master")) .setProperty("largeArray", new int[20000]); masterTx.success(); masterTx.finish(); // Simple sanity check assertEquals(1, master.getBroker().getMaster().other().getMachineId()); assertEquals(1, slave1.getBroker().getMaster().other().getMachineId()); Thread thread1 = new Thread( new Runnable() { public void run() { // TODO Figure out how to do this // Master masterClient = slave1.getBroker().getMaster().first(); // Response<Integer> response = masterClient.createRelationshipType( // slave1.getSlaveContext( 10 ), "name" ); // slave1.receive( response ); // will be suspended here // response.close(); } }, "thread 1"); Thread thread2 = new Thread( new Runnable() { public void run() { /* * We have two operations since we need to make sure this test passes * before and after the proper channel releasing fix. The issue is * that we can't have only one channel since it will deadlock because * the txCopyingThread is suspended and won't release the channel * (after the fix). But the problem is that with two channels going * before the fix it won't break because the RR policy in * ResourcePool will give the unused channel to the new requesting thread, * thus not triggering the bug. The solution is to do two requests so * eventually get the released, half consumed channel. */ // TODO Figure out how to do this // try // { // waitTxCopyToStart(); // Master masterClient = slave1.getBroker().getMaster().first(); // SlaveContext ctx = slave1.getSlaveContext( 11 ); // Response<Integer> response = // masterClient.createRelationshipType( // ctx, "name2" ); // slave1.receive( response ); // response.close(); // // // This will break before the fix // response = masterClient.createRelationshipType( // slave1.getSlaveContext( 12 ), "name3" ); // slave1.receive( response ); // response.close(); // // /* // * If the above fails, this won't happen. Used to fail the // * test gracefully // */ // Transaction masterTx = master.beginTx(); // master.getReferenceNode().createRelationshipTo( // master.createNode(), // DynamicRelationshipType.withName( "test" ) ); // masterTx.success(); // masterTx.finish(); // } // finally // { // finish(); // } } }, "thread 2"); thread1.start(); thread2.start(); thread1.join(); thread2.join(); assertTrue( master .getReferenceNode() .getRelationships(DynamicRelationshipType.withName("test")) .iterator() .hasNext()); }
@AfterClass public static void stopZoo() { zoo.shutdown(); }