Commit writes all changes to disk, updates the meta page and closes the transaction. Returns an error if a disk write error occurs, or if Commit is called on a read-only transaction.
()
| 168 | // Returns an error if a disk write error occurs, or if Commit is |
| 169 | // called on a read-only transaction. |
| 170 | func (tx *Tx) Commit() (err error) { |
| 171 | txId := tx.ID() |
| 172 | lg := tx.db.Logger() |
| 173 | if lg != discardLogger { |
| 174 | lg.Debugf("Committing transaction %d", txId) |
| 175 | defer func() { |
| 176 | if err != nil { |
| 177 | lg.Errorf("Committing transaction failed: %v", err) |
| 178 | } else { |
| 179 | lg.Debugf("Committing transaction %d successfully", txId) |
| 180 | } |
| 181 | }() |
| 182 | } |
| 183 | |
| 184 | common.Assert(!tx.managed, "managed tx commit not allowed") |
| 185 | if tx.db == nil { |
| 186 | return berrors.ErrTxClosed |
| 187 | } else if !tx.writable { |
| 188 | return berrors.ErrTxNotWritable |
| 189 | } |
| 190 | |
| 191 | // TODO(benbjohnson): Use vectorized I/O to write out dirty pages. |
| 192 | |
| 193 | // Rebalance nodes which have had deletions. |
| 194 | var startTime = time.Now() |
| 195 | tx.root.rebalance() |
| 196 | if tx.stats.GetRebalance() > 0 { |
| 197 | tx.stats.IncRebalanceTime(time.Since(startTime)) |
| 198 | } |
| 199 | |
| 200 | opgid := tx.meta.Pgid() |
| 201 | |
| 202 | // spill data onto dirty pages. |
| 203 | startTime = time.Now() |
| 204 | if err = tx.root.spill(); err != nil { |
| 205 | lg.Errorf("spilling data onto dirty pages failed: %v", err) |
| 206 | tx.rollback() |
| 207 | return err |
| 208 | } |
| 209 | tx.stats.IncSpillTime(time.Since(startTime)) |
| 210 | |
| 211 | // Free the old root bucket. |
| 212 | tx.meta.RootBucket().SetRootPage(tx.root.RootPage()) |
| 213 | |
| 214 | // Free the old freelist because commit writes out a fresh freelist. |
| 215 | if tx.meta.Freelist() != common.PgidNoFreelist { |
| 216 | tx.db.freelist.Free(tx.meta.Txid(), tx.db.page(tx.meta.Freelist())) |
| 217 | } |
| 218 | |
| 219 | if !tx.db.NoFreelistSync { |
| 220 | err = tx.commitFreelist() |
| 221 | if err != nil { |
| 222 | lg.Errorf("committing freelist failed: %v", err) |
| 223 | return err |
| 224 | } |
| 225 | } else { |
| 226 | tx.meta.SetFreelist(common.PgidNoFreelist) |
| 227 | } |