/** * Creates a new {@link PreparedStatement} to release the current claim this node has on a token belonging to a * processor with given {@code processorName} and {@code segment}. * * @param connection the connection that should be used to create a {@link PreparedStatement} * @param processorName the name of the processor for which to release this node's claim * @param segment the segment of the processor for which to release this node's claim * @return a {@link PreparedStatement} that will release the claim this node has on the token entry * * @throws SQLException if the statement to release a claim cannot be created */ protected PreparedStatement releaseClaim(Connection connection, String processorName, int segment) throws SQLException { final String sql = "UPDATE " + schema.tokenTable() + " SET " + schema.ownerColum() + " = ?, " + schema.timestampColumn() + " = ? WHERE " + schema.processorNameColumn() + " = ? AND " + schema.segmentColumn() + " = ? AND " + schema.ownerColum() + " = ?"; PreparedStatement preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1, null); preparedStatement.setString(2, formatInstant(AbstractTokenEntry.clock.instant())); preparedStatement.setString(3, processorName); preparedStatement.setInt(4, segment); preparedStatement.setString(5, nodeId); return preparedStatement; }
/** * Convert given {@code resultSet} to an {@link AbstractTokenEntry}. The result set contains a single token entry. * * @param resultSet the result set of a prior select statement containing a single token entry * @return an token entry with data extracted from the result set * * @throws SQLException if the result set cannot be converted to an entry */ protected AbstractTokenEntry<?> readTokenEntry(ResultSet resultSet) throws SQLException { return new GenericTokenEntry<>(readSerializedData(resultSet, schema.tokenColumn()), resultSet.getString(schema.tokenTypeColumn()), resultSet.getString(schema.timestampColumn()), resultSet.getString(schema.ownerColum()), resultSet.getString(schema.processorNameColumn()), resultSet.getInt(schema.segmentColumn()), contentType); }
/** * Returns a {@link PreparedStatement} to select a token entry from the underlying storage. The {@link ResultSet} * that is returned when this statement is executed should be updatable. * * @param connection the connection to the underlying database * @param processorName the name of the processor to fetch the entry for * @param segment the segment of the processor to fetch the entry for * @return a {@link PreparedStatement} that will fetch an updatable token entry when executed * * @throws SQLException when an exception occurs while creating the prepared statement */ protected PreparedStatement selectForUpdate(Connection connection, String processorName, int segment) throws SQLException { final String sql = "SELECT " + String.join(", ", schema.processorNameColumn(), schema.segmentColumn(), schema.tokenColumn(), schema.tokenTypeColumn(), schema.timestampColumn(), schema.ownerColum()) + " FROM " + schema.tokenTable() + " WHERE " + schema.processorNameColumn() + " = ? AND " + schema.segmentColumn() + " = ? FOR UPDATE"; PreparedStatement preparedStatement = connection.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE); preparedStatement.setString(1, processorName); preparedStatement.setInt(2, segment); return preparedStatement; }
@Override public PreparedStatement createTable(Connection connection, TokenSchema schema) throws SQLException { String sql = "CREATE TABLE " + schema.tokenTable() + " (\n" + schema.processorNameColumn() + " VARCHAR(255) NOT NULL,\n" + schema.segmentColumn() + " INTEGER NOT NULL,\n" + schema.tokenColumn() + " " + " BLOB NULL,\n" + schema.tokenTypeColumn() + " VARCHAR(255) NULL,\n" + schema.timestampColumn() + " VARCHAR(255) NULL,\n" + schema.ownerColum() + " VARCHAR(255) NULL,\n" + "PRIMARY KEY (" + schema.processorNameColumn() + "," + schema.segmentColumn() + ")\n" + ")"; return connection.prepareStatement(sql); } }
@Override public PreparedStatement createTable(Connection connection, TokenSchema schema) throws SQLException { String sql = "CREATE TABLE IF NOT EXISTS " + schema.tokenTable() + " (\n" + schema.processorNameColumn() + " VARCHAR(255) NOT NULL,\n" + schema.segmentColumn() + " INTEGER NOT NULL,\n" + schema.tokenColumn() + " " + tokenType() + " NULL,\n" + schema.tokenTypeColumn() + " VARCHAR(255) NULL,\n" + schema.timestampColumn() + " VARCHAR(255) NULL,\n" + schema.ownerColum() + " VARCHAR(255) NULL,\n" + "PRIMARY KEY (" + schema.processorNameColumn() + "," + schema.segmentColumn() + ")\n" + ")"; return connection.prepareStatement(sql); }
/** * Tries to claim the given token {@code entry}. If the claim fails an {@link UnableToClaimTokenException} should be * thrown. Otherwise the given {@code resultSet} should be updated to reflect the claim. * * @param resultSet the updatable query result of an executed {@link PreparedStatement} * @param entry the entry extracted from the given result set * @return the claimed tracking token * * @throws UnableToClaimTokenException if the token cannot be claimed because another node currently owns the token * @throws SQLException when an exception occurs while claiming the token entry */ protected TrackingToken claimToken(ResultSet resultSet, AbstractTokenEntry<?> entry) throws SQLException { if (!entry.claim(nodeId, claimTimeout)) { throw new UnableToClaimTokenException( format("Unable to claim token '%s[%s]'. It is owned by '%s'", entry.getProcessorName(), entry.getSegment(), entry.getOwner())); } resultSet.updateString(schema.ownerColum(), entry.getOwner()); resultSet.updateString(schema.timestampColumn(), entry.timestampAsString()); resultSet.updateRow(); return entry.getToken(serializer); }
/** * Inserts a new token entry via the given updatable {@code resultSet}. * * @param resultSet the updatable result set to add the entry to * @param token the token of the entry to insert * @param processorName the name of the processor to insert a token for * @param segment the segment of the processor to insert a token for * @return the tracking token of the inserted entry * * @throws SQLException when an exception occurs while inserting a token entry */ protected TrackingToken insertTokenEntry(ResultSet resultSet, TrackingToken token, String processorName, int segment) throws SQLException { AbstractTokenEntry<?> entry = new GenericTokenEntry<>(token, serializer, contentType, processorName, segment); entry.claim(nodeId, claimTimeout); resultSet.moveToInsertRow(); resultSet.updateObject(schema.tokenColumn(), token == null ? null : entry.getSerializedToken().getData()); resultSet.updateString(schema.tokenTypeColumn(), token == null ? null : entry.getSerializedToken().getType().getName()); resultSet.updateString(schema.timestampColumn(), entry.timestampAsString()); resultSet.updateString(schema.ownerColum(), entry.getOwner()); resultSet.updateString(schema.processorNameColumn(), processorName); resultSet.updateInt(schema.segmentColumn(), segment); resultSet.insertRow(); return token; }
/** * Creates a new {@link PreparedStatement} to release the current claim this node has on a token belonging to a * processor with given {@code processorName} and {@code segment}. * * @param connection the connection that should be used to create a {@link PreparedStatement} * @param processorName the name of the processor for which to release this node's claim * @param segment the segment of the processor for which to release this node's claim * @return a {@link PreparedStatement} that will release the claim this node has on the token entry * @throws SQLException if the statement to release a claim cannot be created */ protected PreparedStatement releaseClaim(Connection connection, String processorName, int segment) throws SQLException { final String sql = "UPDATE " + schema.tokenTable() + " SET " + schema.ownerColum() + " = ?, " + schema.timestampColumn() + " = ? WHERE " + schema.processorNameColumn() + " = ? AND " + schema.segmentColumn() + " = ? AND " + schema.ownerColum() + " = ?"; PreparedStatement preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1, null); preparedStatement.setString(2, formatInstant(AbstractTokenEntry.clock.instant())); preparedStatement.setString(3, processorName); preparedStatement.setInt(4, segment); preparedStatement.setString(5, nodeId); return preparedStatement; }
/** * Creates a new {@link PreparedStatement} to release the current claim this node has on a token belonging to a * processor with given {@code processorName} and {@code segment}. * * @param connection the connection that should be used to create a {@link PreparedStatement} * @param processorName the name of the processor for which to release this node's claim * @param segment the segment of the processor for which to release this node's claim * @return a {@link PreparedStatement} that will release the claim this node has on the token entry * * @throws SQLException if the statement to release a claim cannot be created */ protected PreparedStatement releaseClaim(Connection connection, String processorName, int segment) throws SQLException { final String sql = "UPDATE " + schema.tokenTable() + " SET " + schema.ownerColum() + " = ?, " + schema.timestampColumn() + " = ? WHERE " + schema.processorNameColumn() + " = ? AND " + schema.segmentColumn() + " = ? AND " + schema.ownerColum() + " = ?"; PreparedStatement preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1, null); preparedStatement.setString(2, formatInstant(AbstractTokenEntry.clock.instant())); preparedStatement.setString(3, processorName); preparedStatement.setInt(4, segment); preparedStatement.setString(5, nodeId); return preparedStatement; }
/** * Convert given {@code resultSet} to an {@link AbstractTokenEntry}. The result set contains a single token entry. * * @param resultSet the result set of a prior select statement containing a single token entry * @return an token entry with data extracted from the result set * @throws SQLException if the result set cannot be converted to an entry */ protected AbstractTokenEntry<?> readTokenEntry(ResultSet resultSet) throws SQLException { return new GenericTokenEntry<>(readSerializedData(resultSet, schema.tokenColumn()), resultSet.getString(schema.tokenTypeColumn()), resultSet.getString(schema.timestampColumn()), resultSet.getString(schema.ownerColum()), resultSet.getString(schema.processorNameColumn()), resultSet.getInt(schema.segmentColumn()), contentType); }
/** * Convert given {@code resultSet} to an {@link AbstractTokenEntry}. The result set contains a single token entry. * * @param resultSet the result set of a prior select statement containing a single token entry * @return an token entry with data extracted from the result set * * @throws SQLException if the result set cannot be converted to an entry */ protected AbstractTokenEntry<?> readTokenEntry(ResultSet resultSet) throws SQLException { return new GenericTokenEntry<>(readSerializedData(resultSet, schema.tokenColumn()), resultSet.getString(schema.tokenTypeColumn()), resultSet.getString(schema.timestampColumn()), resultSet.getString(schema.ownerColum()), resultSet.getString(schema.processorNameColumn()), resultSet.getInt(schema.segmentColumn()), contentType); }
/** * Returns a {@link PreparedStatement} to select a token entry from the underlying storage. The {@link ResultSet} * that is returned when this statement is executed should be updatable. * * @param connection the connection to the underlying database * @param processorName the name of the processor to fetch the entry for * @param segment the segment of the processor to fetch the entry for * @return a {@link PreparedStatement} that will fetch an updatable token entry when executed * * @throws SQLException when an exception occurs while creating the prepared statement */ protected PreparedStatement selectForUpdate(Connection connection, String processorName, int segment) throws SQLException { final String sql = "SELECT " + String.join(", ", schema.processorNameColumn(), schema.segmentColumn(), schema.tokenColumn(), schema.tokenTypeColumn(), schema.timestampColumn(), schema.ownerColum()) + " FROM " + schema.tokenTable() + " WHERE " + schema.processorNameColumn() + " = ? AND " + schema.segmentColumn() + " = ? FOR UPDATE"; PreparedStatement preparedStatement = connection.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE); preparedStatement.setString(1, processorName); preparedStatement.setInt(2, segment); return preparedStatement; }
/** * Returns a {@link PreparedStatement} to select a token entry from the underlying storage. The {@link ResultSet} * that is returned when this statement is executed should be updatable. * * @param connection the connection to the underlying database * @param processorName the name of the processor to fetch the entry for * @param segment the segment of the processor to fetch the entry for * @return a {@link PreparedStatement} that will fetch an updatable token entry when executed * @throws SQLException when an exception occurs while creating the prepared statement */ protected PreparedStatement selectForUpdate(Connection connection, String processorName, int segment) throws SQLException { final String sql = "SELECT " + String.join(", ", schema.processorNameColumn(), schema.segmentColumn(), schema.tokenColumn(), schema.tokenTypeColumn(), schema.timestampColumn(), schema.ownerColum()) + " FROM " + schema.tokenTable() + " WHERE " + schema.processorNameColumn() + " = ? AND " + schema.segmentColumn() + " = ? FOR UPDATE"; PreparedStatement preparedStatement = connection.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE); preparedStatement.setString(1, processorName); preparedStatement.setInt(2, segment); return preparedStatement; }
@Override public PreparedStatement createTable(Connection connection, TokenSchema schema) throws SQLException { String sql = "CREATE TABLE " + schema.tokenTable() + " (\n" + schema.processorNameColumn() + " VARCHAR(255) NOT NULL,\n" + schema.segmentColumn() + " INTEGER NOT NULL,\n" + schema.tokenColumn() + " " + " BLOB NULL,\n" + schema.tokenTypeColumn() + " VARCHAR(255) NULL,\n" + schema.timestampColumn() + " VARCHAR(255) NULL,\n" + schema.ownerColum() + " VARCHAR(255) NULL,\n" + "PRIMARY KEY (" + schema.processorNameColumn() + "," + schema.segmentColumn() + ")\n" + ")"; return connection.prepareStatement(sql); } }
@Override public PreparedStatement createTable(Connection connection, TokenSchema schema) throws SQLException { String sql = "CREATE TABLE " + schema.tokenTable() + " (\n" + schema.processorNameColumn() + " VARCHAR(255) NOT NULL,\n" + schema.segmentColumn() + " INTEGER NOT NULL,\n" + schema.tokenColumn() + " " + " BLOB NULL,\n" + schema.tokenTypeColumn() + " VARCHAR(255) NULL,\n" + schema.timestampColumn() + " VARCHAR(255) NULL,\n" + schema.ownerColum() + " VARCHAR(255) NULL,\n" + "PRIMARY KEY (" + schema.processorNameColumn() + "," + schema.segmentColumn() + ")\n" + ")"; return connection.prepareStatement(sql); } }
@Override public PreparedStatement createTable(Connection connection, TokenSchema schema) throws SQLException { String sql = "CREATE TABLE IF NOT EXISTS " + schema.tokenTable() + " (\n" + schema.processorNameColumn() + " VARCHAR(255) NOT NULL,\n" + schema.segmentColumn() + " INTEGER NOT NULL,\n" + schema.tokenColumn() + " " + tokenType() + " NULL,\n" + schema.tokenTypeColumn() + " VARCHAR(255) NULL,\n" + schema.timestampColumn() + " VARCHAR(255) NULL,\n" + schema.ownerColum() + " VARCHAR(255) NULL,\n" + "PRIMARY KEY (" + schema.processorNameColumn() + "," + schema.segmentColumn() + ")\n" + ")"; return connection.prepareStatement(sql); }
@Override public PreparedStatement createTable(Connection connection, TokenSchema schema) throws SQLException { String sql = "CREATE TABLE IF NOT EXISTS " + schema.tokenTable() + " (\n" + schema.processorNameColumn() + " VARCHAR(255) NOT NULL,\n" + schema.segmentColumn() + " INTEGER NOT NULL,\n" + schema.tokenColumn() + " " + tokenType() + " NULL,\n" + schema.tokenTypeColumn() + " VARCHAR(255) NULL,\n" + schema.timestampColumn() + " VARCHAR(255) NULL,\n" + schema.ownerColum() + " VARCHAR(255) NULL,\n" + "PRIMARY KEY (" + schema.processorNameColumn() + "," + schema.segmentColumn() + ")\n" + ")"; return connection.prepareStatement(sql); }
/** * Tries to claim the given token {@code entry}. If the claim fails an {@link UnableToClaimTokenException} should be * thrown. Otherwise the given {@code resultSet} should be updated to reflect the claim. * * @param resultSet the updatable query result of an executed {@link PreparedStatement} * @param entry the entry extracted from the given result set * @return the claimed tracking token * @throws UnableToClaimTokenException if the token cannot be claimed because another node currently owns the token * @throws SQLException when an exception occurs while claiming the token entry */ protected TrackingToken claimToken(ResultSet resultSet, AbstractTokenEntry<?> entry) throws SQLException { if (!entry.claim(nodeId, claimTimeout)) { throw new UnableToClaimTokenException( format("Unable to claim token '%s[%s]'. It is owned by '%s'", entry.getProcessorName(), entry.getSegment(), entry.getOwner())); } resultSet.updateString(schema.ownerColum(), entry.getOwner()); resultSet.updateString(schema.timestampColumn(), entry.timestampAsString()); resultSet.updateRow(); return entry.getToken(serializer); }
/** * Tries to claim the given token {@code entry}. If the claim fails an {@link UnableToClaimTokenException} should be * thrown. Otherwise the given {@code resultSet} should be updated to reflect the claim. * * @param resultSet the updatable query result of an executed {@link PreparedStatement} * @param entry the entry extracted from the given result set * @return the claimed tracking token * * @throws UnableToClaimTokenException if the token cannot be claimed because another node currently owns the token * @throws SQLException when an exception occurs while claiming the token entry */ protected TrackingToken claimToken(ResultSet resultSet, AbstractTokenEntry<?> entry) throws SQLException { if (!entry.claim(nodeId, claimTimeout)) { throw new UnableToClaimTokenException( format("Unable to claim token '%s[%s]'. It is owned by '%s'", entry.getProcessorName(), entry.getSegment(), entry.getOwner())); } resultSet.updateString(schema.ownerColum(), entry.getOwner()); resultSet.updateString(schema.timestampColumn(), entry.timestampAsString()); resultSet.updateRow(); return entry.getToken(serializer); }
/** * Inserts a new token entry via the given updatable {@code resultSet}. * * @param resultSet the updatable result set to add the entry to * @param token the token of the entry to insert * @param processorName the name of the processor to insert a token for * @param segment the segment of the processor to insert a token for * @return the tracking token of the inserted entry * @throws SQLException when an exception occurs while inserting a token entry */ protected TrackingToken insertTokenEntry(ResultSet resultSet, TrackingToken token, String processorName, int segment) throws SQLException { AbstractTokenEntry<?> entry = new GenericTokenEntry<>(token, serializer, contentType, processorName, segment); entry.claim(nodeId, claimTimeout); resultSet.moveToInsertRow(); resultSet.updateObject(schema.tokenColumn(), token == null ? null : entry.getSerializedToken().getData()); resultSet.updateString(schema.tokenTypeColumn(), token == null ? null : entry.getSerializedToken().getType().getName()); resultSet.updateString(schema.timestampColumn(), entry.timestampAsString()); resultSet.updateString(schema.ownerColum(), entry.getOwner()); resultSet.updateString(schema.processorNameColumn(), processorName); resultSet.updateInt(schema.segmentColumn(), segment); resultSet.insertRow(); return token; }