restic-server: Reduce memory footprint for saving blobs

Before, the restic-server read the whole blob (up to 8MB) into memory
prior to writing it to disk. Concurrent writes consumed a lot
of memory. This change writes the blob to a tmp file directly and
renames it afterwards in case there where no errors.
This commit is contained in:
Fabian Wickborn 2016-02-22 11:50:32 +01:00
parent 4749e610af
commit e4168fdde5
1 changed files with 14 additions and 4 deletions

View File

@ -5,6 +5,7 @@ package main
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"io"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"os" "os"
@ -150,13 +151,22 @@ func SaveBlob(c *Context) http.HandlerFunc {
dir := vars[1] dir := vars[1]
name := vars[2] name := vars[2]
path := filepath.Join(c.path, dir, name) path := filepath.Join(c.path, dir, name)
bytes, err := ioutil.ReadAll(r.Body) tmp := path + "_tmp"
tf, err := os.OpenFile(tmp, os.O_CREATE|os.O_WRONLY, 0600)
if err != nil { if err != nil {
http.Error(w, "400 bad request", 400) http.Error(w, "500 internal server error", 500)
return return
} }
errw := ioutil.WriteFile(path, bytes, 0600) if _, err := io.Copy(tf, r.Body); err != nil {
if errw != nil { http.Error(w, "400 bad request", 400)
tf.Close()
os.Remove(tmp)
return
}
if err := tf.Close(); err != nil {
http.Error(w, "500 internal server error", 500)
}
if err := os.Rename(tmp, path); err != nil {
http.Error(w, "500 internal server error", 500) http.Error(w, "500 internal server error", 500)
return return
} }