You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kylin.apache.org by ga...@apache.org on 2017/02/12 01:35:06 UTC

[1/2] kylin git commit: KYLIN-2443 Report coprocessor error information back to client

Repository: kylin
Updated Branches:
  refs/heads/master 707b05598 -> 43c056672


http://git-wip-us.apache.org/repos/asf/kylin/blob/43c05667/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/coprocessor/endpoint/generated/CubeVisitProtos.java
----------------------------------------------------------------------
diff --git a/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/coprocessor/endpoint/generated/CubeVisitProtos.java b/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/coprocessor/endpoint/generated/CubeVisitProtos.java
index 4b6fc95..b9f2771 100644
--- a/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/coprocessor/endpoint/generated/CubeVisitProtos.java
+++ b/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/coprocessor/endpoint/generated/CubeVisitProtos.java
@@ -121,10 +121,18 @@ public final class CubeVisitProtos {
     // optional int64 maxScanBytes = 8;
     /**
      * <code>optional int64 maxScanBytes = 8;</code>
+     *
+     * <pre>
+     * 0 means no limit
+     * </pre>
      */
     boolean hasMaxScanBytes();
     /**
      * <code>optional int64 maxScanBytes = 8;</code>
+     *
+     * <pre>
+     * 0 means no limit
+     * </pre>
      */
     long getMaxScanBytes();
   }
@@ -972,12 +980,20 @@ public final class CubeVisitProtos {
     private long maxScanBytes_;
     /**
      * <code>optional int64 maxScanBytes = 8;</code>
+     *
+     * <pre>
+     * 0 means no limit
+     * </pre>
      */
     public boolean hasMaxScanBytes() {
       return ((bitField0_ & 0x00000040) == 0x00000040);
     }
     /**
      * <code>optional int64 maxScanBytes = 8;</code>
+     *
+     * <pre>
+     * 0 means no limit
+     * </pre>
      */
     public long getMaxScanBytes() {
       return maxScanBytes_;
@@ -2050,18 +2066,30 @@ public final class CubeVisitProtos {
       private long maxScanBytes_ ;
       /**
        * <code>optional int64 maxScanBytes = 8;</code>
+       *
+       * <pre>
+       * 0 means no limit
+       * </pre>
        */
       public boolean hasMaxScanBytes() {
         return ((bitField0_ & 0x00000080) == 0x00000080);
       }
       /**
        * <code>optional int64 maxScanBytes = 8;</code>
+       *
+       * <pre>
+       * 0 means no limit
+       * </pre>
        */
       public long getMaxScanBytes() {
         return maxScanBytes_;
       }
       /**
        * <code>optional int64 maxScanBytes = 8;</code>
+       *
+       * <pre>
+       * 0 means no limit
+       * </pre>
        */
       public Builder setMaxScanBytes(long value) {
         bitField0_ |= 0x00000080;
@@ -2071,6 +2099,10 @@ public final class CubeVisitProtos {
       }
       /**
        * <code>optional int64 maxScanBytes = 8;</code>
+       *
+       * <pre>
+       * 0 means no limit
+       * </pre>
        */
       public Builder clearMaxScanBytes() {
         bitField0_ = (bitField0_ & ~0x00000080);
@@ -2116,6 +2148,32 @@ public final class CubeVisitProtos {
      * <code>required .CubeVisitResponse.Stats stats = 2;</code>
      */
     org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.StatsOrBuilder getStatsOrBuilder();
+
+    // optional .CubeVisitResponse.ErrorInfo errorInfo = 3;
+    /**
+     * <code>optional .CubeVisitResponse.ErrorInfo errorInfo = 3;</code>
+     *
+     * <pre>
+     * should be set when stats.normalComplete == false
+     * </pre>
+     */
+    boolean hasErrorInfo();
+    /**
+     * <code>optional .CubeVisitResponse.ErrorInfo errorInfo = 3;</code>
+     *
+     * <pre>
+     * should be set when stats.normalComplete == false
+     * </pre>
+     */
+    org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo getErrorInfo();
+    /**
+     * <code>optional .CubeVisitResponse.ErrorInfo errorInfo = 3;</code>
+     *
+     * <pre>
+     * should be set when stats.normalComplete == false
+     * </pre>
+     */
+    org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfoOrBuilder getErrorInfoOrBuilder();
   }
   /**
    * Protobuf type {@code CubeVisitResponse}
@@ -2186,6 +2244,19 @@ public final class CubeVisitProtos {
               bitField0_ |= 0x00000002;
               break;
             }
+            case 26: {
+              org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo.Builder subBuilder = null;
+              if (((bitField0_ & 0x00000004) == 0x00000004)) {
+                subBuilder = errorInfo_.toBuilder();
+              }
+              errorInfo_ = input.readMessage(org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo.PARSER, extensionRegistry);
+              if (subBuilder != null) {
+                subBuilder.mergeFrom(errorInfo_);
+                errorInfo_ = subBuilder.buildPartial();
+              }
+              bitField0_ |= 0x00000004;
+              break;
+            }
           }
         }
       } catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -2225,6 +2296,97 @@ public final class CubeVisitProtos {
       return PARSER;
     }
 
+    /**
+     * Protobuf enum {@code CubeVisitResponse.ErrorType}
+     */
+    public enum ErrorType
+        implements com.google.protobuf.ProtocolMessageEnum {
+      /**
+       * <code>UNKNOWN_TYPE = 0;</code>
+       */
+      UNKNOWN_TYPE(0, 0),
+      /**
+       * <code>TIMEOUT = 1;</code>
+       */
+      TIMEOUT(1, 1),
+      /**
+       * <code>RESOURCE_LIMIT_EXCEEDED = 2;</code>
+       */
+      RESOURCE_LIMIT_EXCEEDED(2, 2),
+      ;
+
+      /**
+       * <code>UNKNOWN_TYPE = 0;</code>
+       */
+      public static final int UNKNOWN_TYPE_VALUE = 0;
+      /**
+       * <code>TIMEOUT = 1;</code>
+       */
+      public static final int TIMEOUT_VALUE = 1;
+      /**
+       * <code>RESOURCE_LIMIT_EXCEEDED = 2;</code>
+       */
+      public static final int RESOURCE_LIMIT_EXCEEDED_VALUE = 2;
+
+
+      public final int getNumber() { return value; }
+
+      public static ErrorType valueOf(int value) {
+        switch (value) {
+          case 0: return UNKNOWN_TYPE;
+          case 1: return TIMEOUT;
+          case 2: return RESOURCE_LIMIT_EXCEEDED;
+          default: return null;
+        }
+      }
+
+      public static com.google.protobuf.Internal.EnumLiteMap<ErrorType>
+          internalGetValueMap() {
+        return internalValueMap;
+      }
+      private static com.google.protobuf.Internal.EnumLiteMap<ErrorType>
+          internalValueMap =
+            new com.google.protobuf.Internal.EnumLiteMap<ErrorType>() {
+              public ErrorType findValueByNumber(int number) {
+                return ErrorType.valueOf(number);
+              }
+            };
+
+      public final com.google.protobuf.Descriptors.EnumValueDescriptor
+          getValueDescriptor() {
+        return getDescriptor().getValues().get(index);
+      }
+      public final com.google.protobuf.Descriptors.EnumDescriptor
+          getDescriptorForType() {
+        return getDescriptor();
+      }
+      public static final com.google.protobuf.Descriptors.EnumDescriptor
+          getDescriptor() {
+        return org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.getDescriptor().getEnumTypes().get(0);
+      }
+
+      private static final ErrorType[] VALUES = values();
+
+      public static ErrorType valueOf(
+          com.google.protobuf.Descriptors.EnumValueDescriptor desc) {
+        if (desc.getType() != getDescriptor()) {
+          throw new java.lang.IllegalArgumentException(
+            "EnumValueDescriptor is not for this type.");
+        }
+        return VALUES[desc.getIndex()];
+      }
+
+      private final int index;
+      private final int value;
+
+      private ErrorType(int index, int value) {
+        this.index = index;
+        this.value = value;
+      }
+
+      // @@protoc_insertion_point(enum_scope:CubeVisitResponse.ErrorType)
+    }
+
     public interface StatsOrBuilder
         extends com.google.protobuf.MessageOrBuilder {
 
@@ -2331,18 +2493,10 @@ public final class CubeVisitProtos {
       // optional int32 normalComplete = 10;
       /**
        * <code>optional int32 normalComplete = 10;</code>
-       *
-       * <pre>
-       *when time outs, normalComplete will be false
-       * </pre>
        */
       boolean hasNormalComplete();
       /**
        * <code>optional int32 normalComplete = 10;</code>
-       *
-       * <pre>
-       *when time outs, normalComplete will be false
-       * </pre>
        */
       int getNormalComplete();
 
@@ -2705,20 +2859,12 @@ public final class CubeVisitProtos {
       private int normalComplete_;
       /**
        * <code>optional int32 normalComplete = 10;</code>
-       *
-       * <pre>
-       *when time outs, normalComplete will be false
-       * </pre>
        */
       public boolean hasNormalComplete() {
         return ((bitField0_ & 0x00000200) == 0x00000200);
       }
       /**
        * <code>optional int32 normalComplete = 10;</code>
-       *
-       * <pre>
-       *when time outs, normalComplete will be false
-       * </pre>
        */
       public int getNormalComplete() {
         return normalComplete_;
@@ -3652,30 +3798,18 @@ public final class CubeVisitProtos {
         private int normalComplete_ ;
         /**
          * <code>optional int32 normalComplete = 10;</code>
-         *
-         * <pre>
-         *when time outs, normalComplete will be false
-         * </pre>
          */
         public boolean hasNormalComplete() {
           return ((bitField0_ & 0x00000200) == 0x00000200);
         }
         /**
          * <code>optional int32 normalComplete = 10;</code>
-         *
-         * <pre>
-         *when time outs, normalComplete will be false
-         * </pre>
          */
         public int getNormalComplete() {
           return normalComplete_;
         }
         /**
          * <code>optional int32 normalComplete = 10;</code>
-         *
-         * <pre>
-         *when time outs, normalComplete will be false
-         * </pre>
          */
         public Builder setNormalComplete(int value) {
           bitField0_ |= 0x00000200;
@@ -3685,10 +3819,6 @@ public final class CubeVisitProtos {
         }
         /**
          * <code>optional int32 normalComplete = 10;</code>
-         *
-         * <pre>
-         *when time outs, normalComplete will be false
-         * </pre>
          */
         public Builder clearNormalComplete() {
           bitField0_ = (bitField0_ & ~0x00000200);
@@ -3741,99 +3871,771 @@ public final class CubeVisitProtos {
       // @@protoc_insertion_point(class_scope:CubeVisitResponse.Stats)
     }
 
-    private int bitField0_;
-    // required bytes compressedRows = 1;
-    public static final int COMPRESSEDROWS_FIELD_NUMBER = 1;
-    private com.google.protobuf.ByteString compressedRows_;
-    /**
-     * <code>required bytes compressedRows = 1;</code>
-     */
-    public boolean hasCompressedRows() {
-      return ((bitField0_ & 0x00000001) == 0x00000001);
-    }
-    /**
-     * <code>required bytes compressedRows = 1;</code>
-     */
-    public com.google.protobuf.ByteString getCompressedRows() {
-      return compressedRows_;
-    }
+    public interface ErrorInfoOrBuilder
+        extends com.google.protobuf.MessageOrBuilder {
 
-    // required .CubeVisitResponse.Stats stats = 2;
-    public static final int STATS_FIELD_NUMBER = 2;
-    private org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.Stats stats_;
-    /**
-     * <code>required .CubeVisitResponse.Stats stats = 2;</code>
-     */
-    public boolean hasStats() {
-      return ((bitField0_ & 0x00000002) == 0x00000002);
-    }
-    /**
-     * <code>required .CubeVisitResponse.Stats stats = 2;</code>
-     */
-    public org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.Stats getStats() {
-      return stats_;
+      // required .CubeVisitResponse.ErrorType type = 1;
+      /**
+       * <code>required .CubeVisitResponse.ErrorType type = 1;</code>
+       */
+      boolean hasType();
+      /**
+       * <code>required .CubeVisitResponse.ErrorType type = 1;</code>
+       */
+      org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorType getType();
+
+      // required string message = 2;
+      /**
+       * <code>required string message = 2;</code>
+       */
+      boolean hasMessage();
+      /**
+       * <code>required string message = 2;</code>
+       */
+      java.lang.String getMessage();
+      /**
+       * <code>required string message = 2;</code>
+       */
+      com.google.protobuf.ByteString
+          getMessageBytes();
     }
     /**
-     * <code>required .CubeVisitResponse.Stats stats = 2;</code>
+     * Protobuf type {@code CubeVisitResponse.ErrorInfo}
      */
-    public org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.StatsOrBuilder getStatsOrBuilder() {
-      return stats_;
-    }
-
-    private void initFields() {
-      compressedRows_ = com.google.protobuf.ByteString.EMPTY;
-      stats_ = org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.Stats.getDefaultInstance();
-    }
-    private byte memoizedIsInitialized = -1;
-    public final boolean isInitialized() {
-      byte isInitialized = memoizedIsInitialized;
-      if (isInitialized != -1) return isInitialized == 1;
+    public static final class ErrorInfo extends
+        com.google.protobuf.GeneratedMessage
+        implements ErrorInfoOrBuilder {
+      // Use ErrorInfo.newBuilder() to construct.
+      private ErrorInfo(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+        super(builder);
+        this.unknownFields = builder.getUnknownFields();
+      }
+      private ErrorInfo(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
 
-      if (!hasCompressedRows()) {
-        memoizedIsInitialized = 0;
-        return false;
+      private static final ErrorInfo defaultInstance;
+      public static ErrorInfo getDefaultInstance() {
+        return defaultInstance;
       }
-      if (!hasStats()) {
-        memoizedIsInitialized = 0;
-        return false;
+
+      public ErrorInfo getDefaultInstanceForType() {
+        return defaultInstance;
       }
-      memoizedIsInitialized = 1;
-      return true;
-    }
 
-    public void writeTo(com.google.protobuf.CodedOutputStream output)
-                        throws java.io.IOException {
-      getSerializedSize();
-      if (((bitField0_ & 0x00000001) == 0x00000001)) {
-        output.writeBytes(1, compressedRows_);
+      private final com.google.protobuf.UnknownFieldSet unknownFields;
+      @java.lang.Override
+      public final com.google.protobuf.UnknownFieldSet
+          getUnknownFields() {
+        return this.unknownFields;
       }
-      if (((bitField0_ & 0x00000002) == 0x00000002)) {
-        output.writeMessage(2, stats_);
+      private ErrorInfo(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        initFields();
+        int mutable_bitField0_ = 0;
+        com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+            com.google.protobuf.UnknownFieldSet.newBuilder();
+        try {
+          boolean done = false;
+          while (!done) {
+            int tag = input.readTag();
+            switch (tag) {
+              case 0:
+                done = true;
+                break;
+              default: {
+                if (!parseUnknownField(input, unknownFields,
+                                       extensionRegistry, tag)) {
+                  done = true;
+                }
+                break;
+              }
+              case 8: {
+                int rawValue = input.readEnum();
+                org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorType value = org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorType.valueOf(rawValue);
+                if (value == null) {
+                  unknownFields.mergeVarintField(1, rawValue);
+                } else {
+                  bitField0_ |= 0x00000001;
+                  type_ = value;
+                }
+                break;
+              }
+              case 18: {
+                bitField0_ |= 0x00000002;
+                message_ = input.readBytes();
+                break;
+              }
+            }
+          }
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          throw e.setUnfinishedMessage(this);
+        } catch (java.io.IOException e) {
+          throw new com.google.protobuf.InvalidProtocolBufferException(
+              e.getMessage()).setUnfinishedMessage(this);
+        } finally {
+          this.unknownFields = unknownFields.build();
+          makeExtensionsImmutable();
+        }
+      }
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.internal_static_CubeVisitResponse_ErrorInfo_descriptor;
       }
-      getUnknownFields().writeTo(output);
-    }
-
-    private int memoizedSerializedSize = -1;
-    public int getSerializedSize() {
-      int size = memoizedSerializedSize;
-      if (size != -1) return size;
 
-      size = 0;
-      if (((bitField0_ & 0x00000001) == 0x00000001)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeBytesSize(1, compressedRows_);
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.internal_static_CubeVisitResponse_ErrorInfo_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo.class, org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo.Builder.class);
       }
-      if (((bitField0_ & 0x00000002) == 0x00000002)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(2, stats_);
+
+      public static com.google.protobuf.Parser<ErrorInfo> PARSER =
+          new com.google.protobuf.AbstractParser<ErrorInfo>() {
+        public ErrorInfo parsePartialFrom(
+            com.google.protobuf.CodedInputStream input,
+            com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+            throws com.google.protobuf.InvalidProtocolBufferException {
+          return new ErrorInfo(input, extensionRegistry);
+        }
+      };
+
+      @java.lang.Override
+      public com.google.protobuf.Parser<ErrorInfo> getParserForType() {
+        return PARSER;
       }
-      size += getUnknownFields().getSerializedSize();
-      memoizedSerializedSize = size;
-      return size;
-    }
 
-    private static final long serialVersionUID = 0L;
-    @java.lang.Override
+      private int bitField0_;
+      // required .CubeVisitResponse.ErrorType type = 1;
+      public static final int TYPE_FIELD_NUMBER = 1;
+      private org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorType type_;
+      /**
+       * <code>required .CubeVisitResponse.ErrorType type = 1;</code>
+       */
+      public boolean hasType() {
+        return ((bitField0_ & 0x00000001) == 0x00000001);
+      }
+      /**
+       * <code>required .CubeVisitResponse.ErrorType type = 1;</code>
+       */
+      public org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorType getType() {
+        return type_;
+      }
+
+      // required string message = 2;
+      public static final int MESSAGE_FIELD_NUMBER = 2;
+      private java.lang.Object message_;
+      /**
+       * <code>required string message = 2;</code>
+       */
+      public boolean hasMessage() {
+        return ((bitField0_ & 0x00000002) == 0x00000002);
+      }
+      /**
+       * <code>required string message = 2;</code>
+       */
+      public java.lang.String getMessage() {
+        java.lang.Object ref = message_;
+        if (ref instanceof java.lang.String) {
+          return (java.lang.String) ref;
+        } else {
+          com.google.protobuf.ByteString bs = 
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          if (bs.isValidUtf8()) {
+            message_ = s;
+          }
+          return s;
+        }
+      }
+      /**
+       * <code>required string message = 2;</code>
+       */
+      public com.google.protobuf.ByteString
+          getMessageBytes() {
+        java.lang.Object ref = message_;
+        if (ref instanceof java.lang.String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          message_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+
+      private void initFields() {
+        type_ = org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorType.UNKNOWN_TYPE;
+        message_ = "";
+      }
+      private byte memoizedIsInitialized = -1;
+      public final boolean isInitialized() {
+        byte isInitialized = memoizedIsInitialized;
+        if (isInitialized != -1) return isInitialized == 1;
+
+        if (!hasType()) {
+          memoizedIsInitialized = 0;
+          return false;
+        }
+        if (!hasMessage()) {
+          memoizedIsInitialized = 0;
+          return false;
+        }
+        memoizedIsInitialized = 1;
+        return true;
+      }
+
+      public void writeTo(com.google.protobuf.CodedOutputStream output)
+                          throws java.io.IOException {
+        getSerializedSize();
+        if (((bitField0_ & 0x00000001) == 0x00000001)) {
+          output.writeEnum(1, type_.getNumber());
+        }
+        if (((bitField0_ & 0x00000002) == 0x00000002)) {
+          output.writeBytes(2, getMessageBytes());
+        }
+        getUnknownFields().writeTo(output);
+      }
+
+      private int memoizedSerializedSize = -1;
+      public int getSerializedSize() {
+        int size = memoizedSerializedSize;
+        if (size != -1) return size;
+
+        size = 0;
+        if (((bitField0_ & 0x00000001) == 0x00000001)) {
+          size += com.google.protobuf.CodedOutputStream
+            .computeEnumSize(1, type_.getNumber());
+        }
+        if (((bitField0_ & 0x00000002) == 0x00000002)) {
+          size += com.google.protobuf.CodedOutputStream
+            .computeBytesSize(2, getMessageBytes());
+        }
+        size += getUnknownFields().getSerializedSize();
+        memoizedSerializedSize = size;
+        return size;
+      }
+
+      private static final long serialVersionUID = 0L;
+      @java.lang.Override
+      protected java.lang.Object writeReplace()
+          throws java.io.ObjectStreamException {
+        return super.writeReplace();
+      }
+
+      @java.lang.Override
+      public boolean equals(final java.lang.Object obj) {
+        if (obj == this) {
+         return true;
+        }
+        if (!(obj instanceof org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo)) {
+          return super.equals(obj);
+        }
+        org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo other = (org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo) obj;
+
+        boolean result = true;
+        result = result && (hasType() == other.hasType());
+        if (hasType()) {
+          result = result &&
+              (getType() == other.getType());
+        }
+        result = result && (hasMessage() == other.hasMessage());
+        if (hasMessage()) {
+          result = result && getMessage()
+              .equals(other.getMessage());
+        }
+        result = result &&
+            getUnknownFields().equals(other.getUnknownFields());
+        return result;
+      }
+
+      private int memoizedHashCode = 0;
+      @java.lang.Override
+      public int hashCode() {
+        if (memoizedHashCode != 0) {
+          return memoizedHashCode;
+        }
+        int hash = 41;
+        hash = (19 * hash) + getDescriptorForType().hashCode();
+        if (hasType()) {
+          hash = (37 * hash) + TYPE_FIELD_NUMBER;
+          hash = (53 * hash) + hashEnum(getType());
+        }
+        if (hasMessage()) {
+          hash = (37 * hash) + MESSAGE_FIELD_NUMBER;
+          hash = (53 * hash) + getMessage().hashCode();
+        }
+        hash = (29 * hash) + getUnknownFields().hashCode();
+        memoizedHashCode = hash;
+        return hash;
+      }
+
+      public static org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo parseFrom(
+          com.google.protobuf.ByteString data)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return PARSER.parseFrom(data);
+      }
+      public static org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo parseFrom(
+          com.google.protobuf.ByteString data,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return PARSER.parseFrom(data, extensionRegistry);
+      }
+      public static org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo parseFrom(byte[] data)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return PARSER.parseFrom(data);
+      }
+      public static org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo parseFrom(
+          byte[] data,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return PARSER.parseFrom(data, extensionRegistry);
+      }
+      public static org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo parseFrom(java.io.InputStream input)
+          throws java.io.IOException {
+        return PARSER.parseFrom(input);
+      }
+      public static org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo parseFrom(
+          java.io.InputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        return PARSER.parseFrom(input, extensionRegistry);
+      }
+      public static org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo parseDelimitedFrom(java.io.InputStream input)
+          throws java.io.IOException {
+        return PARSER.parseDelimitedFrom(input);
+      }
+      public static org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo parseDelimitedFrom(
+          java.io.InputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        return PARSER.parseDelimitedFrom(input, extensionRegistry);
+      }
+      public static org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo parseFrom(
+          com.google.protobuf.CodedInputStream input)
+          throws java.io.IOException {
+        return PARSER.parseFrom(input);
+      }
+      public static org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo parseFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        return PARSER.parseFrom(input, extensionRegistry);
+      }
+
+      public static Builder newBuilder() { return Builder.create(); }
+      public Builder newBuilderForType() { return newBuilder(); }
+      public static Builder newBuilder(org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo prototype) {
+        return newBuilder().mergeFrom(prototype);
+      }
+      public Builder toBuilder() { return newBuilder(this); }
+
+      @java.lang.Override
+      protected Builder newBuilderForType(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        Builder builder = new Builder(parent);
+        return builder;
+      }
+      /**
+       * Protobuf type {@code CubeVisitResponse.ErrorInfo}
+       */
+      public static final class Builder extends
+          com.google.protobuf.GeneratedMessage.Builder<Builder>
+         implements org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfoOrBuilder {
+        public static final com.google.protobuf.Descriptors.Descriptor
+            getDescriptor() {
+          return org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.internal_static_CubeVisitResponse_ErrorInfo_descriptor;
+        }
+
+        protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+            internalGetFieldAccessorTable() {
+          return org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.internal_static_CubeVisitResponse_ErrorInfo_fieldAccessorTable
+              .ensureFieldAccessorsInitialized(
+                  org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo.class, org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo.Builder.class);
+        }
+
+        // Construct using org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo.newBuilder()
+        private Builder() {
+          maybeForceBuilderInitialization();
+        }
+
+        private Builder(
+            com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+          super(parent);
+          maybeForceBuilderInitialization();
+        }
+        private void maybeForceBuilderInitialization() {
+          if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+          }
+        }
+        private static Builder create() {
+          return new Builder();
+        }
+
+        public Builder clear() {
+          super.clear();
+          type_ = org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorType.UNKNOWN_TYPE;
+          bitField0_ = (bitField0_ & ~0x00000001);
+          message_ = "";
+          bitField0_ = (bitField0_ & ~0x00000002);
+          return this;
+        }
+
+        public Builder clone() {
+          return create().mergeFrom(buildPartial());
+        }
+
+        public com.google.protobuf.Descriptors.Descriptor
+            getDescriptorForType() {
+          return org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.internal_static_CubeVisitResponse_ErrorInfo_descriptor;
+        }
+
+        public org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo getDefaultInstanceForType() {
+          return org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo.getDefaultInstance();
+        }
+
+        public org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo build() {
+          org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo result = buildPartial();
+          if (!result.isInitialized()) {
+            throw newUninitializedMessageException(result);
+          }
+          return result;
+        }
+
+        public org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo buildPartial() {
+          org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo result = new org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo(this);
+          int from_bitField0_ = bitField0_;
+          int to_bitField0_ = 0;
+          if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+            to_bitField0_ |= 0x00000001;
+          }
+          result.type_ = type_;
+          if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+            to_bitField0_ |= 0x00000002;
+          }
+          result.message_ = message_;
+          result.bitField0_ = to_bitField0_;
+          onBuilt();
+          return result;
+        }
+
+        public Builder mergeFrom(com.google.protobuf.Message other) {
+          if (other instanceof org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo) {
+            return mergeFrom((org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo)other);
+          } else {
+            super.mergeFrom(other);
+            return this;
+          }
+        }
+
+        public Builder mergeFrom(org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo other) {
+          if (other == org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo.getDefaultInstance()) return this;
+          if (other.hasType()) {
+            setType(other.getType());
+          }
+          if (other.hasMessage()) {
+            bitField0_ |= 0x00000002;
+            message_ = other.message_;
+            onChanged();
+          }
+          this.mergeUnknownFields(other.getUnknownFields());
+          return this;
+        }
+
+        public final boolean isInitialized() {
+          if (!hasType()) {
+            
+            return false;
+          }
+          if (!hasMessage()) {
+            
+            return false;
+          }
+          return true;
+        }
+
+        public Builder mergeFrom(
+            com.google.protobuf.CodedInputStream input,
+            com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+            throws java.io.IOException {
+          org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo parsedMessage = null;
+          try {
+            parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+          } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+            parsedMessage = (org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo) e.getUnfinishedMessage();
+            throw e;
+          } finally {
+            if (parsedMessage != null) {
+              mergeFrom(parsedMessage);
+            }
+          }
+          return this;
+        }
+        private int bitField0_;
+
+        // required .CubeVisitResponse.ErrorType type = 1;
+        private org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorType type_ = org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorType.UNKNOWN_TYPE;
+        /**
+         * <code>required .CubeVisitResponse.ErrorType type = 1;</code>
+         */
+        public boolean hasType() {
+          return ((bitField0_ & 0x00000001) == 0x00000001);
+        }
+        /**
+         * <code>required .CubeVisitResponse.ErrorType type = 1;</code>
+         */
+        public org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorType getType() {
+          return type_;
+        }
+        /**
+         * <code>required .CubeVisitResponse.ErrorType type = 1;</code>
+         */
+        public Builder setType(org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorType value) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          bitField0_ |= 0x00000001;
+          type_ = value;
+          onChanged();
+          return this;
+        }
+        /**
+         * <code>required .CubeVisitResponse.ErrorType type = 1;</code>
+         */
+        public Builder clearType() {
+          bitField0_ = (bitField0_ & ~0x00000001);
+          type_ = org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorType.UNKNOWN_TYPE;
+          onChanged();
+          return this;
+        }
+
+        // required string message = 2;
+        private java.lang.Object message_ = "";
+        /**
+         * <code>required string message = 2;</code>
+         */
+        public boolean hasMessage() {
+          return ((bitField0_ & 0x00000002) == 0x00000002);
+        }
+        /**
+         * <code>required string message = 2;</code>
+         */
+        public java.lang.String getMessage() {
+          java.lang.Object ref = message_;
+          if (!(ref instanceof java.lang.String)) {
+            java.lang.String s = ((com.google.protobuf.ByteString) ref)
+                .toStringUtf8();
+            message_ = s;
+            return s;
+          } else {
+            return (java.lang.String) ref;
+          }
+        }
+        /**
+         * <code>required string message = 2;</code>
+         */
+        public com.google.protobuf.ByteString
+            getMessageBytes() {
+          java.lang.Object ref = message_;
+          if (ref instanceof String) {
+            com.google.protobuf.ByteString b = 
+                com.google.protobuf.ByteString.copyFromUtf8(
+                    (java.lang.String) ref);
+            message_ = b;
+            return b;
+          } else {
+            return (com.google.protobuf.ByteString) ref;
+          }
+        }
+        /**
+         * <code>required string message = 2;</code>
+         */
+        public Builder setMessage(
+            java.lang.String value) {
+          if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000002;
+          message_ = value;
+          onChanged();
+          return this;
+        }
+        /**
+         * <code>required string message = 2;</code>
+         */
+        public Builder clearMessage() {
+          bitField0_ = (bitField0_ & ~0x00000002);
+          message_ = getDefaultInstance().getMessage();
+          onChanged();
+          return this;
+        }
+        /**
+         * <code>required string message = 2;</code>
+         */
+        public Builder setMessageBytes(
+            com.google.protobuf.ByteString value) {
+          if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000002;
+          message_ = value;
+          onChanged();
+          return this;
+        }
+
+        // @@protoc_insertion_point(builder_scope:CubeVisitResponse.ErrorInfo)
+      }
+
+      static {
+        defaultInstance = new ErrorInfo(true);
+        defaultInstance.initFields();
+      }
+
+      // @@protoc_insertion_point(class_scope:CubeVisitResponse.ErrorInfo)
+    }
+
+    private int bitField0_;
+    // required bytes compressedRows = 1;
+    public static final int COMPRESSEDROWS_FIELD_NUMBER = 1;
+    private com.google.protobuf.ByteString compressedRows_;
+    /**
+     * <code>required bytes compressedRows = 1;</code>
+     */
+    public boolean hasCompressedRows() {
+      return ((bitField0_ & 0x00000001) == 0x00000001);
+    }
+    /**
+     * <code>required bytes compressedRows = 1;</code>
+     */
+    public com.google.protobuf.ByteString getCompressedRows() {
+      return compressedRows_;
+    }
+
+    // required .CubeVisitResponse.Stats stats = 2;
+    public static final int STATS_FIELD_NUMBER = 2;
+    private org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.Stats stats_;
+    /**
+     * <code>required .CubeVisitResponse.Stats stats = 2;</code>
+     */
+    public boolean hasStats() {
+      return ((bitField0_ & 0x00000002) == 0x00000002);
+    }
+    /**
+     * <code>required .CubeVisitResponse.Stats stats = 2;</code>
+     */
+    public org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.Stats getStats() {
+      return stats_;
+    }
+    /**
+     * <code>required .CubeVisitResponse.Stats stats = 2;</code>
+     */
+    public org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.StatsOrBuilder getStatsOrBuilder() {
+      return stats_;
+    }
+
+    // optional .CubeVisitResponse.ErrorInfo errorInfo = 3;
+    public static final int ERRORINFO_FIELD_NUMBER = 3;
+    private org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo errorInfo_;
+    /**
+     * <code>optional .CubeVisitResponse.ErrorInfo errorInfo = 3;</code>
+     *
+     * <pre>
+     * should be set when stats.normalComplete == false
+     * </pre>
+     */
+    public boolean hasErrorInfo() {
+      return ((bitField0_ & 0x00000004) == 0x00000004);
+    }
+    /**
+     * <code>optional .CubeVisitResponse.ErrorInfo errorInfo = 3;</code>
+     *
+     * <pre>
+     * should be set when stats.normalComplete == false
+     * </pre>
+     */
+    public org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo getErrorInfo() {
+      return errorInfo_;
+    }
+    /**
+     * <code>optional .CubeVisitResponse.ErrorInfo errorInfo = 3;</code>
+     *
+     * <pre>
+     * should be set when stats.normalComplete == false
+     * </pre>
+     */
+    public org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfoOrBuilder getErrorInfoOrBuilder() {
+      return errorInfo_;
+    }
+
+    private void initFields() {
+      compressedRows_ = com.google.protobuf.ByteString.EMPTY;
+      stats_ = org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.Stats.getDefaultInstance();
+      errorInfo_ = org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo.getDefaultInstance();
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized != -1) return isInitialized == 1;
+
+      if (!hasCompressedRows()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      if (!hasStats()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      if (hasErrorInfo()) {
+        if (!getErrorInfo().isInitialized()) {
+          memoizedIsInitialized = 0;
+          return false;
+        }
+      }
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        output.writeBytes(1, compressedRows_);
+      }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        output.writeMessage(2, stats_);
+      }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        output.writeMessage(3, errorInfo_);
+      }
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(1, compressedRows_);
+      }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeMessageSize(2, stats_);
+      }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeMessageSize(3, errorInfo_);
+      }
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
     protected java.lang.Object writeReplace()
         throws java.io.ObjectStreamException {
       return super.writeReplace();
@@ -3860,6 +4662,11 @@ public final class CubeVisitProtos {
         result = result && getStats()
             .equals(other.getStats());
       }
+      result = result && (hasErrorInfo() == other.hasErrorInfo());
+      if (hasErrorInfo()) {
+        result = result && getErrorInfo()
+            .equals(other.getErrorInfo());
+      }
       result = result &&
           getUnknownFields().equals(other.getUnknownFields());
       return result;
@@ -3881,6 +4688,10 @@ public final class CubeVisitProtos {
         hash = (37 * hash) + STATS_FIELD_NUMBER;
         hash = (53 * hash) + getStats().hashCode();
       }
+      if (hasErrorInfo()) {
+        hash = (37 * hash) + ERRORINFO_FIELD_NUMBER;
+        hash = (53 * hash) + getErrorInfo().hashCode();
+      }
       hash = (29 * hash) + getUnknownFields().hashCode();
       memoizedHashCode = hash;
       return hash;
@@ -3983,6 +4794,7 @@ public final class CubeVisitProtos {
       private void maybeForceBuilderInitialization() {
         if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
           getStatsFieldBuilder();
+          getErrorInfoFieldBuilder();
         }
       }
       private static Builder create() {
@@ -3999,6 +4811,12 @@ public final class CubeVisitProtos {
           statsBuilder_.clear();
         }
         bitField0_ = (bitField0_ & ~0x00000002);
+        if (errorInfoBuilder_ == null) {
+          errorInfo_ = org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo.getDefaultInstance();
+        } else {
+          errorInfoBuilder_.clear();
+        }
+        bitField0_ = (bitField0_ & ~0x00000004);
         return this;
       }
 
@@ -4039,6 +4857,14 @@ public final class CubeVisitProtos {
         } else {
           result.stats_ = statsBuilder_.build();
         }
+        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+          to_bitField0_ |= 0x00000004;
+        }
+        if (errorInfoBuilder_ == null) {
+          result.errorInfo_ = errorInfo_;
+        } else {
+          result.errorInfo_ = errorInfoBuilder_.build();
+        }
         result.bitField0_ = to_bitField0_;
         onBuilt();
         return result;
@@ -4061,6 +4887,9 @@ public final class CubeVisitProtos {
         if (other.hasStats()) {
           mergeStats(other.getStats());
         }
+        if (other.hasErrorInfo()) {
+          mergeErrorInfo(other.getErrorInfo());
+        }
         this.mergeUnknownFields(other.getUnknownFields());
         return this;
       }
@@ -4074,6 +4903,12 @@ public final class CubeVisitProtos {
           
           return false;
         }
+        if (hasErrorInfo()) {
+          if (!getErrorInfo().isInitialized()) {
+            
+            return false;
+          }
+        }
         return true;
       }
 
@@ -4249,6 +5084,159 @@ public final class CubeVisitProtos {
         return statsBuilder_;
       }
 
+      // optional .CubeVisitResponse.ErrorInfo errorInfo = 3;
+      private org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo errorInfo_ = org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo.getDefaultInstance();
+      private com.google.protobuf.SingleFieldBuilder<
+          org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo, org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo.Builder, org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfoOrBuilder> errorInfoBuilder_;
+      /**
+       * <code>optional .CubeVisitResponse.ErrorInfo errorInfo = 3;</code>
+       *
+       * <pre>
+       * should be set when stats.normalComplete == false
+       * </pre>
+       */
+      public boolean hasErrorInfo() {
+        return ((bitField0_ & 0x00000004) == 0x00000004);
+      }
+      /**
+       * <code>optional .CubeVisitResponse.ErrorInfo errorInfo = 3;</code>
+       *
+       * <pre>
+       * should be set when stats.normalComplete == false
+       * </pre>
+       */
+      public org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo getErrorInfo() {
+        if (errorInfoBuilder_ == null) {
+          return errorInfo_;
+        } else {
+          return errorInfoBuilder_.getMessage();
+        }
+      }
+      /**
+       * <code>optional .CubeVisitResponse.ErrorInfo errorInfo = 3;</code>
+       *
+       * <pre>
+       * should be set when stats.normalComplete == false
+       * </pre>
+       */
+      public Builder setErrorInfo(org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo value) {
+        if (errorInfoBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          errorInfo_ = value;
+          onChanged();
+        } else {
+          errorInfoBuilder_.setMessage(value);
+        }
+        bitField0_ |= 0x00000004;
+        return this;
+      }
+      /**
+       * <code>optional .CubeVisitResponse.ErrorInfo errorInfo = 3;</code>
+       *
+       * <pre>
+       * should be set when stats.normalComplete == false
+       * </pre>
+       */
+      public Builder setErrorInfo(
+          org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo.Builder builderForValue) {
+        if (errorInfoBuilder_ == null) {
+          errorInfo_ = builderForValue.build();
+          onChanged();
+        } else {
+          errorInfoBuilder_.setMessage(builderForValue.build());
+        }
+        bitField0_ |= 0x00000004;
+        return this;
+      }
+      /**
+       * <code>optional .CubeVisitResponse.ErrorInfo errorInfo = 3;</code>
+       *
+       * <pre>
+       * should be set when stats.normalComplete == false
+       * </pre>
+       */
+      public Builder mergeErrorInfo(org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo value) {
+        if (errorInfoBuilder_ == null) {
+          if (((bitField0_ & 0x00000004) == 0x00000004) &&
+              errorInfo_ != org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo.getDefaultInstance()) {
+            errorInfo_ =
+              org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo.newBuilder(errorInfo_).mergeFrom(value).buildPartial();
+          } else {
+            errorInfo_ = value;
+          }
+          onChanged();
+        } else {
+          errorInfoBuilder_.mergeFrom(value);
+        }
+        bitField0_ |= 0x00000004;
+        return this;
+      }
+      /**
+       * <code>optional .CubeVisitResponse.ErrorInfo errorInfo = 3;</code>
+       *
+       * <pre>
+       * should be set when stats.normalComplete == false
+       * </pre>
+       */
+      public Builder clearErrorInfo() {
+        if (errorInfoBuilder_ == null) {
+          errorInfo_ = org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo.getDefaultInstance();
+          onChanged();
+        } else {
+          errorInfoBuilder_.clear();
+        }
+        bitField0_ = (bitField0_ & ~0x00000004);
+        return this;
+      }
+      /**
+       * <code>optional .CubeVisitResponse.ErrorInfo errorInfo = 3;</code>
+       *
+       * <pre>
+       * should be set when stats.normalComplete == false
+       * </pre>
+       */
+      public org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo.Builder getErrorInfoBuilder() {
+        bitField0_ |= 0x00000004;
+        onChanged();
+        return getErrorInfoFieldBuilder().getBuilder();
+      }
+      /**
+       * <code>optional .CubeVisitResponse.ErrorInfo errorInfo = 3;</code>
+       *
+       * <pre>
+       * should be set when stats.normalComplete == false
+       * </pre>
+       */
+      public org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfoOrBuilder getErrorInfoOrBuilder() {
+        if (errorInfoBuilder_ != null) {
+          return errorInfoBuilder_.getMessageOrBuilder();
+        } else {
+          return errorInfo_;
+        }
+      }
+      /**
+       * <code>optional .CubeVisitResponse.ErrorInfo errorInfo = 3;</code>
+       *
+       * <pre>
+       * should be set when stats.normalComplete == false
+       * </pre>
+       */
+      private com.google.protobuf.SingleFieldBuilder<
+          org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo, org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo.Builder, org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfoOrBuilder> 
+          getErrorInfoFieldBuilder() {
+        if (errorInfoBuilder_ == null) {
+          errorInfoBuilder_ = new com.google.protobuf.SingleFieldBuilder<
+              org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo, org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfo.Builder, org.apache.kylin.storage.hbase.cube.v2.coprocessor.endpoint.generated.CubeVisitProtos.CubeVisitResponse.ErrorInfoOrBuilder>(
+                  errorInfo_,
+                  getParentForChildren(),
+                  isClean());
+          errorInfo_ = null;
+        }
+        return errorInfoBuilder_;
+      }
+
       // @@protoc_insertion_point(builder_scope:CubeVisitResponse)
     }
 
@@ -4512,6 +5500,11 @@ public final class CubeVisitProtos {
   private static
     com.google.protobuf.GeneratedMessage.FieldAccessorTable
       internal_static_CubeVisitResponse_Stats_fieldAccessorTable;
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_CubeVisitResponse_ErrorInfo_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_CubeVisitResponse_ErrorInfo_fieldAccessorTable;
 
   public static com.google.protobuf.Descriptors.FileDescriptor
       getDescriptor() {
@@ -4530,20 +5523,25 @@ public final class CubeVisitProtos {
       "eVisitRequest.IntList\022\027\n\017kylinProperties" +
       "\030\005 \002(\t\022\017\n\007queryId\030\006 \001(\t\022\032\n\014spillEnabled\030" +
       "\007 \001(\010:\004true\022\024\n\014maxScanBytes\030\010 \001(\003\032\027\n\007Int" +
-      "List\022\014\n\004ints\030\001 \003(\005\"\347\002\n\021CubeVisitResponse",
+      "List\022\014\n\004ints\030\001 \003(\005\"\253\004\n\021CubeVisitResponse",
       "\022\026\n\016compressedRows\030\001 \002(\014\022\'\n\005stats\030\002 \002(\0132" +
-      "\030.CubeVisitResponse.Stats\032\220\002\n\005Stats\022\030\n\020s" +
-      "erviceStartTime\030\001 \001(\003\022\026\n\016serviceEndTime\030" +
-      "\002 \001(\003\022\027\n\017scannedRowCount\030\003 \001(\003\022\032\n\022aggreg" +
-      "atedRowCount\030\004 \001(\003\022\025\n\rsystemCpuLoad\030\005 \001(" +
-      "\001\022\036\n\026freePhysicalMemorySize\030\006 \001(\001\022\031\n\021fre" +
-      "eSwapSpaceSize\030\007 \001(\001\022\020\n\010hostname\030\010 \001(\t\022\016" +
-      "\n\006etcMsg\030\t \001(\t\022\026\n\016normalComplete\030\n \001(\005\022\024" +
-      "\n\014scannedBytes\030\013 \001(\0032F\n\020CubeVisitService" +
-      "\0222\n\tvisitCube\022\021.CubeVisitRequest\032\022.CubeV",
-      "isitResponseB`\nEorg.apache.kylin.storage" +
-      ".hbase.cube.v2.coprocessor.endpoint.gene" +
-      "ratedB\017CubeVisitProtosH\001\210\001\001\240\001\001"
+      "\030.CubeVisitResponse.Stats\022/\n\terrorInfo\030\003" +
+      " \001(\0132\034.CubeVisitResponse.ErrorInfo\032\220\002\n\005S" +
+      "tats\022\030\n\020serviceStartTime\030\001 \001(\003\022\026\n\016servic" +
+      "eEndTime\030\002 \001(\003\022\027\n\017scannedRowCount\030\003 \001(\003\022" +
+      "\032\n\022aggregatedRowCount\030\004 \001(\003\022\025\n\rsystemCpu" +
+      "Load\030\005 \001(\001\022\036\n\026freePhysicalMemorySize\030\006 \001" +
+      "(\001\022\031\n\021freeSwapSpaceSize\030\007 \001(\001\022\020\n\010hostnam" +
+      "e\030\010 \001(\t\022\016\n\006etcMsg\030\t \001(\t\022\026\n\016normalComplet" +
+      "e\030\n \001(\005\022\024\n\014scannedBytes\030\013 \001(\003\032H\n\tErrorIn",
+      "fo\022*\n\004type\030\001 \002(\0162\034.CubeVisitResponse.Err" +
+      "orType\022\017\n\007message\030\002 \002(\t\"G\n\tErrorType\022\020\n\014" +
+      "UNKNOWN_TYPE\020\000\022\013\n\007TIMEOUT\020\001\022\033\n\027RESOURCE_" +
+      "LIMIT_EXCEEDED\020\0022F\n\020CubeVisitService\0222\n\t" +
+      "visitCube\022\021.CubeVisitRequest\032\022.CubeVisit" +
+      "ResponseB`\nEorg.apache.kylin.storage.hba" +
+      "se.cube.v2.coprocessor.endpoint.generate" +
+      "dB\017CubeVisitProtosH\001\210\001\001\240\001\001"
     };
     com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
       new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
@@ -4567,13 +5565,19 @@ public final class CubeVisitProtos {
           internal_static_CubeVisitResponse_fieldAccessorTable = new
             com.google.protobuf.GeneratedMessage.FieldAccessorTable(
               internal_static_CubeVisitResponse_descriptor,
-              new java.lang.String[] { "CompressedRows", "Stats", });
+              new java.lang.String[] { "CompressedRows", "Stats", "ErrorInfo", });
           internal_static_CubeVisitResponse_Stats_descriptor =
             internal_static_CubeVisitResponse_descriptor.getNestedTypes().get(0);
           internal_static_CubeVisitResponse_Stats_fieldAccessorTable = new
             com.google.protobuf.GeneratedMessage.FieldAccessorTable(
               internal_static_CubeVisitResponse_Stats_descriptor,
               new java.lang.String[] { "ServiceStartTime", "ServiceEndTime", "ScannedRowCount", "AggregatedRowCount", "SystemCpuLoad", "FreePhysicalMemorySize", "FreeSwapSpaceSize", "Hostname", "EtcMsg", "NormalComplete", "ScannedBytes", });
+          internal_static_CubeVisitResponse_ErrorInfo_descriptor =
+            internal_static_CubeVisitResponse_descriptor.getNestedTypes().get(1);
+          internal_static_CubeVisitResponse_ErrorInfo_fieldAccessorTable = new
+            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+              internal_static_CubeVisitResponse_ErrorInfo_descriptor,
+              new java.lang.String[] { "Type", "Message", });
           return null;
         }
       };

http://git-wip-us.apache.org/repos/asf/kylin/blob/43c05667/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/coprocessor/endpoint/protobuf/CubeVisit.proto
----------------------------------------------------------------------
diff --git a/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/coprocessor/endpoint/protobuf/CubeVisit.proto b/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/coprocessor/endpoint/protobuf/CubeVisit.proto
index 00015fc..e01ff52 100644
--- a/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/coprocessor/endpoint/protobuf/CubeVisit.proto
+++ b/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/coprocessor/endpoint/protobuf/CubeVisit.proto
@@ -54,11 +54,21 @@ message CubeVisitResponse {
         optional double freeSwapSpaceSize = 7;
         optional string hostname = 8;
         optional string etcMsg = 9;
-        optional int32 normalComplete =10;//when time outs, normalComplete will be false
+        optional int32 normalComplete =10;
         optional int64 scannedBytes = 11;
     }
+    enum ErrorType {
+        UNKNOWN_TYPE = 0;
+        TIMEOUT = 1;
+        RESOURCE_LIMIT_EXCEEDED = 2;
+    }
+    message ErrorInfo {
+        required ErrorType type = 1;
+        required string message = 2;
+    }
     required bytes compressedRows = 1;
     required Stats stats = 2;
+    optional ErrorInfo errorInfo = 3; // should be set when stats.normalComplete == false
 }
 
 service CubeVisitService {


[2/2] kylin git commit: KYLIN-2443 Report coprocessor error information back to client

Posted by ga...@apache.org.
KYLIN-2443 Report coprocessor error information back to client


Project: http://git-wip-us.apache.org/repos/asf/kylin/repo
Commit: http://git-wip-us.apache.org/repos/asf/kylin/commit/43c05667
Tree: http://git-wip-us.apache.org/repos/asf/kylin/tree/43c05667
Diff: http://git-wip-us.apache.org/repos/asf/kylin/diff/43c05667

Branch: refs/heads/master
Commit: 43c0566728092d537201d751d3e8f6e3c0d5f051
Parents: 707b055
Author: gaodayue <ga...@meituan.com>
Authored: Sat Feb 11 19:13:24 2017 +0800
Committer: gaodayue <ga...@meituan.com>
Committed: Sun Feb 12 09:34:49 2017 +0800

----------------------------------------------------------------------
 build/smoke-test/sql/sql1.json                  |    1 -
 build/smoke-test/testQuery.py                   |    1 +
 .../org/apache/kylin/common/QueryContext.java   |   21 +-
 .../exceptions/KylinTimeoutException.java       |   26 +
 .../ResourceLimitExceededException.java         |   30 +
 .../kylin/gridtable/GTAggregateScanner.java     |   12 +-
 .../GTScanExceedThresholdException.java         |   26 -
 .../GTScanSelfTerminatedException.java          |   30 -
 .../kylin/gridtable/GTScanTimeoutException.java |   26 -
 .../apache/kylin/storage/StorageContext.java    |   19 +-
 .../storage/gtrecord/CubeSegmentScanner.java    |    2 +-
 .../kylin/storage/gtrecord/ScannerWorker.java   |    5 +-
 .../gtrecord/SequentialCubeTupleIterator.java   |    6 +-
 .../apache/kylin/query/ITKylinQueryTest.java    |    6 +-
 .../apache/kylin/rest/service/QueryService.java |   28 +-
 .../hbase/cube/v2/CubeHBaseEndpointRPC.java     |   69 +-
 .../storage/hbase/cube/v2/CubeHBaseRPC.java     |    8 +-
 .../storage/hbase/cube/v2/CubeHBaseScanRPC.java |   15 +-
 .../coprocessor/endpoint/CubeVisitService.java  |   42 +-
 .../endpoint/generated/CubeVisitProtos.java     | 1254 ++++++++++++++++--
 .../endpoint/protobuf/CubeVisit.proto           |   12 +-
 21 files changed, 1331 insertions(+), 308 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/kylin/blob/43c05667/build/smoke-test/sql/sql1.json
----------------------------------------------------------------------
diff --git a/build/smoke-test/sql/sql1.json b/build/smoke-test/sql/sql1.json
index 7cb3258..21e4c01 100644
--- a/build/smoke-test/sql/sql1.json
+++ b/build/smoke-test/sql/sql1.json
@@ -9,7 +9,6 @@
     ]
   ],
   "exceptionMessage": null,
-  "totalScanCount": 1,
   "columnMetas": [
     {
       "scale": 0,

http://git-wip-us.apache.org/repos/asf/kylin/blob/43c05667/build/smoke-test/testQuery.py
----------------------------------------------------------------------
diff --git a/build/smoke-test/testQuery.py b/build/smoke-test/testQuery.py
index 87a2456..99c09d3 100644
--- a/build/smoke-test/testQuery.py
+++ b/build/smoke-test/testQuery.py
@@ -59,6 +59,7 @@ class testQuery(unittest.TestCase):
             del actual_result['duration']
             del actual_result['hitExceptionCache']
             del actual_result['storageCacheUsed']
+            del actual_result['totalScanCount']
             del actual_result['totalScanBytes']
 
             expect_result = json.loads(open(sql_file[:-4] + '.json').read().strip())

http://git-wip-us.apache.org/repos/asf/kylin/blob/43c05667/core-common/src/main/java/org/apache/kylin/common/QueryContext.java
----------------------------------------------------------------------
diff --git a/core-common/src/main/java/org/apache/kylin/common/QueryContext.java b/core-common/src/main/java/org/apache/kylin/common/QueryContext.java
index 3a73993..67925b6 100644
--- a/core-common/src/main/java/org/apache/kylin/common/QueryContext.java
+++ b/core-common/src/main/java/org/apache/kylin/common/QueryContext.java
@@ -21,7 +21,7 @@ package org.apache.kylin.common;
 import java.util.concurrent.atomic.AtomicLong;
 
 /**
- * checkout {@link org.apache.kylin.common.debug.BackdoorToggles} for comparison
+ * Holds per query information and statistics.
  */
 public class QueryContext {
 
@@ -33,7 +33,8 @@ public class QueryContext {
     };
 
     private String queryId;
-    private AtomicLong scanBytes = new AtomicLong();
+    private AtomicLong scannedRows = new AtomicLong();
+    private AtomicLong scannedBytes = new AtomicLong();
 
     private QueryContext() {
         // use QueryContext.current() instead
@@ -55,11 +56,19 @@ public class QueryContext {
         this.queryId = queryId;
     }
 
-    public long getScanBytes() {
-        return scanBytes.get();
+    public long getScannedRows() {
+        return scannedRows.get();
     }
 
-    public long addAndGetScanBytes(long delta) {
-        return scanBytes.addAndGet(delta);
+    public long addAndGetScannedRows(long deltaRows) {
+        return scannedRows.addAndGet(deltaRows);
+    }
+
+    public long getScannedBytes() {
+        return scannedBytes.get();
+    }
+
+    public long addAndGetScannedBytes(long deltaBytes) {
+        return scannedBytes.addAndGet(deltaBytes);
     }
 }

http://git-wip-us.apache.org/repos/asf/kylin/blob/43c05667/core-common/src/main/java/org/apache/kylin/common/exceptions/KylinTimeoutException.java
----------------------------------------------------------------------
diff --git a/core-common/src/main/java/org/apache/kylin/common/exceptions/KylinTimeoutException.java b/core-common/src/main/java/org/apache/kylin/common/exceptions/KylinTimeoutException.java
new file mode 100644
index 0000000..75d981f
--- /dev/null
+++ b/core-common/src/main/java/org/apache/kylin/common/exceptions/KylinTimeoutException.java
@@ -0,0 +1,26 @@
+/*
+ * 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.kylin.common.exceptions;
+
+public class KylinTimeoutException extends RuntimeException {
+
+    public KylinTimeoutException(String message) {
+        super(message);
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/43c05667/core-common/src/main/java/org/apache/kylin/common/exceptions/ResourceLimitExceededException.java
----------------------------------------------------------------------
diff --git a/core-common/src/main/java/org/apache/kylin/common/exceptions/ResourceLimitExceededException.java b/core-common/src/main/java/org/apache/kylin/common/exceptions/ResourceLimitExceededException.java
new file mode 100644
index 0000000..df5d88e
--- /dev/null
+++ b/core-common/src/main/java/org/apache/kylin/common/exceptions/ResourceLimitExceededException.java
@@ -0,0 +1,30 @@
+/*
+ * 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.kylin.common.exceptions;
+
+public class ResourceLimitExceededException extends RuntimeException {
+
+    public ResourceLimitExceededException(String message) {
+        super(message);
+    }
+
+    public ResourceLimitExceededException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/43c05667/core-cube/src/main/java/org/apache/kylin/gridtable/GTAggregateScanner.java
----------------------------------------------------------------------
diff --git a/core-cube/src/main/java/org/apache/kylin/gridtable/GTAggregateScanner.java b/core-cube/src/main/java/org/apache/kylin/gridtable/GTAggregateScanner.java
index dd359f8..8b0efcc 100644
--- a/core-cube/src/main/java/org/apache/kylin/gridtable/GTAggregateScanner.java
+++ b/core-cube/src/main/java/org/apache/kylin/gridtable/GTAggregateScanner.java
@@ -35,6 +35,7 @@ import java.util.SortedMap;
 import java.util.Map.Entry;
 
 import org.apache.commons.io.IOUtils;
+import org.apache.kylin.common.exceptions.ResourceLimitExceededException;
 import org.apache.kylin.common.util.ByteArray;
 import org.apache.kylin.common.util.Bytes;
 import org.apache.kylin.common.util.ImmutableBitSet;
@@ -278,14 +279,11 @@ public class GTAggregateScanner implements IGTScanner {
 
                 final long estMemSize = estimatedMemSize();
                 if (spillThreshold > 0 && estMemSize > spillThreshold) {
-                    // spill to disk when aggBufMap used too large memory
-                    if (spillEnabled) {
-                        spillBuffMap(estMemSize);
-                        aggBufMap = createBuffMap();
-
-                    } else {
-                        throw new GTScanSelfTerminatedException("Aggregation using more than " + spillThreshold + " memory and spill is disabled");
+                    if (!spillEnabled) {
+                        throw new ResourceLimitExceededException("aggregation's memory consumption " + estMemSize + " exceeds threshold " + spillThreshold);
                     }
+                    spillBuffMap(estMemSize); // spill to disk
+                    aggBufMap = createBuffMap();
                 }
             }
 

http://git-wip-us.apache.org/repos/asf/kylin/blob/43c05667/core-cube/src/main/java/org/apache/kylin/gridtable/GTScanExceedThresholdException.java
----------------------------------------------------------------------
diff --git a/core-cube/src/main/java/org/apache/kylin/gridtable/GTScanExceedThresholdException.java b/core-cube/src/main/java/org/apache/kylin/gridtable/GTScanExceedThresholdException.java
deleted file mode 100644
index ba75962..0000000
--- a/core-cube/src/main/java/org/apache/kylin/gridtable/GTScanExceedThresholdException.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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.kylin.gridtable;
-
-public class GTScanExceedThresholdException extends GTScanSelfTerminatedException {
-
-    public GTScanExceedThresholdException(String message) {
-        super(message);
-    }
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/43c05667/core-cube/src/main/java/org/apache/kylin/gridtable/GTScanSelfTerminatedException.java
----------------------------------------------------------------------
diff --git a/core-cube/src/main/java/org/apache/kylin/gridtable/GTScanSelfTerminatedException.java b/core-cube/src/main/java/org/apache/kylin/gridtable/GTScanSelfTerminatedException.java
deleted file mode 100644
index 30d3aaa..0000000
--- a/core-cube/src/main/java/org/apache/kylin/gridtable/GTScanSelfTerminatedException.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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.kylin.gridtable;
-
-/**
- * Implementations of {@link IGTScanner} should throw {@link GTScanSelfTerminatedException} or its subclasses
- * in cases where the scan runs out of resources (time, memory, etc) and can not be continued.
- */
-public class GTScanSelfTerminatedException extends RuntimeException {
-
-    public GTScanSelfTerminatedException(String s) {
-        super(s);
-    }
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/43c05667/core-cube/src/main/java/org/apache/kylin/gridtable/GTScanTimeoutException.java
----------------------------------------------------------------------
diff --git a/core-cube/src/main/java/org/apache/kylin/gridtable/GTScanTimeoutException.java b/core-cube/src/main/java/org/apache/kylin/gridtable/GTScanTimeoutException.java
deleted file mode 100644
index 17a8d02..0000000
--- a/core-cube/src/main/java/org/apache/kylin/gridtable/GTScanTimeoutException.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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.kylin.gridtable;
-
-public class GTScanTimeoutException extends GTScanSelfTerminatedException {
-
-    public GTScanTimeoutException(String message) {
-        super(message);
-    }
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/43c05667/core-storage/src/main/java/org/apache/kylin/storage/StorageContext.java
----------------------------------------------------------------------
diff --git a/core-storage/src/main/java/org/apache/kylin/storage/StorageContext.java b/core-storage/src/main/java/org/apache/kylin/storage/StorageContext.java
index 0f52c53..4713d71 100644
--- a/core-storage/src/main/java/org/apache/kylin/storage/StorageContext.java
+++ b/core-storage/src/main/java/org/apache/kylin/storage/StorageContext.java
@@ -47,8 +47,7 @@ public class StorageContext {
     private boolean enableCoprocessor = false;
 
     private IStorageQuery storageQuery;
-    private AtomicLong totalScanCount = new AtomicLong();
-    private AtomicLong totalScanBytes = new AtomicLong();
+    private AtomicLong processedRowCount = new AtomicLong();
     private Cuboid cuboid;
     private boolean partialResultReturned = false;
 
@@ -140,20 +139,12 @@ public class StorageContext {
         return cuboid;
     }
 
-    public long getTotalScanCount() {
-        return totalScanCount.get();
+    public long getProcessedRowCount() {
+        return processedRowCount.get();
     }
 
-    public long increaseTotalScanCount(long count) {
-        return this.totalScanCount.addAndGet(count);
-    }
-
-    public long getTotalScanBytes() {
-        return totalScanBytes.get();
-    }
-
-    public long increaseTotalScanBytes(long bytes) {
-        return totalScanBytes.addAndGet(bytes);
+    public long increaseProcessedRowCount(long count) {
+        return processedRowCount.addAndGet(count);
     }
 
     public boolean isAcceptPartialResult() {

http://git-wip-us.apache.org/repos/asf/kylin/blob/43c05667/core-storage/src/main/java/org/apache/kylin/storage/gtrecord/CubeSegmentScanner.java
----------------------------------------------------------------------
diff --git a/core-storage/src/main/java/org/apache/kylin/storage/gtrecord/CubeSegmentScanner.java b/core-storage/src/main/java/org/apache/kylin/storage/gtrecord/CubeSegmentScanner.java
index 974b8ea..029502c 100644
--- a/core-storage/src/main/java/org/apache/kylin/storage/gtrecord/CubeSegmentScanner.java
+++ b/core-storage/src/main/java/org/apache/kylin/storage/gtrecord/CubeSegmentScanner.java
@@ -78,7 +78,7 @@ public class CubeSegmentScanner implements IGTScanner {
         }
         scanRequest = scanRangePlanner.planScanRequest();
         String gtStorage = ((GTCubeStorageQueryBase) context.getStorageQuery()).getGTStorage();
-        scanner = new ScannerWorker(cubeSeg, cuboid, scanRequest, gtStorage, context);
+        scanner = new ScannerWorker(cubeSeg, cuboid, scanRequest, gtStorage);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/kylin/blob/43c05667/core-storage/src/main/java/org/apache/kylin/storage/gtrecord/ScannerWorker.java
----------------------------------------------------------------------
diff --git a/core-storage/src/main/java/org/apache/kylin/storage/gtrecord/ScannerWorker.java b/core-storage/src/main/java/org/apache/kylin/storage/gtrecord/ScannerWorker.java
index 2a2a86a..fd50c54 100644
--- a/core-storage/src/main/java/org/apache/kylin/storage/gtrecord/ScannerWorker.java
+++ b/core-storage/src/main/java/org/apache/kylin/storage/gtrecord/ScannerWorker.java
@@ -26,7 +26,6 @@ import org.apache.kylin.gridtable.GTScanRequest;
 import org.apache.kylin.gridtable.IGTScanner;
 import org.apache.kylin.gridtable.IGTStorage;
 import org.apache.kylin.metadata.model.ISegment;
-import org.apache.kylin.storage.StorageContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -39,7 +38,7 @@ public class ScannerWorker {
     private static final Logger logger = LoggerFactory.getLogger(ScannerWorker.class);
     private IGTScanner internal = null;
 
-    public ScannerWorker(ISegment segment, Cuboid cuboid, GTScanRequest scanRequest, String gtStorage, StorageContext context) {
+    public ScannerWorker(ISegment segment, Cuboid cuboid, GTScanRequest scanRequest, String gtStorage) {
         if (scanRequest == null) {
             logger.info("Segment {} will be skipped", segment);
             internal = new EmptyGTScanner(0);
@@ -49,7 +48,7 @@ public class ScannerWorker {
         final GTInfo info = scanRequest.getInfo();
 
         try {
-            IGTStorage rpc = (IGTStorage) Class.forName(gtStorage).getConstructor(ISegment.class, Cuboid.class, GTInfo.class, StorageContext.class).newInstance(segment, cuboid, info, context); // default behavior
+            IGTStorage rpc = (IGTStorage) Class.forName(gtStorage).getConstructor(ISegment.class, Cuboid.class, GTInfo.class).newInstance(segment, cuboid, info); // default behavior
             internal = rpc.getGTScanner(scanRequest);
         } catch (IOException | InstantiationException | InvocationTargetException | IllegalAccessException | ClassNotFoundException | NoSuchMethodException e) {
             throw new RuntimeException(e);

http://git-wip-us.apache.org/repos/asf/kylin/blob/43c05667/core-storage/src/main/java/org/apache/kylin/storage/gtrecord/SequentialCubeTupleIterator.java
----------------------------------------------------------------------
diff --git a/core-storage/src/main/java/org/apache/kylin/storage/gtrecord/SequentialCubeTupleIterator.java b/core-storage/src/main/java/org/apache/kylin/storage/gtrecord/SequentialCubeTupleIterator.java
index bb2d7f9..14b6394 100644
--- a/core-storage/src/main/java/org/apache/kylin/storage/gtrecord/SequentialCubeTupleIterator.java
+++ b/core-storage/src/main/java/org/apache/kylin/storage/gtrecord/SequentialCubeTupleIterator.java
@@ -26,8 +26,8 @@ import java.util.Set;
 
 import javax.annotation.Nullable;
 
+import org.apache.kylin.common.exceptions.KylinTimeoutException;
 import org.apache.kylin.cube.cuboid.Cuboid;
-import org.apache.kylin.gridtable.GTScanTimeoutException;
 import org.apache.kylin.metadata.model.FunctionDesc;
 import org.apache.kylin.metadata.model.TblColRef;
 import org.apache.kylin.metadata.tuple.ITuple;
@@ -139,7 +139,7 @@ public class SequentialCubeTupleIterator implements ITupleIterator {
     @Override
     public ITuple next() {
         if (scanCount++ % 100 == 1 && System.currentTimeMillis() > context.getDeadline()) {
-            throw new GTScanTimeoutException("Query Timeout!");
+            throw new KylinTimeoutException("Query timeout after \"kylin.query.timeout-seconds\" seconds");
         }
 
         if (++scanCountDelta >= 1000)
@@ -173,7 +173,7 @@ public class SequentialCubeTupleIterator implements ITupleIterator {
     }
 
     private void flushScanCountDelta() {
-        context.increaseTotalScanCount(scanCountDelta);
+        context.increaseProcessedRowCount(scanCountDelta);
         scanCountDelta = 0;
     }
 

http://git-wip-us.apache.org/repos/asf/kylin/blob/43c05667/kylin-it/src/test/java/org/apache/kylin/query/ITKylinQueryTest.java
----------------------------------------------------------------------
diff --git a/kylin-it/src/test/java/org/apache/kylin/query/ITKylinQueryTest.java b/kylin-it/src/test/java/org/apache/kylin/query/ITKylinQueryTest.java
index 87ddcb8..4590e60 100644
--- a/kylin-it/src/test/java/org/apache/kylin/query/ITKylinQueryTest.java
+++ b/kylin-it/src/test/java/org/apache/kylin/query/ITKylinQueryTest.java
@@ -29,7 +29,7 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.kylin.common.KylinConfig;
 import org.apache.kylin.common.KylinVersion;
 import org.apache.kylin.common.debug.BackdoorToggles;
-import org.apache.kylin.gridtable.GTScanSelfTerminatedException;
+import org.apache.kylin.common.exceptions.KylinTimeoutException;
 import org.apache.kylin.gridtable.StorageSideBehavior;
 import org.apache.kylin.metadata.realization.RealizationType;
 import org.apache.kylin.query.routing.Candidate;
@@ -124,12 +124,12 @@ public class ITKylinQueryTest extends KylinTestBase {
 
                 System.out.println(e.getMessage());
 
-                if (findRoot(e) instanceof GTScanSelfTerminatedException) {
+                if (findRoot(e) instanceof KylinTimeoutException) {
                     //expected
                     continue;
                 }
             }
-            throw new RuntimeException("Expecting GTScanTimeoutException");
+            throw new RuntimeException("Expecting KylinTimeoutException");
         }
     }
 

http://git-wip-us.apache.org/repos/asf/kylin/blob/43c05667/server-base/src/main/java/org/apache/kylin/rest/service/QueryService.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/service/QueryService.java b/server-base/src/main/java/org/apache/kylin/rest/service/QueryService.java
index 7d9e24d..4c02aa4 100644
--- a/server-base/src/main/java/org/apache/kylin/rest/service/QueryService.java
+++ b/server-base/src/main/java/org/apache/kylin/rest/service/QueryService.java
@@ -57,13 +57,13 @@ import org.apache.hadoop.hbase.client.Table;
 import org.apache.kylin.common.KylinConfig;
 import org.apache.kylin.common.QueryContext;
 import org.apache.kylin.common.debug.BackdoorToggles;
+import org.apache.kylin.common.exceptions.ResourceLimitExceededException;
 import org.apache.kylin.common.util.Bytes;
 import org.apache.kylin.common.util.DBUtils;
 import org.apache.kylin.common.util.SetThreadName;
 import org.apache.kylin.cube.CubeInstance;
 import org.apache.kylin.cube.CubeManager;
 import org.apache.kylin.cube.cuboid.Cuboid;
-import org.apache.kylin.gridtable.GTScanExceedThresholdException;
 import org.apache.kylin.metadata.project.RealizationEntry;
 import org.apache.kylin.metadata.realization.RealizationType;
 import org.apache.kylin.query.relnode.OLAPContext;
@@ -328,10 +328,12 @@ public class QueryService extends BasicService {
             throw new InternalErrorException("Project cannot be empty. Please select a project.");
         }
 
-        final String queryId = UUID.randomUUID().toString();
         if (sqlRequest.getBackdoorToggles() != null)
             BackdoorToggles.addToggles(sqlRequest.getBackdoorToggles());
-        QueryContext.current().setQueryId(queryId);
+
+        final QueryContext queryContext = QueryContext.current();
+        final String queryId = UUID.randomUUID().toString();
+        queryContext.setQueryId(queryId);
 
         try (SetThreadName ignored = new SetThreadName("Query %s", queryId)) {
             String sql = sqlRequest.getSql();
@@ -372,6 +374,8 @@ public class QueryService extends BasicService {
 
                 } else {
                     sqlResponse.setDuration(System.currentTimeMillis() - startTime);
+                    sqlResponse.setTotalScanCount(0);
+                    sqlResponse.setTotalScanBytes(0);
                 }
 
                 checkQueryAuth(sqlResponse);
@@ -381,9 +385,10 @@ public class QueryService extends BasicService {
                 String errMsg = QueryUtil.makeErrorMsgUserFriendly(e);
 
                 sqlResponse = new SQLResponse(null, null, 0, true, errMsg);
+                sqlResponse.setTotalScanCount(queryContext.getScannedRows());
+                sqlResponse.setTotalScanBytes(queryContext.getScannedBytes());
 
-                // for exception queries, only cache ScanOutOfLimitException
-                if (queryCacheEnabled && e instanceof GTScanExceedThresholdException) {
+                if (queryCacheEnabled && e.getCause() != null && e.getCause() instanceof ResourceLimitExceededException) {
                     Cache exceptionCache = cacheManager.getCache(EXCEPTION_QUERY_CACHE);
                     exceptionCache.put(new Element(sqlRequest, sqlResponse));
                 }
@@ -582,26 +587,21 @@ public class QueryService extends BasicService {
 
         boolean isPartialResult = false;
         String cube = "";
-        StringBuilder sb = new StringBuilder("Scan stats for each storageContext: ");
-        long totalScanCount = 0;
-        long totalScanBytes = 0;
+        StringBuilder sb = new StringBuilder("Processed rows for each storageContext: ");
         if (OLAPContext.getThreadLocalContexts() != null) { // contexts can be null in case of 'explain plan for'
             for (OLAPContext ctx : OLAPContext.getThreadLocalContexts()) {
                 if (ctx.realization != null) {
                     isPartialResult |= ctx.storageContext.isPartialResultReturned();
                     cube = ctx.realization.getName();
-                    totalScanCount += ctx.storageContext.getTotalScanCount();
-                    totalScanBytes += ctx.storageContext.getTotalScanBytes();
-                    sb.append("{rows=").append(ctx.storageContext.getTotalScanCount()).
-                       append(" bytes=").append(ctx.storageContext.getTotalScanBytes()).append("} ");
+                    sb.append(ctx.storageContext.getProcessedRowCount()).append(" ");
                 }
             }
         }
         logger.info(sb.toString());
 
         SQLResponse response = new SQLResponse(columnMetas, results, cube, 0, false, null, isPartialResult);
-        response.setTotalScanCount(totalScanCount);
-        response.setTotalScanBytes(totalScanBytes);
+        response.setTotalScanCount(QueryContext.current().getScannedRows());
+        response.setTotalScanBytes(QueryContext.current().getScannedBytes());
 
         return response;
     }

http://git-wip-us.apache.org/repos/asf/kylin/blob/43c05667/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/CubeHBaseEndpointRPC.java
----------------------------------------------------------------------
diff --git a/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/CubeHBaseEndpointRPC.java b/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/CubeHBaseEndpointRPC.java
index 68a84c1..3c01da2 100644
--- a/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/CubeHBaseEndpointRPC.java
+++ b/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/CubeHBaseEndpointRPC.java
@@ -24,6 +24,7 @@ import java.nio.ByteBuffer;
 import java.util.List;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicReference;
 import java.util.zip.DataFormatException;
 
 import org.apache.hadoop.hbase.TableName;
@@ -33,7 +34,8 @@ import org.apache.hadoop.hbase.client.coprocessor.Batch;
 import org.apache.hadoop.hbase.ipc.BlockingRpcCallback;
 import org.apache.hadoop.hbase.ipc.ServerRpcController;
 import org.apache.kylin.common.KylinConfig;
-import org.apache.kylin.common.QueryContext;
+import org.apache.kylin.common.exceptions.KylinTimeoutException;
+import org.apache.kylin.common.exceptions.ResourceLimitExceededException;
 import org.apache.kylin.common.util.Bytes;
 import org.apache.kylin.common.util.BytesSerializer;
 import org.apache.kylin.common.util.BytesUtil;
@@ -43,12 +45,9 @@ import org.apache.kylin.common.util.LoggableCachedThreadPool;
 import org.apache.kylin.common.util.Pair;
 import org.apache.kylin.cube.cuboid.Cuboid;
 import org.apache.kylin.gridtable.GTInfo;
-import org.apache.kylin.gridtable.GTScanExceedThresholdException;
 import org.apache.kylin.gridtable.GTScanRequest;
-import org.apache.kylin.gridtable.GTScanSelfTerminatedException;
 import org.apache.kylin.gridtable.IGTScanner;
 import org.apache.kylin.metadata.model.ISegment;
-import org.apache.kylin.storage.StorageContext;
 import org.apache.kylin.storage.gtrecord.DummyPartitionStreamer;
 import org.apache.kylin.storage.gtrecord.StorageResponseGTScatter;
 import org.apache.kylin.storage.hbase.HBaseConnection;
@@ -71,8 +70,8 @@ public class CubeHBaseEndpointRPC extends CubeHBaseRPC {
 
     private static ExecutorService executorService = new LoggableCachedThreadPool();
 
-    public CubeHBaseEndpointRPC(ISegment segment, Cuboid cuboid, GTInfo fullGTInfo, StorageContext context) {
-        super(segment, cuboid, fullGTInfo, context);
+    public CubeHBaseEndpointRPC(ISegment segment, Cuboid cuboid, GTInfo fullGTInfo) {
+        super(segment, cuboid, fullGTInfo);
     }
 
     private byte[] getByteArrayForShort(short v) {
@@ -107,8 +106,6 @@ public class CubeHBaseEndpointRPC extends CubeHBaseRPC {
     @SuppressWarnings("checkstyle:methodlength")
     @Override
     public IGTScanner getGTScanner(final GTScanRequest scanRequest) throws IOException {
-        final QueryContext queryContext = QueryContext.current();
-
         Pair<Short, Short> shardNumAndBaseShard = getShardNumAndBaseShard();
         short shardNum = shardNumAndBaseShard.getFirst();
         short cuboidBaseShard = shardNumAndBaseShard.getSecond();
@@ -175,7 +172,7 @@ public class CubeHBaseEndpointRPC extends CubeHBaseRPC {
                 public void run() {
 
                     final String logHeader = String.format("<sub-thread for Query %s GTScanRequest %s>", queryId, Integer.toHexString(System.identityHashCode(scanRequest)));
-                    final boolean[] abnormalFinish = new boolean[1];
+                    final AtomicReference<RuntimeException> regionErrorHolder = new AtomicReference<>();
 
                     try {
                         Table table = conn.getTable(TableName.valueOf(cubeSeg.getStorageLocationIdentifier()), HBaseConnection.getCoprocessorPool());
@@ -199,22 +196,32 @@ public class CubeHBaseEndpointRPC extends CubeHBaseRPC {
                                 }, new Batch.Callback<CubeVisitResponse>() {
                                     @Override
                                     public void update(byte[] region, byte[] row, CubeVisitResponse result) {
-                                        if (region == null)
+                                        if (region == null) {
                                             return;
+                                        }
 
-                                        final long scanBytes = result.getStats().getScannedBytes();
-                                        context.increaseTotalScanBytes(scanBytes);
-                                        totalScannedCount.addAndGet(result.getStats().getScannedRowCount());
                                         logger.info(logHeader + getStatsString(region, result));
 
-                                        if (queryContext.addAndGetScanBytes(scanBytes) > cubeSeg.getConfig().getQueryMaxScanBytes()) {
-                                            throw new GTScanExceedThresholdException("Query scanned " + queryContext.getScanBytes() + " bytes exceeds threshold " + cubeSeg.getConfig().getQueryMaxScanBytes());
+                                        Stats stats = result.getStats();
+                                        queryContext.addAndGetScannedRows(stats.getScannedRowCount());
+                                        queryContext.addAndGetScannedBytes(stats.getScannedBytes());
+                                        totalScannedCount.addAndGet(stats.getScannedRowCount());
+
+                                        // if any other region has responded with error, skip further processing
+                                        if (regionErrorHolder.get() != null) {
+                                            return;
                                         }
 
+                                        // record coprocessor error if happened
                                         if (result.getStats().getNormalComplete() != 1) {
-                                            abnormalFinish[0] = true;
+                                            regionErrorHolder.compareAndSet(null, getCoprocessorException(result));
                                             return;
                                         }
+
+                                        if (queryContext.getScannedBytes() > cubeSeg.getConfig().getQueryMaxScanBytes()) {
+                                            throw new ResourceLimitExceededException("Query scanned " + queryContext.getScannedBytes() + " bytes exceeds threshold " + cubeSeg.getConfig().getQueryMaxScanBytes());
+                                        }
+
                                         try {
                                             if (compressionResult) {
                                                 epResultItr.append(CompressionUtils.decompress(HBaseZeroCopyByteString.zeroCopyGetBytes(result.getCompressedRows())));
@@ -233,11 +240,10 @@ public class CubeHBaseEndpointRPC extends CubeHBaseRPC {
                         return;
                     }
 
-                    if (abnormalFinish[0]) {
-                        Throwable ex = new GTScanSelfTerminatedException(logHeader + "The coprocessor thread stopped itself due to scan timeout or scan threshold(check region server log), failing current query...");
-                        logger.error(logHeader + "Error when visiting cubes by endpoint", ex); // double log coz the query thread may already timeout
-                        epResultItr.notifyCoprocException(ex);
-                        return;
+                    if (regionErrorHolder.get() != null) {
+                        RuntimeException exception = regionErrorHolder.get();
+                        logger.error(logHeader + "Error when visiting cubes by endpoint", exception); // double log coz the query thread may already timeout
+                        epResultItr.notifyCoprocException(exception);
                     }
                 }
             });
@@ -288,6 +294,8 @@ public class CubeHBaseEndpointRPC extends CubeHBaseRPC {
     private String getStatsString(byte[] region, CubeVisitResponse result) {
         StringBuilder sb = new StringBuilder();
         Stats stats = result.getStats();
+        byte[] compressedRows = HBaseZeroCopyByteString.zeroCopyGetBytes(result.getCompressedRows());
+
         sb.append("Endpoint RPC returned from HTable ").append(cubeSeg.getStorageLocationIdentifier()).append(" Shard ").append(BytesUtil.toHex(region)).append(" on host: ").append(stats.getHostname()).append(".");
         sb.append("Total scanned row: ").append(stats.getScannedRowCount()).append(". ");
         sb.append("Total scanned bytes: ").append(stats.getScannedBytes()).append(". ");
@@ -296,8 +304,27 @@ public class CubeHBaseEndpointRPC extends CubeHBaseRPC {
         sb.append("Server CPU usage: ").append(stats.getSystemCpuLoad()).append(", server physical mem left: ").append(stats.getFreePhysicalMemorySize()).append(", server swap mem left:").append(stats.getFreeSwapSpaceSize()).append(".");
         sb.append("Etc message: ").append(stats.getEtcMsg()).append(".");
         sb.append("Normal Complete: ").append(stats.getNormalComplete() == 1).append(".");
+        sb.append("Compressed row size: ").append(compressedRows.length);
         return sb.toString();
 
     }
 
+    private RuntimeException getCoprocessorException(CubeVisitResponse response) {
+        if (!response.hasErrorInfo()) {
+            return new RuntimeException("Coprocessor aborts due to scan timeout or other reasons, please re-deploy coprocessor to see concrete error message");
+        }
+
+        CubeVisitResponse.ErrorInfo errorInfo = response.getErrorInfo();
+
+        switch (errorInfo.getType()) {
+            case UNKNOWN_TYPE:
+                return new RuntimeException("Coprocessor aborts: " + errorInfo.getMessage());
+            case TIMEOUT:
+                return new KylinTimeoutException(errorInfo.getMessage());
+            case RESOURCE_LIMIT_EXCEEDED:
+                return new ResourceLimitExceededException("Coprocessor resource limit exceeded: " + errorInfo.getMessage());
+            default:
+                throw new AssertionError("Unknown error type: " + errorInfo.getType());
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/kylin/blob/43c05667/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/CubeHBaseRPC.java
----------------------------------------------------------------------
diff --git a/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/CubeHBaseRPC.java b/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/CubeHBaseRPC.java
index 11fbb19..f24290c 100644
--- a/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/CubeHBaseRPC.java
+++ b/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/CubeHBaseRPC.java
@@ -29,6 +29,7 @@ import org.apache.hadoop.hbase.filter.Filter;
 import org.apache.hadoop.hbase.filter.FilterList;
 import org.apache.hadoop.hbase.filter.FuzzyRowFilter;
 import org.apache.kylin.common.KylinConfig;
+import org.apache.kylin.common.QueryContext;
 import org.apache.kylin.common.debug.BackdoorToggles;
 import org.apache.kylin.common.util.Bytes;
 import org.apache.kylin.common.util.ImmutableBitSet;
@@ -48,7 +49,6 @@ import org.apache.kylin.gridtable.GTInfo;
 import org.apache.kylin.gridtable.GTRecord;
 import org.apache.kylin.gridtable.GTScanRange;
 import org.apache.kylin.gridtable.IGTStorage;
-import org.apache.kylin.storage.StorageContext;
 import org.apache.kylin.storage.hbase.HBaseConnection;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -63,18 +63,18 @@ public abstract class CubeHBaseRPC implements IGTStorage {
     final protected CubeSegment cubeSeg;
     final protected Cuboid cuboid;
     final protected GTInfo fullGTInfo;
-    final protected StorageContext context;
+    final protected QueryContext queryContext;
 
     final private RowKeyEncoder fuzzyKeyEncoder;
     final private RowKeyEncoder fuzzyMaskEncoder;
 
-    public CubeHBaseRPC(ISegment segment, Cuboid cuboid, GTInfo fullGTInfo, StorageContext context) {
+    public CubeHBaseRPC(ISegment segment, Cuboid cuboid, GTInfo fullGTInfo) {
         Preconditions.checkArgument(segment instanceof CubeSegment, "segment must be CubeSegment");
         
         this.cubeSeg = (CubeSegment) segment;
         this.cuboid = cuboid;
         this.fullGTInfo = fullGTInfo;
-        this.context = context;
+        this.queryContext = QueryContext.current();
 
         this.fuzzyKeyEncoder = new FuzzyKeyEncoder(cubeSeg, cuboid);
         this.fuzzyMaskEncoder = new FuzzyMaskEncoder(cubeSeg, cuboid);

http://git-wip-us.apache.org/repos/asf/kylin/blob/43c05667/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/CubeHBaseScanRPC.java
----------------------------------------------------------------------
diff --git a/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/CubeHBaseScanRPC.java b/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/CubeHBaseScanRPC.java
index b94346c..1698180 100644
--- a/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/CubeHBaseScanRPC.java
+++ b/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/CubeHBaseScanRPC.java
@@ -42,7 +42,6 @@ import org.apache.kylin.gridtable.GTScanRequest;
 import org.apache.kylin.gridtable.IGTScanner;
 import org.apache.kylin.gridtable.IGTStore;
 import org.apache.kylin.metadata.model.ISegment;
-import org.apache.kylin.storage.StorageContext;
 import org.apache.kylin.storage.hbase.HBaseConnection;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -88,8 +87,8 @@ public class CubeHBaseScanRPC extends CubeHBaseRPC {
         }
     }
 
-    public CubeHBaseScanRPC(ISegment segment, Cuboid cuboid, final GTInfo fullGTInfo, StorageContext context) {
-        super(segment, cuboid, fullGTInfo, context);
+    public CubeHBaseScanRPC(ISegment segment, Cuboid cuboid, final GTInfo fullGTInfo) {
+        super(segment, cuboid, fullGTInfo);
     }
 
     @Override
@@ -182,15 +181,18 @@ public class CubeHBaseScanRPC extends CubeHBaseRPC {
         final Iterator<Result> allResultsIterator = Iterators.concat(resultIterators.iterator());
 
         CellListIterator cellListIterator = new CellListIterator() {
-            long scanBytes = 0;
+            long scannedRows = 0;
+            long scannedBytes = 0;
 
             @Override
             public void close() throws IOException {
+                queryContext.addAndGetScannedRows(scannedRows);
+                queryContext.addAndGetScannedBytes(scannedBytes);
+
                 for (ResultScanner scanner : scanners) {
                     scanner.close();
                 }
                 hbaseTable.close();
-                context.increaseTotalScanBytes(scanBytes);
             }
 
             @Override
@@ -202,8 +204,9 @@ public class CubeHBaseScanRPC extends CubeHBaseRPC {
             public List<Cell> next() {
                 List<Cell> result = allResultsIterator.next().listCells();
                 for (Cell cell : result) {
-                    scanBytes += CellUtil.estimatedSizeOf(cell);
+                    scannedBytes += CellUtil.estimatedSizeOf(cell);
                 }
+                scannedRows++;
                 return result;
             }
 

http://git-wip-us.apache.org/repos/asf/kylin/blob/43c05667/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/coprocessor/endpoint/CubeVisitService.java
----------------------------------------------------------------------
diff --git a/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/coprocessor/endpoint/CubeVisitService.java b/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/coprocessor/endpoint/CubeVisitService.java
index 5fd9740..e18ff0d 100644
--- a/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/coprocessor/endpoint/CubeVisitService.java
+++ b/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/coprocessor/endpoint/CubeVisitService.java
@@ -31,7 +31,6 @@ import java.util.Properties;
 
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang.ArrayUtils;
-import org.apache.commons.lang.mutable.MutableBoolean;
 import org.apache.hadoop.hbase.Cell;
 import org.apache.hadoop.hbase.CellUtil;
 import org.apache.hadoop.hbase.Coprocessor;
@@ -44,16 +43,15 @@ import org.apache.hadoop.hbase.protobuf.ResponseConverter;
 import org.apache.hadoop.hbase.regionserver.HRegion;
 import org.apache.hadoop.hbase.regionserver.RegionScanner;
 import org.apache.kylin.common.KylinConfig;
+import org.apache.kylin.common.exceptions.KylinTimeoutException;
+import org.apache.kylin.common.exceptions.ResourceLimitExceededException;
 import org.apache.kylin.common.util.Bytes;
 import org.apache.kylin.common.util.BytesUtil;
 import org.apache.kylin.common.util.CompressionUtils;
 import org.apache.kylin.common.util.SetThreadName;
 import org.apache.kylin.cube.kv.RowConstants;
 import org.apache.kylin.gridtable.GTRecord;
-import org.apache.kylin.gridtable.GTScanExceedThresholdException;
 import org.apache.kylin.gridtable.GTScanRequest;
-import org.apache.kylin.gridtable.GTScanSelfTerminatedException;
-import org.apache.kylin.gridtable.GTScanTimeoutException;
 import org.apache.kylin.gridtable.IGTScanner;
 import org.apache.kylin.gridtable.IGTStore;
 import org.apache.kylin.gridtable.StorageSideBehavior;
@@ -165,13 +163,13 @@ public class CubeVisitService extends CubeVisitProtos.CubeVisitService implement
         @Override
         public boolean hasNext() {
             if (rowCount > rowCountLimit) {
-                throw new GTScanExceedThresholdException("Number of rows scanned exceeds threshold " + rowCountLimit);
+                throw new ResourceLimitExceededException("scanned row count exceeds threshold " + rowCountLimit);
             }
             if (rowBytes > bytesLimit) {
-                throw new GTScanExceedThresholdException("Scanned " + rowBytes + " bytes exceeds threshold " + bytesLimit);
+                throw new ResourceLimitExceededException("scanned bytes " + rowBytes + " exceeds threshold " + bytesLimit);
             }
             if ((rowCount % GTScanRequest.terminateCheckInterval == 1) && System.currentTimeMillis() > deadline) {
-                throw new GTScanTimeoutException("Scan timeout after " + timeout + " ms");
+                throw new KylinTimeoutException("coprocessor timeout after " + timeout + " ms");
             }
             return delegate.hasNext();
         }
@@ -232,6 +230,8 @@ public class CubeVisitService extends CubeVisitProtos.CubeVisitService implement
         byte[] allRows;
         String debugGitTag = "";
 
+        CubeVisitProtos.CubeVisitResponse.ErrorInfo errorInfo = null;
+
         String queryId = request.hasQueryId() ? request.getQueryId() : "UnknownId";
         try (SetThreadName ignored = new SetThreadName("Query %s", queryId)) {
             this.serviceStartTime = System.currentTimeMillis();
@@ -292,7 +292,6 @@ public class CubeVisitService extends CubeVisitProtos.CubeVisitService implement
                 scanReq.disableAggCacheMemCheck(); // disable mem check if so told
             }
 
-            final MutableBoolean scanNormalComplete = new MutableBoolean(true);
             final long storagePushDownLimit = scanReq.getStoragePushDownLimit();
 
             ResourceTrackingCellListIterator cellListIterator = new ResourceTrackingCellListIterator(
@@ -332,11 +331,18 @@ public class CubeVisitService extends CubeVisitProtos.CubeVisitService implement
                         break;
                     }
                 }
-            } catch (GTScanSelfTerminatedException e) {
-                // the query is using too much resource, we mark it as abnormal finish instead of
-                // throwing RuntimeException to avoid client retrying RPC.
-                scanNormalComplete.setValue(false);
-                logger.warn("Abort scan: {}", e.getMessage());
+            } catch (KylinTimeoutException e) {
+                logger.info("Abort scan: {}", e.getMessage());
+                errorInfo = CubeVisitProtos.CubeVisitResponse.ErrorInfo.newBuilder()
+                        .setType(CubeVisitProtos.CubeVisitResponse.ErrorType.TIMEOUT)
+                        .setMessage(e.getMessage())
+                        .build();
+            } catch (ResourceLimitExceededException e) {
+                logger.info("Abort scan: {}", e.getMessage());
+                errorInfo = CubeVisitProtos.CubeVisitResponse.ErrorInfo.newBuilder()
+                        .setType(CubeVisitProtos.CubeVisitResponse.ErrorType.RESOURCE_LIMIT_EXCEEDED)
+                        .setMessage(e.getMessage())
+                        .build();
             } finally {
                 finalScanner.close();
             }
@@ -347,7 +353,7 @@ public class CubeVisitService extends CubeVisitProtos.CubeVisitService implement
 
             //outputStream.close() is not necessary
             byte[] compressedAllRows;
-            if (scanNormalComplete.booleanValue()) {
+            if (errorInfo == null) {
                 allRows = outputStream.toByteArray();
             } else {
                 allRows = new byte[0];
@@ -370,6 +376,9 @@ public class CubeVisitService extends CubeVisitProtos.CubeVisitService implement
             sb.append(" debugGitTag:" + debugGitTag);
 
             CubeVisitProtos.CubeVisitResponse.Builder responseBuilder = CubeVisitProtos.CubeVisitResponse.newBuilder();
+            if (errorInfo != null) {
+                responseBuilder.setErrorInfo(errorInfo);
+            }
             done.run(responseBuilder.//
                     setCompressedRows(HBaseZeroCopyByteString.wrap(compressedAllRows)).//too many array copies 
                     setStats(CubeVisitProtos.CubeVisitResponse.Stats.newBuilder().
@@ -383,9 +392,8 @@ public class CubeVisitService extends CubeVisitProtos.CubeVisitService implement
                             setFreeSwapSpaceSize(freeSwapSpaceSize).
                             setHostname(InetAddress.getLocalHost().getHostName()).
                             setEtcMsg(sb.toString()).
-                            setNormalComplete(scanNormalComplete.booleanValue() ? 1 : 0).build())
-                    .//
-                    build());
+                            setNormalComplete(errorInfo == null ? 1 : 0).build())
+                    .build());
 
         } catch (IOException ioe) {
             logger.error(ioe.toString(), ioe);