All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.calcite.adapter.geode.util.GeodeUtils Maven / Gradle / Ivy

The newest version!
/*
 * 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.calcite.adapter.geode.util;

import org.apache.calcite.avatica.util.DateTimeUtils;
import org.apache.calcite.linq4j.tree.Primitive;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rel.type.RelDataTypeField;
import org.apache.calcite.util.Util;

import org.apache.commons.lang3.StringUtils;
import org.apache.geode.cache.CacheClosedException;
import org.apache.geode.cache.GemFireCache;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.RegionExistsException;
import org.apache.geode.cache.client.ClientCache;
import org.apache.geode.cache.client.ClientCacheFactory;
import org.apache.geode.cache.client.ClientRegionShortcut;
import org.apache.geode.cache.query.Struct;
import org.apache.geode.pdx.PdxInstance;
import org.apache.geode.pdx.ReflectionBasedAutoSerializer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Utilities for the Geode adapter.
 */
public class GeodeUtils {

  protected static final Logger LOGGER = LoggerFactory.getLogger(GeodeUtils.class.getName());

  /**
   * Cache for the client proxy regions created in the current ClientCache.
   */
  private static final Map REGION_MAP = new ConcurrentHashMap<>();

  private static String currentLocatorHost = "";
  private static int currentLocatorPort = -1;

  private static final JavaTypeFactoryExtImpl JAVA_TYPE_FACTORY = new JavaTypeFactoryExtImpl();

  private GeodeUtils() {
  }

