Esempio n. 1
0
  @Override
  public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
    // TODO: multi-byte characters
    Expression offsetExpression = getOffsetExpression();
    if (!offsetExpression.evaluate(tuple, ptr)) {
      return false;
    }
    LongNative longNative = (LongNative) offsetExpression.getDataType().getNative();
    int offset = (int) longNative.toLong(ptr);

    int length = -1;
    if (hasLengthExpression) {
      Expression lengthExpression = getLengthExpression();
      if (!lengthExpression.evaluate(tuple, ptr)) {
        return false;
      }
      longNative = (LongNative) lengthExpression.getDataType().getNative();
      length = (int) longNative.toLong(ptr);
      if (length <= 0) {
        return false;
      }
    }

    if (!getStrExpression().evaluate(tuple, ptr)) {
      return false;
    }

    try {
      boolean isCharType = getStrExpression().getDataType() == PDataType.CHAR;
      int strlen =
          isCharType
              ? ptr.getLength()
              : StringUtil.calculateUTF8Length(ptr.get(), ptr.getOffset(), ptr.getLength());

      // Account for 1 versus 0-based offset
      offset = offset - (offset <= 0 ? 0 : 1);
      if (offset < 0) { // Offset < 0 means get from end
        offset = strlen + offset;
      }
      if (offset < 0 || offset >= strlen) {
        return false;
      }
      int maxLength = strlen - offset;
      length = length == -1 ? maxLength : Math.min(length, maxLength);

      int byteOffset =
          isCharType
              ? offset
              : StringUtil.getByteLengthForUtf8SubStr(ptr.get(), ptr.getOffset(), offset);
      int byteLength =
          isCharType
              ? length
              : StringUtil.getByteLengthForUtf8SubStr(
                  ptr.get(), ptr.getOffset() + byteOffset, length);
      ptr.set(ptr.get(), ptr.getOffset() + byteOffset, byteLength);
      return true;
    } catch (UnsupportedEncodingException e) {
      return false;
    }
  }
Esempio n. 2
0
 @Override
 public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
   // Starting from the end of the byte, look for all single bytes at the end of the string
   // that is below SPACE_UTF8 (space and control characters) or above (control chars).
   if (!getStringExpression().evaluate(tuple, ptr)) {
     return false;
   }
   if (ptr.getLength() == 0) {
     ptr.set(ByteUtil.EMPTY_BYTE_ARRAY);
     return true;
   }
   byte[] string = ptr.get();
   int offset = ptr.getOffset();
   int length = ptr.getLength();
   int i = offset + length - 1;
   for (; i >= offset; i--) {
     if ((string[i] & SINGLE_BYTE_MASK) == 0 && SPACE_UTF8 < string[i] && string[i] != 0x7f) {
       break;
     }
   }
   if (i == offset - 1) {
     ptr.set(ByteUtil.EMPTY_BYTE_ARRAY);
     return true;
   }
   ptr.set(string, offset, i - offset + 1);
   return true;
 }
 @Override
 public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
   tuple.getKey(ptr);
   int offset = accessor.getOffset(ptr.get(), ptr.getOffset());
   // Null is represented in the last expression of a multi-part key
   // by the bytes not being present.
   if (offset < ptr.getOffset() + ptr.getLength()) {
     byte[] buffer = ptr.get();
     int maxByteSize = ptr.getLength() - (offset - ptr.getOffset());
     int fixedByteSize = -1;
     // FIXME: fixedByteSize <= maxByteSize ? fixedByteSize : 0 required because HBase passes bogus
     // keys to filter to position scan (HBASE-6562)
     if (fromType.isFixedWidth()) {
       fixedByteSize = getByteSize();
       fixedByteSize = fixedByteSize <= maxByteSize ? fixedByteSize : 0;
     }
     int length =
         fixedByteSize >= 0 ? fixedByteSize : accessor.getLength(buffer, offset, maxByteSize);
     // In the middle of the key, an empty variable length byte array represents null
     if (length > 0) {
       if (type == fromType) {
         ptr.set(buffer, offset, length);
       } else {
         ptr.set(type.toBytes(type.toObject(buffer, offset, length, fromType)));
       }
       return true;
     }
   }
   return false;
 }
