001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.util; 019 020import java.util.HashSet; 021import java.util.Set; 022import org.apache.hadoop.conf.Configuration; 023import org.apache.hadoop.hbase.coprocessor.CoprocessorHost; 024import org.apache.yetus.audience.InterfaceAudience; 025 026import org.apache.hbase.thirdparty.com.google.common.base.Preconditions; 027import org.apache.hbase.thirdparty.com.google.common.base.Strings; 028 029/** 030 * Helper class for coprocessor host when configuration changes. 031 */ 032@InterfaceAudience.Private 033public final class CoprocessorConfigurationUtil { 034 035 private CoprocessorConfigurationUtil() { 036 } 037 038 /** 039 * Check configuration change by comparing current loaded coprocessors with configuration values. 040 * This method is useful when the configuration object has been updated but we need to determine 041 * if coprocessor configuration has actually changed compared to what's currently loaded. 042 * <p> 043 * <b>Note:</b> This method only detects changes in the set of coprocessor class names. It does 044 * <b>not</b> detect changes to priority or path for coprocessors that are already loaded with the 045 * same class name. If you need to update the priority or path of an existing coprocessor, you 046 * must restart the region/regionserver/master. 047 * @param coprocessorHost the coprocessor host to check current loaded coprocessors (can be null) 048 * @param conf the configuration to check 049 * @param configurationKey the configuration keys to check 050 * @return true if configuration has changed, false otherwise 051 */ 052 public static boolean checkConfigurationChange(CoprocessorHost<?, ?> coprocessorHost, 053 Configuration conf, String... configurationKey) { 054 Preconditions.checkArgument(configurationKey != null, "Configuration Key(s) must be provided"); 055 Preconditions.checkArgument(conf != null, "Configuration must be provided"); 056 057 if ( 058 !conf.getBoolean(CoprocessorHost.COPROCESSORS_ENABLED_CONF_KEY, 059 CoprocessorHost.DEFAULT_COPROCESSORS_ENABLED) 060 ) { 061 return false; 062 } 063 064 if (coprocessorHost == null) { 065 // If no coprocessor host exists, check if any coprocessors are now configured 066 return hasCoprocessorsConfigured(conf, configurationKey); 067 } 068 069 // Get currently loaded coprocessor class names 070 Set<String> currentlyLoaded = coprocessorHost.getCoprocessorClassNames(); 071 072 // Get coprocessor class names from configuration 073 // Only class names are compared; priority and path changes are not detected 074 Set<String> configuredClasses = new HashSet<>(); 075 for (String key : configurationKey) { 076 String[] classes = conf.getStrings(key); 077 if (classes != null) { 078 for (String className : classes) { 079 // Handle the className|priority|path format 080 String[] classNameToken = className.split("\\|"); 081 String actualClassName = classNameToken[0].trim(); 082 if (!Strings.isNullOrEmpty(actualClassName)) { 083 configuredClasses.add(actualClassName); 084 } 085 } 086 } 087 } 088 089 // Compare the two sets 090 return !currentlyLoaded.equals(configuredClasses); 091 } 092 093 /** 094 * Helper method to check if there are any coprocessors configured. 095 */ 096 private static boolean hasCoprocessorsConfigured(Configuration conf, String... configurationKey) { 097 for (String key : configurationKey) { 098 String[] coprocessors = conf.getStrings(key); 099 if (coprocessors != null && coprocessors.length > 0) { 100 return true; 101 } 102 } 103 return false; 104 } 105}