  /**
   * Creates a Geode client instance connected to locator and configured to
   * support PDX instances.
   *
   * 

If an old instance exists, it will be destroyed and re-created. * * @param locatorHost Locator's host address * @param locatorPort Locator's port * @param autoSerializerPackagePath package name of the Domain classes loaded in the regions * @return Returns a Geode {@link ClientCache} instance connected to Geode cluster */ public static synchronized ClientCache createClientCache(String locatorHost, int locatorPort, String autoSerializerPackagePath, boolean readSerialized) { if (locatorPort != currentLocatorPort || !StringUtils.equalsIgnoreCase(currentLocatorHost, locatorHost)) { LOGGER.info("Close existing ClientCache [" + currentLocatorHost + ":" + currentLocatorPort + "] for new Locator connection at: [" + locatorHost + ":" + locatorPort + "]"); currentLocatorHost = locatorHost; currentLocatorPort = locatorPort; closeClientCache(); } try { // If exists returns the existing client cache. This requires that the pre-created // client proxy regions can also be resolved from the regionMap return ClientCacheFactory.getAnyInstance(); } catch (CacheClosedException cce) { // Do nothing if there is no existing instance } return new ClientCacheFactory() .addPoolLocator(locatorHost, locatorPort) .setPdxSerializer(new ReflectionBasedAutoSerializer(autoSerializerPackagePath)) .setPdxReadSerialized(readSerialized) .setPdxPersistent(false) .create(); } public static synchronized void closeClientCache() { try { ClientCacheFactory.getAnyInstance().close(); } catch (CacheClosedException cce) { // Do nothing if there is no existing instance } REGION_MAP.clear(); } /** * Obtains a proxy pointing to an existing Region on the server * * @param cache {@link GemFireCache} instance to interact with the Geode server * @param regionName Name of the region to create proxy for. * @return Returns a Region proxy to a remote (on the Server) regions. */ public static synchronized Region createRegion(GemFireCache cache, String regionName) { Objects.requireNonNull(cache, "cache"); Objects.requireNonNull(regionName, "regionName"); Region region = REGION_MAP.get(regionName); if (region == null) { try { region = ((ClientCache) cache) .createClientRegionFactory(ClientRegionShortcut.PROXY) .create(regionName); } catch (IllegalStateException | RegionExistsException e) { // means this is a server cache (probably part of embedded testing // or clientCache is passed directly) region = cache.getRegion(regionName); } REGION_MAP.put(regionName, region); } return region; } /** * Converts a Geode object into a Row tuple. * * @param relDataTypeFields Table relation types * @param geodeResultObject Object value returned by Geode query * @return List of objects values corresponding to the relDataTypeFields */ public static Object convertToRowValues( List relDataTypeFields, Object geodeResultObject) { Object values; if (geodeResultObject instanceof Struct) { values = handleStructEntry(relDataTypeFields, geodeResultObject); } else if (geodeResultObject instanceof PdxInstance) { values = handlePdxInstanceEntry(relDataTypeFields, geodeResultObject); } else { values = handleJavaObjectEntry(relDataTypeFields, geodeResultObject); } return values; } private static Object handleStructEntry( List relDataTypeFields, Object obj) { Struct struct = (Struct) obj; Object[] values = new Object[relDataTypeFields.size()]; int index = 0; for (RelDataTypeField relDataTypeField : relDataTypeFields) { Type javaType = JAVA_TYPE_FACTORY.getJavaClass(relDataTypeField.getType()); Object rawValue; try { rawValue = struct.get(relDataTypeField.getName()); } catch (IllegalArgumentException e) { rawValue = ""; System.err.println("Could find field : " + relDataTypeField.getName()); e.printStackTrace(); } values[index++] = convert(rawValue, (Class) javaType); } if (values.length == 1) { return values[0]; } return values; } private static Object handlePdxInstanceEntry( List relDataTypeFields, Object obj) { PdxInstance pdxEntry = (PdxInstance) obj; Object[] values = new Object[relDataTypeFields.size()]; int index = 0; for (RelDataTypeField relDataTypeField : relDataTypeFields) { Type javaType = JAVA_TYPE_FACTORY.getJavaClass(relDataTypeField.getType()); Object rawValue = pdxEntry.getField(relDataTypeField.getName()); values[index++] = convert(rawValue, (Class) javaType); } if (values.length == 1) { return values[0]; } return values; } private static Object handleJavaObjectEntry( List relDataTypeFields, Object obj) { Class clazz = obj.getClass(); if (relDataTypeFields.size() == 1) { try { Field javaField = clazz.getDeclaredField(relDataTypeFields.get(0).getName()); javaField.setAccessible(true); return javaField.get(obj); } catch (Exception e) { e.printStackTrace(); } return null; } Object[] values = new Object[relDataTypeFields.size()]; int index = 0; for (RelDataTypeField relDataTypeField : relDataTypeFields) { try { Field javaField = clazz.getDeclaredField(relDataTypeField.getName()); javaField.setAccessible(true); values[index++] = javaField.get(obj); } catch (Exception e) { e.printStackTrace(); } } return values; } private static Object convert(Object o, Class clazz) { if (o == null) { return null; } Primitive primitive = Primitive.of(clazz); if (primitive != null) { clazz = primitive.boxClass; } else { primitive = Primitive.ofBox(clazz); } if (clazz == null) { // This is in case of nested Objects! if (o instanceof PdxInstance) { return Util.toString( ((PdxInstance) o).getFieldNames(), "PDX[", ",", "]"); } return o.toString(); } if (clazz.isInstance(o)) { return o; } if (o instanceof Date && primitive != null) { o = ((Date) o).getTime() / DateTimeUtils.MILLIS_PER_DAY; } if (o instanceof Number && primitive != null) { return primitive.number((Number) o); } return o; } /** * Extract the first entity of each Regions and use it to build a table types. * * @param region existing region * @return derived data type. */ public static RelDataType autodetectRelTypeFromRegion(Region region) { Objects.requireNonNull(region, "region"); // try to detect type using value constraints (if they exists) final Class constraint = region.getAttributes().getValueConstraint(); if (constraint != null && !PdxInstance.class.isAssignableFrom(constraint)) { return new JavaTypeFactoryExtImpl().createStructType(constraint); } final Iterator iter; if (region.getAttributes().getPoolName() == null) { // means current cache is server (not ClientCache) iter = region.keySet().iterator(); } else { // for ClientCache iter = region.keySetOnServer().iterator(); } if (!iter.hasNext()) { String message = String.format(Locale.ROOT, "Region %s is empty, can't " + "autodetect type(s)", region.getName()); throw new IllegalStateException(message); } final Object entry = region.get(iter.next()); return createRelDataType(entry); } // Create Relational Type by inferring a Geode entry or response instance. private static RelDataType createRelDataType(Object regionEntry) { JavaTypeFactoryExtImpl typeFactory = new JavaTypeFactoryExtImpl(); if (regionEntry instanceof PdxInstance) { return typeFactory.createPdxType((PdxInstance) regionEntry); } else { return typeFactory.createStructType(regionEntry.getClass()); } } } // End GeodeUtils.java





© 2015 - 2024 Weber Informatics LLC | Privacy Policy