Browse code

add since for polling, rename some vars

Victor Vieux authored on 2013/07/13 01:29:23
Showing 3 changed files
... ...
@@ -218,24 +218,55 @@ func getInfo(srv *Server, version float64, w http.ResponseWriter, r *http.Reques
218 218
 }
219 219
 
220 220
 func getEvents(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
221
-	events := make(chan utils.JSONMessage)
222
-	srv.Lock()
223
-	srv.events[r.RemoteAddr] = events
224
-	srv.Unlock()
225
-	w.Header().Set("Content-Type", "application/json")
226
-	wf := utils.NewWriteFlusher(w)
227
-	for {
228
-		event := <-events
221
+	sendEvent := func(wf *utils.WriteFlusher, event *utils.JSONMessage) (bool, error) {
229 222
 		b, err := json.Marshal(event)
230 223
 		if err != nil {
231
-			continue
224
+			return true, nil
232 225
 		}
233 226
 		_, err = wf.Write(b)
234 227
 		if err != nil {
235 228
 			utils.Debugf("%s", err)
236 229
 			srv.Lock()
237
-			delete(srv.events, r.RemoteAddr)
230
+			delete(srv.listeners, r.RemoteAddr)
238 231
 			srv.Unlock()
232
+			return false, err
233
+		}
234
+		return false, nil
235
+	}
236
+
237
+	if err := parseForm(r); err != nil {
238
+		return err
239
+	}
240
+	listener := make(chan utils.JSONMessage)
241
+	srv.Lock()
242
+	srv.listeners[r.RemoteAddr] = listener
243
+	srv.Unlock()
244
+	since, err := strconv.ParseInt(r.Form.Get("since"), 10, 0)
245
+	if err != nil {
246
+		since = 0
247
+	}
248
+	w.Header().Set("Content-Type", "application/json")
249
+	wf := utils.NewWriteFlusher(w)
250
+	if since != 0 {
251
+		for _, event := range srv.events {
252
+			if event.Time >= since {
253
+				skip, err := sendEvent(wf, &event)
254
+				if skip {
255
+					continue
256
+				}
257
+				if err != nil {
258
+					return err
259
+				}
260
+			}
261
+		}
262
+	}
263
+	for {
264
+		event := <-listener
265
+		skip, err := sendEvent(wf, &event)
266
+		if skip {
267
+			continue
268
+		}
269
+		if err != nil {
239 270
 			return err
240 271
 		}
241 272
 	}
... ...
@@ -1058,7 +1058,8 @@ func (cli *DockerCli) CmdCommit(args ...string) error {
1058 1058
 }
1059 1059
 
1060 1060
 func (cli *DockerCli) CmdEvents(args ...string) error {
1061
-	cmd := Subcmd("events", "", "Get real time events from the server")
1061
+	cmd := Subcmd("events", "[OPTIONS]", "Get real time events from the server")
1062
+	since := cmd.String("since", "", "Show events previously created (used for polling).")
1062 1063
 	if err := cmd.Parse(args); err != nil {
1063 1064
 		return nil
1064 1065
 	}
... ...
@@ -1068,7 +1069,12 @@ func (cli *DockerCli) CmdEvents(args ...string) error {
1068 1068
 		return nil
1069 1069
 	}
1070 1070
 
1071
-	if err := cli.stream("GET", "/events", nil, cli.out); err != nil {
1071
+	v := url.Values{}
1072
+	if *since != "" {
1073
+		v.Set("since", *since)
1074
+	}
1075
+
1076
+	if err := cli.stream("GET", "/events?"+v.Encode(), nil, cli.out); err != nil {
1072 1077
 		return err
1073 1078
 	}
1074 1079
 	return nil
... ...
@@ -35,7 +35,7 @@ func (srv *Server) ContainerKill(name string) error {
35 35
 		if err := container.Kill(); err != nil {
36 36
 			return fmt.Errorf("Error killing container %s: %s", name, err)
37 37
 		}
38
-		srv.SendEvent("kill", name)
38
+		srv.LogEvent("kill", name)
39 39
 	} else {
40 40
 		return fmt.Errorf("No such container: %s", name)
41 41
 	}
... ...
@@ -54,7 +54,7 @@ func (srv *Server) ContainerExport(name string, out io.Writer) error {
54 54
 		if _, err := io.Copy(out, data); err != nil {
55 55
 			return err
56 56
 		}
57
-		srv.SendEvent("export", name)
57
+		srv.LogEvent("export", name)
58 58
 		return nil
59 59
 	}
60 60
 	return fmt.Errorf("No such container: %s", name)
... ...
@@ -814,7 +814,7 @@ func (srv *Server) ContainerCreate(config *Config) (string, error) {
814 814
 		}
815 815
 		return "", err
816 816
 	}
817
-	srv.SendEvent("create", container.ShortID())
817
+	srv.LogEvent("create", container.ShortID())
818 818
 	return container.ShortID(), nil
819 819
 }
820 820
 
... ...
@@ -823,7 +823,7 @@ func (srv *Server) ContainerRestart(name string, t int) error {
823 823
 		if err := container.Restart(t); err != nil {
824 824
 			return fmt.Errorf("Error restarting container %s: %s", name, err)
825 825
 		}
826
-		srv.SendEvent("restart", name)
826
+		srv.LogEvent("restart", name)
827 827
 	} else {
828 828
 		return fmt.Errorf("No such container: %s", name)
829 829
 	}
... ...
@@ -843,7 +843,7 @@ func (srv *Server) ContainerDestroy(name string, removeVolume bool) error {
843 843
 		if err := srv.runtime.Destroy(container); err != nil {
844 844
 			return fmt.Errorf("Error destroying container %s: %s", name, err)
845 845
 		}
846
-		srv.SendEvent("destroy", name)
846
+		srv.LogEvent("destroy", name)
847 847
 
848 848
 		if removeVolume {
849 849
 			// Retrieve all volumes from all remaining containers
... ...
@@ -910,7 +910,7 @@ func (srv *Server) deleteImageAndChildren(id string, imgs *[]APIRmi) error {
910 910
 			return err
911 911
 		}
912 912
 		*imgs = append(*imgs, APIRmi{Deleted: utils.TruncateID(id)})
913
-		srv.SendEvent("delete", utils.TruncateID(id))
913
+		srv.LogEvent("delete", utils.TruncateID(id))
914 914
 		return nil
915 915
 	}
916 916
 	return nil
... ...
@@ -954,7 +954,7 @@ func (srv *Server) deleteImage(img *Image, repoName, tag string) ([]APIRmi, erro
954 954
 	}
955 955
 	if tagDeleted {
956 956
 		imgs = append(imgs, APIRmi{Untagged: img.ShortID()})
957
-		srv.SendEvent("untag", img.ShortID())
957
+		srv.LogEvent("untag", img.ShortID())
958 958
 	}
959 959
 	if len(srv.runtime.repositories.ByID()[img.ID]) == 0 {
960 960
 		if err := srv.deleteImageAndChildren(img.ID, &imgs); err != nil {
... ...
@@ -1027,7 +1027,7 @@ func (srv *Server) ContainerStart(name string, hostConfig *HostConfig) error {
1027 1027
 		if err := container.Start(hostConfig); err != nil {
1028 1028
 			return fmt.Errorf("Error starting container %s: %s", name, err)
1029 1029
 		}
1030
-		srv.SendEvent("start", name)
1030
+		srv.LogEvent("start", name)
1031 1031
 	} else {
1032 1032
 		return fmt.Errorf("No such container: %s", name)
1033 1033
 	}
... ...
@@ -1039,7 +1039,7 @@ func (srv *Server) ContainerStop(name string, t int) error {
1039 1039
 		if err := container.Stop(t); err != nil {
1040 1040
 			return fmt.Errorf("Error stopping container %s: %s", name, err)
1041 1041
 		}
1042
-		srv.SendEvent("stop", name)
1042
+		srv.LogEvent("stop", name)
1043 1043
 	} else {
1044 1044
 		return fmt.Errorf("No such container: %s", name)
1045 1045
 	}
... ...
@@ -1173,15 +1173,19 @@ func NewServer(flGraphPath string, autoRestart, enableCors bool, dns ListOpts) (
1173 1173
 		enableCors:  enableCors,
1174 1174
 		pullingPool: make(map[string]struct{}),
1175 1175
 		pushingPool: make(map[string]struct{}),
1176
-		events:      make(map[string]chan utils.JSONMessage),
1176
+		events:      make([]utils.JSONMessage, 0, 64), //only keeps the 64 last events
1177
+		listeners:   make(map[string]chan utils.JSONMessage),
1177 1178
 	}
1178 1179
 	runtime.srv = srv
1179 1180
 	return srv, nil
1180 1181
 }
1181 1182
 
1182
-func (srv *Server) SendEvent(action, id string) {
1183
-	for _, c := range srv.events {
1184
-		c <- utils.JSONMessage{Status: action, ID: id, Time: time.Now().Unix()}
1183
+func (srv *Server) LogEvent(action, id string) {
1184
+	now := time.Now().Unix()
1185
+	jm := utils.JSONMessage{Status: action, ID: id, Time: now}
1186
+	srv.events = append(srv.events, jm)
1187
+	for _, c := range srv.listeners {
1188
+		c <- jm
1185 1189
 	}
1186 1190
 }
1187 1191
 
... ...
@@ -1191,5 +1195,6 @@ type Server struct {
1191 1191
 	enableCors  bool
1192 1192
 	pullingPool map[string]struct{}
1193 1193
 	pushingPool map[string]struct{}
1194
-	events      map[string]chan utils.JSONMessage
1194
+	events      []utils.JSONMessage
1195
+	listeners   map[string]chan utils.JSONMessage
1195 1196
 }