[ARVADOS] created: b750d9042e7e3fa14e7c98c9263cf13e04782a83

Git user git at public.curoverse.com
Thu Apr 28 15:26:49 EDT 2016


        at  b750d9042e7e3fa14e7c98c9263cf13e04782a83 (commit)


commit b750d9042e7e3fa14e7c98c9263cf13e04782a83
Author: Tom Clegg <tom at curoverse.com>
Date:   Thu Apr 28 15:26:29 2016 -0400

    9068: Drop PUT requests if the client disconnects before we get a buffer.

diff --git a/services/keepstore/handlers.go b/services/keepstore/handlers.go
index 043ab69..0b675e3 100644
--- a/services/keepstore/handlers.go
+++ b/services/keepstore/handlers.go
@@ -93,6 +93,36 @@ func GetBlockHandler(resp http.ResponseWriter, req *http.Request) {
 	resp.Write(block)
 }
 
+var errClientDisconnected = fmt.Errorf("client disconnected")
+
+// Get a buffer from the pool -- but give up and return a non-nil
+// error if resp implements http.CloseNotifier and tells us that the
+// client has disconnected before we get a buffer.
+func getBufferForResponseWriter(resp http.ResponseWriter, bufSize int) ([]byte, error) {
+	var closeNotifier <-chan bool
+	if resp, ok := resp.(http.CloseNotifier); ok {
+		closeNotifier = resp.CloseNotify()
+	}
+	var buf []byte
+	bufReady := make(chan []byte)
+	go func() {
+		bufReady <- bufs.Get(bufSize)
+		close(bufReady)
+	}()
+	select {
+	case buf = <-bufReady:
+		return buf, nil
+	case <-closeNotifier:
+		go func() {
+			// Even if closeNotifier happened first, we
+			// need to keep waiting for our buf so we can
+			// return it to the pool.
+			bufs.Put(<-bufReady)
+		}()
+		return nil, errClientDisconnected
+	}
+}
+
 // PutBlockHandler is a HandleFunc to address Put block requests.
 func PutBlockHandler(resp http.ResponseWriter, req *http.Request) {
 	hash := mux.Vars(req)["hash"]
@@ -116,8 +146,14 @@ func PutBlockHandler(resp http.ResponseWriter, req *http.Request) {
 		return
 	}
 
-	buf := bufs.Get(int(req.ContentLength))
-	_, err := io.ReadFull(req.Body, buf)
+	buf, err := getBufferForResponseWriter(resp, int(req.ContentLength))
+	if err != nil {
+		resp.WriteHeader(http.StatusServiceUnavailable)
+		io.WriteString(resp, err.Error())
+		return
+	}
+
+	_, err = io.ReadFull(req.Body, buf)
 	if err != nil {
 		http.Error(resp, err.Error(), 500)
 		bufs.Put(buf)

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list