hive-protolib/src/main/java/com/streamsets/pipeline/stage/lib/hive/cache/HMSCache.java
@SuppressWarnings("unchecked")
  public <T extends HMSCacheSupport.HMSCacheInfo> T getOrLoad(
      HMSCacheType hmsCacheType,
      String qualifiedTableName,
      HiveQueryExecutor queryExecutor
  ) throws StageException {
    if (!cacheMap.containsKey(hmsCacheType)) {
      throw new StageException(Errors.HIVE_16, hmsCacheType);
    }

    // Firstly validate if the data already exists to avoid locking
    T cacheValue = getIfPresent(hmsCacheType, qualifiedTableName);
    if(cacheValue != null) {
      return cacheValue;
    }

    // For altering operation, get exclusive lock
    Lock lock = null;
    try {
      lock = tableLocks.get(keyForLockMap(hmsCacheType, qualifiedTableName));
      lock.lock();

      // Check the presence again as another thread could load the value before we got the lock
      cacheValue = getIfPresent(hmsCacheType, qualifiedTableName);
      if(cacheValue != null) {
        return cacheValue;
      }

      // Load the value from Hive
      return (T)(cacheMap.get(hmsCacheType).get(
        qualifiedTableName,
        () -> hmsCacheType.getSupport().newHMSCacheLoader(queryExecutor).load(qualifiedTableName)
      )).orNull();
    } catch(ExecutionException e) {
      throw new StageException(Errors.HIVE_01, e);
    } finally {
      if(lock != null) {
        lock.unlock();
      }
    }
  }
@SuppressWarnings("unchecked")
  public <T extends HMSCacheSupport.HMSCacheInfo> T getOrLoad(
      HMSCacheType hmsCacheType,
      String qualifiedTableName,
      HiveQueryExecutor queryExecutor
  ) throws StageException {
    if (!cacheMap.containsKey(hmsCacheType)) {
      throw new StageException(Errors.HIVE_16, hmsCacheType);
    }

    // Firstly validate if the data already exists to avoid locking
    T cacheValue = getIfPresent(hmsCacheType, qualifiedTableName);
    if(cacheValue != null) {
      return cacheValue;
    }

    // For altering operation, get exclusive lock
    Lock lock = null;
    try {
      lock = tableLocks.get(keyForLockMap(hmsCacheType, qualifiedTableName));
      lock.lock();

      // Check the presence again as another thread could load the value before we got the lock
      cacheValue = getIfPresent(hmsCacheType, qualifiedTableName);
      if(cacheValue != null) {
        return cacheValue;
      }

      // Load the value from Hive
      return (T)(cacheMap.get(hmsCacheType).get(
        qualifiedTableName,
        () -> hmsCacheType.getSupport().newHMSCacheLoader(queryExecutor).load(qualifiedTableName)
      )).orNull();
    } catch(ExecutionException e) {
      throw new StageException(Errors.HIVE_01, e);
    } finally {
      if(lock != null) {
        lock.unlock();
      }
    }
  }
Returns if the {@link HMSCache} has the corresponding {@link HMSCacheSupport.HMSCacheInfo}
and qualified table name. This method is safe to call from multiple threads - it will block and serialize
multiple readers. It guarantees that each value will be loaded at most once to limit load on HS2 as much
as possible.

If it is not there load it using corresponding {@link HMSCacheSupport.HMSCacheLoader}

@param <T> {@link HMSCacheSupport.HMSCacheInfo}
@param hmsCacheType {@link HMSCacheType}
@param qualifiedTableName qualified table name
@return Corresponding {@link HMSCacheSupport.HMSCacheInfo} for the qualified table name.
@throws StageException if the {@link HMSCacheType} is not supported by {@link HMSCache}