@@ -127,6 +127,16 @@ public class GetProfile implements StellarFunction {
127127 */
128128 public static final String PROFILER_SALT_DIVISOR = "profiler.client.salt.divisor" ;
129129
130+ /**
131+ * The default Profile HBase table name should none be defined in the global properties.
132+ */
133+ public static final String PROFILER_HBASE_TABLE_DEFAULT = "profiler" ;
134+
135+ /**
136+ * The default Profile column family name should none be defined in the global properties.
137+ */
138+ public static final String PROFILER_COLUMN_FAMILY_DEFAULT = "P" ;
139+
130140 /**
131141 * The default Profile period duration should none be defined in the global properties.
132142 */
@@ -144,33 +154,26 @@ public class GetProfile implements StellarFunction {
144154
145155 private static final Logger LOG = LoggerFactory .getLogger (GetProfile .class );
146156
147-
148- // Global configuration from client context, used to help create profiler client.
149- private Map <String , Object > global ;
150-
151157 // Cached client that can retrieve profile values.
152158 private ProfilerClient client ;
153159
154- // Cached value of config override map used to construct the previously cached client.
155- private Map cachedConfigOverrideMap = null ;
160+ // Cached value of config map actually used to construct the previously cached client.
161+ private Map < String , Object > cachedConfigMap = new HashMap < String , Object >( 6 ) ;
156162
157163 /**
158- * Initialization.
164+ * Initialization. No longer need to do anything in initialization,
165+ * as all setup is done lazily and cached.
159166 */
160167 @ Override
161168 public void initialize (Context context ) {
162- // ensure the required capabilities are defined
163- Context .Capabilities [] required = { GLOBAL_CONFIG };
164- validateCapabilities (context , required );
165- global = (Map <String , Object >) context .getCapability (GLOBAL_CONFIG ).get ();
166169 }
167170
168171 /**
169172 * Is the function initialized?
170173 */
171174 @ Override
172175 public boolean isInitialized () {
173- return global != null ;
176+ return true ;
174177 }
175178
176179 /**
@@ -199,44 +202,60 @@ public Object apply(List<Object> args, Context context) throws ParseException {
199202 groups = getGroupsArg (4 , args );
200203 }
201204
205+ Map <String , Object > effectiveConfig = getEffectiveConfig (context , configOverrideMap );
206+
202207 //lazily create new profiler client if needed
203- if (client == null
204- || (cachedConfigOverrideMap == null && configOverrideMap != null )
205- || (cachedConfigOverrideMap != null && !cachedConfigOverrideMap .equals (configOverrideMap ))) {
206- Map <String , Object > configWithOverrides = mergeOverrides (global , configOverrideMap );
207- RowKeyBuilder rowKeyBuilder = getRowKeyBuilder (configWithOverrides );
208- ColumnBuilder columnBuilder = getColumnBuilder (configWithOverrides );
209- HTableInterface table = getTable (configWithOverrides );
208+ if (client == null || !cachedConfigMap .equals (effectiveConfig )) {
209+ RowKeyBuilder rowKeyBuilder = getRowKeyBuilder (effectiveConfig );
210+ ColumnBuilder columnBuilder = getColumnBuilder (effectiveConfig );
211+ HTableInterface table = getTable (effectiveConfig );
210212 client = new HBaseProfilerClient (table , rowKeyBuilder , columnBuilder );
211- cachedConfigOverrideMap = configOverrideMap ;
213+ cachedConfigMap = effectiveConfig ;
212214 }
213215
214216 return client .fetch (Object .class , profile , entity , groups , durationAgo , units );
215217 }
216218
217219 /**
218220 * Merge the configuration parameter override Map into the config from global context,
219- * and return the result.
221+ * and return the result. This has to be done on each call, because either may have changed.
220222 *
221- * Only the six recognized profiler client config parameters may be overridden ,
222- * all other key-value pairs in the Map will be ignored.
223+ * Only the six recognized profiler client config parameters may be set ,
224+ * all other key-value pairs in either Map will be ignored.
223225 *
224226 * Type violations cause a Stellar ParseException.
225227 *
226- * @param global - a context global config Map.
227- * @param configOverrideMap - Map as described above.
228- * @return config Map with overrides applied.
228+ * @param context - from which we get the global config Map.
229+ * @param configOverrideMap - Map of overrides as described above.
230+ * @return effective config Map with overrides applied.
229231 * @throws ParseException - if any override values are of wrong type.
230232 */
231- private Map <String , Object > mergeOverrides (
232- Map < String , Object > global
233+ private Map <String , Object > getEffectiveConfig (
234+ Context context
233235 , Map configOverrideMap
234236 ) throws ParseException {
235237
236- if (configOverrideMap == null ) return global ;
238+ final String [] KEYLIST = {
239+ PROFILER_HBASE_TABLE , PROFILER_COLUMN_FAMILY ,
240+ PROFILER_HBASE_TABLE_PROVIDER , PROFILER_PERIOD ,
241+ PROFILER_PERIOD_UNITS , PROFILER_SALT_DIVISOR };
237242
238- Map <String , Object > result = new HashMap <String , Object >(global );
243+ // ensure the required capabilities are defined
244+ final Context .Capabilities [] required = { GLOBAL_CONFIG };
245+ validateCapabilities (context , required );
246+ Map <String , Object > global = (Map <String , Object >) context .getCapability (GLOBAL_CONFIG ).get ();
247+
248+ Map <String , Object > result = new HashMap <String , Object >(6 );
239249 Object v ;
250+
251+ // extract the relevant parameters from global
252+ for (String k : KEYLIST ) {
253+ v = global .get (k );
254+ if (v != null ) result .put (k , v );
255+ }
256+ if (configOverrideMap == null ) return result ;
257+
258+ // extract override values, typechecking as we go
240259 try {
241260 for (Object key : configOverrideMap .keySet ()) {
242261 if (!(key instanceof String )) {
@@ -333,16 +352,10 @@ private <T> T getArg(int index, Class<T> clazz, List<Object> args) {
333352 * @param global The global configuration.
334353 */
335354 private ColumnBuilder getColumnBuilder (Map <String , Object > global ) {
336- // the builder is not currently configurable - but should be made so
337355 ColumnBuilder columnBuilder ;
338356
339- if (global .containsKey (PROFILER_COLUMN_FAMILY )) {
340- String columnFamily = (String ) global .get (PROFILER_COLUMN_FAMILY );
341- columnBuilder = new ValueOnlyColumnBuilder (columnFamily );
342-
343- } else {
344- columnBuilder = new ValueOnlyColumnBuilder ();
345- }
357+ String columnFamily = (String ) global .getOrDefault (PROFILER_COLUMN_FAMILY , PROFILER_COLUMN_FAMILY_DEFAULT );
358+ columnBuilder = new ValueOnlyColumnBuilder (columnFamily );
346359
347360 return columnBuilder ;
348361 }
@@ -378,7 +391,7 @@ private RowKeyBuilder getRowKeyBuilder(Map<String, Object> global) {
378391 */
379392 private HTableInterface getTable (Map <String , Object > global ) {
380393
381- String tableName = (String ) global .getOrDefault (PROFILER_HBASE_TABLE , "profiler" );
394+ String tableName = (String ) global .getOrDefault (PROFILER_HBASE_TABLE , PROFILER_HBASE_TABLE_DEFAULT );
382395 TableProvider provider = getTableProvider (global );
383396
384397 try {
0 commit comments