Esempio n. 4
0
 public static ProjectedValueTuple mergeProjectedValue(
     ProjectedValueTuple dest,
     KeyValueSchema destSchema,
     ValueBitSet destBitSet,
     Tuple src,
     KeyValueSchema srcSchema,
     ValueBitSet srcBitSet,
     int offset)
     throws IOException {
   ImmutableBytesWritable destValue = new ImmutableBytesWritable(dest.getProjectedValue());
   destBitSet.clear();
   destBitSet.or(destValue);
   int origDestBitSetLen = dest.getBitSetLength();
   ImmutableBytesWritable srcValue = new ImmutableBytesWritable();
   decodeProjectedValue(src, srcValue);
   srcBitSet.clear();
   srcBitSet.or(srcValue);
   int origSrcBitSetLen = srcBitSet.getEstimatedLength();
   for (int i = 0; i < srcBitSet.getMaxSetBit(); i++) {
     if (srcBitSet.get(i)) {
       destBitSet.set(offset + i);
     }
   }
   int destBitSetLen = destBitSet.getEstimatedLength();
   byte[] merged =
       new byte
           [destValue.getLength()
               - origDestBitSetLen
               + srcValue.getLength()
               - origSrcBitSetLen
               + destBitSetLen];
   int o =
       Bytes.putBytes(
           merged,
           0,
           destValue.get(),
           destValue.getOffset(),
           destValue.getLength() - origDestBitSetLen);
   o =
       Bytes.putBytes(
           merged,
           o,
           srcValue.get(),
           srcValue.getOffset(),
           srcValue.getLength() - origSrcBitSetLen);
   destBitSet.toBytes(merged, o);
   ImmutableBytesWritable keyPtr = dest.getKeyPtr();
   return new ProjectedValueTuple(
       keyPtr.get(),
       keyPtr.getOffset(),
       keyPtr.getLength(),
       dest.getTimestamp(),
       merged,
       destBitSetLen);
 }
  @Override
  public void skip(ImmutableBytesWritable bytesWritable) throws IOException {
    if (bytesWritable.getLength() <= 0) return;

    byte[] bytes = bytesWritable.get();
    int offset = bytesWritable.getOffset();
    int len = bytesWritable.getLength();

    RowKeyUtils.seek(
        bytesWritable,
        fixedPrefixLength
            + getBcdEncodedLength(bytes, offset + fixedPrefixLength, len - fixedPrefixLength));
  }
 @Override
 public final Object getValue(Tuple tuple, PDataType type, ImmutableBytesWritable ptr)
     throws SQLException {
   try {
     Expression expression = getExpression();
     if (!expression.evaluate(tuple, ptr)) {
       return null;
     }
     if (ptr.getLength() == 0) {
       return null;
     }
     return type.toObject(
         ptr,
         expression.getDataType(),
         expression.getSortOrder(),
         expression.getMaxLength(),
         expression.getScale());
   } catch (RuntimeException e) {
     // FIXME: Expression.evaluate does not throw SQLException
     // so this will unwrap throws from that.
     if (e.getCause() instanceof SQLException) {
       throw (SQLException) e.getCause();
     }
     throw e;
   }
 }
  @Override
  public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
    BigDecimal result = null;
    for (int i = 0; i < children.size(); i++) {
      Expression childExpr = children.get(i);
      if (!childExpr.evaluate(tuple, ptr)) {
        return false;
      }
      if (ptr.getLength() == 0) {
        return true;
      }

      PDataType childType = children.get(i).getDataType();
      BigDecimal bd = (BigDecimal) PDataType.DECIMAL.toObject(ptr, childType);

      if (result == null) {
        result = bd;
      } else {
        result = result.divide(bd, PDataType.DEFAULT_MATH_CONTEXT);
      }
    }
    if (maxLength != null && scale != null) {
      result = NumberUtil.setDecimalWidthAndScale(result, maxLength, scale);
    }
    if (result == null) {
      throw new ValueTypeIncompatibleException(PDataType.DECIMAL, maxLength, scale);
    }
    ptr.set(PDataType.DECIMAL.toBytes(result));
    return true;
  }
  @Override
  public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
    BigDecimal result = null;
    DateNative dateNative = DateNative.getInstance();
    for (int i = 0; i < children.size(); i++) {
      if (!children.get(i).evaluate(tuple, ptr) || ptr.getLength() == 0) {
        return false;
      }

      PDataType childType = children.get(i).getDataType();
      boolean isDate = childType.isCoercibleTo(PDataType.DATE);
      BigDecimal bd =
          isDate
              ? BigDecimal.valueOf(dateNative.toLong(ptr))
              : (BigDecimal) PDataType.DECIMAL.toObject(ptr, childType);

      if (result == null) {
        result = bd;
      } else {
        result = result.subtract(bd);
        /*
         * Special case for date subtraction - note that only first two expression may be dates.
         * We need to convert the date to a unit of "days" because that's what sql expects.
         */
        if (isDate) {
          result = result.divide(BD_MILLIS_IN_DAY, PDataType.DEFAULT_MATH_CONTEXT);
        }
      }
    }
    ptr.set(PDataType.DECIMAL.toBytes(result));
    return true;
  }
  @Override
  public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
    if (!children.get(0).evaluate(tuple, ptr)) {
      return false;
    }

    String timezone = Bytes.toString(ptr.get(), ptr.getOffset(), ptr.getLength());

    if (!children.get(1).evaluate(tuple, ptr)) {
      return false;
    }

    if (!cachedTimeZones.containsKey(timezone)) {
      TimeZone tz = TimeZone.getTimeZone(timezone);
      if (!tz.getID().equals(timezone)) {
        throw new IllegalDataException("Invalid timezone " + timezone);
      }
      cachedTimeZones.put(timezone, tz);
    }

    Date date = (Date) PDate.INSTANCE.toObject(ptr, children.get(1).getSortOrder());
    int offset = cachedTimeZones.get(timezone).getOffset(date.getTime());

    ptr.set(PInteger.INSTANCE.toBytes(offset / MILLIS_TO_MINUTES));
    return true;
  }
