Browse code

container: Use wrapper to ensure commit/abort happens

Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>

Aaron Lehmann authored on 2017/07/11 05:36:36
Showing 1 changed files
... ...
@@ -139,31 +139,40 @@ func (db *memDB) Snapshot() View {
139 139
 	}
140 140
 }
141 141
 
142
+func (db *memDB) withTxn(cb func(*memdb.Txn) error) error {
143
+	txn := db.store.Txn(true)
144
+	err := cb(txn)
145
+	if err != nil {
146
+		txn.Abort()
147
+		return err
148
+	}
149
+	txn.Commit()
150
+	return nil
151
+}
152
+
142 153
 // Save atomically updates the in-memory store state for a Container.
143 154
 // Only read only (deep) copies of containers may be passed in.
144 155
 func (db *memDB) Save(c *Container) error {
145
-	txn := db.store.Txn(true)
146
-	defer txn.Commit()
147
-	return txn.Insert(memdbContainersTable, c)
156
+	return db.withTxn(func(txn *memdb.Txn) error {
157
+		return txn.Insert(memdbContainersTable, c)
158
+	})
148 159
 }
149 160
 
150 161
 // Delete removes an item by ID
151 162
 func (db *memDB) Delete(c *Container) error {
152
-	txn := db.store.Txn(true)
153
-
154
-	view := &memdbView{txn: txn}
155
-	names := view.getNames(c.ID)
163
+	return db.withTxn(func(txn *memdb.Txn) error {
164
+		view := &memdbView{txn: txn}
165
+		names := view.getNames(c.ID)
156 166
 
157
-	for _, name := range names {
158
-		txn.Delete(memdbNamesTable, nameAssociation{name: name})
159
-	}
167
+		for _, name := range names {
168
+			txn.Delete(memdbNamesTable, nameAssociation{name: name})
169
+		}
160 170
 
161
-	if err := txn.Delete(memdbContainersTable, NewBaseContainer(c.ID, c.Root)); err != nil {
162
-		txn.Abort()
163
-		return err
164
-	}
165
-	txn.Commit()
166
-	return nil
171
+		if err := txn.Delete(memdbContainersTable, NewBaseContainer(c.ID, c.Root)); err != nil {
172
+			return err
173
+		}
174
+		return nil
175
+	})
167 176
 }
168 177
 
169 178
 // ReserveName registers a container ID to a name
... ...
@@ -171,39 +180,34 @@ func (db *memDB) Delete(c *Container) error {
171 171
 // Attempting to reserve a container ID to a name that already exists results in an `ErrNameReserved`
172 172
 // A name reservation is globally unique
173 173
 func (db *memDB) ReserveName(name, containerID string) error {
174
-	txn := db.store.Txn(true)
174
+	return db.withTxn(func(txn *memdb.Txn) error {
175
+		s, err := txn.First(memdbNamesTable, memdbIDIndex, name)
176
+		if err != nil {
177
+			return err
178
+		}
179
+		if s != nil {
180
+			if s.(nameAssociation).containerID != containerID {
181
+				return ErrNameReserved
182
+			}
183
+			return nil
184
+		}
175 185
 
176
-	s, err := txn.First(memdbNamesTable, memdbIDIndex, name)
177
-	if err != nil {
178
-		txn.Abort()
179
-		return err
180
-	}
181
-	if s != nil {
182
-		txn.Abort()
183
-		if s.(nameAssociation).containerID != containerID {
184
-			return ErrNameReserved
186
+		if err := txn.Insert(memdbNamesTable, nameAssociation{name: name, containerID: containerID}); err != nil {
187
+			return err
185 188
 		}
186 189
 		return nil
187
-	}
188
-
189
-	if err := txn.Insert(memdbNamesTable, nameAssociation{name: name, containerID: containerID}); err != nil {
190
-		txn.Abort()
191
-		return err
192
-	}
193
-	txn.Commit()
194
-	return nil
190
+	})
195 191
 }
196 192
 
197 193
 // ReleaseName releases the reserved name
198 194
 // Once released, a name can be reserved again
199 195
 func (db *memDB) ReleaseName(name string) error {
200
-	txn := db.store.Txn(true)
201
-	if err := txn.Delete(memdbNamesTable, nameAssociation{name: name}); err != nil {
202
-		txn.Abort()
203
-		return err
204
-	}
205
-	txn.Commit()
206
-	return nil
196
+	return db.withTxn(func(txn *memdb.Txn) error {
197
+		if err := txn.Delete(memdbNamesTable, nameAssociation{name: name}); err != nil {
198
+			return err
199
+		}
200
+		return nil
201
+	})
207 202
 }
208 203
 
209 204
 type memdbView struct {