You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hive.apache.org by ga...@apache.org on 2017/11/03 23:26:44 UTC
[03/12] hive git commit: HIVE-17980 Moved HiveMetaStoreClient plus a
few remaining classes.
http://git-wip-us.apache.org/repos/asf/hive/blob/20c86d1f/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/messaging/EventUtils.java
----------------------------------------------------------------------
diff --git a/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/messaging/EventUtils.java b/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/messaging/EventUtils.java
new file mode 100644
index 0000000..7d8c1d4
--- /dev/null
+++ b/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/messaging/EventUtils.java
@@ -0,0 +1,202 @@
+/*
+ * 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.hadoop.hive.metastore.messaging;
+
+import org.apache.hadoop.hive.metastore.IMetaStoreClient;
+import org.apache.hadoop.hive.metastore.api.NotificationEvent;
+import org.apache.hadoop.hive.metastore.api.NotificationEventsCountRequest;
+import org.apache.hadoop.hive.metastore.conf.MetastoreConf;
+import org.apache.hadoop.hive.metastore.messaging.event.filters.DatabaseAndTableFilter;
+import org.apache.thrift.TException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public class EventUtils {
+
+ public interface NotificationFetcher {
+ int getBatchSize() throws IOException;
+ long getCurrentNotificationEventId() throws IOException;
+ long getDbNotificationEventsCount(long fromEventId, String dbName) throws IOException;
+ List<NotificationEvent> getNextNotificationEvents(
+ long pos, IMetaStoreClient.NotificationFilter filter) throws IOException;
+ }
+
+ // MetaStoreClient-based impl of NotificationFetcher
+ public static class MSClientNotificationFetcher implements NotificationFetcher{
+
+ private IMetaStoreClient msc = null;
+ private Integer batchSize = null;
+
+ public MSClientNotificationFetcher(IMetaStoreClient msc){
+ this.msc = msc;
+ }
+
+ @Override
+ public int getBatchSize() throws IOException {
+ if (batchSize == null){
+ try {
+ batchSize = Integer.parseInt(
+ msc.getConfigValue(MetastoreConf.ConfVars.BATCH_RETRIEVE_MAX.toString(), "50"));
+ // TODO: we're asking the metastore what its configuration for this var is - we may
+ // want to revisit to pull from client side instead. The reason I have it this way
+ // is because the metastore is more likely to have a reasonable config for this than
+ // an arbitrary client.
+ } catch (TException e) {
+ throw new IOException(e);
+ }
+ }
+ return batchSize;
+ }
+
+ @Override
+ public long getCurrentNotificationEventId() throws IOException {
+ try {
+ return msc.getCurrentNotificationEventId().getEventId();
+ } catch (TException e) {
+ throw new IOException(e);
+ }
+ }
+
+ @Override
+ public long getDbNotificationEventsCount(long fromEventId, String dbName) throws IOException {
+ try {
+ NotificationEventsCountRequest rqst
+ = new NotificationEventsCountRequest(fromEventId, dbName);
+ return msc.getNotificationEventsCount(rqst).getEventsCount();
+ } catch (TException e) {
+ throw new IOException(e);
+ }
+ }
+
+ @Override
+ public List<NotificationEvent> getNextNotificationEvents(
+ long pos, IMetaStoreClient.NotificationFilter filter) throws IOException {
+ try {
+ return msc.getNextNotification(pos,getBatchSize(), filter).getEvents();
+ } catch (TException e) {
+ throw new IOException(e);
+ }
+ }
+ }
+
+ public static class NotificationEventIterator implements Iterator<NotificationEvent> {
+
+ private NotificationFetcher nfetcher;
+ private IMetaStoreClient.NotificationFilter filter;
+ private int maxEvents;
+
+ private Iterator<NotificationEvent> batchIter = null;
+ private List<NotificationEvent> batch = null;
+ private long pos;
+ private long maxPos;
+ private int eventCount;
+
+ public NotificationEventIterator(
+ NotificationFetcher nfetcher, long eventFrom, int maxEvents,
+ String dbName, String tableName) throws IOException {
+ init(nfetcher, eventFrom, maxEvents, new DatabaseAndTableFilter(dbName, tableName));
+ // using init(..) instead of this(..) because the EventUtils.getDbTblNotificationFilter
+ // is an operation that needs to run before delegating to the other ctor, and this messes up chaining
+ // ctors
+ }
+
+ public NotificationEventIterator(
+ NotificationFetcher nfetcher, long eventFrom, int maxEvents,
+ IMetaStoreClient.NotificationFilter filter) throws IOException {
+ init(nfetcher,eventFrom,maxEvents,filter);
+ }
+
+ private void init(
+ NotificationFetcher nfetcher, long eventFrom, int maxEvents,
+ IMetaStoreClient.NotificationFilter filter) throws IOException {
+ this.nfetcher = nfetcher;
+ this.filter = filter;
+ this.pos = eventFrom;
+ if (maxEvents < 1){
+ // 0 or -1 implies fetch everything
+ this.maxEvents = Integer.MAX_VALUE;
+ } else {
+ this.maxEvents = maxEvents;
+ }
+
+ this.eventCount = 0;
+ this.maxPos = nfetcher.getCurrentNotificationEventId();
+ }
+
+ private void fetchNextBatch() throws IOException {
+ batch = nfetcher.getNextNotificationEvents(pos, filter);
+ int batchSize = nfetcher.getBatchSize();
+ while ( ((batch == null) || (batch.isEmpty())) && (pos < maxPos) ){
+ // no valid events this batch, but we're still not done processing events
+ pos += batchSize;
+ batch = nfetcher.getNextNotificationEvents(pos,filter);
+ }
+
+ if (batch == null){
+ batch = new ArrayList<>();
+ // instantiate empty list so that we don't error out on iterator fetching.
+ // If we're here, then the next check of pos will show our caller that
+ // that we've exhausted our event supply
+ }
+ batchIter = batch.iterator();
+ }
+
+ @Override
+ public boolean hasNext() {
+ if (eventCount >= maxEvents){
+ // If we've already satisfied the number of events we were supposed to deliver, we end it.
+ return false;
+ }
+ if ((batchIter != null) && (batchIter.hasNext())){
+ // If we have a valid batchIter and it has more elements, return them.
+ return true;
+ }
+ // If we're here, we want more events, and either batchIter is null, or batchIter
+ // has reached the end of the current batch. Let's fetch the next batch.
+ try {
+ fetchNextBatch();
+ } catch (IOException e) {
+ // Regrettable that we have to wrap the IOException into a RuntimeException,
+ // but throwing the exception is the appropriate result here, and hasNext()
+ // signature will only allow RuntimeExceptions. Iterator.hasNext() really
+ // should have allowed IOExceptions
+ throw new RuntimeException(e);
+ }
+ // New batch has been fetched. If it's not empty, we have more elements to process.
+ return !batch.isEmpty();
+ }
+
+ @Override
+ public NotificationEvent next() {
+ eventCount++;
+ NotificationEvent ev = batchIter.next();
+ pos = ev.getEventId();
+ return ev;
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException("remove() not supported on NotificationEventIterator");
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/hive/blob/20c86d1f/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/messaging/event/filters/AndFilter.java
----------------------------------------------------------------------
diff --git a/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/messaging/event/filters/AndFilter.java b/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/messaging/event/filters/AndFilter.java
new file mode 100644
index 0000000..454d2cc
--- /dev/null
+++ b/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/messaging/event/filters/AndFilter.java
@@ -0,0 +1,39 @@
+/*
+ * 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.hadoop.hive.metastore.messaging.event.filters;
+
+import org.apache.hadoop.hive.metastore.IMetaStoreClient;
+import org.apache.hadoop.hive.metastore.api.NotificationEvent;
+
+public class AndFilter implements IMetaStoreClient.NotificationFilter {
+ final IMetaStoreClient.NotificationFilter[] filters;
+
+ public AndFilter(final IMetaStoreClient.NotificationFilter... filters) {
+ this.filters = filters;
+ }
+
+ @Override
+ public boolean accept(final NotificationEvent event) {
+ for (IMetaStoreClient.NotificationFilter filter : filters) {
+ if (!filter.accept(event)) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
http://git-wip-us.apache.org/repos/asf/hive/blob/20c86d1f/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/messaging/event/filters/BasicFilter.java
----------------------------------------------------------------------
diff --git a/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/messaging/event/filters/BasicFilter.java b/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/messaging/event/filters/BasicFilter.java
new file mode 100644
index 0000000..84302d6
--- /dev/null
+++ b/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/messaging/event/filters/BasicFilter.java
@@ -0,0 +1,33 @@
+/*
+ * 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.hadoop.hive.metastore.messaging.event.filters;
+
+import org.apache.hadoop.hive.metastore.IMetaStoreClient.NotificationFilter;
+import org.apache.hadoop.hive.metastore.api.NotificationEvent;
+
+public abstract class BasicFilter implements NotificationFilter {
+ @Override
+ public boolean accept(final NotificationEvent event) {
+ if (event == null) {
+ return false; // get rid of trivial case first, so that we can safely assume non-null
+ }
+ return shouldAccept(event);
+ }
+
+ abstract boolean shouldAccept(final NotificationEvent event);
+}
http://git-wip-us.apache.org/repos/asf/hive/blob/20c86d1f/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/messaging/event/filters/DatabaseAndTableFilter.java
----------------------------------------------------------------------
diff --git a/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/messaging/event/filters/DatabaseAndTableFilter.java b/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/messaging/event/filters/DatabaseAndTableFilter.java
new file mode 100644
index 0000000..0852abd
--- /dev/null
+++ b/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/messaging/event/filters/DatabaseAndTableFilter.java
@@ -0,0 +1,52 @@
+/*
+ * 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.hadoop.hive.metastore.messaging.event.filters;
+
+import org.apache.hadoop.hive.metastore.api.NotificationEvent;
+
+/**
+ * Utility function that constructs a notification filter to match a given db name and/or table name.
+ * If dbName == null, fetches all warehouse events.
+ * If dnName != null, but tableName == null, fetches all events for the db
+ * If dbName != null && tableName != null, fetches all events for the specified table
+ */
+public class DatabaseAndTableFilter extends BasicFilter {
+ private final String databaseName, tableName;
+
+ public DatabaseAndTableFilter(final String databaseName, final String tableName) {
+ this.databaseName = databaseName;
+ this.tableName = tableName;
+ }
+
+ @Override
+ boolean shouldAccept(final NotificationEvent event) {
+ if (databaseName == null) {
+ return true; // if our dbName is null, we're interested in all wh events
+ }
+ if (databaseName.equalsIgnoreCase(event.getDbName())) {
+ if ((tableName == null)
+ // if our dbName is equal, but tableName is blank, we're interested in this db-level event
+ || (tableName.equalsIgnoreCase(event.getTableName()))
+ // table level event that matches us
+ ) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
http://git-wip-us.apache.org/repos/asf/hive/blob/20c86d1f/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/messaging/event/filters/EventBoundaryFilter.java
----------------------------------------------------------------------
diff --git a/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/messaging/event/filters/EventBoundaryFilter.java b/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/messaging/event/filters/EventBoundaryFilter.java
new file mode 100644
index 0000000..988874d
--- /dev/null
+++ b/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/messaging/event/filters/EventBoundaryFilter.java
@@ -0,0 +1,34 @@
+/*
+ * 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.hadoop.hive.metastore.messaging.event.filters;
+
+import org.apache.hadoop.hive.metastore.api.NotificationEvent;
+
+public class EventBoundaryFilter extends BasicFilter {
+ private final long eventFrom, eventTo;
+
+ public EventBoundaryFilter(final long eventFrom, final long eventTo) {
+ this.eventFrom = eventFrom;
+ this.eventTo = eventTo;
+ }
+
+ @Override
+ boolean shouldAccept(final NotificationEvent event) {
+ return eventFrom <= event.getEventId() && event.getEventId() <= eventTo;
+ }
+}
http://git-wip-us.apache.org/repos/asf/hive/blob/20c86d1f/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/messaging/event/filters/MessageFormatFilter.java
----------------------------------------------------------------------
diff --git a/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/messaging/event/filters/MessageFormatFilter.java b/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/messaging/event/filters/MessageFormatFilter.java
new file mode 100644
index 0000000..b0ce3b9
--- /dev/null
+++ b/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/messaging/event/filters/MessageFormatFilter.java
@@ -0,0 +1,36 @@
+/*
+ * 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.hadoop.hive.metastore.messaging.event.filters;
+
+import org.apache.hadoop.hive.metastore.api.NotificationEvent;
+
+public class MessageFormatFilter extends BasicFilter {
+ private final String format;
+
+ public MessageFormatFilter(String format) {
+ this.format = format;
+ }
+
+ @Override
+ boolean shouldAccept(final NotificationEvent event) {
+ if (format == null) {
+ return true; // let's say that passing null in will not do any filtering.
+ }
+ return format.equalsIgnoreCase(event.getMessageFormat());
+ }
+}
http://git-wip-us.apache.org/repos/asf/hive/blob/20c86d1f/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/tools/HiveMetaTool.java
----------------------------------------------------------------------
diff --git a/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/tools/HiveMetaTool.java b/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/tools/HiveMetaTool.java
new file mode 100644
index 0000000..f4eacd5
--- /dev/null
+++ b/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/tools/HiveMetaTool.java
@@ -0,0 +1,484 @@
+/*
+ * 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.hadoop.hive.metastore.tools;
+
+import java.net.URI;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.GnuParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.OptionBuilder;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hive.metastore.conf.MetastoreConf;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.hive.metastore.ObjectStore;
+
+/**
+ * This class provides Hive admins a tool to
+ * - execute JDOQL against the metastore using DataNucleus
+ * - perform HA name node upgrade
+ */
+
+public class HiveMetaTool {
+
+ private static final Logger LOG = LoggerFactory.getLogger(HiveMetaTool.class.getName());
+ private final Options cmdLineOptions = new Options();
+ private ObjectStore objStore;
+ private boolean isObjStoreInitialized;
+
+ public HiveMetaTool() {
+ this.isObjStoreInitialized = false;
+ }
+
+ @SuppressWarnings("static-access")
+ private void init() {
+
+ System.out.println("Initializing HiveMetaTool..");
+
+ Option help = new Option("help", "print this message");
+ Option listFSRoot = new Option("listFSRoot", "print the current FS root locations");
+ Option executeJDOQL =
+ OptionBuilder.withArgName("query-string")
+ .hasArgs()
+ .withDescription("execute the given JDOQL query")
+ .create("executeJDOQL");
+
+ /* Ideally we want to specify the different arguments to updateLocation as separate argNames.
+ * However if we did that, HelpFormatter swallows all but the last argument. Note that this is
+ * a know issue with the HelpFormatter class that has not been fixed. We specify all arguments
+ * with a single argName to workaround this HelpFormatter bug.
+ */
+ Option updateFSRootLoc =
+ OptionBuilder
+ .withArgName("new-loc> " + "<old-loc")
+ .hasArgs(2)
+ .withDescription(
+ "Update FS root location in the metastore to new location.Both new-loc and " +
+ "old-loc should be valid URIs with valid host names and schemes." +
+ "When run with the dryRun option changes are displayed but are not " +
+ "persisted. When run with the serdepropKey/tablePropKey option " +
+ "updateLocation looks for the serde-prop-key/table-prop-key that is " +
+ "specified and updates its value if found.")
+ .create("updateLocation");
+ Option dryRun = new Option("dryRun" , "Perform a dry run of updateLocation changes.When " +
+ "run with the dryRun option updateLocation changes are displayed but not persisted. " +
+ "dryRun is valid only with the updateLocation option.");
+ Option serdePropKey =
+ OptionBuilder.withArgName("serde-prop-key")
+ .hasArgs()
+ .withValueSeparator()
+ .withDescription("Specify the key for serde property to be updated. serdePropKey option " +
+ "is valid only with updateLocation option.")
+ .create("serdePropKey");
+ Option tablePropKey =
+ OptionBuilder.withArgName("table-prop-key")
+ .hasArg()
+ .withValueSeparator()
+ .withDescription("Specify the key for table property to be updated. tablePropKey option " +
+ "is valid only with updateLocation option.")
+ .create("tablePropKey");
+
+ cmdLineOptions.addOption(help);
+ cmdLineOptions.addOption(listFSRoot);
+ cmdLineOptions.addOption(executeJDOQL);
+ cmdLineOptions.addOption(updateFSRootLoc);
+ cmdLineOptions.addOption(dryRun);
+ cmdLineOptions.addOption(serdePropKey);
+ cmdLineOptions.addOption(tablePropKey);
+ }
+
+ private void initObjectStore(Configuration conf) {
+ if (!isObjStoreInitialized) {
+ objStore = new ObjectStore();
+ objStore.setConf(conf);
+ isObjStoreInitialized = true;
+ }
+ }
+
+ private void shutdownObjectStore() {
+ if (isObjStoreInitialized) {
+ objStore.shutdown();
+ isObjStoreInitialized = false;
+ }
+ }
+
+ private void listFSRoot() {
+ Configuration conf = MetastoreConf.newMetastoreConf();
+ initObjectStore(conf);
+
+ Set<String> hdfsRoots = objStore.listFSRoots();
+ if (hdfsRoots != null) {
+ System.out.println("Listing FS Roots..");
+ for (String s : hdfsRoots) {
+ System.out.println(s);
+ }
+ } else {
+ System.err.println("Encountered error during listFSRoot - " +
+ "commit of JDO transaction failed");
+ }
+ }
+
+ private void executeJDOQLSelect(String query) {
+ Configuration conf = MetastoreConf.newMetastoreConf();
+ initObjectStore(conf);
+
+ System.out.println("Executing query: " + query);
+ try (ObjectStore.QueryWrapper queryWrapper = new ObjectStore.QueryWrapper()) {
+ Collection<?> result = objStore.executeJDOQLSelect(query, queryWrapper);
+ if (result != null) {
+ Iterator<?> iter = result.iterator();
+ while (iter.hasNext()) {
+ Object o = iter.next();
+ System.out.println(o.toString());
+ }
+ } else {
+ System.err.println("Encountered error during executeJDOQLSelect -" +
+ "commit of JDO transaction failed.");
+ }
+ }
+ }
+
+ private void executeJDOQLUpdate(String query) {
+ Configuration conf = MetastoreConf.newMetastoreConf();
+ initObjectStore(conf);
+
+ System.out.println("Executing query: " + query);
+ long numUpdated = objStore.executeJDOQLUpdate(query);
+ if (numUpdated >= 0) {
+ System.out.println("Number of records updated: " + numUpdated);
+ } else {
+ System.err.println("Encountered error during executeJDOQL -" +
+ "commit of JDO transaction failed.");
+ }
+ }
+
+ private int printUpdateLocations(Map<String, String> updateLocations) {
+ int count = 0;
+ for (String key: updateLocations.keySet()) {
+ String value = updateLocations.get(key);
+ System.out.println("old location: " + key + " new location: " + value);
+ count++;
+ }
+ return count;
+ }
+
+ private void printTblURIUpdateSummary(ObjectStore.UpdateMStorageDescriptorTblURIRetVal retVal,
+ boolean isDryRun) {
+ String tblName = "SDS";
+ String fieldName = "LOCATION";
+
+ if (retVal == null) {
+ System.err.println("Encountered error while executing updateMStorageDescriptorTblURI - " +
+ "commit of JDO transaction failed. Failed to update FSRoot locations in " +
+ fieldName + "field in " + tblName + " table.");
+ } else {
+ Map<String, String> updateLocations = retVal.getUpdateLocations();
+ if (isDryRun) {
+ System.out.println("Dry Run of updateLocation on table " + tblName + "..");
+ } else {
+ System.out.println("Successfully updated the following locations..");
+ }
+ int count = printUpdateLocations(updateLocations);
+ if (isDryRun) {
+ System.out.println("Found " + count + " records in " + tblName + " table to update");
+ } else {
+ System.out.println("Updated " + count + " records in " + tblName + " table");
+ }
+ List<String> badRecords = retVal.getBadRecords();
+ if (badRecords.size() > 0) {
+ System.err.println("Warning: Found records with bad " + fieldName + " in " +
+ tblName + " table.. ");
+ for (String badRecord:badRecords) {
+ System.err.println("bad location URI: " + badRecord);
+ }
+ }
+ int numNullRecords = retVal.getNumNullRecords();
+ if (numNullRecords != 0) {
+ LOG.debug("Number of NULL location URI: " + numNullRecords +
+ ". This can happen for View or Index.");
+ }
+ }
+ }
+
+ private void printDatabaseURIUpdateSummary(ObjectStore.UpdateMDatabaseURIRetVal retVal,
+ boolean isDryRun) {
+ String tblName = "DBS";
+ String fieldName = "LOCATION_URI";
+
+ if (retVal == null) {
+ System.err.println("Encountered error while executing updateMDatabaseURI - " +
+ "commit of JDO transaction failed. Failed to update FSRoot locations in " +
+ fieldName + "field in " + tblName + " table.");
+ } else {
+ Map<String, String> updateLocations = retVal.getUpdateLocations();
+ if (isDryRun) {
+ System.out.println("Dry Run of updateLocation on table " + tblName + "..");
+ } else {
+ System.out.println("Successfully updated the following locations..");
+ }
+ int count = printUpdateLocations(updateLocations);
+ if (isDryRun) {
+ System.out.println("Found " + count + " records in " + tblName + " table to update");
+ } else {
+ System.out.println("Updated " + count + " records in " + tblName + " table");
+ }
+ List<String> badRecords = retVal.getBadRecords();
+ if (badRecords.size() > 0) {
+ System.err.println("Warning: Found records with bad " + fieldName + " in " +
+ tblName + " table.. ");
+ for (String badRecord:badRecords) {
+ System.err.println("bad location URI: " + badRecord);
+ }
+ }
+ }
+ }
+
+ private void printPropURIUpdateSummary(ObjectStore.UpdatePropURIRetVal retVal, String
+ tablePropKey, boolean isDryRun, String tblName, String methodName) {
+ if (retVal == null) {
+ System.err.println("Encountered error while executing " + methodName + " - " +
+ "commit of JDO transaction failed. Failed to update FSRoot locations in " +
+ "value field corresponding to" + tablePropKey + " in " + tblName + " table.");
+ } else {
+ Map<String, String> updateLocations = retVal.getUpdateLocations();
+ if (isDryRun) {
+ System.out.println("Dry Run of updateLocation on table " + tblName + "..");
+ } else {
+ System.out.println("Successfully updated the following locations..");
+ }
+ int count = printUpdateLocations(updateLocations);
+ if (isDryRun) {
+ System.out.println("Found " + count + " records in " + tblName + " table to update");
+ } else {
+ System.out.println("Updated " + count + " records in " + tblName + " table");
+ }
+ List<String> badRecords = retVal.getBadRecords();
+ if (badRecords.size() > 0) {
+ System.err.println("Warning: Found records with bad " + tablePropKey + " key in " +
+ tblName + " table.. ");
+ for (String badRecord:badRecords) {
+ System.err.println("bad location URI: " + badRecord);
+ }
+ }
+ }
+ }
+
+ private void printSerdePropURIUpdateSummary(ObjectStore.UpdateSerdeURIRetVal retVal,
+ String serdePropKey, boolean isDryRun) {
+ String tblName = "SERDE_PARAMS";
+
+ if (retVal == null) {
+ System.err.println("Encountered error while executing updateSerdeURI - " +
+ "commit of JDO transaction failed. Failed to update FSRoot locations in " +
+ "value field corresponding to " + serdePropKey + " in " + tblName + " table.");
+ } else {
+ Map<String, String> updateLocations = retVal.getUpdateLocations();
+ if (isDryRun) {
+ System.out.println("Dry Run of updateLocation on table " + tblName + "..");
+ } else {
+ System.out.println("Successfully updated the following locations..");
+ }
+ int count = printUpdateLocations(updateLocations);
+ if (isDryRun) {
+ System.out.println("Found " + count + " records in " + tblName + " table to update");
+ } else {
+ System.out.println("Updated " + count + " records in " + tblName + " table");
+ }
+ List<String> badRecords = retVal.getBadRecords();
+ if (badRecords.size() > 0) {
+ System.err.println("Warning: Found records with bad " + serdePropKey + " key in " +
+ tblName + " table.. ");
+ for (String badRecord:badRecords) {
+ System.err.println("bad location URI: " + badRecord);
+ }
+ }
+ }
+ }
+
+ public void updateFSRootLocation(URI oldURI, URI newURI, String serdePropKey, String
+ tablePropKey, boolean isDryRun) {
+ Configuration conf = MetastoreConf.newMetastoreConf();
+ initObjectStore(conf);
+
+ System.out.println("Looking for LOCATION_URI field in DBS table to update..");
+ ObjectStore.UpdateMDatabaseURIRetVal updateMDBURIRetVal = objStore.updateMDatabaseURI(oldURI,
+ newURI, isDryRun);
+ printDatabaseURIUpdateSummary(updateMDBURIRetVal, isDryRun);
+
+ System.out.println("Looking for LOCATION field in SDS table to update..");
+ ObjectStore.UpdateMStorageDescriptorTblURIRetVal updateTblURIRetVal =
+ objStore.updateMStorageDescriptorTblURI(oldURI, newURI, isDryRun);
+ printTblURIUpdateSummary(updateTblURIRetVal, isDryRun);
+
+ if (tablePropKey != null) {
+ System.out.println("Looking for value of " + tablePropKey + " key in TABLE_PARAMS table " +
+ "to update..");
+ ObjectStore.UpdatePropURIRetVal updateTblPropURIRetVal =
+ objStore.updateTblPropURI(oldURI, newURI,
+ tablePropKey, isDryRun);
+ printPropURIUpdateSummary(updateTblPropURIRetVal, tablePropKey, isDryRun, "TABLE_PARAMS",
+ "updateTblPropURI");
+
+ System.out.println("Looking for value of " + tablePropKey + " key in SD_PARAMS table " +
+ "to update..");
+ ObjectStore.UpdatePropURIRetVal updatePropURIRetVal = objStore
+ .updateMStorageDescriptorTblPropURI(oldURI, newURI, tablePropKey, isDryRun);
+ printPropURIUpdateSummary(updatePropURIRetVal, tablePropKey, isDryRun, "SD_PARAMS",
+ "updateMStorageDescriptorTblPropURI");
+ }
+
+ if (serdePropKey != null) {
+ System.out.println("Looking for value of " + serdePropKey + " key in SERDE_PARAMS table " +
+ "to update..");
+ ObjectStore.UpdateSerdeURIRetVal updateSerdeURIretVal = objStore.updateSerdeURI(oldURI,
+ newURI, serdePropKey, isDryRun);
+ printSerdePropURIUpdateSummary(updateSerdeURIretVal, serdePropKey, isDryRun);
+ }
+ }
+
+ private static void printAndExit(HiveMetaTool metaTool) {
+ HelpFormatter formatter = new HelpFormatter();
+ formatter.printHelp("metatool", metaTool.cmdLineOptions);
+ System.exit(1);
+ }
+
+ public static void main(String[] args) {
+ HiveMetaTool metaTool = new HiveMetaTool();
+ metaTool.init();
+ CommandLineParser parser = new GnuParser();
+ CommandLine line = null;
+
+ try {
+ try {
+ line = parser.parse(metaTool.cmdLineOptions, args);
+ } catch (ParseException e) {
+ System.err.println("HiveMetaTool:Parsing failed. Reason: " + e.getLocalizedMessage());
+ printAndExit(metaTool);
+ }
+
+ if (line.hasOption("help")) {
+ HelpFormatter formatter = new HelpFormatter();
+ formatter.printHelp("metatool", metaTool.cmdLineOptions);
+ } else if (line.hasOption("listFSRoot")) {
+ if (line.hasOption("dryRun")) {
+ System.err.println("HiveMetaTool: dryRun is not valid with listFSRoot");
+ printAndExit(metaTool);
+ } else if (line.hasOption("serdePropKey")) {
+ System.err.println("HiveMetaTool: serdePropKey is not valid with listFSRoot");
+ printAndExit(metaTool);
+ } else if (line.hasOption("tablePropKey")) {
+ System.err.println("HiveMetaTool: tablePropKey is not valid with listFSRoot");
+ printAndExit(metaTool);
+ }
+ metaTool.listFSRoot();
+ } else if (line.hasOption("executeJDOQL")) {
+ String query = line.getOptionValue("executeJDOQL");
+ if (line.hasOption("dryRun")) {
+ System.err.println("HiveMetaTool: dryRun is not valid with executeJDOQL");
+ printAndExit(metaTool);
+ } else if (line.hasOption("serdePropKey")) {
+ System.err.println("HiveMetaTool: serdePropKey is not valid with executeJDOQL");
+ printAndExit(metaTool);
+ } else if (line.hasOption("tablePropKey")) {
+ System.err.println("HiveMetaTool: tablePropKey is not valid with executeJDOQL");
+ printAndExit(metaTool);
+ }
+ if (query.toLowerCase().trim().startsWith("select")) {
+ metaTool.executeJDOQLSelect(query);
+ } else if (query.toLowerCase().trim().startsWith("update")) {
+ metaTool.executeJDOQLUpdate(query);
+ } else {
+ System.err.println("HiveMetaTool:Unsupported statement type");
+ printAndExit(metaTool);
+ }
+ } else if (line.hasOption("updateLocation")) {
+ String[] loc = line.getOptionValues("updateLocation");
+ boolean isDryRun = false;
+ String serdepropKey = null;
+ String tablePropKey = null;
+
+ if (loc.length != 2 && loc.length != 3) {
+ System.err.println("HiveMetaTool:updateLocation takes in 2 required and 1 " +
+ "optional arguments but " +
+ "was passed " + loc.length + " arguments");
+ printAndExit(metaTool);
+ }
+
+ Path newPath = new Path(loc[0]);
+ Path oldPath = new Path(loc[1]);
+
+ URI oldURI = oldPath.toUri();
+ URI newURI = newPath.toUri();
+
+ if (line.hasOption("dryRun")) {
+ isDryRun = true;
+ }
+
+ if (line.hasOption("serdePropKey")) {
+ serdepropKey = line.getOptionValue("serdePropKey");
+ }
+
+ if (line.hasOption("tablePropKey")) {
+ tablePropKey = line.getOptionValue("tablePropKey");
+ }
+
+ /*
+ * validate input - Both new and old URI should contain valid host names and valid schemes.
+ * port is optional in both the URIs since HDFS HA NN URI doesn't have a port.
+ */
+ if (oldURI.getHost() == null || newURI.getHost() == null) {
+ System.err.println("HiveMetaTool:A valid host is required in both old-loc and new-loc");
+ } else if (oldURI.getScheme() == null || newURI.getScheme() == null) {
+ System.err.println("HiveMetaTool:A valid scheme is required in both old-loc and new-loc");
+ } else {
+ metaTool.updateFSRootLocation(oldURI, newURI, serdepropKey, tablePropKey, isDryRun);
+ }
+ } else {
+ if (line.hasOption("dryRun")) {
+ System.err.println("HiveMetaTool: dryRun is not a valid standalone option");
+ } else if (line.hasOption("serdePropKey")) {
+ System.err.println("HiveMetaTool: serdePropKey is not a valid standalone option");
+ } else if (line.hasOption("tablePropKey")) {
+ System.err.println("HiveMetaTool: tablePropKey is not a valid standalone option");
+ printAndExit(metaTool);
+ } else {
+ System.err.print("HiveMetaTool:Parsing failed. Reason: Invalid arguments: " );
+ for (String s : line.getArgs()) {
+ System.err.print(s + " ");
+ }
+ System.err.println();
+ }
+ printAndExit(metaTool);
+ }
+ } finally {
+ metaTool.shutdownObjectStore();
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/hive/blob/20c86d1f/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/utils/FileUtils.java
----------------------------------------------------------------------
diff --git a/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/utils/FileUtils.java b/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/utils/FileUtils.java
index c9deccc..f6d7b5b 100644
--- a/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/utils/FileUtils.java
+++ b/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/utils/FileUtils.java
@@ -53,6 +53,16 @@ public class FileUtils {
return !name.startsWith("_") && !name.startsWith(".");
}
};
+ /**
+ * Filter that filters out hidden files
+ */
+ private static final PathFilter hiddenFileFilter = new PathFilter() {
+ @Override
+ public boolean accept(Path p) {
+ String name = p.getName();
+ return !name.startsWith("_") && !name.startsWith(".");
+ }
+ };
/**
* Move a particular file or directory to the trash.
@@ -412,4 +422,23 @@ public class FileUtils {
throw new MetaException("Unable to : " + path);
}
}
+
+ /**
+ * Utility method that determines if a specified directory already has
+ * contents (non-hidden files) or not - useful to determine if an
+ * immutable table already has contents, for example.
+ *
+ * @param path
+ * @throws IOException
+ */
+ public static boolean isDirEmpty(FileSystem fs, Path path) throws IOException {
+
+ if (fs.exists(path)) {
+ FileStatus[] status = fs.globStatus(new Path(path, "*"), hiddenFileFilter);
+ if (status.length > 0) {
+ return false;
+ }
+ }
+ return true;
+ }
}
http://git-wip-us.apache.org/repos/asf/hive/blob/20c86d1f/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/utils/MetaStoreUtils.java
----------------------------------------------------------------------
diff --git a/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/utils/MetaStoreUtils.java b/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/utils/MetaStoreUtils.java
index bf25e50..c711aa8 100644
--- a/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/utils/MetaStoreUtils.java
+++ b/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/utils/MetaStoreUtils.java
@@ -30,6 +30,7 @@ import org.apache.hadoop.fs.CommonConfigurationKeysPublic;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hive.common.StatsSetupConst;
import org.apache.hadoop.hive.metastore.ColumnType;
+import org.apache.hadoop.hive.metastore.HiveMetaStore;
import org.apache.hadoop.hive.metastore.TableType;
import org.apache.hadoop.hive.metastore.Warehouse;
import org.apache.hadoop.hive.metastore.api.ColumnStatistics;
@@ -63,9 +64,13 @@ import org.slf4j.LoggerFactory;
import javax.annotation.Nullable;
import java.io.File;
+import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.math.BigInteger;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.charset.Charset;
@@ -80,6 +85,7 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Properties;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
@@ -297,8 +303,8 @@ public class MetaStoreUtils {
}
}
- public static String getPartitionValWithInvalidCharacter(List<String> partVals,
- Pattern partitionValidationPattern) {
+ private static String getPartitionValWithInvalidCharacter(List<String> partVals,
+ Pattern partitionValidationPattern) {
if (partitionValidationPattern == null) {
return null;
}
@@ -495,8 +501,9 @@ public class MetaStoreUtils {
}
// check if stats need to be (re)calculated
- public static boolean requireCalStats(Configuration hiveConf, Partition oldPart,
- Partition newPart, Table tbl, EnvironmentContext environmentContext) {
+ public static boolean requireCalStats(Partition oldPart,
+ Partition newPart, Table tbl,
+ EnvironmentContext environmentContext) {
if (environmentContext != null
&& environmentContext.isSetProperties()
@@ -1046,4 +1053,486 @@ public class MetaStoreUtils {
ipAddress = (ipAddress == null) ? StringUtils.EMPTY : ipAddress;
return machineList.includes(ipAddress);
}
+
+ /**
+ * Convert FieldSchemas to Thrift DDL.
+ */
+ public static String getDDLFromFieldSchema(String structName,
+ List<FieldSchema> fieldSchemas) {
+ StringBuilder ddl = new StringBuilder();
+ ddl.append("struct ");
+ ddl.append(structName);
+ ddl.append(" { ");
+ boolean first = true;
+ for (FieldSchema col : fieldSchemas) {
+ if (first) {
+ first = false;
+ } else {
+ ddl.append(", ");
+ }
+ ddl.append(ColumnType.typeToThriftType(col.getType()));
+ ddl.append(' ');
+ ddl.append(col.getName());
+ }
+ ddl.append("}");
+
+ LOG.trace("DDL: {}", ddl);
+ return ddl.toString();
+ }
+
+ public static Properties getTableMetadata(
+ org.apache.hadoop.hive.metastore.api.Table table) {
+ return MetaStoreUtils.getSchema(table.getSd(), table.getSd(), table
+ .getParameters(), table.getDbName(), table.getTableName(), table.getPartitionKeys());
+ }
+
+ public static Properties getPartitionMetadata(
+ org.apache.hadoop.hive.metastore.api.Partition partition,
+ org.apache.hadoop.hive.metastore.api.Table table) {
+ return MetaStoreUtils
+ .getSchema(partition.getSd(), partition.getSd(), partition
+ .getParameters(), table.getDbName(), table.getTableName(),
+ table.getPartitionKeys());
+ }
+
+ public static Properties getSchema(
+ org.apache.hadoop.hive.metastore.api.Partition part,
+ org.apache.hadoop.hive.metastore.api.Table table) {
+ return MetaStoreUtils.getSchema(part.getSd(), table.getSd(), table
+ .getParameters(), table.getDbName(), table.getTableName(), table.getPartitionKeys());
+ }
+
+ /**
+ * Get partition level schema from table level schema.
+ * This function will use the same column names, column types and partition keys for
+ * each partition Properties. Their values are copied from the table Properties. This
+ * is mainly to save CPU and memory. CPU is saved because the first time the
+ * StorageDescriptor column names are accessed, JDO needs to execute a SQL query to
+ * retrieve the data. If we know the data will be the same as the table level schema
+ * and they are immutable, we should just reuse the table level schema objects.
+ *
+ * @param sd The Partition level Storage Descriptor.
+ * @param parameters partition level parameters
+ * @param tblSchema The table level schema from which this partition should be copied.
+ * @return the properties
+ */
+ public static Properties getPartSchemaFromTableSchema(
+ StorageDescriptor sd,
+ Map<String, String> parameters,
+ Properties tblSchema) {
+
+ // Inherent most properties from table level schema and overwrite some properties
+ // in the following code.
+ // This is mainly for saving CPU and memory to reuse the column names, types and
+ // partition columns in the table level schema.
+ Properties schema = (Properties) tblSchema.clone();
+
+ // InputFormat
+ String inputFormat = sd.getInputFormat();
+ if (inputFormat == null || inputFormat.length() == 0) {
+ String tblInput =
+ schema.getProperty(org.apache.hadoop.hive.metastore.api.hive_metastoreConstants.FILE_INPUT_FORMAT);
+ if (tblInput == null) {
+ inputFormat = org.apache.hadoop.mapred.SequenceFileInputFormat.class.getName();
+ } else {
+ inputFormat = tblInput;
+ }
+ }
+ schema.setProperty(org.apache.hadoop.hive.metastore.api.hive_metastoreConstants.FILE_INPUT_FORMAT,
+ inputFormat);
+
+ // OutputFormat
+ String outputFormat = sd.getOutputFormat();
+ if (outputFormat == null || outputFormat.length() == 0) {
+ String tblOutput =
+ schema.getProperty(org.apache.hadoop.hive.metastore.api.hive_metastoreConstants.FILE_OUTPUT_FORMAT);
+ if (tblOutput == null) {
+ outputFormat = org.apache.hadoop.mapred.SequenceFileOutputFormat.class.getName();
+ } else {
+ outputFormat = tblOutput;
+ }
+ }
+ schema.setProperty(org.apache.hadoop.hive.metastore.api.hive_metastoreConstants.FILE_OUTPUT_FORMAT,
+ outputFormat);
+
+ // Location
+ if (sd.getLocation() != null) {
+ schema.setProperty(org.apache.hadoop.hive.metastore.api.hive_metastoreConstants.META_TABLE_LOCATION,
+ sd.getLocation());
+ }
+
+ // Bucket count
+ schema.setProperty(org.apache.hadoop.hive.metastore.api.hive_metastoreConstants.BUCKET_COUNT,
+ Integer.toString(sd.getNumBuckets()));
+
+ if (sd.getBucketCols() != null && sd.getBucketCols().size() > 0) {
+ schema.setProperty(org.apache.hadoop.hive.metastore.api.hive_metastoreConstants.BUCKET_FIELD_NAME,
+ sd.getBucketCols().get(0));
+ }
+
+ // SerdeInfo
+ if (sd.getSerdeInfo() != null) {
+
+ // We should not update the following 3 values if SerDeInfo contains these.
+ // This is to keep backward compatible with getSchema(), where these 3 keys
+ // are updated after SerDeInfo properties got copied.
+ String cols = org.apache.hadoop.hive.metastore.api.hive_metastoreConstants.META_TABLE_COLUMNS;
+ String colTypes = org.apache.hadoop.hive.metastore.api.hive_metastoreConstants.META_TABLE_COLUMN_TYPES;
+ String parts = org.apache.hadoop.hive.metastore.api.hive_metastoreConstants.META_TABLE_PARTITION_COLUMNS;
+
+ for (Map.Entry<String,String> param : sd.getSerdeInfo().getParameters().entrySet()) {
+ String key = param.getKey();
+ if (schema.get(key) != null &&
+ (key.equals(cols) || key.equals(colTypes) || key.equals(parts))) {
+ continue;
+ }
+ schema.put(key, (param.getValue() != null) ? param.getValue() : StringUtils.EMPTY);
+ }
+
+ if (sd.getSerdeInfo().getSerializationLib() != null) {
+ schema.setProperty(ColumnType.SERIALIZATION_LIB, sd.getSerdeInfo().getSerializationLib());
+ }
+ }
+
+ // skipping columns since partition level field schemas are the same as table level's
+ // skipping partition keys since it is the same as table level partition keys
+
+ if (parameters != null) {
+ for (Map.Entry<String, String> e : parameters.entrySet()) {
+ schema.setProperty(e.getKey(), e.getValue());
+ }
+ }
+
+ return schema;
+ }
+
+ private static Properties addCols(Properties schema, List<FieldSchema> cols) {
+
+ StringBuilder colNameBuf = new StringBuilder();
+ StringBuilder colTypeBuf = new StringBuilder();
+ StringBuilder colComment = new StringBuilder();
+
+ boolean first = true;
+ String columnNameDelimiter = getColumnNameDelimiter(cols);
+ for (FieldSchema col : cols) {
+ if (!first) {
+ colNameBuf.append(columnNameDelimiter);
+ colTypeBuf.append(":");
+ colComment.append('\0');
+ }
+ colNameBuf.append(col.getName());
+ colTypeBuf.append(col.getType());
+ colComment.append((null != col.getComment()) ? col.getComment() : StringUtils.EMPTY);
+ first = false;
+ }
+ schema.setProperty(
+ org.apache.hadoop.hive.metastore.api.hive_metastoreConstants.META_TABLE_COLUMNS,
+ colNameBuf.toString());
+ schema.setProperty(ColumnType.COLUMN_NAME_DELIMITER, columnNameDelimiter);
+ String colTypes = colTypeBuf.toString();
+ schema.setProperty(
+ org.apache.hadoop.hive.metastore.api.hive_metastoreConstants.META_TABLE_COLUMN_TYPES,
+ colTypes);
+ schema.setProperty("columns.comments", colComment.toString());
+
+ return schema;
+
+ }
+
+ public static Properties getSchemaWithoutCols(StorageDescriptor sd,
+ Map<String, String> parameters, String databaseName, String tableName,
+ List<FieldSchema> partitionKeys) {
+ Properties schema = new Properties();
+ String inputFormat = sd.getInputFormat();
+ if (inputFormat == null || inputFormat.length() == 0) {
+ inputFormat = org.apache.hadoop.mapred.SequenceFileInputFormat.class
+ .getName();
+ }
+ schema.setProperty(
+ org.apache.hadoop.hive.metastore.api.hive_metastoreConstants.FILE_INPUT_FORMAT,
+ inputFormat);
+ String outputFormat = sd.getOutputFormat();
+ if (outputFormat == null || outputFormat.length() == 0) {
+ outputFormat = org.apache.hadoop.mapred.SequenceFileOutputFormat.class
+ .getName();
+ }
+ schema.setProperty(
+ org.apache.hadoop.hive.metastore.api.hive_metastoreConstants.FILE_OUTPUT_FORMAT,
+ outputFormat);
+
+ schema.setProperty(
+ org.apache.hadoop.hive.metastore.api.hive_metastoreConstants.META_TABLE_NAME,
+ databaseName + "." + tableName);
+
+ if (sd.getLocation() != null) {
+ schema.setProperty(
+ org.apache.hadoop.hive.metastore.api.hive_metastoreConstants.META_TABLE_LOCATION,
+ sd.getLocation());
+ }
+ schema.setProperty(
+ org.apache.hadoop.hive.metastore.api.hive_metastoreConstants.BUCKET_COUNT, Integer
+ .toString(sd.getNumBuckets()));
+ if (sd.getBucketCols() != null && sd.getBucketCols().size() > 0) {
+ schema.setProperty(
+ org.apache.hadoop.hive.metastore.api.hive_metastoreConstants.BUCKET_FIELD_NAME, sd
+ .getBucketCols().get(0));
+ }
+ if (sd.getSerdeInfo() != null) {
+ for (Map.Entry<String,String> param : sd.getSerdeInfo().getParameters().entrySet()) {
+ schema.put(param.getKey(), (param.getValue() != null) ? param.getValue() : StringUtils.EMPTY);
+ }
+
+ if (sd.getSerdeInfo().getSerializationLib() != null) {
+ schema.setProperty(ColumnType.SERIALIZATION_LIB, sd .getSerdeInfo().getSerializationLib());
+ }
+ }
+
+ if (sd.getCols() != null) {
+ schema.setProperty(ColumnType.SERIALIZATION_DDL, getDDLFromFieldSchema(tableName, sd.getCols()));
+ }
+
+ String partString = StringUtils.EMPTY;
+ String partStringSep = StringUtils.EMPTY;
+ String partTypesString = StringUtils.EMPTY;
+ String partTypesStringSep = StringUtils.EMPTY;
+ for (FieldSchema partKey : partitionKeys) {
+ partString = partString.concat(partStringSep);
+ partString = partString.concat(partKey.getName());
+ partTypesString = partTypesString.concat(partTypesStringSep);
+ partTypesString = partTypesString.concat(partKey.getType());
+ if (partStringSep.length() == 0) {
+ partStringSep = "/";
+ partTypesStringSep = ":";
+ }
+ }
+ if (partString.length() > 0) {
+ schema
+ .setProperty(
+ org.apache.hadoop.hive.metastore.api.hive_metastoreConstants.META_TABLE_PARTITION_COLUMNS,
+ partString);
+ schema
+ .setProperty(
+ org.apache.hadoop.hive.metastore.api.hive_metastoreConstants.META_TABLE_PARTITION_COLUMN_TYPES,
+ partTypesString);
+ }
+
+ if (parameters != null) {
+ for (Map.Entry<String, String> e : parameters.entrySet()) {
+ // add non-null parameters to the schema
+ if ( e.getValue() != null) {
+ schema.setProperty(e.getKey(), e.getValue());
+ }
+ }
+ }
+
+ return schema;
+ }
+
+ public static Properties getSchema(
+ org.apache.hadoop.hive.metastore.api.StorageDescriptor sd,
+ org.apache.hadoop.hive.metastore.api.StorageDescriptor tblsd,
+ Map<String, String> parameters, String databaseName, String tableName,
+ List<FieldSchema> partitionKeys) {
+
+ return addCols(getSchemaWithoutCols(sd, parameters, databaseName, tableName, partitionKeys), tblsd.getCols());
+ }
+
+ public static String getColumnNameDelimiter(List<FieldSchema> fieldSchemas) {
+ // we first take a look if any fieldSchemas contain COMMA
+ for (int i = 0; i < fieldSchemas.size(); i++) {
+ if (fieldSchemas.get(i).getName().contains(",")) {
+ return String.valueOf(ColumnType.COLUMN_COMMENTS_DELIMITER);
+ }
+ }
+ return String.valueOf(',');
+ }
+
+ /**
+ * Convert FieldSchemas to columnNames.
+ */
+ public static String getColumnNamesFromFieldSchema(List<FieldSchema> fieldSchemas) {
+ String delimiter = getColumnNameDelimiter(fieldSchemas);
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < fieldSchemas.size(); i++) {
+ if (i > 0) {
+ sb.append(delimiter);
+ }
+ sb.append(fieldSchemas.get(i).getName());
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Convert FieldSchemas to columnTypes.
+ */
+ public static String getColumnTypesFromFieldSchema(
+ List<FieldSchema> fieldSchemas) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < fieldSchemas.size(); i++) {
+ if (i > 0) {
+ sb.append(",");
+ }
+ sb.append(fieldSchemas.get(i).getType());
+ }
+ return sb.toString();
+ }
+
+ public static String getColumnCommentsFromFieldSchema(List<FieldSchema> fieldSchemas) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < fieldSchemas.size(); i++) {
+ if (i > 0) {
+ sb.append(ColumnType.COLUMN_COMMENTS_DELIMITER);
+ }
+ sb.append(fieldSchemas.get(i).getComment());
+ }
+ return sb.toString();
+ }
+
+ public static int startMetaStore() throws Exception {
+ return startMetaStore(HadoopThriftAuthBridge.getBridge(), null);
+ }
+
+ public static int startMetaStore(final HadoopThriftAuthBridge bridge, Configuration conf) throws
+ Exception {
+ int port = findFreePort();
+ startMetaStore(port, bridge, conf);
+ return port;
+ }
+
+ public static int startMetaStore(Configuration conf) throws Exception {
+ return startMetaStore(HadoopThriftAuthBridge.getBridge(), conf);
+ }
+
+ public static void startMetaStore(final int port, final HadoopThriftAuthBridge bridge) throws Exception {
+ startMetaStore(port, bridge, null);
+ }
+
+ public static void startMetaStore(final int port,
+ final HadoopThriftAuthBridge bridge, Configuration hiveConf)
+ throws Exception{
+ if (hiveConf == null) {
+ hiveConf = MetastoreConf.newMetastoreConf();
+ }
+ final Configuration finalHiveConf = hiveConf;
+ Thread thread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ HiveMetaStore.startMetaStore(port, bridge, finalHiveConf);
+ } catch (Throwable e) {
+ LOG.error("Metastore Thrift Server threw an exception...",e);
+ }
+ }
+ });
+ thread.setDaemon(true);
+ thread.start();
+ loopUntilHMSReady(port);
+ }
+
+ /**
+ * A simple connect test to make sure that the metastore is up
+ * @throws Exception
+ */
+ private static void loopUntilHMSReady(int port) throws Exception {
+ int retries = 0;
+ Exception exc;
+ while (true) {
+ try {
+ Socket socket = new Socket();
+ socket.connect(new InetSocketAddress(port), 5000);
+ socket.close();
+ return;
+ } catch (Exception e) {
+ if (retries++ > 60) { //give up
+ exc = e;
+ break;
+ }
+ Thread.sleep(1000);
+ }
+ }
+ // something is preventing metastore from starting
+ // print the stack from all threads for debugging purposes
+ LOG.error("Unable to connect to metastore server: " + exc.getMessage());
+ LOG.info("Printing all thread stack traces for debugging before throwing exception.");
+ LOG.info(getAllThreadStacksAsString());
+ throw exc;
+ }
+
+ private static String getAllThreadStacksAsString() {
+ Map<Thread, StackTraceElement[]> threadStacks = Thread.getAllStackTraces();
+ StringBuilder sb = new StringBuilder();
+ for (Map.Entry<Thread, StackTraceElement[]> entry : threadStacks.entrySet()) {
+ Thread t = entry.getKey();
+ sb.append(System.lineSeparator());
+ sb.append("Name: ").append(t.getName()).append(" State: ").append(t.getState());
+ addStackString(entry.getValue(), sb);
+ }
+ return sb.toString();
+ }
+
+ private static void addStackString(StackTraceElement[] stackElems, StringBuilder sb) {
+ sb.append(System.lineSeparator());
+ for (StackTraceElement stackElem : stackElems) {
+ sb.append(stackElem).append(System.lineSeparator());
+ }
+ }
+
+ /**
+ * Finds a free port on the machine.
+ *
+ * @return
+ * @throws IOException
+ */
+ public static int findFreePort() throws IOException {
+ ServerSocket socket= new ServerSocket(0);
+ int port = socket.getLocalPort();
+ socket.close();
+ return port;
+ }
+
+ /**
+ * Finds a free port on the machine, but allow the
+ * ability to specify a port number to not use, no matter what.
+ */
+ public static int findFreePortExcepting(int portToExclude) throws IOException {
+ ServerSocket socket1 = null;
+ ServerSocket socket2 = null;
+ try {
+ socket1 = new ServerSocket(0);
+ socket2 = new ServerSocket(0);
+ if (socket1.getLocalPort() != portToExclude) {
+ return socket1.getLocalPort();
+ }
+ // If we're here, then socket1.getLocalPort was the port to exclude
+ // Since both sockets were open together at a point in time, we're
+ // guaranteed that socket2.getLocalPort() is not the same.
+ return socket2.getLocalPort();
+ } finally {
+ if (socket1 != null){
+ socket1.close();
+ }
+ if (socket2 != null){
+ socket2.close();
+ }
+ }
+ }
+
+ public static String getIndexTableName(String dbName, String baseTblName, String indexName) {
+ return dbName + "__" + baseTblName + "_" + indexName + "__";
+ }
+
+ public static boolean isMaterializedViewTable(Table table) {
+ if (table == null) {
+ return false;
+ }
+ return TableType.MATERIALIZED_VIEW.toString().equals(table.getTableType());
+ }
+
+ public static List<String> getColumnNames(List<FieldSchema> schema) {
+ List<String> cols = new ArrayList<>(schema.size());
+ for (FieldSchema fs : schema) {
+ cols.add(fs.getName());
+ }
+ return cols;
+ }
}
http://git-wip-us.apache.org/repos/asf/hive/blob/20c86d1f/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/utils/SecurityUtils.java
----------------------------------------------------------------------
diff --git a/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/utils/SecurityUtils.java b/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/utils/SecurityUtils.java
index 41a18cb..0b0cfbd 100644
--- a/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/utils/SecurityUtils.java
+++ b/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/utils/SecurityUtils.java
@@ -36,11 +36,15 @@ import org.apache.zookeeper.client.ZooKeeperSaslClient;
import javax.security.auth.login.AppConfigurationEntry;
import org.apache.thrift.transport.TSSLTransportFactory;
import org.apache.thrift.transport.TServerSocket;
+import org.apache.thrift.transport.TSocket;
+import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLSocket;
import javax.security.auth.login.LoginException;
import javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag;
@@ -284,4 +288,26 @@ public class SecurityUtils {
}
return thriftServerSocket;
}
+
+ public static TTransport getSSLSocket(String host, int port, int loginTimeout,
+ String trustStorePath, String trustStorePassWord) throws TTransportException {
+ TSSLTransportFactory.TSSLTransportParameters params =
+ new TSSLTransportFactory.TSSLTransportParameters();
+ params.setTrustStore(trustStorePath, trustStorePassWord);
+ params.requireClientAuth(true);
+ // The underlying SSLSocket object is bound to host:port with the given SO_TIMEOUT and
+ // SSLContext created with the given params
+ TSocket tSSLSocket = TSSLTransportFactory.getClientSocket(host, port, loginTimeout, params);
+ return getSSLSocketWithHttps(tSSLSocket);
+ }
+
+ // Using endpoint identification algorithm as HTTPS enables us to do
+ // CNAMEs/subjectAltName verification
+ private static TSocket getSSLSocketWithHttps(TSocket tSSLSocket) throws TTransportException {
+ SSLSocket sslSocket = (SSLSocket) tSSLSocket.getSocket();
+ SSLParameters sslParams = sslSocket.getSSLParameters();
+ sslParams.setEndpointIdentificationAlgorithm("HTTPS");
+ sslSocket.setSSLParameters(sslParams);
+ return new TSocket(sslSocket);
+ }
}
http://git-wip-us.apache.org/repos/asf/hive/blob/20c86d1f/standalone-metastore/src/test/java/org/apache/hadoop/hive/metastore/AlternateFailurePreListener.java
----------------------------------------------------------------------
diff --git a/standalone-metastore/src/test/java/org/apache/hadoop/hive/metastore/AlternateFailurePreListener.java b/standalone-metastore/src/test/java/org/apache/hadoop/hive/metastore/AlternateFailurePreListener.java
new file mode 100644
index 0000000..bde29a1
--- /dev/null
+++ b/standalone-metastore/src/test/java/org/apache/hadoop/hive/metastore/AlternateFailurePreListener.java
@@ -0,0 +1,62 @@
+/*
+ * 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.hadoop.hive.metastore;
+
+import javax.jdo.JDOException;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hive.metastore.api.InvalidOperationException;
+import org.apache.hadoop.hive.metastore.api.MetaException;
+import org.apache.hadoop.hive.metastore.api.NoSuchObjectException;
+import org.apache.hadoop.hive.metastore.events.PreEventContext;
+
+/**
+ *
+ * AlternateFailurePreListener.
+ *
+ * An implementation of MetaStorePreEventListener which fails every other time it's invoked,
+ * starting with the first time.
+ *
+ * It also records and makes available the number of times it's been invoked.
+ */
+public class AlternateFailurePreListener extends MetaStorePreEventListener {
+
+ private static int callCount = 0;
+ private static boolean throwException = true;
+
+ public AlternateFailurePreListener(Configuration config) {
+ super(config);
+ }
+
+ @Override
+ public void onEvent(PreEventContext context) throws MetaException, NoSuchObjectException,
+ InvalidOperationException {
+
+ callCount++;
+ if (throwException) {
+ throwException = false;
+ throw new JDOException();
+ }
+
+ throwException = true;
+ }
+
+ public static int getCallCount() {
+ return callCount;
+ }
+}
http://git-wip-us.apache.org/repos/asf/hive/blob/20c86d1f/standalone-metastore/src/test/java/org/apache/hadoop/hive/metastore/DummyEndFunctionListener.java
----------------------------------------------------------------------
diff --git a/standalone-metastore/src/test/java/org/apache/hadoop/hive/metastore/DummyEndFunctionListener.java b/standalone-metastore/src/test/java/org/apache/hadoop/hive/metastore/DummyEndFunctionListener.java
new file mode 100644
index 0000000..ca1f10b
--- /dev/null
+++ b/standalone-metastore/src/test/java/org/apache/hadoop/hive/metastore/DummyEndFunctionListener.java
@@ -0,0 +1,47 @@
+/*
+ * 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.hadoop.hive.metastore;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.hadoop.conf.Configuration;
+
+
+/** A dummy implementation for
+ * {@link org.apache.hadoop.hive.metastore.MetaStoreEndFunctionListener}
+ * for testing purposes.
+ */
+public class DummyEndFunctionListener extends MetaStoreEndFunctionListener{
+
+ public static final List<String> funcNameList = new ArrayList<>();
+ public static final List<MetaStoreEndFunctionContext> contextList =
+ new ArrayList<>();
+
+ public DummyEndFunctionListener(Configuration config) {
+ super(config);
+ }
+
+ @Override
+ public void onEndFunction(String functionName, MetaStoreEndFunctionContext context) {
+ funcNameList.add(functionName);
+ contextList.add(context);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/hive/blob/20c86d1f/standalone-metastore/src/test/java/org/apache/hadoop/hive/metastore/DummyListener.java
----------------------------------------------------------------------
diff --git a/standalone-metastore/src/test/java/org/apache/hadoop/hive/metastore/DummyListener.java b/standalone-metastore/src/test/java/org/apache/hadoop/hive/metastore/DummyListener.java
new file mode 100644
index 0000000..baecd12
--- /dev/null
+++ b/standalone-metastore/src/test/java/org/apache/hadoop/hive/metastore/DummyListener.java
@@ -0,0 +1,144 @@
+/*
+ * 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.hadoop.hive.metastore;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hive.metastore.api.MetaException;
+import org.apache.hadoop.hive.metastore.events.AddIndexEvent;
+import org.apache.hadoop.hive.metastore.events.AddPartitionEvent;
+import org.apache.hadoop.hive.metastore.events.AlterIndexEvent;
+import org.apache.hadoop.hive.metastore.events.AlterPartitionEvent;
+import org.apache.hadoop.hive.metastore.events.AlterTableEvent;
+import org.apache.hadoop.hive.metastore.events.ConfigChangeEvent;
+import org.apache.hadoop.hive.metastore.events.CreateDatabaseEvent;
+import org.apache.hadoop.hive.metastore.events.CreateFunctionEvent;
+import org.apache.hadoop.hive.metastore.events.CreateTableEvent;
+import org.apache.hadoop.hive.metastore.events.DropDatabaseEvent;
+import org.apache.hadoop.hive.metastore.events.DropFunctionEvent;
+import org.apache.hadoop.hive.metastore.events.DropIndexEvent;
+import org.apache.hadoop.hive.metastore.events.DropPartitionEvent;
+import org.apache.hadoop.hive.metastore.events.DropTableEvent;
+import org.apache.hadoop.hive.metastore.events.ListenerEvent;
+import org.apache.hadoop.hive.metastore.events.LoadPartitionDoneEvent;
+
+/** A dummy implementation for
+ * {@link org.apache.hadoop.hive.metastore.MetaStoreEventListener}
+ * for testing purposes.
+ */
+public class DummyListener extends MetaStoreEventListener{
+
+ public static final List<ListenerEvent> notifyList = new ArrayList<>();
+
+ /**
+ * @return The last event received, or null if no event was received.
+ */
+ public static ListenerEvent getLastEvent() {
+ if (notifyList.isEmpty()) {
+ return null;
+ } else {
+ return notifyList.get(notifyList.size() - 1);
+ }
+ }
+
+ public DummyListener(Configuration config) {
+ super(config);
+ }
+
+ @Override
+ public void onConfigChange(ConfigChangeEvent configChange) {
+ addEvent(configChange);
+ }
+
+ @Override
+ public void onAddPartition(AddPartitionEvent partition) throws MetaException {
+ addEvent(partition);
+ }
+
+ @Override
+ public void onCreateDatabase(CreateDatabaseEvent db) throws MetaException {
+ addEvent(db);
+ }
+
+ @Override
+ public void onCreateTable(CreateTableEvent table) throws MetaException {
+ addEvent(table);
+ }
+
+ @Override
+ public void onDropDatabase(DropDatabaseEvent db) throws MetaException {
+ addEvent(db);
+ }
+
+ @Override
+ public void onDropPartition(DropPartitionEvent partition) throws MetaException {
+ addEvent(partition);
+ }
+
+ @Override
+ public void onDropTable(DropTableEvent table) throws MetaException {
+ addEvent(table);
+ }
+
+ @Override
+ public void onAlterTable(AlterTableEvent event) throws MetaException {
+ addEvent(event);
+ }
+
+ @Override
+ public void onAlterPartition(AlterPartitionEvent event) throws MetaException {
+ addEvent(event);
+ }
+
+ @Override
+ public void onLoadPartitionDone(LoadPartitionDoneEvent partEvent) throws MetaException {
+ addEvent(partEvent);
+ }
+
+ @Override
+ public void onAddIndex(AddIndexEvent indexEvent) throws MetaException {
+ addEvent(indexEvent);
+ }
+
+ @Override
+ public void onDropIndex(DropIndexEvent indexEvent) throws MetaException {
+ addEvent(indexEvent);
+ }
+
+ @Override
+ public void onAlterIndex(AlterIndexEvent indexEvent) throws MetaException {
+ addEvent(indexEvent);
+ }
+
+ @Override
+ public void onCreateFunction (CreateFunctionEvent fnEvent) throws MetaException {
+ addEvent(fnEvent);
+ }
+
+ @Override
+ public void onDropFunction (DropFunctionEvent fnEvent) throws MetaException {
+ addEvent(fnEvent);
+ }
+
+ private void addEvent(ListenerEvent event) {
+ notifyList.add(event);
+ }
+}
http://git-wip-us.apache.org/repos/asf/hive/blob/20c86d1f/standalone-metastore/src/test/java/org/apache/hadoop/hive/metastore/DummyMetaStoreInitListener.java
----------------------------------------------------------------------
diff --git a/standalone-metastore/src/test/java/org/apache/hadoop/hive/metastore/DummyMetaStoreInitListener.java b/standalone-metastore/src/test/java/org/apache/hadoop/hive/metastore/DummyMetaStoreInitListener.java
new file mode 100644
index 0000000..0f2a3c7
--- /dev/null
+++ b/standalone-metastore/src/test/java/org/apache/hadoop/hive/metastore/DummyMetaStoreInitListener.java
@@ -0,0 +1,39 @@
+/*
+ * 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.hadoop.hive.metastore;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hive.metastore.api.MetaException;
+
+/*
+ * An implementation of MetaStoreInitListener to verify onInit is called when
+ * HMSHandler is initialized
+ */
+public class DummyMetaStoreInitListener extends MetaStoreInitListener{
+
+ public static boolean wasCalled = false;
+ public DummyMetaStoreInitListener(Configuration config) {
+ super(config);
+ }
+
+ @Override
+ public void onInit(MetaStoreInitContext context) throws MetaException {
+ wasCalled = true;
+ }
+}
http://git-wip-us.apache.org/repos/asf/hive/blob/20c86d1f/standalone-metastore/src/test/java/org/apache/hadoop/hive/metastore/DummyPreListener.java
----------------------------------------------------------------------
diff --git a/standalone-metastore/src/test/java/org/apache/hadoop/hive/metastore/DummyPreListener.java b/standalone-metastore/src/test/java/org/apache/hadoop/hive/metastore/DummyPreListener.java
new file mode 100644
index 0000000..0a68bac
--- /dev/null
+++ b/standalone-metastore/src/test/java/org/apache/hadoop/hive/metastore/DummyPreListener.java
@@ -0,0 +1,49 @@
+/*
+ * 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.hadoop.hive.metastore;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hive.metastore.api.InvalidOperationException;
+import org.apache.hadoop.hive.metastore.api.MetaException;
+import org.apache.hadoop.hive.metastore.api.NoSuchObjectException;
+import org.apache.hadoop.hive.metastore.events.PreEventContext;
+
+/**
+ *
+ * DummyPreListener.
+ *
+ * An implementation of MetaStorePreEventListener which stores the Events it's seen in a list.
+ */
+public class DummyPreListener extends MetaStorePreEventListener {
+
+ public static final List<PreEventContext> notifyList = new ArrayList<>();
+
+ public DummyPreListener(Configuration config) {
+ super(config);
+ }
+
+ @Override
+ public void onEvent(PreEventContext context) throws MetaException, NoSuchObjectException,
+ InvalidOperationException {
+ notifyList.add(context);
+ }
+
+}