github.com/aliyun/aliyun-oss-go-sdk@v3.0.2+incompatible/oss/select_object_type.go (about)

     1  package oss
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"fmt"
     7  	"hash"
     8  	"hash/crc32"
     9  	"io"
    10  	"net/http"
    11  	"time"
    12  )
    13  
    14  // The adapter class for Select object's response.
    15  // The response consists of frames. Each frame has the following format:
    16  
    17  // Type  |   Payload Length |  Header Checksum | Payload | Payload Checksum
    18  
    19  // |<4-->|  <--4 bytes------><---4 bytes-------><-n/a-----><--4 bytes--------->
    20  // And we have three kind of frames.
    21  // Data Frame:
    22  // Type:8388609
    23  // Payload:   Offset    |    Data
    24  //            <-8 bytes>
    25  
    26  // Continuous Frame
    27  // Type:8388612
    28  // Payload: Offset  (8-bytes)
    29  
    30  // End Frame
    31  // Type:8388613
    32  // Payload: Offset | total scanned bytes | http status code | error message
    33  //     <-- 8bytes--><-----8 bytes--------><---4 bytes-------><---variabe--->
    34  
    35  // SelectObjectResponse defines HTTP response from OSS SelectObject
    36  type SelectObjectResponse struct {
    37  	StatusCode          int
    38  	Headers             http.Header
    39  	Body                io.ReadCloser
    40  	Frame               SelectObjectResult
    41  	ReadTimeOut         uint
    42  	ClientCRC32         uint32
    43  	ServerCRC32         uint32
    44  	WriterForCheckCrc32 hash.Hash32
    45  	Finish              bool
    46  }
    47  
    48  func (sr *SelectObjectResponse) Read(p []byte) (n int, err error) {
    49  	n, err = sr.readFrames(p)
    50  	return
    51  }
    52  
    53  // Close http reponse body
    54  func (sr *SelectObjectResponse) Close() error {
    55  	return sr.Body.Close()
    56  }
    57  
    58  // PostSelectResult is the request of SelectObject
    59  type PostSelectResult struct {
    60  	Response *SelectObjectResponse
    61  }
    62  
    63  // readFrames is read Frame
    64  func (sr *SelectObjectResponse) readFrames(p []byte) (int, error) {
    65  	var nn int
    66  	var err error
    67  	var checkValid bool
    68  	if sr.Frame.OutputRawData == true {
    69  		nn, err = sr.Body.Read(p)
    70  		return nn, err
    71  	}
    72  
    73  	if sr.Finish {
    74  		return 0, io.EOF
    75  	}
    76  
    77  	for {
    78  		// if this Frame is Readed, then not reading Header
    79  		if sr.Frame.OpenLine != true {
    80  			err = sr.analysisHeader()
    81  			if err != nil {
    82  				return nn, err
    83  			}
    84  		}
    85  
    86  		if sr.Frame.FrameType == DataFrameType {
    87  			n, err := sr.analysisData(p[nn:])
    88  			if err != nil {
    89  				return nn, err
    90  			}
    91  			nn += n
    92  
    93  			// if this Frame is readed all data, then empty the Frame to read it with next frame
    94  			if sr.Frame.ConsumedBytesLength == sr.Frame.PayloadLength-8 {
    95  				checkValid, err = sr.checkPayloadSum()
    96  				if err != nil || !checkValid {
    97  					return nn, fmt.Errorf("%s", err.Error())
    98  				}
    99  				sr.emptyFrame()
   100  			}
   101  
   102  			if nn == len(p) {
   103  				return nn, nil
   104  			}
   105  		} else if sr.Frame.FrameType == ContinuousFrameType {
   106  			checkValid, err = sr.checkPayloadSum()
   107  			if err != nil || !checkValid {
   108  				return nn, fmt.Errorf("%s", err.Error())
   109  			}
   110  			sr.Frame.OpenLine = false
   111  		} else if sr.Frame.FrameType == EndFrameType {
   112  			err = sr.analysisEndFrame()
   113  			if err != nil {
   114  				return nn, err
   115  			}
   116  			checkValid, err = sr.checkPayloadSum()
   117  			if checkValid {
   118  				sr.Finish = true
   119  			}
   120  			return nn, err
   121  		} else if sr.Frame.FrameType == MetaEndFrameCSVType {
   122  			err = sr.analysisMetaEndFrameCSV()
   123  			if err != nil {
   124  				return nn, err
   125  			}
   126  			checkValid, err = sr.checkPayloadSum()
   127  			if checkValid {
   128  				sr.Finish = true
   129  			}
   130  			return nn, err
   131  		} else if sr.Frame.FrameType == MetaEndFrameJSONType {
   132  			err = sr.analysisMetaEndFrameJSON()
   133  			if err != nil {
   134  				return nn, err
   135  			}
   136  			checkValid, err = sr.checkPayloadSum()
   137  			if checkValid {
   138  				sr.Finish = true
   139  			}
   140  			return nn, err
   141  		}
   142  	}
   143  	return nn, nil
   144  }
   145  
   146  type chanReadIO struct {
   147  	readLen int
   148  	err     error
   149  }
   150  
   151  func (sr *SelectObjectResponse) readLen(p []byte, timeOut time.Duration) (int, error) {
   152  	r := sr.Body
   153  	ch := make(chan chanReadIO, 1)
   154  	defer close(ch)
   155  	go func(p []byte) {
   156  		var needReadLength int
   157  		readChan := chanReadIO{}
   158  		needReadLength = len(p)
   159  		for {
   160  			n, err := r.Read(p[readChan.readLen:needReadLength])
   161  			readChan.readLen += n
   162  			if err != nil {
   163  				readChan.err = err
   164  				ch <- readChan
   165  				return
   166  			}
   167  
   168  			if readChan.readLen == needReadLength {
   169  				break
   170  			}
   171  		}
   172  		ch <- readChan
   173  	}(p)
   174  
   175  	select {
   176  	case <-time.After(time.Second * timeOut):
   177  		return 0, fmt.Errorf("requestId: %s, readLen timeout, timeout is %d(second),need read:%d", sr.Headers.Get(HTTPHeaderOssRequestID), timeOut, len(p))
   178  	case result := <-ch:
   179  		return result.readLen, result.err
   180  	}
   181  }
   182  
   183  // analysisHeader is reading selectObject response body's header
   184  func (sr *SelectObjectResponse) analysisHeader() error {
   185  	headFrameByte := make([]byte, 20)
   186  	_, err := sr.readLen(headFrameByte, time.Duration(sr.ReadTimeOut))
   187  	if err != nil {
   188  		return fmt.Errorf("requestId: %s, Read response frame header failure,err:%s", sr.Headers.Get(HTTPHeaderOssRequestID), err.Error())
   189  	}
   190  
   191  	frameTypeByte := headFrameByte[0:4]
   192  	sr.Frame.Version = frameTypeByte[0]
   193  	frameTypeByte[0] = 0
   194  	bytesToInt(frameTypeByte, &sr.Frame.FrameType)
   195  
   196  	if sr.Frame.FrameType != DataFrameType && sr.Frame.FrameType != ContinuousFrameType &&
   197  		sr.Frame.FrameType != EndFrameType && sr.Frame.FrameType != MetaEndFrameCSVType && sr.Frame.FrameType != MetaEndFrameJSONType {
   198  		return fmt.Errorf("requestId: %s, Unexpected frame type: %d", sr.Headers.Get(HTTPHeaderOssRequestID), sr.Frame.FrameType)
   199  	}
   200  
   201  	payloadLengthByte := headFrameByte[4:8]
   202  	bytesToInt(payloadLengthByte, &sr.Frame.PayloadLength)
   203  	headCheckSumByte := headFrameByte[8:12]
   204  	bytesToInt(headCheckSumByte, &sr.Frame.HeaderCheckSum)
   205  	byteOffset := headFrameByte[12:20]
   206  	bytesToInt(byteOffset, &sr.Frame.Offset)
   207  	sr.Frame.OpenLine = true
   208  
   209  	err = sr.writerCheckCrc32(byteOffset)
   210  	return err
   211  }
   212  
   213  // analysisData is reading the DataFrameType data of selectObject response body
   214  func (sr *SelectObjectResponse) analysisData(p []byte) (int, error) {
   215  	var needReadLength int32
   216  	lenP := int32(len(p))
   217  	restByteLength := sr.Frame.PayloadLength - 8 - sr.Frame.ConsumedBytesLength
   218  	if lenP <= restByteLength {
   219  		needReadLength = lenP
   220  	} else {
   221  		needReadLength = restByteLength
   222  	}
   223  	n, err := sr.readLen(p[:needReadLength], time.Duration(sr.ReadTimeOut))
   224  	if err != nil {
   225  		return n, fmt.Errorf("read frame data error,%s", err.Error())
   226  	}
   227  	sr.Frame.ConsumedBytesLength += int32(n)
   228  	err = sr.writerCheckCrc32(p[:n])
   229  	return n, err
   230  }
   231  
   232  // analysisEndFrame is reading the EndFrameType data of selectObject response body
   233  func (sr *SelectObjectResponse) analysisEndFrame() error {
   234  	var eF EndFrame
   235  	payLoadBytes := make([]byte, sr.Frame.PayloadLength-8)
   236  	_, err := sr.readLen(payLoadBytes, time.Duration(sr.ReadTimeOut))
   237  	if err != nil {
   238  		return fmt.Errorf("read end frame error:%s", err.Error())
   239  	}
   240  	bytesToInt(payLoadBytes[0:8], &eF.TotalScanned)
   241  	bytesToInt(payLoadBytes[8:12], &eF.HTTPStatusCode)
   242  	errMsgLength := sr.Frame.PayloadLength - 20
   243  	eF.ErrorMsg = string(payLoadBytes[12 : errMsgLength+12])
   244  	sr.Frame.EndFrame.TotalScanned = eF.TotalScanned
   245  	sr.Frame.EndFrame.HTTPStatusCode = eF.HTTPStatusCode
   246  	sr.Frame.EndFrame.ErrorMsg = eF.ErrorMsg
   247  	err = sr.writerCheckCrc32(payLoadBytes)
   248  	return err
   249  }
   250  
   251  // analysisMetaEndFrameCSV is reading the MetaEndFrameCSVType data of selectObject response body
   252  func (sr *SelectObjectResponse) analysisMetaEndFrameCSV() error {
   253  	var mCF MetaEndFrameCSV
   254  	payLoadBytes := make([]byte, sr.Frame.PayloadLength-8)
   255  	_, err := sr.readLen(payLoadBytes, time.Duration(sr.ReadTimeOut))
   256  	if err != nil {
   257  		return fmt.Errorf("read meta end csv frame error:%s", err.Error())
   258  	}
   259  
   260  	bytesToInt(payLoadBytes[0:8], &mCF.TotalScanned)
   261  	bytesToInt(payLoadBytes[8:12], &mCF.Status)
   262  	bytesToInt(payLoadBytes[12:16], &mCF.SplitsCount)
   263  	bytesToInt(payLoadBytes[16:24], &mCF.RowsCount)
   264  	bytesToInt(payLoadBytes[24:28], &mCF.ColumnsCount)
   265  	errMsgLength := sr.Frame.PayloadLength - 36
   266  	mCF.ErrorMsg = string(payLoadBytes[28 : errMsgLength+28])
   267  	sr.Frame.MetaEndFrameCSV.ErrorMsg = mCF.ErrorMsg
   268  	sr.Frame.MetaEndFrameCSV.TotalScanned = mCF.TotalScanned
   269  	sr.Frame.MetaEndFrameCSV.Status = mCF.Status
   270  	sr.Frame.MetaEndFrameCSV.SplitsCount = mCF.SplitsCount
   271  	sr.Frame.MetaEndFrameCSV.RowsCount = mCF.RowsCount
   272  	sr.Frame.MetaEndFrameCSV.ColumnsCount = mCF.ColumnsCount
   273  	err = sr.writerCheckCrc32(payLoadBytes)
   274  	return err
   275  }
   276  
   277  // analysisMetaEndFrameJSON is reading the MetaEndFrameJSONType data of selectObject response body
   278  func (sr *SelectObjectResponse) analysisMetaEndFrameJSON() error {
   279  	var mJF MetaEndFrameJSON
   280  	payLoadBytes := make([]byte, sr.Frame.PayloadLength-8)
   281  	_, err := sr.readLen(payLoadBytes, time.Duration(sr.ReadTimeOut))
   282  	if err != nil {
   283  		return fmt.Errorf("read meta end json frame error:%s", err.Error())
   284  	}
   285  
   286  	bytesToInt(payLoadBytes[0:8], &mJF.TotalScanned)
   287  	bytesToInt(payLoadBytes[8:12], &mJF.Status)
   288  	bytesToInt(payLoadBytes[12:16], &mJF.SplitsCount)
   289  	bytesToInt(payLoadBytes[16:24], &mJF.RowsCount)
   290  	errMsgLength := sr.Frame.PayloadLength - 32
   291  	mJF.ErrorMsg = string(payLoadBytes[24 : errMsgLength+24])
   292  	sr.Frame.MetaEndFrameJSON.ErrorMsg = mJF.ErrorMsg
   293  	sr.Frame.MetaEndFrameJSON.TotalScanned = mJF.TotalScanned
   294  	sr.Frame.MetaEndFrameJSON.Status = mJF.Status
   295  	sr.Frame.MetaEndFrameJSON.SplitsCount = mJF.SplitsCount
   296  	sr.Frame.MetaEndFrameJSON.RowsCount = mJF.RowsCount
   297  
   298  	err = sr.writerCheckCrc32(payLoadBytes)
   299  	return err
   300  }
   301  
   302  func (sr *SelectObjectResponse) checkPayloadSum() (bool, error) {
   303  	payLoadChecksumByte := make([]byte, 4)
   304  	n, err := sr.readLen(payLoadChecksumByte, time.Duration(sr.ReadTimeOut))
   305  	if n == 4 {
   306  		bytesToInt(payLoadChecksumByte, &sr.Frame.PayloadChecksum)
   307  		sr.ServerCRC32 = sr.Frame.PayloadChecksum
   308  		sr.ClientCRC32 = sr.WriterForCheckCrc32.Sum32()
   309  		if sr.Frame.EnablePayloadCrc == true && sr.ServerCRC32 != 0 && sr.ServerCRC32 != sr.ClientCRC32 {
   310  			return false, fmt.Errorf("RequestId: %s, Unexpected frame type: %d, client %d but server %d",
   311  				sr.Headers.Get(HTTPHeaderOssRequestID), sr.Frame.FrameType, sr.ClientCRC32, sr.ServerCRC32)
   312  		}
   313  		return true, err
   314  	}
   315  	return false, fmt.Errorf("RequestId:%s, read checksum error:%s", sr.Headers.Get(HTTPHeaderOssRequestID), err.Error())
   316  }
   317  
   318  func (sr *SelectObjectResponse) writerCheckCrc32(p []byte) (err error) {
   319  	err = nil
   320  	if sr.Frame.EnablePayloadCrc == true {
   321  		_, err = sr.WriterForCheckCrc32.Write(p)
   322  	}
   323  	return err
   324  }
   325  
   326  // emptyFrame is emptying SelectObjectResponse Frame information
   327  func (sr *SelectObjectResponse) emptyFrame() {
   328  	crcCalc := crc32.NewIEEE()
   329  	sr.WriterForCheckCrc32 = crcCalc
   330  	sr.Finish = false
   331  
   332  	sr.Frame.ConsumedBytesLength = 0
   333  	sr.Frame.OpenLine = false
   334  	sr.Frame.Version = byte(0)
   335  	sr.Frame.FrameType = 0
   336  	sr.Frame.PayloadLength = 0
   337  	sr.Frame.HeaderCheckSum = 0
   338  	sr.Frame.Offset = 0
   339  	sr.Frame.Data = ""
   340  
   341  	sr.Frame.EndFrame.TotalScanned = 0
   342  	sr.Frame.EndFrame.HTTPStatusCode = 0
   343  	sr.Frame.EndFrame.ErrorMsg = ""
   344  
   345  	sr.Frame.MetaEndFrameCSV.TotalScanned = 0
   346  	sr.Frame.MetaEndFrameCSV.Status = 0
   347  	sr.Frame.MetaEndFrameCSV.SplitsCount = 0
   348  	sr.Frame.MetaEndFrameCSV.RowsCount = 0
   349  	sr.Frame.MetaEndFrameCSV.ColumnsCount = 0
   350  	sr.Frame.MetaEndFrameCSV.ErrorMsg = ""
   351  
   352  	sr.Frame.MetaEndFrameJSON.TotalScanned = 0
   353  	sr.Frame.MetaEndFrameJSON.Status = 0
   354  	sr.Frame.MetaEndFrameJSON.SplitsCount = 0
   355  	sr.Frame.MetaEndFrameJSON.RowsCount = 0
   356  	sr.Frame.MetaEndFrameJSON.ErrorMsg = ""
   357  
   358  	sr.Frame.PayloadChecksum = 0
   359  }
   360  
   361  // bytesToInt byte's array trans to int
   362  func bytesToInt(b []byte, ret interface{}) {
   363  	binBuf := bytes.NewBuffer(b)
   364  	binary.Read(binBuf, binary.BigEndian, ret)
   365  }