Chris Lu
4 years ago
4 changed files with 116 additions and 101 deletions
-
4weed/server/filer_server_handlers.go
-
4weed/server/filer_server_handlers_write.go
-
104weed/server/filer_server_handlers_write_autochunk.go
-
105weed/server/filer_server_handlers_write_upload.go
@ -0,0 +1,105 @@ |
|||||
|
package weed_server |
||||
|
|
||||
|
import ( |
||||
|
"crypto/md5" |
||||
|
"hash" |
||||
|
"io" |
||||
|
"io/ioutil" |
||||
|
"net/http" |
||||
|
"strings" |
||||
|
"time" |
||||
|
|
||||
|
"github.com/chrislusf/seaweedfs/weed/filer" |
||||
|
"github.com/chrislusf/seaweedfs/weed/glog" |
||||
|
"github.com/chrislusf/seaweedfs/weed/operation" |
||||
|
"github.com/chrislusf/seaweedfs/weed/pb/filer_pb" |
||||
|
"github.com/chrislusf/seaweedfs/weed/security" |
||||
|
"github.com/chrislusf/seaweedfs/weed/stats" |
||||
|
"github.com/chrislusf/seaweedfs/weed/util" |
||||
|
) |
||||
|
|
||||
|
func (fs *FilerServer) uploadReaderToChunks(w http.ResponseWriter, r *http.Request, reader io.Reader, chunkSize int32, fileName, contentType string, contentLength int64, so *operation.StorageOption) ([]*filer_pb.FileChunk, hash.Hash, int64, error, []byte) { |
||||
|
var fileChunks []*filer_pb.FileChunk |
||||
|
|
||||
|
md5Hash := md5.New() |
||||
|
var partReader = ioutil.NopCloser(io.TeeReader(reader, md5Hash)) |
||||
|
|
||||
|
chunkOffset := int64(0) |
||||
|
var smallContent []byte |
||||
|
|
||||
|
for { |
||||
|
limitedReader := io.LimitReader(partReader, int64(chunkSize)) |
||||
|
|
||||
|
data, err := ioutil.ReadAll(limitedReader) |
||||
|
if err != nil { |
||||
|
return nil, nil, 0, err, nil |
||||
|
} |
||||
|
if chunkOffset == 0 && !isAppend(r) { |
||||
|
if len(data) < fs.option.SaveToFilerLimit || strings.HasPrefix(r.URL.Path, filer.DirectoryEtcRoot) && len(data) < 4*1024 { |
||||
|
smallContent = data |
||||
|
chunkOffset += int64(len(data)) |
||||
|
break |
||||
|
} |
||||
|
} |
||||
|
dataReader := util.NewBytesReader(data) |
||||
|
|
||||
|
// retry to assign a different file id
|
||||
|
var fileId, urlLocation string |
||||
|
var auth security.EncodedJwt |
||||
|
var assignErr, uploadErr error |
||||
|
var uploadResult *operation.UploadResult |
||||
|
for i := 0; i < 3; i++ { |
||||
|
// assign one file id for one chunk
|
||||
|
fileId, urlLocation, auth, assignErr = fs.assignNewFileInfo(so) |
||||
|
if assignErr != nil { |
||||
|
return nil, nil, 0, assignErr, nil |
||||
|
} |
||||
|
|
||||
|
// upload the chunk to the volume server
|
||||
|
uploadResult, uploadErr, _ = fs.doUpload(urlLocation, w, r, dataReader, fileName, contentType, nil, auth) |
||||
|
if uploadErr != nil { |
||||
|
time.Sleep(251 * time.Millisecond) |
||||
|
continue |
||||
|
} |
||||
|
break |
||||
|
} |
||||
|
if uploadErr != nil { |
||||
|
return nil, nil, 0, uploadErr, nil |
||||
|
} |
||||
|
|
||||
|
// if last chunk exhausted the reader exactly at the border
|
||||
|
if uploadResult.Size == 0 { |
||||
|
break |
||||
|
} |
||||
|
|
||||
|
// Save to chunk manifest structure
|
||||
|
fileChunks = append(fileChunks, uploadResult.ToPbFileChunk(fileId, chunkOffset)) |
||||
|
|
||||
|
glog.V(4).Infof("uploaded %s chunk %d to %s [%d,%d)", fileName, len(fileChunks), fileId, chunkOffset, chunkOffset+int64(uploadResult.Size)) |
||||
|
|
||||
|
// reset variables for the next chunk
|
||||
|
chunkOffset = chunkOffset + int64(uploadResult.Size) |
||||
|
|
||||
|
// if last chunk was not at full chunk size, but already exhausted the reader
|
||||
|
if int64(uploadResult.Size) < int64(chunkSize) { |
||||
|
break |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return fileChunks, md5Hash, chunkOffset, nil, smallContent |
||||
|
} |
||||
|
|
||||
|
func (fs *FilerServer) doUpload(urlLocation string, w http.ResponseWriter, r *http.Request, limitedReader io.Reader, fileName string, contentType string, pairMap map[string]string, auth security.EncodedJwt) (*operation.UploadResult, error, []byte) { |
||||
|
|
||||
|
stats.FilerRequestCounter.WithLabelValues("chunkUpload").Inc() |
||||
|
start := time.Now() |
||||
|
defer func() { |
||||
|
stats.FilerRequestHistogram.WithLabelValues("chunkUpload").Observe(time.Since(start).Seconds()) |
||||
|
}() |
||||
|
|
||||
|
uploadResult, err, data := operation.Upload(urlLocation, fileName, fs.option.Cipher, limitedReader, false, contentType, pairMap, auth) |
||||
|
if uploadResult != nil && uploadResult.RetryCount > 0 { |
||||
|
stats.FilerRequestCounter.WithLabelValues("chunkUploadRetry").Add(float64(uploadResult.RetryCount)) |
||||
|
} |
||||
|
return uploadResult, err, data |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue