Package com.alibaba.wasp.jdbc.result

Source Code of com.alibaba.wasp.jdbc.result.ResultRemote

/**
* 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 com.alibaba.wasp.jdbc.result;

import com.alibaba.wasp.ClientConcernedException;
import com.alibaba.wasp.DataType;
import com.alibaba.wasp.FConstants;
import com.alibaba.wasp.ReadModel;
import com.alibaba.wasp.client.ExecuteResult;
import com.alibaba.wasp.client.FClient;
import com.alibaba.wasp.fserver.OperationStatus;
import com.alibaba.wasp.jdbc.JdbcException;
import com.alibaba.wasp.jdbc.value.Value;
import com.alibaba.wasp.jdbc.value.ValueInt;
import com.alibaba.wasp.session.ExecuteSession;
import com.alibaba.wasp.util.New;
import com.alibaba.wasp.util.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.hbase.util.Pair;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* The client side part of a result set that is kept on the server. In many
* cases, the complete data is kept on the client side, but for large results
* only a subset is in-memory.
*/
public class ResultRemote implements ResultInterface {

  private Log log = LogFactory.getLog(ResultRemote.class);

  private int fetchSize;
  private ExecuteSession session;
  private int id;
  // private final ResultColumn[] columns;
  private Value[] currentRow;
  private int rowCount;
  private int rowId, rowOffset;
  private ArrayList<Value[]> result;
  private String tablename;
  private HashMap<Integer, String> aliasLabelMap = New.hashMap();
  private boolean lableAliasInited = false;
  private final FClient fClient;
  private final String sql;
  private boolean isQuery = false;
  // the interface is query
  private boolean isExecuteQuery = false;

  private boolean isLastScan = false;

  private transient boolean isClose;

  private transient boolean isTransaction;

  private List<String> sqls;


  public ResultRemote(FClient fClient, ExecuteSession session,
      ResultTransfer transfer, String sql, int id, int fetchSize,
      boolean isExecuteQuery, ReadModel readModel, boolean isTransaction, List<String> sqls) throws IOException,
      SQLException {
    this.session = session;
    this.id = id;
    this.tablename = transfer.getTablename();
    rowId = -1;
    result = New.arrayList();
    this.fetchSize = fetchSize;
    this.sql = sql;
    this.fClient = fClient;
    this.isExecuteQuery = isExecuteQuery;
    this.isTransaction = isTransaction;
    this.sqls = sqls;
    fetchRows(false);
  }

  public ResultRemote(FClient fClient, ExecuteSession session,
      ResultTransfer transfer, String sql, ReadModel readModel)
      throws IOException, SQLException {
    this(fClient, session, transfer, sql, 0, 0, false, readModel, false, null);
  }

  public ResultRemote(FClient fClient, ExecuteSession session,
      ResultTransfer transfer, List<String> sqls, boolean isTransaction)
      throws IOException, SQLException {
    this(fClient, session, transfer, null, 0, 0, false, null, isTransaction, sqls);
  }

  private static void mapColumn(HashMap<Integer, String> map, String label,
      int index) {
    // put the index (usually that's the only operation)
    String old = map.put(index, label);
    if (old != null) {
      // if there was a clash (which is seldom),
      // put the old one back
      map.put(index, old);
    }
  }

  @Override
  public String getColumnName(int i) {
    return aliasLabelMap.get(i);
  }

  @Override
  public long getColumnPrecision(int i) {
    return -1;
  }

  @Override
  public int getColumnScale(int i) {
    return -1;
  }

  @Override
  public int getNullable(int i) {
    return -1;
  }

  @Override
  public void reset() {
    rowId = -1;
    currentRow = null;
    if (session == null) {
      return;
    }
    synchronized (session) {
      session.checkClosed();
    }
  }

  @Override
  public boolean isQuery() {
    return this.isQuery || this.isExecuteQuery;
  }

  @Override
  public String getSessionId() {
    if(session != null) {
      return session.getSessionId();
    } else {
      return null;
    }
  }

  @Override
  public Value[] currentRow() {
    return currentRow;
  }

  @Override
  public boolean next() throws SQLException {
    if (rowId < rowCount) {
      rowId++;
      remapIfOld();
      if (rowId < rowCount) {
        if (rowId - rowOffset >= result.size()) {
          if (isLastScan) {
            return false;
          }
          fetchRows(true);
        }
        currentRow = result.get(rowId - rowOffset);
        return true;
      }
      currentRow = null;
    }
    return false;
  }

  @Override
  public int getRowId() {
    return rowId;
  }

  @Override
  public int getVisibleColumnCount() {
    return aliasLabelMap.size();
  }

  @Override
  public int getRowCount() {
    return rowCount;
  }

  private void sendClose() throws IOException {
    if (isClose || session == null) {
      return;
    }
    this.fClient.closeSession(this.session.getSessionId());
    session = null;
  }

