/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.facebook.presto.raptor.metadata; import com.facebook.presto.raptor.util.UuidUtil.UuidArgumentFactory; import com.facebook.presto.raptor.util.UuidUtil.UuidMapperFactory; import org.skife.jdbi.v2.sqlobject.Bind; import org.skife.jdbi.v2.sqlobject.GetGeneratedKeys; import org.skife.jdbi.v2.sqlobject.SqlBatch; import org.skife.jdbi.v2.sqlobject.SqlQuery; import org.skife.jdbi.v2.sqlobject.SqlUpdate; import org.skife.jdbi.v2.sqlobject.customizers.Mapper; import org.skife.jdbi.v2.sqlobject.customizers.RegisterArgumentFactory; import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapperFactory; import java.sql.Timestamp; import java.util.List; import java.util.Set; import java.util.UUID; @RegisterArgumentFactory(UuidArgumentFactory.class) @RegisterMapperFactory(UuidMapperFactory.class) public interface ShardDao { int CLEANABLE_SHARDS_BATCH_SIZE = 1000; int CLEANUP_TRANSACTIONS_BATCH_SIZE = 10_000; @SqlUpdate("INSERT INTO nodes (node_identifier) VALUES (:nodeIdentifier)") @GetGeneratedKeys int insertNode(@Bind("nodeIdentifier") String nodeIdentifier); @SqlUpdate("INSERT INTO shard_nodes (shard_id, node_id)\n" + "VALUES ((SELECT shard_id FROM shards WHERE shard_uuid = :shardUuid), :nodeId)") void insertShardNode(@Bind("shardUuid") UUID shardUuid, @Bind("nodeId") int nodeId); @SqlUpdate("DELETE FROM shard_nodes\n" + "WHERE shard_id = (SELECT shard_id FROM shards WHERE shard_uuid = :shardUuid)\n" + " AND node_id = :nodeId") void deleteShardNode(@Bind("shardUuid") UUID shardUuid, @Bind("nodeId") int nodeId); @SqlQuery("SELECT node_id FROM nodes WHERE node_identifier = :nodeIdentifier") Integer getNodeId(@Bind("nodeIdentifier") String nodeIdentifier); @SqlQuery("SELECT node_identifier FROM nodes WHERE node_id = :nodeId") String getNodeIdentifier(@Bind("nodeId") int nodeId); @SqlQuery("SELECT node_id, node_identifier FROM nodes") @Mapper(RaptorNode.Mapper.class) List<RaptorNode> getNodes(); @SqlQuery("SELECT table_id, shard_id, shard_uuid, bucket_number, row_count, compressed_size, uncompressed_size\n" + "FROM (\n" + " SELECT s.*\n" + " FROM shards s\n" + " JOIN shard_nodes sn ON (s.shard_id = sn.shard_id)\n" + " JOIN nodes n ON (sn.node_id = n.node_id)\n" + " WHERE n.node_identifier = :nodeIdentifier\n" + " AND s.bucket_number IS NULL\n" + " AND (s.table_id = :tableId OR :tableId IS NULL)\n" + " UNION ALL\n" + " SELECT s.*\n" + " FROM shards s\n" + " JOIN tables t ON (s.table_id = t.table_id)\n" + " JOIN distributions d ON (t.distribution_id = d.distribution_id)\n" + " JOIN buckets b ON (\n" + " d.distribution_id = b.distribution_id AND\n" + " s.bucket_number = b.bucket_number)\n" + " JOIN nodes n ON (b.node_id = n.node_id)\n" + " WHERE n.node_identifier = :nodeIdentifier\n" + " AND (s.table_id = :tableId OR :tableId IS NULL)\n" + ") x") @Mapper(ShardMetadata.Mapper.class) Set<ShardMetadata> getNodeShards(@Bind("nodeIdentifier") String nodeIdentifier, @Bind("tableId") Long tableId); @SqlQuery("SELECT n.node_identifier, x.bytes\n" + "FROM (\n" + " SELECT node_id, sum(compressed_size) bytes\n" + " FROM (\n" + " SELECT sn.node_id, s.compressed_size\n" + " FROM shards s\n" + " JOIN shard_nodes sn ON (s.shard_id = sn.shard_id)\n" + " WHERE s.bucket_number IS NULL\n" + " UNION ALL\n" + " SELECT b.node_id, s.compressed_size\n" + " FROM shards s\n" + " JOIN tables t ON (s.table_id = t.table_id)\n" + " JOIN distributions d ON (t.distribution_id = d.distribution_id)\n" + " JOIN buckets b ON (\n" + " d.distribution_id = b.distribution_id AND\n" + " s.bucket_number = b.bucket_number)\n" + " ) x\n" + " GROUP BY node_id\n" + ") x\n" + "JOIN nodes n ON (x.node_id = n.node_id)") @Mapper(NodeSize.Mapper.class) Set<NodeSize> getNodeSizes(); @SqlUpdate("DELETE FROM shard_nodes WHERE shard_id IN (\n" + " SELECT shard_id\n" + " FROM shards\n" + " WHERE table_id = :tableId)") void dropShardNodes(@Bind("tableId") long tableId); @SqlUpdate("DELETE FROM shards WHERE table_id = :tableId") void dropShards(@Bind("tableId") long tableId); @SqlUpdate("INSERT INTO external_batches (external_batch_id, successful)\n" + "VALUES (:externalBatchId, TRUE)") void insertExternalBatch(@Bind("externalBatchId") String externalBatchId); @SqlQuery("SELECT count(*)\n" + "FROM external_batches\n" + "WHERE external_batch_id = :externalBatchId") boolean externalBatchExists(@Bind("externalBatchId") String externalBatchId); @SqlUpdate("INSERT INTO transactions (start_time) VALUES (CURRENT_TIMESTAMP)") @GetGeneratedKeys long insertTransaction(); @SqlUpdate("UPDATE transactions SET\n" + " successful = :successful\n" + ", end_time = CURRENT_TIMESTAMP\n" + "WHERE transaction_id = :transactionId\n" + " AND successful IS NULL") int finalizeTransaction( @Bind("transactionId") long transactionId, @Bind("successful") boolean successful); @SqlQuery("SELECT successful FROM transactions WHERE transaction_id = :transactionId") Boolean transactionSuccessful(@Bind("transactionId") long transactionId); @SqlUpdate("UPDATE transactions SET\n" + " successful = FALSE\n" + ", end_time = CURRENT_TIMESTAMP\n" + "WHERE successful IS NULL\n" + " AND start_time < :maxStartTime") void abortOldTransactions(@Bind("maxStartTime") Timestamp maxStartTime); @SqlUpdate("INSERT INTO created_shards (shard_uuid, transaction_id)\n" + "VALUES (:shardUuid, :transactionId)") void insertCreatedShard( @Bind("shardUuid") UUID shardUuid, @Bind("transactionId") long transactionId); @SqlUpdate("DELETE FROM created_shards WHERE transaction_id = :transactionId") void deleteCreatedShards(@Bind("transactionId") long transactionId); @SqlBatch("DELETE FROM created_shards WHERE shard_uuid = :shardUuid") void deleteCreatedShards(@Bind("shardUuid") Iterable<UUID> shardUuids); void insertDeletedShards(Iterable<UUID> shardUuids); @SqlUpdate("INSERT INTO deleted_shards (shard_uuid, delete_time)\n" + "SELECT shard_uuid, CURRENT_TIMESTAMP\n" + "FROM shards\n" + "WHERE table_id = :tableId") void insertDeletedShards(@Bind("tableId") long tableId); @SqlQuery("SELECT s.shard_uuid\n" + "FROM created_shards s\n" + "JOIN transactions t ON (s.transaction_id = t.transaction_id)\n" + "WHERE NOT t.successful\n" + "LIMIT 10000") List<UUID> getOldCreatedShardsBatch(); @SqlQuery("SELECT shard_uuid\n" + "FROM deleted_shards\n" + "WHERE delete_time < :maxDeleteTime\n" + "LIMIT " + CLEANABLE_SHARDS_BATCH_SIZE) Set<UUID> getCleanableShardsBatch(@Bind("maxDeleteTime") Timestamp maxDeleteTime); @SqlBatch("DELETE FROM deleted_shards WHERE shard_uuid = :shardUuid") void deleteCleanedShards(@Bind("shardUuid") Iterable<UUID> shardUuids); @SqlBatch("INSERT INTO buckets (distribution_id, bucket_number, node_id)\n" + "VALUES (:distributionId, :bucketNumber, :nodeId)\n") void insertBuckets( @Bind("distributionId") long distributionId, @Bind("bucketNumber") List<Integer> bucketNumbers, @Bind("nodeId") List<Integer> nodeIds); @SqlQuery("SELECT b.bucket_number, n.node_identifier\n" + "FROM buckets b\n" + "JOIN nodes n ON (b.node_id = n.node_id)\n" + "WHERE b.distribution_id = :distributionId\n" + "ORDER BY b.bucket_number") @Mapper(BucketNode.Mapper.class) List<BucketNode> getBucketNodes(@Bind("distributionId") long distributionId); @SqlQuery("SELECT distribution_id, distribution_name, column_types, bucket_count\n" + "FROM distributions\n" + "WHERE distribution_id IN (SELECT distribution_id FROM tables)") List<Distribution> listActiveDistributions(); @SqlQuery("SELECT SUM(compressed_size)\n" + "FROM tables\n" + "WHERE distribution_id = :distributionId") long getDistributionSizeBytes(@Bind("distributionId") long distributionId); @SqlUpdate("UPDATE buckets SET node_id = :nodeId\n" + "WHERE distribution_id = :distributionId\n" + " AND bucket_number = :bucketNumber") void updateBucketNode( @Bind("distributionId") long distributionId, @Bind("bucketNumber") int bucketNumber, @Bind("nodeId") int nodeId); int deleteOldCompletedTransactions(@Bind("maxEndTime") Timestamp maxEndTime); }