Esempio n. 10
0
 /**
  * Check that none of no columns in our updatable VIEW are changing values.
  *
  * @param tableRef
  * @param overlapViewColumns
  * @param targetColumns
  * @param projector
  * @throws SQLException
  */
 private static void throwIfNotUpdatable(
     TableRef tableRef,
     Set<PColumn> overlapViewColumns,
     List<PColumn> targetColumns,
     RowProjector projector,
     boolean sameTable)
     throws SQLException {
   PTable table = tableRef.getTable();
   if (table.getViewType() == ViewType.UPDATABLE && !overlapViewColumns.isEmpty()) {
     ImmutableBytesWritable ptr = new ImmutableBytesWritable();
     for (int i = 0; i < targetColumns.size(); i++) {
       PColumn targetColumn = targetColumns.get(i);
       if (overlapViewColumns.contains(targetColumn)) {
         Expression source = projector.getColumnProjector(i).getExpression();
         if (source.isStateless()) {
           source.evaluate(null, ptr);
           if (Bytes.compareTo(
                   ptr.get(),
                   ptr.getOffset(),
                   ptr.getLength(),
                   targetColumn.getViewConstant(),
                   0,
                   targetColumn.getViewConstant().length - 1)
               == 0) {
             continue;
           }
         }
         throw new SQLExceptionInfo.Builder(SQLExceptionCode.CANNOT_UPDATE_VIEW_COLUMN)
             .setColumnName(targetColumn.getName().getString())
             .build()
             .buildException();
       }
     }
   }
 }
 @Override
 public void aggregate(Tuple tuple, ImmutableBytesWritable ptr) {
   ImmutableBytesPtr key = new ImmutableBytesPtr(ptr.get(), ptr.getOffset(), ptr.getLength());
   Integer count = this.valueVsCount.get(key);
   if (count == null) {
     this.valueVsCount.put(key, 1);
   } else {
     this.valueVsCount.put(key, count++);
   }
 }
 private void evaluateAndAssertResult(
     Expression expression, Object expectedResult, String context) {
   context = context == null ? "" : context;
   ImmutableBytesWritable ptr = new ImmutableBytesWritable();
   assertTrue(expression.evaluate(null, ptr));
   PDataType dataType = expression.getDataType();
   SortOrder sortOrder = expression.getSortOrder();
   Object result =
       dataType.toObject(ptr.get(), ptr.getOffset(), ptr.getLength(), dataType, sortOrder);
   assertEquals(context, expectedResult, result);
 }
  @Override
  public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
    if (!getChildExpression().evaluate(tuple, ptr)) {
      return false;
    }

    // Update the digest value
    messageDigest.update(ptr.get(), ptr.getOffset(), ptr.getLength());
    // Get the digest bytes (note this resets the messageDigest as well)
    ptr.set(messageDigest.digest());
    return true;
  }
 @Override
 protected int compare(Tuple t1, Tuple t2) {
   for (int i = 0; i < orderByColumns.size(); i++) {
     OrderByExpression order = orderByColumns.get(i);
     Expression orderExpr = order.getExpression();
     boolean isNull1 = !orderExpr.evaluate(t1, ptr1) || ptr1.getLength() == 0;
     boolean isNull2 = !orderExpr.evaluate(t2, ptr2) || ptr2.getLength() == 0;
     if (isNull1 && isNull2) {
       continue;
     } else if (isNull1) {
       return order.isNullsLast() ? 1 : -1;
     } else if (isNull2) {
       return order.isNullsLast() ? -1 : 1;
     }
     int cmp = ptr1.compareTo(ptr2);
     if (cmp == 0) {
       continue;
     }
     return order.isAscending() ? cmp : -cmp;
   }
   return 0;
 }
 private int setStartKey(ImmutableBytesWritable ptr, int offset, int i) {
   int length = ptr.getOffset() - offset;
   startKey = copyKey(startKey, length + this.maxKeyLength, ptr.get(), offset, length);
   startKeyLength = length;
   // Add separator byte if we're at the end of the buffer, since trailing separator bytes are
   // stripped
   if (ptr.getOffset() + ptr.getLength() == offset + length
       && i - 1 > 0
       && !schema.getField(i - 1).getType().isFixedWidth()) {
     startKey[startKeyLength++] = QueryConstants.SEPARATOR_BYTE;
   }
   startKeyLength += setKey(Bound.LOWER, startKey, startKeyLength, i);
   return length;
 }
