Skip to content
Open
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
Comment thread
henrib marked this conversation as resolved.
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.iceberg.hive;

import org.apache.hadoop.hive.metastore.IMetaStoreClient;
import org.apache.hadoop.hive.metastore.api.GetProjectionsSpec;
import org.apache.hadoop.hive.metastore.api.NoSuchObjectException;
import org.apache.hadoop.hive.metastore.api.Table;
import org.apache.hadoop.hive.metastore.client.builder.GetTableProjectionsSpecBuilder;
import org.apache.iceberg.BaseMetastoreTableOperations;
import org.apache.iceberg.ClientPool;
import org.apache.iceberg.MetadataTableType;
import org.apache.iceberg.catalog.TableIdentifier;
import org.apache.iceberg.exceptions.NoSuchTableException;
import org.apache.thrift.TException;

import java.util.Collections;
import java.util.List;

/**
* Fetches the location of a given metadata table.
* <p>Since the location mutates with each transaction, this allows determining if a cached version of the
* table is the latest known in the HMS database.</p>
*/
public class MetadataLocator {
private static final org.slf4j.Logger LOGGER = org.slf4j.LoggerFactory.getLogger(MetadataLocator.class);
private static final GetProjectionsSpec PARAM_SPEC = new GetTableProjectionsSpecBuilder()
.includeParameters() // only fetches table.parameters
.build();
private final HiveCatalog catalog;

public MetadataLocator(HiveCatalog catalog) {
this.catalog = catalog;
}

public HiveCatalog getCatalog() {
return catalog;
}

/**
* Returns the location of the metadata table identified by the given identifier, or null if the table is
* not a metadata table.
* <p>This uses the Thrift API to fetch the table parameters, which is more efficient than fetching the entire table object.</p>

Check warning on line 59 in standalone-metastore/metastore-rest-catalog/src/main/java/org/apache/iceberg/hive/MetadataLocator.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Line is longer than 120 characters (found 130).

See more on https://sonarcloud.io/project/issues?id=apache_hive&issues=AZ2c3HhvLdirLWE7GIty&open=AZ2c3HhvLdirLWE7GIty&pullRequest=6441
* @param identifier the identifier of the metadata table to fetch the location for
* @return the location of the metadata table, or null if the table does not exist or is not a metadata table
* @throws NoSuchTableException if the table does not exist
*/
public String getLocation(TableIdentifier identifier) {
final ClientPool<IMetaStoreClient, TException> clients = catalog.clientPool();

Check failure on line 65 in standalone-metastore/metastore-rest-catalog/src/main/java/org/apache/iceberg/hive/MetadataLocator.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this usage of "clientPool", it is annotated with @VisibleForTesting and should not be accessed from production code.

See more on https://sonarcloud.io/project/issues?id=apache_hive&issues=AZ2c3HhvLdirLWE7GItu&open=AZ2c3HhvLdirLWE7GItu&pullRequest=6441
final String catName = catalog.name();
final TableIdentifier baseTableIdentifier;
if (!catalog.isValidIdentifier(identifier)) {
if (!isValidMetadataIdentifier(identifier)) {
return null;
} else {
baseTableIdentifier = TableIdentifier.of(identifier.namespace().levels());
}
} else {
baseTableIdentifier = identifier;
}
String database = baseTableIdentifier.namespace().level(0);
String tableName = baseTableIdentifier.name();
try {
List<Table> tables = clients.run(
client -> client.getTables(catName, database, Collections.singletonList(tableName), PARAM_SPEC)
);
return tables == null || tables.isEmpty()
? null
: tables.getFirst().getParameters().get(BaseMetastoreTableOperations.METADATA_LOCATION_PROP);
Comment thread
henrib marked this conversation as resolved.
} catch (NoSuchTableException e) {

Check warning on line 86 in standalone-metastore/metastore-rest-catalog/src/main/java/org/apache/iceberg/hive/MetadataLocator.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Either log this exception and handle it, or rethrow it with some contextual information.

See more on https://sonarcloud.io/project/issues?id=apache_hive&issues=AZ3p3MbRDB_MdPLc16hd&open=AZ3p3MbRDB_MdPLc16hd&pullRequest=6441
LOGGER.debug("Table {} not found: {}", baseTableIdentifier, e.getMessage());
throw e;
} catch (NoSuchObjectException e) {
throw new NoSuchTableException("Table %s not found: %s", baseTableIdentifier, e.getMessage());
} catch (TException e) {
LOGGER.info("Table {} parameters fetch failed: {}", baseTableIdentifier, e.getMessage());
throw new RuntimeException("Failed to fetch table parameters for " + baseTableIdentifier, e);

Check warning on line 93 in standalone-metastore/metastore-rest-catalog/src/main/java/org/apache/iceberg/hive/MetadataLocator.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace generic exceptions with specific library exceptions or a custom exception.

See more on https://sonarcloud.io/project/issues?id=apache_hive&issues=AZ3p3MbRDB_MdPLc16hb&open=AZ3p3MbRDB_MdPLc16hb&pullRequest=6441
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("Interrupted while fetching table parameters for " + baseTableIdentifier, e);

Check warning on line 96 in standalone-metastore/metastore-rest-catalog/src/main/java/org/apache/iceberg/hive/MetadataLocator.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace generic exceptions with specific library exceptions or a custom exception.

See more on https://sonarcloud.io/project/issues?id=apache_hive&issues=AZ3p3MbRDB_MdPLc16hc&open=AZ3p3MbRDB_MdPLc16hc&pullRequest=6441
}
}

private boolean isValidMetadataIdentifier(TableIdentifier identifier) {
return MetadataTableType.from(identifier.name()) != null
&& catalog.isValidIdentifier(TableIdentifier.of(identifier.namespace().levels()));
}
}
Loading
Loading