Skip to content

Commit

Permalink
crc
Browse files Browse the repository at this point in the history
  • Loading branch information
baiyubin2020 committed Sep 27, 2016
1 parent 5327b18 commit 5d20b5a
Show file tree
Hide file tree
Showing 6 changed files with 227 additions and 22 deletions.
60 changes: 53 additions & 7 deletions oss/bucket.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ func (bucket Bucket) copy(srcObjectKey, destBucketName, destObjectKey string, op
if err != nil {
return out, err
}
resp, err := bucket.Client.Conn.Do("PUT", destBucketName, destObjectKey, "", "", headers, nil)
resp, err := bucket.Client.Conn.Do("PUT", destBucketName, destObjectKey, "", "", headers, nil, 0)
if err != nil {
return out, err
}
Expand All @@ -273,8 +273,8 @@ func (bucket Bucket) copy(srcObjectKey, destBucketName, destObjectKey string, op
// appendPosition object追加的起始位置。
// destObjectProperties 第一次追加时指定新对象的属性,如CacheControl、ContentDisposition、ContentEncoding、
// Expires、ServerSideEncryption、ObjectACL。
// int64 下次追加的开始位置,error为nil空时有效。
//
// int64 下次追加的开始位置,error为nil空时有效。
// error 操作无错误为nil,非nil为错误信息。
//
func (bucket Bucket) AppendObject(objectKey string, reader io.Reader, appendPosition int64, options ...Option) (int64, error) {
Expand All @@ -283,18 +283,65 @@ func (bucket Bucket) AppendObject(objectKey string, reader io.Reader, appendPosi
opts := addContentType(options, objectKey)
resp, err := bucket.do("POST", objectKey, params, params, opts, reader)
if err != nil {
return nextAppendPosition, err
return appendPosition, err
}
defer resp.body.Close()

napint, err := strconv.Atoi(resp.headers.Get(HTTPHeaderOssNextAppendPosition))
nextAppendPosition, err = strconv.ParseInt(resp.headers.Get(HTTPHeaderOssNextAppendPosition), 10, 64)
if err != nil {
return nextAppendPosition, err
}
nextAppendPosition = int64(napint)

return nextAppendPosition, nil
}

//
// AppendObjectWithCRC 追加方式上传。
//
// AppendObject参数必须包含position,其值指定从何处进行追加。首次追加操作的position必须为0,
// 后续追加操作的position是Object的当前长度。例如,第一次Append Object请求指定position值为0,
// content-length是65536;那么,第二次Append Object需要指定position为65536。
// 每次操作成功后,响应头部x-oss-next-append-position也会标明下一次追加的position。
//
// objectKey 需要追加的Object。
// reader io.Reader,读取追的内容。
// appendPosition object追加的起始位置。
// initCRC 上次追加的返回的CRC校验值,第一次填0。
// destObjectProperties 第一次追加时指定新对象的属性,如CacheControl、ContentDisposition、ContentEncoding、
// Expires、ServerSideEncryption、ObjectACL。
//
// int64 下次追加的开始位置,error为nil空时有效。
// int64 本次追加后文件的CRC值,作为下次的初始化值。
// error 操作无错误为nil,非nil为错误信息。
//
func (bucket Bucket) AppendObjectWithCRC(objectKey string, reader io.Reader, appendPosition int64, initCRC uint64, options ...Option) (int64, uint64, error) {
var nextAppendPosition int64
params := "append&position=" + strconv.Itoa(int(appendPosition))
opts := addContentType(options, objectKey)
headers := make(map[string]string)

handleOptions(headers, opts)
resp, err := bucket.Client.Conn.Do("POST", bucket.BucketName, objectKey, params, params, headers, reader, initCRC)
if err != nil {
return nextAppendPosition, initCRC, err
}
defer resp.body.Close()

nextAppendPosition, err = strconv.ParseInt(resp.headers.Get(HTTPHeaderOssNextAppendPosition), 10, 64)
if err != nil {
return nextAppendPosition, initCRC, err
}

if bucket.getConfig().IsEnableCRC {
err = checkCRC(resp, "AppendObject")
if err != nil {
return nextAppendPosition, resp.serverCRC, err
}
}

return nextAppendPosition, resp.serverCRC, nil
}

//
// DeleteObject 删除Object。
//
Expand Down Expand Up @@ -531,14 +578,13 @@ func (bucket Bucket) do(method, objectName, urlParams, subResource string,
return nil, err
}
return bucket.Client.Conn.Do(method, bucket.BucketName, objectName,
urlParams, subResource, headers, data)
urlParams, subResource, headers, data, 0)
}

func (bucket Bucket) getConfig() *Config {
return bucket.Client.Config
}

// Private
func addContentType(options []Option, keys ...string) []Option {
typ := TypeByExtension("")
for _, key := range keys {
Expand Down
13 changes: 12 additions & 1 deletion oss/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,17 @@ func EnableCRC(isEnableCRC bool) ClientOption {
}
}

//
// UserAgent 指定UserAgent,默认如下aliyun-sdk-go/1.2.0 (windows/-/amd64;go1.5.2)。
//
// userAgent user agent字符串。
//
func UserAgent(userAgent string) ClientOption {
return func(client *Client) {
client.Config.UserAgent = userAgent
}
}

//
// Proxy 设置代理服务器,默认不使用代理。
//
Expand Down Expand Up @@ -724,5 +735,5 @@ func AuthProxy(proxyHost, proxyUser, proxyPassword string) ClientOption {
func (client Client) do(method, bucketName, urlParams, subResource string,
headers map[string]string, data io.Reader) (*Response, error) {
return client.Conn.Do(method, bucketName, "", urlParams,
subResource, headers, data)
subResource, headers, data, 0)
}
4 changes: 4 additions & 0 deletions oss/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1319,6 +1319,10 @@ func (s *OssClientSuite) TestClientOption(c *C) {
c.Assert(client.Conn.config.IsAuthProxy, Equals, true)
c.Assert(client.Conn.config.ProxyUser, Equals, proxyUser)
c.Assert(client.Conn.config.ProxyPassword, Equals, proxyPasswd)

client, err = New(endpoint, accessID, accessKey, UserAgent("go sdk user agent"))

c.Assert(client.Conn.config.UserAgent, Equals, "go sdk user agent")
}

// _TestProxy
Expand Down
13 changes: 6 additions & 7 deletions oss/conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"encoding/xml"
"fmt"
"hash"
"hash/crc64"
"io"
"io/ioutil"
"net"
Expand Down Expand Up @@ -36,14 +35,14 @@ type Response struct {

// Do 处理请求,返回响应结果。
func (conn Conn) Do(method, bucketName, objectName, urlParams, subResource string,
headers map[string]string, data io.Reader) (*Response, error) {
headers map[string]string, data io.Reader, initCRC uint64) (*Response, error) {
uri := conn.url.getURL(bucketName, objectName, urlParams)
resource := conn.url.getResource(bucketName, objectName, subResource)
return conn.doRequest(method, uri, resource, headers, data)
return conn.doRequest(method, uri, resource, headers, data, initCRC)
}

func (conn Conn) doRequest(method string, uri *url.URL, canonicalizedResource string,
headers map[string]string, data io.Reader) (*Response, error) {
headers map[string]string, data io.Reader, initCRC uint64) (*Response, error) {
httpTimeOut := conn.config.HTTPTimeout
method = strings.ToUpper(method)
if !conn.config.IsUseProxy {
Expand All @@ -59,7 +58,7 @@ func (conn Conn) doRequest(method string, uri *url.URL, canonicalizedResource st
Host: uri.Host,
}

fd, crc := conn.handleBody(req, data)
fd, crc := conn.handleBody(req, data, initCRC)
if fd != nil {
defer func() {
fd.Close()
Expand Down Expand Up @@ -135,7 +134,7 @@ func (conn Conn) doRequest(method string, uri *url.URL, canonicalizedResource st
}

// handle request body
func (conn Conn) handleBody(req *http.Request, body io.Reader) (*os.File, hash.Hash64) {
func (conn Conn) handleBody(req *http.Request, body io.Reader, initCRC uint64) (*os.File, hash.Hash64) {
var file *os.File
var crc hash.Hash64
reader := body
Expand Down Expand Up @@ -180,7 +179,7 @@ func (conn Conn) handleBody(req *http.Request, body io.Reader) (*os.File, hash.H
}

if reader != nil && conn.config.IsEnableCRC {
crc = crc64.New(crcTable())
crc = NewCRC(crcTable(), initCRC)
reader = io.TeeReader(reader, crc)
}

Expand Down
44 changes: 44 additions & 0 deletions oss/crc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package oss

import (
"hash"
"hash/crc64"
)

// digest represents the partial evaluation of a checksum.
type digest struct {
crc uint64
tab *crc64.Table
}

// NewCRC creates a new hash.Hash64 computing the CRC-64 checksum
// using the polynomial represented by the Table.
func NewCRC(tab *crc64.Table, init uint64) hash.Hash64 { return &digest{init, tab} }

// Size returns the number of bytes Sum will return.
func (d *digest) Size() int { return crc64.Size }

// BlockSize returns the hash's underlying block size.
// The Write method must be able to accept any amount
// of data, but it may operate more efficiently if all writes
// are a multiple of the block size.
func (d *digest) BlockSize() int { return 1 }

// Reset resets the Hash to its initial state.
func (d *digest) Reset() { d.crc = 0 }

// Write (via the embedded io.Writer interface) adds more data to the running hash.
// It never returns an error.
func (d *digest) Write(p []byte) (n int, err error) {
d.crc = crc64.Update(d.crc, d.tab, p)
return len(p), nil
}

// Sum64 returns crc64 value.
func (d *digest) Sum64() uint64 { return d.crc }

// Sum returns hash value.
func (d *digest) Sum(in []byte) []byte {
s := d.Sum64()
return append(in, byte(s>>56), byte(s>>48), byte(s>>40), byte(s>>32), byte(s>>24), byte(s>>16), byte(s>>8), byte(s))
}

0 comments on commit 5d20b5a

Please sign in to comment.