Esempio n. 16
0
  @Override
  public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
    if (!getStringExpression().evaluate(tuple, ptr)) {
      return false;
    }
    if (ptr.getLength() == 0) {
      ptr.set(ByteUtil.EMPTY_BYTE_ARRAY);
      return true;
    }
    byte[] string = ptr.get();
    int offset = ptr.getOffset();
    int length = ptr.getLength();

    ColumnModifier columnModifier = getColumnModifier();
    int end = StringUtil.getFirstNonBlankCharIdxFromEnd(string, offset, length, columnModifier);
    if (end == offset - 1) {
      ptr.set(ByteUtil.EMPTY_BYTE_ARRAY);
      return true;
    }
    int head = StringUtil.getFirstNonBlankCharIdxFromStart(string, offset, length, columnModifier);
    ptr.set(string, head, end - head + 1);
    return true;
  }
 /**
  * Collect all column values for the same Row. RowKey may be different if indexes are involved, so
  * it writes a separate record for each unique RowKey
  *
  * @param context Current mapper context
  * @param tableName Table index in tableNames list
  * @param lkv List of KV values that will be combined in a single ImmutableBytesWritable
  * @throws IOException
  * @throws InterruptedException
  */
 private void writeAggregatedRow(Context context, String tableName, List<KeyValue> lkv)
     throws IOException, InterruptedException {
   ByteArrayOutputStream bos = new ByteArrayOutputStream(1024);
   DataOutputStream outputStream = new DataOutputStream(bos);
   ImmutableBytesWritable outputKey = null;
   if (!lkv.isEmpty()) {
     for (KeyValue cell : lkv) {
       if (outputKey == null
           || Bytes.compareTo(
                   outputKey.get(),
                   outputKey.getOffset(),
                   outputKey.getLength(),
                   cell.getRowArray(),
                   cell.getRowOffset(),
                   cell.getRowLength())
               != 0) {
         // This a the first RowKey or a different from previous
         if (outputKey != null) { // It's a different RowKey, so we need to write it
           ImmutableBytesWritable aggregatedArray = new ImmutableBytesWritable(bos.toByteArray());
           outputStream.close();
           context.write(new TableRowkeyPair(tableName, outputKey), aggregatedArray);
         }
         outputKey =
             new ImmutableBytesWritable(
                 cell.getRowArray(), cell.getRowOffset(), cell.getRowLength());
         bos = new ByteArrayOutputStream(1024);
         outputStream = new DataOutputStream(bos);
       }
       /*
       The order of aggregation: type, index of column, length of value, value itself
        */
       int i = findIndex(cell);
       if (i == -1) {
         // That may happen when we load only local indexes. Since KV pairs for both
         // table and local index are going to the same physical table at that point
         // we skip those KVs that are not belongs to loca index
         continue;
       }
       outputStream.writeByte(cell.getTypeByte());
       WritableUtils.writeVInt(outputStream, i);
       WritableUtils.writeVInt(outputStream, cell.getValueLength());
       outputStream.write(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength());
     }
     ImmutableBytesWritable aggregatedArray = new ImmutableBytesWritable(bos.toByteArray());
     outputStream.close();
     context.write(new TableRowkeyPair(tableName, outputKey), aggregatedArray);
   }
 }
