Package org.teiid.dqp.internal.process

Source Code of org.teiid.dqp.internal.process.SessionAwareCache$CacheID

/*
* JBoss, Home of Professional Open Source.
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.  Some portions may be licensed
* to Red Hat, Inc. under one or more contributor license agreements.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*/

package org.teiid.dqp.internal.process;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;

import org.teiid.cache.Cachable;
import org.teiid.cache.Cache;
import org.teiid.cache.CacheConfiguration;
import org.teiid.cache.CacheFactory;
import org.teiid.cache.DefaultCache;
import org.teiid.cache.DefaultCacheFactory;
import org.teiid.cache.CacheConfiguration.Policy;
import org.teiid.common.buffer.BufferManager;
import org.teiid.core.types.DataTypeManager;
import org.teiid.core.util.EquivalenceUtil;
import org.teiid.core.util.HashCodeUtil;
import org.teiid.logging.LogConstants;
import org.teiid.logging.LogManager;
import org.teiid.metadata.FunctionMethod.Determinism;
import org.teiid.query.parser.ParseInfo;
import org.teiid.vdb.runtime.VDBKey;


/**
* This class is used to cache session aware objects
*/
public class SessionAwareCache<T> {
  public static final int DEFAULT_MAX_SIZE_TOTAL = 512;
  public enum Type {
    RESULTSET,
    PREPAREDPLAN;
  }

  private Cache<CacheID, T> localCache;
  private Cache<CacheID, T> distributedCache;
  private Cache tupleBatchCache;
 
  private int maxSize = DEFAULT_MAX_SIZE_TOTAL;
  private long modTime;
  private Type type;
 
  private AtomicInteger cacheHit = new AtomicInteger();
  private AtomicInteger totalRequests = new AtomicInteger();
 
  private BufferManager bufferManager;
 
  public SessionAwareCache(){
    this(DEFAULT_MAX_SIZE_TOTAL);
  }
 
  SessionAwareCache(int maxSize){
    this(new DefaultCacheFactory(), Type.RESULTSET, new CacheConfiguration(Policy.LRU, 60, maxSize, "default")); //$NON-NLS-1$
  }
 
