Browse code

Simplified Graph.Delete() - no more garbage collecting, just atomic deregister then os.RemoveAll

Solomon Hykes authored on 2013/04/04 14:14:28
Showing 1 changed files
... ...
@@ -129,6 +129,9 @@ func (graph *Graph) Register(layerData Archive, img *Image) error {
129 129
 
130 130
 // Mktemp creates a temporary sub-directory inside the graph's filesystem.
131 131
 func (graph *Graph) Mktemp(id string) (string, error) {
132
+	if id == "" {
133
+		id = GenerateId()
134
+	}
132 135
 	tmp, err := NewGraph(path.Join(graph.Root, ":tmp:"))
133 136
 	if err != nil {
134 137
 		return "", fmt.Errorf("Couldn't create temp: %s", err)
... ...
@@ -139,13 +142,6 @@ func (graph *Graph) Mktemp(id string) (string, error) {
139 139
 	return tmp.imageRoot(id), nil
140 140
 }
141 141
 
142
-// Garbage returns the "garbage", a staging area for deleted images.
143
-// This allows images to be deleted atomically by os.Rename(), instead of
144
-// os.RemoveAll() which is prone to race conditions.
145
-func (graph *Graph) Garbage() (*Graph, error) {
146
-	return NewGraph(path.Join(graph.Root, ":garbage:"))
147
-}
148
-
149 142
 // Check if given error is "not empty".
150 143
 // Note: this is the way golang does it internally with os.IsNotExists.
151 144
 func isNotEmpty(err error) bool {
... ...
@@ -166,54 +162,16 @@ func (graph *Graph) Delete(name string) error {
166 166
 	if err != nil {
167 167
 		return err
168 168
 	}
169
-	garbage, err := graph.Garbage()
169
+	tmp, err := graph.Mktemp("")
170 170
 	if err != nil {
171 171
 		return err
172 172
 	}
173 173
 	graph.idIndex.Delete(id)
174
-	err = os.Rename(graph.imageRoot(id), garbage.imageRoot(id))
175
-	if err != nil {
176
-		// FIXME: this introduces a race condition in Delete() if the image is already present
177
-		// in garbage. Let's store at random names in grabage instead.
178
-		if isNotEmpty(err) {
179
-			Debugf("The image %s is already present in garbage. Removing it.", id)
180
-			if err = os.RemoveAll(garbage.imageRoot(id)); err != nil {
181
-				Debugf("Error while removing the image %s from garbage: %s\n", id, err)
182
-				return err
183
-			}
184
-			Debugf("Image %s removed from garbage", id)
185
-			if err = os.Rename(graph.imageRoot(id), garbage.imageRoot(id)); err != nil {
186
-				return err
187
-			}
188
-			Debugf("Image %s put in the garbage", id)
189
-		} else {
190
-			Debugf("Error putting the image %s to garbage: %s\n", id, err)
191
-		}
192
-		return err
193
-	}
194
-	return nil
195
-}
196
-
197
-// Undelete moves an image back from the garbage to the main graph.
198
-func (graph *Graph) Undelete(id string) error {
199
-	garbage, err := graph.Garbage()
200
-	if err != nil {
201
-		return err
202
-	}
203
-	if err := os.Rename(garbage.imageRoot(id), graph.imageRoot(id)); err != nil {
204
-		return err
205
-	}
206
-	graph.idIndex.Add(id)
207
-	return nil
208
-}
209
-
210
-// GarbageCollect definitely deletes all images moved to the garbage.
211
-func (graph *Graph) GarbageCollect() error {
212
-	garbage, err := graph.Garbage()
174
+	err = os.Rename(graph.imageRoot(id), tmp)
213 175
 	if err != nil {
214 176
 		return err
215 177
 	}
216
-	return os.RemoveAll(garbage.Root)
178
+	return os.RemoveAll(tmp)
217 179
 }
218 180
 
219 181
 // Map returns a list of all images in the graph, addressable by ID.