@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)); }
public SweepTableIndices(KeyValueService kvs) { this(new IdsToNames(kvs), new NamesToIds(kvs)); }
void moveToComplete(TableReference table, int id) { SweepNameToIdRow row = SweepNameToIdRow.of(table.getQualifiedName()); Cell cell = Cell.create(row.persistToBytes(), SweepNameToIdNamedColumn.ID.getShortName()); SweepTableIdentifier oldValue = SweepTableIdentifier.pending(id); SweepTableIdentifier newValue = SweepTableIdentifier.identified(id); CheckAndSetRequest request = CheckAndSetRequest.singleCell( NAME_TO_ID, cell, oldValue.persistToBytes(), newValue.persistToBytes()); try { kvs.checkAndSet(request); } catch (CheckAndSetException e) { SweepTableIdentifier actual = currentMapping(table).get(); checkState(newValue.equals(actual), "Unexpectedly we state changed from pending(id) to " + "not(identified(id)) after identifying id as the correct value"); } }
@Test public void testConcurrentCreationOfSameTable() { namesToIds.storeAsPending(table(1), 2); assertThat(tableIndices.getTableId(table(1))).isEqualTo(2); }
SweepTableIdentifier storeAsPending(TableReference table, int nextId) { SweepNameToIdRow row = SweepNameToIdRow.of(table.getQualifiedName()); Cell cell = Cell.create(row.persistToBytes(), SweepNameToIdNamedColumn.ID.getShortName()); SweepTableIdentifier newValue = SweepTableIdentifier.pending(nextId); CheckAndSetRequest cas = CheckAndSetRequest.newCell(NAME_TO_ID, cell, newValue.persistToBytes()); try { kvs.checkAndSet(cas); return newValue; } catch (CheckAndSetException e) { return currentMapping(table).get(); } }
@Test public void testConcurrentCreationOfMultipleTables() { namesToIds.storeAsPending(table(1), 1); idsToNames.storeNewMapping(table(2), 1); assertThat(tableIndices.getTableId(table(1))).isEqualTo(2); }
@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)); } }
void moveToComplete(TableReference table, int id) { SweepNameToIdRow row = SweepNameToIdRow.of(table.getQualifiedName()); Cell cell = Cell.create(row.persistToBytes(), SweepNameToIdNamedColumn.ID.getShortName()); SweepTableIdentifier oldValue = SweepTableIdentifier.pending(id); SweepTableIdentifier newValue = SweepTableIdentifier.identified(id); CheckAndSetRequest request = CheckAndSetRequest.singleCell( NAME_TO_ID, cell, oldValue.persistToBytes(), newValue.persistToBytes()); try { kvs.checkAndSet(request); } catch (CheckAndSetException e) { SweepTableIdentifier actual = currentMapping(table).get(); checkState(newValue.equals(actual), "Unexpectedly we state changed from pending(id) to " + "not(identified(id)) after identifying id as the correct value"); } }
public SweepTableIndices(KeyValueService kvs) { this(new IdsToNames(kvs), new NamesToIds(kvs)); }
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()); } } }
SweepTableIdentifier storeAsPending(TableReference table, int nextId) { SweepNameToIdRow row = SweepNameToIdRow.of(table.getQualifiedName()); Cell cell = Cell.create(row.persistToBytes(), SweepNameToIdNamedColumn.ID.getShortName()); SweepTableIdentifier newValue = SweepTableIdentifier.pending(nextId); CheckAndSetRequest cas = CheckAndSetRequest.newCell(NAME_TO_ID, cell, newValue.persistToBytes()); try { kvs.checkAndSet(cas); return newValue; } catch (CheckAndSetException e) { return currentMapping(table).get(); } }
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()); } } }