@Test public void testWorkflow() { assertThat(idsToNames.getNextId()).isEqualTo(1); assertThat(idsToNames.get(1)).isEmpty(); assertThat(idsToNames.storeNewMapping(tableRef(0), 1)).isTrue(); assertThat(idsToNames.storeNewMapping(tableRef(1), 1)).isFalse(); assertThat(idsToNames.get(1)).contains(tableRef(0)); assertThat(idsToNames.getNextId()).isEqualTo(2); assertThat(idsToNames.storeNewMapping(tableRef(1), 2)).isTrue(); assertThat(idsToNames.getNextId()).isEqualTo(3); }
public SweepTableIndices(KeyValueService kvs) { this(new IdsToNames(kvs), new NamesToIds(kvs)); }
int getNextId() { RowColumnRangeIterator iterator = kvs.getRowsColumnRange( ID_TO_NAME, Collections.singleton(rowAsBytes), BatchColumnRangeSelection.create(null, null, 1), Long.MAX_VALUE).getOrDefault(rowAsBytes, emptyIterator()); if (!iterator.hasNext()) { return 1; } Map.Entry<Cell, Value> first = iterator.next(); RowResult<byte[]> rowResult = RowResult.of(first.getKey(), first.getValue().getContents()); SweepIdToNameRowResult deserializedRowResult = SweepIdToNameRowResult.of(rowResult); return Ints.checkedCast( Iterables.getOnlyElement(deserializedRowResult.getColumnValues()).getColumnName().getTableId()) + 1; }
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()); } } }
private TableReference getTableReferenceUncached(int tableId) { return idToNames.get(tableId) .orElseThrow(() -> new NoSuchElementException("Id " + tableId + " does not exist")); }
@Test public void testConcurrentCreationOfDifferentTable() { idsToNames.storeNewMapping(table(2), 1); assertThat(tableIndices.getTableId(table(1))).isEqualTo(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()); } } }
boolean storeNewMapping(TableReference table, int id) { SweepIdToNameColumn column = SweepIdToNameColumn.of(id); SweepIdToNameColumnValue value = SweepIdToNameColumnValue.of(column, table.getQualifiedName()); Cell cell = Cell.create(rowAsBytes, value.persistColumnName()); CheckAndSetRequest request = CheckAndSetRequest.newCell(ID_TO_NAME, cell, value.persistValue()); try { kvs.checkAndSet(request); return true; } catch (CheckAndSetException e) { return get(id).get().equals(table); } }
@Test public void testConcurrentCreationOfMultipleTables() { namesToIds.storeAsPending(table(1), 1); idsToNames.storeNewMapping(table(2), 1); assertThat(tableIndices.getTableId(table(1))).isEqualTo(2); }
private TableReference getTableReferenceUncached(int tableId) { return idToNames.get(tableId) .orElseThrow(() -> new NoSuchElementException("Id " + tableId + " does not exist")); }
public SweepTableIndices(KeyValueService kvs) { this(new IdsToNames(kvs), new NamesToIds(kvs)); }
int getNextId() { RowColumnRangeIterator iterator = kvs.getRowsColumnRange( ID_TO_NAME, Collections.singleton(rowAsBytes), BatchColumnRangeSelection.create(null, null, 1), Long.MAX_VALUE).getOrDefault(rowAsBytes, emptyIterator()); if (!iterator.hasNext()) { return 1; } Map.Entry<Cell, Value> first = iterator.next(); RowResult<byte[]> rowResult = RowResult.of(first.getKey(), first.getValue().getContents()); SweepIdToNameRowResult deserializedRowResult = SweepIdToNameRowResult.of(rowResult); return Ints.checkedCast( Iterables.getOnlyElement(deserializedRowResult.getColumnValues()).getColumnName().getTableId()) + 1; }
boolean storeNewMapping(TableReference table, int id) { SweepIdToNameColumn column = SweepIdToNameColumn.of(id); SweepIdToNameColumnValue value = SweepIdToNameColumnValue.of(column, table.getQualifiedName()); Cell cell = Cell.create(rowAsBytes, value.persistColumnName()); CheckAndSetRequest request = CheckAndSetRequest.newCell(ID_TO_NAME, cell, value.persistValue()); try { kvs.checkAndSet(request); return true; } catch (CheckAndSetException e) { return get(id).get().equals(table); } }