Browse code

Refactor waitExitOrRemoved by mlaventure

Reduce complexity of waitExitOrRemoved.

Signed-off-by: mlaventure
Signed-off-by: Zhang Wei <zhangwei555@huawei.com>

Zhang Wei authored on 2016/08/12 01:44:18
Showing 1 changed files
... ...
@@ -21,40 +21,44 @@ func waitExitOrRemoved(dockerCli *client.DockerCli, ctx context.Context, contain
21 21
 		panic("Internal Error: waitExitOrRemoved needs a containerID as parameter")
22 22
 	}
23 23
 
24
-	var exitCode int
25 24
 	statusChan := make(chan int)
26
-	exitChan := make(chan struct{})
27
-	detachChan := make(chan struct{})
28
-	destroyChan := make(chan struct{})
29
-	eventsErr := make(chan error)
25
+	exitCode := 125
30 26
 
31
-	// Start watch events
32
-	eh := system.InitEventHandler()
33
-	eh.Handle("die", func(e events.Message) {
34
-		if len(e.Actor.Attributes) > 0 {
35
-			for k, v := range e.Actor.Attributes {
36
-				if k == "exitCode" {
37
-					var err error
38
-					if exitCode, err = strconv.Atoi(v); err != nil {
39
-						logrus.Errorf("Can't convert %q to int: %v", v, err)
40
-					}
41
-					close(exitChan)
42
-					break
27
+	eventProcessor := func(e events.Message, err error) error {
28
+		if err != nil {
29
+			statusChan <- exitCode
30
+			return fmt.Errorf("failed to decode event: %v", err)
31
+		}
32
+
33
+		stopProcessing := false
34
+		switch e.Status {
35
+		case "die":
36
+			if v, ok := e.Actor.Attributes["exitCode"]; ok {
37
+				code, cerr := strconv.Atoi(v)
38
+				if cerr != nil {
39
+					logrus.Errorf("failed to convert exitcode '%q' to int: %v", v, cerr)
40
+				} else {
41
+					exitCode = code
43 42
 				}
44 43
 			}
44
+			if !waitRemove {
45
+				stopProcessing = true
46
+			}
47
+		case "detach":
48
+			exitCode = 0
49
+			stopProcessing = true
50
+		case "destroy":
51
+			stopProcessing = true
45 52
 		}
46
-	})
47 53
 
48
-	eh.Handle("detach", func(e events.Message) {
49
-		exitCode = 0
50
-		close(detachChan)
51
-	})
52
-	eh.Handle("destroy", func(e events.Message) {
53
-		close(destroyChan)
54
-	})
54
+		if stopProcessing {
55
+			statusChan <- exitCode
56
+			// stop the loop processing
57
+			return fmt.Errorf("done")
58
+		}
55 59
 
56
-	eventChan := make(chan events.Message)
57
-	go eh.Watch(eventChan)
60
+		return nil
61
+	}
58 62
 
59 63
 	// Get events via Events API
60 64
 	f := filters.NewArgs()
... ...
@@ -68,45 +72,8 @@ func waitExitOrRemoved(dockerCli *client.DockerCli, ctx context.Context, contain
68 68
 		return nil, fmt.Errorf("can't get events from daemon: %v", err)
69 69
 	}
70 70
 
71
-	go func() {
72
-		eventsErr <- system.DecodeEvents(resBody, func(event events.Message, err error) error {
73
-			if err != nil {
74
-				return fmt.Errorf("decode events error: %v", err)
75
-			}
76
-			eventChan <- event
77
-			return nil
78
-		})
79
-		close(eventChan)
80
-	}()
81
-
82
-	go func() {
83
-		var waitErr error
84
-		if waitRemove {
85
-			select {
86
-			case <-destroyChan:
87
-				// keep exitcode and return
88
-			case <-detachChan:
89
-				exitCode = 0
90
-			case waitErr = <-eventsErr:
91
-				exitCode = 125
92
-			}
93
-		} else {
94
-			select {
95
-			case <-exitChan:
96
-				// keep exitcode and return
97
-			case <-detachChan:
98
-				exitCode = 0
99
-			case waitErr = <-eventsErr:
100
-				exitCode = 125
101
-			}
102
-		}
103
-		if waitErr != nil {
104
-			logrus.Errorf("%v", waitErr)
105
-		}
106
-		statusChan <- exitCode
71
+	go system.DecodeEvents(resBody, eventProcessor)
107 72
 
108
-		resBody.Close()
109
-	}()
110 73
 	return statusChan, nil
111 74
 }
112 75