X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/dc00995b1843cd1decebffe1493e55a16c3c0df9..01cc618477e897423d6144beb082792e06a0e6b6:/services/keepstore/handlers.go diff --git a/services/keepstore/handlers.go b/services/keepstore/handlers.go index 75b56eb827..8930b79c33 100644 --- a/services/keepstore/handlers.go +++ b/services/keepstore/handlers.go @@ -19,7 +19,6 @@ import ( "net/http" "os" "regexp" - "runtime" "strconv" "strings" "syscall" @@ -112,32 +111,20 @@ func GetBlockHandler(resp http.ResponseWriter, req *http.Request) { } block, err := GetBlock(hash, false) - - // Garbage collect after each GET. Fixes #2865. - // TODO(twp): review Keep memory usage and see if there's - // a better way to do this than blindly garbage collecting - // after every block. - defer runtime.GC() - if err != nil { // This type assertion is safe because the only errors // GetBlock can return are DiskHashError or NotFoundError. http.Error(resp, err.Error(), err.(*KeepError).HTTPCode) return } + defer bufs.Put(block) - resp.Header().Set("Content-Length", fmt.Sprintf("%d", len(block))) - - _, err = resp.Write(block) - - return + resp.Header().Set("Content-Length", strconv.Itoa(len(block))) + resp.Header().Set("Content-Type", "application/octet-stream") + resp.Write(block) } func PutBlockHandler(resp http.ResponseWriter, req *http.Request) { - // Garbage collect after each PUT. Fixes #2865. - // See also GetBlockHandler. - defer runtime.GC() - hash := mux.Vars(req)["hash"] // Detect as many error conditions as possible before reading @@ -159,17 +146,17 @@ func PutBlockHandler(resp http.ResponseWriter, req *http.Request) { return } - buf := make([]byte, req.ContentLength) - nread, err := io.ReadFull(req.Body, buf) + buf := bufs.Get(int(req.ContentLength)) + _, err := io.ReadFull(req.Body, buf) if err != nil { http.Error(resp, err.Error(), 500) - return - } else if int64(nread) < req.ContentLength { - http.Error(resp, "request truncated", 500) + bufs.Put(buf) return } err = PutBlock(buf, hash) + bufs.Put(buf) + if err != nil { ke := err.(*KeepError) http.Error(resp, ke.Error(), ke.HTTPCode) @@ -178,7 +165,7 @@ func PutBlockHandler(resp http.ResponseWriter, req *http.Request) { // Success; add a size hint, sign the locator if possible, and // return it to the client. - return_hash := fmt.Sprintf("%s+%d", hash, len(buf)) + return_hash := fmt.Sprintf("%s+%d", hash, req.ContentLength) api_token := GetApiToken(req) if PermissionSecret != nil && api_token != "" { expiry := time.Now().Add(blob_signature_ttl) @@ -417,7 +404,7 @@ func PullHandler(resp http.ResponseWriter, req *http.Request) { var pr []PullRequest r := json.NewDecoder(req.Body) if err := r.Decode(&pr); err != nil { - http.Error(resp, BadRequestError.Error(), BadRequestError.HTTPCode) + http.Error(resp, err.Error(), BadRequestError.HTTPCode) return } @@ -451,7 +438,7 @@ func TrashHandler(resp http.ResponseWriter, req *http.Request) { var trash []TrashRequest r := json.NewDecoder(req.Body) if err := r.Decode(&trash); err != nil { - http.Error(resp, BadRequestError.Error(), BadRequestError.HTTPCode) + http.Error(resp, err.Error(), BadRequestError.HTTPCode) return } @@ -533,6 +520,7 @@ func GetBlock(hash string, update_timestamp bool) ([]byte, error) { log.Printf("%s: checksum mismatch for request %s (actual %s)\n", vol, hash, filehash) error_to_caller = DiskHashError + bufs.Put(buf) continue } if error_to_caller == DiskHashError { @@ -544,6 +532,7 @@ func GetBlock(hash string, update_timestamp bool) ([]byte, error) { error_to_caller = GenericError log.Printf("%s: Touch %s failed: %s", vol, hash, error_to_caller) + bufs.Put(buf) continue } } @@ -594,6 +583,7 @@ func PutBlock(block []byte, hash string) error { // so there is nothing special to do if err != nil. // if oldblock, err := GetBlock(hash, true); err == nil { + defer bufs.Put(oldblock) if bytes.Compare(block, oldblock) == 0 { // The block already exists; return success. return nil