private int loadUncached(TableReference table) { while (true) { Optional<SweepTableIdentifier> identifier = namesToIds.currentMapping(table); if (identifier.isPresent() && !identifier.get().isPending()) { return identifier.get().identifier(); } log.info("Assigning table {} an identifier", LoggingArgs.tableRef(table)); // note - the second time through the loop this will fail, since on those iterations we're // doing our updates as CAS (at the bottom) not PUE, but it doubles as a get SweepTableIdentifier afterPendingPut = namesToIds.storeAsPending(table, idToNames.getNextId()); if (!afterPendingPut.isPending()) { log.info("Assigned table {} to id {}", LoggingArgs.tableRef(table), SafeArg.of("id", afterPendingPut.identifier())); return afterPendingPut.identifier(); } boolean assigmentWasSuccessful = idToNames.storeNewMapping(table, afterPendingPut.identifier()); if (assigmentWasSuccessful) { namesToIds.moveToComplete(table, afterPendingPut.identifier()); log.info("Assigned table {} to id {}", LoggingArgs.tableRef(table), SafeArg.of("id", afterPendingPut.identifier())); return afterPendingPut.identifier(); } // B namesToIds.storeAsPending(table, afterPendingPut.identifier(), idToNames.getNextId()); } } }
@Test public void testConflicts() { assertThat(namesToIds.storeAsPending(TABLE, 1)) .isEqualTo(SweepTableIdentifier.pending(1)); assertThat(namesToIds.storeAsPending(TABLE, 2)) .isEqualTo(SweepTableIdentifier.pending(1)); namesToIds.storeAsPending(TABLE, 2, 3); assertThat(namesToIds.currentMapping(TABLE)).contains(SweepTableIdentifier.pending(1)); assertThatExceptionOfType(IllegalStateException.class) .isThrownBy(() -> namesToIds.moveToComplete(TABLE, 2)) .withMessage("Unexpectedly we state changed from pending(id) to not(identified(id)) after " + "identifying id as the correct value"); assertThat(namesToIds.currentMapping(TABLE)).contains(SweepTableIdentifier.pending(1)); namesToIds.moveToComplete(TABLE, 1); assertThat(namesToIds.storeAsPending(TABLE, 1)).isEqualTo(SweepTableIdentifier.identified(1)); } }
@Test public void testWorkflow() { assertThat(namesToIds.storeAsPending(TABLE, 1)) .isEqualTo(SweepTableIdentifier.pending(1)); namesToIds.storeAsPending(TABLE, 1, 2); assertThat(namesToIds.currentMapping(TABLE)).contains(SweepTableIdentifier.pending(2)); namesToIds.moveToComplete(TABLE, 2); assertThat(namesToIds.currentMapping(TABLE)).contains(SweepTableIdentifier.identified(2)); }
private int loadUncached(TableReference table) { while (true) { Optional<SweepTableIdentifier> identifier = namesToIds.currentMapping(table); if (identifier.isPresent() && !identifier.get().isPending()) { return identifier.get().identifier(); } log.info("Assigning table {} an identifier", LoggingArgs.tableRef(table)); // note - the second time through the loop this will fail, since on those iterations we're // doing our updates as CAS (at the bottom) not PUE, but it doubles as a get SweepTableIdentifier afterPendingPut = namesToIds.storeAsPending(table, idToNames.getNextId()); if (!afterPendingPut.isPending()) { log.info("Assigned table {} to id {}", LoggingArgs.tableRef(table), SafeArg.of("id", afterPendingPut.identifier())); return afterPendingPut.identifier(); } boolean assigmentWasSuccessful = idToNames.storeNewMapping(table, afterPendingPut.identifier()); if (assigmentWasSuccessful) { namesToIds.moveToComplete(table, afterPendingPut.identifier()); log.info("Assigned table {} to id {}", LoggingArgs.tableRef(table), SafeArg.of("id", afterPendingPut.identifier())); return afterPendingPut.identifier(); } // B namesToIds.storeAsPending(table, afterPendingPut.identifier(), idToNames.getNextId()); } } }