  @Override
  public synchronized void close() {
    result = null;
    try {
      sendClose();
      isClose = true;
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  private void remapIfOld() {
    if (session == null) {
      return;
    }
    if (id <= session.getCurrentId()) {
      // object is too old - we need to map it to a new id
      int newId = session.getNextId();
      id = newId;
    }
  }

  private void fetchRows(boolean sendFetch) throws SQLException {
    synchronized (session) {
      rowOffset += result.size();
      result.clear();
      if (isClose) {
        return;
      }
      int fetch = Math.min(fetchSize, rowCount - rowOffset);
      Pair<String, Pair<Boolean, List<ExecuteResult>>> pair = null;
      try {
        if(!isTransaction) {
          if (rowOffset == 0 && rowOffset < fetchSize
              && session.getSessionId() == null) {
            pair = fClient.execute(sql, ReadModel.CURRENT, fetchSize);
            session.setSessionId(pair.getFirst());
          } else if (rowOffset < fetch && session.getSessionId() != null) {
            pair = fClient.next(session.getSessionId());
          } else if (!isExecuteQuery) {
            pair = fClient.execute(sql, session.getSessionId());
          }
        } else {
          if(isExecuteQuery) {
            pair = fClient.execute(sql, ReadModel.CURRENT, fetchSize);
          } else {
            pair = fClient.execute(sqls, session.getSessionId());
          }
        }
      } catch (IOException ioe) {
        if (ioe instanceof ClientConcernedException) {
          ClientConcernedException exception = (ClientConcernedException) ioe;
          throw new SQLException(JdbcException.get(exception.getErrorCode(),
              ioe, ioe.getMessage()));
        }

        log.error("FClinet execute sql error", ioe);
        throw new RuntimeException(ioe);
      }

      // if the query result is null
      if (pair == null) {
        return;
      }

      Pair<Boolean, List<ExecuteResult>> resultPair = pair.getSecond();
      if (resultPair == null) {
        return;
      }

      List<ExecuteResult> executeResults = resultPair.getSecond();

      isLastScan = resultPair.getFirst();

      int effectNums = 0;

      for (ExecuteResult executeResult : executeResults) {
        isQuery = executeResult.isQuery();
        // Query
        if (executeResult.isQuery()) {
          Map<String, Pair<DataType, byte[]>> ret = executeResult.getMap();

          List<Value> values = New.arrayList();

          int i = 0;
          for (Map.Entry<String, Pair<DataType, byte[]>> stringPairEntry : ret
              .entrySet()) {
            String columnLabel = stringPairEntry.getKey();
            if (columnLabel.equalsIgnoreCase("rowkey")) {
              continue;
            }
            if (lableAliasInited == false) {
              mapColumn(aliasLabelMap, columnLabel, i++);
            }
            Pair<DataType, byte[]> typeAndValue = ret.get(columnLabel);
            Value v = Value.toValue(typeAndValue.getSecond(),
                typeAndValue.getFirst());
            values.add(v);
          }
          result.add(values.toArray(new Value[values.size()]));
          lableAliasInited = true;
        } else {
          OperationStatus operationStatus = executeResult.getStatus();

          // write
          if ((FConstants.OperationStatusCode.SUCCESS.name())
              .equals(operationStatus.getOperationStatusCode().name())) {
            effectNums++;
          } else if (((FConstants.OperationStatusCode.FAILURE.name())
              .equals(operationStatus.getOperationStatusCode().name()))) {
            String exceptionClassName = operationStatus.getExceptionClassname();
            String exceptionMsg = operationStatus.getExceptionMsg();

            if (StringUtils.isNullOrEmpty(exceptionClassName)) {
              continue;
            }

            try {
              Class exceptionClazz = Class.forName(exceptionClassName);
              Constructor constructor = exceptionClazz
                  .getConstructor(String.class);
              Object exceptionObject = constructor.newInstance(exceptionMsg);
              if (exceptionObject instanceof ClientConcernedException) {
                ClientConcernedException exception = (ClientConcernedException) exceptionObject;
                throw new SQLException(JdbcException.get(
                    exception.getErrorCode(), exceptionMsg));
              }
            } catch (ClassNotFoundException e) {
              log.error("ClassNotFoundException with Exception class name "
                  + exceptionClassName, e);
              throw new RuntimeException(e);
            } catch (InstantiationException e) {
              log.error("InstantiationException ", e);
              throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
              log.error("IllegalAccessException ", e);
              throw new RuntimeException(e);
            } catch (NoSuchMethodException e) {
              log.error("NoSuchMethodException ", e);
              throw new RuntimeException(e);
            } catch (InvocationTargetException e) {
              log.error("InvocationTargetException ", e);
              throw new RuntimeException(e);
            }
          }
        }
      }

      if (effectNums > 0) {
        Value[] values = new Value[1];
        values[0] = ValueInt.get(effectNums);
        result.clear();
        result.add(values);
      }
      rowCount = result.size();
    }
  }

  @Override
  public String toString() {
    return "columns: " + aliasLabelMap.size() + " rows: " + rowCount + " pos: "
        + rowId;
  }

  @Override
  public int getFetchSize() {
    return fetchSize;
  }

  @Override
  public void setFetchSize(int fetchSize) {
    this.fetchSize = fetchSize;
  }

  @Override
  public String getAlias(int i) {
    if (i > aliasLabelMap.size() - 1) {
      throw new JdbcException("the alias greater than the columns size");
    }
    return aliasLabelMap.get(i);
  }

  @Override
  public String getTableName(int i) {
    return tablename;
  }

  public boolean needToClose() {
    return true;
  }

}
TOP

Related Classes of com.alibaba.wasp.jdbc.result.ResultRemote

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.