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 }