  SessionAwareCache (final CacheFactory cacheFactory, final Type type, final CacheConfiguration config){
    this.maxSize = config.getMaxEntries();
    if(this.maxSize < 0){
      this.maxSize = Integer.MAX_VALUE;
    }   
    this.localCache = new DefaultCache<CacheID, T>("local", maxSize, config.getMaxAgeInSeconds()*1000); //$NON-NLS-1$
   
    if (type == Type.PREPAREDPLAN) {
      this.distributedCache = localCache;
    }
    else {
      String location = config.getLocation()+"/"+type.name(); //$NON-NLS-1$
      this.distributedCache = cacheFactory.get(location, config);
      if (type == Type.RESULTSET) {
        this.tupleBatchCache = cacheFactory.get(location+"/batches", config); //$NON-NLS-1$
      }
      else {
        this.tupleBatchCache = this.distributedCache;
      }
    }
    this.modTime = config.getMaxStaleness()*1000;
    this.type = type;
 
 
  public T get(CacheID id){

    this.totalRequests.getAndIncrement();
   
    id.setSessionId(id.originalSessionId);
    T result = localCache.get(id);
   
    if (result == null) {
      id.setSessionId(null);
     
      id.setUserName(id.originalUserName);
      result = distributedCache.get(id);
     
      if (result == null) {
        id.setUserName(null);
        result = distributedCache.get(id);
      }
     
      if (result instanceof Cachable) {
        Cachable c = (Cachable)result;
        if (!c.restore(this.tupleBatchCache, this.bufferManager)) {
          result = null;
        }
      }
    }
   
    if (result != null) {
      if (result instanceof Cachable) {
        Cachable c = (Cachable)result;
        AccessInfo info = c.getAccessInfo();
        if (info != null && !info.validate(type == Type.RESULTSET, modTime)) {
          LogManager.logTrace(LogConstants.CTX_DQP, "Invalidating cache entry", id); //$NON-NLS-1$
          if (id.getSessionId() == null) {
            this.distributedCache.remove(id);
          } else {
            this.localCache.remove(id);
          }
          return null;
        }
      }
      LogManager.logTrace(LogConstants.CTX_DQP, "Cache hit for", id); //$NON-NLS-1$
      cacheHit.getAndIncrement();
    } else {
      LogManager.logTrace(LogConstants.CTX_DQP, "Cache miss for", id); //$NON-NLS-1$
    }
    return result;
  }
 
  public int getCacheHitCount() {
    return cacheHit.get();
  }
   
  public int getRequestCount() {
    return this.totalRequests.get();
  }
 
  public int getTotalCacheEntries() {
    if (this.localCache == this.distributedCache) {
      return this.localCache.size();
    }
    return localCache.size() + distributedCache.size();
  }
 
  public void put(CacheID id, Determinism determinismLevel, T t, Long ttl){
    if (determinismLevel.compareTo(Determinism.SESSION_DETERMINISTIC) <= 0) {
      id.setSessionId(id.originalSessionId);
      LogManager.logTrace(LogConstants.CTX_DQP, "Adding to session/local cache", id); //$NON-NLS-1$
      this.localCache.put(id, t, ttl);
    }
    else {
     
      boolean insert = true;
     
      id.setSessionId(null);
     
      if (determinismLevel == Determinism.USER_DETERMINISTIC) {
        id.setUserName(id.originalUserName);
      }
      else {
        id.setUserName(null);
      }
     
      if (t instanceof Cachable) {
        Cachable c = (Cachable)t;
        insert = c.prepare(this.tupleBatchCache, this.bufferManager);
      }
     
      if (insert) {
        LogManager.logTrace(LogConstants.CTX_DQP, "Adding to global/distributed cache", id); //$NON-NLS-1$
        this.distributedCache.put(id, t, ttl);
      }
    }
  }
 
  /**
   * Clear all the cached plans for all the clientConns
   * @param clientConn ClientConnection
   */
  public void clearAll(){
    this.localCache.clear();
    this.distributedCache.clear();
    this.totalRequests = new AtomicInteger();
    this.cacheHit = new AtomicInteger();
 
 
  public void clearForVDB(String vdbName, int version) {
    clearCache(this.localCache, vdbName, version);
    clearCache(this.distributedCache, vdbName, version);
  }
 
  private void clearCache(Cache<CacheID, T> cache, String vdbName, int version) {
    Set<CacheID> keys = cache.keys();
    VDBKey vdbKey = new VDBKey(vdbName, version);
    for (CacheID key:keys) {
      if (key.vdbInfo.equals(vdbKey)) {
        cache.remove(key);
      }
    }
  }
 
  public static class CacheID implements Serializable {
    private static final long serialVersionUID = 8261905111156764744L;
    private String sql;
    private VDBKey vdbInfo;
    private ParseInfo pi;
    private String sessionId;
    private String originalSessionId;
    private List<Serializable> parameters;
    private String userName;
    private String originalUserName;
   
    public CacheID(DQPWorkContext context, ParseInfo pi, String sql){
      this(pi, sql, context.getVdbName(), context.getVdbVersion(), context.getSessionId(), context.getUserName());
    }
   
    public CacheID(ParseInfo pi, String sql, String vdbName, int vdbVersion, String sessionId, String userName){
      this.sql = sql;
      this.vdbInfo = new VDBKey(vdbName, vdbVersion);
      this.pi = pi;
      this.originalSessionId = sessionId;
      this.originalUserName = userName;
    }

   
    public String getSessionId() {
      return sessionId;
    }
   
    public String getUserName() {
      return userName;
    }
   
    private void setSessionId(String sessionId) {
      this.sessionId = sessionId;
    }
   
    /**
     * Set the raw (non-Constant) parameter values.
     * @param parameters
     * @return
     */
    public boolean setParameters(List<?> parameters) {
      if (parameters !=  null && !parameters.isEmpty()) {
        this.parameters = new ArrayList<Serializable>();
        for (Object obj:parameters) {
          if (obj == null) {
            this.parameters.add(null);
            continue;
          }
          if (!(obj instanceof Serializable)) {
            return false;
          }
         
          Class<?> type = DataTypeManager.determineDataTypeClass(obj);
          if (type == DataTypeManager.DefaultDataClasses.OBJECT) {
            return false;
          }
          this.parameters.add((Serializable)obj);
        }
      }
      return true;
    }
   
    public String getSql() {
      return sql;
    }
   
    void setUserName(String name) {
      this.userName = name;
    }
           
    public boolean equals(Object obj){
          if(obj == this) {
              return true;
          }
          if(! (obj instanceof CacheID)) {
              return false;
          }
          CacheID that = (CacheID)obj;
            return EquivalenceUtil.areEqual(this.pi, that.pi) && this.vdbInfo.equals(that.vdbInfo) && this.sql.equals(that.sql)
              && EquivalenceUtil.areEqual(this.userName, that.userName)             
              && EquivalenceUtil.areEqual(this.sessionId, that.sessionId)
              && EquivalenceUtil.areEqual(this.parameters, that.parameters);
    }
   
      public int hashCode() {
          return HashCodeUtil.hashCode(0, vdbInfo, sql, pi, this.userName, sessionId, parameters);
      }
     
      @Override
      public String toString() {
        return "Cache Entry<" + originalSessionId + "="+ originalUserName + "> params:" + parameters + " sql:" + sql; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
      }
     
  }
 
    int getSpaceAllowed() {
        return maxSize;
    }
   
    public void setBufferManager(BufferManager bufferManager) {
      this.bufferManager = bufferManager;
    }
   
    public void setModTime(long modTime) {
    this.modTime = modTime;
  }
}
TOP

Related Classes of org.teiid.dqp.internal.process.SessionAwareCache$CacheID

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.