Esempio n. 18
0
 @Override
 public KeyValue getValue(byte[] family, byte[] qualifier) {
   if (keyValue == null) {
     keyValue =
         KeyValueUtil.newKeyValue(
             keyPtr.get(),
             keyPtr.getOffset(),
             keyPtr.getLength(),
             VALUE_COLUMN_FAMILY,
             VALUE_COLUMN_QUALIFIER,
             timestamp,
             projectedValue,
             0,
             projectedValue.length);
   }
   return keyValue;
 }
Esempio n. 19
0
 @Override
 public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
   Expression arg = getChildren().get(0);
   if (!arg.evaluate(tuple, ptr)) {
     return false;
   }
   if (ptr.getLength() == 0) {
     return true;
   }
   long dateTime = inputCodec.decodeLong(ptr, arg.getSortOrder());
   DateTime jodaDT = new DateTime(dateTime);
   int day = jodaDT.getDayOfYear();
   PDataType returnDataType = getDataType();
   byte[] byteValue = new byte[returnDataType.getByteSize()];
   returnDataType.getCodec().encodeInt(day, byteValue, 0);
   ptr.set(byteValue);
   return true;
 }
  @Override
  public Object deserialize(ImmutableBytesWritable bytesWritable) throws IOException {
    final int length = bytesWritable.getLength();

    if (length <= 0 && fixedPrefixLength == 0) return null;

    final int offset = bytesWritable.getOffset();
    final int variableLengthSuffixOffset = offset + fixedPrefixLength;
    final int variableLengthSuffixLength = length - fixedPrefixLength;

    final byte[] fixedLengthPrefix = decodeFixedPrefix(bytesWritable);

    final byte[] variableLengthSuffix =
        fromStringRepresentation(
            decodeCustomizedReversedPackedBcd(
                bytesWritable, variableLengthSuffixOffset, variableLengthSuffixLength));

    return new BytesWritable(merge(fixedLengthPrefix, variableLengthSuffix));
  }
  @Override
  public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
    BigDecimal result = null;
    for (int i = 0; i < children.size(); i++) {
      if (!children.get(i).evaluate(tuple, ptr) || ptr.getLength() == 0) {
        return false;
      }

      PDataType childType = children.get(i).getDataType();
      BigDecimal bd = (BigDecimal) PDataType.DECIMAL.toObject(ptr, childType);

      if (result == null) {
        result = bd;
      } else {
        result = result.divide(bd, PDataType.DEFAULT_MATH_CONTEXT);
      }
    }
    ptr.set(PDataType.DECIMAL.toBytes(result));
    return true;
  }
