PageRenderTime 260ms CodeModel.GetById 11ms RepoModel.GetById 1ms app.codeStats 0ms

/src/java/org/apache/cassandra/utils/NativeSSTableLoaderClient.java

https://github.com/beobal/cassandra
Java | 232 lines | 168 code | 36 blank | 28 comment | 15 complexity | 3244981f51d51b4e750c6a03670217ad MD5 | raw file
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. package org.apache.cassandra.utils;
  19. import java.nio.ByteBuffer;
  20. import java.net.InetSocketAddress;
  21. import java.net.UnknownHostException;
  22. import java.util.*;
  23. import com.datastax.driver.core.*;
  24. import org.apache.cassandra.locator.InetAddressAndPort;
  25. import org.apache.cassandra.schema.*;
  26. import org.apache.cassandra.schema.ColumnMetadata;
  27. import org.apache.cassandra.schema.ColumnMetadata.ClusteringOrder;
  28. import org.apache.cassandra.cql3.ColumnIdentifier;
  29. import org.apache.cassandra.db.marshal.*;
  30. import org.apache.cassandra.dht.*;
  31. import org.apache.cassandra.dht.Token;
  32. import org.apache.cassandra.dht.Token.TokenFactory;
  33. import org.apache.cassandra.io.sstable.SSTableLoader;
  34. import org.apache.cassandra.schema.TableMetadata;
  35. import org.apache.cassandra.schema.CQLTypeParser;
  36. import org.apache.cassandra.schema.SchemaKeyspace;
  37. import org.apache.cassandra.schema.Types;
  38. public class NativeSSTableLoaderClient extends SSTableLoader.Client
  39. {
  40. protected final Map<String, TableMetadataRef> tables;
  41. private final Collection<InetSocketAddress> hosts;
  42. private final int storagePort;
  43. private final AuthProvider authProvider;
  44. private final SSLOptions sslOptions;
  45. public NativeSSTableLoaderClient(Collection<InetSocketAddress> hosts, int storagePort, String username, String password, SSLOptions sslOptions)
  46. {
  47. this(hosts, storagePort, new PlainTextAuthProvider(username, password), sslOptions);
  48. }
  49. public NativeSSTableLoaderClient(Collection<InetSocketAddress> hosts, int storagePort, AuthProvider authProvider, SSLOptions sslOptions)
  50. {
  51. super();
  52. this.tables = new HashMap<>();
  53. this.hosts = hosts;
  54. this.authProvider = authProvider;
  55. this.sslOptions = sslOptions;
  56. this.storagePort = storagePort;
  57. }
  58. public void init(String keyspace)
  59. {
  60. Cluster.Builder builder = Cluster.builder().addContactPointsWithPorts(hosts).allowBetaProtocolVersion();
  61. if (sslOptions != null)
  62. builder.withSSL(sslOptions);
  63. if (authProvider != null)
  64. builder = builder.withAuthProvider(authProvider);
  65. try (Cluster cluster = builder.build(); Session session = cluster.connect())
  66. {
  67. Metadata metadata = cluster.getMetadata();
  68. Set<TokenRange> tokenRanges = metadata.getTokenRanges();
  69. IPartitioner partitioner = FBUtilities.newPartitioner(metadata.getPartitioner());
  70. TokenFactory tokenFactory = partitioner.getTokenFactory();
  71. for (TokenRange tokenRange : tokenRanges)
  72. {
  73. Set<Host> endpoints = metadata.getReplicas(Metadata.quote(keyspace), tokenRange);
  74. Range<Token> range = new Range<>(tokenFactory.fromString(tokenRange.getStart().getValue().toString()),
  75. tokenFactory.fromString(tokenRange.getEnd().getValue().toString()));
  76. for (Host endpoint : endpoints)
  77. {
  78. int broadcastPort = endpoint.getBroadcastSocketAddress().getPort();
  79. // use port from broadcast address if set.
  80. int portToUse = broadcastPort != 0 ? broadcastPort : storagePort;
  81. addRangeForEndpoint(range, InetAddressAndPort.getByNameOverrideDefaults(endpoint.getAddress().getHostAddress(), portToUse));
  82. }
  83. }
  84. Types types = fetchTypes(keyspace, session);
  85. tables.putAll(fetchTables(keyspace, session, partitioner, types));
  86. // We only need the TableMetadata for the views, so we only load that.
  87. tables.putAll(fetchViews(keyspace, session, partitioner, types));
  88. }
  89. catch (UnknownHostException e)
  90. {
  91. throw new RuntimeException(e);
  92. }
  93. }
  94. public TableMetadataRef getTableMetadata(String tableName)
  95. {
  96. return tables.get(tableName);
  97. }
  98. @Override
  99. public void setTableMetadata(TableMetadataRef cfm)
  100. {
  101. tables.put(cfm.name, cfm);
  102. }
  103. private static Types fetchTypes(String keyspace, Session session)
  104. {
  105. String query = String.format("SELECT * FROM %s.%s WHERE keyspace_name = ?", SchemaConstants.SCHEMA_KEYSPACE_NAME, SchemaKeyspace.TYPES);
  106. Types.RawBuilder types = Types.rawBuilder(keyspace);
  107. for (Row row : session.execute(query, keyspace))
  108. {
  109. String name = row.getString("type_name");
  110. List<String> fieldNames = row.getList("field_names", String.class);
  111. List<String> fieldTypes = row.getList("field_types", String.class);
  112. types.add(name, fieldNames, fieldTypes);
  113. }
  114. return types.build();
  115. }
  116. /*
  117. * The following is a slightly simplified but otherwise duplicated version of
  118. * SchemaKeyspace.createTableFromTableRowAndColumnRows().
  119. * It might be safer to have a simple wrapper of the driver ResultSet/Row implementing
  120. * UntypedResultSet/UntypedResultSet.Row and reuse the original method.
  121. *
  122. * Note: It is not safe for this class to use static methods from SchemaKeyspace (static final fields are ok)
  123. * as that triggers initialization of the class, which fails in client mode.
  124. */
  125. private static Map<String, TableMetadataRef> fetchTables(String keyspace, Session session, IPartitioner partitioner, Types types)
  126. {
  127. Map<String, TableMetadataRef> tables = new HashMap<>();
  128. String query = String.format("SELECT * FROM %s.%s WHERE keyspace_name = ?", SchemaConstants.SCHEMA_KEYSPACE_NAME, SchemaKeyspace.TABLES);
  129. for (Row row : session.execute(query, keyspace))
  130. {
  131. String name = row.getString("table_name");
  132. tables.put(name, createTableMetadata(keyspace, session, partitioner, false, row, name, types));
  133. }
  134. return tables;
  135. }
  136. private static Map<String, TableMetadataRef> fetchViews(String keyspace, Session session, IPartitioner partitioner, Types types)
  137. {
  138. Map<String, TableMetadataRef> tables = new HashMap<>();
  139. String query = String.format("SELECT * FROM %s.%s WHERE keyspace_name = ?", SchemaConstants.SCHEMA_KEYSPACE_NAME, SchemaKeyspace.VIEWS);
  140. for (Row row : session.execute(query, keyspace))
  141. {
  142. String name = row.getString("view_name");
  143. tables.put(name, createTableMetadata(keyspace, session, partitioner, true, row, name, types));
  144. }
  145. return tables;
  146. }
  147. private static TableMetadataRef createTableMetadata(String keyspace,
  148. Session session,
  149. IPartitioner partitioner,
  150. boolean isView,
  151. Row row,
  152. String name,
  153. Types types)
  154. {
  155. TableMetadata.Builder builder = TableMetadata.builder(keyspace, name, TableId.fromUUID(row.getUUID("id")))
  156. .partitioner(partitioner);
  157. if (!isView)
  158. builder.flags(TableMetadata.Flag.fromStringSet(row.getSet("flags", String.class)));
  159. String columnsQuery = String.format("SELECT * FROM %s.%s WHERE keyspace_name = ? AND table_name = ?",
  160. SchemaConstants.SCHEMA_KEYSPACE_NAME,
  161. SchemaKeyspace.COLUMNS);
  162. for (Row colRow : session.execute(columnsQuery, keyspace, name))
  163. builder.addColumn(createDefinitionFromRow(colRow, keyspace, name, types));
  164. String droppedColumnsQuery = String.format("SELECT * FROM %s.%s WHERE keyspace_name = ? AND table_name = ?",
  165. SchemaConstants.SCHEMA_KEYSPACE_NAME,
  166. SchemaKeyspace.DROPPED_COLUMNS);
  167. Map<ByteBuffer, DroppedColumn> droppedColumns = new HashMap<>();
  168. for (Row colRow : session.execute(droppedColumnsQuery, keyspace, name))
  169. {
  170. DroppedColumn droppedColumn = createDroppedColumnFromRow(colRow, keyspace, name);
  171. droppedColumns.put(droppedColumn.column.name.bytes, droppedColumn);
  172. }
  173. builder.droppedColumns(droppedColumns);
  174. return TableMetadataRef.forOfflineTools(builder.build());
  175. }
  176. private static ColumnMetadata createDefinitionFromRow(Row row, String keyspace, String table, Types types)
  177. {
  178. ClusteringOrder order = ClusteringOrder.valueOf(row.getString("clustering_order").toUpperCase());
  179. AbstractType<?> type = CQLTypeParser.parse(keyspace, row.getString("type"), types);
  180. if (order == ClusteringOrder.DESC)
  181. type = ReversedType.getInstance(type);
  182. ColumnIdentifier name = new ColumnIdentifier(row.getBytes("column_name_bytes"), row.getString("column_name"));
  183. int position = row.getInt("position");
  184. org.apache.cassandra.schema.ColumnMetadata.Kind kind = ColumnMetadata.Kind.valueOf(row.getString("kind").toUpperCase());
  185. return new ColumnMetadata(keyspace, table, name, type, position, kind);
  186. }
  187. private static DroppedColumn createDroppedColumnFromRow(Row row, String keyspace, String table)
  188. {
  189. String name = row.getString("column_name");
  190. AbstractType<?> type = CQLTypeParser.parse(keyspace, row.getString("type"), Types.none());
  191. ColumnMetadata.Kind kind = ColumnMetadata.Kind.valueOf(row.getString("kind").toUpperCase());
  192. ColumnMetadata column = new ColumnMetadata(keyspace, table, ColumnIdentifier.getInterned(name, true), type, ColumnMetadata.NO_POSITION, kind);
  193. long droppedTime = row.getTimestamp("dropped_time").getTime();
  194. return new DroppedColumn(column, droppedTime);
  195. }
  196. }