Esempio n. 22
0
 private Tuple join(Tuple lhs, Tuple rhs) throws SQLException {
   try {
     ProjectedValueTuple t = null;
     if (lhs == null) {
       t =
           new ProjectedValueTuple(
               rhs,
               rhs.getValue(0).getTimestamp(),
               this.emptyProjectedValue,
               0,
               this.emptyProjectedValue.length,
               this.emptyProjectedValue.length);
     } else if (lhs instanceof ProjectedValueTuple) {
       t = (ProjectedValueTuple) lhs;
     } else {
       ImmutableBytesWritable ptr = context.getTempPtr();
       TupleProjector.decodeProjectedValue(lhs, ptr);
       lhsBitSet.clear();
       lhsBitSet.or(ptr);
       int bitSetLen = lhsBitSet.getEstimatedLength();
       t =
           new ProjectedValueTuple(
               lhs,
               lhs.getValue(0).getTimestamp(),
               ptr.get(),
               ptr.getOffset(),
               ptr.getLength(),
               bitSetLen);
     }
     return rhsBitSet == ValueBitSet.EMPTY_VALUE_BITSET
         ? t
         : TupleProjector.mergeProjectedValue(
             t, joinedSchema, destBitSet, rhs, rhsSchema, rhsBitSet, rhsFieldPosition);
   } catch (IOException e) {
     throw new SQLException(e);
   }
 }
  @Override
  public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
    BigDecimal finalResult = BigDecimal.ZERO;

    for (int i = 0; i < children.size(); i++) {
      if (!children.get(i).evaluate(tuple, ptr)) {
        return false;
      }
      if (ptr.getLength() == 0) {
        return true;
      }
      BigDecimal value;
      PDataType type = children.get(i).getDataType();
      ColumnModifier columnModifier = children.get(i).getColumnModifier();
      if (type == PDataType.TIMESTAMP || type == PDataType.UNSIGNED_TIMESTAMP) {
        value = (BigDecimal) (PDataType.DECIMAL.toObject(ptr, type, columnModifier));
      } else if (type.isCoercibleTo(PDataType.DECIMAL)) {
        value =
            (((BigDecimal) PDataType.DECIMAL.toObject(ptr, columnModifier))
                    .multiply(QueryConstants.BD_MILLIS_IN_DAY))
                .setScale(6, RoundingMode.HALF_UP);
      } else if (type.isCoercibleTo(PDataType.DOUBLE)) {
        value =
            ((BigDecimal.valueOf(type.getCodec().decodeDouble(ptr, columnModifier)))
                    .multiply(QueryConstants.BD_MILLIS_IN_DAY))
                .setScale(6, RoundingMode.HALF_UP);
      } else {
        value = BigDecimal.valueOf(type.getCodec().decodeLong(ptr, columnModifier));
      }
      finalResult = finalResult.add(value);
    }
    Timestamp ts = DateUtil.getTimestamp(finalResult);
    byte[] resultPtr = new byte[getDataType().getByteSize()];
    PDataType.TIMESTAMP.toBytes(ts, resultPtr, 0);
    ptr.set(resultPtr);
    return true;
  }
Esempio n. 24
0
 public static KeyValue newKeyValue(
     ImmutableBytesWritable key,
     byte[] cf,
     byte[] cq,
     long ts,
     byte[] value,
     int valueOffset,
     int valueLength) {
   return new KeyValue(
       key.get(),
       key.getOffset(),
       key.getLength(),
       cf,
       0,
       cf.length,
       cq,
       0,
       cq.length,
       ts,
       Type.Put,
       value,
       valueOffset,
       valueLength);
 }
Esempio n. 25
0
 public void set(JoinKey other) {
   for (int i = 0; i < keys.size(); i++) {
     ImmutableBytesWritable key = other.keys.get(i);
     this.keys.get(i).set(key.get(), key.getOffset(), key.getLength());
   }
 }
Esempio n. 26
0
  public ServerCache addServerCache(
      ScanRanges keyRanges,
      final ImmutableBytesWritable cachePtr,
      final byte[] txState,
      final ServerCacheFactory cacheFactory,
      final TableRef cacheUsingTableRef)
      throws SQLException {
    ConnectionQueryServices services = connection.getQueryServices();
    MemoryChunk chunk = services.getMemoryManager().allocate(cachePtr.getLength());
    List<Closeable> closeables = new ArrayList<Closeable>();
    closeables.add(chunk);
    ServerCache hashCacheSpec = null;
    SQLException firstException = null;
    final byte[] cacheId = generateId();
    /** Execute EndPoint in parallel on each server to send compressed hash cache */
    // TODO: generalize and package as a per region server EndPoint caller
    // (ideally this would be functionality provided by the coprocessor framework)
    boolean success = false;
    ExecutorService executor = services.getExecutor();
    List<Future<Boolean>> futures = Collections.emptyList();
    try {
      final PTable cacheUsingTable = cacheUsingTableRef.getTable();
      List<HRegionLocation> locations =
          services.getAllTableRegions(cacheUsingTable.getPhysicalName().getBytes());
      int nRegions = locations.size();
      // Size these based on worst case
      futures = new ArrayList<Future<Boolean>>(nRegions);
      Set<HRegionLocation> servers = new HashSet<HRegionLocation>(nRegions);
      for (HRegionLocation entry : locations) {
        // Keep track of servers we've sent to and only send once
        byte[] regionStartKey = entry.getRegionInfo().getStartKey();
        byte[] regionEndKey = entry.getRegionInfo().getEndKey();
        if (!servers.contains(entry)
            && keyRanges.intersects(
                regionStartKey,
                regionEndKey,
                cacheUsingTable.getIndexType() == IndexType.LOCAL
                    ? ScanUtil.getRowKeyOffset(regionStartKey, regionEndKey)
                    : 0,
                true)) {
          // Call RPC once per server
          servers.add(entry);
          if (LOG.isDebugEnabled()) {
            LOG.debug(
                addCustomAnnotations("Adding cache entry to be sent for " + entry, connection));
          }
          final byte[] key = entry.getRegionInfo().getStartKey();
          final HTableInterface htable =
              services.getTable(cacheUsingTableRef.getTable().getPhysicalName().getBytes());
          closeables.add(htable);
          futures.add(
              executor.submit(
                  new JobCallable<Boolean>() {

                    @Override
                    public Boolean call() throws Exception {
                      final Map<byte[], AddServerCacheResponse> results;
                      try {
                        results =
                            htable.coprocessorService(
                                ServerCachingService.class,
                                key,
                                key,
                                new Batch.Call<ServerCachingService, AddServerCacheResponse>() {
                                  @Override
                                  public AddServerCacheResponse call(ServerCachingService instance)
                                      throws IOException {
                                    ServerRpcController controller = new ServerRpcController();
                                    BlockingRpcCallback<AddServerCacheResponse> rpcCallback =
                                        new BlockingRpcCallback<AddServerCacheResponse>();
                                    AddServerCacheRequest.Builder builder =
                                        AddServerCacheRequest.newBuilder();
                                    if (connection.getTenantId() != null) {
                                      try {
                                        byte[] tenantIdBytes =
                                            ScanUtil.getTenantIdBytes(
                                                cacheUsingTable.getRowKeySchema(),
                                                cacheUsingTable.getBucketNum() != null,
                                                connection.getTenantId(),
                                                cacheUsingTable.isMultiTenant());
                                        builder.setTenantId(ByteStringer.wrap(tenantIdBytes));
                                      } catch (SQLException e) {
                                        new IOException(e);
                                      }
                                    }
                                    builder.setCacheId(ByteStringer.wrap(cacheId));
                                    builder.setCachePtr(
                                        org.apache.phoenix.protobuf.ProtobufUtil.toProto(cachePtr));
                                    ServerCacheFactoryProtos.ServerCacheFactory.Builder
                                        svrCacheFactoryBuider =
                                            ServerCacheFactoryProtos.ServerCacheFactory
                                                .newBuilder();
                                    svrCacheFactoryBuider.setClassName(
                                        cacheFactory.getClass().getName());
                                    builder.setCacheFactory(svrCacheFactoryBuider.build());
                                    builder.setTxState(HBaseZeroCopyByteString.wrap(txState));
                                    instance.addServerCache(
                                        controller, builder.build(), rpcCallback);
                                    if (controller.getFailedOn() != null) {
                                      throw controller.getFailedOn();
                                    }
                                    return rpcCallback.get();
                                  }
                                });
                      } catch (Throwable t) {
                        throw new Exception(t);
                      }
                      if (results != null && results.size() == 1) {
                        return results.values().iterator().next().getReturn();
                      }
                      return false;
                    }

                    /**
                     * Defines the grouping for round robin behavior. All threads spawned to process
                     * this scan will be grouped together and time sliced with other simultaneously
                     * executing parallel scans.
                     */
                    @Override
                    public Object getJobId() {
                      return ServerCacheClient.this;
                    }

                    @Override
                    public TaskExecutionMetricsHolder getTaskExecutionMetric() {
                      return NO_OP_INSTANCE;
                    }
                  }));
        } else {
          if (LOG.isDebugEnabled()) {
            LOG.debug(
                addCustomAnnotations(
                    "NOT adding cache entry to be sent for "
                        + entry
                        + " since one already exists for that entry",
                    connection));
          }
        }
      }

      hashCacheSpec = new ServerCache(cacheId, servers, cachePtr.getLength());
      // Execute in parallel
      int timeoutMs =
          services
              .getProps()
              .getInt(
                  QueryServices.THREAD_TIMEOUT_MS_ATTRIB,
                  QueryServicesOptions.DEFAULT_THREAD_TIMEOUT_MS);
      for (Future<Boolean> future : futures) {
        future.get(timeoutMs, TimeUnit.MILLISECONDS);
      }

      cacheUsingTableRefMap.put(Bytes.mapKey(cacheId), cacheUsingTableRef);
      success = true;
    } catch (SQLException e) {
      firstException = e;
    } catch (Exception e) {
      firstException = new SQLException(e);
    } finally {
      try {
        if (!success) {
          SQLCloseables.closeAllQuietly(Collections.singletonList(hashCacheSpec));
          for (Future<Boolean> future : futures) {
            future.cancel(true);
          }
        }
      } finally {
        try {
          Closeables.closeAll(closeables);
        } catch (IOException e) {
          if (firstException == null) {
            firstException = new SQLException(e);
          }
        } finally {
          if (firstException != null) {
            throw firstException;
          }
        }
      }
    }
    if (LOG.isDebugEnabled()) {
      LOG.debug(
          addCustomAnnotations("Cache " + cacheId + " successfully added to servers.", connection));
    }
    return hashCacheSpec;
  }
Esempio n. 27
0
 @Override
 public void getKey(ImmutableBytesWritable ptr) {
   ptr.set(keyPtr.get(), keyPtr.getOffset(), keyPtr.getLength());
 }